企微短剧业务系统

ChatMenuService.php 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: shensong
  5. * Date: 2022/6/23
  6. * Time: 17:39
  7. */
  8. namespace App\Service;
  9. use App\Log;
  10. use App\Models\ChatMenuGroup;
  11. use App\Models\ChatMenuMsg;
  12. use App\Models\ChatMenuRecord;
  13. use App\Models\ChatMenuRule;
  14. use App\Models\Material;
  15. use App\Models\UserSop\UserSopMsg;
  16. use App\RedisModel;
  17. use App\Support\EmailQueue;
  18. class ChatMenuService
  19. {
  20. public static function createChatMenuGroup($params)
  21. {
  22. try{
  23. // 验证雷达组名称是否重复
  24. $info = ChatMenuGroup::getGroupInfoByName($params['corpid'], $params['sys_group_id'], $params['group_name']);
  25. if(!empty($info)) {
  26. Log::logError('createChatMenuGroup', [
  27. 'params' => $params,
  28. 'message' => '话术组名称已使用',
  29. ],'interface');
  30. return ['话术组名称已使用', 3403];
  31. }
  32. // 获取雷达组最大排序值
  33. $maxSortOrder = ChatMenuGroup::getMaxSortOrder($params['corpid'], $params['sys_group_id']);
  34. $res = ChatMenuGroup::query()
  35. ->insert([
  36. 'sys_group_id' => $params['sys_group_id'],
  37. 'corpid' => $params['corpid'],
  38. 'group_name' => $params['group_name'],
  39. 'creator_id' => \Auth::id(),
  40. 'sort_order' => $maxSortOrder + 1,
  41. ]);
  42. if($res) {
  43. return ['添加成功', 0];
  44. } else {
  45. Log::logError('createChatMenuGroup', [
  46. 'params' => $params,
  47. 'message' => '添加失败',
  48. 'res' => $res,
  49. ],'interface');
  50. return ['添加失败', 400];
  51. }
  52. } catch (\Exception $exception) {
  53. Log::logError('createChatMenuGroup', [
  54. 'params' => $params,
  55. 'file' => $exception->getFile(),
  56. 'line' => $exception->getLine(),
  57. 'message' => $exception->getMessage(),
  58. 'trace' => $exception->getTraceAsString(),
  59. ], 'interface');
  60. return ['添加失败', 400];
  61. }
  62. }
  63. public static function chatMenuGroupList($params)
  64. {
  65. try{
  66. $query = ChatMenuGroup::query()
  67. ->where('corpid', $params['corpid'])
  68. ->where('enable', 1);
  69. if(isset($params['sys_group_id']) && $params['sys_group_id'])
  70. $query->where('sys_group_id', $params['sys_group_id']);
  71. if(!empty($params['keyword'])) {
  72. $query->where('group_name', 'like', '%'.$params['keyword'].'%');
  73. }
  74. $count = $query->count();
  75. $list = $query->select(['group_name', 'sort_order'])
  76. ->selectRaw('id as group_id')
  77. ->orderBy('sort_order', 'desc')
  78. ->offset(($params['page']-1) * $params['page_size'])
  79. ->limit($params['page_size'])
  80. ->get();
  81. } catch (\Exception $exception) {
  82. Log::logError('chatMenuGroupList', [
  83. 'params' => $params,
  84. 'file' => $exception->getFile(),
  85. 'line' => $exception->getLine(),
  86. 'message' => $exception->getMessage(),
  87. 'trace' => $exception->getTraceAsString(),
  88. ], 'interface');
  89. return [[], 0];
  90. }
  91. return [$list, $count];
  92. }
  93. // 编辑话术组
  94. public static function updateChatMenuGroup($params)
  95. {
  96. try{
  97. // 验证雷达组名称是否重复
  98. $info = ChatMenuGroup::getGroupInfoByName($params['corpid'], $params['sys_group_id'], $params['group_name']);
  99. if(isset($info->id) && $info->id != $params['group_id']) {
  100. Log::logError('updateChatMenuGroup', [
  101. 'params' => $params,
  102. 'message' => '话术组名称已使用',
  103. ],'interface');
  104. return ['话术组名称已使用', 3403];
  105. }
  106. $radarGroupInfo = ChatMenuGroup::query()
  107. ->where('id', $params['group_id'])
  108. ->first();
  109. if($params['group_name'] == $radarGroupInfo->group_name) {
  110. return ['修改成功', 0];
  111. }
  112. $res = ChatMenuGroup::query()
  113. ->where('id', $params['group_id'])
  114. ->update([
  115. 'group_name' => $params['group_name']
  116. ]);
  117. if($res) {
  118. return ['修改成功', 0];
  119. } else {
  120. Log::logError('updateChatMenuGroup', [
  121. 'params' => $params,
  122. 'message' => '修改失败',
  123. 'res' => $res,
  124. ],'interface');
  125. return ['修改失败', 400];
  126. }
  127. } catch (\Exception $exception) {
  128. Log::logError('updateChatMenuGroup', [
  129. 'params' => $params,
  130. 'file' => $exception->getFile(),
  131. 'line' => $exception->getLine(),
  132. 'message' => $exception->getMessage(),
  133. 'trace' => $exception->getTraceAsString(),
  134. ], 'interface');
  135. return ['修改失败', 400];
  136. }
  137. }
  138. public static function deleteChatMenuGroup($params)
  139. {
  140. try{
  141. \DB::begintransaction();
  142. $groupRes = ChatMenuGroup::query()
  143. ->where('id', $params['group_id'])
  144. ->update([
  145. 'enable' => 0
  146. ]);
  147. $detailCount = ChatMenuRule::query()
  148. ->where('group_id', $params['group_id'])
  149. ->where('enable', 1)
  150. ->count();
  151. // 防止出现本来雷达组下就没有雷达,更新不到数据导致整体删除失败
  152. if($detailCount > 0) {
  153. if(1 == $params['type']) {
  154. $detailRes = ChatMenuRule::query()
  155. ->where('group_id', $params['group_id'])
  156. ->where('enable', 1)
  157. ->update(['group_id' => 0]);
  158. } else {
  159. $detailRes = ChatMenuRule::query()
  160. ->where('group_id', $params['group_id'])
  161. ->where('enable', 1)
  162. ->update(['enable' => 0]);
  163. }
  164. } else {
  165. $detailRes = true;
  166. }
  167. if($groupRes && $detailRes) {
  168. \DB::commit();
  169. return ['删除成功', 0];
  170. } else {
  171. \DB::rollBack();
  172. Log::logError('deleteChatMenuGroup', [
  173. 'params' => $params,
  174. 'message' => '删除失败',
  175. 'group_res' => $groupRes,
  176. 'detail_res' => $detailRes,
  177. ],'interface');
  178. return ['删除失败', 400];
  179. }
  180. } catch (\Exception $exception) {
  181. Log::logError('deleteChatMenuGroup', [
  182. 'params' => $params,
  183. 'file' => $exception->getFile(),
  184. 'line' => $exception->getLine(),
  185. 'message' => $exception->getMessage(),
  186. 'trace' => $exception->getTraceAsString(),
  187. ], 'interface');
  188. return ['删除失败', 400];
  189. }
  190. }
  191. public static function updateChatMenuGroupSortOrder($params)
  192. {
  193. try{
  194. // 查询被操作分组原始排序值
  195. $operatorGroup = ChatMenuGroup::query()
  196. ->where('id', $params['operate_group_id'])
  197. ->first();
  198. $operatorGroupOriginalSortOrder = $operatorGroup->sort_order;
  199. if(!empty($params['behind_group_id']) && empty($params['front_group_id'])) {
  200. // 上移到第一位,判断是否有调整后的排在调整分组后面的分组id
  201. $behindGroup = ChatMenuGroup::query()
  202. ->where('id', $params['behind_group_id'])
  203. ->first();
  204. $behindGroupOriginalSortOrder = $behindGroup->sort_order;
  205. list($data, $code) = self::radarGroupMoveUp($params, $behindGroupOriginalSortOrder, $operatorGroupOriginalSortOrder);
  206. return [$data, $code];
  207. } else if(!empty($params['front_group_id']) && empty($params['behind_group_id'])) {
  208. // 下移到最后一位,判断是否有调整后的排在调整分组前面的分组id
  209. $frontGroup = ChatMenuGroup::query()
  210. ->where('id', $params['front_group_id'])
  211. ->first();
  212. $frontGroupOriginalSortOrder = $frontGroup->sort_order;
  213. list($data, $code) = self::radarGroupMoveDown($params, $frontGroupOriginalSortOrder, $operatorGroupOriginalSortOrder);
  214. return [$data, $code];
  215. } else if(!empty($params['front_group_id']) && !empty($params['behind_group_id'])) {
  216. $frontGroup = ChatMenuGroup::query()
  217. ->where('id', $params['front_group_id'])
  218. ->first();
  219. $frontGroupOriginalSortOrder = $frontGroup->sort_order;
  220. $behindGroup = ChatMenuGroup::query()
  221. ->where('id', $params['behind_group_id'])
  222. ->first();
  223. $behindGroupOriginalSortOrder = $behindGroup->sort_order;
  224. if($operatorGroupOriginalSortOrder > $frontGroupOriginalSortOrder) {
  225. // 下移
  226. list($data, $code) = self::radarGroupMoveDown($params, $frontGroupOriginalSortOrder, $operatorGroupOriginalSortOrder);
  227. } else {
  228. // 上移
  229. list($data, $code) = self::radarGroupMoveUp($params, $behindGroupOriginalSortOrder, $operatorGroupOriginalSortOrder);
  230. }
  231. return [$data, $code];
  232. } else {
  233. Log::logError('updateChatMenuGroupSortOrder', [
  234. 'params' => $params,
  235. 'message' => '被操作话术组前后分组id不可同时为空',
  236. ],'interface');
  237. return ['被操作话术组前后分组id不可同时为空', 3507];
  238. }
  239. } catch (\Exception $exception) {
  240. Log::logError('updateChatMenuGroupSortOrder', [
  241. 'params' => $params,
  242. 'file' => $exception->getFile(),
  243. 'line' => $exception->getLine(),
  244. 'message' => $exception->getMessage(),
  245. 'trace' => $exception->getTraceAsString(),
  246. ], 'interface');
  247. return ['移动失败', 400];
  248. }
  249. }
  250. // 话术组上移
  251. public static function radarGroupMoveUp($params, $behindGroupOriginalSortOrder, $operatorGroupOriginalSortOrder)
  252. {
  253. \DB::begintransaction();
  254. $moveRes = ChatMenuGroup::query()
  255. ->where('corpid', $params['corpid'])
  256. ->where('sys_group_id', $params['sys_group_id'])
  257. ->where('enable', 1)
  258. ->where('sort_order', '<=', $behindGroupOriginalSortOrder)
  259. ->where('sort_order', '>', $operatorGroupOriginalSortOrder)
  260. ->decrement('sort_order');// 自减1
  261. $operatorRes = ChatMenuGroup::query()
  262. ->where('id', $params['operate_group_id'])
  263. ->update(['sort_order' => $behindGroupOriginalSortOrder]);
  264. if($moveRes && $operatorRes) {
  265. \DB::commit();
  266. return ['移动成功', 0];
  267. } else {
  268. \DB::rollBack();
  269. Log::logError('updateChatMenuGroupSortOrder', [
  270. 'params' => $params,
  271. 'message' => '移动失败',
  272. 'move_res' => $moveRes,
  273. 'operator_res' => $operatorRes,
  274. 'operator_sort_order' => $operatorGroupOriginalSortOrder,
  275. 'behind_sort_order' => $behindGroupOriginalSortOrder,
  276. ],'interface');
  277. return ['移动失败', 400];
  278. }
  279. }
  280. // 话术组下移
  281. public static function radarGroupMoveDown($params, $frontGroupOriginalSortOrder, $operatorGroupOriginalSortOrder)
  282. {
  283. \DB::begintransaction();
  284. $moveRes = ChatMenuGroup::query()
  285. ->where('corpid', $params['corpid'])
  286. ->where('sys_group_id', $params['sys_group_id'])
  287. ->where('enable', 1)
  288. ->where('sort_order', '>=', $frontGroupOriginalSortOrder)
  289. ->where('sort_order', '<', $operatorGroupOriginalSortOrder)
  290. ->increment('sort_order');// 自增1
  291. $operatorRes = ChatMenuGroup::query()
  292. ->where('id', $params['operate_group_id'])
  293. ->update(['sort_order' => $frontGroupOriginalSortOrder]);
  294. if($moveRes && $operatorRes) {
  295. \DB::commit();
  296. return ['移动成功', 0];
  297. } else {
  298. \DB::rollBack();
  299. Log::logError('updateChatMenuGroupSortOrder', [
  300. 'params' => $params,
  301. 'message' => '移动失败',
  302. 'move_res' => $moveRes,
  303. 'operator_res' => $operatorRes,
  304. 'operator_sort_order' => $operatorGroupOriginalSortOrder,
  305. 'front_sort_order' => $frontGroupOriginalSortOrder,
  306. ],'interface');
  307. return ['移动失败', 400];
  308. }
  309. }
  310. public static function createChatMenuRule($params)
  311. {
  312. try{
  313. // 解析话术消息
  314. $msgData = json_decode($params['msg_data_list'], 1);
  315. if(count($msgData) > 9) {
  316. Log::logError('createChatMenuRule', [
  317. 'params' => $params,
  318. 'errmsg' => '最多添加9条话术内容',
  319. ], 'interface');
  320. return [['error' => '最多添加9条话术内容'], 3505];
  321. }
  322. if(empty($msgData)) {
  323. Log::logError('createChatMenuRule', [
  324. 'params' => $params,
  325. 'errmsg' => '最少添加1条话术内容',
  326. ], 'interface');
  327. return [['error' => '最少添加1条话术内容'], 3506];
  328. }
  329. // 获取最高的排序值
  330. $maxSortOrder = ChatMenuRule::getMaxSortOrder($params['corpid'], $params['sys_group_id']);
  331. \DB::begintransaction();
  332. //保存话术规则
  333. $chatMenuRule = new ChatMenuRule();
  334. $chatMenuRule->group_id = empty($params['group_id']) ? 0 : $params['group_id'];
  335. $chatMenuRule->title = $params['title'];
  336. $chatMenuRule->sort_order = $maxSortOrder+1;
  337. $chatMenuRule->corpid = $params['corpid'];
  338. $chatMenuRule->sys_group_id = $params['sys_group_id'];
  339. $chatMenuRule->creator_id = \Auth::id();
  340. if($chatMenuRule->save()){
  341. $ruleId = $chatMenuRule->id;
  342. //分类型保存话术消息
  343. foreach ($msgData as $msgInfo) {
  344. $res = ChatMenuMsg::saveData(null, $msgInfo['chat_type'], $msgInfo,
  345. $params['corpid'], $params['sys_group_id'], $ruleId);
  346. if(!$res) {
  347. Log::logError('createChatMenuRule', [
  348. 'params' => $params,
  349. 'chat_menu_rule' => (array)$chatMenuRule,
  350. 'chat_menu_msg' => (array)$res,
  351. 'errmsg' => '添加失败,消息保存失败',
  352. ], 'interface');
  353. \DB::rollBack();
  354. // 添加失败
  355. return ['添加失败', 400];
  356. }
  357. }
  358. \DB::commit();
  359. return ['添加成功', 0];
  360. } else {
  361. Log::logError('createChatMenuRule', [
  362. 'params' => $params,
  363. 'chat_menu_rule' => (array)$chatMenuRule,
  364. 'chat_menu_msg' => [],
  365. 'errmsg' => '添加失败,规则保存失败',
  366. ], 'interface');
  367. \DB::rollBack();
  368. // 添加失败
  369. return ['添加失败', 400];
  370. }
  371. } catch (\Exception $exception) {
  372. Log::logError('createChatMenuRule', [
  373. 'params' => $params,
  374. 'errmsg' => $exception->getMessage(),
  375. 'file' => $exception->getFile(),
  376. 'line' => $exception->getLine(),
  377. 'trace' => $exception->getTraceAsString(),
  378. ],'interface');
  379. return ['添加失败', 400];
  380. }
  381. }
  382. public static function chatMenuRuleList($params)
  383. {
  384. try{
  385. $offset = ($params['page'] - 1) * $params['page_size'];
  386. $query = ChatMenuRule::query()
  387. ->where('corpid', $params['corpid'])
  388. ->where('sys_group_id', $params['sys_group_id'])
  389. ->where('enable', 1);
  390. if(!empty($params['group_id'])) {
  391. $query->where('group_id', $params['group_id']);
  392. }
  393. if(!empty($params['title'])) {
  394. $query->where('title', 'like', '%'.$params['title'].'%');
  395. }
  396. $count = $query->count();
  397. $data = $query->select(['group_id', 'title', 'sort_order'])
  398. ->selectRaw('id as rule_id')
  399. ->orderBy('sort_order', 'desc')
  400. ->offset($offset)
  401. ->limit($params['page_size'])
  402. ->get();
  403. // 提取分组id,并获取分组名称
  404. $groupIdList = array_unique(array_column($data->toArray(), 'group_id'));
  405. $groupDataList = ChatMenuGroup::query()
  406. ->whereIn('id', $groupIdList)
  407. ->where('enable', 1)
  408. ->get();
  409. // 提取话术规则id
  410. $ruleIdList = array_column($data->toArray(), 'rule_id');
  411. // 根据规则id批量查询发送次数
  412. $ruleSendStatisticsData = ChatMenuRecord::getRuleSendStatistics($ruleIdList);
  413. // 根据规则id获取下边所有的消息内容
  414. $newRuleMsgList = ChatMenuMsg::getMsgListByRuleId($ruleIdList);
  415. // 数据拼接
  416. foreach($data as &$val) {
  417. // 分组
  418. $groupInfo = $groupDataList->where('id', $val->group_id)->first();
  419. $val->group_name = !empty($groupInfo->group_name) ? $groupInfo->group_name : null;
  420. // 统计
  421. $statistcsInfo = $ruleSendStatisticsData->where('rule_id', $val->rule_id)->first();
  422. $val->send_num = !empty($statistcsInfo->count) ? $statistcsInfo->count : 0;
  423. // 话术内容以及类型
  424. $msgList = isset($newRuleMsgList[$val->rule_id]) ? $newRuleMsgList[$val->rule_id] : [];
  425. $msgList['chat_type'] = array_unique($msgList['chat_type']);
  426. $val->chat_type_name = isset($msgList['chat_type']) ?
  427. (count($msgList['chat_type']) > 1 ? '复合类型' : ChatMenuMsg::CHAT_TYPE[$msgList['chat_type'][0]]) : null;
  428. $val->chat_message = isset($msgList['chat_message']) ? $msgList['chat_message'] : [];
  429. }
  430. return [$data, $count];
  431. } catch (\Exception $exception) {
  432. Log::logError('chatMenuRuleList', [
  433. 'params' => $params,
  434. 'errmsg' => $exception->getMessage(),
  435. 'file' => $exception->getFile(),
  436. 'line' => $exception->getLine(),
  437. 'trace' => $exception->getTraceAsString(),
  438. ],'interface');
  439. return [[], 0];
  440. }
  441. }
  442. /**
  443. * 侧边栏快捷话术信息列表
  444. * */
  445. public static function chatMenuRuleListForH5($params)
  446. {
  447. try{
  448. $query = ChatMenuRule::where('corpid', $params['corpid'])
  449. ->where('group_id', $params['group_id'])
  450. ->where('enable', 1);
  451. if(isset($params['title']) && $params['title']) {
  452. $query->where('title', 'like', '%'.$params['title'].'%');
  453. }
  454. $count = $query->count();
  455. $ruleList = $query->selectRaw('id as rule_id, title, sort_order')
  456. ->orderBy('sort_order', 'desc')
  457. ->offset(($params['page'] - 1) * $params['page_size'])
  458. ->limit($params['page_size'])
  459. ->get();
  460. // 提取快捷话术信息
  461. $ruleIdList = $ruleList->pluck('rule_id');
  462. $ruleMsgList = ChatMenuMsg::selectRaw('id as msg_id, rule_id, chat_type, chat_message')
  463. ->whereIn('rule_id', $ruleIdList)->where('enable', 1)->get();
  464. foreach($ruleList as $rule) {
  465. $msgList = $ruleMsgList->where('rule_id', $rule->rule_id)->all();
  466. $rule->msg_list = array_values($msgList);
  467. }
  468. } catch (\Exception $exception) {
  469. Log::logError('chatMenuRuleListForH5', [
  470. 'params' => $params,
  471. 'errmsg' => $exception->getMessage(),
  472. 'file' => $exception->getFile(),
  473. 'line' => $exception->getLine(),
  474. 'trace' => $exception->getTraceAsString(),
  475. ],'interface');
  476. return [[], 0];
  477. }
  478. return [$ruleList, $count];
  479. }
  480. public static function chatMenuRuleDetail($params)
  481. {
  482. try{
  483. $chatMenuRule = ChatMenuRule::query()
  484. ->select(['group_id', 'title'])
  485. ->selectRaw('id as rule_id')
  486. ->where('id', $params['rule_id'])
  487. ->where('enable', 1)
  488. ->first();
  489. if(empty($chatMenuRule)) {
  490. return [[], 3002];
  491. }
  492. $chatMenuRule = json_decode(json_encode($chatMenuRule), 1);
  493. $newRuleMsgList = ChatMenuMsg::getMsgListByRuleId([$params['rule_id']]);
  494. $chatMenuRule['msg_list'] = $newRuleMsgList[$params['rule_id']]['chat_message'];
  495. $chatMenuRule['group_id'] = empty($chatMenuRule['group_id']) ? null : $chatMenuRule['group_id'];
  496. return [$chatMenuRule, 0];
  497. } catch (\Exception $exception) {
  498. Log::logError('chatMenuRuleList', [
  499. 'params' => $params,
  500. 'errmsg' => $exception->getMessage(),
  501. 'file' => $exception->getFile(),
  502. 'line' => $exception->getLine(),
  503. 'trace' => $exception->getTraceAsString(),
  504. ],'interface');
  505. return [[], 400];
  506. }
  507. }
  508. public static function updateChatMenuRuleSortOrder($params)
  509. {
  510. try{
  511. // 查询被操作分组原始排序值
  512. $operatorRule = ChatMenuRule::query()
  513. ->where('id', $params['operate_rule_id'])
  514. ->first();
  515. $operatorRuleOriginalSortOrder = $operatorRule->sort_order;
  516. if(!empty($params['behind_rule_id']) && empty($params['front_rule_id'])) {
  517. // 上移到第一位,判断是否有调整后的排在调整分组后面的分组id
  518. $behindRule = ChatMenuRule::query()
  519. ->where('id', $params['behind_rule_id'])
  520. ->first();
  521. $behindRuleOriginalSortOrder = $behindRule->sort_order;
  522. list($data, $code) = self::radarRuleMoveUp($params, $behindRuleOriginalSortOrder, $operatorRuleOriginalSortOrder);
  523. return [$data, $code];
  524. } else if(!empty($params['front_rule_id']) && empty($params['behind_rule_id'])) {
  525. // 下移到最后一位,判断是否有调整后的排在调整分组前面的分组id
  526. $frontRule = ChatMenuRule::query()
  527. ->where('id', $params['front_rule_id'])
  528. ->first();
  529. $frontRuleOriginalSortOrder = $frontRule->sort_order;
  530. list($data, $code) = self::radarRuleMoveDown($params, $frontRuleOriginalSortOrder, $operatorRuleOriginalSortOrder);
  531. return [$data, $code];
  532. } else if(!empty($params['front_rule_id']) && !empty($params['behind_rule_id'])) {
  533. $frontRule = ChatMenuRule::query()
  534. ->where('id', $params['front_rule_id'])
  535. ->first();
  536. $frontRuleOriginalSortOrder = $frontRule->sort_order;
  537. $behindRule = ChatMenuRule::query()
  538. ->where('id', $params['behind_rule_id'])
  539. ->first();
  540. $behindRuleOriginalSortOrder = $behindRule->sort_order;
  541. if($operatorRuleOriginalSortOrder > $frontRuleOriginalSortOrder) {
  542. // 下移
  543. list($data, $code) = self::radarRuleMoveDown($params, $frontRuleOriginalSortOrder, $operatorRuleOriginalSortOrder);
  544. } else {
  545. // 上移
  546. list($data, $code) = self::radarRuleMoveUp($params, $behindRuleOriginalSortOrder, $operatorRuleOriginalSortOrder);
  547. }
  548. return [$data, $code];
  549. } else {
  550. Log::logError('updateChatMenuRuleSortOrder', [
  551. 'params' => $params,
  552. 'message' => '被操作话术规则前后规则id不可同时为空',
  553. ],'interface');
  554. return [['error' => '被操作话术规则前后规则id不可同时为空'], 3507];
  555. }
  556. } catch (\Exception $exception) {
  557. Log::logError('updateChatMenuRuleSortOrder', [
  558. 'params' => $params,
  559. 'file' => $exception->getFile(),
  560. 'line' => $exception->getLine(),
  561. 'message' => $exception->getMessage(),
  562. 'trace' => $exception->getTraceAsString(),
  563. ], 'interface');
  564. return ['移动失败', 400];
  565. }
  566. }
  567. // 话术规则上移
  568. public static function radarRuleMoveUp($params, $behindRuleOriginalSortOrder, $operatorRuleOriginalSortOrder)
  569. {
  570. \DB::begintransaction();
  571. $moveRes = ChatMenuRule::query()
  572. ->where('corpid', $params['corpid'])
  573. ->where('sys_group_id', $params['sys_group_id'])
  574. ->where('enable', 1)
  575. ->where('sort_order', '<=', $behindRuleOriginalSortOrder)
  576. ->where('sort_order', '>', $operatorRuleOriginalSortOrder)
  577. ->decrement('sort_order');// 自减1
  578. $operatorRes = ChatMenuRule::query()
  579. ->where('id', $params['operate_rule_id'])
  580. ->update(['sort_order' => $behindRuleOriginalSortOrder]);
  581. if($moveRes && $operatorRes) {
  582. \DB::commit();
  583. return ['移动成功', 0];
  584. } else {
  585. \DB::rollBack();
  586. Log::logError('updateChatMenuRuleSortOrder', [
  587. 'params' => $params,
  588. 'message' => '移动失败',
  589. 'move_res' => $moveRes,
  590. 'operator_res' => $operatorRes,
  591. 'operator_sort_order' => $operatorRuleOriginalSortOrder,
  592. 'behind_sort_order' => $behindRuleOriginalSortOrder,
  593. ],'interface');
  594. return ['移动失败', 400];
  595. }
  596. }
  597. // 话术规则下移
  598. public static function radarRuleMoveDown($params, $frontRuleOriginalSortOrder, $operatorRuleOriginalSortOrder)
  599. {
  600. \DB::begintransaction();
  601. $moveRes = ChatMenuRule::query()
  602. ->where('corpid', $params['corpid'])
  603. ->where('sys_group_id', $params['sys_group_id'])
  604. ->where('enable', 1)
  605. ->where('sort_order', '>=', $frontRuleOriginalSortOrder)
  606. ->where('sort_order', '<', $operatorRuleOriginalSortOrder)
  607. ->increment('sort_order');// 自增1
  608. $operatorRes = ChatMenuRule::query()
  609. ->where('id', $params['operate_rule_id'])
  610. ->update(['sort_order' => $frontRuleOriginalSortOrder]);
  611. if($moveRes && $operatorRes) {
  612. \DB::commit();
  613. return ['移动成功', 0];
  614. } else {
  615. \DB::rollBack();
  616. Log::logError('updateChatMenuRuleSortOrder', [
  617. 'params' => $params,
  618. 'message' => '移动失败',
  619. 'move_res' => $moveRes,
  620. 'operator_res' => $operatorRes,
  621. 'operator_sort_order' => $operatorRuleOriginalSortOrder,
  622. 'front_sort_order' => $frontRuleOriginalSortOrder,
  623. ],'interface');
  624. return ['移动失败', 400];
  625. }
  626. }
  627. public static function deleteChatMenuRule($params)
  628. {
  629. try{
  630. \DB::begintransaction();
  631. $ruleRes = ChatMenuRule::query()
  632. ->where('id', $params['rule_id'])
  633. ->update([
  634. 'enable' => 0
  635. ]);
  636. $msgCount = ChatMenuMsg::query()
  637. ->where('rule_id', $params['rule_id'])
  638. ->where('enable', 1)
  639. ->count();
  640. // 防止出现本来雷达组下就没有雷达,更新不到数据导致整体删除失败
  641. if($msgCount > 0) {
  642. $msgRes = ChatMenuMsg::query()
  643. ->where('rule_id', $params['rule_id'])
  644. ->where('enable', 1)
  645. ->update(['enable' => 0]);
  646. } else {
  647. $msgRes = true;
  648. }
  649. if($ruleRes && $msgRes) {
  650. \DB::commit();
  651. return ['删除成功', 0];
  652. } else {
  653. \DB::rollBack();
  654. Log::logError('deleteChatMenuRule', [
  655. 'params' => $params,
  656. 'message' => '删除失败',
  657. 'rule_res' => $ruleRes,
  658. 'msg_res' => $msgRes,
  659. ],'interface');
  660. return ['删除失败', 400];
  661. }
  662. } catch (\Exception $exception) {
  663. Log::logError('deleteChatMenuRule', [
  664. 'params' => $params,
  665. 'file' => $exception->getFile(),
  666. 'line' => $exception->getLine(),
  667. 'message' => $exception->getMessage(),
  668. 'trace' => $exception->getTraceAsString(),
  669. ], 'interface');
  670. return ['删除失败', 400];
  671. }
  672. }
  673. public static function updateChatMenuRule($params)
  674. {
  675. try{
  676. // 解析话术消息
  677. $msgData = json_decode($params['msg_data_list'], 1);
  678. if(count($msgData) > 9) {
  679. Log::logError('updateChatMenuRule', [
  680. 'params' => $params,
  681. 'errmsg' => '最多添加9条话术内容',
  682. ],'interface');
  683. return [['error' => '最多添加9条话术内容'], 3505];
  684. }
  685. if(empty($msgData)) {
  686. Log::logError('updateChatMenuRule', [
  687. 'params' => $params,
  688. 'errmsg' => '最少添加1条话术内容',
  689. ],'interface');
  690. return [['error' => '最少添加1条话术内容'], 3506];
  691. }
  692. \DB::begintransaction();
  693. //保存话术规则
  694. $chatMenuRule = new ChatMenuRule();
  695. $chatMenuRule = $chatMenuRule->find($params['rule_id']);
  696. $chatMenuRule->group_id = empty($params['group_id']) ? 0 : $params['group_id'];
  697. $chatMenuRule->title = $params['title'];
  698. if($chatMenuRule->save()){
  699. // 提取消息id
  700. $msgIdList = array_column($msgData, 'msg_id');
  701. // 将不属于本次消息中的消息删除
  702. $count = ChatMenuMsg::query()
  703. ->where('rule_id', $params['rule_id'])
  704. ->where('enable', 1)
  705. ->whereNotIn('id', $msgIdList)
  706. ->count();
  707. if($count > 0) {
  708. $res = ChatMenuMsg::query()
  709. ->where('rule_id', $params['rule_id'])
  710. ->where('enable', 1)
  711. ->whereNotIn('id', $msgIdList)
  712. ->update(['enable' => 0]);
  713. if(!$res) {
  714. Log::logError('updateChatMenuRule', [
  715. 'params' => $params,
  716. 'chat_menu_rule' => (array)$chatMenuRule,
  717. 'chat_menu_msg_del_res' => (array)$res,
  718. 'errmsg' => '编辑失败,删除消息失败',
  719. ],'interface');
  720. \DB::rollBack();
  721. // 添加失败
  722. return ['编辑失败', 400];
  723. }
  724. }
  725. //分类型保存话术消息
  726. foreach ($msgData as $msgInfo) {
  727. $res = ChatMenuMsg::saveData($msgInfo['msg_id'], $msgInfo['chat_type'], $msgInfo,
  728. $params['corpid'], $params['sys_group_id'], $params['rule_id']);
  729. if(!$res) {
  730. Log::logError('updateChatMenuRule', [
  731. 'params' => $params,
  732. 'chat_menu_rule' => (array)$chatMenuRule,
  733. 'chat_menu_msg_save_res' => (array)$res,
  734. 'errmsg' => '编辑失败,消息保存失败',
  735. ],'interface');
  736. \DB::rollBack();
  737. // 添加失败
  738. return ['编辑失败', 400];
  739. }
  740. }
  741. \DB::commit();
  742. return ['编辑成功', 0];
  743. } else {
  744. Log::logError('updateChatMenuRule', [
  745. 'params' => $params,
  746. 'chat_menu_rule' => (array)$chatMenuRule,
  747. 'chat_menu_msg' => [],
  748. 'errmsg' => '添加失败,规则保存失败',
  749. ],'interface');
  750. \DB::rollBack();
  751. // 添加失败
  752. return ['编辑失败', 400];
  753. }
  754. } catch (\Exception $exception) {
  755. Log::logError('updateChatMenuRule', [
  756. 'params' => $params,
  757. 'errmsg' => $exception->getMessage(),
  758. 'file' => $exception->getFile(),
  759. 'line' => $exception->getLine(),
  760. 'trace' => $exception->getTraceAsString(),
  761. ],'interface');
  762. return ['编辑失败', 400];
  763. }
  764. }
  765. /**
  766. * 快捷回复处理成可发送的数据结构
  767. * */
  768. public static function getChatMessage($params, &$errno)
  769. {
  770. try {
  771. if($params['type'] == 1) {
  772. $msgInfo = ChatMenuMsg::select(['chat_type', 'chat_message', 'corpid'])->where('corpid', $params['corpid'])
  773. ->where('rule_id', $params['rule_id'])->where('id', $params['msg_id'])
  774. ->where('enable', 1)->first();
  775. } else {
  776. $msgInfo = UserSopMsg::selectRaw("msg_type as chat_type, content as chat_message, corpid")
  777. ->where('corpid', $params['corpid'])
  778. ->where('rule_id', $params['rule_id'])->where('id', $params['msg_id'])
  779. ->where('enable', 1)->first();
  780. $chatType = $msgInfo->chat_type ?? '';
  781. $message = json_decode($msgInfo->chat_message, true);
  782. # 处理数据
  783. switch($chatType) {
  784. case 1:
  785. $chatMessage = [
  786. "msgtype" => "text",
  787. "text" => $message
  788. ];
  789. break;
  790. case 2:
  791. $chatMessage= [
  792. "msgtype" => "image",
  793. "image" => $message
  794. ];
  795. break;
  796. case 3:
  797. $chatMessage = [
  798. "msgtype" => "video",
  799. "video" => $message
  800. ];
  801. break;
  802. case 4:
  803. $chatMessage = [
  804. "msgtype" => "file",
  805. "file" => $message
  806. ];
  807. break;
  808. case 5:
  809. $chatMessage = [
  810. "msgtype" => "news",
  811. "news" => $message
  812. ];
  813. break;
  814. case 6:
  815. $chatMessage = [
  816. "msgtype" => "miniprogram",
  817. "miniprogram" => $message
  818. ];
  819. break;
  820. }
  821. $msgInfo->chat_message = json_encode($chatMessage);
  822. }
  823. if(empty($msgInfo)) {
  824. $errno = 3501;
  825. return [];
  826. }
  827. $corpid = $msgInfo->corpid ?? '';
  828. $chatType = $msgInfo->chat_type ?? 0;
  829. $chatMessage = $msgInfo->chat_message ? json_decode($msgInfo->chat_message, true) : [];
  830. if(in_array($chatType, [2, 3, 4])) { // 图片、视频、文件类获取对应素材ID
  831. $mediaType = $chatType == 2 ? 1 : $chatType;
  832. $materialId = $chatMessage[$chatMessage['msgtype']]['mediaid'];
  833. $mediaId = MaterialService::getMediaId($materialId, $corpid, false, $mediaType);
  834. if($mediaId===false) {
  835. Log::logInfo('临时素材ID获取失败', [
  836. 'chatMessage' => $chatMessage,
  837. 'corpid' => $corpid
  838. ], 'ChatMenuMsgDealTrace');
  839. $errno = 3503;
  840. return [];
  841. }
  842. $chatMessage[$chatMessage['msgtype']]['mediaid'] = $mediaId;
  843. }
  844. } catch(\Exception $e) {
  845. EmailQueue::rPush('快捷回复信息处理成链接类型消息体过程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'],
  846. '快捷回复信息处理成链接类型消息体过程发生异常');
  847. Log::logError('快捷回复信息处理成链接类型消息体过程发生异常', [
  848. 'line' => $e->getLine(),
  849. 'msg' => $e->getMessage()
  850. ], 'ChatMenuMsgDealTrace');
  851. $errno = 3502;
  852. return [];
  853. }
  854. return $chatMessage;
  855. }
  856. /**
  857. * 快捷回复数据上报
  858. * */
  859. public static function behaviorReport($param)
  860. {
  861. try {
  862. if($param['external_userid'])
  863. $param['con_user_cus'] = $param['user_id'] . $param['external_userid'];
  864. # 行为数据存储
  865. $result = ChatMenuRecord::insert($param);
  866. if(!$result) {
  867. Log::logError('发送数据上报失败', [
  868. 'param' => $param,
  869. ], 'ChatMenuBehaviorReport');
  870. return 3504;
  871. }
  872. } catch (\Exception $e) {
  873. Log::logError('发送数据上报发生异常', [
  874. 'param' => $param,
  875. 'line' => $e->getLine(),
  876. 'msg' => $e->getMessage()
  877. ], 'ChatMenuBehaviorReport-Exception');
  878. return 3504;
  879. }
  880. return 0;
  881. }
  882. }