Workorder.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. <?php
  2. namespace app\index\controller;
  3. use app\common\controller\Frontend;
  4. use think\Db;
  5. use addons\workorder\model\Kbs;
  6. use addons\workorder\model\Orders;
  7. use addons\workorder\model\Engineer;
  8. use addons\workorder\model\Records;
  9. use addons\workorder\library\General;
  10. class Workorder extends Frontend
  11. {
  12. protected $noNeedLogin = [];
  13. protected $noNeedRight = ['*'];
  14. protected $layout = 'default';
  15. protected $fileField = ['image', 'images', 'file', 'files'];
  16. /**
  17. * @var General 实例
  18. */
  19. protected $General = null;
  20. protected $userEngineerId = null;
  21. protected $workorderConfig = [];
  22. public function _initialize()
  23. {
  24. parent::_initialize();
  25. $this->General = General::instance();
  26. // 当前用户是否是工程师
  27. if ($this->auth) {
  28. $this->userEngineerId = Engineer::where('user_id', $this->auth->id)->where('status', '1')->value('id');
  29. }
  30. $this->workorderConfig = get_addon_config('workorder');
  31. $this->General->autoClose();
  32. }
  33. public function my()
  34. {
  35. $page = $this->request->param('page');
  36. if ($this->request->isDelete()) {
  37. $order_id = (int)$this->request->param('order_id');
  38. $order = Orders::get($order_id);
  39. if ($order->status != 5) {
  40. $this->error(__('You can delete a work order after closing it!'));
  41. }
  42. if (Orders::destroy(['id' => $order_id, 'user_id' => $this->auth->id])) {
  43. General::orderNumberChangeCalcEngineerStatistics($order->id, $order->engineer_id, 'del');
  44. $this->success(__('Delete Success~'));
  45. } else {
  46. $this->error(__('Delete Fail!'));
  47. }
  48. }
  49. $orders = Orders::where('user_id', $this->auth->id)
  50. ->order('createtime desc')
  51. ->paginate(10, null, [])
  52. ->each(function ($item, $key) {
  53. $item->status = $this->General->handleStatus($item->status, false);
  54. $item->title = $item->title ?? __('Untitled');
  55. });
  56. // 防止删除后当页显示空白
  57. if (count($orders) == 0 && $page > 1) {
  58. $this->redirect('workorder/my');
  59. }
  60. $this->view->assign('title', __('My work order'));
  61. $this->view->assign('orders', $orders);
  62. return $this->view->fetch();
  63. }
  64. public function manage()
  65. {
  66. if (!$this->userEngineerId) {
  67. $this->error(__('You have no permission to operate!'));
  68. }
  69. $page = $this->request->param('page');
  70. $type = $this->request->param('type') ?? 'all';
  71. $where['engineer_id'] = $this->userEngineerId;
  72. switch ($type) {
  73. case 'noreply':
  74. $where['status'] = ['in', '1,2'];
  75. break;
  76. case 'replied' :
  77. $where['status'] = 3;
  78. break;
  79. case 'closed':
  80. $where['status'] = ['in', '4,5'];
  81. break;
  82. }
  83. $orders = Orders::where($where)->order('createtime desc')->paginate(10, null, [])->each(function ($item, $key) {
  84. $item->title = $item->title ?? __('Untitled');
  85. $item->status = $this->General->handleStatus($item->status, true);
  86. });
  87. if (count($orders) == 0 && $page > 1) {
  88. $this->redirect('workorder/manage');
  89. }
  90. $this->view->assign('title', __('work order manage'));
  91. $this->view->assign('orders', $orders);
  92. $this->view->assign('type', $type);
  93. return $this->view->fetch();
  94. }
  95. public function reply($id)
  96. {
  97. $token = $this->request->post('__token__');
  98. if (session('__token__') != $token) {
  99. $this->error(__('Token incorrect!'), null, ['token' => $this->request->token()]);
  100. }
  101. $order = Orders::get($id);
  102. if (!$order) {
  103. $this->error(__('Work order not found~'));
  104. }
  105. $user = ($order->user_id == $this->auth->id) ? $this->auth : false;
  106. $engineer = ($order->engineer_id == $this->userEngineerId) ? Engineer::get($this->userEngineerId) : false;
  107. if (!$user && !$engineer) {
  108. $this->error(__('You have no permission to operate!'), null, ['token' => $this->request->token()]);
  109. }
  110. $row = $this->request->post('row/a');
  111. $res = $this->General->createReply($order, $user, $engineer, $row);
  112. $this->assignconfig('editor_name', $this->getEditorName());
  113. if ($res['code'] == 1) {
  114. $this->view->engine->layout(false);
  115. foreach ($res['data']['records'] as $index => $record) {
  116. $recordsHtml[$index] = $this->view->fetch('workorder/common/message_item', [
  117. 'record' => $record,
  118. 'isUser' => (bool)$user
  119. ]);
  120. }
  121. $this->success($res['msg'], '', ['recordsHtml' => $recordsHtml]);
  122. } else {
  123. $this->error($res['msg'], null, ['token' => $this->request->token()]);
  124. }
  125. }
  126. public function transfer($id)
  127. {
  128. $row = Orders::get($id);
  129. if (!$row) {
  130. $this->error(__('Work order not found~'));
  131. }
  132. $isCurrentEngineer = ($row->engineer_id === $this->userEngineerId) ? true : false;
  133. if (!$isCurrentEngineer) {
  134. $this->error(__('You have no permission to operate!'));
  135. }
  136. if ($this->request->isPost()) {
  137. $token = $this->request->post('__token__');
  138. if (session('__token__') != $token) {
  139. $this->error(__('Token incorrect!'), null, ['token' => $this->request->token()]);
  140. }
  141. $transferEngineer = $this->request->post('transfer_engineer');
  142. $res = $this->General->transfer($row, $transferEngineer);
  143. if ($res['code'] == 1) {
  144. $this->success($res['msg'], url('index/workorder/manage'));
  145. } else {
  146. $this->error($res['msg'], null, ['token' => $this->request->token()]);
  147. }
  148. }
  149. $this->error(__('Nothing happened~'), null, ['token' => $this->request->token()]);
  150. }
  151. public function detail($id)
  152. {
  153. $row = Orders::get($id);
  154. if (!$row) {
  155. $this->error(__('Work order not found~'), url('index/workorder/my'));
  156. }
  157. $isUser = ($row->user_id == $this->auth->id) ? true : false;
  158. $isCurrentEngineer = ($row->engineer_id === $this->userEngineerId) ? true : false;
  159. if (!$isUser && !$isCurrentEngineer) {
  160. $this->error(__('You have no permission to operate!'));
  161. }
  162. if ($this->request->isPost()) {
  163. $type = $this->request->param('type');
  164. if ($type == 'close') {
  165. $this->output($this->General->closeOrder($row, $isCurrentEngineer));
  166. } elseif ($type == 'urging' && $isUser) {
  167. $this->output($this->General->urgingOrder($row));
  168. }
  169. $this->error(__('Nothing happened~'));
  170. }
  171. $orderInfo = $this->General->orderInfoHandle($row, $isUser, $isCurrentEngineer);
  172. // 聊天记录和工程师资料
  173. $records = $this->General->orderRecords($id, $row->engineer_id);
  174. $editorName = $this->getEditorName();
  175. $replyField = $row->getFields(null, $isUser ? 1 : 2);
  176. $this->view->assign('row', $orderInfo['order']);
  177. $this->view->assign('isUser', $isUser);
  178. $this->view->assign('fields', $replyField);
  179. $this->view->assign('records', $records['records']);
  180. $this->view->assign('engineers', $records['engineers']);
  181. $this->view->assign('title', $orderInfo['order']->title . ' – ' . __('Work order details'));
  182. $this->view->assign('basicField', $orderInfo['basicField']);
  183. $this->view->assign('editor_name', $editorName);
  184. $this->assignconfig('editor_name', $editorName);
  185. return $this->view->fetch();
  186. }
  187. protected function getEditorName()
  188. {
  189. $editor = ['nkeditor', 'umeditor', 'markdown', 'tinymce', 'simditor', 'ueditor', 'summernote'];
  190. $editorList = get_addon_list();
  191. foreach ($editor as $index => $item) {
  192. if (array_key_exists($item, $editorList) && $editorList[$item]['state'] == 1) {
  193. return $item;
  194. }
  195. }
  196. return 'none';
  197. }
  198. /**
  199. * 输出方法返回结果
  200. */
  201. protected function output($res)
  202. {
  203. if ($res['code'] == 1) {
  204. $this->success($res['msg']);
  205. } else {
  206. $this->error($res['msg']);
  207. }
  208. }
  209. public function evaluate($id)
  210. {
  211. $order = Orders::get($id);
  212. if (!$order) {
  213. $this->error(__('Work order not found~'));
  214. }
  215. if ($order->status == 1) {
  216. $this->error(__('The current status of the work order cannot be evaluated~'));
  217. }
  218. if ($order->status == 5) {
  219. $this->error(__('The work order has been evaluated~'));
  220. }
  221. if ($this->request->isPost()) {
  222. $token = $this->request->post('__token__');
  223. if (session('__token__') != $token) {
  224. $this->error(__('Token incorrect!'), null, ['token' => $this->request->token()]);
  225. }
  226. $row = $this->request->post('row/a');
  227. $res = $this->General->createEvaluate($order, $row, $this->auth->id);
  228. if ($res['code'] == 1) {
  229. $this->success($res['msg'], url('index/workorder/my'));
  230. } else {
  231. $this->error($res['msg'], null, ['token' => $this->request->token()]);
  232. }
  233. }
  234. $this->view->assign('title', __('Evaluation Work Order'));
  235. $this->view->assign('row', $order);
  236. return $this->view->fetch();
  237. }
  238. public function create()
  239. {
  240. $keywords = $this->request->param('keywords');
  241. $category = $this->request->param('category');
  242. $steps = $this->request->param('steps');
  243. // 第一步-选择产品/服务
  244. if (!$category) {
  245. $where['status'] = '1';
  246. $where['deletetime'] = null;
  247. if ($keywords) {
  248. $where['pid'] = ['>', 0];
  249. $where['name'] = ['like', '%' . $keywords . '%'];
  250. }
  251. $category_temp = Db::name('workorder_category')->where($where)->order('weigh desc')->select();
  252. foreach ($category_temp as $key => $item) {
  253. $category_temp[$key]['logo_image'] = cdnurl($item['logo_image'], true);
  254. }
  255. if ($keywords) {
  256. $category_list[] = [
  257. 'name' => __('Query results'),
  258. 'child' => $category_temp
  259. ];
  260. } else {
  261. foreach ($category_temp as $index => $item) {
  262. $pid = $item['pid'];
  263. if ($pid == 0) {
  264. $category_list[] = $item;
  265. } else {
  266. $category_child_temp[$pid][] = $item;
  267. }
  268. }
  269. foreach ($category_list as $index => $item) {
  270. $category_list[$index]['child'] = isset($category_child_temp[$item['id']]) ? $category_child_temp[$item['id']] : [];
  271. }
  272. }
  273. $steps = 1;
  274. $this->view->assign('title', __('Submit work order'));
  275. $this->view->assign('category_list', $category_list);
  276. }
  277. // 第二步-推荐解决方案
  278. if ($category && ($steps != 3 || $keywords)) {
  279. $kbs_ids = Db::name('workorder_category')
  280. ->where('id', $category)
  281. ->where('status', '1')
  282. ->where('deletetime', null)
  283. ->value('kbs_ids');
  284. $kbs = [];
  285. if ($kbs_ids) {
  286. $where['id'] = ['in', $kbs_ids];
  287. $where['status'] = '1';
  288. $where['deletetime'] = null;
  289. if ($keywords) {
  290. $where['title'] = ['like', '%' . $keywords . '%'];
  291. }
  292. $kbs = Db::name('workorder_kbs')
  293. ->field('id,title,views,likes,url')
  294. ->where($where)
  295. ->order('weigh desc')
  296. ->limit(20)
  297. ->select();
  298. }
  299. $submit_channel = Db::name('workorder_submit_channel')->where('status', 1)->order('weigh desc')->select();
  300. foreach ($submit_channel as $index => $item) {
  301. $submit_channel[$index]['logo_image'] = cdnurl($item['logo_image'], true);
  302. $submit_channel[$index]['url'] = $this->General->handleUrl($item['url'], $category);
  303. }
  304. $steps = 2;
  305. $this->view->assign('kbs', $kbs);
  306. $this->view->assign('kbs_count', count($kbs));
  307. $this->view->assign('title', __('Recommended solutions'));
  308. $this->view->assign('submit_channel', $submit_channel);
  309. $this->view->assign('search_kbs', $keywords ? true : false);
  310. }
  311. // 第三步-创建工单
  312. if ($category && $steps == 3) {
  313. $fields = Orders::getFields(null, 0);
  314. $category_name = Db::name('workorder_category')
  315. ->where('id', $category)
  316. ->where('status', '1')
  317. ->where('deletetime', null)
  318. ->value('name');
  319. if (!$category_name) {
  320. $this->error(__('Product / service classification not found~'));
  321. }
  322. if ($this->request->isPost()) {
  323. $token = $this->request->post('__token__');
  324. if (session('__token__') != $token) {
  325. $this->error(__('Token incorrect!'), null, ['token' => $this->request->token()]);
  326. }
  327. $row = $this->request->post('row/a');
  328. $row['category_id'] = $category;
  329. $res = $this->General->createOrder($row, $this->auth->id);
  330. if ($res['code'] == 1) {
  331. $this->success(__('Submitted successfully~'), url('index/workorder/detail', ['id' => $res['data']['id']]));
  332. } else {
  333. $this->error($res['msg'], null, ['token' => $this->request->token()]);
  334. }
  335. }
  336. $urgentrank = Db::name('workorder_urgentrank')
  337. ->where('status', '1')
  338. ->where('deletetime', null)
  339. ->order('weigh desc')
  340. ->select();
  341. if (!$urgentrank) {
  342. $this->error(__('Emergency level of no work order available!'));
  343. }
  344. $this->view->assign('fields', $fields);
  345. $this->view->assign('urgentrank', $urgentrank);
  346. $this->view->assign('title', __('Create work order'));
  347. $this->view->assign('category_name', $category_name);
  348. }
  349. $this->view->assign('category', $category);
  350. $this->view->assign('steps', isset($steps) ? $steps : 1);
  351. return $this->view->fetch();
  352. }
  353. public function kbs()
  354. {
  355. $id = $this->request->param('id');
  356. $category = $this->request->param('category');
  357. $kbs = Kbs::get(['id' => $id, 'status' => '1']);
  358. if (!$kbs) {
  359. $this->error(__('I cant find the knowledge~'), url('index/workorder/create'));
  360. }
  361. if ($this->request->isPost()) {
  362. $type = $this->request->param('type');
  363. if ($type == 'likes' || $type == 'dislikes') {
  364. $cookieName = 'workorder_kbs_' . $type . '_cookie';
  365. $workorderKbsCookie = \think\Cookie::get($cookieName);
  366. if ($workorderKbsCookie) {
  367. $workorderKbsCookieArr = explode('|', $workorderKbsCookie);
  368. if (in_array($id, $workorderKbsCookieArr)) {
  369. $this->error(__('You have already ordered %s!', [($type == 'likes' ? __('fabulous') : __('step on'))]));
  370. }
  371. }
  372. Db::name('workorder_kbs')->where('id', $id)->setInc($type);
  373. $workorderKbsCookie .= $id . '|';
  374. \think\Cookie::set($cookieName, $workorderKbsCookie, 315360000);
  375. $this->success();
  376. }
  377. }
  378. $kbs->setInc('views', 1);
  379. $recKbs = $this->General->recKbs($id, $category);
  380. $this->view->assign('kbs', $kbs);
  381. $this->view->assign('rec_kbs', $recKbs);
  382. $this->view->assign('title', $kbs['title']);
  383. $this->view->assign('category', $category);
  384. return $this->view->fetch();
  385. }
  386. public function icon()
  387. {
  388. $suffix = $this->request->param("suffix");
  389. header('Content-type: image/svg+xml');
  390. $suffix = $suffix ? $suffix : "FILE";
  391. echo $this->General->buildSuffixImage($suffix);
  392. exit;
  393. }
  394. }