AnalysisMessageJob.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. /*
  3. * This file is part of the ZhMead/laravel-logger.
  4. *
  5. * (c) Mead <751066209@qql.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace App\Jobs\Manage;
  11. use App\Repositories\Enums\Manage\AnalysisStatusEnum;
  12. use App\Repositories\Models\Manage\Category;
  13. use App\Repositories\Models\Manage\Message;
  14. use App\Repositories\Models\Manage\PreMessage;
  15. use App\Repositories\Models\Manage\Task;
  16. use App\Repositories\Models\Manage\TaskResult;
  17. use Carbon\Carbon;
  18. use Illuminate\Bus\Queueable;
  19. use Illuminate\Contracts\Queue\ShouldQueue;
  20. use Illuminate\Queue\InteractsWithQueue;
  21. use Illuminate\Support\Facades\DB;
  22. use Illuminate\Support\Facades\Log;
  23. class AnalysisMessageJob implements ShouldQueue
  24. {
  25. use InteractsWithQueue;
  26. use Queueable;
  27. private $recordId;
  28. /**
  29. * Create a new job instance.
  30. */
  31. public function __construct($recordId)
  32. {
  33. $this->recordId = $recordId;
  34. }
  35. /**
  36. * 确定任务应该超时的时间
  37. *
  38. * @return \DateTime
  39. */
  40. public function retryUntil()
  41. {
  42. return Carbon::now()->addHours(24);
  43. }
  44. public $tries = 1;
  45. public $timeout = 1440;
  46. /**
  47. * Execute the job.
  48. */
  49. public function handle()
  50. {
  51. $this->analysis();
  52. }
  53. /**
  54. * 导入数据
  55. * @return false|void
  56. */
  57. public function analysis()
  58. {
  59. $model = Task::query()->find($this->recordId);
  60. $model->status = AnalysisStatusEnum::IN;
  61. $model->save();
  62. $main_ids = $model->message_ids;
  63. $is_main = false;
  64. if (is_array($main_ids)) {
  65. $is_main = count($main_ids);
  66. }
  67. TaskResult::query()->where('task_id', $model->id)->delete();
  68. Message::query()->where('task_id', $model->id)->update(['task_id' => 0]);
  69. PreMessage::query()->where('task_id', $model->id)->forceDelete();
  70. TaskResult::query()->where('task_id', $model->id)->forceDelete();
  71. DB::beginTransaction();
  72. try {
  73. Log::error('*************分析数据中*****************');
  74. $type_ids = $model->type_ids;
  75. $category_id = $model->category_id;
  76. $start_date = $model->start_date;
  77. $end_date = $model->end_date;
  78. $deal_department_id = $model->department_id;
  79. $arr = [];
  80. if ($category_id) $arr = Category::byCategoryIdGetCategoryArr($category_id);
  81. $category_1_id = 0;
  82. $category_2_id = 0;
  83. $category_3_id = 0;
  84. $category_4_id = 0;
  85. $category_5_id = 0;
  86. if (count($arr) >= 1) $category_1_id = $arr[0];
  87. if (count($arr) >= 2) $category_2_id = $arr[1];
  88. if (count($arr) >= 3) $category_3_id = $arr[2];
  89. if (count($arr) >= 4) $category_3_id = $arr[3];
  90. if (count($arr) >= 5) $category_3_id = $arr[4];
  91. $messages = Message::query()
  92. ->when($type_ids, function ($query) use ($type_ids) {
  93. return $query->whereIn('type_id', $type_ids);
  94. })
  95. ->when($deal_department_id, function ($query) use ($deal_department_id) {
  96. return $query->whereIn('deal_department_id', $deal_department_id);
  97. })
  98. ->when($category_1_id, function ($query) use ($category_1_id) {
  99. return $query->where('category_1_id', $category_1_id);
  100. })
  101. ->when($category_2_id, function ($query) use ($category_2_id) {
  102. return $query->where('category_2_id', $category_2_id);
  103. })
  104. ->when($category_3_id, function ($query) use ($category_3_id) {
  105. return $query->where('category_3_id', $category_3_id);
  106. })
  107. ->when($category_4_id, function ($query) use ($category_4_id) {
  108. return $query->where('category_4_id', $category_4_id);
  109. })
  110. ->when($category_5_id, function ($query) use ($category_5_id) {
  111. return $query->where('category_5_id', $category_5_id);
  112. })
  113. ->when($start_date, function ($query) use ($start_date) {
  114. return $query->whereDate('complain_date', '>=', $start_date);
  115. })
  116. ->when($end_date, function ($query) use ($end_date) {
  117. return $query->whereDate('complain_date', '<', $end_date);
  118. })
  119. ->when($is_main, function ($query) use ($main_ids) {
  120. return $query->whereNotIn('id', $main_ids);
  121. })->whereNotIn('id', $main_ids)
  122. ->where("more_pid", 0)
  123. ->select(['id', 'keywords', 'type_id', 'category_1_id', 'category_2_id', 'category_3_id', 'category_4_id', 'category_5_id', 'name', 'mobile', 'address_name', 'address_id', 'body', 'complain_date', 'warn_type_id', 'deal_department_id'])
  124. ->get();
  125. $t = $messages->count();
  126. $dbMessage = false;
  127. if ($t <= 1) throw new \Exception('分析的数据量太小');
  128. if (!$is_main) {
  129. if ($t > 2) {
  130. $total = $this->C($messages->count(), 2);
  131. } else {
  132. $total = 1;
  133. }
  134. $dbMessage = $messages;
  135. } else {
  136. $dbMessage = Message::query()->whereIn('id', $main_ids)->where("more_pid", 0)->select(['id', 'keywords', 'type_id', 'category_1_id', 'category_2_id', 'category_3_id', 'category_4_id', 'category_5_id', 'name', 'mobile', 'address_name', 'address_id', 'body', 'complain_date', 'warn_type_id', 'deal_department_id'])->get();
  137. $total = $dbMessage->count() * $t;
  138. foreach ($dbMessage as $message) {
  139. $data = $message->toArray();
  140. $data['message_id'] = $data['id'];
  141. unset($data['id']);
  142. $data['task_id'] = $model->id;
  143. $data['is_check'] = 1;
  144. PreMessage::query()->create($data);
  145. }
  146. }
  147. foreach ($messages as $message) {
  148. $data = $message->toArray();
  149. $data['message_id'] = $data['id'];
  150. unset($data['id']);
  151. $data['task_id'] = $model->id;
  152. $data['is_check'] = 1;
  153. PreMessage::query()->create($data);
  154. }
  155. $model->nums = $total;
  156. $use_nums = 0;
  157. $rateData = [];
  158. $rateSData = [];
  159. foreach ($dbMessage as $k => $message) {
  160. foreach ($messages as $kk => $m) {
  161. if ($k >= $kk) continue;
  162. $rate = $this->get_similar_percent($message->keywords, $m->keywords);
  163. TaskResult::query()->create([
  164. 'task_id' => $model->id,
  165. 'message_1_id' => $message->id,
  166. 'message_2_id' => $m->id,
  167. 'rate' => $rate,
  168. 'is_match' => ($rate >= $model->rate) ? 1 : 0,
  169. ]);
  170. $use_nums++;
  171. if ($rate >= $model->rate) {
  172. if (in_array($m->id, $rateSData)) continue;
  173. $rateSData[] = $m->id;
  174. $rateData[$message->id][] = $m->id;
  175. }
  176. }
  177. $progress = bcdiv($use_nums, $total, 2) * 100;
  178. DB::table('manage_tasks')->where('id', $model->id)->update(['progress' => $progress]);
  179. }
  180. foreach ($rateData as $m_id => $ids) {
  181. //合并
  182. $mainMessage = PreMessage::query()->where('message_id', $m_id)->where('task_id', $model->id)->first();
  183. PreMessage::query()->whereIn('message_id', $ids)->where('task_id', $model->id)->update([
  184. 'pid' => $mainMessage->id,
  185. // 'task_id' => $model->id,
  186. 'is_check' => 0,
  187. ]);
  188. $mainMessage->similar_nums = count($ids);
  189. $mainMessage->is_check = 0;
  190. $mainMessage->is_main = 1;
  191. // $mainMessage->task_id = $model->id;
  192. $mainMessage->save();
  193. }
  194. DB::commit();
  195. $model->status = AnalysisStatusEnum::OK;
  196. $model->message = '执行成功';
  197. } catch (\Exception $exception) {
  198. DB::rollBack();
  199. Log::error($exception);
  200. $model->status = AnalysisStatusEnum::ERROR;
  201. $model->message = $exception;
  202. }
  203. $model->save();
  204. Log::error("-----------完成---------------");
  205. }
  206. /**
  207. * 相似度
  208. * @param $str1_arr
  209. * @param $str2_arr
  210. * @return float|int
  211. */
  212. function get_similar_percent($str1_arr, $str2_arr)
  213. {
  214. $res_arr = [];
  215. foreach ($str1_arr as $word) {
  216. if (!isset($res_arr[$word])) {
  217. $res_arr[$word] = ['A' => 1, 'B' => 0];
  218. } else {
  219. $res_arr[$word]['A'] += 1;
  220. }
  221. }
  222. foreach ($str2_arr as $word2) {
  223. if (!isset($res_arr[$word2])) {
  224. $res_arr[$word2] = ['A' => 0, 'B' => 1];
  225. } else {
  226. $res_arr[$word2]['B'] += 1;
  227. }
  228. }
  229. $x = 0;
  230. $y1 = 0;
  231. $y2 = 0;
  232. foreach ($res_arr as $v) {
  233. $x += $v['A'] * $v['B'];
  234. $y1 += $v['A'] * $v['A'];
  235. $y2 += $v['B'] * $v['B'];
  236. }
  237. return ($y1 == 0 || $y2 == 0) ? -1 : ($x / (sqrt($y1) * sqrt($y2))) * 100;
  238. }
  239. public function factorial($n)
  240. {
  241. return array_product(range(1, $n));
  242. }
  243. // 计算排列个数
  244. public function A($n, $m)
  245. {
  246. return $this->factorial($n) / $this->factorial($n - $m);
  247. }
  248. // 计算组合个数
  249. public function C($n, $m)
  250. {
  251. return $this->A($n, $m) / $this->factorial($m);
  252. }
  253. }