Message.php 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Description: 站内信
  4. // +----------------------------------------------------------------------
  5. // | Author: ymob
  6. // +----------------------------------------------------------------------
  7. namespace app\admin\model;
  8. use app\admin\model\ImportRecord as ImportRecordModel;
  9. use app\admin\model\User as UserModel;
  10. use app\crm\model\Contract as ContractModel;
  11. use app\crm\model\Invoice;
  12. use app\crm\model\Receivables as ReceivablesModel;
  13. use app\oa\model\Announcement as AnnouncementModel;
  14. use app\oa\model\Event as EventModel;
  15. use app\oa\model\Examine as ExamineModel;
  16. use app\oa\model\ExamineCategory;
  17. use app\oa\model\Log as LogModel;
  18. use app\work\model\Task as TaskModel;
  19. class Message extends Common
  20. {
  21. protected $name = 'admin_message';
  22. protected $autoWriteTimestamp = true;
  23. protected $createTime = 'send_time';
  24. protected $updateTime = false;
  25. /**
  26. * 错误信息
  27. */
  28. public $error = '';
  29. /**
  30. * 将要发送的消息内容
  31. */
  32. protected $content = '';
  33. /**
  34. * 消息类型
  35. */
  36. protected $type = 0;
  37. /**
  38. * 任务分配
  39. */
  40. const TASK_ALLOCATION = 1;
  41. /**
  42. * 任务邀请
  43. */
  44. const TASK_INVITE = 2;
  45. /**
  46. * 任务结束
  47. */
  48. const TASK_OVER = 3;
  49. /**
  50. * 回复日志
  51. */
  52. const LOG_REPLAY = 4;
  53. /**
  54. * 发送日志
  55. */
  56. const LOG_SEND = 5;
  57. /**
  58. * 审批待处理
  59. */
  60. const EXAMINE_TO_DO = 6;
  61. /**
  62. * 审批驳回
  63. */
  64. const EXAMINE_REJECT = 7;
  65. /**
  66. * 审批通过
  67. */
  68. const EXAMINE_PASS = 8;
  69. /**
  70. * 公告
  71. */
  72. const NOTICE_MESSAGE = 9;
  73. /**
  74. * 日程
  75. */
  76. const EVENT_MESSAGE = 10;
  77. /**
  78. * 合同待审批
  79. */
  80. const CONTRACT_TO_DO = 11;
  81. /**
  82. * 合同审批驳回
  83. */
  84. const CONTRACT_REJECT = 12;
  85. /**
  86. * 合同审批通过
  87. */
  88. const CONTRACT_PASS = 13;
  89. /**
  90. * 回款待审批
  91. */
  92. const RECEIVABLES_TO_DO = 14;
  93. /**
  94. * 回款审批驳回
  95. */
  96. const RECEIVABLES_REJECT = 15;
  97. /**
  98. * 回款审批通过
  99. */
  100. const RECEIVABLES_PASS = 16;
  101. /**
  102. * 客户导入
  103. */
  104. const IMPORT_CUSTOMER = 17;
  105. /**
  106. * 联系人
  107. */
  108. const IMPORT_CONTACTS = 18;
  109. /**
  110. * 线索
  111. */
  112. const IMPORT_LEADS = 19;
  113. /**
  114. * 产品
  115. */
  116. const IMPORT_PRODUCT = 20;
  117. /**
  118. * 团队成员-客户
  119. */
  120. const TEAM_CUSTOMER = 21;
  121. /**
  122. * 团队成员-商机
  123. */
  124. const TEAM_BUSINESS = 22;
  125. /**
  126. * 团队成员-合同
  127. */
  128. const TEAM_CONTRACT = 23;
  129. /**
  130. * 发票待审批
  131. */
  132. const INVOICE_TO_DO = 24;
  133. /**
  134. * 发票审批驳回
  135. */
  136. const INVOICE_REJECT = 25;
  137. /**
  138. * 发票审批通过
  139. */
  140. const INVOICE_PASS = 26;
  141. /**
  142. * 项目任务导入
  143. */
  144. const IMPORT_TASK = 27;
  145. /**
  146. * 退出商机团队
  147. */
  148. const BUSINESS_PASS = 28;
  149. /**
  150. * 退出客户团队
  151. */
  152. const CUSTOMER_PASS = 29;
  153. /**
  154. * 退出合同团队
  155. */
  156. const CONTRACT_END = 30;
  157. /**
  158. * 移除团队成员
  159. */
  160. const TEAM_END = 31;
  161. /**
  162. * 移除队成员
  163. */
  164. const TEAM_LEADS = 32;
  165. /**
  166. * 消息类型
  167. *
  168. * @var array
  169. * @author Ymob
  170. * @datetime 2019-10-17 15:27:43
  171. */
  172. protected $typeList = [
  173. 1 => [
  174. 'template' => '{from_user} 将 {title} 任务分配给您,请及时查看。',
  175. ],
  176. 2 => [
  177. 'template' => '{from_user} 邀请您参与 {title} 任务,请及时查看。',
  178. ],
  179. 3 => [
  180. 'template' => '{from_user} 将 {title} 任务标记结束。',
  181. ],
  182. 4 => [
  183. 'template' => '{from_user} 回复了您的 {title} 日志:“今天工作状态不错,继续加油!”,请及时查看',
  184. ],
  185. 5 => [
  186. 'template' => '{from_user} 将日志 {title} 发送给您,请及时查看。',
  187. ],
  188. 6 => [
  189. 'template' => '{from_user} 提交 {title} 审批,请及时处理。',
  190. ],
  191. 7 => [
  192. 'template' => '{from_user} 拒绝您的 {title} 审批,拒绝理由:“日期填写错误”,请及时处理。',
  193. ],
  194. 8 => [
  195. 'template' => '{from_user} 已经审核通过您的 {title} ,请及时查看。',
  196. ],
  197. 9 => [
  198. 'template' => '您有一个新公告 {title} ,请及时查看。',
  199. ],
  200. 10 => [
  201. 'template' => '{from_user} 邀请您参与 {title} 日程,将于**分钟后开始,请及时查看。',
  202. ],
  203. 11 => [
  204. 'template' => '{from_user} 提交 {title} 合同审批待您处理,请及时查看。',
  205. ],
  206. 12 => [
  207. 'template' => '{from_user} 拒绝您的 {title} 合同审批,拒绝理由:“日期填写错误”,请及时处理。',
  208. ],
  209. 13 => [
  210. 'template' => '{from_user} 已经审核通过您的 {title} 合同,请及时查看',
  211. ],
  212. 14 => [
  213. 'template' => '{from_user} 提交 {title} 回款审批待您处理,请及时查看。',
  214. ],
  215. 15 => [
  216. 'template' => '{from_user} 拒绝您的 {title} 回款审批,拒绝理由:“日期填写错误”,请及时处理。',
  217. ],
  218. 16 => [
  219. 'template' => '{from_user} 已经审核通过您的 {title} 回款,请及时查看。',
  220. ],
  221. 17 => [
  222. // 'template' => '{from_user} 导入客户数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
  223. 'template' => '{total},{cover},{success},{error}',
  224. ],
  225. 18 => [
  226. // 'template' => '{from_user} 导入联系人数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
  227. 'template' => '{total},{cover},{success},{error}',
  228. ],
  229. 19 => [
  230. // 'template' => '{from_user} 导入线索数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
  231. 'template' => '{total},{cover},{success},{error}',
  232. ],
  233. 20 => [
  234. // 'template' => '{from_user} 导入产品数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
  235. 'template' => '{total},{cover},{success},{error}',
  236. ],
  237. 21 => [
  238. 'template' => '{from_user} 将您添加为客户 {title} 的成员。',
  239. ],
  240. 22 => [
  241. 'template' => '{from_user} 将您添加为商机 {title} 的成员。',
  242. ],
  243. 23 => [
  244. 'template' => '{from_user} 将您添加为合同 {title} 的成员。',
  245. ],
  246. 24 => [
  247. 'template' => '{from_user} 提交 {title} 发票审批待您处理,请及时查看。',
  248. ],
  249. 25 => [
  250. 'template' => '{from_user} 拒绝您的 {title} 发票审批,请及时处理。',
  251. ],
  252. 26 => [
  253. 'template' => '您的 {title} 发票已经审批通过,请及时查看。',
  254. ],
  255. 27 => [
  256. // 'template' => '{date},{from_user} 导入任务,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。{title}',
  257. 'template' => '{total},{cover},{success},{error}',
  258. ],
  259. 28 => [
  260. 'template' => '{from_user} 退出了您商机 {title} 的团队。',
  261. ],
  262. 29 => [
  263. 'template' => '{from_user} 退出了您客户 {title} 的团队。',
  264. ],
  265. 30 => [
  266. 'template' => '{from_user} 退出了您合同 {title} 的团队。',
  267. ],
  268. 31 => [
  269. 'template' => '将{from_user} 移除了您 {title} 的团队。',
  270. ],
  271. 32 => [
  272. 'template' => '{from_user} 将您添加为线索 {title} 的成员。',
  273. ],
  274. ];
  275. /**
  276. * 消息类型分组
  277. */
  278. public static $typeGroup = [
  279. 'announcement' => [
  280. self::NOTICE_MESSAGE,
  281. ],
  282. 'examine' => [
  283. self::EXAMINE_TO_DO,
  284. self::EXAMINE_REJECT,
  285. self::EXAMINE_PASS,
  286. ],
  287. 'task' => [
  288. self::TASK_ALLOCATION,
  289. self::TASK_INVITE,
  290. self::TASK_OVER,
  291. self::IMPORT_TASK,
  292. ],
  293. 'log' => [
  294. self::LOG_REPLAY,
  295. self::LOG_SEND,
  296. ],
  297. 'event' => [
  298. self::EVENT_MESSAGE,
  299. ],
  300. 'crm' => [
  301. self::CONTRACT_TO_DO,
  302. self::CONTRACT_REJECT,
  303. self::CONTRACT_PASS,
  304. self::RECEIVABLES_TO_DO,
  305. self::RECEIVABLES_REJECT,
  306. self::RECEIVABLES_PASS,
  307. self::IMPORT_CUSTOMER,
  308. self::IMPORT_CONTACTS,
  309. self::IMPORT_LEADS,
  310. self::IMPORT_PRODUCT,
  311. self::TEAM_CUSTOMER,
  312. self::TEAM_BUSINESS,
  313. self::TEAM_CONTRACT,
  314. self::INVOICE_TO_DO,
  315. self::INVOICE_REJECT,
  316. self::INVOICE_PASS,
  317. self::BUSINESS_PASS,
  318. self::CUSTOMER_PASS,
  319. self::CONTRACT_END,
  320. ]
  321. ];
  322. /**
  323. * 发送系统通知
  324. *
  325. * @param int $type 消息类型
  326. * @param array $data 关联信息
  327. * @param array|int $user_id 接收消息员工ID
  328. * @param boolean $system 是否系统消息
  329. * @return bool
  330. * @author Ymob
  331. * @datetime 2019-10-17 17:23:05
  332. */
  333. public function send($type, $data, $user_id_list, $system = false)
  334. {
  335. if (!isset($this->typeList[$type])) {
  336. $this->error = '消息类型错误';
  337. return false;
  338. }
  339. $user_id_list = (array)$user_id_list;
  340. $user_id_list = array_unique(array_filter($user_id_list));
  341. if (empty($user_id_list)) {
  342. $this->error = '接收人不能为空';
  343. return false;
  344. }
  345. $action_id = $data['action_id'];
  346. $title = $data['title'];
  347. $content = $this->typeList[$type]['template'];
  348. foreach ($data as $key => $val) {
  349. $content = str_replace('{' . $key . '}', $val, $content);
  350. }
  351. $advance_time= $data['advance_time'];
  352. $content = str_replace('{from_user}', User::userInfo('realname'), $content);
  353. $content = str_replace('{date}', date('Y-m-d'), $content);
  354. $data = [];
  355. $data['type'] = $type;
  356. $data['content'] = $content;
  357. $data['action_id'] = $action_id;
  358. $data['read_time'] = 0;
  359. $data['from_user_id'] = $system ? 0 : User::userInfo('id');
  360. $data['title'] = $title;
  361. $data['advance_time'] = $advance_time ?: 0;
  362. $request = request();
  363. $data['controller_name'] = strtolower($request->controller());
  364. $data['module_name'] = strtolower($request->module());
  365. $data['action_name'] = strtolower($request->action());
  366. $from_user_id = $data['from_user_id'];
  367. if (!in_array($type,[9,17,18,19,20,27])) {
  368. $user_id_list = array_filter($user_id_list, function ($val) use ($from_user_id) {
  369. return $val !== $from_user_id;
  370. });
  371. }
  372. $all_data = [];
  373. foreach ($user_id_list as $user_id) {
  374. $temp = $data;
  375. $temp['to_user_id'] = $user_id;
  376. $all_data[] = $temp;
  377. }
  378. if (!empty($from_user_id) && class_exists('DingTalk')) {
  379. (new Dingtalk())->message($user_id_list, $content);
  380. }
  381. $this->saveAll($all_data);
  382. }
  383. /**
  384. * 获取关联模块数据
  385. *
  386. * @author Ymob
  387. * @datetime 2019-10-22 15:34:35
  388. */
  389. public function getRelationTitleAttr($val, $data)
  390. {
  391. switch ($data['type']) {
  392. // 任务
  393. case self::TASK_ALLOCATION:
  394. case self::TASK_INVITE:
  395. case self::TASK_OVER:
  396. return TaskModel::where(['task_id' => $data['action_id']])->value('name') ?: '';
  397. // 日志
  398. case self::LOG_REPLAY:
  399. case self::LOG_SEND:
  400. return LogModel::where(['log_id' => $data['action_id']])->value('title') ?: '';
  401. // 审批
  402. case self::EXAMINE_TO_DO:
  403. case self::EXAMINE_REJECT:
  404. case self::EXAMINE_PASS:
  405. $category_id = ExamineModel::where(['examine_id' => $data['action_id']])->value('category_id') ?: 0;
  406. $categoryInfo = (new ExamineCategory())->getDataById($category_id);
  407. return $categoryInfo['title'];
  408. // 公告
  409. case self::NOTICE_MESSAGE:
  410. return AnnouncementModel::where(['announcement_id' => $data['action_id']])->value('title') ?: '';
  411. // 日程
  412. case self::EVENT_MESSAGE:
  413. return EventModel::where(['event_id' => $data['action_id']])->value('title') ?: '';
  414. // 合同
  415. case self::CONTRACT_TO_DO:
  416. case self::CONTRACT_REJECT:
  417. case self::CONTRACT_PASS:
  418. case self::TEAM_CONTRACT:
  419. return ContractModel::where(['contract_id' => $data['action_id']])->value('name') ?: '';
  420. // 回款
  421. case self::RECEIVABLES_TO_DO:
  422. case self::RECEIVABLES_REJECT:
  423. case self::RECEIVABLES_PASS:
  424. return ReceivablesModel::where(['receivables_id' => $data['action_id']])->value('number') ?: '';
  425. // 发票
  426. case self::INVOICE_TO_DO:
  427. case self::INVOICE_REJECT:
  428. case self::INVOICE_PASS:
  429. return Invoice::where(['invoice_id' => $data['action_id']])->value('invoice_apple_number') ?: '';
  430. // 导入数据
  431. case self::IMPORT_CUSTOMER:
  432. case self::IMPORT_CONTACTS:
  433. case self::IMPORT_LEADS:
  434. case self::IMPORT_PRODUCT:
  435. case self::IMPORT_TASK:
  436. $error = ImportRecordModel::where(['id' => $data['action_id']])->value('error');
  437. return $error ? '点击下载错误数据' : '';
  438. // 客户
  439. case self::TEAM_CUSTOMER:
  440. case self::CUSTOMER_PASS:
  441. return CustomerModel::where(['customer_id' => $data['action_id']])->value('name') ?: '';
  442. // 商机
  443. case self::TEAM_BUSINESS:
  444. case self::BUSINESS_PASS:
  445. return BusinessModel::where(['business_id' => $data['action_id']])->value('name') ?: '';
  446. }
  447. return '';
  448. }
  449. /**
  450. * 发送人
  451. */
  452. public function getFromUserIdInfoAttr($val, $data)
  453. {
  454. return $data['from_user_id'] ? UserModel::getUserById($data['from_user_id']) : [];
  455. }
  456. }