SmartScreenImport.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace app\jobs;
  3. use app\model\ConstructionStep;
  4. use app\model\Employee;
  5. use app\model\SmartScreenConstruction;
  6. use app\model\SmartScreenImportLog;
  7. use app\model\SmartScreenProject;
  8. use cutExcel\MyreadFilter;
  9. use OSS\Core\OssException;
  10. use PhpOffice\PhpSpreadsheet\IOFactory;
  11. use think\facade\Db;
  12. use think\facade\Log;
  13. use think\queue\Job;
  14. use think\facade\Queue;
  15. class SmartScreenImport
  16. {
  17. public function fire(Job $job, $queuedata)
  18. {
  19. Log::close(NULL);
  20. $delete = false; // 失败
  21. try {
  22. if ($job->attempts() > 2) {
  23. $job->delete();
  24. $delete = true;
  25. }
  26. $is_done = $this->jobDone($queuedata);
  27. if($is_done){
  28. $job->delete();
  29. } else {
  30. $job->delete();
  31. $delete = true;
  32. }
  33. } catch (OssException $e) {
  34. //报错直接结束
  35. $job->delete();
  36. $delete = true;
  37. }
  38. if ($delete) {
  39. // 导入过程失败
  40. $log = SmartScreenImportLog::where('id', $queuedata['id'])->find();
  41. $tmp_file = $log['tmp_path'];
  42. if (file_exists($tmp_file)) {
  43. unlink($tmp_file);
  44. }
  45. $log->tmp_path = '';
  46. $log->status = 3;
  47. $log->save();
  48. }
  49. }
  50. public function failed($queuedata)
  51. {
  52. // ...任务达到最大重试次数后,失败了
  53. }
  54. // 导入
  55. private function jobDone($data){
  56. $log_id = $data['id'];
  57. $type = $data['type'];
  58. $log = SmartScreenImportLog::where('id', $log_id)->findOrEmpty();
  59. if ($log->isEmpty()) {
  60. return false;
  61. }
  62. if ($log['status'] == 2) {
  63. return true;
  64. }
  65. if (empty($log['tmp_path'])) {
  66. // 开始导入
  67. $ali_oss_bindurl = config('app.ali_oss_bindurl');
  68. $path = 'https://' . $ali_oss_bindurl . '/' . $log['path'];
  69. // 抓取远程Excel文件的内容
  70. try {
  71. $content = file_get_contents($path);
  72. if (!$content) {
  73. return false;
  74. }
  75. } catch (\Exception $e) {
  76. return false;
  77. }
  78. // 保存Excel文件到本地临时文件
  79. $run_path = runtime_path();
  80. $tmp_file = tempnam($run_path, 'PHPExcel');
  81. file_put_contents($tmp_file, $content);
  82. $log->tmp_path = $tmp_file;
  83. $log->save();
  84. } else {
  85. $tmp_file = $log['tmp_path'];
  86. }
  87. //实例化PHPExcel类
  88. $reader = IOFactory::createReader('Xlsx');
  89. if (!$reader->canRead($tmp_file)) {
  90. Log::record('-------screen import error------')->save();
  91. Log::record('file canRead false')->save();
  92. Log::record('-------screen import error------')->save();
  93. return false;
  94. }
  95. $rows = 100;
  96. if ($log['execute_rows'] == 0) {
  97. $start_rows = 1;
  98. } else {
  99. $start_rows = $log['execute_rows'];
  100. }
  101. $end_rows = $start_rows + $rows;
  102. $MyReadFilter = new MyreadFilter($start_rows, $end_rows);
  103. $reader->setReadFilter($MyReadFilter);
  104. $reader->setReadDataOnly(true);
  105. $objPHPExcel = $reader->load($tmp_file);
  106. $sheet = $objPHPExcel->getSheet(0); //excel中的第一张sheet
  107. $highestRow = $sheet->getHighestRow(); // 取得总行数
  108. $highestColumn = $sheet->getHighestColumn(); // 取得总列数
  109. \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
  110. $lines = $highestRow - 1;
  111. $end = true;
  112. $root_id = $log['root_id'];
  113. if ($lines > 0) {
  114. $datas = [];
  115. $j = $start_rows + 1;
  116. for ($j; $j <= $highestRow; $j++) {
  117. $date_check = ['I'];
  118. $date_value = [];
  119. foreach ($date_check as $v) {
  120. try {
  121. $get_value = $objPHPExcel->getActiveSheet()->getCell($v . $j)->getValue();
  122. if (empty($get_value)) {
  123. $date_value[$v] = '';
  124. continue;
  125. }
  126. } catch (\Exception $e) {
  127. $date_value[$v] = '';
  128. }
  129. }
  130. if ($type == 1) {
  131. $datas[] = [
  132. 'owner_name' => trim($objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue()),
  133. 'address' => trim($objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue()),
  134. 'designer' => trim($objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue()),
  135. 'project_manager' => trim($objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue()),
  136. 'inspection' => trim($objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue()),
  137. 'status' => trim($objPHPExcel->getActiveSheet()->getCell("F" . $j)->getValue()),
  138. 'row'=> $j
  139. ];
  140. } elseif ($type == 2) {
  141. $datas[] = [
  142. 'category' => trim($objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue()),
  143. 'name' => trim($objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue()),
  144. 'unit' => trim($objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue()),
  145. 'price' => trim($objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue()),
  146. 'content' => trim($objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue()),
  147. 'row'=> $j
  148. ];
  149. }
  150. }
  151. $save_data = [];
  152. foreach ($datas as $k => $v) {
  153. $one_cus = [];
  154. if ($type == 1) {
  155. $designer_id = 0;
  156. if (!empty($v['designer'])) {
  157. $designer_id = Employee::where([['name', '=', $v['designer']], ['root_id', '=', $root_id]])->value('id');
  158. }
  159. $status = 0;
  160. if (!empty($v['status'])) {
  161. $status = ConstructionStep::where([['root_id', '=', $root_id], ['name', '=', $v['status']]])->value('id');
  162. }
  163. $one_cus['owner_name'] = $v['owner_name'];
  164. $one_cus['address'] = $v['address'];
  165. $one_cus['designer_id'] = $designer_id ? $designer_id : 0;
  166. $one_cus['project_manager'] = $v['project_manager'];
  167. $one_cus['inspection'] = $v['inspection'];
  168. $one_cus['status'] = $status;
  169. $one_cus['employee_id'] = $log['employee_id'];
  170. $one_cus['root_id'] = $root_id;
  171. } elseif ($type == 2) {
  172. $one_cus['category'] = $v['category'];
  173. $one_cus['name'] = $v['name'];
  174. $one_cus['unit'] = $v['unit'];
  175. $one_cus['price'] = $v['price'];
  176. $one_cus['content'] = $v['content'];
  177. $one_cus['employee_id'] = $log['employee_id'];
  178. $one_cus['root_id'] = $root_id;
  179. }
  180. $save_data[] = $one_cus;
  181. }
  182. Db::startTrans();
  183. try {
  184. foreach ($save_data as $k => $v) {
  185. if ($type == 1) {
  186. $result = SmartScreenConstruction::create($v);
  187. } elseif ($type == 2) {
  188. SmartScreenProject::create($v);
  189. }
  190. }
  191. Db::commit();
  192. } catch (\Exception $e) {
  193. trace($e->getMessage(), 'error');
  194. // 回滚事务
  195. Db::rollback();
  196. return false;
  197. }
  198. if ($log['status'] == 0) {
  199. $log->status = 1;
  200. }
  201. $log->count = $log['count'] + count($datas);
  202. $log->valid_count = $log['valid_count'] + count($datas);
  203. $log->execute_rows = $highestRow;
  204. $log->save();
  205. if (count($datas) > 0) {
  206. $end = false;
  207. } else {
  208. $log->tmp_path = '';
  209. $log->status = 2;
  210. $log->save();
  211. if (file_exists($tmp_file)) {
  212. unlink($tmp_file);
  213. }
  214. }
  215. } else {
  216. $log->tmp_path = '';
  217. $log->status = 2;
  218. $log->save();
  219. if (file_exists($tmp_file)) {
  220. unlink($tmp_file);
  221. }
  222. }
  223. if($lines == $rows) {
  224. $end = false;
  225. }
  226. if (!$end) {
  227. $jobHandlerClassName = 'app\jobs\SmartScreenImport';
  228. $jobQueueName = 'smart_screen_import';
  229. $orderData = ['id'=> $log_id, 'type'=> $type]; //这个是需要传到消费者的数据
  230. Queue::later(0, $jobHandlerClassName, $orderData, $jobQueueName);
  231. }
  232. return true;
  233. }
  234. }