System.php 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. <?php
  2. namespace app\admin\controller;
  3. use app\admin\model\Office;
  4. use think\cache\driver\Redis;
  5. /**
  6. * 管理系统系统设置类
  7. */
  8. class System extends Base
  9. {
  10. /**
  11. * 基础设置
  12. *
  13. * @access public
  14. */
  15. public function basics()
  16. {
  17. $settings = db('settings')->find();
  18. // 表单提交.
  19. if (request()->isPost()) {
  20. $param = input('post.');
  21. try {
  22. // 修改系统欢迎语.
  23. if (empty($param['advertisement_img']) === false) {
  24. $updateAstData['advertisement_img'] = $param['advertisement_img'];
  25. }
  26. if (empty($param['logo_img']) === false) {
  27. $updateinfo['logo'] = $param['logo_img'];
  28. }
  29. $updateinfo['enterprise_name'] = $param['enterprise_name'];
  30. $updateinfo['visitor_url'] = $param['visitor_url'];
  31. $updateinfo['customer_url'] = $param['customer_url'];
  32. $updateinfo['backend_url'] = $param['backend_url'];
  33. $updateAstData['advertisement_url'] = $param['advertisementUrl'];
  34. $updateAstData['advertisement_status'] = $param['status'];
  35. model('Advertisement')->updateAst($updateAstData);
  36. /*// 修改系统欢迎语.
  37. $updateSysData['word'] = $param['systemWord'];
  38. $updateSysWhere['id'] = 1;
  39. model('Reply')->updateReply($updateSysWhere, $updateSysData);*/
  40. // 修改客服欢迎语.
  41. $updateSevData['word'] = $param['serverWord'];
  42. $updateSevWhere['id'] = 2;
  43. model('Reply')->updateReply($updateSevWhere, $updateSevData);
  44. if (!empty($updateinfo)) {
  45. db('settings')->where('id', 1)->update($updateinfo);
  46. $err = $this->updateJsTmpl($updateinfo);
  47. if ($err == -20003) {
  48. return json(['code' => -2, 'data' => '', 'msg' => 'JS调用模板路径不可以写']);
  49. }
  50. }
  51. return json(['code' => 1, 'data' => '', 'msg' => '设置成功']);
  52. } catch (\Exception $e) {
  53. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  54. }//end try
  55. }//end if
  56. // 获取广告.
  57. $advertisement = model('Advertisement')->findAst();
  58. /*// 获取系统欢迎语.
  59. $replySystemWhere['id'] = 1;
  60. $replySystem = model('Reply')->findReply($replySystemWhere);*/
  61. // 获取客服欢迎语.
  62. $replyServerWhere['id'] = 2;
  63. $replyServer = model('Reply')->findReply($replyServerWhere);
  64. // 获取logo.
  65. $this->assign(
  66. [
  67. 'advertisement' => $advertisement,
  68. //'replySystem' => $replySystem,
  69. 'replyServer' => $replyServer,
  70. 'settings' => $settings,
  71. 'socket' => config('socket'),
  72. 'status' => config('kf_status'),
  73. ]
  74. );
  75. return $this->fetch();
  76. }//end basics()
  77. public function updateJsTmpl($settings)
  78. {
  79. $src = ROOT_PATH . 'public/entranceJs/jstmpl.js';
  80. $tar = ROOT_PATH . 'public/entranceJs/FloatingButton.js';
  81. if (is_writable($tar) && is_readable($src)) {
  82. $content = file_get_contents($src);
  83. $content = str_replace('{VISITOR_DOMAIN}', $settings['visitor_url'], $content);
  84. $content = str_replace('{CUSTOMER_DOMAIN}', $settings['customer_url'], $content);
  85. $content = str_replace('{ADMIN_DOMAIN}', $settings['backend_url'], $content);
  86. file_put_contents($tar, $content);
  87. } else {
  88. return -20003;
  89. }
  90. }
  91. /**
  92. * 系统欢迎语
  93. *
  94. * @access public
  95. */
  96. public function welcoming()
  97. {
  98. if (request()->isAjax()) {
  99. $replySystemWhere['type'] = 1;
  100. $result = model('Reply')->selectReply($replySystemWhere);
  101. foreach ($result as $key => $vo) {
  102. // 生成操作按钮
  103. $result[$key]['operate'] = $this->makeBotton($vo['id']);
  104. $result[$key]['word'] = htmlspecialchars_decode($vo['word']);
  105. }
  106. $return['rows'] = $result;
  107. return json($return);
  108. }
  109. $this->assign([
  110. 'socket' => config('socket'),
  111. ]);
  112. return $this->fetch();
  113. }//end welcoming()
  114. /**
  115. * 修改系统欢迎语
  116. *
  117. * @access public
  118. */
  119. public function editWelcome()
  120. {
  121. if (request()->isAjax()) {
  122. $param = input('post.');
  123. $where['id'] = $param['id'];
  124. $data['sort'] = $param['sort'];
  125. $data['word'] = htmlspecialchars($param['word']);
  126. try {
  127. model('Reply')->updateReply($where, $data);
  128. } catch (\Exception $e) {
  129. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  130. }
  131. return json(['code' => 1, 'data' => '', 'msg' => '编辑成功']);
  132. }
  133. $id = input('param.id');
  134. $replySystemWhere['id'] = $id;
  135. $replySystem = model('Reply')->findReply($replySystemWhere);
  136. $this->assign([
  137. 'replySystem' => $replySystem,
  138. 'socket' => config('socket'),
  139. ]);
  140. return $this->fetch('editwelcome');
  141. }//end editWelcome()
  142. /**
  143. * 新增系统欢迎语
  144. *
  145. * @access public
  146. */
  147. public function delWelcome()
  148. {
  149. if (request()->isAjax()) {
  150. $id = input('param.id');
  151. $where['id'] = $id;
  152. try {
  153. model('Reply')->delReply($where);
  154. } catch (\Exception $e) {
  155. return json(['code' => -1, 'data' => '', 'msg' => $e->getMessage()]);
  156. }
  157. return json(['code' => 1, 'data' => '', 'msg' => '删除成功']);
  158. }
  159. }
  160. /**
  161. * 新增系统欢迎语
  162. *
  163. * @access public
  164. */
  165. public function addWelcome()
  166. {
  167. if (request()->isAjax()) {
  168. $param = input('post.');
  169. $data['sort'] = $param['sort'];
  170. $data['word'] = htmlspecialchars($param['word']);
  171. $data['status'] = 1;
  172. $data['type'] = 1;
  173. try {
  174. model('Reply')->addReply($data);
  175. } catch (\Exception $e) {
  176. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  177. }
  178. return json(['code' => 1, 'data' => '', 'msg' => '新增成功']);
  179. }
  180. $this->assign([
  181. 'socket' => config('socket'),
  182. ]);
  183. return $this->fetch('addwelcome');
  184. }//end addWelcome()
  185. /**
  186. * 会话设置
  187. *
  188. * @access public
  189. */
  190. public function conversation()
  191. {
  192. // 表单提交.
  193. if (request()->isPost()) {
  194. $param = input('post.');
  195. try {
  196. // 修改会话超时.
  197. $updateOvertimeData['systemconfig_data'] = $param['overtime'];
  198. $updateOvertimeData['systemconfig_content'] = $param['overtimeInfo'];
  199. $updateOvertimeWhere['systemconfig_id'] = 1;
  200. model('Systemconfig')->updateSystemconfig($updateOvertimeWhere, $updateOvertimeData);
  201. // 修改访客静默.
  202. $upUptdData['systemconfig_data'] = $param['unoperated'];
  203. $upUptdData['systemconfig_content'] = $param['unoperatedInfo'];
  204. $upUptdWhere['systemconfig_id'] = 2;
  205. model('Systemconfig')->updateSystemconfig($upUptdWhere, $upUptdData);
  206. // 质检会话时长设置.
  207. $upAllTimeData['systemconfig_data'] = $param['verifyAllTime'];
  208. $upAllTimeWhere['systemconfig_id'] = 3;
  209. model('Systemconfig')->updateSystemconfig($upAllTimeWhere, $upAllTimeData);
  210. // 质检会话响应时长设置.
  211. $upReturnTimeData['systemconfig_data'] = $param['verifyReturnTime'];
  212. $upReturnTimeWhere['systemconfig_id'] = 4;
  213. model('Systemconfig')->updateSystemconfig($upReturnTimeWhere, $upReturnTimeData);
  214. // 满意度评价回合限制.
  215. $upRoundData['systemconfig_data'] = $param['round'];
  216. $upRoundWhere['systemconfig_id'] = 5;
  217. model('Systemconfig')->updateSystemconfig($upRoundWhere, $upRoundData);
  218. // 客服接待人数设置.
  219. $upMSWhere['systemconfig_enName'] = 'KFMaxServices';
  220. $upMSData['systemconfig_data'] = $param['max_service'];
  221. model('Systemconfig')->updateSystemconfig($upMSWhere, $upMSData);
  222. // 最大排队人数设置.
  223. $upMWWhere['systemconfig_enName'] = 'maxWait';
  224. $upMWData['systemconfig_data'] = $param['kfConfig_maxWait'];
  225. model('Systemconfig')->updateSystemconfig($upMWWhere, $upMWData);
  226. return json(['code' => 1, 'data' => '', 'msg' => '设置成功']);
  227. } catch (\Exception $e) {
  228. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  229. }//end try
  230. }//end if
  231. // 获取设置.
  232. $systemconfig = model('Systemconfig')->selectSystemconfig();
  233. $this->assign(
  234. [
  235. 'systemconfig' => $systemconfig,
  236. 'status' => config('kf_status'),
  237. 'socket' => config('socket'),
  238. ]
  239. );
  240. return $this->fetch();
  241. }//end conversation()
  242. // 自动回复设置
  243. public function reply()
  244. {
  245. if (request()->isPost()) {
  246. $param = input('post.');
  247. if (empty($param['word'])) {
  248. return json(['code' => -1, 'data' => '', 'msg' => '回复内容不能为空']);
  249. }
  250. try {
  251. db('reply')->where('id', 1)->update($param);
  252. } catch (\Exception $e) {
  253. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  254. }
  255. return json(['code' => 1, 'data' => '', 'msg' => '设置成功']);
  256. }
  257. $info = db('reply')->where('id', 1)->find();
  258. $this->assign([
  259. 'info' => $info,
  260. 'socket' => config('socket'),
  261. 'status' => config('kf_status')
  262. ]);
  263. return $this->fetch();
  264. }
  265. // 历史会话记录
  266. public function wordsLog()
  267. {
  268. // $toExcel = input('param.toExcel', 0);
  269. if (request()->isAjax()) {
  270. $param = input('param.');
  271. $limit = $param['pageSize'];
  272. $offset = ($param['pageNumber'] - 1) * $limit;
  273. // 默认显示最近7天
  274. $start = input('param.start');
  275. $end = input('param.end');
  276. $user_id = input('param.user_id');
  277. $group_id = input('param.group_id');
  278. $temp = db('service_log');
  279. $countTmp = db('service_log');
  280. if (strlen($param['searchText'])) {
  281. $temp = $temp->whereLike('user_name', '%' . $param['searchText'] . '%');
  282. $countTmp = $countTmp->whereLike('user_name', '%' . $param['searchText'] . '%');
  283. }
  284. //日期
  285. if (!empty($start) && !empty($end) && $start <= $end) {
  286. $temp = $temp->whereBetween('start_time', [strtotime($start), strtotime($end . ' 23:59:59')]);
  287. $countTmp = $countTmp->whereBetween('start_time', [strtotime($start), strtotime($end . ' 23:59:59')]);
  288. }
  289. //结束时间为空
  290. if (!empty($start) && empty($end)) {
  291. $temp = $temp->where('start_time', '>', strtotime($start));
  292. $countTmp = $countTmp->where('start_time', '>', strtotime($start));
  293. }
  294. //开始时间为空
  295. if (empty($start) && !empty($end)) {
  296. $temp = $temp->where('start_time', '<', strtotime($end . ' 23:59:59'));
  297. $countTmp = $countTmp->where('start_time', '<', strtotime($end . ' 23:59:59'));
  298. }
  299. //客服
  300. if ($user_id != 0) {
  301. $temp = $temp->where('kf_id', $user_id);
  302. $countTmp = $countTmp->where('kf_id', $user_id);
  303. }
  304. //客服组
  305. if ($group_id != 0) {
  306. $temp = $temp->where('group_id', $group_id);
  307. $countTmp = $countTmp->where('group_id', $group_id);
  308. }
  309. $result = $temp->limit($offset, $limit)->order('start_time', 'desc')->select();
  310. //所有客服
  311. $users = db('users')->select();
  312. //所有客服组
  313. $groups = db('groups')->select();
  314. //满意度
  315. $evaluate = db('evaluate')->select();
  316. //$alarm报警信息
  317. $alarm = db('alarm')->select();
  318. foreach ($result as $key => $vo) {
  319. if ($result[$key]['intime'] != 0) {
  320. $result[$key]['intime'] = date('Y-m-d H:i:s', $vo['intime']);
  321. $date = explode(' ', $result[$key]['intime']);
  322. $year = explode('-', $result[$key]['intime']);
  323. if ($date[0] == date('Y-m-d', time())) {
  324. $result[$key]['intime'] = '<span style="float: right;">' . $date[1] . '</span>';
  325. } else if ($date[0] == date('Y-m-d', strtotime("-1 day"))) {
  326. $result[$key]['intime'] = '<span style="float: right;">' . '昨天 ' . $date[1] . '</span>';
  327. } else {
  328. if ($year[0] == date('Y', time())) {
  329. $result[$key]['intime'] = '<span style="float: right;">' . date('m-d H:i:s', strtotime($result[$key]['intime'])) . '</span>';
  330. }
  331. }
  332. } else {
  333. $result[$key]['intime'] = '-';
  334. }
  335. if ($result[$key]['start_time'] != 0) {
  336. $result[$key]['start_time'] = date('Y-m-d H:i:s', $vo['start_time']);
  337. $date = explode(' ', $result[$key]['start_time']);
  338. $year = explode('-', $result[$key]['start_time']);
  339. if ($date[0] == date('Y-m-d', time())) {
  340. $result[$key]['start_time'] = '<span style="float: right;">' . $date[1] . '</span>';
  341. } else if ($date[0] == date('Y-m-d', strtotime("-1 day"))) {
  342. $result[$key]['start_time'] = '<span style="float: right;">' . '昨天 ' . $date[1] . '</span>';
  343. } else {
  344. if ($year[0] == date('Y', time())) {
  345. $result[$key]['start_time'] = '<span style="float: right;">' . date('m-d H:i:s', strtotime($result[$key]['start_time'])) . '</span>';
  346. }
  347. }
  348. } else {
  349. $result[$key]['start_time'] = '-';
  350. }
  351. if ($result[$key]['end_time'] != 0) {
  352. $result[$key]['end_time'] = date('Y-m-d H:i:s', $vo['end_time']);
  353. $date = explode(' ', $result[$key]['end_time']);
  354. $year = explode('-', $result[$key]['end_time']);
  355. if ($date[0] == date('Y-m-d', time())) {
  356. $result[$key]['end_time'] = '<span style="float: right;">' . $date[1] . '</span>';
  357. } else if ($date[0] == date('Y-m-d', strtotime("-1 day"))) {
  358. $result[$key]['end_time'] = '<span style="float: right;">' . '昨天 ' . $date[1] . '</span>';
  359. } else {
  360. if ($year[0] == date('Y', time())) {
  361. $result[$key]['end_time'] = '<span style="float: right;">' . date('m-d H:i:s', strtotime($result[$key]['end_time'])) . '</span>';
  362. }
  363. }
  364. } else {
  365. $result[$key]['end_time'] = '-';
  366. }
  367. //客服名称
  368. for ($i = 0; $i < count($users); $i++) {
  369. if ($result[$key]['kf_id'] == $users[$i]['id']) {
  370. $result[$key]['kefu_name'] = $users[$i]['user_name'];
  371. }
  372. }
  373. //满意度
  374. for ($j = 0; $j < count($evaluate); $j++) {
  375. if ($result[$key]['evaluate_id'] == $evaluate[$j]['evaluate_id']) {
  376. $result[$key]['evaluate_name'] = $evaluate[$j]['evaluate_name'];
  377. }
  378. }
  379. //客服所在组
  380. for ($a = 0; $a < count($groups); $a++) {
  381. if ($result[$key]['group_id'] == $groups[$a]['id']) {
  382. $result[$key]['group_name'] = $groups[$a]['name'];
  383. }
  384. }
  385. //会话时长/响应时长
  386. for ($b = 0; $b < count($alarm); $b++) {
  387. if ($result[$key]['servicelog_id'] == $alarm[$b]['servicelog_id']) {
  388. //会话时长
  389. $conversation_min = intval($alarm[$b]['alarm_cvtOvertime'] / 60);
  390. $conversation_s = $alarm[$b]['alarm_cvtOvertime'] % 60;
  391. $result[$key]['conversation'] = $conversation_min . '分' . $conversation_s . '秒';
  392. //响应时长
  393. $response_min = intval($alarm[$b]['alarm_corresponding'] / 60);
  394. $response_s = $alarm[$b]['alarm_corresponding'] % 60;
  395. $result[$key]['response'] = $response_min . '分' . $response_s . '秒';
  396. }
  397. }
  398. if ($vo['servicelog_close_type'] == 0) {
  399. $result[$key]['servicelog_close_type'] = '未知';
  400. }
  401. if ($vo['servicelog_close_type'] == 1) {
  402. $result[$key]['servicelog_close_type'] = '无效会话';
  403. }
  404. if ($vo['servicelog_close_type'] == 2) {
  405. $result[$key]['servicelog_close_type'] = '双方静默';
  406. }
  407. if ($vo['servicelog_close_type'] == 3) {
  408. $result[$key]['servicelog_close_type'] = '客服关闭';
  409. }
  410. if ($vo['servicelog_close_type'] == 4) {
  411. $result[$key]['servicelog_close_type'] = '客服掉线';
  412. }
  413. if ($vo['servicelog_close_type'] == 5) {
  414. $result[$key]['servicelog_close_type'] = '转出';
  415. }
  416. if ($vo['servicelog_close_type'] == 6) {
  417. $result[$key]['servicelog_close_type'] = '用户关闭';
  418. }
  419. // 生成操作按钮
  420. if (0 != $vo['servicelog_id']) {
  421. $result[$key]['operate'] = $this->makeBtn($vo['servicelog_id']);
  422. }
  423. }
  424. $return['total'] = $countTmp->count(); //总数据
  425. $return['rows'] = $result;
  426. // if (!$toExcel) {
  427. // return json($return);
  428. // } else {
  429. // $head = ['工单id', '访客进线时间', '接待客服', '所在组', '访客账号', '开始时间', '结束时间', '会话时长', '响应时长', '关闭原因', '满意度'];
  430. // $key = ['servicelog_id', 'intime', 'kefu_name', 'group_name', 'user_name', 'start_time', 'end_time', 'conversation', 'response', 'servicelog_close_type', 'evaluate_name'];
  431. // (new Office())->outdata('工作报表数据导出', $result, $head, $key);
  432. // return true;
  433. // }
  434. return json($return);
  435. }
  436. //所有客服
  437. $users = db('users')->select();
  438. $useroption = '';
  439. if (!empty($users)) {
  440. $option = '<option value="0">全部客服</option>';
  441. for ($i = 0; $i < count($users); $i++) {
  442. $option = $option . '<option value="' . $users[$i]['id'] . '">' . $users[$i]['user_name'] . '</option>';
  443. }
  444. $useroption = '<select class="selector_user" lay-verify="required" lay-filter="user_id" style="height: 30px;">' . $option . '</select>';
  445. }
  446. //所有客服组
  447. $groups = db('groups')->select();
  448. $groupoption = '';
  449. if (!empty($groups)) {
  450. $option = '<option value="0">全部客服组</option>';
  451. for ($j = 0; $j < count($groups); $j++) {
  452. $option = $option . '<option value="' . $groups[$j]['id'] . '">' . $groups[$j]['name'] . '</option>';
  453. }
  454. $groupoption = '<select class="selector_group" lay-verify="required" lay-filter="group_id" style="height: 30px;">' . $option . '</select>';
  455. }
  456. $this->assign([
  457. 'useroption' => $useroption,
  458. 'groupoption' => $groupoption
  459. ]);
  460. return $this->fetch('wordslog');
  461. }
  462. function matching($str, $a, $b)
  463. {
  464. $pattern = '/(' . $a . ')(.*)(?)(' . $b . ')/'; //正则规则匹配支付串中任何一个位置字符串
  465. //$pattern = '/(#\[)(.*)(?)(\]\/)/';
  466. preg_match_all($pattern, $str, $m);
  467. //preg_match_all($pattern, $str, $m); //返回一个匹配结果
  468. //print_r($m);die; //到时候在这里书写返回值就好了 .die;
  469. }
  470. // 历史会话记录详情
  471. public function detail()
  472. {
  473. $id = input('get.id');
  474. $type = input('get.type', '');
  475. $chat = db('chat_log')->where('servicelog_id', $id)->order('time_line')->select();
  476. $html = '';
  477. for ($i = 0; $i < count($chat); $i++) {
  478. $content = json_decode($chat[$i]['content'], true);
  479. $chat[$i]['time_line'] = date('H:i', $chat[$i]['time_line']);
  480. if (!empty($content['text'])) {
  481. $content['content'] = '&nbsp&nbsp' . $content['text'] . '&nbsp&nbsp';
  482. }
  483. if (!empty($content['img'])) {
  484. $content['content'] = '<img width="100%" src="' . $content['img'] . '"/>';
  485. }
  486. if ((strpos($chat[$i]['to_id'], 'KF')) !== false) {
  487. /*$preg1 = "/^#[*]$/";
  488. $preg= '/xue[\s\S]*?om/i';
  489. preg_match_all($preg1,"#[哈哈]/",$res);
  490. var_dump($res);*/
  491. $this->matching("#[哈哈]/", "#\[", "\]\/");
  492. //$this->getFacesIcon();
  493. $html = $html . '<div style="margin-top:15px;width:75%"><div>' . $chat[$i]['from_name'] . '&nbsp&nbsp&nbsp' . $chat[$i]['time_line'] . '</div>';
  494. $html = $html . '<div style="margin-top:5px;display:inline-block;*display:inline;*zoom:1;word-break:break-all;word-wrap:break-word" class="form-content">' . $content['content'] . '</div></div>';
  495. } else {
  496. $html = $html . '<div style="margin-top:15px;width:75%;margin-left:25%;text-align:right;"><div>' . $chat[$i]['from_name'] . '&nbsp&nbsp&nbsp' . $chat[$i]['time_line'] . '</div>';
  497. $html = $html . '<div style="margin-top:5px;display:inline-block;*display:inline;*zoom:1;text-align:left;word-break:break-all;word-wrap:break-word" class="form-content">' . $content['content'] . '</div></div>';
  498. }
  499. }
  500. $redis = new Redis;
  501. if ($type === 'onLine') {
  502. $servicelog = json_decode($redis->handler()->Hget('SERVICELOG', $id), true);
  503. } else {
  504. $servicelog = db('service_log')->where('servicelog_id', $id)->find();
  505. }
  506. //满意度
  507. $evaluate = db('evaluate')->where('evaluate_id', $servicelog['evaluate_id'])->find();
  508. $evaluate = '<img width="40px" style="margin-top:15px;" src="' . $evaluate['evaluate_url'] . '"/>';
  509. //$alarm报警信息
  510. if ($type === 'onLine') {
  511. $alarm = json_decode($redis->handler()->Hget('SERVICELOG', $id), true);
  512. } else {
  513. $alarm = db('alarm')->where('servicelog_id', $id)->find();
  514. }
  515. //会话超时标准
  516. $verifyAllTime = db('systemconfig')->where('systemconfig_name', '质检会话时长设置')->find();
  517. //会话响应时长标准
  518. $verifyReturnTime = db('systemconfig')->where('systemconfig_name', '质检会话响应时长设置')->find();
  519. $span = '';
  520. if (!empty($alarm)) {
  521. if ($alarm['alarm_userSensitive'] != 0) {
  522. $span = $span . '<span class="alarm_info">访客敏感词</span>';
  523. }
  524. if ($alarm['alarm_serverSensitive'] != 0) {
  525. $span = $span . '<span class="alarm_info">客服敏感词</span>';
  526. }
  527. if ($alarm['alarm_corresponding'] > $verifyReturnTime['systemconfig_data']) {
  528. $span = $span . '<span class="alarm_info">响应超时</span>';
  529. }
  530. if ($alarm['alarm_cvtOvertime'] > $verifyAllTime['systemconfig_data']) {
  531. $span = $span . '<span class="alarm_info">会话超时</span>';
  532. }
  533. if ($alarm['alarm_respond'] == 1) {
  534. $span = $span . '<span class="alarm_info">客服未回应</span>';
  535. }
  536. if ($alarm['alarm_count'] == 0 && $type !== 'onLine') {
  537. $span = $span . '<span class="alarm_info">会话无内容</span>';
  538. }
  539. }
  540. //用户信息
  541. $account = db('accounts')->where('id', $servicelog['user_id'])->find();
  542. $label = db('accountslabel')->where('id', $account['label_id'])->find();
  543. $account['label'] = $label['name'];
  544. $this->assign([
  545. 'html' => $html,
  546. 'span' => $span,
  547. 'evaluate' => $evaluate,
  548. 'servicelog' => $servicelog,
  549. 'account' => $account
  550. ]);
  551. return $this->fetch();
  552. }
  553. // 生成按钮
  554. private function makeBtn($id)
  555. {
  556. $operate = '<a href="' . url('system/detail', ['id' => $id]) . '">';
  557. // $operate .= '<button type="button" class="btn btn-primary btn-sm"><i class="fa fa-paste"></i> 详情</button></a> ';
  558. $operate .= '<button type="button" class="btn btn-primary btn-sm"> 详情</button></a> ';
  559. return $operate;
  560. }
  561. public function getFacesIcon($facesIcon)
  562. {
  563. $data = ["[微笑]", "[嘻嘻]", "[哈哈]", "[可爱]", "[可怜]", "[挖鼻]", "[吃惊]", "[害羞]", "[挤眼]", "[闭嘴]", "[鄙视]",
  564. "[爱你]", "[泪]", "[偷笑]", "[亲亲]", "[生病]", "[太开心]", "[白眼]", "[右哼哼]", "[左哼哼]", "[嘘]", "[衰]",
  565. "[委屈]", "[吐]", "[哈欠]", "[抱抱]", "[怒]", "[疑问]", "[馋嘴]", "[拜拜]", "[思考]", "[汗]", "[困]", "[睡]",
  566. "[钱]", "[失望]", "[酷]", "[色]", "[哼]", "[鼓掌]", "[晕]", "[悲伤]", "[抓狂]", "[黑线]", "[阴险]", "[怒骂]",
  567. "[互粉]", "[心]", "[伤心]", "[猪头]", "[熊猫]", "[兔子]", "[ok]", "[耶]", "[good]", "[NO]", "[赞]", "[来]",
  568. "[弱]", "[草泥马]", "[神马]", "[囧]", "[浮云]", "[给力]", "[围观]", "[威武]", "[奥特曼]", "[礼物]", "[钟]",
  569. "[话筒]", "[蜡烛]", "[蛋糕]"];
  570. $key = array_search($facesIcon, $data);
  571. return $key;
  572. }
  573. //导出数据
  574. public function toexcel()
  575. {
  576. $param = input('param.');
  577. $limit = $param['pageSize'];
  578. $offset = ($param['pageNumber'] - 1) * $limit;
  579. $start = $param['start'];
  580. $end = $param['end'];
  581. $where = [];
  582. if ($param['user_id'] != 0) {
  583. $where['kf_id'] = $param['user_id'];
  584. }
  585. if ($param['group_id'] != 0) {
  586. $where['group_id'] = $param['group_id'];
  587. }
  588. if (!empty($param['username'])) {
  589. $where['user_name'] = $param['username'];
  590. }
  591. $result = db('service_log')->whereBetween('start_time', [strtotime($start), strtotime($end . ' 23:59:59')])->where($where)->order('start_time', 'desc')->select();
  592. //所有客服
  593. $users = db('users')->select();
  594. //所有客服组
  595. $groups = db('groups')->select();
  596. //满意度
  597. $evaluate = db('evaluate')->select();
  598. //$alarm报警信息
  599. $alarm = db('alarm')->select();
  600. //会话超时标准
  601. $verifyAllTime = db('systemconfig')->where('systemconfig_name', '质检会话时长设置')->find();
  602. //会话响应时长标准
  603. $verifyReturnTime = db('systemconfig')->where('systemconfig_name', '质检会话响应时长设置')->find();
  604. for ($c = 0; $c < count($alarm); $c++) {
  605. $alarm[$c]['alarminfo'] = '';
  606. if ($alarm[$c]['alarm_userSensitive'] != 0) {
  607. $alarm[$c]['alarminfo'] .= '访客敏感词/';
  608. }
  609. if ($alarm[$c]['alarm_serverSensitive'] != 0) {
  610. $alarm[$c]['alarminfo'] .= '客服敏感词/';
  611. }
  612. if ($alarm[$c]['alarm_corresponding'] > $verifyReturnTime['systemconfig_data']) {
  613. $alarm[$c]['alarminfo'] .= '响应超时/';
  614. }
  615. if ($alarm[$c]['alarm_cvtOvertime'] > $verifyAllTime['systemconfig_data']) {
  616. $alarm[$c]['alarminfo'] .= '会话超时/';
  617. }
  618. if ($alarm[$c]['alarm_respond'] == 1) {
  619. $alarm[$c]['alarminfo'] .= '客服未回应/';
  620. }
  621. if ($alarm[$c]['alarm_count'] == 0) {
  622. $alarm[$c]['alarminfo'] .= '会话无内容';
  623. }
  624. }
  625. foreach ($result as $key => $vo) {
  626. if ($result[$key]['intime'] != 0) {
  627. $result[$key]['intime'] = date('Y-m-d H:i:s', $vo['intime']);
  628. } else {
  629. $result[$key]['intime'] = '-';
  630. }
  631. if ($result[$key]['start_time'] != 0) {
  632. $result[$key]['start_time'] = date('Y-m-d H:i:s', $vo['start_time']);
  633. } else {
  634. $result[$key]['start_time'] = '-';
  635. }
  636. if ($result[$key]['end_time'] != 0) {
  637. $result[$key]['end_time'] = date('Y-m-d H:i:s', $vo['end_time']);
  638. } else {
  639. $result[$key]['end_time'] = '-';
  640. }
  641. //客服昵称
  642. for ($i = 0; $i < count($users); $i++) {
  643. $result[$key]['kefu_name'] = '-';
  644. if ($result[$key]['kf_id'] == $users[$i]['id']) {
  645. $result[$key]['kefu_name'] = $users[$i]['user_name'];
  646. }
  647. }
  648. //满意度
  649. $result[$key]['evaluate_name'] = '';
  650. for ($j = 0; $j < count($evaluate); $j++) {
  651. if ($result[$key]['evaluate_id'] == $evaluate[$j]['evaluate_id']) {
  652. $result[$key]['evaluate_name'] = $evaluate[$j]['evaluate_name'];
  653. }
  654. }
  655. //客服所在组
  656. for ($a = 0; $a < count($groups); $a++) {
  657. if ($result[$key]['group_id'] == $groups[$a]['id']) {
  658. $result[$key]['group_name'] = $groups[$a]['name'];
  659. }
  660. }
  661. //会话时长/响应时长/报警信息
  662. $result[$key]['conversation'] = '';
  663. $result[$key]['response'] = '';
  664. $result[$key]['alarm'] = '';
  665. for ($b = 0; $b < count($alarm); $b++) {
  666. if ($result[$key]['servicelog_id'] == $alarm[$b]['servicelog_id']) {
  667. //会话时长
  668. $conversation_min = intval($alarm[$b]['alarm_cvtOvertime'] / 60);
  669. $conversation_s = $alarm[$b]['alarm_cvtOvertime'] % 60;
  670. $result[$key]['conversation'] = $conversation_min . '分' . $conversation_s . '秒';
  671. //响应时长
  672. $response_min = intval($alarm[$b]['alarm_corresponding'] / 60);
  673. $response_s = $alarm[$b]['alarm_corresponding'] % 60;
  674. $result[$key]['response'] = $response_min . '分' . $response_s . '秒';
  675. //报警信息
  676. $result[$key]['alarminfo'] = $alarm[$b]['alarminfo'];
  677. }
  678. }
  679. if ($vo['servicelog_close_type'] == 0) {
  680. $result[$key]['servicelog_close_type'] = '未知';
  681. }
  682. if ($vo['servicelog_close_type'] == 1) {
  683. $result[$key]['servicelog_close_type'] = '无效会话';
  684. }
  685. if ($vo['servicelog_close_type'] == 2) {
  686. $result[$key]['servicelog_close_type'] = '双方静默';
  687. }
  688. if ($vo['servicelog_close_type'] == 3) {
  689. $result[$key]['servicelog_close_type'] = '客服关闭';
  690. }
  691. if ($vo['servicelog_close_type'] == 4) {
  692. $result[$key]['servicelog_close_type'] = '客服掉线';
  693. }
  694. if ($vo['servicelog_close_type'] == 5) {
  695. $result[$key]['servicelog_close_type'] = '转出';
  696. }
  697. if ($vo['servicelog_close_type'] == 6) {
  698. $result[$key]['servicelog_close_type'] = '用户关闭';
  699. }
  700. //工单聊天详情
  701. $chat_log = db('chat_log')->where('servicelog_id', $vo['servicelog_id'])->order('time_line', 'desc')->select();
  702. $result[$key]['detail'] = '';
  703. for ($c = 0; $c < count($chat_log); $c++) {
  704. $content = json_decode($chat_log[$c]['content'], true);
  705. $chat_log[$c]['time_line'] = date('Y-m-d H:i:s', $chat_log[$c]['time_line']);
  706. $result[$key]['detail'] = $result[$key]['detail'] . ' ' . $chat_log[$c]['time_line'] . ' ' . $chat_log[$c]['from_name'];
  707. $content['content'] = '';
  708. if (!empty($content['text'])) {
  709. $content['content'] = $content['text'];
  710. }
  711. if (!empty($content['img'])) {
  712. $content['content'] = '<img width="100%" src="' . $content['img'] . '"/>';
  713. }
  714. $result[$key]['detail'] = $result[$key]['detail'] . ' ' . $content['content'];
  715. }
  716. }
  717. $head = ['工单id', '访客进线时间', '接待客服', '所在组', '访客账号', '开始时间', '结束时间', '会话时长', '响应时长', '关闭原因', '满意度', '来源ip', '来源网站', '来源系统', '来源浏览器', '报警信息', '聊天详情'];
  718. $key = ['servicelog_id', 'intime', 'kefu_name', 'group_name', 'user_name', 'start_time', 'end_time', 'conversation', 'response', 'servicelog_close_type', 'evaluate_name', 'user_ip', 'website', 'system', 'browse', 'alarminfo', 'detail'];
  719. (new Office())->outdata('工单数据导出', $result, $head, $key);
  720. return true;
  721. }
  722. // 生成按钮
  723. private function makeBotton($id)
  724. {
  725. $operate = '<a href="' . url('editWelcome', ['id' => $id]) . '">';
  726. $operate .= '<button type="button" class="btn btn-primary btn-sm"><i class="fa fa-paste"></i> 编辑</button></a> ';
  727. $operate .= '<a href="javascript:delWelcome(' . $id . ')"><button type="button" class="btn btn-danger btn-sm">';
  728. $operate .= '<i class="fa fa-trash-o"></i> 删除</button></a> ';
  729. return $operate;
  730. }
  731. /**
  732. * 验证平台设置
  733. *
  734. * @access public
  735. */
  736. public function platform()
  737. {
  738. // 表单提交.
  739. $Where['platform_code'] = 'Customer-Service';
  740. if (request()->isPost()) {
  741. $param = input('post.');
  742. $status = intval($param['status']) ? 1 : 0;
  743. try {
  744. $updateData = [
  745. 'platform_url_token' => $param['urlToken'],
  746. 'platform_url_code' => $param['urlCode'],
  747. 'platform_status' => $status,
  748. ];
  749. db('platform')->where($Where)->update($updateData);
  750. return json(['code' => 1, 'data' => '', 'msg' => '设置成功']);
  751. } catch (\Exception $e) {
  752. return json(['code' => -2, 'data' => '', 'msg' => $e->getMessage()]);
  753. }//end try
  754. }//end if
  755. // 信息.
  756. $settings = db('platform')->where($Where)->find();
  757. $this->assign(
  758. [
  759. 'urlToken' => $settings['platform_url_token'],
  760. 'urlCode' => $settings['platform_url_code'],
  761. 'status' => $settings['platform_status'],
  762. ]
  763. );
  764. return $this->fetch();
  765. }//end basics()
  766. }