From b0a60e428c249e02729a0862952351eb8616cb6a Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Thu, 20 Nov 2025 16:07:57 +0800
Subject: [PATCH 1/7] =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E8=AF=84=E5=88=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/model/WechatAccountModel.php | 24 +-
.../CheckAndFixWechatAccountCommand.php | 159 ++
.../WechatAccountHealthScoreService.php | 378 +++
.../controller/WorkbenchController.php | 244 +-
Server/sql.sql | 2301 +++++++++++++++++
Server/微信健康分规则v2.md | 58 +
6 files changed, 3116 insertions(+), 48 deletions(-)
create mode 100644 Server/application/command/CheckAndFixWechatAccountCommand.php
create mode 100644 Server/application/common/service/WechatAccountHealthScoreService.php
create mode 100644 Server/sql.sql
create mode 100644 Server/微信健康分规则v2.md
diff --git a/Server/application/api/model/WechatAccountModel.php b/Server/application/api/model/WechatAccountModel.php
index 2f72b908..919da478 100644
--- a/Server/application/api/model/WechatAccountModel.php
+++ b/Server/application/api/model/WechatAccountModel.php
@@ -7,5 +7,27 @@ use think\Model;
class WechatAccountModel extends Model
{
// 设置表名
- protected $table = 's2_wechat_account';
+ protected $table = 's2_wechat_account';
+
+ // 定义字段类型
+ protected $type = [
+ 'healthScore' => 'integer',
+ 'baseScore' => 'integer',
+ 'dynamicScore' => 'integer',
+ 'isModifiedAlias' => 'integer',
+ 'frequentCount' => 'integer',
+ 'consecutiveNoFrequentDays' => 'integer',
+ 'lastFrequentTime' => 'integer',
+ 'lastNoFrequentTime' => 'integer',
+ 'scoreUpdateTime' => 'integer',
+ ];
+
+ // 允许批量赋值的字段
+ protected $field = [
+ 'id', 'wechatId', 'alias', 'nickname', 'avatar', 'gender', 'region', 'signature',
+ 'healthScore', 'baseScore', 'dynamicScore', 'isModifiedAlias',
+ 'lastFrequentTime', 'frequentCount', 'lastNoFrequentTime',
+ 'consecutiveNoFrequentDays', 'scoreUpdateTime',
+ 'createTime', 'updateTime', 'status', 'isDeleted'
+ ];
}
\ No newline at end of file
diff --git a/Server/application/command/CheckAndFixWechatAccountCommand.php b/Server/application/command/CheckAndFixWechatAccountCommand.php
new file mode 100644
index 00000000..e498f77b
--- /dev/null
+++ b/Server/application/command/CheckAndFixWechatAccountCommand.php
@@ -0,0 +1,159 @@
+setName('wechat:check-and-fix')
+ ->setDescription('检测和修复s2_wechat_account表中wechatId和alias不一致的问题,并更新健康分');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $output->writeln("开始检测和修复s2_wechat_account表...");
+
+ try {
+ // 1. 检测wechatId和alias不一致的记录
+ $output->writeln("步骤1: 检测wechatId和alias不一致的记录...");
+ $inconsistentAccounts = $this->findInconsistentAccounts();
+ $output->writeln("发现 " . count($inconsistentAccounts) . " 条不一致记录");
+
+ if (empty($inconsistentAccounts)) {
+ $output->writeln("没有发现不一致的记录,任务完成!");
+ return;
+ }
+
+ // 2. 修复不一致的记录
+ $output->writeln("步骤2: 修复不一致的记录...");
+ $fixedCount = $this->fixInconsistentAccounts($inconsistentAccounts);
+ $output->writeln("已修复 " . $fixedCount . " 条记录");
+
+ // 3. 更新isModifiedAlias字段
+ $output->writeln("步骤3: 更新isModifiedAlias字段...");
+ $updatedCount = $this->updateModifiedAliasFlag();
+ $output->writeln("已更新 " . $updatedCount . " 条记录的isModifiedAlias字段");
+
+ // 4. 重新计算健康分
+ $output->writeln("步骤4: 重新计算健康分...");
+ $healthScoreService = new WechatAccountHealthScoreService();
+ $accountIds = array_column($inconsistentAccounts, 'id');
+ $stats = $healthScoreService->batchCalculateAndUpdate($accountIds, 100);
+ $output->writeln("健康分计算完成:成功 " . $stats['success'] . " 条,失败 " . $stats['failed'] . " 条");
+
+ if (!empty($stats['errors'])) {
+ $output->writeln("错误详情:");
+ foreach ($stats['errors'] as $error) {
+ $output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ }
+ }
+
+ $output->writeln("任务完成!");
+
+ } catch (\Exception $e) {
+ $output->writeln("错误: " . $e->getMessage());
+ $output->writeln($e->getTraceAsString());
+ }
+ }
+
+ /**
+ * 查找wechatId和alias不一致的记录
+ *
+ * @return array
+ */
+ private function findInconsistentAccounts()
+ {
+ // 查找wechatId和alias不一致的记录
+ // 条件:wechatId不为空,alias不为空,且wechatId != alias
+ $accounts = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId != alias')
+ ->field('id, wechatId, alias, nickname, isModifiedAlias')
+ ->select();
+
+ return $accounts ?: [];
+ }
+
+ /**
+ * 修复不一致的记录
+ * 策略:从s2_wechat_friend表中查找最新的alias值来更新
+ *
+ * @param array $accounts 不一致的账号列表
+ * @return int 修复数量
+ */
+ private function fixInconsistentAccounts($accounts)
+ {
+ $fixedCount = 0;
+
+ foreach ($accounts as $account) {
+ $wechatId = $account['wechatId'];
+
+ // 从s2_wechat_friend表中查找最新的alias值
+ $latestAlias = Db::table('s2_wechat_friend')
+ ->where('wechatId', $wechatId)
+ ->where('alias', '<>', '')
+ ->order('updateTime', 'desc')
+ ->value('alias');
+
+ // 如果找到了最新的alias,则更新
+ if (!empty($latestAlias) && $latestAlias !== $account['alias']) {
+ Db::table('s2_wechat_account')
+ ->where('id', $account['id'])
+ ->update([
+ 'alias' => $latestAlias,
+ 'updateTime' => time()
+ ]);
+ $fixedCount++;
+ }
+ }
+
+ return $fixedCount;
+ }
+
+ /**
+ * 更新isModifiedAlias字段
+ * 如果wechatId和alias不一致,则标记为已修改
+ *
+ * @return int 更新数量
+ */
+ private function updateModifiedAliasFlag()
+ {
+ // 更新isModifiedAlias字段:wechatId != alias 的记录标记为1
+ $updatedCount = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId != alias')
+ ->update([
+ 'isModifiedAlias' => 1,
+ 'updateTime' => time()
+ ]);
+
+ // 更新isModifiedAlias字段:wechatId == alias 的记录标记为0
+ Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId = alias')
+ ->update([
+ 'isModifiedAlias' => 0,
+ 'updateTime' => time()
+ ]);
+
+ return $updatedCount;
+ }
+}
+
diff --git a/Server/application/common/service/WechatAccountHealthScoreService.php b/Server/application/common/service/WechatAccountHealthScoreService.php
new file mode 100644
index 00000000..cda09cfd
--- /dev/null
+++ b/Server/application/common/service/WechatAccountHealthScoreService.php
@@ -0,0 +1,378 @@
+where('id', $accountId)
+ ->find();
+ }
+
+ if (empty($accountData)) {
+ throw new Exception("账号不存在:{$accountId}");
+ }
+
+ // 计算基础分
+ $baseScore = $this->calculateBaseScore($accountData);
+
+ // 计算动态分
+ $dynamicScore = $this->calculateDynamicScore($accountData);
+
+ // 计算总分
+ $healthScore = $baseScore + $dynamicScore;
+
+ // 确保健康分在合理范围内(0-100)
+ $healthScore = max(0, min(100, $healthScore));
+
+ // 更新数据库
+ $updateData = [
+ 'healthScore' => $healthScore,
+ 'baseScore' => $baseScore,
+ 'dynamicScore' => $dynamicScore,
+ 'scoreUpdateTime' => time()
+ ];
+
+ Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->update($updateData);
+
+ return [
+ 'accountId' => $accountId,
+ 'wechatId' => $accountData['wechatId'] ?? '',
+ 'healthScore' => $healthScore,
+ 'baseScore' => $baseScore,
+ 'dynamicScore' => $dynamicScore,
+ 'baseInfoScore' => $this->getBaseInfoScore($accountData),
+ 'friendCountScore' => $this->getFriendCountScore($accountData['totalFriend'] ?? 0),
+ 'maxAddFriendPerDay' => $this->getMaxAddFriendPerDay($healthScore)
+ ];
+
+ } catch (Exception $e) {
+ throw new Exception("计算健康分失败:" . $e->getMessage());
+ }
+ }
+
+ /**
+ * 计算基础分
+ * 基础分 = 默认60分 + 基础信息分(10分) + 好友数量分(30分)
+ *
+ * @param array $accountData 账号数据
+ * @return int 基础分
+ */
+ private function calculateBaseScore($accountData)
+ {
+ $baseScore = self::DEFAULT_BASE_SCORE;
+
+ // 基础信息分(已修改微信号得10分)
+ $baseScore += $this->getBaseInfoScore($accountData);
+
+ // 好友数量分(最高30分)
+ $totalFriend = $accountData['totalFriend'] ?? 0;
+ $baseScore += $this->getFriendCountScore($totalFriend);
+
+ return $baseScore;
+ }
+
+ /**
+ * 获取基础信息分
+ * 已修改微信号:10分
+ *
+ * @param array $accountData 账号数据
+ * @return int 基础信息分
+ */
+ private function getBaseInfoScore($accountData)
+ {
+ // 检查是否已修改微信号
+ // 如果isModifiedAlias字段为1,或者wechatId和alias不一致,则认为已修改
+ $isModifiedAlias = isset($accountData['isModifiedAlias']) ? (int)$accountData['isModifiedAlias'] : 0;
+ $wechatId = trim($accountData['wechatId'] ?? '');
+ $alias = trim($accountData['alias'] ?? '');
+
+ // 如果字段标记为已修改,或者wechatId和alias不一致,则得分
+ if ($isModifiedAlias == 1 || (!empty($wechatId) && !empty($alias) && $wechatId !== $alias)) {
+ return self::BASE_INFO_SCORE;
+ }
+
+ return 0;
+ }
+
+ /**
+ * 获取好友数量分
+ * 根据好友数量区间得分(最高30分)
+ *
+ * @param int $totalFriend 总好友数
+ * @return int 好友数量分
+ */
+ private function getFriendCountScore($totalFriend)
+ {
+ if ($totalFriend <= 50) {
+ return 3; // 0-50: 3分
+ } elseif ($totalFriend <= 500) {
+ return 6; // 51-500: 6分
+ } elseif ($totalFriend <= 3000) {
+ return 8; // 501-3000: 8分
+ } else {
+ return 12; // 3001以上: 12分
+ }
+ }
+
+ /**
+ * 计算动态分
+ * 动态分 = 扣分 + 加分
+ *
+ * @param array $accountData 账号数据
+ * @return int 动态分
+ */
+ private function calculateDynamicScore($accountData)
+ {
+ $dynamicScore = 0;
+
+ // 处理扣分
+ $dynamicScore += $this->calculatePenalty($accountData);
+
+ // 处理加分
+ $dynamicScore += $this->calculateBonus($accountData);
+
+ return $dynamicScore;
+ }
+
+ /**
+ * 计算扣分
+ * 首次频繁:-15分
+ * 再次频繁:-25分
+ * 封号:-60分
+ *
+ * @param array $accountData 账号数据
+ * @return int 扣分数
+ */
+ private function calculatePenalty($accountData)
+ {
+ $penalty = 0;
+
+ // 检查是否有频繁记录
+ $lastFrequentTime = $accountData['lastFrequentTime'] ?? null;
+ $frequentCount = $accountData['frequentCount'] ?? 0;
+
+ if (!empty($lastFrequentTime)) {
+ // 判断是首次频繁还是再次频繁
+ if ($frequentCount == 1) {
+ $penalty += self::PENALTY_FIRST_FREQUENT; // 首次频繁-15分
+ } elseif ($frequentCount >= 2) {
+ $penalty += self::PENALTY_SECOND_FREQUENT; // 再次频繁-25分
+ }
+ }
+
+ // 检查是否封号(这里需要根据实际业务逻辑判断,比如status字段或其他标识)
+ // 假设status=0表示封号
+ $status = $accountData['status'] ?? 1;
+ if ($status == 0) {
+ $penalty += self::PENALTY_BANNED; // 封号-60分
+ }
+
+ return $penalty;
+ }
+
+ /**
+ * 计算加分
+ * 连续3天不触发频繁:每天+5分
+ *
+ * @param array $accountData 账号数据
+ * @return int 加分数
+ */
+ private function calculateBonus($accountData)
+ {
+ $bonus = 0;
+
+ $lastNoFrequentTime = $accountData['lastNoFrequentTime'] ?? null;
+ $consecutiveNoFrequentDays = $accountData['consecutiveNoFrequentDays'] ?? 0;
+
+ // 如果连续不频繁天数>=3,则每天+5分
+ if ($consecutiveNoFrequentDays >= 3) {
+ $bonus = $consecutiveNoFrequentDays * self::BONUS_NO_FREQUENT_PER_DAY;
+ }
+
+ return $bonus;
+ }
+
+ /**
+ * 根据健康分计算每日最大加人次数
+ * 公式:每日最大加人次数 = 健康分 * 0.2
+ *
+ * @param int $healthScore 健康分
+ * @return int 每日最大加人次数
+ */
+ public function getMaxAddFriendPerDay($healthScore)
+ {
+ return (int)floor($healthScore * 0.2);
+ }
+
+ /**
+ * 批量计算并更新多个账号的健康分
+ *
+ * @param array $accountIds 账号ID数组
+ * @param int $batchSize 每批处理数量
+ * @return array 处理结果统计
+ */
+ public function batchCalculateAndUpdate($accountIds = [], $batchSize = 100)
+ {
+ $stats = [
+ 'total' => 0,
+ 'success' => 0,
+ 'failed' => 0,
+ 'errors' => []
+ ];
+
+ // 如果没有指定账号ID,则处理所有账号
+ if (empty($accountIds)) {
+ $accountIds = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->column('id');
+ }
+
+ $stats['total'] = count($accountIds);
+
+ // 分批处理
+ $batches = array_chunk($accountIds, $batchSize);
+
+ foreach ($batches as $batch) {
+ foreach ($batch as $accountId) {
+ try {
+ $this->calculateAndUpdate($accountId);
+ $stats['success']++;
+ } catch (Exception $e) {
+ $stats['failed']++;
+ $stats['errors'][] = [
+ 'accountId' => $accountId,
+ 'error' => $e->getMessage()
+ ];
+ }
+ }
+ }
+
+ return $stats;
+ }
+
+ /**
+ * 记录频繁事件
+ *
+ * @param int $accountId 账号ID
+ * @return bool
+ */
+ public function recordFrequent($accountId)
+ {
+ $accountData = Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->find();
+
+ if (empty($accountData)) {
+ return false;
+ }
+
+ $frequentCount = ($accountData['frequentCount'] ?? 0) + 1;
+
+ $updateData = [
+ 'lastFrequentTime' => time(),
+ 'frequentCount' => $frequentCount,
+ 'consecutiveNoFrequentDays' => 0, // 重置连续不频繁天数
+ 'lastNoFrequentTime' => null
+ ];
+
+ Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->update($updateData);
+
+ // 重新计算健康分
+ $this->calculateAndUpdate($accountId);
+
+ return true;
+ }
+
+ /**
+ * 记录不频繁事件(用于加分)
+ *
+ * @param int $accountId 账号ID
+ * @return bool
+ */
+ public function recordNoFrequent($accountId)
+ {
+ $accountData = Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->find();
+
+ if (empty($accountData)) {
+ return false;
+ }
+
+ $lastNoFrequentTime = $accountData['lastNoFrequentTime'] ?? null;
+ $consecutiveNoFrequentDays = $accountData['consecutiveNoFrequentDays'] ?? 0;
+ $currentTime = time();
+
+ // 如果上次不频繁时间是昨天或更早,则增加连续天数
+ if (empty($lastNoFrequentTime) || ($currentTime - $lastNoFrequentTime) >= 86400) {
+ // 如果间隔超过1天,重置为1天
+ if (!empty($lastNoFrequentTime) && ($currentTime - $lastNoFrequentTime) > 86400 * 2) {
+ $consecutiveNoFrequentDays = 1;
+ } else {
+ $consecutiveNoFrequentDays++;
+ }
+ }
+
+ $updateData = [
+ 'lastNoFrequentTime' => $currentTime,
+ 'consecutiveNoFrequentDays' => $consecutiveNoFrequentDays
+ ];
+
+ Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->update($updateData);
+
+ // 重新计算健康分
+ $this->calculateAndUpdate($accountId);
+
+ return true;
+ }
+}
+
diff --git a/Server/application/cunkebao/controller/WorkbenchController.php b/Server/application/cunkebao/controller/WorkbenchController.php
index 62e17116..11681d9d 100644
--- a/Server/application/cunkebao/controller/WorkbenchController.php
+++ b/Server/application/cunkebao/controller/WorkbenchController.php
@@ -2816,6 +2816,8 @@ class WorkbenchController extends Controller
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$keyword = $this->request->param('keyword', '');
+ $pushType = $this->request->param('pushType', ''); // 推送类型筛选:''=全部, 'friend'=好友消息, 'group'=群消息, 'announcement'=群公告
+ $status = $this->request->param('status', ''); // 状态筛选:''=全部, 'success'=已完成, 'progress'=进行中, 'failed'=失败
$userId = $this->request->userInfo['id'];
// 构建工作台查询条件
@@ -2840,10 +2842,11 @@ class WorkbenchController extends Controller
$workbenchWhere[] = ['w.id', '=', $workbenchId];
}
- // 按内容ID、工作台ID和时间分组,统计每次推送
- $query = Db::name('workbench_group_push_item')
+ // 1. 先查询所有已执行的推送记录(按推送时间分组)
+ $pushHistoryQuery = Db::name('workbench_group_push_item')
->alias('wgpi')
->join('workbench w', 'w.id = wgpi.workbenchId', 'left')
+ ->join('workbench_group_push wgp', 'wgp.workbenchId = wgpi.workbenchId', 'left')
->join('content_item ci', 'ci.id = wgpi.contentId', 'left')
->join('content_library cl', 'cl.id = ci.libraryId', 'left')
->where($workbenchWhere)
@@ -2853,52 +2856,57 @@ class WorkbenchController extends Controller
'wgpi.contentId',
'FROM_UNIXTIME(wgpi.createTime, "%Y-%m-%d %H:00:00") as pushTime',
'wgpi.targetType',
+ 'wgp.groupPushSubType',
'MIN(wgpi.createTime) as createTime',
'COUNT(DISTINCT wgpi.id) as totalCount',
'cl.name as contentLibraryName'
])
- ->group('wgpi.workbenchId, wgpi.contentId, pushTime, wgpi.targetType');
+ ->group('wgpi.workbenchId, wgpi.contentId, pushTime, wgpi.targetType, wgp.groupPushSubType');
if (!empty($keyword)) {
- $query->where('w.name|cl.name|ci.content', 'like', '%' . $keyword . '%');
+ $pushHistoryQuery->where('w.name|cl.name|ci.content', 'like', '%' . $keyword . '%');
}
- // 获取分页数据
- $list = $query->order('createTime', 'desc')
- ->page($page, $limit)
- ->select();
-
- // 对于有 group by 的查询,统计总数需要重新查询
- $totalQuery = Db::name('workbench_group_push_item')
- ->alias('wgpi')
- ->join('workbench w', 'w.id = wgpi.workbenchId', 'left')
- ->join('content_item ci', 'ci.id = wgpi.contentId', 'left')
- ->join('content_library cl', 'cl.id = ci.libraryId', 'left')
- ->where($workbenchWhere);
-
- if (!empty($keyword)) {
- $totalQuery->where('w.name|cl.name|ci.content', 'like', '%' . $keyword . '%');
- }
-
- // 统计分组后的记录数(使用子查询)
- $subQuery = $totalQuery
+ $pushHistoryList = $pushHistoryQuery->order('createTime', 'desc')->select();
+
+ // 2. 查询所有任务(包括未执行的)
+ $allTasksQuery = Db::name('workbench')
+ ->alias('w')
+ ->join('workbench_group_push wgp', 'wgp.workbenchId = w.id', 'left')
+ ->where($workbenchWhere)
->field([
- 'wgpi.workbenchId',
- 'wgpi.contentId',
- 'FROM_UNIXTIME(wgpi.createTime, "%Y-%m-%d %H:00:00") as pushTime',
- 'wgpi.targetType'
- ])
- ->group('wgpi.workbenchId, wgpi.contentId, pushTime, wgpi.targetType')
- ->buildSql();
-
- $total = Db::table('(' . $subQuery . ') as temp')->count();
+ 'w.id as workbenchId',
+ 'w.name as workbenchName',
+ 'w.createTime',
+ 'wgp.targetType',
+ 'wgp.groupPushSubType',
+ 'wgp.groups',
+ 'wgp.friends',
+ 'wgp.trafficPools'
+ ]);
- // 处理每条记录
- foreach ($list as &$item) {
+ if (!empty($keyword)) {
+ $allTasksQuery->where('w.name', 'like', '%' . $keyword . '%');
+ }
+
+ $allTasks = $allTasksQuery->select();
+
+ // 3. 合并数据:已执行的推送记录 + 未执行的任务
+ $resultList = [];
+ $executedWorkbenchIds = [];
+
+ // 处理已执行的推送记录
+ foreach ($pushHistoryList as $item) {
$itemWorkbenchId = $item['workbenchId'];
$contentId = $item['contentId'];
$pushTime = $item['pushTime'];
$targetType = intval($item['targetType']);
+ $groupPushSubType = isset($item['groupPushSubType']) ? intval($item['groupPushSubType']) : 1;
+
+ // 标记该工作台已有执行记录
+ if (!in_array($itemWorkbenchId, $executedWorkbenchIds)) {
+ $executedWorkbenchIds[] = $itemWorkbenchId;
+ }
// 将时间字符串转换为时间戳范围(小时级别)
$pushTimeStart = strtotime($pushTime);
@@ -2937,23 +2945,149 @@ class WorkbenchController extends Controller
$failCount = 0; // 简化处理,实际需要从发送状态获取
// 状态判断
- $status = $successCount > 0 ? 'success' : 'failed';
+ $itemStatus = $successCount > 0 ? 'success' : 'failed';
if ($failCount > 0 && $successCount > 0) {
- $status = 'partial';
+ $itemStatus = 'partial';
}
- $item['pushType'] = $targetType == 1 ? '群推送' : '好友推送';
- $item['pushTypeCode'] = $targetType;
- $item['targetCount'] = $targetCount;
- $item['successCount'] = $successCount;
- $item['failCount'] = $failCount;
- $item['status'] = $status;
- $item['statusText'] = $status == 'success' ? '成功' : ($status == 'partial' ? '部分成功' : '失败');
- $item['createTime'] = date('Y-m-d H:i:s', $item['createTime']);
- // 任务名称(工作台名称)
- $item['taskName'] = $item['workbenchName'] ?? '';
+ // 推送类型判断
+ $pushTypeText = '';
+ $pushTypeCode = '';
+ if ($targetType == 1) {
+ // 群推送
+ if ($groupPushSubType == 2) {
+ $pushTypeText = '群公告';
+ $pushTypeCode = 'announcement';
+ } else {
+ $pushTypeText = '群消息';
+ $pushTypeCode = 'group';
+ }
+ } else {
+ // 好友推送
+ $pushTypeText = '好友消息';
+ $pushTypeCode = 'friend';
+ }
+
+ $resultList[] = [
+ 'workbenchId' => $itemWorkbenchId,
+ 'taskName' => $item['workbenchName'] ?? '',
+ 'pushType' => $pushTypeText,
+ 'pushTypeCode' => $pushTypeCode,
+ 'targetCount' => $targetCount,
+ 'successCount' => $successCount,
+ 'failCount' => $failCount,
+ 'status' => $itemStatus,
+ 'statusText' => $this->getStatusText($itemStatus),
+ 'createTime' => date('Y-m-d H:i:s', $item['createTime']),
+ 'contentLibraryName' => $item['contentLibraryName'] ?? ''
+ ];
}
- unset($item);
+
+ // 处理未执行的任务
+ foreach ($allTasks as $task) {
+ $taskWorkbenchId = $task['workbenchId'];
+
+ // 如果该任务已有执行记录,跳过(避免重复)
+ if (in_array($taskWorkbenchId, $executedWorkbenchIds)) {
+ continue;
+ }
+
+ $targetType = isset($task['targetType']) ? intval($task['targetType']) : 1;
+ $groupPushSubType = isset($task['groupPushSubType']) ? intval($task['groupPushSubType']) : 1;
+
+ // 计算目标数量(从配置中获取)
+ $targetCount = 0;
+ if ($targetType == 1) {
+ // 群推送:统计配置的群数量
+ $groups = json_decode($task['groups'] ?? '[]', true);
+ $targetCount = is_array($groups) ? count($groups) : 0;
+ } else {
+ // 好友推送:统计配置的好友数量或流量池数量
+ $friends = json_decode($task['friends'] ?? '[]', true);
+ $trafficPools = json_decode($task['trafficPools'] ?? '[]', true);
+ $friendCount = is_array($friends) ? count($friends) : 0;
+ $poolCount = is_array($trafficPools) ? count($trafficPools) : 0;
+ // 如果配置了流量池,目标数量暂时显示为流量池数量(实际数量需要从流量池中统计)
+ $targetCount = $friendCount > 0 ? $friendCount : $poolCount;
+ }
+
+ // 推送类型判断
+ $pushTypeText = '';
+ $pushTypeCode = '';
+ if ($targetType == 1) {
+ // 群推送
+ if ($groupPushSubType == 2) {
+ $pushTypeText = '群公告';
+ $pushTypeCode = 'announcement';
+ } else {
+ $pushTypeText = '群消息';
+ $pushTypeCode = 'group';
+ }
+ } else {
+ // 好友推送
+ $pushTypeText = '好友消息';
+ $pushTypeCode = 'friend';
+ }
+
+ $resultList[] = [
+ 'workbenchId' => $taskWorkbenchId,
+ 'taskName' => $task['workbenchName'] ?? '',
+ 'pushType' => $pushTypeText,
+ 'pushTypeCode' => $pushTypeCode,
+ 'targetCount' => $targetCount,
+ 'successCount' => 0,
+ 'failCount' => 0,
+ 'status' => 'pending',
+ 'statusText' => '进行中',
+ 'createTime' => date('Y-m-d H:i:s', $task['createTime']),
+ 'contentLibraryName' => ''
+ ];
+ }
+
+ // 应用筛选条件
+ $filteredList = [];
+ foreach ($resultList as $item) {
+ // 推送类型筛选
+ if (!empty($pushType)) {
+ if ($pushType === 'friend' && $item['pushTypeCode'] !== 'friend') {
+ continue;
+ }
+ if ($pushType === 'group' && $item['pushTypeCode'] !== 'group') {
+ continue;
+ }
+ if ($pushType === 'announcement' && $item['pushTypeCode'] !== 'announcement') {
+ continue;
+ }
+ }
+
+ // 状态筛选
+ if (!empty($status)) {
+ if ($status === 'success' && $item['status'] !== 'success') {
+ continue;
+ }
+ if ($status === 'progress') {
+ // 进行中:包括 partial 和 pending
+ if ($item['status'] !== 'partial' && $item['status'] !== 'pending') {
+ continue;
+ }
+ }
+ if ($status === 'failed' && $item['status'] !== 'failed') {
+ continue;
+ }
+ }
+
+ $filteredList[] = $item;
+ }
+
+ // 按创建时间倒序排序
+ usort($filteredList, function($a, $b) {
+ return strtotime($b['createTime']) - strtotime($a['createTime']);
+ });
+
+ // 分页处理
+ $total = count($filteredList);
+ $offset = ($page - 1) * $limit;
+ $list = array_slice($filteredList, $offset, $limit);
return json([
'code' => 200,
@@ -2967,5 +3101,21 @@ class WorkbenchController extends Controller
]);
}
+ /**
+ * 获取状态文本
+ * @param string $status 状态码
+ * @return string 状态文本
+ */
+ private function getStatusText($status)
+ {
+ $statusMap = [
+ 'success' => '已完成',
+ 'partial' => '进行中',
+ 'pending' => '进行中',
+ 'failed' => '失败'
+ ];
+ return $statusMap[$status] ?? '未知';
+ }
+
}
\ No newline at end of file
diff --git a/Server/sql.sql b/Server/sql.sql
new file mode 100644
index 00000000..b49716bc
--- /dev/null
+++ b/Server/sql.sql
@@ -0,0 +1,2301 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server : kr_存客宝
+ Source Server Type : MySQL
+ Source Server Version : 50736
+ Source Host : 56b4c23f6853c.gz.cdb.myqcloud.com:14413
+ Source Schema : cunkebao_v3
+
+ Target Server Type : MySQL
+ Target Server Version : 50736
+ File Encoding : 65001
+
+ Date: 12/11/2025 11:05:39
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for ck_administrator_permissions
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_administrator_permissions`;
+CREATE TABLE `ck_administrator_permissions` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自动ID',
+ `adminId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '超管用户ID',
+ `permissions` json NULL COMMENT '权限对象',
+ `createTime` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '更新时间',
+ `deleteTime` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '超级管理员权限配置表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_administrators
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_administrators`;
+CREATE TABLE `ck_administrators` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `username` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '管理员名字',
+ `account` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录账号',
+ `password` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录密码',
+ `status` tinyint(3) UNSIGNED NULL DEFAULT 1 COMMENT '1->可用,0->禁用',
+ `lastLoginTime` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '最近登录时间',
+ `lastLoginIp` char(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '最近登录ip',
+ `authId` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '权限id',
+ `createTime` int(10) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(10) NULL DEFAULT NULL COMMENT '更新时间',
+ `deleteTime` int(11) NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '超级管理员表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_ai_knowledge_base
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_ai_knowledge_base`;
+CREATE TABLE `ck_ai_knowledge_base` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `typeId` int(11) NULL DEFAULT 1 COMMENT '类型id',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `label` json NULL COMMENT '标签',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
+ `documentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '知识库文件id',
+ `fileUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件地址',
+ `size` int(10) NULL DEFAULT NULL COMMENT '文件大小',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ai知识库' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_ai_knowledge_base_type
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_ai_knowledge_base_type`;
+CREATE TABLE `ck_ai_knowledge_base_type` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `type` tinyint(2) NULL DEFAULT 1 COMMENT '类型 0系统 1用户创建',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
+ `label` json NULL COMMENT '标签',
+ `prompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '提示词',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
+ `status` tinyint(2) NULL DEFAULT 1 COMMENT '状态 1启用 0禁用',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ai知识库类型' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_ai_settings
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_ai_settings`;
+CREATE TABLE `ck_ai_settings` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `config` json NULL COMMENT '配置信息',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isRelease` tinyint(2) NULL DEFAULT 0 COMMENT '是否发布 0未发布 1已发布',
+ `releaseTime` int(11) NULL DEFAULT NULL COMMENT '发布时间',
+ `botId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '智能体id',
+ `datasetId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '知识库id',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'AI配置' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_app_version
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_app_version`;
+CREATE TABLE `ck_app_version` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `forceUpdate` tinyint(2) NULL DEFAULT 0 COMMENT '是否强制更新',
+ `version` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `downloadUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `updateContent` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_attachments
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_attachments`;
+CREATE TABLE `ck_attachments` (
+ `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增长ID',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源名',
+ `hash_key` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源hash校验值',
+ `server` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储服务商',
+ `source` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源地址',
+ `dl_count` int(10) NULL DEFAULT 0 COMMENT '下载次数',
+ `size` int(10) NULL DEFAULT 0 COMMENT '资源大小',
+ `suffix` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源类型',
+ `scene` tinyint(3) NOT NULL COMMENT '引用场景,获客海报1',
+ `create_at` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
+ `update_at` timestamp(0) NULL DEFAULT NULL COMMENT '修改时间',
+ `delete_at` timestamp(0) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_hash_key`(`hash_key`) USING BTREE,
+ INDEX `idx_server`(`server`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 481 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '附件表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_call_recording
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_call_recording`;
+CREATE TABLE `ck_call_recording` (
+ `id` int(11) NOT NULL,
+ `phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
+ `isCallOut` tinyint(2) NULL DEFAULT NULL COMMENT '是否外呼',
+ `companyId` int(11) NULL DEFAULT NULL,
+ `callType` tinyint(2) NULL DEFAULT NULL,
+ `beginTime` int(11) NULL DEFAULT NULL,
+ `endTime` int(11) NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_id_phone_isCallOut_companyId`(`id`, `phone`, `isCallOut`, `companyId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_company
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_company`;
+CREATE TABLE `ck_company` (
+ `id` int(11) UNSIGNED NOT NULL COMMENT '项目真实ID,非自增',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '项目名称',
+ `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态',
+ `tenantId` int(11) UNSIGNED NULL DEFAULT 242 COMMENT '触客宝租户ID',
+ `companyId` int(11) UNSIGNED NOT NULL COMMENT '触客宝部门ID',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `createTime` int(11) NULL DEFAULT NULL,
+ `updateTime` int(11) NULL DEFAULT NULL,
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_content_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_content_item`;
+CREATE TABLE `ck_content_item` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `libraryId` int(11) NOT NULL COMMENT '所属内容库ID',
+ `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'moment' COMMENT '内容类型(moment:朋友圈)',
+ `contentType` tinyint(1) NULL DEFAULT 0 COMMENT '0:未知 1:图片 2:链接 3:视频 4:文本 5:小程序 ',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '内容标题',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文本内容',
+ `contentAi` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文本内容_Ai版',
+ `contentData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '完整内容数据(JSON格式)',
+ `snsId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '朋友圈唯一标识',
+ `msgId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群消息唯一标识',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信ID',
+ `friendId` int(11) NULL DEFAULT NULL COMMENT '微信好友ID',
+ `createMomentTime` bigint(20) NULL DEFAULT 0 COMMENT '朋友圈创建时间',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '记录创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '记录更新时间',
+ `coverImage` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图片URL',
+ `resUrls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '资源URL列表(JSON格式)',
+ `urls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '相对路径URL列表(JSON格式)',
+ `location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地理位置名称',
+ `lat` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '纬度',
+ `lng` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '经度',
+ `status` tinyint(1) NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
+ `isDel` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除(0:否,1:是)',
+ `delTime` int(11) NULL DEFAULT 0 COMMENT '删除时间',
+ `wechatChatroomId` int(11) NULL DEFAULT NULL,
+ `senderNickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `createMessageTime` int(11) NULL DEFAULT NULL,
+ `comment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '评论',
+ `sendTime` int(11) NULL DEFAULT 0 COMMENT '预计发布时间',
+ `sendTimes` int(11) NULL DEFAULT 0 COMMENT '实际发布时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_library`(`libraryId`) USING BTREE,
+ INDEX `idx_snsid`(`snsId`) USING BTREE,
+ INDEX `idx_wechatid`(`wechatId`) USING BTREE,
+ INDEX `idx_friendid`(`friendId`) USING BTREE,
+ INDEX `idx_create_time`(`createTime`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5876 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '内容项目表-存储朋友圈采集数据' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_content_library
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_content_library`;
+CREATE TABLE `ck_content_library` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `sourceType` tinyint(2) NOT NULL DEFAULT 1 COMMENT '类型 1好友 2群 3自定义',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容库名称',
+ `devices` json NULL COMMENT '设备列表,JSON格式:[{\"id\":1,\"name\":\"设备1\"},{\"id\":2,\"name\":\"设备2\"}]',
+ `catchType` json NULL COMMENT '采集类型',
+ `sourceFriends` json NULL COMMENT '选择的微信好友',
+ `sourceGroups` json NULL COMMENT '选择的微信群',
+ `groupMembers` json NULL COMMENT '选择的微信群的群成员',
+ `keywordInclude` json NULL COMMENT '包含的关键词',
+ `keywordExclude` json NULL COMMENT '排除的关键词',
+ `aiEnabled` tinyint(1) NULL DEFAULT 0 COMMENT '是否启用AI:0=禁用,1=启用',
+ `aiPrompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'AI提示词',
+ `timeEnabled` tinyint(1) NULL DEFAULT 0 COMMENT '是否启用时间限制:0=禁用,1=启用',
+ `timeStart` int(11) NULL DEFAULT NULL COMMENT '开始时间',
+ `timeEnd` int(11) NULL DEFAULT NULL COMMENT '结束时间',
+ `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态:0=禁用,1=启用',
+ `userId` int(11) NOT NULL COMMENT '用户ID',
+ `companyId` int(11) NOT NULL COMMENT '公司ID',
+ `createTime` int(11) NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT 0 COMMENT '更新时间',
+ `isDel` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 87 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '内容库表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_coze_conversation
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_coze_conversation`;
+CREATE TABLE `ck_coze_conversation` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户id',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `conversation_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '对话ID',
+ `bot_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '机器人ID',
+ `created_at` int(11) NOT NULL DEFAULT 0 COMMENT '会话创建时间戳',
+ `meta_data` json NULL COMMENT '元数据',
+ `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间戳',
+ `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间戳',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `idx_conversation_id`(`conversation_id`) USING BTREE,
+ INDEX `idx_bot_id`(`bot_id`) USING BTREE,
+ INDEX `idx_create_time`(`create_time`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Coze AI 会话表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_coze_message
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_coze_message`;
+CREATE TABLE `ck_coze_message` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `chat_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '消息ID',
+ `conversation_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '会话ID',
+ `bot_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '机器人ID',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '消息内容',
+ `content_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'text' COMMENT '内容类型',
+ `role` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色',
+ `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '消息类型',
+ `created_at` int(11) NOT NULL COMMENT '消息创建时间',
+ `updated_at` int(11) NOT NULL COMMENT '消息更新时间',
+ `create_time` int(11) NOT NULL COMMENT '记录创建时间',
+ `update_time` int(11) NOT NULL COMMENT '记录更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_chat_id`(`chat_id`) USING BTREE,
+ INDEX `idx_conversation_id`(`conversation_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 184 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '消息记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_coze_workspace
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_coze_workspace`;
+CREATE TABLE `ck_coze_workspace` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `workspace_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '工作区ID',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '工作区名称',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '工作区描述',
+ `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `workspace_id`(`workspace_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Coze空间表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_customer_acquisition_task
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_customer_acquisition_task`;
+CREATE TABLE `ck_customer_acquisition_task` (
+ `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增长ID',
+ `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '计划名称',
+ `sceneId` int(11) NULL DEFAULT 1 COMMENT '场景ID',
+ `sceneConf` json NULL COMMENT '场景具体配置信息',
+ `reqConf` json NULL COMMENT '好友申请设置',
+ `msgConf` json NULL COMMENT '消息设置',
+ `tagConf` json NULL COMMENT '标签设置',
+ `userId` int(11) NULL DEFAULT 0 COMMENT '创建者',
+ `companyId` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '公司ID',
+ `status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '状态 0禁用 1启用',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '修改时间',
+ `deleteTime` int(11) NULL DEFAULT 0 COMMENT '删除时间',
+ `apiKey` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 162 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '获客计划表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_device
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_device`;
+CREATE TABLE `ck_device` (
+ `id` int(11) UNSIGNED NOT NULL COMMENT '设备真实ID,非自增',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备名称',
+ `imei` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '设备IMEI',
+ `deviceImei` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备本地IMEI',
+ `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
+ `operatingSystem` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作系统版本',
+ `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '型号',
+ `brand` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '品牌',
+ `rooted` tinyint(1) NULL DEFAULT 0 COMMENT '是否root',
+ `xPosed` tinyint(1) NULL DEFAULT 0 COMMENT '是否安装xposed',
+ `softwareVersion` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '软件版本',
+ `extra` json NULL COMMENT '额外信息JSON',
+ `alive` tinyint(1) NULL DEFAULT 0 COMMENT '是否在线',
+ `companyId` int(11) NOT NULL COMMENT '公司ID',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_id_imei`(`imei`, `id`) USING BTREE,
+ INDEX `idx_group`(`companyId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_device_handle_log
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_device_handle_log`;
+CREATE TABLE `ck_device_handle_log` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `content` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作说明',
+ `deviceId` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '设备id',
+ `userId` int(11) NULL DEFAULT NULL COMMENT '用户id',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '租户id',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '操作时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 304 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_device_taskconf
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_device_taskconf`;
+CREATE TABLE `ck_device_taskconf` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `deviceId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '设备ID',
+ `autoLike` tinyint(3) NULL DEFAULT 0 COMMENT '自动点赞',
+ `momentsSync` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '朋友圈同步',
+ `autoCustomerDev` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '自动开发客户',
+ `groupMessageDeliver` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '群消息推送',
+ `autoGroup` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '自动建群',
+ `autoAddFriend` tinyint(3) NULL DEFAULT 0 COMMENT '自动加好友',
+ `contentSync` tinyint(255) UNSIGNED NULL DEFAULT 0 COMMENT '朋友圈同步',
+ `aiChat` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT 'AI 会话',
+ `autoReply` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '自动回复',
+ `companyId` int(10) NULL DEFAULT NULL COMMENT '公司ID',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '更新时间',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备任务配置表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_device_user
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_device_user`;
+CREATE TABLE `ck_device_user` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `companyId` int(11) UNSIGNED NOT NULL COMMENT '公司id',
+ `userId` int(11) UNSIGNED NOT NULL COMMENT '用户id',
+ `deviceId` int(11) UNSIGNED NOT NULL COMMENT '设备id',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备跟操盘手的关联关系' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_device_wechat_login
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_device_wechat_login`;
+CREATE TABLE `ck_device_wechat_login` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `deviceId` int(11) NULL DEFAULT NULL COMMENT '设备ID',
+ `wechatId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信ID',
+ `alive` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '微信在线否',
+ `companyId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '租户ID',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '更新时间',
+ `isTips` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否提示迁移',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `wechatId`(`wechatId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 309 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备登录微信记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_flow_package
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_flow_package`;
+CREATE TABLE `ck_flow_package` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '套餐名称',
+ `tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '套餐标签',
+ `originalPrice` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '原价',
+ `price` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '售价',
+ `monthlyFlow` int(11) NOT NULL DEFAULT 0 COMMENT '每月流量(人/月)',
+ `duration` int(11) NOT NULL DEFAULT 1 COMMENT '套餐时长(月)',
+ `privileges` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '套餐特权,多行文本存储',
+ `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
+ `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态: 0=禁用, 1=启用',
+ `isDel` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_name`(`name`) USING BTREE,
+ INDEX `idx_tag`(`tag`) USING BTREE,
+ INDEX `idx_is_del`(`isDel`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量套餐表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_flow_package_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_flow_package_order`;
+CREATE TABLE `ck_flow_package_order` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `orderNo` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订单编号',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `packageId` int(11) NOT NULL DEFAULT 0 COMMENT '套餐ID',
+ `packageName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '套餐名称',
+ `amount` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '订单金额',
+ `duration` int(11) NOT NULL DEFAULT 1 COMMENT '购买时长(月)',
+ `payStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '支付状态: 0=未支付, 1=已支付,10=无需支付',
+ `payTime` int(11) NOT NULL DEFAULT 0 COMMENT '支付时间',
+ `payType` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '支付方式: wechat=微信, alipay=支付宝,nopay=无需支付',
+ `transactionId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '第三方支付交易号',
+ `status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '订单状态: 0=待支付, 1=已支付, 2=已取消, 3=已退款',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
+ `isDel` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_order_no`(`orderNo`) USING BTREE,
+ INDEX `idx_user_id`(`userId`) USING BTREE,
+ INDEX `idx_package_id`(`packageId`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE,
+ INDEX `idx_pay_status`(`payStatus`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 37 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '套餐订单表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_flow_usage_record
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_flow_usage_record`;
+CREATE TABLE `ck_flow_usage_record` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `packageId` int(11) NOT NULL DEFAULT 0 COMMENT '套餐ID',
+ `userPackageId` int(11) NOT NULL DEFAULT 0 COMMENT '用户套餐ID',
+ `taskId` int(11) NOT NULL DEFAULT 0 COMMENT '关联任务ID',
+ `phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '微信号',
+ `usageAmount` int(11) NOT NULL DEFAULT 0 COMMENT '使用量(人)',
+ `usageType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '使用类型: 1=添加好友, 2=群发消息, 3=其他',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_user_id`(`userId`) USING BTREE,
+ INDEX `idx_package_id`(`packageId`) USING BTREE,
+ INDEX `idx_user_package_id`(`userPackageId`) USING BTREE,
+ INDEX `idx_task_id`(`taskId`) USING BTREE,
+ INDEX `idx_phone`(`phone`) USING BTREE,
+ INDEX `idx_create_time`(`createTime`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量使用记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_jd_promotion_site
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_jd_promotion_site`;
+CREATE TABLE `ck_jd_promotion_site` (
+ `id` bigint(11) NOT NULL,
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `jdSocialMediaId` bigint(11) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_jd_social_media
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_jd_social_media`;
+CREATE TABLE `ck_jd_social_media` (
+ `id` bigint(11) NOT NULL,
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `appkey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `secretkey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_ai_push
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_ai_push`;
+CREATE TABLE `ck_kf_ai_push` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '推送名称',
+ `tags` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '目标用户标签(JSON数组格式)',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '推送内容(支持变量:{客户名称}{产品功能}{核心价值}等)',
+ `pushTiming` tinyint(4) NOT NULL DEFAULT 1 COMMENT '推送时机:1=立即推送,2=最佳时机(AI决定),3=定时推送',
+ `scheduledTime` int(11) NOT NULL DEFAULT 0 COMMENT '定时推送时间(时间戳,仅当pushTiming=3时有效)',
+ `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '启用状态:0=禁用,1=启用',
+ `successRate` decimal(5, 2) NOT NULL DEFAULT 0.00 COMMENT '成功率(百分比,保留两位小数)',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司ID',
+ `isDel` tinyint(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0=未删除,1=已删除',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间(时间戳)',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间(时间戳)',
+ `delTime` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间(时间戳)',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_company_user`(`companyId`, `userId`) USING BTREE,
+ INDEX `idx_pushTiming`(`pushTiming`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE,
+ INDEX `idx_isDel`(`isDel`) USING BTREE,
+ INDEX `idx_scheduledTime`(`scheduledTime`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'AI智能推送表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_ai_push_record
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_ai_push_record`;
+CREATE TABLE `ck_kf_ai_push_record` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `pushId` int(11) NOT NULL DEFAULT 0 COMMENT '推送ID',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司ID',
+ `wechatAccountId` int(11) NOT NULL DEFAULT 0 COMMENT '微信账号ID',
+ `friendIdOrGroupId` int(11) NOT NULL DEFAULT 0 COMMENT '好友ID或群ID',
+ `isSend` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否发送:0=未发送,1=已发送',
+ `sendTime` int(11) NOT NULL DEFAULT 0 COMMENT '发送时间(时间戳)',
+ `receiveTime` int(11) NOT NULL DEFAULT 0 COMMENT '接收时间(时间戳)',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间(时间戳)',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_pushId`(`pushId`) USING BTREE,
+ INDEX `idx_company`(`companyId`) USING BTREE,
+ INDEX `idx_user`(`userId`) USING BTREE,
+ INDEX `idx_createTime`(`createTime`) USING BTREE,
+ INDEX `idx_isSend`(`isSend`) USING BTREE,
+ INDEX `idx_wechatAccount`(`wechatAccountId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'AI智能推送记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_auto_greetings
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_auto_greetings`;
+CREATE TABLE `ck_kf_auto_greetings` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '规则名称',
+ `trigger` tinyint(4) NOT NULL DEFAULT 0 COMMENT '触发类型:1=好友首次添加,2=首次发消息,3=时间触发,4=关键词触发,5=生日触发,6=自定义',
+ `condition` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '具体条件(JSON格式)',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '问候内容',
+ `level` int(11) NOT NULL DEFAULT 0 COMMENT '优先级(数字越小优先级越高)',
+ `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '启用状态:0=禁用,1=启用',
+ `usageCount` int(11) NOT NULL DEFAULT 0 COMMENT '使用次数',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司ID',
+ `is_template` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否模板:0=否,1=是',
+ `isDel` tinyint(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0=未删除,1=已删除',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间(时间戳)',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间(时间戳)',
+ `delTime` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间(时间戳)',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_company_user`(`companyId`, `userId`) USING BTREE,
+ INDEX `idx_trigger`(`trigger`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE,
+ INDEX `idx_isDel`(`isDel`) USING BTREE,
+ INDEX `idx_level`(`level`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '问候规则表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_auto_greetings_record
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_auto_greetings_record`;
+CREATE TABLE `ck_kf_auto_greetings_record` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `autoId` int(11) NOT NULL DEFAULT 0 COMMENT '规则ID',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司ID',
+ `wechatAccountId` int(11) NOT NULL DEFAULT 0 COMMENT '微信账号ID',
+ `friendIdOrGroupId` int(11) NOT NULL DEFAULT 0 COMMENT '好友ID或群ID',
+ `isSend` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否发送:0=未发送,1=已发送',
+ `sendTime` int(11) NOT NULL DEFAULT 0 COMMENT '发送时间(时间戳)',
+ `receiveTime` int(11) NOT NULL DEFAULT 0 COMMENT '接收时间(时间戳)',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间(时间戳)',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_autoId`(`autoId`) USING BTREE,
+ INDEX `idx_company`(`companyId`) USING BTREE,
+ INDEX `idx_user`(`userId`) USING BTREE,
+ INDEX `idx_createTime`(`createTime`) USING BTREE,
+ INDEX `idx_isSend`(`isSend`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '问候规则使用记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_follow_up
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_follow_up`;
+CREATE TABLE `ck_kf_follow_up` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
+ `friendId` int(12) NULL DEFAULT NULL COMMENT '好友id',
+ `type` tinyint(2) NULL DEFAULT 0 COMMENT '类型 0其他 1电话回访 2发送消息 3安排会议 4发送邮件',
+ `reminderTime` int(12) NULL DEFAULT NULL COMMENT '提醒时间',
+ `isRemind` tinyint(2) NULL DEFAULT 0 COMMENT '是否提醒',
+ `isProcess` tinyint(2) NULL DEFAULT 0 COMMENT '是否处理',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE,
+ INDEX `idx_userId`(`userId`) USING BTREE,
+ INDEX `idx_level`(`type`) USING BTREE,
+ INDEX `idx_isRemind`(`isRemind`) USING BTREE,
+ INDEX `idx_isProcess`(`isProcess`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '跟进提醒' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_friend_settings
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_friend_settings`;
+CREATE TABLE `ck_kf_friend_settings` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `type` tinyint(2) NULL DEFAULT 0 COMMENT '匹配类型 0人工接待 1AI辅助 2AI接管',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `friendId` int(11) NULL DEFAULT NULL COMMENT '好友id',
+ `conversationId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '会话id',
+ `conversationTime` int(11) NULL DEFAULT NULL COMMENT '会话创建时间',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE,
+ INDEX `idx_userId`(`userId`) USING BTREE,
+ INDEX `idx_wechatAccountId`(`wechatAccountId`) USING BTREE,
+ INDEX `idx_friendId`(`friendId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 37 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友AI配置' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_keywords
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_keywords`;
+CREATE TABLE `ck_kf_keywords` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `keywords` json NULL COMMENT '关键词',
+ `type` tinyint(2) NULL DEFAULT NULL COMMENT '匹配类型 0模糊 1精确',
+ `replyType` tinyint(2) NULL DEFAULT NULL COMMENT '回复类型 0素材回复 1自定义',
+ `content` json NULL COMMENT '自定义内容',
+ `metailGroups` json NULL COMMENT '素材id',
+ `status` tinyint(2) NULL DEFAULT NULL COMMENT '状态 0停用 1启用',
+ `level` tinyint(2) NULL DEFAULT 0 COMMENT '等级 0低优先级 1中优先级 2高优先级',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关键词管理' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_material
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_material`;
+CREATE TABLE `ck_kf_material` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `content` json NULL COMMENT '内容',
+ `cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面',
+ `status` tinyint(2) NULL DEFAULT NULL COMMENT '状态 0停用 1启用',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '素材库管理' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_moments
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_moments`;
+CREATE TABLE `ck_kf_moments` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `sendData` json NULL COMMENT '发送的具体信息',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `isSend` tinyint(2) NULL DEFAULT 0 COMMENT '是否发送 0否 1是',
+ `sendTime` int(11) NULL DEFAULT NULL COMMENT '发送时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客服端发布朋友圈记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_moments_settings
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_moments_settings`;
+CREATE TABLE `ck_kf_moments_settings` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `wechatId` int(12) NULL DEFAULT NULL COMMENT '微信客服id',
+ `max` int(11) NULL DEFAULT 5 COMMENT '每日上限',
+ `sendNum` int(11) NULL DEFAULT 0 COMMENT '今日发送次数',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客服朋友圈配置信息' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_notice
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_notice`;
+CREATE TABLE `ck_kf_notice` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `type` tinyint(2) NULL DEFAULT NULL COMMENT '通知类型 1代办事项 2跟进提醒 ',
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `bindId` int(11) NULL DEFAULT NULL COMMENT '绑定的id',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '通知消息',
+ `isRead` tinyint(2) NULL DEFAULT 0 COMMENT '是否读取',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `readTime` int(12) NULL DEFAULT NULL COMMENT '读取时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 246 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '通知消息' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_questions
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_questions`;
+CREATE TABLE `ck_kf_questions` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `type` tinyint(2) NULL DEFAULT 0 COMMENT '匹配类型 0模糊 1精确',
+ `questions` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '问题',
+ `answers` json NULL COMMENT '答案',
+ `status` tinyint(2) NULL DEFAULT 1 COMMENT '状态 0禁用 1启用',
+ `isDel` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `deleteTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE,
+ INDEX `idx_userId`(`userId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'AI问答' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_reply
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_reply`;
+CREATE TABLE `ck_kf_reply` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `groupId` int(11) NULL DEFAULT NULL,
+ `userId` int(11) NULL DEFAULT NULL,
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `msgType` tinyint(2) NULL DEFAULT NULL,
+ `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ `lastUpdateTime` int(11) NULL DEFAULT NULL,
+ `sortIndex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 130746 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '快捷回复' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_reply_group
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_reply_group`;
+CREATE TABLE `ck_kf_reply_group` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `userId` int(11) NULL DEFAULT 0,
+ `companyId` int(11) NULL DEFAULT 0,
+ `groupName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `sortIndex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `parentId` int(11) NULL DEFAULT NULL,
+ `replyType` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `replys` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 21898 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '快捷回复分组' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_sensitive_word
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_sensitive_word`;
+CREATE TABLE `ck_kf_sensitive_word` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `keywords` json NULL COMMENT '关键词',
+ `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '替换内容/警告内容',
+ `operation` tinyint(2) NULL DEFAULT NULL COMMENT '操作 0不操作 1替换 2删除 3警告 4禁止发送',
+ `status` tinyint(2) NULL DEFAULT NULL COMMENT '状态 0停用 1启用',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '敏感词管理' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_kf_to_do
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_kf_to_do`;
+CREATE TABLE `ck_kf_to_do` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题',
+ `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
+ `friendId` int(12) NULL DEFAULT NULL COMMENT '好友id',
+ `level` tinyint(2) NULL DEFAULT 0 COMMENT '提示等级 0低优先级 1中优先级 2高优先级 3紧急',
+ `reminderTime` int(12) NULL DEFAULT NULL COMMENT '提醒时间',
+ `isRemind` tinyint(2) NULL DEFAULT 0 COMMENT '是否提醒',
+ `isProcess` tinyint(2) NULL DEFAULT 0 COMMENT '是否处理',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE,
+ INDEX `idx_userId`(`userId`) USING BTREE,
+ INDEX `idx_level`(`level`) USING BTREE,
+ INDEX `idx_isRemind`(`isRemind`) USING BTREE,
+ INDEX `idx_isProcess`(`isProcess`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '待办事项' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_menus
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_menus`;
+CREATE TABLE `ck_menus` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
+ `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单名称',
+ `path` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '路由路径',
+ `icon` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标名称',
+ `parentId` int(11) NOT NULL DEFAULT 0 COMMENT '父菜单ID,0表示顶级菜单',
+ `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:1启用,0禁用',
+ `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序,数值越小越靠前',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_parent_id`(`parentId`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统菜单表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_order`;
+CREATE TABLE `ck_order` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `mchId` int(11) NULL DEFAULT NULL COMMENT '门店号',
+ `companyId` int(11) UNSIGNED NOT NULL,
+ `userId` int(11) NULL DEFAULT NULL,
+ `orderType` tinyint(2) NULL DEFAULT NULL COMMENT '订单类型 1购买算力',
+ `status` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '支付状态 0待支付 1已付款 2已退款 3付款失败',
+ `goodsId` int(11) NULL DEFAULT 0 COMMENT '商品id',
+ `goodsName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品名称',
+ `goodsSpecs` json NULL COMMENT '商品规格',
+ `money` int(11) NULL DEFAULT 0 COMMENT '金额 单位分',
+ `orderNo` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单号',
+ `ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `nonceStr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '随机字符串',
+ `createTime` int(11) NULL DEFAULT NULL,
+ `payType` tinyint(2) NULL DEFAULT NULL COMMENT '支付类型 1微信 2支付宝',
+ `payTime` int(11) NULL DEFAULT NULL,
+ `payInfo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '错误信息',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 79 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_plan_scene
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_plan_scene`;
+CREATE TABLE `ck_plan_scene` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '场景名称',
+ `description` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
+ `image` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片icon',
+ `status` tinyint(3) NULL DEFAULT NULL COMMENT '状态',
+ `sort` tinyint(3) NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '修改时间',
+ `deleteTime` int(11) NULL DEFAULT 0 COMMENT '删除时间',
+ `scenarioTags` json NULL COMMENT '标签',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '获客场景' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_plan_tags
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_plan_tags`;
+CREATE TABLE `ck_plan_tags` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `tagName` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签名',
+ `companyId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '部门ID',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量标签表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_task_customer
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_task_customer`;
+CREATE TABLE `ck_task_customer` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `task_id` int(11) NOT NULL,
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户姓名',
+ `source` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源',
+ `phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
+ `remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `tags` json NULL,
+ `siteTags` json NULL COMMENT '站内标签',
+ `processed_wechat_ids` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
+ `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '0-未处理,1-已处理/添加中,2-~~添加成功~~ ~~已添加~~添加任务成功 3-添加失败 4-已通过-已发消息',
+ `fail_reason` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
+ `addTime` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
+ `passTime` int(11) NOT NULL DEFAULT 0 COMMENT '通过时间',
+ `createTime` int(11) NOT NULL DEFAULT 0,
+ `updateTime` int(11) NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `task_id`(`task_id`) USING BTREE,
+ INDEX `addTime`(`addTime`) USING BTREE,
+ INDEX `passTime`(`passTime`) USING BTREE,
+ INDEX `updateTime`(`updateTime`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 24192 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_tokens_company
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_tokens_company`;
+CREATE TABLE `ck_tokens_company` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `tokens` bigint(100) NULL DEFAULT NULL,
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '公司算力账户' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_tokens_package
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_tokens_package`;
+CREATE TABLE `ck_tokens_package` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `tokens` int(12) NULL DEFAULT NULL,
+ `price` int(12) NULL DEFAULT NULL COMMENT '售价 单位分',
+ `originalPrice` int(12) NULL DEFAULT NULL COMMENT '原价 单位分',
+ `description` json NULL COMMENT '描述',
+ `sort` int(12) NULL DEFAULT 50 COMMENT '排序',
+ `isTrial` tinyint(2) NULL DEFAULT 0 COMMENT '是否试用',
+ `isRecommend` tinyint(2) NULL DEFAULT 0 COMMENT '是否推荐',
+ `isHot` tinyint(2) NULL DEFAULT 0 COMMENT '是否热门',
+ `isVip` tinyint(2) NULL DEFAULT 0 COMMENT '是否VIP',
+ `status` tinyint(2) NULL DEFAULT 0 COMMENT '状态 0停用 1启用',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `delTime` int(12) NULL DEFAULT NULL COMMENT '删除时间',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(12) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'token套餐' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_tokens_record
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_tokens_record`;
+CREATE TABLE `ck_tokens_record` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(11) NOT NULL DEFAULT 0 COMMENT '公司id',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '创建用户ID',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `friendIdOrGroupId` int(11) NULL DEFAULT NULL COMMENT '好友id或者群id',
+ `form` tinyint(2) NULL DEFAULT 0 COMMENT '来源 0未知 1好友聊天 2群聊天 3群公告 4商家 5充值',
+ `type` tinyint(2) NULL DEFAULT 0 COMMENT '类型 0减少 1增加',
+ `tokens` int(11) NULL DEFAULT NULL COMMENT '消耗tokens',
+ `balanceTokens` int(11) NULL DEFAULT NULL COMMENT '剩余tokens',
+ `remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `createTime` int(12) NULL DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 236 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '算力明细记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_order`;
+CREATE TABLE `ck_traffic_order` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `companyId` int(10) UNSIGNED NULL DEFAULT NULL,
+ `identifier` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量池用户',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `isDel` tinyint(2) NULL DEFAULT 0,
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ `orderno` varchar(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单编号',
+ `userId` int(11) NULL DEFAULT NULL,
+ `storeId` int(11) NULL DEFAULT NULL COMMENT '门店id',
+ `goddsName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品价格',
+ `price` int(10) NULL DEFAULT NULL COMMENT '商品价格',
+ `actualPay` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '实际支付',
+ `ownerWechatId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_pool
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_pool`;
+CREATE TABLE `ck_traffic_pool` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量标识,可以是手机号、微信号',
+ `mobile` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
+ `wechatId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信ID',
+ `createTime` int(10) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(10) NULL DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_identifier`(`identifier`) USING BTREE,
+ INDEX `idx_wechatId`(`wechatId`) USING BTREE,
+ INDEX `idx_mobile`(`mobile`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 959687 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量池' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_profile
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_profile`;
+CREATE TABLE `ck_traffic_profile` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量标识,可以是手机号、微信号',
+ `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '平台昵称',
+ `avatar` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '平台头像',
+ `gender` tinyint(3) NULL DEFAULT 0 COMMENT '平台性别',
+ `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '平台手机号',
+ `platformId` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '平台Id',
+ `createTime` int(10) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(10) NULL DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_identifier`(`identifier`) USING BTREE,
+ INDEX `idx_mobile`(`phone`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 196606 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量池用户个人信息' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_source
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_source`;
+CREATE TABLE `ck_traffic_source` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `type` tinyint(2) NULL DEFAULT 1 COMMENT '流量来源 0其他 1好友 2群 3场景',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量标识',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `status` tinyint(3) NULL DEFAULT 1 COMMENT '1待处理,2处理中,3已通过,4已拒绝,5已过期,6已取消 -3已删除(同步 tk_friend_task 表的 status)',
+ `sourceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源id(微信id或群id)',
+ `fromd` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量来源(群聊名称)',
+ `sceneId` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '场景ID',
+ `companyId` int(11) NULL DEFAULT 0 COMMENT '账号所属项目id',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '修改时间',
+ `R` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ `F` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ `M` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_identifier_sourceId_sceneId`(`identifier`, `sourceId`, `sceneId`) USING BTREE,
+ INDEX `idx_identifier`(`identifier`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 564508 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量来源' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_source_package
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_source_package`;
+CREATE TABLE `ck_traffic_source_package` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `userId` int(10) NULL DEFAULT NULL COMMENT '用户id',
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
+ `pic` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '账号所属项目id',
+ `matchingRules` json NULL COMMENT '匹配规则',
+ `isSys` tinyint(2) NULL DEFAULT 0 COMMENT '是否系统只有',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `updateTime` int(11) NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT 0 COMMENT '创建时间',
+ `deleteTime` int(11) NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `companyId`(`companyId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量池包' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_source_package_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_source_package_item`;
+CREATE TABLE `ck_traffic_source_package_item` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `packageId` int(10) NULL DEFAULT NULL COMMENT '流量包id',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '账号所属项目id',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流量标识,可以是手机号、微信号',
+ `isDel` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
+ `createTime` int(11) NULL DEFAULT 0 COMMENT '创建时间',
+ `deleteTime` int(10) NULL DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_packageId_companyId_identifier_isDel`(`packageId`, `companyId`, `identifier`, `isDel`) USING BTREE,
+ INDEX `packageId`(`packageId`) USING BTREE,
+ INDEX `companyId`(`companyId`) USING BTREE,
+ INDEX `identifier`(`identifier`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 34 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_traffic_tag
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_traffic_tag`;
+CREATE TABLE `ck_traffic_tag` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `tagId` int(11) NULL DEFAULT NULL,
+ `tagName` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签名',
+ `tagType` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签值',
+ `tagValue` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签值',
+ `companyId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '部门ID',
+ `trafficPoolId` int(10) NULL DEFAULT NULL COMMENT '流量池用户id traffic_pool的主键',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `isDel` tinyint(2) NULL DEFAULT NULL,
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量标签表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_user_flow_package
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_user_flow_package`;
+CREATE TABLE `ck_user_flow_package` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `packageId` int(11) NOT NULL DEFAULT 0 COMMENT '套餐ID',
+ `orderId` int(11) NOT NULL DEFAULT 0 COMMENT '关联订单ID',
+ `duration` int(11) NOT NULL DEFAULT 1 COMMENT '套餐时长(月)',
+ `totalFlow` int(11) NOT NULL DEFAULT 0 COMMENT '总流量(人)',
+ `usedFlow` int(11) NOT NULL DEFAULT 0 COMMENT '已使用流量(人)',
+ `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态: 0=无效, 1=有效',
+ `startTime` int(11) NOT NULL DEFAULT 0 COMMENT '开始时间',
+ `expireTime` int(11) NOT NULL DEFAULT 0 COMMENT '到期时间',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_user_id`(`userId`) USING BTREE,
+ INDEX `idx_package_id`(`packageId`) USING BTREE,
+ INDEX `idx_order_id`(`orderId`) USING BTREE,
+ INDEX `idx_expire_time`(`expireTime`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户流量套餐表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_user_log
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_user_log`;
+CREATE TABLE `ck_user_log` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `userId` int(11) NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `userName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
+ `action` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作类型',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '操作描述',
+ `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'IP地址',
+ `userAgent` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户设备信息',
+ `requestMethod` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '请求方法',
+ `requestUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '请求URL',
+ `requestData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求数据',
+ `responseCode` int(11) NULL DEFAULT 0 COMMENT '响应状态码',
+ `responseMsg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '响应消息',
+ `createTime` int(11) NULL DEFAULT 0 COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_user_id`(`userId`) USING BTREE,
+ INDEX `idx_user_name`(`userName`) USING BTREE,
+ INDEX `idx_action`(`action`) USING BTREE,
+ INDEX `idx_create_time`(`createTime`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 45 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户操作日志表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_user_portrait
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_user_portrait`;
+CREATE TABLE `ck_user_portrait` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `type` tinyint(2) NULL DEFAULT 0 COMMENT '类型 0浏览 1点击 2下单/购买 3注册 4互动',
+ `companyId` int(11) NULL DEFAULT 0,
+ `trafficPoolId` int(10) NULL DEFAULT NULL COMMENT '流量池用户id traffic_pool的主键',
+ `source` tinyint(2) NULL DEFAULT 0 COMMENT '来源 0本站 1老油条 2老坑爹',
+ `uniqueId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '来源网站唯一id',
+ `sourceData` json NULL COMMENT '来源网站数据',
+ `remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `count` int(10) NULL DEFAULT 1 COMMENT '统计次数(半小时内)',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 17718 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户画像' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_users
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_users`;
+CREATE TABLE `ck_users` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `account` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号',
+ `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `phone` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录手机号',
+ `passwordMd5` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
+ `passwordLocal` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '本地密码',
+ `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'https://img.icons8.com/color/512/circled-user-male-skin-type-7.png' COMMENT '头像',
+ `isAdmin` tinyint(3) NULL DEFAULT 0 COMMENT '是否管理身份 1->是 0->否',
+ `companyId` int(10) UNSIGNED NOT NULL COMMENT '账号所属项目id',
+ `typeId` tinyint(3) NOT NULL DEFAULT -1 COMMENT '类型:运营后台/操盘手 传1 、 门店传2',
+ `status` tinyint(3) NULL DEFAULT 0 COMMENT '1->可用,0->禁用',
+ `s2_accountId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'S2的用户账号id',
+ `balance` int(11) NULL DEFAULT 0 COMMENT '余额',
+ `tokens` int(11) NULL DEFAULT 0 COMMENT '算力余额',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '修改时间',
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1652 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_vendor_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_vendor_order`;
+CREATE TABLE `ck_vendor_order` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '订单ID',
+ `orderNo` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单编号',
+ `userId` int(10) UNSIGNED NOT NULL COMMENT '用户ID',
+ `packageId` int(10) UNSIGNED NOT NULL COMMENT '套餐ID',
+ `packageName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '套餐名称',
+ `totalAmount` decimal(10, 2) NOT NULL COMMENT '订单总额',
+ `payAmount` decimal(10, 2) NOT NULL COMMENT '支付金额',
+ `advancePayment` decimal(10, 2) NULL DEFAULT 0.00 COMMENT '预付款',
+ `status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态:0=待支付,1=已支付,2=已完成,3=已取消',
+ `payTime` int(11) NULL DEFAULT 0 COMMENT '支付时间',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `orderNo`(`orderNo`) USING BTREE,
+ INDEX `userId`(`userId`) USING BTREE,
+ INDEX `packageId`(`packageId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商订单表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_vendor_package
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_vendor_package`;
+CREATE TABLE `ck_vendor_package` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '套餐ID',
+ `userId` int(11) NULL DEFAULT NULL COMMENT '用户id',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '公司id',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '套餐名称',
+ `originalPrice` decimal(10, 2) NOT NULL COMMENT '原价',
+ `price` decimal(10, 2) NOT NULL COMMENT '售价',
+ `discount` decimal(4, 2) NULL DEFAULT 0.00 COMMENT '折扣',
+ `advancePayment` decimal(10, 2) NULL DEFAULT 0.00 COMMENT '预付款',
+ `tags` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '套餐描述',
+ `cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图片',
+ `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:0=下架,1=上架',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL COMMENT '更新时间',
+ `isDel` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商套餐表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_vendor_project
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_vendor_project`;
+CREATE TABLE `ck_vendor_project` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '项目ID',
+ `packageId` int(10) UNSIGNED NOT NULL COMMENT '套餐ID',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '项目名称',
+ `originalPrice` decimal(10, 2) NOT NULL COMMENT '原价',
+ `price` decimal(10, 2) NOT NULL COMMENT '售价',
+ `duration` int(11) NULL DEFAULT 0 COMMENT '项目时长(分钟)',
+ `image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '项目图片',
+ `detail` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '项目详情',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL COMMENT '更新时间',
+ `isDel` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `packageId`(`packageId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商套餐项目表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_account
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_account`;
+CREATE TABLE `ck_wechat_account` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `s2_wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '微信账号id',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信ID',
+ `alias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信号',
+ `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `pyInitial` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拼音首字母',
+ `quanPin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '全拼',
+ `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像URL',
+ `gender` tinyint(1) NULL DEFAULT 0 COMMENT '性别 0->保密;1->男;2->女',
+ `region` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区',
+ `signature` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '个性签名',
+ `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电话',
+ `country` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '国家',
+ `privince` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '省份',
+ `city` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '城市',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_wechatId`(`wechatId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3097959 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信账号表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_customer
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_customer`;
+CREATE TABLE `ck_wechat_customer` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
+ `wechatId` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信id',
+ `basic` json NULL COMMENT '保存基础信息',
+ `weight` json NULL COMMENT '保存权重信息',
+ `activity` json NULL COMMENT '保存账号活跃信息',
+ `friendShip` json NULL COMMENT '保存朋友关系信息',
+ `companyId` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '公司id',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_wechatId`(`wechatId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 153 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信客服信息' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_friendship
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_friendship`;
+CREATE TABLE `ck_wechat_friendship` (
+ `id` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '好友id',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信ID',
+ `tags` json NULL COMMENT '好友标签',
+ `memo` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '好友备注',
+ `ownerWechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所有者微信ID',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '公司ID',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ UNIQUE INDEX `uk_owner_wechat_account`(`ownerWechatId`, `wechatId`) USING BTREE,
+ INDEX `idx_wechat_id`(`wechatId`) USING BTREE,
+ INDEX `idx_owner_wechat_id`(`ownerWechatId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信好友表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_group
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_group`;
+CREATE TABLE `ck_wechat_group` (
+ `id` int(11) UNSIGNED NOT NULL COMMENT 'S2微信群id',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '微信账号ID',
+ `chatroomId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信群聊id',
+ `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群名称',
+ `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群头像',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '项目id',
+ `ownerWechatId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所有者微信ID',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群主(流量标识,可以是手机号、微信号)',
+ `createTime` int(11) UNSIGNED NULL DEFAULT NULL,
+ `updateTime` int(11) UNSIGNED NULL DEFAULT NULL,
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_owner_chatroomId`(`chatroomId`, `ownerWechatId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信群' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_group_member
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_group_member`;
+CREATE TABLE `ck_wechat_group_member` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群成员(流量标识,可以是手机号、微信号)',
+ `chatroomId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群真实id',
+ `customerIs` tinyint(3) NULL DEFAULT 0 COMMENT '是否客服',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '项目id',
+ `groupId` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '所属群ID',
+ `createTime` int(11) UNSIGNED NULL DEFAULT 0,
+ `deleteTime` int(11) UNSIGNED NULL DEFAULT 0,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_identifier_chatroomId_groupId`(`identifier`, `chatroomId`, `groupId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 549847 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信群成员' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_restricts
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_restricts`;
+CREATE TABLE `ck_wechat_restricts` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `taskId` int(11) NULL DEFAULT NULL COMMENT '任务id',
+ `level` tinyint(3) UNSIGNED NULL DEFAULT 1 COMMENT '风险类型 1 普通 2 警告 3 错误',
+ `reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '风险原因',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '记录更详细的风险信息',
+ `wechatId` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信id',
+ `companyId` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '项目id',
+ `restrictTime` int(11) NULL DEFAULT NULL COMMENT '限制日期',
+ `recoveryTime` int(11) NULL DEFAULT NULL COMMENT '恢复日期',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1302 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信风险受限记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_wechat_tag
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_wechat_tag`;
+CREATE TABLE `ck_wechat_tag` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+ `tags` json NULL COMMENT '标签JSON',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信ID',
+ `companyId` int(11) NULL DEFAULT NULL COMMENT '公司ID',
+ `createTime` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_wechatId`(`wechatId`) USING BTREE,
+ INDEX `idx_companyId`(`companyId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 123366 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信账号表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench`;
+CREATE TABLE `ck_workbench` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `userId` int(11) NOT NULL COMMENT '创建用户ID',
+ `companyId` int(11) NULL DEFAULT 0 COMMENT '公司id',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '工作台名称',
+ `type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '工作台类型:1=自动点赞,2=朋友圈同步,3=群消息推送,4=自动建群,5=流量分发,6=通讯录导入',
+ `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:0=禁用,1=启用',
+ `autoStart` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否自动启动:0=否,1=是',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL COMMENT '更新时间',
+ `isDel` tinyint(1) NULL DEFAULT 0,
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_user_id`(`userId`) USING BTREE,
+ INDEX `idx_type`(`type`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 275 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '工作台主表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_auto_like
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_auto_like`;
+CREATE TABLE `ck_workbench_auto_like` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `interval` int(11) NOT NULL DEFAULT 60 COMMENT '点赞间隔(秒)',
+ `maxLikes` int(11) NOT NULL DEFAULT 100 COMMENT '最大点赞数',
+ `startTime` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '00:00:00' COMMENT '开始时间',
+ `endTime` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '23:59:59' COMMENT '结束时间',
+ `contentTypes` json NULL COMMENT '内容类型',
+ `devices` json NULL COMMENT '设备列表,JSON格式:[{\"id\":1,\"name\":\"设备1\"},{\"id\":2,\"name\":\"设备2\"}]',
+ `friends` json NULL COMMENT '用户列表',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `updateTime` int(11) NOT NULL COMMENT '更新时间',
+ `targetGroups` json NULL COMMENT '目标用户组列表,JSON格式:[{\"id\":1,\"name\":\"用户组1\"},{\"id\":2,\"name\":\"用户组2\"}] 废除',
+ `tagOperator` tinyint(1) NULL DEFAULT 2 COMMENT '标签匹配规则 1:and 2:or 废除',
+ `friendMaxLikes` int(10) NULL DEFAULT NULL COMMENT '好友最大点赞数',
+ `friendTags` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '好友标签',
+ `enableFriendTags` tinyint(1) NULL DEFAULT 0 COMMENT '启用好友标签',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_workbench_id`(`workbenchId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 54 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自动点赞配置表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_auto_like_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_auto_like_item`;
+CREATE TABLE `ck_workbench_auto_like_item` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `deviceId` int(11) NULL DEFAULT 0 COMMENT '设备id',
+ `snsId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自动点赞id',
+ `wechatFriendId` int(11) NULL DEFAULT NULL COMMENT '好友id',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `momentsId` int(11) NULL DEFAULT NULL COMMENT '朋友圈id',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `workbenchId`(`workbenchId`) USING BTREE,
+ INDEX `wechatFriendId`(`wechatFriendId`) USING BTREE,
+ INDEX `wechatAccountId`(`wechatAccountId`) USING BTREE,
+ INDEX `momentsId`(`momentsId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4639 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '工作台-自动点赞记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_group_create
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_group_create`;
+CREATE TABLE `ck_workbench_group_create` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `workbenchId` int(11) NOT NULL COMMENT '计划ID',
+ `devices` json NULL COMMENT '目标设备/客服(JSON数组)',
+ `poolGroups` json NULL COMMENT '流量池JSON',
+ `wechatGroups` json NULL COMMENT '微信客服JSON',
+ `startTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开始时间',
+ `endTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '结束时间',
+ `groupSizeMin` int(10) NULL DEFAULT NULL COMMENT '群好友最小人数',
+ `groupSizeMax` int(10) NULL DEFAULT NULL COMMENT '群好友最大人数',
+ `maxGroupsPerDay` int(10) NULL DEFAULT NULL COMMENT '每日建群最大数量',
+ `groupNameTemplate` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群模板信息',
+ `groupDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群描述',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_group_create_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_group_create_item`;
+CREATE TABLE `ck_workbench_group_create_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `friendId` int(11) NULL DEFAULT NULL,
+ `wechatId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '微信id',
+ `groupId` int(10) NULL DEFAULT NULL COMMENT '群id',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 46 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_group_push
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_group_push`;
+CREATE TABLE `ck_workbench_group_push` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `pushType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '推送方式 0定时 1立即',
+ `targetType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '推送目标类型:1=群推送,2=好友推送',
+ `startTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '推送开始时间',
+ `endTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '推送结束时间',
+ `maxPerDay` int(11) NULL DEFAULT 0 COMMENT '每日推送条数',
+ `pushOrder` tinyint(1) NULL DEFAULT 1 COMMENT '推送顺序 1最早 2最新',
+ `isLoop` tinyint(1) NULL DEFAULT 0 COMMENT '是否循环推送 0否 1是',
+ `status` tinyint(1) NULL DEFAULT 1 COMMENT '是否启用 0否 1是',
+ `groups` json NULL COMMENT '推送微信群组(JSON)',
+ `friends` json NULL COMMENT '推送好友列表(JSON)',
+ `ownerWechatIds` json NULL COMMENT '所属微信id',
+ `contentLibraries` json NULL COMMENT '内容库(JSON)',
+ `friendIntervalMin` int(11) NOT NULL DEFAULT 10 COMMENT '好友间最小间隔时间(秒)',
+ `friendIntervalMax` int(11) NOT NULL DEFAULT 20 COMMENT '好友间最大间隔时间(秒)',
+ `messageIntervalMin` int(11) NOT NULL DEFAULT 1 COMMENT '消息间最小间隔时间(秒)',
+ `messageIntervalMax` int(11) NOT NULL DEFAULT 12 COMMENT '消息间最大间隔时间(秒)',
+ `isRandomTemplate` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否随机选择话术组(0=否,1=是)',
+ `postPushTags` json NOT NULL COMMENT '推送完成后打标签',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `socialMediaId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '京东导购媒体',
+ `promotionSiteId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '京东广告位',
+ `trafficPools` json NULL COMMENT '流量池',
+ `devices` json NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_workbench_id`(`workbenchId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群消息推送扩展表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_group_push_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_group_push_item`;
+CREATE TABLE `ck_workbench_group_push_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `targetType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '推送目标类型:1=群,2=好友',
+ `contentId` int(11) NULL DEFAULT 0 COMMENT '内容库is',
+ `groupId` int(10) NULL DEFAULT NULL COMMENT '群id',
+ `friendId` int(11) NULL DEFAULT NULL COMMENT '好友ID(当targetType=2时使用)',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `isLoop` tinyint(2) NULL DEFAULT 0 COMMENT '是否循环完成',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 302 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_import_contact
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_import_contact`;
+CREATE TABLE `ck_workbench_import_contact` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `devices` json NULL COMMENT '设备id',
+ `pools` json NULL COMMENT '流量池',
+ `num` int(11) NULL DEFAULT NULL COMMENT '分配数量',
+ `clearContact` tinyint(2) NULL DEFAULT 0 COMMENT '是否清除现有联系人',
+ `remarkType` tinyint(2) NOT NULL DEFAULT 0 COMMENT '备注类型 0不备注 1年月日 2月日 3自定义',
+ `remark` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `startTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开始时间',
+ `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '结束时间',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_import_contact_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_import_contact_item`;
+CREATE TABLE `ck_workbench_import_contact_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `deviceId` int(11) NULL DEFAULT NULL COMMENT '设备id',
+ `packageId` int(11) NULL DEFAULT 0 COMMENT '流量包id',
+ `poolId` int(11) NULL DEFAULT NULL COMMENT '流量id',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 140 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_moments_sync
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_moments_sync`;
+CREATE TABLE `ck_workbench_moments_sync` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `syncInterval` int(11) NOT NULL DEFAULT 1 COMMENT '同步间隔(小时)',
+ `syncCount` int(11) NOT NULL DEFAULT 5 COMMENT '每日同步数量',
+ `syncType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '同步类型:1=文本,2=图片,3=视频,4=链接',
+ `startTime` time(0) NULL DEFAULT '06:00:00' COMMENT '发布开始时间',
+ `endTime` time(0) NULL DEFAULT '23:59:00' COMMENT '发布结束时间',
+ `accountType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '账号类型:1=业务号,2=个人号',
+ `devices` json NOT NULL COMMENT '设备列表,JSON格式',
+ `contentLibraries` json NULL COMMENT '内容库ID列表,JSON格式',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_workbench_id`(`workbenchId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '朋友圈同步配置' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_moments_sync_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_moments_sync_item`;
+CREATE TABLE `ck_workbench_moments_sync_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '工作台ID',
+ `deviceId` int(11) NULL DEFAULT 0 COMMENT '设备id',
+ `contentId` int(10) NULL DEFAULT NULL COMMENT '内容库id',
+ `wechatAccountId` int(11) NULL DEFAULT NULL COMMENT '客服id',
+ `createTime` int(11) NOT NULL COMMENT '创建时间',
+ `isLoop` tinyint(2) NULL DEFAULT 0,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1650 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '朋友圈同步配置' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_traffic_config
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_traffic_config`;
+CREATE TABLE `ck_workbench_traffic_config` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL COMMENT '流量分发计划ID',
+ `distributeType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '分配方式 1均分 2优先级 3比例',
+ `maxPerDay` int(11) NOT NULL DEFAULT 0 COMMENT '每日最大分配量',
+ `timeType` tinyint(1) NOT NULL DEFAULT 1 COMMENT '时间限制 1全天 2自定义',
+ `startTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开始时间',
+ `endTime` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '结束时间',
+ `account` json NULL COMMENT '分发的账号',
+ `devices` json NULL COMMENT '目标设备/客服(JSON数组)',
+ `pools` json NULL COMMENT '流量池(JSON数组)',
+ `exp` int(10) NULL DEFAULT 30 COMMENT '有效期 单位天',
+ `createTime` int(11) NOT NULL,
+ `updateTime` int(11) NOT NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uniq_workbench`(`workbenchId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 31 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量分发计划扩展表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for ck_workbench_traffic_config_item
+-- ----------------------------
+DROP TABLE IF EXISTS `ck_workbench_traffic_config_item`;
+CREATE TABLE `ck_workbench_traffic_config_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `workbenchId` int(11) NOT NULL DEFAULT 0 COMMENT '工作台ID',
+ `deviceId` int(11) NULL DEFAULT 0 COMMENT '设备id',
+ `wechatFriendId` int(10) NULL DEFAULT NULL COMMENT '好友id',
+ `wechatAccountId` int(11) NULL DEFAULT 0 COMMENT '客服id',
+ `expTime` int(11) NULL DEFAULT 0 COMMENT '有效时间',
+ `exp` int(11) NULL DEFAULT 0 COMMENT '有效时间 天',
+ `isRecycle` tinyint(2) NULL DEFAULT 0 COMMENT '是否回收',
+ `recycleTime` int(11) NULL DEFAULT 0 COMMENT '回收时间',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `workbenchId`(`workbenchId`) USING BTREE,
+ INDEX `deviceId`(`deviceId`) USING BTREE,
+ INDEX `wechatFriendId`(`wechatFriendId`) USING BTREE,
+ INDEX `wechatAccountId`(`wechatAccountId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 49898 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流量分发计划扩展表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_allot_rule
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_allot_rule`;
+CREATE TABLE `s2_allot_rule` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '规则ID',
+ `departmentId` int(11) NULL DEFAULT 0 COMMENT '部门id',
+ `tenantId` int(11) NOT NULL DEFAULT 0 COMMENT '租户ID',
+ `allotType` tinyint(4) NOT NULL DEFAULT 0 COMMENT '分配类型',
+ `allotOnline` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否在线分配',
+ `kefuRange` tinyint(4) NOT NULL DEFAULT 0 COMMENT '客服范围',
+ `wechatRange` tinyint(4) NOT NULL DEFAULT 0 COMMENT '微信范围',
+ `kefuData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '客服数据JSON',
+ `wechatData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '微信ID列表JSON',
+ `labels` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '标签JSON',
+ `priorityStrategy` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '优先级策略JSON',
+ `sortIndex` int(11) NOT NULL DEFAULT 0 COMMENT '排序索引',
+ `creatorAccountId` int(11) NOT NULL DEFAULT 0 COMMENT '创建者账号ID',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `ruleName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '规则名称',
+ `isDel` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_tenant`(`tenantId`) USING BTREE,
+ INDEX `idx_sort`(`sortIndex`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2176 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '分配规则表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_call_recording
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_call_recording`;
+CREATE TABLE `s2_call_recording` (
+ `id` bigint(20) NOT NULL COMMENT '主键ID',
+ `tenantId` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户ID',
+ `deviceOwnerId` bigint(20) NOT NULL DEFAULT 0 COMMENT '设备所有者ID',
+ `userName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
+ `nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '昵称',
+ `realName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '真实姓名',
+ `deviceMemo` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '设备备注',
+ `fileName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件名',
+ `imei` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '设备IMEI',
+ `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '电话号码',
+ `isCallOut` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为呼出电话(0:呼入,1:呼出)',
+ `beginTime` int(11) NOT NULL DEFAULT 0 COMMENT '通话开始时间戳',
+ `endTime` int(11) NOT NULL DEFAULT 0 COMMENT '通话结束时间戳',
+ `audioUrl` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '录音文件URL',
+ `mp3AudioUrl` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'MP3录音文件URL',
+ `callBeginTime` int(11) NOT NULL DEFAULT 0 COMMENT '呼叫开始时间戳',
+ `callLogId` bigint(20) NOT NULL DEFAULT 0 COMMENT '通话日志ID',
+ `callType` int(11) NOT NULL DEFAULT 0 COMMENT '通话类型',
+ `duration` int(11) NOT NULL DEFAULT 0 COMMENT '通话时长(秒)',
+ `skipReason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '跳过原因',
+ `skipUpload` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否跳过上传',
+ `isDeleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否已删除',
+ `createTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间戳',
+ `lastUpdateTime` int(11) NOT NULL DEFAULT 0 COMMENT '最后更新时间戳',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_tenant_id`(`tenantId`) USING BTREE,
+ INDEX `idx_device_owner_id`(`deviceOwnerId`) USING BTREE,
+ INDEX `idx_user_name`(`userName`) USING BTREE,
+ INDEX `idx_phone`(`phone`) USING BTREE,
+ INDEX `idx_begin_time`(`beginTime`) USING BTREE,
+ INDEX `idx_end_time`(`endTime`) USING BTREE,
+ INDEX `idx_call_begin_time`(`callBeginTime`) USING BTREE,
+ INDEX `idx_imei`(`imei`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '通话记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_company_account
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_company_account`;
+CREATE TABLE `s2_company_account` (
+ `id` int(11) NULL DEFAULT NULL COMMENT 'id',
+ `tenantId` int(11) NULL DEFAULT NULL,
+ `userName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户名',
+ `realName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实姓名',
+ `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '昵称',
+ `memo` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注',
+ `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '头像',
+ `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '密钥',
+ `accountType` int(11) NULL DEFAULT 0 COMMENT '账户类型',
+ `departmentId` int(11) NULL DEFAULT 0 COMMENT '部门ID',
+ `departmentName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门名称',
+ `useGoogleSecretKey` tinyint(1) NULL DEFAULT 0 COMMENT '是否使用谷歌密钥',
+ `hasVerifyGoogleSecret` tinyint(1) NULL DEFAULT 0 COMMENT '是否验证谷歌密钥',
+ `passwordMd5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'MD5加密密码',
+ `passwordLocal` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '本地加密密码',
+ `lastLoginIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '最后登录IP',
+ `lastLoginTime` int(11) NULL DEFAULT 0 COMMENT '最后登录时间',
+ `createTime` int(11) NULL DEFAULT 0 COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT 0 COMMENT '更新时间',
+ `privilegeIds` json NULL COMMENT '权限',
+ `alive` tinyint(1) NULL DEFAULT NULL,
+ `creator` int(10) NULL DEFAULT NULL COMMENT '创建者',
+ `creatorRealName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建者真实姓名',
+ `creatorUserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建者用户名',
+ `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态 0正常 1禁用',
+ UNIQUE INDEX `idx_username`(`userName`) USING BTREE,
+ INDEX `idx_create_time`(`createTime`) USING BTREE,
+ INDEX `idx_update_time`(`updateTime`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '公司账户表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_department
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_department`;
+CREATE TABLE `s2_department` (
+ `id` int(11) NOT NULL,
+ `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `tenantId` int(11) NULL DEFAULT NULL,
+ `isTop` tinyint(1) NULL DEFAULT 0,
+ `level` int(10) NULL DEFAULT 0,
+ `parentId` int(10) NULL DEFAULT 0,
+ `privileges` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ `lastUpdateTime` int(11) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_device
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_device`;
+CREATE TABLE `s2_device` (
+ `id` int(11) NULL DEFAULT NULL COMMENT '设备真实ID',
+ `userName` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
+ `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `realName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '真实姓名',
+ `groupName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分组名称',
+ `wechatAccounts` json NULL COMMENT '微信账号列表JSON',
+ `alive` tinyint(1) NULL DEFAULT 0 COMMENT '是否在线',
+ `lastAliveTime` int(11) NULL DEFAULT NULL COMMENT '最后在线时间',
+ `tenantId` int(11) NULL DEFAULT NULL COMMENT '租户ID',
+ `groupId` int(11) NULL DEFAULT NULL COMMENT '分组ID',
+ `currentAccountId` int(11) NULL DEFAULT NULL COMMENT '当前账号ID',
+ `imei` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '设备IMEI',
+ `deviceImei` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备本地IMEI',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `isDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `deletedAndStop` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除并停止',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ `rooted` tinyint(1) NULL DEFAULT 0 COMMENT '是否root',
+ `xPosed` tinyint(1) NULL DEFAULT 0 COMMENT '是否安装xposed',
+ `brand` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '品牌',
+ `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '型号',
+ `operatingSystem` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作系统版本',
+ `softwareVersion` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '软件版本',
+ `extra` json NULL COMMENT '额外信息JSON',
+ `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
+ `lastUpdateTime` int(11) NULL DEFAULT NULL COMMENT '最后更新时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `taskConfig` json NULL COMMENT '自动化任务开关 \r\nautoLike:自动点赞\r\nmomentsSync:朋友圈同步\r\nautoCustomerDev:自动开发客户\r\ngroupMessageDeliver:群消息推送\r\nautoGroup:自动建群',
+ UNIQUE INDEX `uk_imei`(`imei`) USING BTREE,
+ INDEX `idx_tenant`(`tenantId`) USING BTREE,
+ INDEX `idx_group`(`groupId`) USING BTREE,
+ INDEX `idx_current_account`(`currentAccountId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_device_group
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_device_group`;
+CREATE TABLE `s2_device_group` (
+ `id` int(11) NOT NULL,
+ `tenantId` int(11) NOT NULL COMMENT '租户ID',
+ `groupName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '分组名称',
+ `groupMemo` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分组备注',
+ `count` int(11) NULL DEFAULT 0 COMMENT '设备数量',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ INDEX `idx_tenant`(`tenantId`) USING BTREE,
+ INDEX `idx_group_name`(`groupName`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '设备分组表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_friend_task
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_friend_task`;
+CREATE TABLE `s2_friend_task` (
+ `id` int(11) NOT NULL COMMENT '任务ID',
+ `tenantId` int(11) NULL DEFAULT 0 COMMENT '租户ID',
+ `operatorAccountId` int(11) NULL DEFAULT 0 COMMENT '操作账号ID',
+ `status` int(11) NULL DEFAULT 1 COMMENT '状态:0执行中,1执行成功,2执行失败',
+ `phone` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号/微信号',
+ `msgContent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '验证消息',
+ `wechatAccountId` int(11) NULL DEFAULT 0 COMMENT '微信账号ID',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间戳',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `extra` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '额外数据JSON',
+ `labels` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签,逗号分隔',
+ `from` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源',
+ `alias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信账号别名',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信ID',
+ `wechatAvatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信头像',
+ `wechatNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信昵称',
+ `accountNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号昵称',
+ `accountRealName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号真实姓名',
+ `accountUsername` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号用户名',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间戳',
+ UNIQUE INDEX `uk_task_id`(`id`) USING BTREE,
+ INDEX `idx_tenant_id`(`tenantId`) USING BTREE,
+ INDEX `idx_operator_account_id`(`operatorAccountId`) USING BTREE,
+ INDEX `idx_wechat_account_id`(`wechatAccountId`) USING BTREE,
+ INDEX `idx_status`(`status`) USING BTREE,
+ INDEX `idx_phone`(`phone`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '添加好友任务记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_moments_item
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_moments_item`;
+CREATE TABLE `s2_moments_item` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `task_id` int(11) NOT NULL COMMENT '朋友圈任务ID',
+ `temp_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '临时ID',
+ `wechat_account_id` int(11) NULL DEFAULT NULL COMMENT '微信账号ID',
+ `execute_count` int(11) NULL DEFAULT 0 COMMENT '执行次数',
+ `executed` tinyint(1) NULL DEFAULT 0 COMMENT '是否已执行',
+ `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态',
+ `extra` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '额外信息',
+ `execute_time` int(11) NULL DEFAULT NULL COMMENT '执行时间',
+ `finished_time` int(11) NULL DEFAULT NULL COMMENT '完成时间',
+ `labels` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '标签',
+ `alt_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '替代列表',
+ `comments` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '评论',
+ `moment_content_type` tinyint(1) NULL DEFAULT 0 COMMENT '朋友圈内容类型',
+ `text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文本内容',
+ `pic_url_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '图片URL列表',
+ `video_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '视频URL',
+ `link` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '链接信息',
+ `is_use_location` tinyint(1) NULL DEFAULT 0 COMMENT '是否使用位置',
+ `lat` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '纬度',
+ `lng` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '经度',
+ `poi_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '位置名称',
+ `poi_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '位置地址',
+ `video_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '视频编号',
+ `created_at` int(11) NULL DEFAULT NULL COMMENT '记录创建时间',
+ `updated_at` int(11) NULL DEFAULT NULL COMMENT '记录更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `idx_task_temp`(`task_id`, `temp_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 184 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '朋友圈任务项表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_moments_task
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_moments_task`;
+CREATE TABLE `s2_moments_task` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `task_id` int(11) NOT NULL COMMENT '朋友圈任务ID',
+ `tenant_id` int(11) NULL DEFAULT NULL COMMENT '租户ID',
+ `operator_account_id` int(11) NULL DEFAULT NULL COMMENT '操作人账号ID',
+ `account_username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号用户名',
+ `account_nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号昵称',
+ `account_real_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号真实姓名',
+ `public_mode` tinyint(1) NULL DEFAULT 0 COMMENT '发布模式',
+ `moment_content_type` tinyint(1) NULL DEFAULT 1 COMMENT '朋友圈内容类型:1纯文本,2图片,3视频,4链接',
+ `text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文本内容',
+ `pic_url_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '图片URL列表',
+ `video_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '视频URL',
+ `link` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '链接信息',
+ `job_status` tinyint(1) NULL DEFAULT 0 COMMENT '任务状态',
+ `job_origin_status` tinyint(1) NULL DEFAULT 0 COMMENT '任务原始状态',
+ `job_group` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务组',
+ `job_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务名称',
+ `begin_time` int(11) NULL DEFAULT NULL COMMENT '开始时间',
+ `end_time` int(11) NULL DEFAULT NULL COMMENT '结束时间',
+ `timing_time` int(11) NULL DEFAULT NULL COMMENT '定时发布时间',
+ `create_time` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `immediately` tinyint(1) NULL DEFAULT 1 COMMENT '是否立即发布',
+ `created_at` int(11) NULL DEFAULT NULL COMMENT '记录创建时间',
+ `updated_at` int(11) NULL DEFAULT NULL COMMENT '记录更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `idx_task_id`(`task_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 88 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '朋友圈任务表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_reply
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_reply`;
+CREATE TABLE `s2_reply` (
+ `id` int(11) NOT NULL,
+ `tenantId` int(255) NULL DEFAULT NULL,
+ `groupId` int(11) NULL DEFAULT NULL,
+ `accountId` int(11) NULL DEFAULT NULL,
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `msgType` tinyint(2) NULL DEFAULT NULL,
+ `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ `lastUpdateTime` int(11) NULL DEFAULT NULL,
+ `sortIndex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '快捷回复' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_reply_group
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_reply_group`;
+CREATE TABLE `s2_reply_group` (
+ `id` int(11) NOT NULL,
+ `groupName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `sortIndex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `parentId` int(11) NULL DEFAULT NULL,
+ `replyType` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `replys` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `departmentId` int(11) NULL DEFAULT 2130,
+ `accountId` int(11) NULL DEFAULT 5150,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '快捷回复分组' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_account
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_account`;
+CREATE TABLE `s2_wechat_account` (
+ `id` int(11) NOT NULL COMMENT '微信账号ID',
+ `wechatId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信ID',
+ `deviceAccountId` int(11) NULL DEFAULT 0 COMMENT '设备账号ID',
+ `imei` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'IMEI',
+ `deviceMemo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备备注',
+ `accountUserName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号用户名',
+ `accountRealName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号真实姓名',
+ `accountNickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号昵称',
+ `keFuAlive` tinyint(1) NULL DEFAULT 0 COMMENT '客服是否在线',
+ `deviceAlive` tinyint(1) NULL DEFAULT 0 COMMENT '设备是否在线',
+ `wechatAlive` tinyint(1) NULL DEFAULT 0 COMMENT '微信是否在线',
+ `yesterdayMsgCount` int(11) NULL DEFAULT 0 COMMENT '昨日消息数',
+ `sevenDayMsgCount` int(11) NULL DEFAULT 0 COMMENT '7天消息数',
+ `thirtyDayMsgCount` int(11) NULL DEFAULT 0 COMMENT '30天消息数',
+ `totalFriend` int(11) NULL DEFAULT 0 COMMENT '总好友数',
+ `maleFriend` int(11) NULL DEFAULT 0 COMMENT '男性好友数',
+ `unknowFriend` int(11) NULL DEFAULT NULL COMMENT '未知好友数',
+ `femaleFriend` int(11) NULL DEFAULT 0 COMMENT '女性好友数',
+ `wechatGroupName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信群组名称',
+ `tenantId` int(11) NULL DEFAULT NULL COMMENT '租户ID',
+ `nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `alias` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '别名',
+ `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',
+ `gender` tinyint(1) NULL DEFAULT 0 COMMENT '性别',
+ `region` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区',
+ `signature` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '签名',
+ `bindQQ` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定QQ',
+ `bindEmail` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定邮箱',
+ `bindMobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定手机',
+ `currentDeviceId` int(11) NULL DEFAULT 0 COMMENT '当前设备ID',
+ `isDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ `groupId` int(11) NULL DEFAULT 0 COMMENT '分组ID',
+ `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `wechatVersion` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信版本',
+ `labels` json NULL COMMENT '标签',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `status` tinyint(3) NULL DEFAULT 1 COMMENT '状态值',
+ INDEX `idx_wechat_id`(`wechatId`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信账号表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_chatroom
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_chatroom`;
+CREATE TABLE `s2_wechat_chatroom` (
+ `id` int(11) NOT NULL,
+ `wechatAccountId` int(11) NOT NULL COMMENT '微信账号ID',
+ `wechatAccountAlias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信账号别名',
+ `wechatAccountWechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信账号微信ID',
+ `wechatAccountAvatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信账号头像',
+ `wechatAccountNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '微信账号昵称',
+ `chatroomId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊ID',
+ `hasMe` tinyint(1) NULL DEFAULT 0 COMMENT '是否包含自己',
+ `chatroomOwnerNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群主昵称',
+ `chatroomOwnerAvatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群主头像',
+ `conRemark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群聊名称',
+ `pyInitial` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拼音首字母',
+ `quanPin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '全拼',
+ `chatroomAvatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群头像',
+ `isDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `accountId` int(11) NULL DEFAULT 0 COMMENT '账号ID',
+ `accountUserName` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号用户名',
+ `accountRealName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号真实姓名',
+ `accountNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号昵称',
+ `groupId` int(11) NULL DEFAULT 0 COMMENT '分组ID',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ UNIQUE INDEX `uk_chatroom_account`(`chatroomId`, `wechatAccountId`) USING BTREE,
+ INDEX `wechatAccountId`(`wechatAccountId`) USING BTREE,
+ INDEX `chatroomId`(`chatroomId`) USING BTREE,
+ INDEX `wechatAccountWechatId`(`wechatAccountWechatId`) USING BTREE,
+ INDEX `idx_account_deleted`(`accountId`, `isDeleted`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信群表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_chatroom_member
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_chatroom_member`;
+CREATE TABLE `s2_wechat_chatroom_member` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `chatroomId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊ID',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信ID',
+ `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',
+ `conRemark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `alias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '别名',
+ `friendType` tinyint(11) NULL DEFAULT 0 COMMENT '好友类型',
+ `createTime` int(10) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(10) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_chatroom_wechat`(`chatroomId`, `wechatId`) USING BTREE,
+ INDEX `chatroomId`(`chatroomId`) USING BTREE,
+ INDEX `wechatId`(`wechatId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 495043 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信群成员表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_friend
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_friend`;
+CREATE TABLE `s2_wechat_friend` (
+ `id` int(11) NULL DEFAULT NULL COMMENT '好友id',
+ `wechatAccountId` int(11) NOT NULL COMMENT '所有者微信账号ID',
+ `alias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '好友微信号',
+ `wechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '好友微信ID',
+ `conRemark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注名',
+ `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+ `pyInitial` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拼音首字母',
+ `quanPin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '全拼',
+ `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像URL',
+ `gender` tinyint(1) NULL DEFAULT 0 COMMENT '性别',
+ `region` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区',
+ `addFrom` int(11) NULL DEFAULT NULL COMMENT '添加来源',
+ `labels` json NULL COMMENT '标签JSON',
+ `siteLabels` json NULL COMMENT '站内标签JSON',
+ `signature` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '个性签名',
+ `isDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
+ `isPassed` tinyint(1) NULL DEFAULT 1 COMMENT '是否通过',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ `accountId` int(11) NULL DEFAULT 0 COMMENT '账号ID',
+ `extendFields` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展字段JSON',
+ `accountUserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号用户名',
+ `accountRealName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号真实姓名',
+ `accountNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号昵称',
+ `ownerAlias` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所有者别名',
+ `ownerWechatId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所有者微信ID',
+ `ownerNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所有者昵称',
+ `ownerAvatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所有者头像',
+ `phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电话',
+ `thirdParty` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '第三方数据JSON',
+ `groupId` int(11) NULL DEFAULT 0 COMMENT '分组ID',
+ `passTime` int(11) NULL DEFAULT NULL COMMENT '通过时间',
+ `additionalPicture` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '附加图片',
+ `desc` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述',
+ `country` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '国家',
+ `privince` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '省份',
+ `city` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '城市',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `updateTime` int(11) NULL DEFAULT NULL COMMENT '更新时间',
+ `R` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ `F` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ `M` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0',
+ UNIQUE INDEX `uk_owner_wechat_account`(`ownerWechatId`, `wechatId`, `wechatAccountId`) USING BTREE,
+ INDEX `idx_wechat_account_id`(`wechatAccountId`) USING BTREE,
+ INDEX `idx_wechat_id`(`wechatId`) USING BTREE,
+ INDEX `idx_owner_wechat_id`(`ownerWechatId`) USING BTREE,
+ INDEX `idx_id`(`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信好友表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_group
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_group`;
+CREATE TABLE `s2_wechat_group` (
+ `id` int(11) NOT NULL,
+ `tenantId` int(11) NULL DEFAULT NULL,
+ `groupName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `groupMemo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `groupType` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `sortIndex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `groupOwnerType` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `departmentId` int(11) NULL DEFAULT NULL,
+ `accountId` int(11) NULL DEFAULT NULL,
+ `createTime` int(11) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_message
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_message`;
+CREATE TABLE `s2_wechat_message` (
+ `id` bigint(20) NOT NULL COMMENT '消息ID',
+ `type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '消息类型 1好友 2群',
+ `wechatFriendId` bigint(20) NULL DEFAULT NULL COMMENT '微信好友ID',
+ `wechatChatroomId` bigint(20) NOT NULL COMMENT '微信群聊ID',
+ `senderNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送者昵称',
+ `senderWechatId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送者微信ID',
+ `senderIsAdmin` tinyint(1) NULL DEFAULT 0 COMMENT '发送者是否管理员',
+ `senderIsDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '发送者是否已删除',
+ `senderChatroomNickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送者群昵称',
+ `senderWechatAccountId` bigint(20) NULL DEFAULT NULL COMMENT '发送者微信账号ID',
+ `wechatAccountId` bigint(20) NULL DEFAULT NULL COMMENT '微信账号ID',
+ `tenantId` bigint(20) NULL DEFAULT NULL COMMENT '租户ID',
+ `accountId` bigint(20) NULL DEFAULT NULL COMMENT '账号ID',
+ `synergyAccountId` bigint(20) NULL DEFAULT 0 COMMENT '协同账号ID',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容',
+ `originalContent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容(原版)',
+ `msgType` int(11) NULL DEFAULT NULL COMMENT '消息类型 1 文字 3图片 47动态图片 34语言 43视频 42名片 40/20链接 49文件 419430449转账 436207665红包',
+ `msgSubType` int(11) NULL DEFAULT 0 COMMENT '消息子类型',
+ `msgSvrId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息服务器ID',
+ `isSend` tinyint(1) NULL DEFAULT 1 COMMENT '是否发送',
+ `createTime` int(11) NULL DEFAULT NULL COMMENT '创建时间',
+ `isDeleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否已删除',
+ `deleteTime` int(11) NULL DEFAULT NULL COMMENT '删除时间',
+ `sendStatus` int(11) NULL DEFAULT 0 COMMENT '发送状态',
+ `wechatTime` int(11) NULL DEFAULT NULL COMMENT '微信时间',
+ `origin` int(11) NULL DEFAULT 0 COMMENT '来源',
+ `msgId` bigint(20) NULL DEFAULT NULL COMMENT '消息ID',
+ `recallId` tinyint(1) NULL DEFAULT 0 COMMENT '撤回ID',
+ `isRead` tinyint(1) NULL DEFAULT 0 COMMENT '是否读取',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_wechatChatroomId`(`wechatChatroomId`) USING BTREE,
+ INDEX `idx_wechatAccountId`(`wechatAccountId`) USING BTREE,
+ INDEX `idx_msgSvrId`(`msgSvrId`) USING BTREE,
+ INDEX `idx_type`(`type`) USING BTREE,
+ INDEX `idx_type_wechatTime`(`type`, `wechatTime`, `id`) USING BTREE,
+ INDEX `idx_friend_time`(`wechatFriendId`, `wechatTime`, `id`) USING BTREE,
+ INDEX `idx_chatroom_time`(`wechatChatroomId`, `wechatTime`, `id`) USING BTREE,
+ INDEX `idx_account_type`(`accountId`, `type`, `wechatTime`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信群聊消息记录表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for s2_wechat_moments
+-- ----------------------------
+DROP TABLE IF EXISTS `s2_wechat_moments`;
+CREATE TABLE `s2_wechat_moments` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `wechatAccountId` int(11) NOT NULL COMMENT '微信账号ID',
+ `wechatFriendId` int(11) NULL DEFAULT NULL COMMENT '微信好友ID',
+ `snsId` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '朋友圈消息ID',
+ `commentList` json NULL COMMENT '评论列表JSON',
+ `createTime` bigint(20) NULL DEFAULT 0 COMMENT '创建时间戳',
+ `likeList` json NULL COMMENT '点赞列表JSON',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '朋友圈内容',
+ `lat` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '纬度',
+ `lng` decimal(10, 6) NULL DEFAULT 0.000000 COMMENT '经度',
+ `location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '位置信息',
+ `picSize` int(11) NULL DEFAULT 0 COMMENT '图片大小',
+ `resUrls` json NULL COMMENT '资源URL列表',
+ `userName` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户名',
+ `type` int(11) NULL DEFAULT 0 COMMENT '朋友圈类型',
+ `create_time` int(11) NULL DEFAULT NULL COMMENT '数据创建时间',
+ `update_time` int(11) NULL DEFAULT NULL COMMENT '数据更新时间',
+ `coverImage` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `urls` json NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `idx_sns_account`(`snsId`, `wechatAccountId`) USING BTREE,
+ INDEX `idx_account_friend`(`wechatAccountId`, `wechatFriendId`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 39669 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信朋友圈数据表' ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/Server/微信健康分规则v2.md b/Server/微信健康分规则v2.md
new file mode 100644
index 00000000..90c63f07
--- /dev/null
+++ b/Server/微信健康分规则v2.md
@@ -0,0 +1,58 @@
+# 微信健康分规则 v2
+
+## 一、定义
+
+当客户收到手机设备后,登录了微信号,我们将对其微信号进行健康分的评估。
+
+**健康分 = 基础分 + 动态分**
+
+健康分只与系统中的"每日自动添加好友次数"这个功能相关联。\
+通过健康分体系来定义一个微信号每日**最佳、最稳定的添加次数**。\
+后期还可将健康分作为标签属性,用于快速筛选微信号。
+
+**公式:每日最大加人次数 = 健康分 × 0.2**
+
+## 二、基础分
+
+基础分为 **60--100 分**。
+
+由 `60 + 40(基础加成分)` 四个维度参数组成,每个参数具有不同权重。
+
+### 基础分组成
+
+ 类型 权重 分数
+ ------------ ------ ------
+ 基础信息 0.2 10
+ 好友数量 0.3 30
+ 默认基础分 --- 60
+
+### 1. 基础信息(权重 0.2,满分 10)
+
+ 类型 权重 分数
+ -------------- ------ ------
+ 已修改微信号 1 10
+
+### 2. 好友数量(权重 0.3,满分 30)
+
+ 好友数量范围 权重 分数
+ -------------- ------ ------
+ 0--50 0.1 3
+ 51--500 0.2 6
+ 501--3000 0.3 8
+ 3001 以上 0.4 12
+
+## 三、动态分规则
+
+### 扣分规则
+
+ 场景 扣分 处罚
+ ---------- ------ --------------
+ 首次频繁 15 暂停 24 小时
+ 再次频繁 25 暂停 24 小时
+ 封号 60 暂停 72 小时
+
+### 加分规则
+
+ 场景 加分
+ --------------------- ------
+ 连续 3 天不触发频繁 5/日
From 719ed989964afebaa9f77a24189f18f4fd525f6f Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Thu, 20 Nov 2025 16:11:27 +0800
Subject: [PATCH 2/7] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/composer.json | 3 +-
.../extend/Eison/Utils/Helper/ArrHelper.php | 125 ++++++++++++++++++
2 files changed, 127 insertions(+), 1 deletion(-)
create mode 100644 Server/extend/Eison/Utils/Helper/ArrHelper.php
diff --git a/Server/composer.json b/Server/composer.json
index ea979146..5bb827df 100644
--- a/Server/composer.json
+++ b/Server/composer.json
@@ -48,7 +48,8 @@
},
"autoload": {
"psr-4": {
- "app\\": "application"
+ "app\\": "application",
+ "Eison\\": "extend/Eison"
},
"files": [
"application/common.php"
diff --git a/Server/extend/Eison/Utils/Helper/ArrHelper.php b/Server/extend/Eison/Utils/Helper/ArrHelper.php
new file mode 100644
index 00000000..a659c82d
--- /dev/null
+++ b/Server/extend/Eison/Utils/Helper/ArrHelper.php
@@ -0,0 +1,125 @@
+
Date: Thu, 20 Nov 2025 16:18:16 +0800
Subject: [PATCH 3/7] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/composer.json | 137 ++++++++++++++++++++++---------------------
1 file changed, 69 insertions(+), 68 deletions(-)
diff --git a/Server/composer.json b/Server/composer.json
index 5bb827df..26ba92b7 100644
--- a/Server/composer.json
+++ b/Server/composer.json
@@ -1,71 +1,72 @@
{
- "name": "topthink/think",
- "description": "the new thinkphp framework",
- "type": "project",
- "keywords": [
- "framework",
- "thinkphp",
- "ORM"
+ "name": "topthink/think",
+ "description": "the new thinkphp framework",
+ "type": "project",
+ "keywords": [
+ "framework",
+ "thinkphp",
+ "ORM"
+ ],
+ "homepage": "http://thinkphp.cn/",
+ "license": "Apache-2.0",
+ "authors": [
+ {
+ "name": "liu21st",
+ "email": "liu21st@gmail.com"
+ },
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.6.0",
+ "topthink/framework": "5.1.41",
+ "topthink/think-installer": "2.*",
+ "topthink/think-captcha": "^2.0",
+ "topthink/think-helper": "^3.0",
+ "topthink/think-image": "^1.0",
+ "topthink/think-queue": "^2.0",
+ "topthink/think-worker": "^2.0",
+ "textalk/websocket": "^1.5",
+ "aliyuncs/oss-sdk-php": "^2.6",
+ "monolog/monolog": "^1.27",
+ "guzzlehttp/guzzle": "^6.5",
+ "overtrue/wechat": "~4.6",
+ "endroid/qr-code": "^3.9",
+ "phpoffice/phpspreadsheet": "^1.29",
+ "workerman/workerman": "^3.5",
+ "workerman/gateway-worker": "^3.0",
+ "hashids/hashids": "^2.0",
+ "khanamiryan/qrcode-detector-decoder": "^1.0",
+ "lizhichao/word": "^2.0",
+ "adbario/php-dot-notation": "^2.2"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^3.4|^4.4",
+ "topthink/think-migration": "^2.0",
+ "phpunit/phpunit": "^5.0|^6.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "app\\": "application",
+ "Eison\\": "extend/Eison"
+ },
+ "files": [
+ "application/common.php"
],
- "homepage": "http://thinkphp.cn/",
- "license": "Apache-2.0",
- "authors": [
- {
- "name": "liu21st",
- "email": "liu21st@gmail.com"
- },
- {
- "name": "yunwuxin",
- "email": "448901948@qq.com"
- }
- ],
- "require": {
- "php": ">=5.6.0",
- "topthink/framework": "5.1.*",
- "topthink/think-installer": "~1.0",
- "topthink/think-captcha": "^2.0",
- "topthink/think-helper": "^3.0",
- "topthink/think-image": "^1.0",
- "topthink/think-queue": "^2.0",
- "topthink/think-worker": "^2.0",
- "textalk/websocket": "^1.2",
- "aliyuncs/oss-sdk-php": "^2.3",
- "monolog/monolog": "^1.24",
- "guzzlehttp/guzzle": "^6.3",
- "overtrue/wechat": "~4.0",
- "endroid/qr-code": "^3.5",
- "phpoffice/phpspreadsheet": "^1.8",
- "workerman/workerman": "^3.5",
- "workerman/gateway-worker": "^3.0",
- "hashids/hashids": "^2.0",
- "khanamiryan/qrcode-detector-decoder": "^1.0",
- "lizhichao/word": "^2.0",
- "adbario/php-dot-notation": "^2.2"
- },
- "require-dev": {
- "symfony/var-dumper": "^3.4",
- "topthink/think-migration": "^2.0"
- },
- "autoload": {
- "psr-4": {
- "app\\": "application",
- "Eison\\": "extend/Eison"
- },
- "files": [
- "application/common.php"
- ],
- "classmap": []
- },
- "extra": {
- "think-path": "thinkphp"
- },
- "config": {
- "preferred-install": "dist",
- "allow-plugins": {
- "topthink/think-installer": true,
- "easywechat-composer/easywechat-composer": true
- }
- },
- "minimum-stability": "dev",
- "prefer-stable": true
+ "classmap": []
+ },
+ "extra": {
+ "think-path": "thinkphp"
+ },
+ "config": {
+ "preferred-install": "dist",
+ "allow-plugins": {
+ "topthink/think-installer": true,
+ "easywechat-composer/easywechat-composer": true
+ }
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
}
From 3faee0d8be1ac6034d5bc69978727b53b7f1ec8a Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Fri, 21 Nov 2025 14:38:29 +0800
Subject: [PATCH 4/7] =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E5=81=A5=E5=BA=B7?=
=?UTF-8?q?=E5=88=86=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/application/command.php | 3 +
.../CalculateWechatAccountScoreCommand.php | 311 +++++++++
.../CheckAndFixWechatAccountCommand.php | 159 -----
.../UpdateWechatAccountScoreCommand.php | 168 +++++
.../common/model/WechatAccountScore.php | 44 ++
.../WechatAccountHealthScoreService.php | 649 ++++++++++++++----
Server/crontab_tasks.md | 8 +
.../Adapters/ChuKeBao/Adapter.php | 85 ++-
8 files changed, 1129 insertions(+), 298 deletions(-)
create mode 100644 Server/application/command/CalculateWechatAccountScoreCommand.php
delete mode 100644 Server/application/command/CheckAndFixWechatAccountCommand.php
create mode 100644 Server/application/command/UpdateWechatAccountScoreCommand.php
create mode 100644 Server/application/common/model/WechatAccountScore.php
diff --git a/Server/application/command.php b/Server/application/command.php
index f1d4d72b..b5c4d0e5 100644
--- a/Server/application/command.php
+++ b/Server/application/command.php
@@ -39,4 +39,7 @@ return [
'workbench:groupCreate' => 'app\command\WorkbenchGroupCreateCommand', // 工作台群创建任务
'workbench:import-contact' => 'app\command\WorkbenchImportContactCommand', // 工作台通讯录导入任务
'kf:notice' => 'app\command\KfNoticeCommand', // 客服端消息通知
+
+ 'wechat:calculate-score' => 'app\command\CalculateWechatAccountScoreCommand', // 统一计算微信账号健康分
+ 'wechat:update-score' => 'app\command\UpdateWechatAccountScoreCommand', // 更新微信账号评分记录
];
diff --git a/Server/application/command/CalculateWechatAccountScoreCommand.php b/Server/application/command/CalculateWechatAccountScoreCommand.php
new file mode 100644
index 00000000..dbc7ec5b
--- /dev/null
+++ b/Server/application/command/CalculateWechatAccountScoreCommand.php
@@ -0,0 +1,311 @@
+setName('wechat:calculate-score')
+ ->setDescription('统一计算微信账号健康分(包含初始化、更新评分记录、批量计算)');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $output->writeln("==========================================");
+ $output->writeln("开始统一计算微信账号健康分...");
+ $output->writeln("==========================================");
+
+ $startTime = time();
+ $service = new WechatAccountHealthScoreService();
+
+ try {
+ // 步骤1: 初始化未计算基础分的账号
+ $output->writeln("\n[步骤1] 初始化未计算基础分的账号...");
+ $initStats = $this->initUncalculatedAccounts($service, $output);
+ $output->writeln("初始化完成:成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条");
+
+ // 步骤2: 更新评分记录(根据wechatId和alias不一致情况)
+ $output->writeln("\n[步骤2] 更新评分记录(根据wechatId和alias不一致情况)...");
+ $updateStats = $this->updateScoreRecords($service, $output);
+ $output->writeln("更新完成:处理了 {$updateStats['total']} 条记录");
+
+ // 步骤3: 批量更新健康分(只更新动态分,不重新计算基础分)
+ $output->writeln("\n[步骤3] 批量更新健康分(只更新动态分)...");
+ $batchStats = $this->batchUpdateHealthScore($service, $output);
+ $output->writeln("批量更新完成:成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+
+ // 统计信息
+ $endTime = time();
+ $duration = $endTime - $startTime;
+
+ $output->writeln("\n==========================================");
+ $output->writeln("任务完成!");
+ $output->writeln("==========================================");
+ $output->writeln("总耗时: {$duration} 秒");
+ $output->writeln("初始化: 成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条");
+ $output->writeln("更新评分记录: {$updateStats['total']} 条");
+ $output->writeln("批量更新: 成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+
+ if (!empty($initStats['errors'])) {
+ $output->writeln("\n初始化错误详情:");
+ foreach (array_slice($initStats['errors'], 0, 10) as $error) {
+ $output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ }
+ if (count($initStats['errors']) > 10) {
+ $output->writeln(" ... 还有 " . (count($initStats['errors']) - 10) . " 个错误");
+ }
+ }
+
+ if (!empty($batchStats['errors'])) {
+ $output->writeln("\n批量更新错误详情:");
+ foreach (array_slice($batchStats['errors'], 0, 10) as $error) {
+ $output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ }
+ if (count($batchStats['errors']) > 10) {
+ $output->writeln(" ... 还有 " . (count($batchStats['errors']) - 10) . " 个错误");
+ }
+ }
+
+ } catch (\Exception $e) {
+ $output->writeln("\n错误: " . $e->getMessage());
+ $output->writeln($e->getTraceAsString());
+ }
+ }
+
+ /**
+ * 初始化未计算基础分的账号
+ *
+ * @param WechatAccountHealthScoreService $service
+ * @param Output $output
+ * @return array
+ */
+ private function initUncalculatedAccounts($service, $output)
+ {
+ $stats = [
+ 'total' => 0,
+ 'success' => 0,
+ 'failed' => 0,
+ 'errors' => []
+ ];
+
+ // 获取所有未计算基础分的账号
+ $accounts = Db::table('s2_wechat_account')
+ ->alias('a')
+ ->leftJoin(['s2_wechat_account_score' => 's'], 's.accountId = a.id')
+ ->where('a.isDeleted', 0)
+ ->where(function($query) {
+ $query->whereNull('s.id')
+ ->whereOr('s.baseScoreCalculated', 0);
+ })
+ ->field('a.id, a.wechatId')
+ ->select();
+
+ $stats['total'] = count($accounts);
+
+ if ($stats['total'] == 0) {
+ $output->writeln("没有需要初始化的账号");
+ return $stats;
+ }
+
+ $output->writeln("找到 {$stats['total']} 个需要初始化的账号");
+
+ $batchSize = 100;
+ $batches = array_chunk($accounts, $batchSize);
+
+ foreach ($batches as $batchIndex => $batch) {
+ foreach ($batch as $account) {
+ try {
+ $service->calculateAndUpdate($account['id']);
+ $stats['success']++;
+
+ if ($stats['success'] % 100 == 0) {
+ $output->write(".");
+ }
+ } catch (\Exception $e) {
+ $stats['failed']++;
+ $stats['errors'][] = [
+ 'accountId' => $account['id'],
+ 'error' => $e->getMessage()
+ ];
+ }
+ }
+
+ if (($batchIndex + 1) % 10 == 0) {
+ $output->writeln(" 已处理 " . ($batchIndex + 1) * $batchSize . " 条");
+ }
+ }
+
+ return $stats;
+ }
+
+ /**
+ * 更新评分记录(根据wechatId和alias不一致情况)
+ *
+ * @param WechatAccountHealthScoreService $service
+ * @param Output $output
+ * @return array
+ */
+ private function updateScoreRecords($service, $output)
+ {
+ $stats = ['total' => 0];
+
+ // 查找wechatId和alias不一致的账号
+ $inconsistentAccounts = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId != alias')
+ ->field('id, wechatId, alias')
+ ->select();
+
+ // 查找wechatId和alias一致的账号
+ $consistentAccounts = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId = alias')
+ ->field('id, wechatId, alias')
+ ->select();
+
+ $allAccounts = array_merge($inconsistentAccounts, $consistentAccounts);
+ $stats['total'] = count($allAccounts);
+
+ if ($stats['total'] == 0) {
+ $output->writeln("没有需要更新的账号");
+ return $stats;
+ }
+
+ $output->writeln("找到 {$stats['total']} 个需要更新的账号(不一致: " . count($inconsistentAccounts) . ",一致: " . count($consistentAccounts) . ")");
+
+ $updatedCount = 0;
+
+ foreach ($allAccounts as $account) {
+ $isModifiedAlias = in_array($account['id'], array_column($inconsistentAccounts, 'id'));
+ $this->updateScoreRecord($account['id'], $isModifiedAlias, $service);
+ $updatedCount++;
+
+ if ($updatedCount % 100 == 0) {
+ $output->write(".");
+ }
+ }
+
+ if ($updatedCount > 0 && $updatedCount % 100 == 0) {
+ $output->writeln("");
+ }
+
+ return $stats;
+ }
+
+ /**
+ * 批量更新健康分(只更新动态分)
+ *
+ * @param WechatAccountHealthScoreService $service
+ * @param Output $output
+ * @return array
+ */
+ private function batchUpdateHealthScore($service, $output)
+ {
+ // 获取所有已计算基础分的账号
+ $accountIds = Db::table('s2_wechat_account_score')
+ ->where('baseScoreCalculated', 1)
+ ->column('accountId');
+
+ $total = count($accountIds);
+
+ if ($total == 0) {
+ $output->writeln("没有需要更新的账号");
+ return ['success' => 0, 'failed' => 0, 'errors' => []];
+ }
+
+ $output->writeln("找到 {$total} 个需要更新动态分的账号");
+
+ $stats = $service->batchCalculateAndUpdate($accountIds, 100, false);
+
+ return $stats;
+ }
+
+ /**
+ * 更新评分记录
+ *
+ * @param int $accountId 账号ID
+ * @param bool $isModifiedAlias 是否已修改微信号
+ * @param WechatAccountHealthScoreService $service 评分服务
+ */
+ private function updateScoreRecord($accountId, $isModifiedAlias, $service)
+ {
+ // 获取账号数据
+ $accountData = Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->find();
+
+ if (empty($accountData)) {
+ return;
+ }
+
+ // 确保评分记录存在
+ $scoreRecord = Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find();
+
+ if (empty($scoreRecord)) {
+ // 如果记录不存在,创建并计算基础分
+ $service->calculateAndUpdate($accountId);
+ $scoreRecord = Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find();
+ }
+
+ if (empty($scoreRecord)) {
+ return;
+ }
+
+ // 更新isModifiedAlias字段
+ $updateData = [
+ 'isModifiedAlias' => $isModifiedAlias ? 1 : 0,
+ 'updateTime' => time()
+ ];
+
+ // 如果基础分已计算,需要更新基础信息分和基础分
+ if ($scoreRecord['baseScoreCalculated']) {
+ $oldBaseInfoScore = $scoreRecord['baseInfoScore'] ?? 0;
+ $newBaseInfoScore = $isModifiedAlias ? 10 : 0; // 已修改微信号得10分
+
+ if ($oldBaseInfoScore != $newBaseInfoScore) {
+ $oldBaseScore = $scoreRecord['baseScore'] ?? 60;
+ $newBaseScore = $oldBaseScore - $oldBaseInfoScore + $newBaseInfoScore;
+
+ $updateData['baseInfoScore'] = $newBaseInfoScore;
+ $updateData['baseScore'] = $newBaseScore;
+
+ // 重新计算健康分
+ $dynamicScore = $scoreRecord['dynamicScore'] ?? 0;
+ $healthScore = $newBaseScore + $dynamicScore;
+ $healthScore = max(0, min(100, $healthScore));
+ $updateData['healthScore'] = $healthScore;
+ $updateData['maxAddFriendPerDay'] = (int)floor($healthScore * 0.2);
+ }
+ } else {
+ // 基础分未计算,只更新标记和基础信息分
+ $updateData['baseInfoScore'] = $isModifiedAlias ? 10 : 0;
+ }
+
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->update($updateData);
+ }
+}
+
diff --git a/Server/application/command/CheckAndFixWechatAccountCommand.php b/Server/application/command/CheckAndFixWechatAccountCommand.php
deleted file mode 100644
index e498f77b..00000000
--- a/Server/application/command/CheckAndFixWechatAccountCommand.php
+++ /dev/null
@@ -1,159 +0,0 @@
-setName('wechat:check-and-fix')
- ->setDescription('检测和修复s2_wechat_account表中wechatId和alias不一致的问题,并更新健康分');
- }
-
- protected function execute(Input $input, Output $output)
- {
- $output->writeln("开始检测和修复s2_wechat_account表...");
-
- try {
- // 1. 检测wechatId和alias不一致的记录
- $output->writeln("步骤1: 检测wechatId和alias不一致的记录...");
- $inconsistentAccounts = $this->findInconsistentAccounts();
- $output->writeln("发现 " . count($inconsistentAccounts) . " 条不一致记录");
-
- if (empty($inconsistentAccounts)) {
- $output->writeln("没有发现不一致的记录,任务完成!");
- return;
- }
-
- // 2. 修复不一致的记录
- $output->writeln("步骤2: 修复不一致的记录...");
- $fixedCount = $this->fixInconsistentAccounts($inconsistentAccounts);
- $output->writeln("已修复 " . $fixedCount . " 条记录");
-
- // 3. 更新isModifiedAlias字段
- $output->writeln("步骤3: 更新isModifiedAlias字段...");
- $updatedCount = $this->updateModifiedAliasFlag();
- $output->writeln("已更新 " . $updatedCount . " 条记录的isModifiedAlias字段");
-
- // 4. 重新计算健康分
- $output->writeln("步骤4: 重新计算健康分...");
- $healthScoreService = new WechatAccountHealthScoreService();
- $accountIds = array_column($inconsistentAccounts, 'id');
- $stats = $healthScoreService->batchCalculateAndUpdate($accountIds, 100);
- $output->writeln("健康分计算完成:成功 " . $stats['success'] . " 条,失败 " . $stats['failed'] . " 条");
-
- if (!empty($stats['errors'])) {
- $output->writeln("错误详情:");
- foreach ($stats['errors'] as $error) {
- $output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
- }
- }
-
- $output->writeln("任务完成!");
-
- } catch (\Exception $e) {
- $output->writeln("错误: " . $e->getMessage());
- $output->writeln($e->getTraceAsString());
- }
- }
-
- /**
- * 查找wechatId和alias不一致的记录
- *
- * @return array
- */
- private function findInconsistentAccounts()
- {
- // 查找wechatId和alias不一致的记录
- // 条件:wechatId不为空,alias不为空,且wechatId != alias
- $accounts = Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->where('wechatId', '<>', '')
- ->where('alias', '<>', '')
- ->whereRaw('wechatId != alias')
- ->field('id, wechatId, alias, nickname, isModifiedAlias')
- ->select();
-
- return $accounts ?: [];
- }
-
- /**
- * 修复不一致的记录
- * 策略:从s2_wechat_friend表中查找最新的alias值来更新
- *
- * @param array $accounts 不一致的账号列表
- * @return int 修复数量
- */
- private function fixInconsistentAccounts($accounts)
- {
- $fixedCount = 0;
-
- foreach ($accounts as $account) {
- $wechatId = $account['wechatId'];
-
- // 从s2_wechat_friend表中查找最新的alias值
- $latestAlias = Db::table('s2_wechat_friend')
- ->where('wechatId', $wechatId)
- ->where('alias', '<>', '')
- ->order('updateTime', 'desc')
- ->value('alias');
-
- // 如果找到了最新的alias,则更新
- if (!empty($latestAlias) && $latestAlias !== $account['alias']) {
- Db::table('s2_wechat_account')
- ->where('id', $account['id'])
- ->update([
- 'alias' => $latestAlias,
- 'updateTime' => time()
- ]);
- $fixedCount++;
- }
- }
-
- return $fixedCount;
- }
-
- /**
- * 更新isModifiedAlias字段
- * 如果wechatId和alias不一致,则标记为已修改
- *
- * @return int 更新数量
- */
- private function updateModifiedAliasFlag()
- {
- // 更新isModifiedAlias字段:wechatId != alias 的记录标记为1
- $updatedCount = Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->where('wechatId', '<>', '')
- ->where('alias', '<>', '')
- ->whereRaw('wechatId != alias')
- ->update([
- 'isModifiedAlias' => 1,
- 'updateTime' => time()
- ]);
-
- // 更新isModifiedAlias字段:wechatId == alias 的记录标记为0
- Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->where('wechatId', '<>', '')
- ->where('alias', '<>', '')
- ->whereRaw('wechatId = alias')
- ->update([
- 'isModifiedAlias' => 0,
- 'updateTime' => time()
- ]);
-
- return $updatedCount;
- }
-}
-
diff --git a/Server/application/command/UpdateWechatAccountScoreCommand.php b/Server/application/command/UpdateWechatAccountScoreCommand.php
new file mode 100644
index 00000000..13ded8d4
--- /dev/null
+++ b/Server/application/command/UpdateWechatAccountScoreCommand.php
@@ -0,0 +1,168 @@
+setName('wechat:update-score')
+ ->setDescription('更新微信账号评分记录,根据wechatId和alias不一致情况更新isModifiedAlias字段(仅用于评分)');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $output->writeln("开始更新微信账号评分记录...");
+
+ try {
+ // 1. 查找所有需要更新的账号
+ $output->writeln("步骤1: 查找需要更新的账号...");
+
+ // 查找wechatId和alias不一致的账号
+ $inconsistentAccounts = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId != alias')
+ ->field('id, wechatId, alias')
+ ->select();
+
+ // 查找wechatId和alias一致的账号
+ $consistentAccounts = Db::table('s2_wechat_account')
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '')
+ ->whereRaw('wechatId = alias')
+ ->field('id, wechatId, alias')
+ ->select();
+
+ $output->writeln("发现 " . count($inconsistentAccounts) . " 条不一致记录(已修改微信号)");
+ $output->writeln("发现 " . count($consistentAccounts) . " 条一致记录(未修改微信号)");
+
+ // 2. 更新评分记录表中的isModifiedAlias字段
+ $output->writeln("步骤2: 更新评分记录表...");
+ $updatedCount = 0;
+ $healthScoreService = new WechatAccountHealthScoreService();
+
+ // 更新不一致的记录
+ foreach ($inconsistentAccounts as $account) {
+ $this->updateScoreRecord($account['id'], true, $healthScoreService);
+ $updatedCount++;
+ }
+
+ // 更新一致的记录
+ foreach ($consistentAccounts as $account) {
+ $this->updateScoreRecord($account['id'], false, $healthScoreService);
+ $updatedCount++;
+ }
+
+ $output->writeln("已更新 " . $updatedCount . " 条评分记录");
+
+ // 3. 重新计算健康分(只更新基础信息分,不重新计算基础分)
+ $output->writeln("步骤3: 重新计算健康分...");
+ $allAccountIds = array_merge(
+ array_column($inconsistentAccounts, 'id'),
+ array_column($consistentAccounts, 'id')
+ );
+
+ if (!empty($allAccountIds)) {
+ $stats = $healthScoreService->batchCalculateAndUpdate($allAccountIds, 100, false);
+ $output->writeln("健康分计算完成:成功 " . $stats['success'] . " 条,失败 " . $stats['failed'] . " 条");
+
+ if (!empty($stats['errors'])) {
+ $output->writeln("错误详情:");
+ foreach ($stats['errors'] as $error) {
+ $output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ }
+ }
+ }
+
+ $output->writeln("任务完成!");
+
+ } catch (\Exception $e) {
+ $output->writeln("错误: " . $e->getMessage());
+ $output->writeln($e->getTraceAsString());
+ }
+ }
+
+ /**
+ * 更新评分记录
+ *
+ * @param int $accountId 账号ID
+ * @param bool $isModifiedAlias 是否已修改微信号
+ * @param WechatAccountHealthScoreService $service 评分服务
+ */
+ private function updateScoreRecord($accountId, $isModifiedAlias, $service)
+ {
+ // 获取或创建评分记录
+ $accountData = Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->find();
+
+ if (empty($accountData)) {
+ return;
+ }
+
+ // 确保评分记录存在
+ $scoreRecord = Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find();
+
+ if (empty($scoreRecord)) {
+ // 如果记录不存在,创建并计算基础分
+ $service->calculateAndUpdate($accountId);
+ $scoreRecord = Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find();
+ }
+
+ if (empty($scoreRecord)) {
+ return;
+ }
+
+ // 更新isModifiedAlias字段
+ $updateData = [
+ 'isModifiedAlias' => $isModifiedAlias ? 1 : 0,
+ 'updateTime' => time()
+ ];
+
+ // 如果基础分已计算,需要更新基础信息分和基础分
+ if ($scoreRecord['baseScoreCalculated']) {
+ $oldBaseInfoScore = $scoreRecord['baseInfoScore'] ?? 0;
+ $newBaseInfoScore = $isModifiedAlias ? 10 : 0; // 已修改微信号得10分
+
+ if ($oldBaseInfoScore != $newBaseInfoScore) {
+ $oldBaseScore = $scoreRecord['baseScore'] ?? 60;
+ $newBaseScore = $oldBaseScore - $oldBaseInfoScore + $newBaseInfoScore;
+
+ $updateData['baseInfoScore'] = $newBaseInfoScore;
+ $updateData['baseScore'] = $newBaseScore;
+
+ // 重新计算健康分
+ $dynamicScore = $scoreRecord['dynamicScore'] ?? 0;
+ $healthScore = $newBaseScore + $dynamicScore;
+ $healthScore = max(0, min(100, $healthScore));
+ $updateData['healthScore'] = $healthScore;
+ $updateData['maxAddFriendPerDay'] = (int)floor($healthScore * 0.2);
+ }
+ } else {
+ // 基础分未计算,只更新标记和基础信息分
+ $updateData['baseInfoScore'] = $isModifiedAlias ? 10 : 0;
+ }
+
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->update($updateData);
+ }
+}
+
diff --git a/Server/application/common/model/WechatAccountScore.php b/Server/application/common/model/WechatAccountScore.php
new file mode 100644
index 00000000..43170f78
--- /dev/null
+++ b/Server/application/common/model/WechatAccountScore.php
@@ -0,0 +1,44 @@
+ 'integer',
+ 'baseScore' => 'integer',
+ 'baseScoreCalculated' => 'integer',
+ 'baseInfoScore' => 'integer',
+ 'friendCountScore' => 'integer',
+ 'friendCount' => 'integer',
+ 'dynamicScore' => 'integer',
+ 'frequentCount' => 'integer',
+ 'frequentPenalty' => 'integer',
+ 'consecutiveNoFrequentDays' => 'integer',
+ 'noFrequentBonus' => 'integer',
+ 'banPenalty' => 'integer',
+ 'healthScore' => 'integer',
+ 'maxAddFriendPerDay' => 'integer',
+ 'isModifiedAlias' => 'integer',
+ 'isBanned' => 'integer',
+ 'lastFrequentTime' => 'integer',
+ 'lastNoFrequentTime' => 'integer',
+ 'baseScoreCalcTime' => 'integer',
+ 'createTime' => 'integer',
+ 'updateTime' => 'integer',
+ ];
+}
+
diff --git a/Server/application/common/service/WechatAccountHealthScoreService.php b/Server/application/common/service/WechatAccountHealthScoreService.php
index cda09cfd..02a89a9b 100644
--- a/Server/application/common/service/WechatAccountHealthScoreService.php
+++ b/Server/application/common/service/WechatAccountHealthScoreService.php
@@ -6,9 +6,15 @@ use think\Db;
use think\Exception;
/**
- * 微信账号健康分评分服务
+ * 微信账号健康分评分服务(优化版)
* 基于《微信健康分规则v2.md》实现
*
+ * 优化点:
+ * 1. 基础分只计算一次
+ * 2. 各个评分维度独立存储
+ * 3. 使用独立的评分记录表
+ * 4. 好友数量评分特殊处理(避免同步问题)
+ *
* 健康分 = 基础分 + 动态分
* 基础分:60-100分(默认60分 + 基础信息10分 + 好友数量30分)
* 动态分:扣分和加分规则
@@ -18,13 +24,14 @@ class WechatAccountHealthScoreService
// 默认基础分
const DEFAULT_BASE_SCORE = 60;
- // 基础信息权重和分数
- const BASE_INFO_WEIGHT = 0.2;
+ // 基础信息分数
const BASE_INFO_SCORE = 10;
- // 好友数量权重和分数
- const FRIEND_COUNT_WEIGHT = 0.3;
- const FRIEND_COUNT_MAX_SCORE = 30;
+ // 好友数量分数区间
+ const FRIEND_COUNT_SCORE_0_50 = 3;
+ const FRIEND_COUNT_SCORE_51_500 = 6;
+ const FRIEND_COUNT_SCORE_501_3000 = 8;
+ const FRIEND_COUNT_SCORE_3001_PLUS = 12;
// 动态分扣分规则
const PENALTY_FIRST_FREQUENT = -15; // 首次频繁扣15分
@@ -39,9 +46,10 @@ class WechatAccountHealthScoreService
*
* @param int $accountId 账号ID(s2_wechat_account表的id)
* @param array $accountData 账号数据(可选,如果不传则从数据库查询)
+ * @param bool $forceRecalculateBase 是否强制重新计算基础分(默认false)
* @return array 返回评分结果
*/
- public function calculateAndUpdate($accountId, $accountData = null)
+ public function calculateAndUpdate($accountId, $accountData = null, $forceRecalculateBase = false)
{
try {
// 获取账号数据
@@ -55,39 +63,68 @@ class WechatAccountHealthScoreService
throw new Exception("账号不存在:{$accountId}");
}
- // 计算基础分
- $baseScore = $this->calculateBaseScore($accountData);
+ $wechatId = $accountData['wechatId'] ?? '';
+ if (empty($wechatId)) {
+ throw new Exception("账号wechatId为空:{$accountId}");
+ }
- // 计算动态分
- $dynamicScore = $this->calculateDynamicScore($accountData);
+ // 获取或创建评分记录
+ $scoreRecord = $this->getOrCreateScoreRecord($accountId, $wechatId);
+
+ // 计算基础分(只计算一次,除非强制重新计算)
+ if (!$scoreRecord['baseScoreCalculated'] || $forceRecalculateBase) {
+ $baseScoreData = $this->calculateBaseScore($accountData, $scoreRecord);
+ $this->updateBaseScore($accountId, $baseScoreData);
+ // 重新获取记录以获取最新数据
+ $scoreRecord = $this->getScoreRecord($accountId);
+ }
+
+ // 计算动态分(每次都要重新计算)
+ $dynamicScoreData = $this->calculateDynamicScore($accountData, $scoreRecord);
// 计算总分
+ $baseScore = $scoreRecord['baseScore'];
+ $dynamicScore = $dynamicScoreData['total'];
$healthScore = $baseScore + $dynamicScore;
// 确保健康分在合理范围内(0-100)
$healthScore = max(0, min(100, $healthScore));
- // 更新数据库
+ // 计算每日最大加人次数
+ $maxAddFriendPerDay = $this->getMaxAddFriendPerDay($healthScore);
+
+ // 更新评分记录
$updateData = [
- 'healthScore' => $healthScore,
- 'baseScore' => $baseScore,
'dynamicScore' => $dynamicScore,
- 'scoreUpdateTime' => time()
+ 'frequentPenalty' => $dynamicScoreData['frequentPenalty'],
+ 'noFrequentBonus' => $dynamicScoreData['noFrequentBonus'],
+ 'banPenalty' => $dynamicScoreData['banPenalty'],
+ 'lastFrequentTime' => $dynamicScoreData['lastFrequentTime'],
+ 'frequentCount' => $dynamicScoreData['frequentCount'],
+ 'lastNoFrequentTime' => $dynamicScoreData['lastNoFrequentTime'],
+ 'consecutiveNoFrequentDays' => $dynamicScoreData['consecutiveNoFrequentDays'],
+ 'isBanned' => $dynamicScoreData['isBanned'],
+ 'healthScore' => $healthScore,
+ 'maxAddFriendPerDay' => $maxAddFriendPerDay,
+ 'updateTime' => time()
];
- Db::table('s2_wechat_account')
- ->where('id', $accountId)
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
->update($updateData);
return [
'accountId' => $accountId,
- 'wechatId' => $accountData['wechatId'] ?? '',
+ 'wechatId' => $wechatId,
'healthScore' => $healthScore,
'baseScore' => $baseScore,
+ 'baseInfoScore' => $scoreRecord['baseInfoScore'],
+ 'friendCountScore' => $scoreRecord['friendCountScore'],
'dynamicScore' => $dynamicScore,
- 'baseInfoScore' => $this->getBaseInfoScore($accountData),
- 'friendCountScore' => $this->getFriendCountScore($accountData['totalFriend'] ?? 0),
- 'maxAddFriendPerDay' => $this->getMaxAddFriendPerDay($healthScore)
+ 'frequentPenalty' => $dynamicScoreData['frequentPenalty'],
+ 'noFrequentBonus' => $dynamicScoreData['noFrequentBonus'],
+ 'banPenalty' => $dynamicScoreData['banPenalty'],
+ 'maxAddFriendPerDay' => $maxAddFriendPerDay
];
} catch (Exception $e) {
@@ -96,24 +133,119 @@ class WechatAccountHealthScoreService
}
/**
- * 计算基础分
- * 基础分 = 默认60分 + 基础信息分(10分) + 好友数量分(30分)
+ * 获取或创建评分记录
+ *
+ * @param int $accountId 账号ID
+ * @param string $wechatId 微信ID
+ * @return array 评分记录
+ */
+ private function getOrCreateScoreRecord($accountId, $wechatId)
+ {
+ $record = Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find();
+
+ if (empty($record)) {
+ // 创建新记录
+ $data = [
+ 'accountId' => $accountId,
+ 'wechatId' => $wechatId,
+ 'baseScore' => 0,
+ 'baseScoreCalculated' => 0,
+ 'baseInfoScore' => 0,
+ 'friendCountScore' => 0,
+ 'dynamicScore' => 0,
+ 'frequentCount' => 0,
+ 'consecutiveNoFrequentDays' => 0,
+ 'healthScore' => 0,
+ 'maxAddFriendPerDay' => 0,
+ 'createTime' => time(),
+ 'updateTime' => time()
+ ];
+
+ Db::table('s2_wechat_account_score')->insert($data);
+
+ return $data;
+ }
+
+ return $record;
+ }
+
+ /**
+ * 获取评分记录
+ *
+ * @param int $accountId 账号ID
+ * @return array
+ */
+ private function getScoreRecord($accountId)
+ {
+ return Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->find() ?: [];
+ }
+
+ /**
+ * 计算基础分(只计算一次)
+ * 基础分 = 默认60分 + 基础信息分(10分) + 好友数量分(3-12分)
*
* @param array $accountData 账号数据
- * @return int 基础分
+ * @param array $scoreRecord 现有评分记录
+ * @return array 基础分数据
*/
- private function calculateBaseScore($accountData)
+ private function calculateBaseScore($accountData, $scoreRecord = [])
{
$baseScore = self::DEFAULT_BASE_SCORE;
// 基础信息分(已修改微信号得10分)
- $baseScore += $this->getBaseInfoScore($accountData);
+ $baseInfoScore = $this->getBaseInfoScore($accountData);
+ $baseScore += $baseInfoScore;
- // 好友数量分(最高30分)
- $totalFriend = $accountData['totalFriend'] ?? 0;
- $baseScore += $this->getFriendCountScore($totalFriend);
+ // 好友数量分(特殊处理:使用快照值,避免同步问题)
+ $friendCountScore = 0;
+ $friendCount = 0;
+ $friendCountSource = 'manual';
- return $baseScore;
+ // 如果已有评分记录且好友数量分已计算,使用历史值
+ if (!empty($scoreRecord['friendCountScore']) && $scoreRecord['friendCountScore'] > 0) {
+ $friendCountScore = $scoreRecord['friendCountScore'];
+ $friendCount = $scoreRecord['friendCount'] ?? 0;
+ $friendCountSource = $scoreRecord['friendCountSource'] ?? 'manual';
+ } else {
+ // 首次计算:使用当前好友数量,但标记为手动计算
+ $totalFriend = $accountData['totalFriend'] ?? 0;
+ $friendCountScore = $this->getFriendCountScore($totalFriend);
+ $friendCount = $totalFriend;
+ $friendCountSource = 'manual';
+ }
+
+ $baseScore += $friendCountScore;
+
+ // 检查是否已修改微信号
+ $isModifiedAlias = $this->checkIsModifiedAlias($accountData);
+
+ return [
+ 'baseScore' => $baseScore,
+ 'baseInfoScore' => $baseInfoScore,
+ 'friendCountScore' => $friendCountScore,
+ 'friendCount' => $friendCount,
+ 'friendCountSource' => $friendCountSource,
+ 'isModifiedAlias' => $isModifiedAlias ? 1 : 0,
+ 'baseScoreCalculated' => 1,
+ 'baseScoreCalcTime' => time()
+ ];
+ }
+
+ /**
+ * 更新基础分
+ *
+ * @param int $accountId 账号ID
+ * @param array $baseScoreData 基础分数据
+ */
+ private function updateBaseScore($accountId, $baseScoreData)
+ {
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->update($baseScoreData);
}
/**
@@ -125,23 +257,36 @@ class WechatAccountHealthScoreService
*/
private function getBaseInfoScore($accountData)
{
- // 检查是否已修改微信号
- // 如果isModifiedAlias字段为1,或者wechatId和alias不一致,则认为已修改
- $isModifiedAlias = isset($accountData['isModifiedAlias']) ? (int)$accountData['isModifiedAlias'] : 0;
- $wechatId = trim($accountData['wechatId'] ?? '');
- $alias = trim($accountData['alias'] ?? '');
-
- // 如果字段标记为已修改,或者wechatId和alias不一致,则得分
- if ($isModifiedAlias == 1 || (!empty($wechatId) && !empty($alias) && $wechatId !== $alias)) {
+ if ($this->checkIsModifiedAlias($accountData)) {
return self::BASE_INFO_SCORE;
}
-
return 0;
}
+ /**
+ * 检查是否已修改微信号
+ * 判断标准:wechatId和alias不一致且都不为空,则认为已修改微信号
+ * 注意:这里只用于评分,不修复数据
+ *
+ * @param array $accountData 账号数据
+ * @return bool
+ */
+ private function checkIsModifiedAlias($accountData)
+ {
+ $wechatId = trim($accountData['wechatId'] ?? '');
+ $alias = trim($accountData['alias'] ?? '');
+
+ // 如果wechatId和alias不一致且都不为空,则认为已修改微信号(用于评分)
+ if (!empty($wechatId) && !empty($alias) && $wechatId !== $alias) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* 获取好友数量分
- * 根据好友数量区间得分(最高30分)
+ * 根据好友数量区间得分(最高12分)
*
* @param int $totalFriend 总好友数
* @return int 好友数量分
@@ -149,92 +294,292 @@ class WechatAccountHealthScoreService
private function getFriendCountScore($totalFriend)
{
if ($totalFriend <= 50) {
- return 3; // 0-50: 3分
+ return self::FRIEND_COUNT_SCORE_0_50;
} elseif ($totalFriend <= 500) {
- return 6; // 51-500: 6分
+ return self::FRIEND_COUNT_SCORE_51_500;
} elseif ($totalFriend <= 3000) {
- return 8; // 501-3000: 8分
+ return self::FRIEND_COUNT_SCORE_501_3000;
} else {
- return 12; // 3001以上: 12分
+ return self::FRIEND_COUNT_SCORE_3001_PLUS;
}
}
+ /**
+ * 手动更新好友数量分(用于处理同步问题)
+ *
+ * @param int $accountId 账号ID
+ * @param int $friendCount 好友数量
+ * @param string $source 来源(manual=手动,sync=同步)
+ * @return bool
+ */
+ public function updateFriendCountScore($accountId, $friendCount, $source = 'manual')
+ {
+ $scoreRecord = $this->getScoreRecord($accountId);
+
+ // 如果基础分已计算,不允许修改好友数量分(除非是手动更新)
+ if (!empty($scoreRecord['baseScoreCalculated']) && $source === 'sync') {
+ // 同步数据不允许修改已计算的基础分
+ return false;
+ }
+
+ $friendCountScore = $this->getFriendCountScore($friendCount);
+
+ // 重新计算基础分
+ $oldBaseScore = $scoreRecord['baseScore'] ?? self::DEFAULT_BASE_SCORE;
+ $oldFriendCountScore = $scoreRecord['friendCountScore'] ?? 0;
+ $baseInfoScore = $scoreRecord['baseInfoScore'] ?? 0;
+
+ $newBaseScore = self::DEFAULT_BASE_SCORE + $baseInfoScore + $friendCountScore;
+
+ $updateData = [
+ 'friendCountScore' => $friendCountScore,
+ 'friendCount' => $friendCount,
+ 'friendCountSource' => $source,
+ 'baseScore' => $newBaseScore,
+ 'updateTime' => time()
+ ];
+
+ // 如果基础分已计算,需要更新总分
+ if (!empty($scoreRecord['baseScoreCalculated'])) {
+ $dynamicScore = $scoreRecord['dynamicScore'] ?? 0;
+ $healthScore = $newBaseScore + $dynamicScore;
+ $healthScore = max(0, min(100, $healthScore));
+ $updateData['healthScore'] = $healthScore;
+ $updateData['maxAddFriendPerDay'] = $this->getMaxAddFriendPerDay($healthScore);
+ }
+
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
+ ->update($updateData);
+
+ return true;
+ }
+
/**
* 计算动态分
* 动态分 = 扣分 + 加分
*
* @param array $accountData 账号数据
- * @return int 动态分
+ * @param array $scoreRecord 现有评分记录
+ * @return array 动态分数据
*/
- private function calculateDynamicScore($accountData)
+ private function calculateDynamicScore($accountData, $scoreRecord)
{
- $dynamicScore = 0;
+ $result = [
+ 'total' => 0,
+ 'frequentPenalty' => 0,
+ 'noFrequentBonus' => 0,
+ 'banPenalty' => 0,
+ 'lastFrequentTime' => null,
+ 'frequentCount' => 0,
+ 'lastNoFrequentTime' => null,
+ 'consecutiveNoFrequentDays' => 0,
+ 'isBanned' => 0
+ ];
- // 处理扣分
- $dynamicScore += $this->calculatePenalty($accountData);
+ $accountId = $accountData['id'] ?? 0;
+ $wechatId = $accountData['wechatId'] ?? '';
- // 处理加分
- $dynamicScore += $this->calculateBonus($accountData);
+ if (empty($accountId) || empty($wechatId)) {
+ return $result;
+ }
- return $dynamicScore;
+ // 继承现有数据
+ if (!empty($scoreRecord)) {
+ $result['lastFrequentTime'] = $scoreRecord['lastFrequentTime'] ?? null;
+ $result['frequentCount'] = $scoreRecord['frequentCount'] ?? 0;
+ $result['lastNoFrequentTime'] = $scoreRecord['lastNoFrequentTime'] ?? null;
+ $result['consecutiveNoFrequentDays'] = $scoreRecord['consecutiveNoFrequentDays'] ?? 0;
+ $result['frequentPenalty'] = $scoreRecord['frequentPenalty'] ?? 0;
+ $result['noFrequentBonus'] = $scoreRecord['noFrequentBonus'] ?? 0;
+ $result['banPenalty'] = $scoreRecord['banPenalty'] ?? 0;
+ }
+
+ // 1. 检查频繁记录(从s2_friend_task表查询,只统计近30天)
+ $frequentData = $this->checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord);
+ $result['lastFrequentTime'] = $frequentData['lastFrequentTime'] ?? null;
+ $result['frequentCount'] = $frequentData['frequentCount'] ?? 0;
+ $result['frequentPenalty'] = $frequentData['frequentPenalty'] ?? 0;
+
+ // 2. 检查封号记录(从s2_wechat_message表查询)
+ $banData = $this->checkBannedFromMessage($accountId, $wechatId);
+ if (!empty($banData)) {
+ $result['isBanned'] = $banData['isBanned'];
+ $result['banPenalty'] = $banData['banPenalty'];
+ }
+
+ // 3. 计算不频繁加分(基于近30天的频繁记录,反向参考频繁规则)
+ $noFrequentData = $this->calculateNoFrequentBonus($accountId, $wechatId, $frequentData);
+ $result['noFrequentBonus'] = $noFrequentData['bonus'] ?? 0;
+ $result['consecutiveNoFrequentDays'] = $noFrequentData['consecutiveDays'] ?? 0;
+ $result['lastNoFrequentTime'] = $noFrequentData['lastNoFrequentTime'] ?? null;
+
+ // 计算总分
+ $result['total'] = $result['frequentPenalty'] + $result['noFrequentBonus'] + $result['banPenalty'];
+
+ return $result;
}
/**
- * 计算扣分
- * 首次频繁:-15分
- * 再次频繁:-25分
- * 封号:-60分
+ * 从s2_friend_task表检查频繁记录
+ * extra字段包含"操作过于频繁"即需要扣分
+ * 只统计近30天的数据
*
- * @param array $accountData 账号数据
- * @return int 扣分数
+ * @param int $accountId 账号ID
+ * @param string $wechatId 微信ID
+ * @param array $scoreRecord 现有评分记录
+ * @return array|null
*/
- private function calculatePenalty($accountData)
+ private function checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord)
{
+ // 计算30天前的时间戳
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+
+ // 查询包含"操作过于频繁"的记录(只统计近30天)
+ // extra字段可能是文本或JSON格式,使用LIKE查询
+ $frequentTasks = Db::table('s2_friend_task')
+ ->where('wechatAccountId', $accountId)
+ ->where('createTime', '>=', $thirtyDaysAgo)
+ ->where(function($query) use ($wechatId) {
+ if (!empty($wechatId)) {
+ $query->where('wechatId', $wechatId);
+ }
+ })
+ ->where(function($query) {
+ // 检查extra字段是否包含"操作过于频繁"(可能是文本或JSON)
+ $query->where('extra', 'like', '%操作过于频繁%')
+ ->whereOr('extra', 'like', '%"操作过于频繁"%');
+ })
+ ->order('createTime', 'desc')
+ ->field('id, createTime, extra')
+ ->select();
+
+ // 获取最新的频繁时间
+ $latestFrequentTime = !empty($frequentTasks) ? $frequentTasks[0]['createTime'] : null;
+
+ // 计算频繁次数(统计近30天内包含"操作过于频繁"的记录)
+ $frequentCount = count($frequentTasks);
+
+ // 如果30天内没有频繁记录,清除扣分
+ if (empty($frequentTasks)) {
+ return [
+ 'lastFrequentTime' => null,
+ 'frequentCount' => 0,
+ 'frequentPenalty' => 0
+ ];
+ }
+
+ // 根据30天内的频繁次数计算扣分
$penalty = 0;
+ if ($frequentCount == 1) {
+ $penalty = self::PENALTY_FIRST_FREQUENT; // 首次频繁-15分
+ } elseif ($frequentCount >= 2) {
+ $penalty = self::PENALTY_SECOND_FREQUENT; // 再次频繁-25分
+ }
- // 检查是否有频繁记录
- $lastFrequentTime = $accountData['lastFrequentTime'] ?? null;
- $frequentCount = $accountData['frequentCount'] ?? 0;
+ return [
+ 'lastFrequentTime' => $latestFrequentTime,
+ 'frequentCount' => $frequentCount,
+ 'frequentPenalty' => $penalty
+ ];
+ }
+
+ /**
+ * 从s2_wechat_message表检查封号记录
+ * content包含"你的账号被限制"且msgType为10000
+ * 只统计近30天的数据
+ *
+ * @param int $accountId 账号ID
+ * @param string $wechatId 微信ID
+ * @return array|null
+ */
+ private function checkBannedFromMessage($accountId, $wechatId)
+ {
+ // 计算30天前的时间戳
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
- if (!empty($lastFrequentTime)) {
- // 判断是首次频繁还是再次频繁
- if ($frequentCount == 1) {
- $penalty += self::PENALTY_FIRST_FREQUENT; // 首次频繁-15分
- } elseif ($frequentCount >= 2) {
- $penalty += self::PENALTY_SECOND_FREQUENT; // 再次频繁-25分
+ // 查询封号消息(只统计近30天)
+ $banMessage = Db::table('s2_wechat_message')
+ ->where('wechatAccountId', $accountId)
+ ->where('msgType', 10000)
+ ->where('content', 'like', '%你的账号被限制%')
+ ->where('isDeleted', 0)
+ ->where('createTime', '>=', $thirtyDaysAgo)
+ ->order('createTime', 'desc')
+ ->find();
+
+ if (!empty($banMessage)) {
+ return [
+ 'isBanned' => 1,
+ 'banPenalty' => self::PENALTY_BANNED // 封号-60分
+ ];
+ }
+
+ return [
+ 'isBanned' => 0,
+ 'banPenalty' => 0
+ ];
+ }
+
+ /**
+ * 计算不频繁加分
+ * 反向参考频繁规则:查询近30天的频繁记录,计算连续不频繁天数
+ * 规则:30天内连续不频繁的,只要有一次频繁就得重新计算(重置连续不频繁天数)
+ * 如果连续3天没有频繁,则每天+5分
+ *
+ * @param int $accountId 账号ID
+ * @param string $wechatId 微信ID
+ * @param array $frequentData 频繁数据(包含lastFrequentTime和frequentCount)
+ * @return array 包含bonus、consecutiveDays、lastNoFrequentTime
+ */
+ private function calculateNoFrequentBonus($accountId, $wechatId, $frequentData)
+ {
+ $result = [
+ 'bonus' => 0,
+ 'consecutiveDays' => 0,
+ 'lastNoFrequentTime' => null
+ ];
+
+ if (empty($accountId) || empty($wechatId)) {
+ return $result;
+ }
+
+ // 计算30天前的时间戳
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ $currentTime = time();
+
+ // 获取最后一次频繁时间(30天内最后一次频繁的时间)
+ $lastFrequentTime = $frequentData['lastFrequentTime'] ?? null;
+
+ // 规则:30天内连续不频繁的,只要有一次频繁就得重新计算(重置连续不频繁天数)
+ if (empty($lastFrequentTime)) {
+ // 情况1:30天内没有频繁记录,说明30天内连续不频繁
+ // 计算从30天前到现在的连续不频繁天数(最多30天)
+ $consecutiveDays = min(30, floor(($currentTime - $thirtyDaysAgo) / 86400));
+ } else {
+ // 情况2:30天内有频繁记录,从最后一次频繁时间开始重新计算连续不频繁天数
+ // 只要有一次频繁,连续不频繁天数就从最后一次频繁时间开始重新计算
+ // 计算从最后一次频繁时间到现在,连续多少天没有频繁
+ $timeDiff = $currentTime - $lastFrequentTime;
+ $consecutiveDays = floor($timeDiff / 86400); // 向下取整,得到完整的天数
+
+ // 边界情况:如果最后一次频繁时间在30天前(理论上不应该发生,因为查询已经限制了30天),则按30天处理
+ if ($lastFrequentTime < $thirtyDaysAgo) {
+ $consecutiveDays = min(30, floor(($currentTime - $thirtyDaysAgo) / 86400));
}
}
- // 检查是否封号(这里需要根据实际业务逻辑判断,比如status字段或其他标识)
- // 假设status=0表示封号
- $status = $accountData['status'] ?? 1;
- if ($status == 0) {
- $penalty += self::PENALTY_BANNED; // 封号-60分
+ // 如果连续3天或以上没有频繁,则每天+5分
+ if ($consecutiveDays >= 3) {
+ $bonus = $consecutiveDays * self::BONUS_NO_FREQUENT_PER_DAY;
+ $result['bonus'] = $bonus;
+ $result['consecutiveDays'] = $consecutiveDays;
+ $result['lastNoFrequentTime'] = $currentTime;
+ } else {
+ $result['consecutiveDays'] = $consecutiveDays;
}
- return $penalty;
- }
-
- /**
- * 计算加分
- * 连续3天不触发频繁:每天+5分
- *
- * @param array $accountData 账号数据
- * @return int 加分数
- */
- private function calculateBonus($accountData)
- {
- $bonus = 0;
-
- $lastNoFrequentTime = $accountData['lastNoFrequentTime'] ?? null;
- $consecutiveNoFrequentDays = $accountData['consecutiveNoFrequentDays'] ?? 0;
-
- // 如果连续不频繁天数>=3,则每天+5分
- if ($consecutiveNoFrequentDays >= 3) {
- $bonus = $consecutiveNoFrequentDays * self::BONUS_NO_FREQUENT_PER_DAY;
- }
-
- return $bonus;
+ return $result;
}
/**
@@ -252,11 +597,12 @@ class WechatAccountHealthScoreService
/**
* 批量计算并更新多个账号的健康分
*
- * @param array $accountIds 账号ID数组
+ * @param array $accountIds 账号ID数组(为空则处理所有账号)
* @param int $batchSize 每批处理数量
+ * @param bool $forceRecalculateBase 是否强制重新计算基础分
* @return array 处理结果统计
*/
- public function batchCalculateAndUpdate($accountIds = [], $batchSize = 100)
+ public function batchCalculateAndUpdate($accountIds = [], $batchSize = 100, $forceRecalculateBase = false)
{
$stats = [
'total' => 0,
@@ -280,7 +626,7 @@ class WechatAccountHealthScoreService
foreach ($batches as $batch) {
foreach ($batch as $accountId) {
try {
- $this->calculateAndUpdate($accountId);
+ $this->calculateAndUpdate($accountId, null, $forceRecalculateBase);
$stats['success']++;
} catch (Exception $e) {
$stats['failed']++;
@@ -296,38 +642,22 @@ class WechatAccountHealthScoreService
}
/**
- * 记录频繁事件
+ * 记录频繁事件(已废弃,改为从s2_friend_task表自动检测)
+ * 保留此方法以兼容旧代码,实际频繁检测在calculateDynamicScore中完成
*
* @param int $accountId 账号ID
* @return bool
*/
public function recordFrequent($accountId)
{
- $accountData = Db::table('s2_wechat_account')
- ->where('id', $accountId)
- ->find();
-
- if (empty($accountData)) {
+ // 频繁检测已改为从s2_friend_task表自动检测
+ // 直接重新计算健康分即可
+ try {
+ $this->calculateAndUpdate($accountId);
+ return true;
+ } catch (\Exception $e) {
return false;
}
-
- $frequentCount = ($accountData['frequentCount'] ?? 0) + 1;
-
- $updateData = [
- 'lastFrequentTime' => time(),
- 'frequentCount' => $frequentCount,
- 'consecutiveNoFrequentDays' => 0, // 重置连续不频繁天数
- 'lastNoFrequentTime' => null
- ];
-
- Db::table('s2_wechat_account')
- ->where('id', $accountId)
- ->update($updateData);
-
- // 重新计算健康分
- $this->calculateAndUpdate($accountId);
-
- return true;
}
/**
@@ -338,21 +668,29 @@ class WechatAccountHealthScoreService
*/
public function recordNoFrequent($accountId)
{
- $accountData = Db::table('s2_wechat_account')
- ->where('id', $accountId)
- ->find();
+ $scoreRecord = $this->getScoreRecord($accountId);
- if (empty($accountData)) {
- return false;
+ if (empty($scoreRecord)) {
+ // 如果记录不存在,先创建
+ $accountData = Db::table('s2_wechat_account')
+ ->where('id', $accountId)
+ ->find();
+
+ if (empty($accountData)) {
+ return false;
+ }
+
+ $this->getOrCreateScoreRecord($accountId, $accountData['wechatId']);
+ $scoreRecord = $this->getScoreRecord($accountId);
}
- $lastNoFrequentTime = $accountData['lastNoFrequentTime'] ?? null;
- $consecutiveNoFrequentDays = $accountData['consecutiveNoFrequentDays'] ?? 0;
+ $lastNoFrequentTime = $scoreRecord['lastNoFrequentTime'] ?? null;
+ $consecutiveNoFrequentDays = $scoreRecord['consecutiveNoFrequentDays'] ?? 0;
$currentTime = time();
// 如果上次不频繁时间是昨天或更早,则增加连续天数
if (empty($lastNoFrequentTime) || ($currentTime - $lastNoFrequentTime) >= 86400) {
- // 如果间隔超过1天,重置为1天
+ // 如果间隔超过2天,重置为1天
if (!empty($lastNoFrequentTime) && ($currentTime - $lastNoFrequentTime) > 86400 * 2) {
$consecutiveNoFrequentDays = 1;
} else {
@@ -360,13 +698,21 @@ class WechatAccountHealthScoreService
}
}
+ // 计算加分(连续3天及以上才加分)
+ $bonus = 0;
+ if ($consecutiveNoFrequentDays >= 3) {
+ $bonus = $consecutiveNoFrequentDays * self::BONUS_NO_FREQUENT_PER_DAY;
+ }
+
$updateData = [
'lastNoFrequentTime' => $currentTime,
- 'consecutiveNoFrequentDays' => $consecutiveNoFrequentDays
+ 'consecutiveNoFrequentDays' => $consecutiveNoFrequentDays,
+ 'noFrequentBonus' => $bonus,
+ 'updateTime' => $currentTime
];
- Db::table('s2_wechat_account')
- ->where('id', $accountId)
+ Db::table('s2_wechat_account_score')
+ ->where('accountId', $accountId)
->update($updateData);
// 重新计算健康分
@@ -374,5 +720,38 @@ class WechatAccountHealthScoreService
return true;
}
+
+ /**
+ * 获取账号健康分信息
+ *
+ * @param int $accountId 账号ID
+ * @return array|null
+ */
+ public function getHealthScore($accountId)
+ {
+ $scoreRecord = $this->getScoreRecord($accountId);
+
+ if (empty($scoreRecord)) {
+ return null;
+ }
+
+ return [
+ 'accountId' => $scoreRecord['accountId'],
+ 'wechatId' => $scoreRecord['wechatId'],
+ 'healthScore' => $scoreRecord['healthScore'] ?? 0,
+ 'baseScore' => $scoreRecord['baseScore'] ?? 0,
+ 'baseInfoScore' => $scoreRecord['baseInfoScore'] ?? 0,
+ 'friendCountScore' => $scoreRecord['friendCountScore'] ?? 0,
+ 'friendCount' => $scoreRecord['friendCount'] ?? 0,
+ 'dynamicScore' => $scoreRecord['dynamicScore'] ?? 0,
+ 'frequentPenalty' => $scoreRecord['frequentPenalty'] ?? 0,
+ 'noFrequentBonus' => $scoreRecord['noFrequentBonus'] ?? 0,
+ 'banPenalty' => $scoreRecord['banPenalty'] ?? 0,
+ 'maxAddFriendPerDay' => $scoreRecord['maxAddFriendPerDay'] ?? 0,
+ 'baseScoreCalculated' => $scoreRecord['baseScoreCalculated'] ?? 0,
+ 'lastFrequentTime' => $scoreRecord['lastFrequentTime'] ?? null,
+ 'frequentCount' => $scoreRecord['frequentCount'] ?? 0,
+ 'isBanned' => $scoreRecord['isBanned'] ?? 0
+ ];
+ }
}
-
diff --git a/Server/crontab_tasks.md b/Server/crontab_tasks.md
index f5849517..f7d1dfc8 100644
--- a/Server/crontab_tasks.md
+++ b/Server/crontab_tasks.md
@@ -81,6 +81,8 @@
# 消息提醒
*/1 * * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think kf:notice >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/kf_notice.log 2>&1
+# 客服评分
+0 2 * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think wechat:calculate-score >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/calculate_score.log 2>&1
@@ -107,4 +109,10 @@
```bash
crontab -l
+```
+
+```bash
+- 本地: php think worker:server
+- 线上: php think worker:server -d (自带守护进程,无需搭配Supervisor 之类的工具)
+- php think worker:server stop php think worker:server status
```
\ No newline at end of file
diff --git a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php
index adafc321..247684bc 100644
--- a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php
+++ b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php
@@ -18,6 +18,7 @@ use think\facade\Config;
use think\facade\Log;
use app\api\controller\FriendTaskController;
use app\common\service\AuthService;
+use app\common\service\WechatAccountHealthScoreService;
use app\api\controller\WebSocketController;
use Workerman\Lib\Timer;
@@ -180,13 +181,11 @@ class Adapter implements WeChatServiceInterface
->select();
$taskData = array_merge($taskData, $tasks);
}
-
if ($taskData) {
foreach ($taskData as $task) {
$task_id = $task['task_id'];
$task_info = $this->getCustomerAcquisitionTask($task_id);
-
if (empty($task_info['status']) || empty($task_info['reqConf']) || empty($task_info['reqConf']['device'])) {
continue;
}
@@ -213,9 +212,86 @@ class Adapter implements WeChatServiceInterface
continue;
}
- // 判断24h内加的好友数量,friend_task 先固定10个人 getLast24hAddedFriendsCount
+ // 根据健康分判断24h内加的好友数量限制
+ $healthScoreService = new WechatAccountHealthScoreService();
+ $healthScoreInfo = $healthScoreService->getHealthScore($accountId);
+
+ // 如果健康分记录不存在,先计算一次
+ if (empty($healthScoreInfo)) {
+ try {
+ $healthScoreService->calculateAndUpdate($accountId);
+ $healthScoreInfo = $healthScoreService->getHealthScore($accountId);
+ } catch (\Exception $e) {
+ Log::error("计算健康分失败 (accountId: {$accountId}): " . $e->getMessage());
+ // 如果计算失败,使用默认值5作为兜底
+ $maxAddFriendPerDay = 5;
+ }
+ }
+
+ // 获取每日最大加人次数(基于健康分)
+ $maxAddFriendPerDay = $healthScoreInfo['maxAddFriendPerDay'] ?? 5;
+
+ // 如果健康分为0或很低,不允许添加好友
+ if ($maxAddFriendPerDay <= 0) {
+ Log::info("账号健康分过低,不允许添加好友 (accountId: {$accountId}, wechatId: {$wechatId}, healthScore: " . ($healthScoreInfo['healthScore'] ?? 0) . ")");
+ continue;
+ }
+
+ // 检查频繁暂停限制:首次频繁或再次频繁,暂停24小时
+ $lastFrequentTime = $healthScoreInfo['lastFrequentTime'] ?? null;
+ $frequentCount = $healthScoreInfo['frequentCount'] ?? 0;
+ if (!empty($lastFrequentTime) && $frequentCount > 0) {
+ $frequentPauseHours = 24; // 频繁暂停24小时
+ $frequentPauseTime = $lastFrequentTime + ($frequentPauseHours * 3600);
+ $currentTime = time();
+
+ if ($currentTime < $frequentPauseTime) {
+ $remainingHours = ceil(($frequentPauseTime - $currentTime) / 3600);
+ Log::info("账号频繁,暂停添加好友 (accountId: {$accountId}, wechatId: {$wechatId}, frequentCount: {$frequentCount}, 剩余暂停时间: {$remainingHours}小时)");
+ continue;
+ }
+ }
+
+ // 检查封号暂停限制:封号暂停72小时
+ $isBanned = $healthScoreInfo['isBanned'] ?? 0;
+ if ($isBanned == 1) {
+ // 查询封号时间(从s2_wechat_message表查询最近一次封号消息)
+ $banMessage = Db::table('s2_wechat_message')
+ ->where('wechatAccountId', $accountId)
+ ->where('msgType', 10000)
+ ->where('content', 'like', '%你的账号被限制%')
+ ->where('isDeleted', 0)
+ ->order('createTime', 'desc')
+ ->find();
+
+ if (!empty($banMessage)) {
+ $banTime = $banMessage['createTime'] ?? 0;
+ $banPauseHours = 72; // 封号暂停72小时
+ $banPauseTime = $banTime + ($banPauseHours * 3600);
+ $currentTime = time();
+
+ if ($currentTime < $banPauseTime) {
+ $remainingHours = ceil(($banPauseTime - $currentTime) / 3600);
+ Log::info("账号封号,暂停添加好友 (accountId: {$accountId}, wechatId: {$wechatId}, 剩余暂停时间: {$remainingHours}小时)");
+ continue;
+ }
+ }
+ }
+
+ // 判断今天添加的好友数量,使用健康分计算的每日最大加人次数
+ // 优先使用今天添加的好友数量(更符合"每日"限制)
+ $todayAddedFriendsCount = $this->getTodayAddedFriendsCount($wechatId);
+ if ($todayAddedFriendsCount >= $maxAddFriendPerDay) {
+ Log::info("今天添加好友数量已达上限 (accountId: {$accountId}, wechatId: {$wechatId}, count: {$todayAddedFriendsCount}, max: {$maxAddFriendPerDay}, healthScore: " . ($healthScoreInfo['healthScore'] ?? 0) . ")");
+ continue;
+ }
+
+ // 如果今天添加数量未达上限,再检查24小时内的数量(作为额外保护)
$last24hAddedFriendsCount = $this->getLast24hAddedFriendsCount($wechatId);
- if ($last24hAddedFriendsCount >= 20) {
+ // 24小时内的限制可以稍微宽松一些,设置为每日限制的1.2倍(防止跨天累积)
+ $max24hLimit = (int)ceil($maxAddFriendPerDay * 1.2);
+ if ($last24hAddedFriendsCount >= $max24hLimit) {
+ Log::info("24小时内添加好友数量已达上限 (accountId: {$accountId}, wechatId: {$wechatId}, count: {$last24hAddedFriendsCount}, max24h: {$max24hLimit}, maxDaily: {$maxAddFriendPerDay})");
continue;
}
@@ -828,6 +904,7 @@ class Adapter implements WeChatServiceInterface
if (empty($deviceIds)) {
return [];
}
+
$records = Db::table('s2_wechat_account')
->where('deviceAlive', 1)
->where('wechatAlive', 1)
From 36eb67a217791f7676d697d4f2746b8d5d342672 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Fri, 21 Nov 2025 17:22:33 +0800
Subject: [PATCH 5/7] =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E8=AF=84=E5=88=86?=
=?UTF-8?q?=E4=BD=93=E7=B3=BB=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CalculateWechatAccountScoreCommand.php | 413 ++++++++++++----
.../WechatAccountHealthScoreService.php | 455 +++++++++++++++---
2 files changed, 711 insertions(+), 157 deletions(-)
diff --git a/Server/application/command/CalculateWechatAccountScoreCommand.php b/Server/application/command/CalculateWechatAccountScoreCommand.php
index dbc7ec5b..aeb73784 100644
--- a/Server/application/command/CalculateWechatAccountScoreCommand.php
+++ b/Server/application/command/CalculateWechatAccountScoreCommand.php
@@ -6,6 +6,7 @@ use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
+use think\facade\Log;
use app\common\service\WechatAccountHealthScoreService;
/**
@@ -17,36 +18,122 @@ use app\common\service\WechatAccountHealthScoreService;
*/
class CalculateWechatAccountScoreCommand extends Command
{
+ /**
+ * 数据库表名
+ */
+ const TABLE_WECHAT_ACCOUNT = 's2_wechat_account';
+ const TABLE_WECHAT_ACCOUNT_SCORE = 's2_wechat_account_score';
protected function configure()
{
$this->setName('wechat:calculate-score')
- ->setDescription('统一计算微信账号健康分(包含初始化、更新评分记录、批量计算)');
+ ->setDescription('统一计算微信账号健康分(包含初始化、更新评分记录、批量计算)')
+ ->addOption('only-init', null, \think\console\input\Option::VALUE_NONE, '仅执行初始化步骤')
+ ->addOption('only-update', null, \think\console\input\Option::VALUE_NONE, '仅执行更新评分记录步骤')
+ ->addOption('only-batch', null, \think\console\input\Option::VALUE_NONE, '仅执行批量更新健康分步骤')
+ ->addOption('account-id', 'a', \think\console\input\Option::VALUE_OPTIONAL, '指定账号ID,仅处理该账号')
+ ->addOption('batch-size', 'b', \think\console\input\Option::VALUE_OPTIONAL, '批处理大小', 50)
+ ->addOption('force-recalculate', 'f', \think\console\input\Option::VALUE_NONE, '强制重新计算基础分');
}
+ /**
+ * 执行命令
+ *
+ * @param Input $input 输入对象
+ * @param Output $output 输出对象
+ * @return int 命令执行状态码(0表示成功)
+ */
protected function execute(Input $input, Output $output)
{
+ // 解析命令行参数
+ $onlyInit = $input->getOption('only-init');
+ $onlyUpdate = $input->getOption('only-update');
+ $onlyBatch = $input->getOption('only-batch');
+ $accountId = $input->getOption('account-id');
+ $batchSize = (int)$input->getOption('batch-size');
+ $forceRecalculate = $input->getOption('force-recalculate');
+
+ // 参数验证
+ if ($batchSize <= 0) {
+ $batchSize = 50; // 默认批处理大小
+ }
+
+ // 显示执行参数
$output->writeln("==========================================");
$output->writeln("开始统一计算微信账号健康分...");
$output->writeln("==========================================");
+ if ($accountId) {
+ $output->writeln("指定账号ID: {$accountId}");
+ }
+
+ if ($onlyInit) {
+ $output->writeln("仅执行初始化步骤");
+ } elseif ($onlyUpdate) {
+ $output->writeln("仅执行更新评分记录步骤");
+ } elseif ($onlyBatch) {
+ $output->writeln("仅执行批量更新健康分步骤");
+ }
+
+ if ($forceRecalculate) {
+ $output->writeln("强制重新计算基础分");
+ }
+
+ $output->writeln("批处理大小: {$batchSize}");
+
+ // 记录命令开始执行的日志
+ Log::info('开始执行微信账号健康分计算命令', [
+ 'accountId' => $accountId,
+ 'onlyInit' => $onlyInit ? 'true' : 'false',
+ 'onlyUpdate' => $onlyUpdate ? 'true' : 'false',
+ 'onlyBatch' => $onlyBatch ? 'true' : 'false',
+ 'batchSize' => $batchSize,
+ 'forceRecalculate' => $forceRecalculate ? 'true' : 'false'
+ ]);
+
$startTime = time();
- $service = new WechatAccountHealthScoreService();
+
+ try {
+ // 实例化服务
+ $service = new WechatAccountHealthScoreService();
+ } catch (\Exception $e) {
+ $errorMsg = "实例化WechatAccountHealthScoreService失败: " . $e->getMessage();
+ $output->writeln("{$errorMsg}");
+ Log::error($errorMsg);
+ return 1; // 返回非零状态码表示失败
+ }
+
+ // 初始化统计数据
+ $initStats = ['success' => 0, 'failed' => 0, 'errors' => []];
+ $updateStats = ['total' => 0];
+ $batchStats = ['success' => 0, 'failed' => 0, 'errors' => []];
try {
// 步骤1: 初始化未计算基础分的账号
- $output->writeln("\n[步骤1] 初始化未计算基础分的账号...");
- $initStats = $this->initUncalculatedAccounts($service, $output);
- $output->writeln("初始化完成:成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条");
+ if (!$onlyUpdate && !$onlyBatch) {
+ $output->writeln("\n[步骤1] 初始化未计算基础分的账号...");
+ Log::info('[步骤1] 开始初始化未计算基础分的账号');
+ $initStats = $this->initUncalculatedAccounts($service, $output, $accountId, $batchSize);
+ $output->writeln("初始化完成:成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条");
+ Log::info("初始化完成:成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条");
+ }
// 步骤2: 更新评分记录(根据wechatId和alias不一致情况)
- $output->writeln("\n[步骤2] 更新评分记录(根据wechatId和alias不一致情况)...");
- $updateStats = $this->updateScoreRecords($service, $output);
- $output->writeln("更新完成:处理了 {$updateStats['total']} 条记录");
+ if (!$onlyInit && !$onlyBatch) {
+ $output->writeln("\n[步骤2] 更新评分记录(根据wechatId和alias不一致情况)...");
+ Log::info('[步骤2] 开始更新评分记录(根据wechatId和alias不一致情况)');
+ $updateStats = $this->updateScoreRecords($service, $output, $accountId, $batchSize);
+ $output->writeln("更新完成:处理了 {$updateStats['total']} 条记录");
+ Log::info("更新评分记录完成:处理了 {$updateStats['total']} 条记录");
+ }
// 步骤3: 批量更新健康分(只更新动态分,不重新计算基础分)
- $output->writeln("\n[步骤3] 批量更新健康分(只更新动态分)...");
- $batchStats = $this->batchUpdateHealthScore($service, $output);
- $output->writeln("批量更新完成:成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+ if (!$onlyInit && !$onlyUpdate) {
+ $output->writeln("\n[步骤3] 批量更新健康分(只更新动态分)...");
+ Log::info('[步骤3] 开始批量更新健康分(只更新动态分)');
+ $batchStats = $this->batchUpdateHealthScore($service, $output, $accountId, $batchSize, $forceRecalculate);
+ $output->writeln("批量更新完成:成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+ Log::info("批量更新健康分完成:成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+ }
// 统计信息
$endTime = time();
@@ -60,40 +147,89 @@ class CalculateWechatAccountScoreCommand extends Command
$output->writeln("更新评分记录: {$updateStats['total']} 条");
$output->writeln("批量更新: 成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+ // 记录命令执行完成的日志
+ Log::info("微信账号健康分计算命令执行完成,总耗时: {$duration} 秒," .
+ "初始化: 成功 {$initStats['success']} 条,失败 {$initStats['failed']} 条," .
+ "更新评分记录: {$updateStats['total']} 条," .
+ "批量更新: 成功 {$batchStats['success']} 条,失败 {$batchStats['failed']} 条");
+
if (!empty($initStats['errors'])) {
$output->writeln("\n初始化错误详情:");
+ Log::warning("初始化阶段出现 " . count($initStats['errors']) . " 个错误");
+
foreach (array_slice($initStats['errors'], 0, 10) as $error) {
$output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ Log::error("初始化错误 - 账号ID {$error['accountId']}: {$error['error']}");
}
+
if (count($initStats['errors']) > 10) {
$output->writeln(" ... 还有 " . (count($initStats['errors']) - 10) . " 个错误");
+ Log::warning("初始化错误过多,只记录前10个,还有 " . (count($initStats['errors']) - 10) . " 个错误未显示");
}
}
if (!empty($batchStats['errors'])) {
$output->writeln("\n批量更新错误详情:");
+ Log::warning("批量更新阶段出现 " . count($batchStats['errors']) . " 个错误");
+
foreach (array_slice($batchStats['errors'], 0, 10) as $error) {
$output->writeln(" 账号ID {$error['accountId']}: {$error['error']}");
+ Log::error("批量更新错误 - 账号ID {$error['accountId']}: {$error['error']}");
}
+
if (count($batchStats['errors']) > 10) {
$output->writeln(" ... 还有 " . (count($batchStats['errors']) - 10) . " 个错误");
+ Log::warning("批量更新错误过多,只记录前10个,还有 " . (count($batchStats['errors']) - 10) . " 个错误未显示");
}
}
- } catch (\Exception $e) {
- $output->writeln("\n错误: " . $e->getMessage());
+ } catch (\PDOException $e) {
+ // 数据库异常
+ $errorMsg = "数据库操作失败: " . $e->getMessage();
+ $output->writeln("\n数据库错误: " . $errorMsg . "");
$output->writeln($e->getTraceAsString());
+
+ // 记录数据库错误
+ Log::error("数据库错误: " . $errorMsg);
+ Log::error("错误堆栈: " . $e->getTraceAsString());
+
+ return 2; // 数据库错误状态码
+ } catch (\Exception $e) {
+ // 一般异常
+ $errorMsg = "命令执行失败: " . $e->getMessage();
+ $output->writeln("\n错误: " . $errorMsg . "");
+ $output->writeln($e->getTraceAsString());
+
+ // 记录严重错误
+ Log::error($errorMsg);
+ Log::error("错误堆栈: " . $e->getTraceAsString());
+
+ return 1; // 一般错误状态码
+ } catch (\Throwable $e) {
+ // 其他所有错误
+ $errorMsg = "严重错误: " . $e->getMessage();
+ $output->writeln("\n严重错误: " . $errorMsg . "");
+ $output->writeln($e->getTraceAsString());
+
+ // 记录严重错误
+ Log::critical($errorMsg);
+ Log::critical("错误堆栈: " . $e->getTraceAsString());
+
+ return 3; // 严重错误状态码
}
+
+ return 0; // 成功执行
}
/**
* 初始化未计算基础分的账号
*
- * @param WechatAccountHealthScoreService $service
- * @param Output $output
- * @return array
+ * @param WechatAccountHealthScoreService $service 健康分服务实例
+ * @param Output $output 输出对象
+ * @return array 处理结果统计
+ * @throws \Exception 如果查询或处理过程中出现错误
*/
- private function initUncalculatedAccounts($service, $output)
+ private function initUncalculatedAccounts($service, $output, $accountId = null, $batchSize = 50)
{
$stats = [
'total' => 0,
@@ -102,41 +238,67 @@ class CalculateWechatAccountScoreCommand extends Command
'errors' => []
];
- // 获取所有未计算基础分的账号
- $accounts = Db::table('s2_wechat_account')
- ->alias('a')
- ->leftJoin(['s2_wechat_account_score' => 's'], 's.accountId = a.id')
- ->where('a.isDeleted', 0)
- ->where(function($query) {
- $query->whereNull('s.id')
- ->whereOr('s.baseScoreCalculated', 0);
- })
- ->field('a.id, a.wechatId')
- ->select();
+ try {
+ // 获取所有未计算基础分的账号
+ // 优化查询:使用索引字段,只查询必要的字段
+ $query = Db::table(self::TABLE_WECHAT_ACCOUNT)
+ ->alias('a')
+ ->leftJoin([self::TABLE_WECHAT_ACCOUNT_SCORE => 's'], 's.accountId = a.id')
+ ->where('a.isDeleted', 0)
+ ->where(function($query) {
+ $query->whereNull('s.id')
+ ->whereOr('s.baseScoreCalculated', 0);
+ });
+
+ // 如果指定了账号ID,则只处理该账号
+ if ($accountId) {
+ $query->where('a.id', $accountId);
+ }
+
+ $accounts = $query->field('a.id, a.wechatId') // 只查询必要的字段
+ ->select();
+ } catch (\Exception $e) {
+ Log::error("查询未计算基础分的账号失败: " . $e->getMessage());
+ throw new \Exception("查询未计算基础分的账号失败: " . $e->getMessage(), 0, $e);
+ }
$stats['total'] = count($accounts);
if ($stats['total'] == 0) {
$output->writeln("没有需要初始化的账号");
+ Log::info("没有需要初始化的账号");
return $stats;
}
$output->writeln("找到 {$stats['total']} 个需要初始化的账号");
+ Log::info("找到 {$stats['total']} 个需要初始化的账号");
- $batchSize = 100;
+ // 优化批处理:使用传入的批处理大小
$batches = array_chunk($accounts, $batchSize);
+ $batchCount = count($batches);
+
+ Log::info("将分 {$batchCount} 批处理,每批 {$batchSize} 个账号");
foreach ($batches as $batchIndex => $batch) {
+ $batchStartTime = microtime(true);
+ $batchSuccessCount = 0;
+ $batchFailedCount = 0;
+
foreach ($batch as $account) {
try {
$service->calculateAndUpdate($account['id']);
$stats['success']++;
+ $batchSuccessCount++;
- if ($stats['success'] % 100 == 0) {
+ if ($stats['success'] % 20 == 0) { // 更频繁地显示进度
$output->write(".");
+ Log::debug("已成功初始化 {$stats['success']} 个账号");
}
} catch (\Exception $e) {
$stats['failed']++;
+ $batchFailedCount++;
+ $errorMsg = "初始化账号 {$account['id']} 失败: " . $e->getMessage();
+ Log::error($errorMsg);
$stats['errors'][] = [
'accountId' => $account['id'],
'error' => $e->getMessage()
@@ -144,9 +306,12 @@ class CalculateWechatAccountScoreCommand extends Command
}
}
- if (($batchIndex + 1) % 10 == 0) {
- $output->writeln(" 已处理 " . ($batchIndex + 1) * $batchSize . " 条");
- }
+ $batchEndTime = microtime(true);
+ $batchDuration = round($batchEndTime - $batchStartTime, 2);
+
+ // 每批次完成后输出进度信息
+ $output->writeln(" 批次 " . ($batchIndex + 1) . "/{$batchCount} 完成,耗时 {$batchDuration} 秒,成功 {$batchSuccessCount},失败 {$batchFailedCount}");
+ Log::info("初始化批次 " . ($batchIndex + 1) . "/{$batchCount} 完成,耗时 {$batchDuration} 秒,成功 {$batchSuccessCount},失败 {$batchFailedCount}");
}
return $stats;
@@ -155,52 +320,90 @@ class CalculateWechatAccountScoreCommand extends Command
/**
* 更新评分记录(根据wechatId和alias不一致情况)
*
- * @param WechatAccountHealthScoreService $service
- * @param Output $output
- * @return array
+ * @param WechatAccountHealthScoreService $service 健康分服务实例
+ * @param Output $output 输出对象
+ * @return array 处理结果统计
+ * @throws \Exception 如果查询或处理过程中出现错误
*/
- private function updateScoreRecords($service, $output)
+ private function updateScoreRecords($service, $output, $accountId = null, $batchSize = 50)
{
$stats = ['total' => 0];
- // 查找wechatId和alias不一致的账号
- $inconsistentAccounts = Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->where('wechatId', '<>', '')
- ->where('alias', '<>', '')
- ->whereRaw('wechatId != alias')
- ->field('id, wechatId, alias')
- ->select();
-
- // 查找wechatId和alias一致的账号
- $consistentAccounts = Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->where('wechatId', '<>', '')
- ->where('alias', '<>', '')
- ->whereRaw('wechatId = alias')
- ->field('id, wechatId, alias')
- ->select();
+ try {
+ // 优化查询:合并两次查询为一次,减少数据库访问次数
+ $query = Db::table(self::TABLE_WECHAT_ACCOUNT)
+ ->where('isDeleted', 0)
+ ->where('wechatId', '<>', '')
+ ->where('alias', '<>', '');
+
+ // 如果指定了账号ID,则只处理该账号
+ if ($accountId) {
+ $query->where('id', $accountId);
+ }
+
+ $accounts = $query->field('id, wechatId, alias, IF(wechatId = alias, 0, 1) as isModifiedAlias')
+ ->select();
+
+ // 分类处理查询结果
+ $inconsistentAccounts = [];
+ $consistentAccounts = [];
+
+ foreach ($accounts as $account) {
+ if ($account['isModifiedAlias'] == 1) {
+ $inconsistentAccounts[] = $account;
+ } else {
+ $consistentAccounts[] = $account;
+ }
+ }
+ } catch (\Exception $e) {
+ Log::error("查询需要更新评分记录的账号失败: " . $e->getMessage());
+ throw new \Exception("查询需要更新评分记录的账号失败: " . $e->getMessage(), 0, $e);
+ }
$allAccounts = array_merge($inconsistentAccounts, $consistentAccounts);
$stats['total'] = count($allAccounts);
if ($stats['total'] == 0) {
$output->writeln("没有需要更新的账号");
+ Log::info("没有需要更新的评分记录");
return $stats;
}
$output->writeln("找到 {$stats['total']} 个需要更新的账号(不一致: " . count($inconsistentAccounts) . ",一致: " . count($consistentAccounts) . ")");
+ Log::info("找到 {$stats['total']} 个需要更新的账号(不一致: " . count($inconsistentAccounts) . ",一致: " . count($consistentAccounts) . ")");
$updatedCount = 0;
- foreach ($allAccounts as $account) {
- $isModifiedAlias = in_array($account['id'], array_column($inconsistentAccounts, 'id'));
- $this->updateScoreRecord($account['id'], $isModifiedAlias, $service);
- $updatedCount++;
+ // 优化批处理:使用传入的批处理大小
+ $batches = array_chunk($allAccounts, $batchSize);
+ $batchCount = count($batches);
+
+ Log::info("将分 {$batchCount} 批更新评分记录,每批 {$batchSize} 个账号");
+
+ foreach ($batches as $batchIndex => $batch) {
+ $batchStartTime = microtime(true);
+ $batchUpdatedCount = 0;
- if ($updatedCount % 100 == 0) {
- $output->write(".");
+ foreach ($batch as $account) {
+ $isModifiedAlias = isset($account['isModifiedAlias']) ?
+ ($account['isModifiedAlias'] == 1) :
+ in_array($account['id'], array_column($inconsistentAccounts, 'id'));
+
+ $this->updateScoreRecord($account['id'], $isModifiedAlias, $service);
+ $updatedCount++;
+ $batchUpdatedCount++;
+
+ if ($batchUpdatedCount % 20 == 0) {
+ $output->write(".");
+ }
}
+
+ $batchEndTime = microtime(true);
+ $batchDuration = round($batchEndTime - $batchStartTime, 2);
+
+ // 每批次完成后输出进度信息
+ $output->writeln(" 批次 " . ($batchIndex + 1) . "/{$batchCount} 完成,耗时 {$batchDuration} 秒,更新 {$batchUpdatedCount} 条记录");
+ Log::info("更新评分记录批次 " . ($batchIndex + 1) . "/{$batchCount} 完成,耗时 {$batchDuration} 秒,更新 {$batchUpdatedCount} 条记录");
}
if ($updatedCount > 0 && $updatedCount % 100 == 0) {
@@ -213,27 +416,44 @@ class CalculateWechatAccountScoreCommand extends Command
/**
* 批量更新健康分(只更新动态分)
*
- * @param WechatAccountHealthScoreService $service
- * @param Output $output
- * @return array
+ * @param WechatAccountHealthScoreService $service 健康分服务实例
+ * @param Output $output 输出对象
+ * @return array 处理结果统计
+ * @throws \Exception 如果查询或处理过程中出现错误
*/
- private function batchUpdateHealthScore($service, $output)
+ private function batchUpdateHealthScore($service, $output, $accountId = null, $batchSize = 50, $forceRecalculate = false)
{
- // 获取所有已计算基础分的账号
- $accountIds = Db::table('s2_wechat_account_score')
- ->where('baseScoreCalculated', 1)
- ->column('accountId');
+ try {
+ // 获取所有已计算基础分的账号
+ // 优化查询:只查询必要的字段,使用索引字段
+ $query = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
+ ->where('baseScoreCalculated', 1);
+
+ // 如果指定了账号ID,则只处理该账号
+ if ($accountId) {
+ $query->where('accountId', $accountId);
+ }
+
+ $accountIds = $query->column('accountId');
+ } catch (\Exception $e) {
+ Log::error("查询需要批量更新健康分的账号失败: " . $e->getMessage());
+ throw new \Exception("查询需要批量更新健康分的账号失败: " . $e->getMessage(), 0, $e);
+ }
$total = count($accountIds);
if ($total == 0) {
$output->writeln("没有需要更新的账号");
+ Log::info("没有需要批量更新健康分的账号");
return ['success' => 0, 'failed' => 0, 'errors' => []];
}
$output->writeln("找到 {$total} 个需要更新动态分的账号");
+ Log::info("找到 {$total} 个需要更新动态分的账号");
- $stats = $service->batchCalculateAndUpdate($accountIds, 100, false);
+ // 使用传入的批处理大小和强制重新计算标志
+ Log::info("使用批量大小 {$batchSize} 进行批量更新健康分,强制重新计算基础分: " . ($forceRecalculate ? 'true' : 'false'));
+ $stats = $service->batchCalculateAndUpdate($accountIds, $batchSize, $forceRecalculate);
return $stats;
}
@@ -245,31 +465,47 @@ class CalculateWechatAccountScoreCommand extends Command
* @param bool $isModifiedAlias 是否已修改微信号
* @param WechatAccountHealthScoreService $service 评分服务
*/
+ /**
+ * 更新评分记录
+ *
+ * @param int $accountId 账号ID
+ * @param bool $isModifiedAlias 是否已修改微信号
+ * @param WechatAccountHealthScoreService $service 评分服务
+ * @return bool 是否成功更新
+ */
private function updateScoreRecord($accountId, $isModifiedAlias, $service)
{
- // 获取账号数据
- $accountData = Db::table('s2_wechat_account')
- ->where('id', $accountId)
- ->find();
+ Log::debug("开始更新账号 {$accountId} 的评分记录,isModifiedAlias: " . ($isModifiedAlias ? 'true' : 'false'));
- if (empty($accountData)) {
- return;
- }
-
- // 确保评分记录存在
- $scoreRecord = Db::table('s2_wechat_account_score')
- ->where('accountId', $accountId)
- ->find();
+ try {
+ // 获取账号数据 - 只查询必要的字段
+ $accountData = Db::table(self::TABLE_WECHAT_ACCOUNT)
+ ->where('id', $accountId)
+ ->field('id, wechatId, alias') // 只查询必要的字段
+ ->find();
+
+ if (empty($accountData)) {
+ Log::warning("账号 {$accountId} 不存在,跳过更新评分记录");
+ return false;
+ }
+
+ // 确保评分记录存在 - 只查询必要的字段
+ $scoreRecord = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
+ ->where('accountId', $accountId)
+ ->field('accountId, baseScore, baseScoreCalculated, baseInfoScore, dynamicScore') // 只查询必要的字段
+ ->find();
if (empty($scoreRecord)) {
// 如果记录不存在,创建并计算基础分
+ Log::info("账号 {$accountId} 的评分记录不存在,创建并计算基础分");
$service->calculateAndUpdate($accountId);
- $scoreRecord = Db::table('s2_wechat_account_score')
+ $scoreRecord = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
->where('accountId', $accountId)
->find();
}
if (empty($scoreRecord)) {
+ Log::warning("账号 {$accountId} 的评分记录创建失败,跳过更新");
return;
}
@@ -297,15 +533,26 @@ class CalculateWechatAccountScoreCommand extends Command
$healthScore = max(0, min(100, $healthScore));
$updateData['healthScore'] = $healthScore;
$updateData['maxAddFriendPerDay'] = (int)floor($healthScore * 0.2);
+
+ Log::info("账号 {$accountId} 的基础信息分从 {$oldBaseInfoScore} 更新为 {$newBaseInfoScore}," .
+ "基础分从 {$oldBaseScore} 更新为 {$newBaseScore},健康分更新为 {$healthScore}");
}
} else {
// 基础分未计算,只更新标记和基础信息分
$updateData['baseInfoScore'] = $isModifiedAlias ? 10 : 0;
}
- Db::table('s2_wechat_account_score')
+ $result = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
->where('accountId', $accountId)
->update($updateData);
+
+ Log::debug("账号 {$accountId} 的评分记录更新" . ($result !== false ? "成功" : "失败"));
+
+ return $result !== false;
+ } catch (\Exception $e) {
+ Log::error("更新账号 {$accountId} 的评分记录失败: " . $e->getMessage());
+ return false;
+ }
}
}
diff --git a/Server/application/common/service/WechatAccountHealthScoreService.php b/Server/application/common/service/WechatAccountHealthScoreService.php
index 02a89a9b..d6246a26 100644
--- a/Server/application/common/service/WechatAccountHealthScoreService.php
+++ b/Server/application/common/service/WechatAccountHealthScoreService.php
@@ -4,6 +4,8 @@ namespace app\common\service;
use think\Db;
use think\Exception;
+use think\facade\Log;
+use think\facade\Cache;
/**
* 微信账号健康分评分服务(优化版)
@@ -14,33 +16,63 @@ use think\Exception;
* 2. 各个评分维度独立存储
* 3. 使用独立的评分记录表
* 4. 好友数量评分特殊处理(避免同步问题)
+ * 5. 动态分仅统计近30天数据
+ * 6. 优化数据库查询,减少重复计算
+ * 7. 添加完善的日志记录,便于问题排查
*
* 健康分 = 基础分 + 动态分
* 基础分:60-100分(默认60分 + 基础信息10分 + 好友数量30分)
* 动态分:扣分和加分规则
+ *
+ * @author Your Name
+ * @version 2.0.0
*/
class WechatAccountHealthScoreService
{
- // 默认基础分
+ /**
+ * 缓存相关配置
+ */
+ const CACHE_PREFIX = 'wechat_health_score:'; // 缓存前缀
+ const CACHE_TTL = 3600; // 缓存有效期(秒)
+
+ /**
+ * 默认基础分
+ */
const DEFAULT_BASE_SCORE = 60;
- // 基础信息分数
+ /**
+ * 基础信息分数
+ */
const BASE_INFO_SCORE = 10;
- // 好友数量分数区间
- const FRIEND_COUNT_SCORE_0_50 = 3;
- const FRIEND_COUNT_SCORE_51_500 = 6;
- const FRIEND_COUNT_SCORE_501_3000 = 8;
- const FRIEND_COUNT_SCORE_3001_PLUS = 12;
+ /**
+ * 好友数量分数区间
+ */
+ const FRIEND_COUNT_SCORE_0_50 = 3; // 0-50个好友
+ const FRIEND_COUNT_SCORE_51_500 = 6; // 51-500个好友
+ const FRIEND_COUNT_SCORE_501_3000 = 8; // 501-3000个好友
+ const FRIEND_COUNT_SCORE_3001_PLUS = 12; // 3001+个好友
- // 动态分扣分规则
- const PENALTY_FIRST_FREQUENT = -15; // 首次频繁扣15分
+ /**
+ * 动态分扣分规则
+ */
+ const PENALTY_FIRST_FREQUENT = -15; // 首次频繁扣15分
const PENALTY_SECOND_FREQUENT = -25; // 再次频繁扣25分
const PENALTY_BANNED = -60; // 封号扣60分
- // 动态分加分规则
+ /**
+ * 动态分加分规则
+ */
const BONUS_NO_FREQUENT_PER_DAY = 5; // 连续3天不触发频繁,每天+5分
+ /**
+ * 数据库表名
+ */
+ const TABLE_WECHAT_ACCOUNT = 's2_wechat_account';
+ const TABLE_WECHAT_ACCOUNT_SCORE = 's2_wechat_account_score';
+ const TABLE_FRIEND_TASK = 's2_friend_task';
+ const TABLE_WECHAT_MESSAGE = 's2_wechat_message';
+
/**
* 计算并更新账号健康分
*
@@ -48,38 +80,65 @@ class WechatAccountHealthScoreService
* @param array $accountData 账号数据(可选,如果不传则从数据库查询)
* @param bool $forceRecalculateBase 是否强制重新计算基础分(默认false)
* @return array 返回评分结果
+ * @throws Exception 如果计算过程中出现错误
*/
public function calculateAndUpdate($accountId, $accountData = null, $forceRecalculateBase = false)
{
+ // 参数验证
+ if (empty($accountId) || !is_numeric($accountId)) {
+ $errorMsg = "无效的账号ID: " . (is_scalar($accountId) ? $accountId : gettype($accountId));
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
+ }
+
try {
+ Log::info("开始计算账号健康分,accountId: {$accountId}, forceRecalculateBase: " . ($forceRecalculateBase ? 'true' : 'false'));
+
// 获取账号数据
if (empty($accountData)) {
- $accountData = Db::table('s2_wechat_account')
+ $accountData = Db::table(self::TABLE_WECHAT_ACCOUNT)
->where('id', $accountId)
->find();
+
+ Log::debug("查询账号数据: " . ($accountData ? "成功" : "失败"));
}
if (empty($accountData)) {
- throw new Exception("账号不存在:{$accountId}");
+ $errorMsg = "账号不存在:{$accountId}";
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
}
$wechatId = $accountData['wechatId'] ?? '';
if (empty($wechatId)) {
- throw new Exception("账号wechatId为空:{$accountId}");
+ $errorMsg = "账号wechatId为空:{$accountId}";
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
}
+ Log::debug("账号数据: accountId={$accountId}, wechatId={$wechatId}");
+
// 获取或创建评分记录
$scoreRecord = $this->getOrCreateScoreRecord($accountId, $wechatId);
+ Log::debug("获取评分记录: " . ($scoreRecord ? "成功" : "失败"));
// 计算基础分(只计算一次,除非强制重新计算)
if (!$scoreRecord['baseScoreCalculated'] || $forceRecalculateBase) {
+ Log::info("计算基础分,accountId: {$accountId}, baseScoreCalculated: " .
+ ($scoreRecord['baseScoreCalculated'] ? 'true' : 'false') .
+ ", forceRecalculateBase: " . ($forceRecalculateBase ? 'true' : 'false'));
+
$baseScoreData = $this->calculateBaseScore($accountData, $scoreRecord);
$this->updateBaseScore($accountId, $baseScoreData);
+
+ Log::debug("基础分计算结果: " . json_encode($baseScoreData));
+
// 重新获取记录以获取最新数据
$scoreRecord = $this->getScoreRecord($accountId);
}
// 计算动态分(每次都要重新计算)
+ Log::info("计算动态分,accountId: {$accountId}");
$dynamicScoreData = $this->calculateDynamicScore($accountData, $scoreRecord);
// 计算总分
@@ -93,6 +152,9 @@ class WechatAccountHealthScoreService
// 计算每日最大加人次数
$maxAddFriendPerDay = $this->getMaxAddFriendPerDay($healthScore);
+ Log::info("健康分计算结果,accountId: {$accountId}, baseScore: {$baseScore}, dynamicScore: {$dynamicScore}, " .
+ "healthScore: {$healthScore}, maxAddFriendPerDay: {$maxAddFriendPerDay}");
+
// 更新评分记录
$updateData = [
'dynamicScore' => $dynamicScore,
@@ -109,11 +171,16 @@ class WechatAccountHealthScoreService
'updateTime' => time()
];
- Db::table('s2_wechat_account_score')
+ $updateResult = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
->where('accountId', $accountId)
->update($updateData);
+
+ // 更新成功后,清除缓存
+ if ($updateResult !== false) {
+ $this->clearScoreCache($accountId);
+ }
- return [
+ $result = [
'accountId' => $accountId,
'wechatId' => $wechatId,
'healthScore' => $healthScore,
@@ -127,8 +194,19 @@ class WechatAccountHealthScoreService
'maxAddFriendPerDay' => $maxAddFriendPerDay
];
- } catch (Exception $e) {
- throw new Exception("计算健康分失败:" . $e->getMessage());
+ Log::debug("健康分计算完成,返回结果: " . json_encode($result));
+ return $result;
+
+ } catch (\PDOException $e) {
+ // 数据库异常
+ $errorMsg = "数据库操作失败,accountId: {$accountId}, 错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
+ } catch (\Throwable $e) {
+ // 其他所有异常
+ $errorMsg = "计算健康分失败,accountId: {$accountId}, 错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
}
}
@@ -141,11 +219,13 @@ class WechatAccountHealthScoreService
*/
private function getOrCreateScoreRecord($accountId, $wechatId)
{
- $record = Db::table('s2_wechat_account_score')
- ->where('accountId', $accountId)
- ->find();
+ // 尝试获取现有记录
+ $record = $this->getScoreRecord($accountId);
+ // 如果记录不存在,创建新记录
if (empty($record)) {
+ Log::info("为账号 {$accountId} 创建新的评分记录");
+
// 创建新记录
$data = [
'accountId' => $accountId,
@@ -163,7 +243,7 @@ class WechatAccountHealthScoreService
'updateTime' => time()
];
- Db::table('s2_wechat_account_score')->insert($data);
+ Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)->insert($data);
return $data;
}
@@ -175,13 +255,33 @@ class WechatAccountHealthScoreService
* 获取评分记录
*
* @param int $accountId 账号ID
- * @return array
+ * @param bool $useCache 是否使用缓存(默认true)
+ * @return array 评分记录,如果不存在则返回空数组
*/
- private function getScoreRecord($accountId)
+ private function getScoreRecord($accountId, $useCache = true)
{
- return Db::table('s2_wechat_account_score')
+ // 生成缓存键
+ $cacheKey = self::CACHE_PREFIX . 'score:' . $accountId;
+
+ // 如果使用缓存且缓存存在,则直接返回缓存数据
+ if ($useCache && Cache::has($cacheKey)) {
+ $cachedData = Cache::get($cacheKey);
+ Log::debug("从缓存获取评分记录,accountId: {$accountId}");
+ return $cachedData ?: [];
+ }
+
+ // 从数据库获取记录
+ $record = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
->where('accountId', $accountId)
- ->find() ?: [];
+ ->find();
+
+ // 如果记录存在且使用缓存,则缓存记录
+ if ($record && $useCache) {
+ Cache::set($cacheKey, $record, self::CACHE_TTL);
+ Log::debug("缓存评分记录,accountId: {$accountId}");
+ }
+
+ return $record ?: [];
}
/**
@@ -240,12 +340,41 @@ class WechatAccountHealthScoreService
*
* @param int $accountId 账号ID
* @param array $baseScoreData 基础分数据
+ * @return bool 更新是否成功
*/
private function updateBaseScore($accountId, $baseScoreData)
{
- Db::table('s2_wechat_account_score')
- ->where('accountId', $accountId)
- ->update($baseScoreData);
+ try {
+ $result = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
+ ->where('accountId', $accountId)
+ ->update($baseScoreData);
+
+ Log::debug("更新基础分,accountId: {$accountId}, 结果: " . ($result ? "成功" : "失败"));
+
+ // 更新成功后,清除缓存
+ if ($result !== false) {
+ $this->clearScoreCache($accountId);
+ }
+
+ return $result !== false;
+ } catch (Exception $e) {
+ Log::error("更新基础分失败,accountId: {$accountId}, 错误: " . $e->getMessage());
+ return false;
+ }
+ }
+
+ /**
+ * 清除评分记录缓存
+ *
+ * @param int $accountId 账号ID
+ * @return bool 是否成功清除缓存
+ */
+ private function clearScoreCache($accountId)
+ {
+ $cacheKey = self::CACHE_PREFIX . 'score:' . $accountId;
+ $result = Cache::rm($cacheKey);
+ Log::debug("清除评分记录缓存,accountId: {$accountId}, 结果: " . ($result ? "成功" : "失败"));
+ return $result;
}
/**
@@ -310,16 +439,44 @@ class WechatAccountHealthScoreService
* @param int $accountId 账号ID
* @param int $friendCount 好友数量
* @param string $source 来源(manual=手动,sync=同步)
- * @return bool
+ * @return bool 更新是否成功
+ * @throws Exception 如果参数无效或更新过程中出现错误
*/
public function updateFriendCountScore($accountId, $friendCount, $source = 'manual')
{
- $scoreRecord = $this->getScoreRecord($accountId);
+ // 参数验证
+ if (empty($accountId) || !is_numeric($accountId)) {
+ $errorMsg = "无效的账号ID: " . (is_scalar($accountId) ? $accountId : gettype($accountId));
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
+ }
- // 如果基础分已计算,不允许修改好友数量分(除非是手动更新)
- if (!empty($scoreRecord['baseScoreCalculated']) && $source === 'sync') {
- // 同步数据不允许修改已计算的基础分
- return false;
+ if (!is_numeric($friendCount) || $friendCount < 0) {
+ $errorMsg = "无效的好友数量: {$friendCount}";
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
+ }
+
+ if (!in_array($source, ['manual', 'sync'])) {
+ $errorMsg = "无效的来源: {$source},必须是 'manual' 或 'sync'";
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
+ }
+
+ try {
+ $scoreRecord = $this->getScoreRecord($accountId);
+
+ // 如果基础分已计算,不允许修改好友数量分(除非是手动更新)
+ if (!empty($scoreRecord['baseScoreCalculated']) && $source === 'sync') {
+ // 同步数据不允许修改已计算的基础分
+ Log::warning("同步数据不允许修改已计算的基础分,accountId: {$accountId}");
+ return false;
+ }
+ }
+ catch (\Exception $e) {
+ $errorMsg = "获取评分记录失败,accountId: {$accountId}, 错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
}
$friendCountScore = $this->getFriendCountScore($friendCount);
@@ -348,16 +505,36 @@ class WechatAccountHealthScoreService
$updateData['maxAddFriendPerDay'] = $this->getMaxAddFriendPerDay($healthScore);
}
- Db::table('s2_wechat_account_score')
- ->where('accountId', $accountId)
- ->update($updateData);
-
- return true;
+ try {
+ $result = Db::table(self::TABLE_WECHAT_ACCOUNT_SCORE)
+ ->where('accountId', $accountId)
+ ->update($updateData);
+
+ // 更新成功后,清除缓存
+ if ($result !== false) {
+ $this->clearScoreCache($accountId);
+ $this->clearHealthScoreCache($accountId);
+ Log::info("更新好友数量分成功,accountId: {$accountId}, friendCount: {$friendCount}, source: {$source}");
+ } else {
+ Log::warning("更新好友数量分失败,accountId: {$accountId}, friendCount: {$friendCount}, source: {$source}");
+ }
+
+ return $result !== false;
+ } catch (\PDOException $e) {
+ $errorMsg = "数据库操作失败,accountId: {$accountId}, 错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
+ } catch (\Throwable $e) {
+ $errorMsg = "更新好友数量分失败,accountId: {$accountId}, 错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
+ }
}
/**
* 计算动态分
* 动态分 = 扣分 + 加分
+ * 如果添加好友记录表没有记录,则动态分为0
*
* @param array $accountData 账号数据
* @param array $scoreRecord 现有评分记录
@@ -365,6 +542,11 @@ class WechatAccountHealthScoreService
*/
private function calculateDynamicScore($accountData, $scoreRecord)
{
+ $accountId = $accountData['id'] ?? 0;
+ $wechatId = $accountData['wechatId'] ?? '';
+
+ Log::debug("开始计算动态分,accountId: {$accountId}, wechatId: {$wechatId}");
+
$result = [
'total' => 0,
'frequentPenalty' => 0,
@@ -377,13 +559,33 @@ class WechatAccountHealthScoreService
'isBanned' => 0
];
- $accountId = $accountData['id'] ?? 0;
- $wechatId = $accountData['wechatId'] ?? '';
-
if (empty($accountId) || empty($wechatId)) {
+ Log::warning("计算动态分失败: accountId或wechatId为空");
return $result;
}
+ // 计算30天前的时间戳(在多个方法中使用)
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+
+ // 检查添加好友记录表是否有记录,如果没有记录则动态分为0
+ // 使用EXISTS子查询优化性能,只检查是否存在记录,不需要计数
+ $hasFriendTask = Db::table(self::TABLE_FRIEND_TASK)
+ ->where('wechatAccountId', $accountId)
+ ->where(function($query) use ($wechatId) {
+ if (!empty($wechatId)) {
+ $query->where('wechatId', $wechatId);
+ }
+ })
+ ->value('id'); // 只获取ID,比count()更高效
+
+ // 如果添加好友记录表没有记录,则动态分为0
+ if (empty($hasFriendTask)) {
+ Log::info("账号没有添加好友记录,动态分为0,accountId: {$accountId}");
+ return $result;
+ }
+
+ Log::debug("账号有添加好友记录,继续计算动态分,accountId: {$accountId}");
+
// 继承现有数据
if (!empty($scoreRecord)) {
$result['lastFrequentTime'] = $scoreRecord['lastFrequentTime'] ?? null;
@@ -396,20 +598,20 @@ class WechatAccountHealthScoreService
}
// 1. 检查频繁记录(从s2_friend_task表查询,只统计近30天)
- $frequentData = $this->checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord);
+ $frequentData = $this->checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord, $thirtyDaysAgo);
$result['lastFrequentTime'] = $frequentData['lastFrequentTime'] ?? null;
$result['frequentCount'] = $frequentData['frequentCount'] ?? 0;
$result['frequentPenalty'] = $frequentData['frequentPenalty'] ?? 0;
// 2. 检查封号记录(从s2_wechat_message表查询)
- $banData = $this->checkBannedFromMessage($accountId, $wechatId);
+ $banData = $this->checkBannedFromMessage($accountId, $wechatId, $thirtyDaysAgo);
if (!empty($banData)) {
$result['isBanned'] = $banData['isBanned'];
$result['banPenalty'] = $banData['banPenalty'];
}
// 3. 计算不频繁加分(基于近30天的频繁记录,反向参考频繁规则)
- $noFrequentData = $this->calculateNoFrequentBonus($accountId, $wechatId, $frequentData);
+ $noFrequentData = $this->calculateNoFrequentBonus($accountId, $wechatId, $frequentData, $thirtyDaysAgo);
$result['noFrequentBonus'] = $noFrequentData['bonus'] ?? 0;
$result['consecutiveNoFrequentDays'] = $noFrequentData['consecutiveDays'] ?? 0;
$result['lastNoFrequentTime'] = $noFrequentData['lastNoFrequentTime'] ?? null;
@@ -417,6 +619,10 @@ class WechatAccountHealthScoreService
// 计算总分
$result['total'] = $result['frequentPenalty'] + $result['noFrequentBonus'] + $result['banPenalty'];
+ Log::debug("动态分计算结果,accountId: {$accountId}, frequentPenalty: {$result['frequentPenalty']}, " .
+ "noFrequentBonus: {$result['noFrequentBonus']}, banPenalty: {$result['banPenalty']}, " .
+ "total: {$result['total']}");
+
return $result;
}
@@ -428,16 +634,20 @@ class WechatAccountHealthScoreService
* @param int $accountId 账号ID
* @param string $wechatId 微信ID
* @param array $scoreRecord 现有评分记录
+ * @param int $thirtyDaysAgo 30天前的时间戳(可选,如果已计算则传入以避免重复计算)
* @return array|null
*/
- private function checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord)
+ private function checkFrequentFromFriendTask($accountId, $wechatId, $scoreRecord, $thirtyDaysAgo = null)
{
- // 计算30天前的时间戳
- $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ // 如果没有传入30天前的时间戳,则计算
+ if ($thirtyDaysAgo === null) {
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ }
// 查询包含"操作过于频繁"的记录(只统计近30天)
// extra字段可能是文本或JSON格式,使用LIKE查询
- $frequentTasks = Db::table('s2_friend_task')
+ // 优化查询:只查询必要的字段,减少数据传输量
+ $frequentTasks = Db::table(self::TABLE_FRIEND_TASK)
->where('wechatAccountId', $accountId)
->where('createTime', '>=', $thirtyDaysAgo)
->where(function($query) use ($wechatId) {
@@ -448,7 +658,7 @@ class WechatAccountHealthScoreService
->where(function($query) {
// 检查extra字段是否包含"操作过于频繁"(可能是文本或JSON)
$query->where('extra', 'like', '%操作过于频繁%')
- ->whereOr('extra', 'like', '%"操作过于频繁"%');
+ ->whereOr('extra', 'like', '%"当前账号存在安全风险"%');
})
->order('createTime', 'desc')
->field('id, createTime, extra')
@@ -491,20 +701,25 @@ class WechatAccountHealthScoreService
*
* @param int $accountId 账号ID
* @param string $wechatId 微信ID
+ * @param int $thirtyDaysAgo 30天前的时间戳(可选,如果已计算则传入以避免重复计算)
* @return array|null
*/
- private function checkBannedFromMessage($accountId, $wechatId)
+ private function checkBannedFromMessage($accountId, $wechatId, $thirtyDaysAgo = null)
{
- // 计算30天前的时间戳
- $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ // 如果没有传入30天前的时间戳,则计算
+ if ($thirtyDaysAgo === null) {
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ }
// 查询封号消息(只统计近30天)
- $banMessage = Db::table('s2_wechat_message')
+ // 优化查询:只查询必要的字段,减少数据传输量
+ $banMessage = Db::table(self::TABLE_WECHAT_MESSAGE)
->where('wechatAccountId', $accountId)
->where('msgType', 10000)
->where('content', 'like', '%你的账号被限制%')
->where('isDeleted', 0)
->where('createTime', '>=', $thirtyDaysAgo)
+ ->field('id, createTime') // 只查询必要的字段
->order('createTime', 'desc')
->find();
@@ -530,9 +745,10 @@ class WechatAccountHealthScoreService
* @param int $accountId 账号ID
* @param string $wechatId 微信ID
* @param array $frequentData 频繁数据(包含lastFrequentTime和frequentCount)
+ * @param int $thirtyDaysAgo 30天前的时间戳(可选,如果已计算则传入以避免重复计算)
* @return array 包含bonus、consecutiveDays、lastNoFrequentTime
*/
- private function calculateNoFrequentBonus($accountId, $wechatId, $frequentData)
+ private function calculateNoFrequentBonus($accountId, $wechatId, $frequentData, $thirtyDaysAgo = null)
{
$result = [
'bonus' => 0,
@@ -544,8 +760,10 @@ class WechatAccountHealthScoreService
return $result;
}
- // 计算30天前的时间戳
- $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ // 如果没有传入30天前的时间戳,则计算
+ if ($thirtyDaysAgo === null) {
+ $thirtyDaysAgo = time() - (30 * 24 * 3600);
+ }
$currentTime = time();
// 获取最后一次频繁时间(30天内最后一次频繁的时间)
@@ -601,29 +819,54 @@ class WechatAccountHealthScoreService
* @param int $batchSize 每批处理数量
* @param bool $forceRecalculateBase 是否强制重新计算基础分
* @return array 处理结果统计
+ * @throws Exception 如果参数无效或批量处理过程中出现严重错误
*/
public function batchCalculateAndUpdate($accountIds = [], $batchSize = 100, $forceRecalculateBase = false)
{
- $stats = [
- 'total' => 0,
- 'success' => 0,
- 'failed' => 0,
- 'errors' => []
- ];
-
- // 如果没有指定账号ID,则处理所有账号
- if (empty($accountIds)) {
- $accountIds = Db::table('s2_wechat_account')
- ->where('isDeleted', 0)
- ->column('id');
+ // 参数验证
+ if (!is_array($accountIds)) {
+ $errorMsg = "无效的账号ID数组: " . gettype($accountIds);
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
}
+ if (!is_numeric($batchSize) || $batchSize <= 0) {
+ $errorMsg = "无效的批处理大小: {$batchSize}";
+ Log::error($errorMsg);
+ throw new Exception($errorMsg);
+ }
+
+ try {
+ $startTime = microtime(true);
+ Log::info("开始批量计算健康分,batchSize: {$batchSize}, forceRecalculateBase: " . ($forceRecalculateBase ? 'true' : 'false'));
+
+ $stats = [
+ 'total' => 0,
+ 'success' => 0,
+ 'failed' => 0,
+ 'errors' => []
+ ];
+
+ // 如果没有指定账号ID,则处理所有账号
+ if (empty($accountIds)) {
+ Log::info("未指定账号ID,处理所有未删除账号");
+ $accountIds = Db::table(self::TABLE_WECHAT_ACCOUNT)
+ ->where('isDeleted', 0)
+ ->column('id');
+ }
+
$stats['total'] = count($accountIds);
+ Log::info("需要处理的账号总数: {$stats['total']}");
// 分批处理
$batches = array_chunk($accountIds, $batchSize);
+ $batchCount = count($batches);
+ Log::info("分批处理,共 {$batchCount} 批");
- foreach ($batches as $batch) {
+ foreach ($batches as $batchIndex => $batch) {
+ $batchStartTime = microtime(true);
+ Log::info("开始处理第 " . ($batchIndex + 1) . " 批,共 " . count($batch) . " 个账号");
+
foreach ($batch as $accountId) {
try {
$this->calculateAndUpdate($accountId, null, $forceRecalculateBase);
@@ -634,11 +877,30 @@ class WechatAccountHealthScoreService
'accountId' => $accountId,
'error' => $e->getMessage()
];
+ Log::error("账号 {$accountId} 计算失败: " . $e->getMessage());
}
}
+
+ $batchEndTime = microtime(true);
+ $batchDuration = round($batchEndTime - $batchStartTime, 2);
+ Log::info("第 " . ($batchIndex + 1) . " 批处理完成,耗时: {$batchDuration}秒," .
+ "成功: {$stats['success']},失败: {$stats['failed']}");
}
+ $endTime = microtime(true);
+ $totalDuration = round($endTime - $startTime, 2);
+ Log::info("批量计算健康分完成,总耗时: {$totalDuration}秒,成功: {$stats['success']},失败: {$stats['failed']}");
+
return $stats;
+ } catch (\PDOException $e) {
+ $errorMsg = "批量计算健康分过程中数据库操作失败: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
+ } catch (\Throwable $e) {
+ $errorMsg = "批量计算健康分过程中发生严重错误: " . $e->getMessage();
+ Log::error($errorMsg);
+ throw new Exception($errorMsg, $e->getCode(), $e);
+ }
}
/**
@@ -672,7 +934,7 @@ class WechatAccountHealthScoreService
if (empty($scoreRecord)) {
// 如果记录不存在,先创建
- $accountData = Db::table('s2_wechat_account')
+ $accountData = Db::table(self::TABLE_WECHAT_ACCOUNT)
->where('id', $accountId)
->find();
@@ -725,17 +987,36 @@ class WechatAccountHealthScoreService
* 获取账号健康分信息
*
* @param int $accountId 账号ID
+ * @param bool $useCache 是否使用缓存(默认true)
+ * @param bool $forceRecalculate 是否强制重新计算(默认false)
* @return array|null
*/
- public function getHealthScore($accountId)
+ public function getHealthScore($accountId, $useCache = true, $forceRecalculate = false)
{
- $scoreRecord = $this->getScoreRecord($accountId);
+ // 如果强制重新计算,则不使用缓存
+ if ($forceRecalculate) {
+ Log::info("强制重新计算健康分,accountId: {$accountId}");
+ return $this->calculateAndUpdate($accountId, null, false);
+ }
+
+ // 生成缓存键
+ $cacheKey = self::CACHE_PREFIX . 'health:' . $accountId;
+
+ // 如果使用缓存且缓存存在,则直接返回缓存数据
+ if ($useCache && !$forceRecalculate && Cache::has($cacheKey)) {
+ $cachedData = Cache::get($cacheKey);
+ Log::debug("从缓存获取健康分信息,accountId: {$accountId}");
+ return $cachedData;
+ }
+
+ // 从数据库获取记录
+ $scoreRecord = $this->getScoreRecord($accountId, $useCache);
if (empty($scoreRecord)) {
return null;
}
- return [
+ $healthScoreInfo = [
'accountId' => $scoreRecord['accountId'],
'wechatId' => $scoreRecord['wechatId'],
'healthScore' => $scoreRecord['healthScore'] ?? 0,
@@ -753,5 +1034,31 @@ class WechatAccountHealthScoreService
'frequentCount' => $scoreRecord['frequentCount'] ?? 0,
'isBanned' => $scoreRecord['isBanned'] ?? 0
];
+
+ // 如果使用缓存,则缓存健康分信息
+ if ($useCache) {
+ Cache::set($cacheKey, $healthScoreInfo, self::CACHE_TTL);
+ Log::debug("缓存健康分信息,accountId: {$accountId}");
+ }
+
+ return $healthScoreInfo;
+ }
+
+ /**
+ * 清除健康分信息缓存
+ *
+ * @param int $accountId 账号ID
+ * @return bool 是否成功清除缓存
+ */
+ public function clearHealthScoreCache($accountId)
+ {
+ $cacheKey = self::CACHE_PREFIX . 'health:' . $accountId;
+ $result = Cache::rm($cacheKey);
+
+ // 同时清除评分记录缓存
+ $this->clearScoreCache($accountId);
+
+ Log::debug("清除健康分信息缓存,accountId: {$accountId}, 结果: " . ($result ? "成功" : "失败"));
+ return $result;
}
}
From 1786dec900ec91a28719fc7ade31e1c45745da67 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 24 Nov 2025 10:13:30 +0800
Subject: [PATCH 6/7] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/controller/WebSocketController.php | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Server/application/api/controller/WebSocketController.php b/Server/application/api/controller/WebSocketController.php
index 773cbb3d..5b714997 100644
--- a/Server/application/api/controller/WebSocketController.php
+++ b/Server/application/api/controller/WebSocketController.php
@@ -457,7 +457,7 @@ class WebSocketController extends BaseController
// 构建请求参数
$params = [
- "cmdType" => 'CmdDownloadMomentImagesResult',
+ "cmdType" => 'CmdDownloadMomentImages',
"snsId" => $data['snsId'],
"urls" => $data['snsUrls'],
"wechatAccountId" => $data['wechatAccountId'],
@@ -558,15 +558,15 @@ class WebSocketController extends BaseController
$dataToSave['create_time'] = time();
$res = WechatMoments::create($dataToSave);
}
- // // 获取资源链接
- // if(empty($momentEntity['resUrls']) && !empty($momentEntity['urls'])){
- // $snsData = [
- // 'snsId' => $moment['snsId'],
- // 'snsUrls' => $momentEntity['urls'],
- // 'wechatAccountId' => $wechatAccountId,
- // ];
- // $this->getMomentSourceRealUrl($snsData);
- // }
+ // 获取资源链接
+ if(empty($momentEntity['resUrls']) && !empty($momentEntity['urls'])){
+ $snsData = [
+ 'snsId' => $moment['snsId'],
+ 'snsUrls' => $momentEntity['urls'],
+ 'wechatAccountId' => $wechatAccountId,
+ ];
+ $this->getMomentSourceRealUrl($snsData);
+ }
}
//Log::write('朋友圈数据已存入数据库,共' . count($momentList) . '条');
From 30b33ec974059ede3ee8f6dcd4fef64ef2f5f994 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 24 Nov 2025 11:03:31 +0800
Subject: [PATCH 7/7] =?UTF-8?q?=E6=9C=8B=E5=8F=8B=E5=9C=88=E9=87=87?=
=?UTF-8?q?=E9=9B=86=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/controller/WebSocketController.php | 12 ++++--------
.../cunkebao/controller/ContentLibraryController.php | 8 ++++----
2 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/Server/application/api/controller/WebSocketController.php b/Server/application/api/controller/WebSocketController.php
index 5b714997..b9b8a860 100644
--- a/Server/application/api/controller/WebSocketController.php
+++ b/Server/application/api/controller/WebSocketController.php
@@ -463,16 +463,10 @@ class WebSocketController extends BaseController
"wechatAccountId" => $data['wechatAccountId'],
"seq" => time(),
];
-
// 记录请求日志
Log::info('获取朋友圈资源链接请求:' . json_encode($params, 256));
- // 发送请求
- $this->client->send(json_encode($params));
-
- // 接收响应
- $response = $this->client->receive();
- $message = json_decode($response, true);
+ $message = $this->sendMessage($params);
if (empty($message)) {
return json_encode(['code' => 500, 'msg' => '获取朋友圈资源链接失败']);
@@ -558,8 +552,10 @@ class WebSocketController extends BaseController
$dataToSave['create_time'] = time();
$res = WechatMoments::create($dataToSave);
}
+
+
// 获取资源链接
- if(empty($momentEntity['resUrls']) && !empty($momentEntity['urls'])){
+ if(empty($momentEntity['resUrls']) && !empty($momentEntity['urls']) && $moment['type'] == 1) {
$snsData = [
'snsId' => $moment['snsId'],
'snsUrls' => $momentEntity['urls'],
diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php
index e4a2f639..69291123 100644
--- a/Server/application/cunkebao/controller/ContentLibraryController.php
+++ b/Server/application/cunkebao/controller/ContentLibraryController.php
@@ -1070,7 +1070,7 @@ class ContentLibraryController extends Controller
->select()->toArray();
if (empty($libraries)) {
- return json(['code' => 200, 'msg' => '没有可用的内容库配置']);
+ return json_encode(['code' => 200, 'msg' => '没有可用的内容库配置'],256);
}
$successCount = 0;
@@ -1159,7 +1159,7 @@ class ContentLibraryController extends Controller
}
// 返回采集结果
- return json([
+ return json_encode([
'code' => 200,
'msg' => '采集任务执行完成',
'data' => [
@@ -1169,7 +1169,7 @@ class ContentLibraryController extends Controller
'skipped' => $totalLibraries - $successCount - $failCount,
'results' => $results
]
- ]);
+ ],256);
}
/**
@@ -1206,7 +1206,7 @@ class ContentLibraryController extends Controller
->whereIn('id', $friendIds)
->where('isDeleted', 0)
->select();
-
+
if (empty($friends)) {
return [
'status' => 'failed',