diff --git a/extend/crontab/CronParser.php b/extend/crontab/CronParser.php new file mode 100644 index 0000000..8771699 --- /dev/null +++ b/extend/crontab/CronParser.php @@ -0,0 +1,224 @@ + 'Sunday', + 1 => 'Monday', + 2 => 'Tuesday', + 3 => 'Wednesday', + 4 => 'Thursday', + 5 => 'Friday', + 6 => 'Saturday', + ]; + + /** + * 检查crontab格式是否支持 + * @param string $cronstr + * @return boolean true|false + */ + public static function check($cronstr, $checkCount = true) + { + $cronstr = trim($cronstr); + + $splitTags = preg_split('#\s+#', $cronstr); + + if ($checkCount && count($splitTags) !== 5) { + return false; + } + + foreach ($splitTags as $tag) { + $r = '#^\*(\/\d+)?|\d+([\-\/]\d+(\/\d+)?)?(,\d+([\-\/]\d+(\/\d+)?)?)*$#'; + if (preg_match($r, $tag) == false) { + return false; + } + } + + return true; + } + + /** + * 格式化crontab格式字符串 + * @param string $cronstr + * @param int $maxSize 设置返回符合条件的时间数量, 默认为1 + * @return array 返回符合格式的时间 + * @throws \Exception + */ + public static function formatToDate($cronstr, $maxSize = 1) + { + if (!static::check($cronstr)) { + throw new \Exception("格式错误: $cronstr", 1); + } + $dates = []; + self::$tags = preg_split('#\s+#', $cronstr); + + $crons = [ + 'minutes' => static::parseTag(self::$tags[0], 0, 59), //分钟 + 'hours' => static::parseTag(self::$tags[1], 0, 23), //小时 + 'day' => static::parseTag(self::$tags[2], 1, 31), //一个月中的第几天 + 'month' => static::parseTag(self::$tags[3], 1, 12), //月份 + 'week' => static::parseTag(self::$tags[4], 0, 6), // 星期 + ]; + + $crons['week'] = array_map(function($item){ + return static::$weekMap[$item]; + }, $crons['week']); + + return self::getDateList($crons, $maxSize); + } + + /** + * 递归获取符合格式的日期,直到取到满足$maxSize的数为止 + * @param array $crons 解析crontab字符串后的数组 + * @param interge $maxSize 最多返回多少数据的时间 + * @param interge $year 指定年 + * @return array|null 符合条件的日期 + */ + private static function getDateList(array $crons, $maxSize, $year = null) + { + + $dates = []; + + // 年份基点 + $nowyear = ($year) ? $year : date('Y'); + + // 时间基点已当前为准,用于过滤小于当前时间的日期 + $nowtime = strtotime(date("Y-m-d H:i")); + + foreach ($crons['month'] as $month) { + // 获取此月最大天数 + $maxDay = cal_days_in_month(CAL_GREGORIAN, $month, $nowyear); + foreach (range(1, $maxDay) as $day) { + foreach ($crons['hours'] as $hours) { + foreach ($crons['minutes'] as $minutes) { + $i = mktime($hours, $minutes, 0, $month, $day, $nowyear); + if ($nowtime >= $i) { + continue; + } + + $date = getdate($i); + + // 解析是第几天 + if (self::$tags[2] != '*' && in_array($date['mday'], $crons['day'])) { + $dates[] = date('Y-m-d H:i', $i); + } + + // 解析星期几 + if (self::$tags[4] != '*' && in_array($date['weekday'], $crons['week'])) { + $dates[] = date('Y-m-d H:i', $i); + } + + // 天与星期几 + if (self::$tags[2] == '*' && self::$tags[4] == '*') { + $dates[] = date('Y-m-d H:i', $i); + } + + $dates = array_unique($dates); + + if (isset($dates) && count($dates) == $maxSize) { + break 4; + } + } + } + } + } + + // 已经递归获取了.但是还是没拿到符合的日期时间,说明指定的时期时间有问题 + if ($year && !count($dates)) { + return []; + } + + if (count($dates) != $maxSize) { + // 向下一年递归 + $dates = array_merge(self::getDateList($crons, $maxSize, ($nowyear + 1)), $dates); + } + + return $dates; + } + + /** + * 解析元素 + * @param string $tag 元素标签 + * @param integer $tmin 最小值 + * @param integer $tmax 最大值 + * @return array + * @throws \Exception + */ + private static function parseTag($tag, $tmin, $tmax) + { + if ($tag == '*') { + return range($tmin, $tmax); + } + + $step = 1; + $dateList = []; + + // x-x/2 情况 + if (false !== strpos($tag, ',')) { + $tmp = explode(',', $tag); + // 处理 xxx-xxx/x,x,x-x + foreach ($tmp as $t) { + if (self::checkExp($t)) {// 递归处理 + $dateList = array_merge(self::parseTag($t, $tmin, $tmax), $dateList); + } else { + $dateList[] = $t; + } + } + } + else if (false !== strpos($tag, '/') && false !== strpos($tag, '-')) { + list($number, $mod) = explode('/', $tag); + list($left, $right) = explode('-', $number); + if ($left > $right) { + throw new \Exception("$tag 不支持"); + } + foreach (range($left, $right) as $n) { + if ($n % $mod === 0) { + $dateList[] = $n; + } + } + } + else if (false !== strpos($tag, '/')) { + $tmp = explode('/', $tag); + $step = isset($tmp[1]) ? $tmp[1] : 1; + $dateList = range($tmin, $tmax, $step); + } + else if (false !== strpos($tag, '-')) { + list($left, $right) = explode('-', $tag); + if ($left > $right) { + throw new \Exception("$tag 不支持"); + } + $dateList = range($left, $right, $step); + } + else { + $dateList = array($tag); + } + + // 越界判断 + foreach ($dateList as $num) { + if ($num < $tmin || $num > $tmax) { + throw new \Exception('数值越界'); + } + } + + sort($dateList); + + return array_unique($dateList); + + } + + /** + * 判断tag是否可再次切割 + * @return 需要切割的标识符|null + */ + private static function checkExp($tag) + { + return (false !== strpos($tag, ',')) || (false !== strpos($tag, '-')) || (false !== strpos($tag, '/')); + } +} \ No newline at end of file diff --git a/extend/excel/Analysis.php b/extend/excel/Analysis.php new file mode 100644 index 0000000..c7afdb3 --- /dev/null +++ b/extend/excel/Analysis.php @@ -0,0 +1,21 @@ +worksheetName && $row >= ($this->startRow + 1) && $row <= ($this->endRow + 1)) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/extend/excel/Excel.php b/extend/excel/Excel.php new file mode 100644 index 0000000..2bab148 --- /dev/null +++ b/extend/excel/Excel.php @@ -0,0 +1,186 @@ + 1, 'msg' => '操作成功'); + protected static $is_active_sheet = true; + + /** + * @param $file + * @return Spreadsheet + * @throws Exception + */ + public static function loadFile($file) + { + $reader = new Xlsx(); + //判断文件类型 + if (!$reader->canRead($file)) { + $spreadsheet = IOFactory::load($file); + return $spreadsheet; + } + $reader->setReadDataOnly(TRUE); + return $reader->load($file); + } + + /** + * @param $filename + * @return bool|int + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + public static function excelToJson($filename, $export) + { + $spreadsheet = self::loadFile($filename); + $flag_row = '1'; + $top_row = '1'; + $body_start_row = '3'; + $sheet = $spreadsheet->getSheet(0); // 读取第一个工作表(编号从 0 开始) + $total_row = $sheet->getHighestRow(); // 取得总行数 + $max_column = $sheet->getHighestColumn(); // 取得总列数 + print("max_column: $max_column \n"); + $arr = array(1 => 'A', 2 => 'B', 3 => 'C', 4 => 'D', 5 => 'E', 6 => 'F', 7 => 'G', 8 => 'H', 9 => 'I', 10 => 'J', 11 => 'K', 12 => 'L', 13 => 'M', 14 => 'N', 15 => 'O', 16 => 'P', 17 => 'Q', 18 => 'R', 19 => 'S', 20 => 'T', 21 => 'U', 22 => 'V', 23 => 'W', 24 => 'X', 25 => 'Y', 26 => 'Z'); + $total_column = array_search($max_column, $arr); + print("total_column: $total_column \n"); + //标记行 + $flag = array(); + for ($column = 1; $column <= $total_column; $column++) { + $val = $sheet->getCellByColumnAndRow($column, $flag_row)->getValue(); + $flag[$column] = trim($val); + } + print('flag:'.json_encode(array_values($flag))." \n"); + //键名行 + $top = array(); + for ($column = 1; $column <= $total_column; $column++) { + if (!$flag[$column]) { + continue; + } + $val = $sheet->getCellByColumnAndRow($column, $top_row)->getValue(); + $top[$column] = trim($val); + } + print('top:'.json_encode(array_values($top))." \n"); + //内容行 + $body = array(); + for ($row = $body_start_row; $row <= $total_row; $row++) { + $temp = array(); + //获取数据 + for ($column = 1; $column <= $total_column; $column++) { + if (!$flag[$column]) { + continue; + } + $val = $sheet->getCellByColumnAndRow($column, $row)->getValue(); + $key = $top[$column]; + $temp[$key] = trim($val); + } + $body[] = $temp; + } + return FileSystem::saveFile($export, $body); + } + + /** + * @param $import + * @param $export + * @return array + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + public static function batchExcelToJson($import, $export) + { + $dirs = FileSystem::scanFile($import); + foreach ($dirs as $name => $dir) { + if (is_array($dir)) { + foreach ($dir as $file) { + print("filename: $file \n"); + $result[$name][] = self::excelToJson($import . $name . '/' . $file, $export . $name . '/' . $file); + } + } else { + print("filename: $dir \n"); + $result[] = self::excelToJson($import . $dir, $export . $dir); + } + } + return $result; + } + + /** + * 切割文件 + * @param $file + * @param $num + * @return array + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception + */ + public static function divisionFile($file, $num) + { + $tempDir = FileSystem::getRuntimePath() . 'tmp/'; + list($fileName,) = explode('.', basename($file)); + $spreadsheetReader = self::loadFile($file); + $sheet = $spreadsheetReader->getSheet(0); + $highestRow = $sheet->getHighestRow(); // e.g. 10 + $highestColumn = $sheet->getHighestColumn(); // e.g 'F' + $highestColumnIndex = Coordinate::columnIndexFromString($highestColumn); // e.g. 5 + $title = array_pop($sheet->rangeToArray( + "A1:{$highestColumn}1", // 要检索的工作表区域 + NULL, // 空单元格返回的值 + TRUE, // 计算值 + TRUE, // 格式化值 + TRUE // 数组应按单元格行和单元格列编制索引 + )); + $row_array = []; + $files = []; + $arg_num = ceil($highestRow / $num); + for ($row = 2; $row <= $highestRow; $row++) { + $row_array[] = array_pop($sheet->rangeToArray( + "A{$row}:{$highestColumn}{$row}", // 要检索的工作表区域 + NULL, // 空单元格返回的值 + TRUE, // 计算值 + TRUE, // 格式化值 + TRUE // 数组应按单元格行和单元格列编制索引 + )); + if($row == $arg_num) { + $saveFile = $tempDir . $fileName . '_'. $row .'.csv'; + self::createFile($saveFile, array_merge($title,$row_array), 'csv'); + $files[] = $saveFile; + $row_array = []; + } + } + return $files; + } + + /** + * 创建文件 + * @param $save_file + * @param $data + * @param $ext + * @throws \PhpOffice\PhpSpreadsheet\Exception + * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception + */ + public static function createFile($save_file, $data, $ext) + { + $data = array_values($data); + if(!file_exists($save_file)){ + FileSystem::saveFile($save_file); + } + $spreadsheetWriter = new Spreadsheet(); + $letter = array(1 => 'A', 2 => 'B', 3 => 'C', 4 => 'D', 5 => 'E', 6 => 'F', 7 => 'G', 8 => 'H', 9 => 'I', 10 => 'J', 11 => 'K', 12 => 'L', 13 => 'M', 14 => 'N', 15 => 'O', 16 => 'P', 17 => 'Q', 18 => 'R', 19 => 'S', 20 => 'T', 21 => 'U', 22 => 'V', 23 => 'W', 24 => 'X', 25 => 'Y', 26 => 'Z'); + $row_num = count($data); + for ($row = 1; $row <= $row_num; $row++) { + $data[$row] = array_values($data[$row]); + $col_num = count($data[$row]); + for ($col = 1; $col <= $col_num; $col++) { + $spreadsheetWriter->getActiveSheet()->setCellValue($letter[$col] . $row, $data[$row][$col]); + } + } + $writer = IOFactory::createWriter($spreadsheetWriter, ucfirst($ext)); + $writer->save($save_file); + $spreadsheetWriter->disconnectWorksheets(); + unset($spreadsheetWriter); + } +} \ No newline at end of file diff --git a/extend/excel/ReadAheadFilter.php b/extend/excel/ReadAheadFilter.php new file mode 100644 index 0000000..df0d312 --- /dev/null +++ b/extend/excel/ReadAheadFilter.php @@ -0,0 +1,26 @@ +record[$worksheetName])) { + if ($this->lastRow != $row) { + $this->record[$worksheetName]++; + $this->lastRow = $row; + } + } else { + $this->record[$worksheetName] = 1; + $this->lastRow = $row; + } + return false; + } +} \ No newline at end of file diff --git a/extend/file/FileSystem.php b/extend/file/FileSystem.php new file mode 100644 index 0000000..86ac311 --- /dev/null +++ b/extend/file/FileSystem.php @@ -0,0 +1,250 @@ +=0 ? $start: 0; + if($end !=0 && $start > $end){ + $temp = $start; + $start = $end; + $end = $start; + } + while (!feof($handle)) { + ++$n; + $str = fgets($handle, 4096); + if ($start <= $n && trim($str) != '') { + $encode = mb_detect_encoding($str, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5')); + if($encode){ + $str = mb_convert_encoding($str, 'UTF-8', $encode); + }else { + $str = mb_convert_encoding($str, 'UTF-8'); + } + if($callback){ + $data[] = call_user_func($callback, $str); + }else { + $data[] = $str; + } + } + if ($end == $n) break; + } + fclose($handle); + return $data; + } +} \ No newline at end of file diff --git a/extend/file/FileSystem.php.bak b/extend/file/FileSystem.php.bak new file mode 100644 index 0000000..e8fae5b --- /dev/null +++ b/extend/file/FileSystem.php.bak @@ -0,0 +1,250 @@ +=0 ? $start: 0; + if($end !=0 && $start > $end){ + $temp = $start; + $start = $end; + $end = $start; + } + while (!feof($handle)) { + ++$n; + $str = fgets($handle, 4096); + if ($start <= $n && trim($str) != '') { + if($callback){ + $encode = mb_detect_encoding($str, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5')); + if($encode){ + $str = mb_convert_encoding($str, 'UTF-8', $encode); + }else { + $str = mb_convert_encoding($str, 'UTF-8'); + } + $data[] = call_user_func($callback, $str); + }else { + $data[] = $str; + } + } + if ($end == $n) break; + } + fclose($handle); + return $data; + } +} \ No newline at end of file diff --git a/extend/library/Tree.php b/extend/library/Tree.php new file mode 100644 index 0000000..f4f5f26 --- /dev/null +++ b/extend/library/Tree.php @@ -0,0 +1,443 @@ +data = $arr; + $this->res = ''; + return is_array($arr); + } + + public function setNode($id, $value, $parent = 0) + { + $this->data[$id] = $value; + $this->cateArray[$id] = $parent; + } + + public function getAllChildrenNodes($id = 0,\Closure $compFunc = null,\Closure $retFunc = null) + { + $result = []; + $children = array_keys($this->cateArray, $id); + if ($id > 0 && $compFunc && $compFunc($this->data[$id])) { + $result = $retFunc === null ? $id : $retFunc($this->data[$id]); + } else if (count($children) > 0) { + foreach ($children as $child) { + $result = array_merge($result, $this->getAllChildrenNodes($child, $compFunc, $retFunc)); + } + } else { + $result = $retFunc === null ? $id: $retFunc($this->data[$id]); + } + return $result; + } + + public function getChildsTree($id = 0) + { + $childs = array(); + foreach ($this->cateArray as $child => $parent) { + if ($parent == $id) { + $childs[$child] = $this->getChildsTree($child); + } + } + return $childs; + } + + + public function getParentsTree($id = 0) + { + $parents = array(); + foreach ($this->cateArray as $child => $parent) { + if ($child == $id) { + $parents[$parent] = $this->getParentsTree($parent); + } + } + return $parents; + } + + public function getChilds($id = 0) + { + $childArray = array(); + $childs = $this->getChild($id); + foreach ($childs as $child) { + $childArray[] = $child; + $childArray = array_merge($childArray, $this->getChilds($child)); + } + return $childArray; + } + + public function getChild($id) + { + $childs = array(); + foreach ($this->cateArray as $child => $parent) { + if ($parent == $id) { + $childs[$child] = $child; + } + } + return $childs; + } + + public function getParents($id) + { + $parentArray = array(); + $parents = $this->getParent($id); + foreach ($parents as $parent) { + $parentArray[] = $parent; + $parentArray = array_merge($parentArray, $this->getParents($parent)); + } + return $parentArray; + } + + public function getParent($id) + { + $parents = array(); + foreach ($this->cateArray as $child => $parent) { + if ($child == $id) { + $parents[$parent] = $parent; + } + } + return $parents; + } + + //单线获取父节点 + public function getNodeLever($id) + { + $parents = array(); + if (key_exists($this->cateArray[$id], $this->cateArray)) { + $parents[] = $this->cateArray[$id]; + $parents = array_merge($parents, $this->getNodeLever($this->cateArray[$id])); + } + return $parents; + } + + public function getLayer($id, $preStr = '|-') + { + return str_repeat($preStr, count($this->getNodeLever($id))); + } + + public function getValue($id) + { + return $this->data[$id]; + } + + //获取所有节点数据生成树 + public function getTreeShow($id = 0, $str = "|-") + { + if ($id != 0) { + $str = $str . "|-"; + } + //遍历所有数组检查parent是否有id + foreach ($this->cateArray as $child => $parent) { + //检查是否有相等的ID + if ($parent == $id) { + $showname = $this->getValue($child); + if(is_string($showname)){ + $this->res[$child] = $str . $showname; + }else if(is_array($showname) && isset($showname['name'])){ + $this->res[$child] = $str . $showname['name']; + }else { + $this->res[$child] = $str . $child; + } + $this->getTreeShow($child, $str); + } + } + } +} + +//class Tree +//{ +// /** +// * 生成树型结构所需要的2维数组 +// * @var array +// */ +// public $arr = array(); +// +// /** +// * 生成树型结构所需修饰符号,可以换成图片 +// * @var array +// */ +// public $icon = array('│', '├', '└'); +// public $nbsp = " "; +// +// /** +// * @access private +// */ +// public $ret = ''; +// +// /** +// * 构造函数,初始化类 +// * @param array 2维数组,例如: +// * array( +// * 1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'), +// * 2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'), +// * 3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'), +// * 4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'), +// * 5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'), +// * 6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'), +// * 7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二') +// * ) +// */ +// public function init($arr = array()) +// { +// $this->arr = $arr; +// $this->ret = ''; +// return is_array($arr); +// } +// +// /** +// * 得到父级数组 +// * @param int +// * @return array +// */ +// public function get_parent($myid) +// { +// $newarr = array(); +// if (!isset($this->arr[$myid])) return false; +// $pid = $this->arr[$myid]['parentid']; +// $pid = $this->arr[$pid]['parentid']; +// if (is_array($this->arr)) { +// foreach ($this->arr as $id => $a) { +// if ($a['parentid'] == $pid) $newarr[$id] = $a; +// } +// } +// return $newarr; +// } +// +// /** +// * 得到子级数组 +// * @param int +// * @return array +// */ +// public function get_child($myid) +// { +// $a = $newarr = array(); +// if (is_array($this->arr)) { +// foreach ($this->arr as $id => $a) { +// if ($a['parentid'] == $myid) $newarr[$id] = $a; +// } +// } +// return $newarr ? $newarr : false; +// } +// +// /** +// * 得到当前位置数组 +// * @param int +// * @return array +// */ +// public function get_pos($myid, &$newarr) +// { +// $a = array(); +// if (!isset($this->arr[$myid])) return false; +// $newarr[] = $this->arr[$myid]; +// $pid = $this->arr[$myid]['parentid']; +// if (isset($this->arr[$pid])) { +// $this->get_pos($pid, $newarr); +// } +// if (is_array($newarr)) { +// krsort($newarr); +// foreach ($newarr as $v) { +// $a[$v['id']] = $v; +// } +// } +// return $a; +// } +// +// /** +// * 得到树型结构 +// * @param int ID,表示获得这个ID下的所有子级 +// * @param string 生成树型结构的基本代码,例如:"" +// * @param int 被选中的ID,比如在做树型下拉框的时候需要用到 +// * @return string +// */ +// public function get_tree($myid, $str, $sid = 0, $adds = '', $str_group = '') +// { +// $number = 1; +// $child = $this->get_child($myid); +// if (is_array($child)) { +// $total = count($child); +// foreach ($child as $id => $value) { +// $j = $k = ''; +// if ($number == $total) { +// $j .= $this->icon[2]; +// } else { +// $j .= $this->icon[1]; +// $k = $adds ? $this->icon[0] : ''; +// } +// $spacer = $adds ? $adds . $j : ''; +// $selected = $id == $sid ? 'selected' : ''; +// @extract($value); +// $parentid == 0 && $str_group ? eval("\$nstr = \"$str_group\";") : eval("\$nstr = \"$str\";"); +// $this->ret .= $nstr; +// $nbsp = $this->nbsp; +// $this->get_tree($id, $str, $sid, $adds . $k . $nbsp, $str_group); +// $number++; +// } +// } +// return $this->ret; +// } +// +// /** +// * 同上一方法类似,但允许多选 +// */ +// public function get_tree_multi($myid, $str, $sid = 0, $adds = '') +// { +// $number = 1; +// $child = $this->get_child($myid); +// if (is_array($child)) { +// $total = count($child); +// foreach ($child as $id => $a) { +// $j = $k = ''; +// if ($number == $total) { +// $j .= $this->icon[2]; +// } else { +// $j .= $this->icon[1]; +// $k = $adds ? $this->icon[0] : ''; +// } +// $spacer = $adds ? $adds . $j : ''; +// +// $selected = $this->have($sid, $id) ? 'selected' : ''; +// @extract($a); +// eval("\$nstr = \"$str\";"); +// $this->ret .= $nstr; +// $this->get_tree_multi($id, $str, $sid, $adds . $k . ' '); +// $number++; +// } +// } +// return $this->ret; +// } +// +// /** +// * @param integer $myid 要查询的ID +// * @param string $str 第一种HTML代码方式 +// * @param string $str2 第二种HTML代码方式 +// * @param integer $sid 默认选中 +// * @param integer $adds 前缀 +// */ +// public function get_tree_category($myid, $str, $str2, $sid = 0, $adds = '') +// { +// $number = 1; +// $child = $this->get_child($myid); +// if (is_array($child)) { +// $total = count($child); +// foreach ($child as $id => $a) { +// $j = $k = ''; +// if ($number == $total) { +// $j .= $this->icon[2]; +// } else { +// $j .= $this->icon[1]; +// $k = $adds ? $this->icon[0] : ''; +// } +// $spacer = $adds ? $adds . $j : ''; +// +// $selected = $this->have($sid, $id) ? 'selected' : ''; +// @extract($a); +// if (empty($html_disabled)) { +// eval("\$nstr = \"$str\";"); +// } else { +// eval("\$nstr = \"$str2\";"); +// } +// $this->ret .= $nstr; +// $this->get_tree_category($id, $str, $str2, $sid, $adds . $k . ' '); +// $number++; +// } +// } +// return $this->ret; +// } +// +// /** +// * 同上一类方法,jquery treeview 风格,可伸缩样式(需要treeview插件支持) +// * @param $myid 表示获得这个ID下的所有子级 +// * @param $effected_id 需要生成treeview目录数的id +// * @param $str 末级样式 +// * @param $str2 目录级别样式 +// * @param $showlevel 直接显示层级数,其余为异步显示,0为全部限制 +// * @param $style 目录样式 默认 filetree 可增加其他样式如'filetree treeview-famfamfam' +// * @param $currentlevel 计算当前层级,递归使用 适用改函数时不需要用该参数 +// * @param $recursion 递归使用 外部调用时为FALSE +// */ +// function get_treeview($myid, $effected_id = 'example', $str = "\$name", $str2 = "\$name", $showlevel = 0, $style = 'filetree ', $currentlevel = 1, $recursion = FALSE) +// { +// $child = $this->get_child($myid); +// if (!defined('EFFECTED_INIT')) { +// $effected = ' id="' . $effected_id . '"'; +// define('EFFECTED_INIT', 1); +// } else { +// $effected = ''; +// } +// $placeholder = ''; +// if (!$recursion) $this->str .= ''; +// foreach ($child as $id => $a) { +// +// @extract($a); +// if ($showlevel > 0 && $showlevel == $currentlevel && $this->get_child($id)) $folder = 'hasChildren'; //如设置显示层级模式@2011.07.01 +// $floder_status = isset($folder) ? ' class="' . $folder . '"' : ''; +// $this->str .= $recursion ? '' : ''; +// } +// if (!$recursion) $this->str .= ''; +// return $this->str; +// } +// +// /** +// * 获取子栏目json +// * Enter description here ... +// * @param unknown_type $myid +// */ +// public function creat_sub_json($myid, $str = '') +// { +// $sub_cats = $this->get_child($myid); +// $n = 0; +// if (is_array($sub_cats)) foreach ($sub_cats as $c) { +// $data[$n]['id'] = iconv(CHARSET, 'utf-8', $c['catid']); +// if ($this->get_child($c['catid'])) { +// $data[$n]['liclass'] = 'hasChildren'; +// $data[$n]['children'] = array(array('text' => ' ', 'classes' => 'placeholder')); +// $data[$n]['classes'] = 'folder'; +// $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']); +// } else { +// if ($str) { +// @extract(array_iconv($c, CHARSET, 'utf-8')); +// eval("\$data[$n]['text'] = \"$str\";"); +// } else { +// $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']); +// } +// } +// $n++; +// } +// return json_encode($data); +// } +// +// private function have($list, $item) +// { +// return (strpos(',,' . $list . ',', ',' . $item . ',')); +// } +//} diff --git a/extend/service/CarInfoHandle.php b/extend/service/CarInfoHandle.php new file mode 100644 index 0000000..000c4ce --- /dev/null +++ b/extend/service/CarInfoHandle.php @@ -0,0 +1,626 @@ +insertAll($insert_data); + cache('shell_process_' . $id, round(($i + 2000) / $lines * 100, 3), 300); + echo '当前进度:' . round(round(($i + 2000) / $lines * 100, 3)) . PHP_EOL; + } + Db::execute('ALTER TABLE car_info_t ENABLE KEYS;'); + return '导入成功:' . ($lines - 1); + } + + /** + * @param $data + * @param $id + * @return string + */ + public function export($data, $id) + { + $where = []; + $map_or1 = []; + $map_or2 = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $where[] = ['car_info_t.register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $where[] = ['car_info_t.register_date', '<=', $data['export_date2']]; + } + if (isset($data['price1']) && $data['price1'] != '') { + $where[] = ['car_info_t.purchase_price', '>=', $data['price1'] * 10000]; + } + if (isset($data['price2']) && $data['price2'] != '') { + $where[] = ['car_info_t.purchase_price', '<=', $data['price2'] * 10000]; + } + if (isset($data['empty_phone_check']) && $data['empty_phone_check'] == 'yes') { + $where[] = ['car_phone', '<>', '']; + } + if (isset($data['export_field'])) { + foreach ($data['export_field'] as $item) { + $where[] = [$item, '<>', '']; + } + } + if (isset($data['export_type']) && $data['export_type'] != '' && $data['export_limit'] != 0) { + if($data['export_type'] == 'bhx'){ + $where[] = ['is_export_bhx', '=', 0]; + $where[] = ['is_update_bhx', '=', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + } + if($data['export_type'] == 'bmc'){ + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '>', 0]; + $where[] = ['is_export_bmc', '=', 0]; + } + if ($data['export_type'] == 'failed') { + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '<', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + } + if ($data['export_type'] == 'failed_bmc') { + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '<', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + } + if ($data['export_type'] == 'none_bmc') { + $where[] = ['is_export_bhx', '=', 0]; + $where[] = ['is_update_bhx', '=', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + $where[] = ['is_export_none_bmc', '=', 0]; + } + } + $insurer_month1 = $data['insurer_month1']??''; + $insurer_day1 = $data['insurer_day1']??''; + $insurer_month2 = $data['insurer_month2']??''; + $insurer_day2 = $data['insurer_day2']??''; + if($insurer_month1 != '' && $insurer_day1 == '') { + $map_or1[] = [Db::raw('month(car_info_t.insurer1_date)'), '>=', $insurer_month1]; + $map_or2[] = [Db::raw('month(car_info_t.insurer2_date)'), '>=', $insurer_month1]; + } else if ($insurer_month1 == '' && $insurer_day1 != '') { + $map_or1[] = [Db::raw('day(car_info_t.insurer1_date)'), '>=', $insurer_day1]; + $map_or2[] = [Db::raw('day(car_info_t.insurer2_date)'), '>=', $insurer_day1]; + } else if ($insurer_month1 != '' && $insurer_day1 != '') { + $map_or1[] = [Db::raw('DATE_FORMAT(car_info_t.insurer1_date,"%m-%d")'), '>=', substr('0' . $insurer_month1, -2) . '-' . substr('0' . $insurer_day1, -2)]; + $map_or2[] = [Db::raw('DATE_FORMAT(car_info_t.insurer2_date,"%m-%d")'), '>=', substr('0' . $insurer_month1, -2) . '-' . substr('0' . $insurer_day1, -2)]; + } + if($insurer_month2 != '' && $insurer_day2 == '') { + $map_or1[] = [Db::raw('month(car_info_t.insurer1_date)'), '<=', $insurer_month2]; + $map_or2[] = [Db::raw('month(car_info_t.insurer2_date)'), '<=', $insurer_month2]; + } else if ($insurer_month2 == '' && $insurer_day2 != '') { + $map_or1[] = [Db::raw('day(car_info_t.insurer1_date)'), '<=', $insurer_day2]; + $map_or2[] = [Db::raw('day(car_info_t.insurer2_date)'), '<=', $insurer_day2]; + } else if ($insurer_month2 != '' && $insurer_day2 != '') { + $map_or1[] = [Db::raw('DATE_FORMAT(car_info_t.insurer1_date,"%m-%d")'), '<=', substr('0' . $insurer_month2, -2) . '-' . substr('0' . $insurer_day2, -2)]; + $map_or2[] = [Db::raw('DATE_FORMAT(car_info_t.insurer2_date,"%m-%d")'), '<=', substr('0' . $insurer_month2, -2) . '-' . substr('0' . $insurer_day2, -2)]; + } + if (count($map_or1) > 0) { + $map_or1 = array_merge([['car_info_t.insurer1_date', '<>', '']], $map_or1); + } + if (count($map_or2) > 0) { + $map_or2 = array_merge([['car_info_t.insurer1_date', '=', ''], ['car_info_t.insurer2_date', '<>', '']], $map_or2); + } + $query = CarInfoT::where($where)->where(function ($query) use ($map_or1, $map_or2) { + if (count($map_or1) > 0 && count($map_or2) > 0) { + $query->whereOr([$map_or1, $map_or2]); + } + }); + if ($data['export_type'] == 'repeat') { + if ($data['export_table'] == 'repeat_frame_t') { + $query = RepeatFrameT::leftjoin('car_info_t', 'repeat_frame_t.car_frame_no = car_info_t.car_frame_no') + ->field('car_info_t.*')->order('car_info_t.register_date asc') + ->where('repeat_frame_t.source', $data['source_id']); + } else if ($data['export_table'] == 'peer_phone_t') { + $query = $query->rightJoin('peer_phone_t', 'peer_phone_t.phone = car_info_t.car_phone') + ->field('car_info_t.*')->order('car_info_t.register_date asc') + ->where([['peer_phone_t.source', '=', $data['source_id']],['car_info_t.car_number', 'REGEXP', '^[1-9][[:digit:]]{7}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}$|^[1-9][[:digit:]]{5}[1-9][[:digit:]]{3}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}([0-9]|X)$']]); + } + }else { + $query = $query->order('register_date asc'); + } + $count = $query->count(); + $count = $count <= $data['export_limit'] || $data['export_limit'] == 0 ? $count : $data['export_limit']; + echo '总计:' . $count . PHP_EOL; + cache('shell_process_' . $id, 0, 300); + $data['export_field'] = $data['export_field'] ?? []; + list($titles, $fields) = $this->getTitleAndField($data['export_type'], $data['export_field']); + if (isset($data['is_excel']) && $data['is_excel'] == 'yes') { + $basename = '/export/' . date('YmdHis') . '.xlsx'; + $this->exportExcel($data['export_type'], $data['export_limit'], $titles, $fields, root_path() . 'public' . $basename, $query, $count, $id); + } else { + $basename = '/export/' . date('YmdHis') . '.csv'; + $this->exportCsv($data['export_type'], $data['export_limit'], $titles, $fields, root_path() . 'public' . $basename, $query, $count, $id); + } + $this->setProcess($count, $count, $id); + $this->addExportLog($count, $data['export_type'],$id); + return $basename; + } + + public function peerPhones($data, $id) + { + $where = [ + ['car_phone', '<>', ''], + ['car_number', 'REGEXP', '^[1-9][[:digit:]]{7}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}$|^[1-9][[:digit:]]{5}[1-9][[:digit:]]{3}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}([0-9]|X)$'] + ]; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + $query = CarInfoT::field('car_phone,count(*) as count') + ->where($where) + ->where($map) + ->group('car_phone'); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $peer_phone_number = $data['peer_phone_number']; + $peer_phone_count = $repeat_count = 0; + cache('shell_process_' . $id, 0, 300); + $query->chunk(3000, function ($infos) use (&$current, &$peer_phone_count, &$repeat_count, $count, $id, $peer_phone_number, $map) { + $insert_data = []; + foreach ($infos as $item) { + if ($item->count >= $peer_phone_number) { + $card_ids = CarInfoT::where('car_phone', $item->car_phone)->where($map)->column('car_number'); + if (count(array_flip(array_flip($card_ids))) <= 1) { + continue; + } + $insert_data[] = [ + 'phone' => $item->car_phone, + 'source' => $id, + ]; + $peer_phone_count++; + $repeat_count += $item->count; + } + $current++; + } + PeerPhoneT::duplicate(Db::raw('phone = values(phone), source = values(source)'))->insertAll($insert_data); + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + }, 'car_phone'); + return '重复总数:' . $repeat_count . ', 重复电话数:' . $peer_phone_count; + } + + public function carFrameNo($data, $id) + { + $where = [ + ['car_frame_no', '<>', ''] + ]; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $where[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $where[] = ['register_date', '<=', $data['export_date2']]; + } + $query = CarInfoT::field('car_frame_no,count(*) as count') + ->where($where) + ->group('car_frame_no') + ->having('count>=2'); + $current = $repeat_frame_count = 0; + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + cache('shell_process_' . $id, 0, 300); + $query->chunk(3000, function ($infos) use (&$current, &$repeat_frame_count, $count, $id) { + $insert_data = []; + foreach ($infos as $item) { + $insert_data[] = [ + 'car_frame_no' => $item->car_frame_no, + 'source' => $id, + ]; + $current++; + $repeat_frame_count += $item->count; + } + RepeatFrameT::duplicate(Db::raw('source = values(source)'))->insertAll($insert_data); + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + }, 'car_frame_no'); + return '重复总数:' . $repeat_frame_count . ', 重复车架数:' . $count; + } + + public function deletePeerPhones($data, $id) + { + $query = PeerPhoneT::where(['source' => $data['source_id']]); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $faild_num = 0; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + cache('shell_process_' . $id, 0, 300); + $query->chunk(1000, function ($infos) use (&$current, &$faild_num, $count, $id, $map) { + foreach ($infos as $item) { + if ($current % 10 == 0) { + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + } + $ids = CarInfoT::where('car_phone', $item->phone)->where($map)->column('id'); + Db::startTrans(); + try { + CarInfoT::where('id', 'in', $ids) + ->update(['car_phone' => '']);; + PeerPhoneT::where('phone', $item->phone)->delete(); + Db::commit(); + } catch (\Exception $e) { + $faild_num++; + Db::rollback(); + } + $current++; + } + }, 'phone'); + return '处理总数:' . $count . ', 失败总数:' . $faild_num; + } + + public function deleteCarFrameNo($data, $id) + { + $query = RepeatFrameT::where(['source' => $data['source_id']]); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $faild_num = 0; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + cache('shell_process_' . $id, 0, 300); + $query->chunk(1000, function ($infos) use (&$current, &$faild_num, $count, $id, $map) { + foreach ($infos as $item) { + if ($current % 10 == 0) { + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + } + $ids = CarInfoT::where(['car_frame_no' => $item->car_frame_no])->where($map)->order('car_phone desc, insurer1_date desc, car_no desc, id desc')->column('id'); + array_shift($ids); + Db::startTrans(); + try { + CarInfoT::destroy($ids); + RepeatFrameT::where('car_frame_no', $item->car_frame_no)->delete(); + Db::commit(); + } catch (\Exception $e) { + $faild_num++; + Db::rollback(); + } + $current++; + } + }, 'car_frame_no'); + return '处理总数:' . $count . ', 失败总数:' . $faild_num; + } + + public function carInfoUpdate($data, $id) + { + $filename = public_path('public/storage') . $data['filename']; + if (empty($filename) OR !file_exists($filename)) { + return '文件不存在!'; + } + $spreadRead = Excel::loadFile($filename); + $worksheet = $spreadRead->getSheet(0); + $highestRow = $worksheet->getHighestRow(); // e.g. 10 + $total = $highestRow - 1; + echo '总计:' . $total . PHP_EOL; + $statistical_information = [ + 'total_all' => $total, + 'total_skip' => 0, + 'total_insert' => 0, + 'total_update' => 0, + 'total_error' => 0, + 'total_error_arr' => [], + 'total_skip_arr' => [], + ]; + $is_update_failed = 0; + for ($row = 2; $row <= $highestRow; $row++) { + $car_no = trim($worksheet->getCellByColumnAndRow(1, $row)->getValue()); + $car_man = trim($worksheet->getCellByColumnAndRow(2, $row)->getValue()); + $factory_model = trim($worksheet->getCellByColumnAndRow(3, $row)->getValue()); + $engine_no = trim($worksheet->getCellByColumnAndRow(4, $row)->getValue()); + $car_frame_no = trim($worksheet->getCellByColumnAndRow(5, $row)->getValue()); + $register_date = trim($worksheet->getCellByColumnAndRow(6, $row)->getValue()); + $company = trim($worksheet->getCellByColumnAndRow(7, $row)->getValue()); + $insurer1_date = trim($worksheet->getCellByColumnAndRow(8, $row)->getValue()); + $insurer2_date = trim($worksheet->getCellByColumnAndRow(9, $row)->getValue()); + $id_man = trim($worksheet->getCellByColumnAndRow(10, $row)->getValue()); + $id_number = trim($worksheet->getCellByColumnAndRow(11, $row)->getValue()); + if($car_frame_no == ''){ + continue; + } + $car_info = CarInfoT::where('car_frame_no', $car_frame_no)->find(); + if (isset($car_info)) { + if ($is_update_failed == 0 && $car_info->is_export_failed > 0) { + + $is_update_failed = $car_info->is_export_failed; + } + $car_info->car_no = $car_no != '' ? $car_no : $car_info->car_no; + $car_info->car_man = $car_info->car_man != '' ? $car_info->car_man : $car_man; + $car_info->register_date = $register_date; + $car_info->factory_model = $factory_model; + //对比原信息是否包含待更新信息(删除星号) + $car_info->engine_no = $car_info->engine_no != '' && startsWith($car_info->engine_no, rtrim($engine_no, '*')) ? $car_info->engine_no : $engine_no; + $insurer1_flag = strtotime(date('Y', strtotime($insurer1_date))) > strtotime(date('Y', strtotime($car_info->insurer1_date))); + if ($insurer1_flag) { + $car_info->insurer1_date = $insurer1_date; + } + $insurer2_flag = strtotime(date('Y', strtotime($insurer2_date))) > strtotime(date('Y', strtotime($car_info->insurer2_date))); + if ($insurer2_flag) { + $car_info->insurer2_date = $insurer2_date; + } + if (($car_info->insurer1_date != '' && $insurer1_flag) || ($car_info->insurer2_date != '' && $insurer2_flag) || $car_info->insurer1_date == '' || $car_info->insurer2_date == '') { + $car_info->company = $company != '' ? $company : $car_info->company; + $car_info->id_man = $car_info->id_man != '' && startsWith($car_info->id_man, rtrim($id_man, '*')) ? $car_info->id_man : $id_man; + $car_info->id_number = $car_info->id_number != '' && startsWith($car_info->id_number, rtrim($id_number, '*')) ? $car_info->id_number : $id_number; + } + $car_info->is_update_bhx = $id; + $car_info->is_export_failed = 0; + if (!$car_info->save()) { + $statistical_information['total_error']++; + $statistical_information['total_error_arr'][] = $row; + } else { + $statistical_information['total_update']++; + } + } else { + $statistical_information['total_skip_arr'][] = $row; + $statistical_information['total_skip']++; + } + cache('shell_process_' . $id, round($row / $total * 100, 3), 300); + echo '当前进度:' . round($row / $total * 100, 3) . PHP_EOL; + } + if($is_update_failed > 0){ + CarInfoT::where('is_export_failed', $is_update_failed) + ->update(['is_export_failed' => 0, 'is_update_bhx' => Db::raw('is_update_bhx - 1')]); + }else if($car_info) { + CarInfoT::where('is_update_bhx', 0) + ->where('is_export_bhx', $car_info->is_export_bhx) + ->update(['is_update_bhx' => -1]); + } + return '操作成功' . "数据总计{$statistical_information['total_all']}条, + 更新{$statistical_information['total_update']}, + 失败{$statistical_information['total_error']}, + 失败数据列:" . implode(',', $statistical_information['total_error_arr']) . ", + 跳过{$statistical_information['total_skip']}, + 跳过数据列:" . implode(',', $statistical_information['total_skip_arr']); + } + + private function importExcel($data, $id) + { + $filename = public_path('public/storage') . $data['filename']; + $t1 = microtime(true); + $spreadRead = Excel::loadFile($filename); + $worksheet = $spreadRead->getSheet(0); + $highestRow = $worksheet->getHighestRow(); // e.g. 10 + echo '总计:' . $highestRow . PHP_EOL; + $now = date('Y-m-d H:i:s'); + Db::execute('ALTER TABLE car_info_t DISABLE KEYS;'); + for ($row = 2; $row <= $highestRow; $row++) { + $row_array[] = [ + 'duty_no' => $worksheet->getCellByColumnAndRow(1, $row)->getValue(), + 'register_date' => $worksheet->getCellByColumnAndRow(2, $row)->getValue(), + 'car_man' => $worksheet->getCellByColumnAndRow(3, $row)->getValue(), + 'car_number' => $worksheet->getCellByColumnAndRow(4, $row)->getValue(), + 'car_phone' => $worksheet->getCellByColumnAndRow(5, $row)->getValue(), + 'car_frame_no' => $worksheet->getCellByColumnAndRow(6, $row)->getValue(), + 'car_no' => $worksheet->getCellByColumnAndRow(7, $row)->getValue(), + 'engine_no' => $worksheet->getCellByColumnAndRow(8, $row)->getValue(), + 'factory_model' => $worksheet->getCellByColumnAndRow(9, $row)->getValue(), + 'purchase_price' => $worksheet->getCellByColumnAndRow(10, $row)->getValue(), + 'create_timestamp' => $now, + 'update_timestamp' => $now + ]; + if ($row >= 1000) { + Db::name('car_info_t')->insertAll($row_array); + cache('shell_process_' . $id, round(($i + 2000) / $lines * 100, 3), 300); + echo '当前进度:' . round(round(($i + 2000) / $lines * 100, 3)) . PHP_EOL; + $row_array = []; + } + } + Db::execute('ALTER TABLE car_info_t ENABLE KEYS;'); + $t2 = microtime(true); + echo '耗时' . round($t2 - $t1, 3) . '秒' . PHP_EOL; + echo 'Now memory_get_usage: ' . memory_get_usage() . PHP_EOL; + return '导入成功:' . ($highestRow - 1); + } + + private function exportCsv($export_type, $export_limit, $titles, $fields, $filename, $query, $count, $id) + { + $head = ''; + foreach ($titles as $val) { + if ($val == 'line') { + $head .= "\r\n"; + continue; + } + $head .= "\"{$val}\t\","; + } + $head = substr($head, 0, -1) . "\r\n"; + if (file_exists($filename)) { + unlink($filename); + } + if (is_dir(pathinfo($filename, PATHINFO_DIRNAME))) { + file_put_contents($filename, $head); + } else { + mkdir(pathinfo($filename, PATHINFO_DIRNAME), 0777); + file_put_contents($filename, $head); + } + $current = 0; + if ($count <= 3000) { + $ids = []; + $content = ''; + foreach ($query->limit($count)->select() as $item) { + $ids[] = $item->id; + foreach ($fields as $field) { + $content .= "\"" . ($item->$field ?: '') . "\"\t,"; + } + $content = substr($content, 0, -1) . "\r\n"; + $this->setProcess(++$current, $count, $id); + } + FileSystem::appendWriteFile($filename, $content, false); + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + } else { + $info = $query->limit(3000)->select(); + $limit = $count; + while ($limit > 0) { + $ids = []; + $content = ''; + foreach ($info as $item) { + $ids[] = $item->id; + foreach ($fields as $field) { + $content .= "\"" . ($item->$field ?: '') . "\"\t,"; + } + $content = substr($content, 0, -1) . "\r\n"; + $this->setProcess(++$current, $count, $id); + } + FileSystem::appendWriteFile($filename, $content, false); + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + $limit -= 3000; + $end = $info->pop(); + $lastRegisterDate = is_array($end) ? $end['register_date'] : $end->getData('register_date'); + $limit > 0 && ($info = $query->where('register_date', '>=', $lastRegisterDate)->limit($limit >= 3000 ? 3000 : $limit)->select()); + } + } + } + + private function exportExcel($export_type, $export_limit, $titles, $fields, $filename, $query, $count, $id) + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet()->setTitle('sheet1'); + $row = 0; + $i = 0; + foreach ($titles as $col => $val) { + if ($val == 'line') { + $row += 1; + $i += 1; + continue; + } + $sheet->setCellValueByColumnAndRow($col + 1 - $i, $row + 1, $val); + } + if ($count <= 3000) { + $ids = []; + foreach ($query->limit($count)->select() as $item) { + $ids[] = $item->id; + $row += 1; + foreach ($fields as $index => $field) { + $sheet->setCellValueExplicitByColumnAndRow($index + 1, $row + 1, ($item->$field ?: ''), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); + } + $this->setProcess($row, $count * 1.2, $id); + } + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + } else { + $info = $query->limit(3000)->select(); + $limit = $count; + while ($limit > 0) { + $ids = []; + foreach ($info as $item) { + $ids[] = $item->id; + $row += 1; + foreach ($fields as $index => $field) { + $sheet->setCellValueExplicitByColumnAndRow($index + 1, $row + 1, ($item->$field ?: ''), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); + } + $this->setProcess($row, $count * 1.2, $id); + } + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + $limit -= 3000; + $end = $info->pop(); + $lastRegisterDate = is_array($end) ? $end['register_date'] : $end->getData('register_date'); + $limit > 0 && ($info = $query->where('register_date', '>=', $lastRegisterDate)->limit($limit >= 3000 ? 3000 : $limit)->select()); + } + } + $writer = new Xlsx($spreadsheet); + $writer->save($filename); + } + + private function setProcess($cur, $count, $id) + { + $process = round($cur / $count * 100, 3); + cache('shell_process_' . $id, $process, 300); + echo '当前进度:' . $process . PHP_EOL; + } + + /** + * @param $export_type + * @param $export_field + * @return array + */ + private function getTitleAndField($export_type, $export_field) + { + $orgTitles = ['区域', '购车日期', '客户姓名', '证件号码', '联系方式', '车架号', '车牌号', '发动机号', '品牌型号', '新车购置价', '保险公司', '商业止保日期', '交强止保日期', '被保险人', '被保险人证件号']; + $bhxTitles = ['line', 'line', '车牌号', '车架号', '发动机号', '车主证件号码', '品牌型号', '注册日期', '去年投保公司', '交强险到期时间', '商业险到期时间', '客户姓名', '客户电话1', '客户电话2', '客户备注', '客户备注2', '客户类别', '业务员姓名', '业务员账号']; + $bmcTitles = ['注册日期', '车牌号', '车架号', '发动机号', '品牌型号', '年款', '排量', '车主', '车主证件号', '联系电话', '新车购置价', '被保险人', '被保险人证件号', '联系电话', '上年承保公司', '商业止保日期', '交强止保日期', 'insurer_type', '联系人', '联系电话', '联系人', '联系电话', '联系人', '联系电话']; + $orgFields = ['duty_no', 'register_date', 'car_man', 'car_number', 'car_phone', 'car_frame_no', 'car_no', 'engine_no', 'factory_model', 'purchase_price', 'compay', 'insurer1_date', 'insurer2_date', 'id_man', 'id_number']; + if (in_array($export_type, ['bhx', 'failed']) && count($export_field) == 1) { + $bhxFields = $export_field[0] == 'car_no' ? ['car_no'] : ['car_empty_item', 'car_frame_no']; + } else { + $bhxFields = ['car_no', 'car_frame_no']; + } + $bmcFields = ['register_date', 'car_no', 'car_frame_no', 'engine_no', 'factory_model', 'car_year', 'displacement', 'car_man', 'car_number', 'car_phone', 'purchase_price', 'id_man', 'id_number', 'id_phone', 'company', 'insurer1_date', 'insurer2_date', 'insurer_type', 'linkman', 'linkphone', 'linkman', 'linkphone', 'linkman', 'linkphone']; + $titles = in_array($export_type, ['bmc','failed_bmc','none_bmc']) ? $bmcTitles : ($export_type == 'repeat' ? $orgTitles : $bhxTitles); + $fields = in_array($export_type, ['bmc','failed_bmc','none_bmc']) ? $bmcFields : ($export_type == 'repeat' ? $orgFields : $bhxFields); + return [$titles, $fields]; + } + + private function addExportLog($total, $export_type, $id) + { + $queue_name = JobsT::where('id',$id)->value('queue'); + $export_log = new ExportLogT; + $export_log->type = $export_type; + $export_log->name = $queue_name; + $export_log->total = $total; + $export_log->create_timestamp = date('Y-m-d H:i:s'); + $export_log->save(); + } +} \ No newline at end of file diff --git a/extend/service/CarInfoHandle.php.bak b/extend/service/CarInfoHandle.php.bak new file mode 100644 index 0000000..7c68fe9 --- /dev/null +++ b/extend/service/CarInfoHandle.php.bak @@ -0,0 +1,626 @@ +insertAll($insert_data); + cache('shell_process_' . $id, round(($i + 2000) / $lines * 100, 3), 300); + echo '当前进度:' . round(round(($i + 2000) / $lines * 100, 3)) . PHP_EOL; + } + Db::execute('ALTER TABLE car_info_t ENABLE KEYS;'); + return '导入成功:' . ($lines - 1); + } + + /** + * @param $data + * @param $id + * @return string + */ + public function export($data, $id) + { + $where = []; + $map_or1 = []; + $map_or2 = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $where[] = ['car_info_t.register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $where[] = ['car_info_t.register_date', '<=', $data['export_date2']]; + } + if (isset($data['price1']) && $data['price1'] != '') { + $where[] = ['car_info_t.purchase_price', '>=', $data['price1'] * 10000]; + } + if (isset($data['price2']) && $data['price2'] != '') { + $where[] = ['car_info_t.purchase_price', '<=', $data['price2'] * 10000]; + } + if (isset($data['empty_phone_check']) && $data['empty_phone_check'] == 'yes') { + $where[] = ['car_phone', '<>', '']; + } + if (isset($data['export_field'])) { + foreach ($data['export_field'] as $item) { + $where[] = [$item, '<>', '']; + } + } + if (isset($data['export_type']) && $data['export_type'] != '' && $data['export_limit'] != 0) { + if($data['export_type'] == 'bhx'){ + $where[] = ['is_export_bhx', '=', 0]; + $where[] = ['is_update_bhx', '=', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + } + if($data['export_type'] == 'bmc'){ + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '>', 0]; + $where[] = ['is_export_bmc', '=', 0]; + } + if ($data['export_type'] == 'failed') { + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '=', -1]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + } + if ($data['export_type'] == 'failed_bmc') { + $where[] = ['is_export_bhx', '>', 0]; + $where[] = ['is_update_bhx', '=', -1]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + } + if ($data['export_type'] == 'none_bmc') { + $where[] = ['is_export_bhx', '=', 0]; + $where[] = ['is_update_bhx', '=', 0]; + $where[] = ['is_export_bmc', '=', 0]; + $where[] = ['is_export_failed', '=', 0]; + $where[] = ['is_export_failed_bmc', '=', 0]; + $where[] = ['is_export_none_bmc', '=', 0]; + } + } + $insurer_month1 = $data['insurer_month1']??''; + $insurer_day1 = $data['insurer_day1']??''; + $insurer_month2 = $data['insurer_month2']??''; + $insurer_day2 = $data['insurer_day2']??''; + if($insurer_month1 != '' && $insurer_day1 == '') { + $map_or1[] = [Db::raw('month(car_info_t.insurer1_date)'), '>=', $insurer_month1]; + $map_or2[] = [Db::raw('month(car_info_t.insurer2_date)'), '>=', $insurer_month1]; + } else if ($insurer_month1 == '' && $insurer_day1 != '') { + $map_or1[] = [Db::raw('day(car_info_t.insurer1_date)'), '>=', $insurer_day1]; + $map_or2[] = [Db::raw('day(car_info_t.insurer2_date)'), '>=', $insurer_day1]; + } else if ($insurer_month1 != '' && $insurer_day1 != '') { + $map_or1[] = [Db::raw('DATE_FORMAT(car_info_t.insurer1_date,"%m-%d")'), '>=', substr('0' . $insurer_month1, -2) . '-' . substr('0' . $insurer_day1, -2)]; + $map_or2[] = [Db::raw('DATE_FORMAT(car_info_t.insurer2_date,"%m-%d")'), '>=', substr('0' . $insurer_month1, -2) . '-' . substr('0' . $insurer_day1, -2)]; + } + if($insurer_month2 != '' && $insurer_day2 == '') { + $map_or1[] = [Db::raw('month(car_info_t.insurer1_date)'), '<=', $insurer_month2]; + $map_or2[] = [Db::raw('month(car_info_t.insurer2_date)'), '<=', $insurer_month2]; + } else if ($insurer_month2 == '' && $insurer_day2 != '') { + $map_or1[] = [Db::raw('day(car_info_t.insurer1_date)'), '<=', $insurer_day2]; + $map_or2[] = [Db::raw('day(car_info_t.insurer2_date)'), '<=', $insurer_day2]; + } else if ($insurer_month2 != '' && $insurer_day2 != '') { + $map_or1[] = [Db::raw('DATE_FORMAT(car_info_t.insurer1_date,"%m-%d")'), '<=', substr('0' . $insurer_month2, -2) . '-' . substr('0' . $insurer_day2, -2)]; + $map_or2[] = [Db::raw('DATE_FORMAT(car_info_t.insurer2_date,"%m-%d")'), '<=', substr('0' . $insurer_month2, -2) . '-' . substr('0' . $insurer_day2, -2)]; + } + if (count($map_or1) > 0) { + $map_or1 = array_merge([['car_info_t.insurer1_date', '<>', '']], $map_or1); + } + if (count($map_or2) > 0) { + $map_or2 = array_merge([['car_info_t.insurer1_date', '=', ''], ['car_info_t.insurer2_date', '<>', '']], $map_or2); + } + $query = CarInfoT::where($where)->where(function ($query) use ($map_or1, $map_or2) { + if (count($map_or1) > 0 && count($map_or2) > 0) { + $query->whereOr([$map_or1, $map_or2]); + } + }); + if ($data['export_type'] == 'repeat') { + if ($data['export_table'] == 'repeat_frame_t') { + $query = RepeatFrameT::leftjoin('car_info_t', 'repeat_frame_t.car_frame_no = car_info_t.car_frame_no') + ->field('car_info_t.*')->order('car_info_t.register_date asc') + ->where('repeat_frame_t.source', $data['source_id']); + } else if ($data['export_table'] == 'peer_phone_t') { + $query = $query->rightJoin('peer_phone_t', 'peer_phone_t.phone = car_info_t.car_phone') + ->field('car_info_t.*')->order('car_info_t.register_date asc') + ->where([['peer_phone_t.source', '=', $data['source_id']],['car_info_t.car_number', 'REGEXP', '^[1-9][[:digit:]]{7}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}$|^[1-9][[:digit:]]{5}[1-9][[:digit:]]{3}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}([0-9]|X)$']]); + } + }else { + $query = $query->order('register_date asc'); + } + $count = $query->count(); + $count = $count <= $data['export_limit'] || $data['export_limit'] == 0 ? $count : $data['export_limit']; + echo '总计:' . $count . PHP_EOL; + cache('shell_process_' . $id, 0, 300); + $data['export_field'] = $data['export_field'] ?? []; + list($titles, $fields) = $this->getTitleAndField($data['export_type'], $data['export_field']); + if (isset($data['is_excel']) && $data['is_excel'] == 'yes') { + $basename = '/export/' . date('YmdHis') . '.xlsx'; + $this->exportExcel($data['export_type'], $data['export_limit'], $titles, $fields, root_path() . 'public' . $basename, $query, $count, $id); + } else { + $basename = '/export/' . date('YmdHis') . '.csv'; + $this->exportCsv($data['export_type'], $data['export_limit'], $titles, $fields, root_path() . 'public' . $basename, $query, $count, $id); + } + $this->setProcess($count, $count, $id); + $this->addExportLog($count, $data['export_type'],$id); + return $basename; + } + + public function peerPhones($data, $id) + { + $where = [ + ['car_phone', '<>', ''], + ['car_number', 'REGEXP', '^[1-9][[:digit:]]{7}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}$|^[1-9][[:digit:]]{5}[1-9][[:digit:]]{3}((0[[:digit:]])|(1[0-2]))(([0|1|2][[:digit:]])|3[0-1])[[:digit:]]{3}([0-9]|X)$'] + ]; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + $query = CarInfoT::field('car_phone,count(*) as count') + ->where($where) + ->where($map) + ->group('car_phone'); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $peer_phone_number = $data['peer_phone_number']; + $peer_phone_count = $repeat_count = 0; + cache('shell_process_' . $id, 0, 300); + $query->chunk(3000, function ($infos) use (&$current, &$peer_phone_count, &$repeat_count, $count, $id, $peer_phone_number, $map) { + $insert_data = []; + foreach ($infos as $item) { + if ($item->count >= $peer_phone_number) { + $card_ids = CarInfoT::where('car_phone', $item->car_phone)->where($map)->column('car_number'); + if (count(array_flip(array_flip($card_ids))) <= 1) { + continue; + } + $insert_data[] = [ + 'phone' => $item->car_phone, + 'source' => $id, + ]; + $peer_phone_count++; + $repeat_count += $item->count; + } + $current++; + } + PeerPhoneT::duplicate(Db::raw('phone = values(phone), source = values(source)'))->insertAll($insert_data); + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + }, 'car_phone'); + return '重复总数:' . $repeat_count . ', 重复电话数:' . $peer_phone_count; + } + + public function carFrameNo($data, $id) + { + $where = [ + ['car_frame_no', '<>', ''] + ]; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $where[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $where[] = ['register_date', '<=', $data['export_date2']]; + } + $query = CarInfoT::field('car_frame_no,count(*) as count') + ->where($where) + ->group('car_frame_no') + ->having('count>=2'); + $current = $repeat_frame_count = 0; + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + cache('shell_process_' . $id, 0, 300); + $query->chunk(3000, function ($infos) use (&$current, &$repeat_frame_count, $count, $id) { + $insert_data = []; + foreach ($infos as $item) { + $insert_data[] = [ + 'car_frame_no' => $item->car_frame_no, + 'source' => $id, + ]; + $current++; + $repeat_frame_count += $item->count; + } + RepeatFrameT::duplicate(Db::raw('source = values(source)'))->insertAll($insert_data); + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + }, 'car_frame_no'); + return '重复总数:' . $repeat_frame_count . ', 重复车架数:' . $count; + } + + public function deletePeerPhones($data, $id) + { + $query = PeerPhoneT::where(['source' => $data['source_id']]); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $faild_num = 0; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + cache('shell_process_' . $id, 0, 300); + $query->chunk(1000, function ($infos) use (&$current, &$faild_num, $count, $id, $map) { + foreach ($infos as $item) { + if ($current % 10 == 0) { + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + } + $ids = CarInfoT::where('car_phone', $item->phone)->where($map)->column('id'); + Db::startTrans(); + try { + CarInfoT::where('id', 'in', $ids) + ->update(['car_phone' => '']);; + PeerPhoneT::where('phone', $item->phone)->delete(); + Db::commit(); + } catch (\Exception $e) { + $faild_num++; + Db::rollback(); + } + $current++; + } + }, 'phone'); + return '处理总数:' . $count . ', 失败总数:' . $faild_num; + } + + public function deleteCarFrameNo($data, $id) + { + $query = RepeatFrameT::where(['source' => $data['source_id']]); + $count = $query->count(); + echo '总计:' . $count . PHP_EOL; + $current = 0; + $faild_num = 0; + $map = []; + if (isset($data['export_date1']) && $data['export_date1'] != '') { + $map[] = ['register_date', '>=', $data['export_date1']]; + } + if (isset($data['export_date2']) && $data['export_date2'] != '') { + $map[] = ['register_date', '<=', $data['export_date2']]; + } + cache('shell_process_' . $id, 0, 300); + $query->chunk(1000, function ($infos) use (&$current, &$faild_num, $count, $id, $map) { + foreach ($infos as $item) { + if ($current % 10 == 0) { + cache('shell_process_' . $id, round($current / $count * 100, 3), 300); + echo '当前进度:' . round($current / $count * 100, 3) . PHP_EOL; + } + $ids = CarInfoT::where(['car_frame_no' => $item->car_frame_no])->where($map)->order('car_phone desc, insurer1_date desc, car_no desc, id desc')->column('id'); + array_shift($ids); + Db::startTrans(); + try { + CarInfoT::destroy($ids); + RepeatFrameT::where('car_frame_no', $item->car_frame_no)->delete(); + Db::commit(); + } catch (\Exception $e) { + $faild_num++; + Db::rollback(); + } + $current++; + } + }, 'car_frame_no'); + return '处理总数:' . $count . ', 失败总数:' . $faild_num; + } + + public function carInfoUpdate($data, $id) + { + $filename = public_path('public/storage') . $data['filename']; + if (empty($filename) OR !file_exists($filename)) { + return '文件不存在!'; + } + $spreadRead = Excel::loadFile($filename); + $worksheet = $spreadRead->getSheet(0); + $highestRow = $worksheet->getHighestRow(); // e.g. 10 + $total = $highestRow - 1; + echo '总计:' . $total . PHP_EOL; + $statistical_information = [ + 'total_all' => $total, + 'total_skip' => 0, + 'total_insert' => 0, + 'total_update' => 0, + 'total_error' => 0, + 'total_error_arr' => [], + 'total_skip_arr' => [], + ]; + $is_update_failed = 0; + for ($row = 2; $row <= $highestRow; $row++) { + $car_no = trim($worksheet->getCellByColumnAndRow(1, $row)->getValue()); + $car_man = trim($worksheet->getCellByColumnAndRow(2, $row)->getValue()); + $factory_model = trim($worksheet->getCellByColumnAndRow(3, $row)->getValue()); + $engine_no = trim($worksheet->getCellByColumnAndRow(4, $row)->getValue()); + $car_frame_no = trim($worksheet->getCellByColumnAndRow(5, $row)->getValue()); + $register_date = trim($worksheet->getCellByColumnAndRow(6, $row)->getValue()); + $company = trim($worksheet->getCellByColumnAndRow(7, $row)->getValue()); + $insurer1_date = trim($worksheet->getCellByColumnAndRow(8, $row)->getValue()); + $insurer2_date = trim($worksheet->getCellByColumnAndRow(9, $row)->getValue()); + $id_man = trim($worksheet->getCellByColumnAndRow(10, $row)->getValue()); + $id_number = trim($worksheet->getCellByColumnAndRow(11, $row)->getValue()); + if($car_frame_no == ''){ + continue; + } + $car_info = CarInfoT::where('car_frame_no', $car_frame_no)->find(); + if (isset($car_info)) { + if ($is_update_failed == 0 && $car_info->is_export_failed > 0) { + $is_update_failed = $car_info->is_export_failed; + } + $car_info->car_no = $car_no != '' ? $car_no : $car_info->car_no; + $car_info->car_man = $car_info->car_man != '' ? $car_info->car_man : $car_man; + $car_info->register_date = $register_date; + $car_info->factory_model = $factory_model; + //对比原信息是否包含待更新信息(删除星号) + $car_info->engine_no = $car_info->engine_no != '' && startsWith($car_info->engine_no, rtrim($engine_no, '*')) ? $car_info->engine_no : $engine_no; + $insurer1_flag = strtotime(date('Y', strtotime($insurer1_date))) > strtotime(date('Y', strtotime($car_info->insurer1_date))); + if ($insurer1_flag) { + $car_info->insurer1_date = $insurer1_date; + } + $insurer2_flag = strtotime(date('Y', strtotime($insurer2_date))) > strtotime(date('Y', strtotime($car_info->insurer2_date))); + if ($insurer2_flag) { + $car_info->insurer2_date = $insurer2_date; + } + if (($car_info->insurer1_date != '' && $insurer1_flag) || ($car_info->insurer2_date != '' && $insurer2_flag) || $car_info->insurer1_date == '' || $car_info->insurer2_date == '') { + $car_info->company = $company != '' ? $company : $car_info->company; + $car_info->id_man = $car_info->id_man != '' && startsWith($car_info->id_man, rtrim($id_man, '*')) ? $car_info->id_man : $id_man; + $car_info->id_number = $car_info->id_number != '' && startsWith($car_info->id_number, rtrim($id_number, '*')) ? $car_info->id_number : $id_number; + } + $car_info->is_update_bhx = $id; + $car_info->is_export_failed = 0; + if (!$car_info->save()) { + $statistical_information['total_error']++; + $statistical_information['total_error_arr'][] = $row; + } else { + $statistical_information['total_update']++; + } + } else { + $statistical_information['total_skip_arr'][] = $row; + $statistical_information['total_skip']++; + } + cache('shell_process_' . $id, round($row / $total * 100, 3), 300); + echo '当前进度:' . round($row / $total * 100, 3) . PHP_EOL; + } + if($is_update_failed > 0){ + CarInfoT::where('is_update_bhx', '<', 0) + ->where('is_export_failed', $is_update_failed) + ->update(['is_export_failed' => 0, 'is_update_bhx' => Db::raw('is_update_bhx - 1')]); + }else if($car_info) { + CarInfoT::where('is_update_bhx', 0) + ->where('is_export_bhx', $car_info->is_export_bhx) + ->update(['is_update_bhx' => -1]); + } + return '操作成功' . "数据总计{$statistical_information['total_all']}条, + 更新{$statistical_information['total_update']}, + 失败{$statistical_information['total_error']}, + 失败数据列:" . implode(',', $statistical_information['total_error_arr']) . ", + 跳过{$statistical_information['total_skip']}, + 跳过数据列:" . implode(',', $statistical_information['total_skip_arr']); + } + + private function importExcel($data, $id) + { + $filename = public_path('public/storage') . $data['filename']; + $t1 = microtime(true); + $spreadRead = Excel::loadFile($filename); + $worksheet = $spreadRead->getSheet(0); + $highestRow = $worksheet->getHighestRow(); // e.g. 10 + echo '总计:' . $highestRow . PHP_EOL; + $now = date('Y-m-d H:i:s'); + Db::execute('ALTER TABLE car_info_t DISABLE KEYS;'); + for ($row = 2; $row <= $highestRow; $row++) { + $row_array[] = [ + 'duty_no' => $worksheet->getCellByColumnAndRow(1, $row)->getValue(), + 'register_date' => $worksheet->getCellByColumnAndRow(2, $row)->getValue(), + 'car_man' => $worksheet->getCellByColumnAndRow(3, $row)->getValue(), + 'car_number' => $worksheet->getCellByColumnAndRow(4, $row)->getValue(), + 'car_phone' => $worksheet->getCellByColumnAndRow(5, $row)->getValue(), + 'car_frame_no' => $worksheet->getCellByColumnAndRow(6, $row)->getValue(), + 'car_no' => $worksheet->getCellByColumnAndRow(7, $row)->getValue(), + 'engine_no' => $worksheet->getCellByColumnAndRow(8, $row)->getValue(), + 'factory_model' => $worksheet->getCellByColumnAndRow(9, $row)->getValue(), + 'purchase_price' => $worksheet->getCellByColumnAndRow(10, $row)->getValue(), + 'create_timestamp' => $now, + 'update_timestamp' => $now + ]; + if ($row >= 1000) { + Db::name('car_info_t')->insertAll($row_array); + cache('shell_process_' . $id, round(($i + 2000) / $lines * 100, 3), 300); + echo '当前进度:' . round(round(($i + 2000) / $lines * 100, 3)) . PHP_EOL; + $row_array = []; + } + } + Db::execute('ALTER TABLE car_info_t ENABLE KEYS;'); + $t2 = microtime(true); + echo '耗时' . round($t2 - $t1, 3) . '秒' . PHP_EOL; + echo 'Now memory_get_usage: ' . memory_get_usage() . PHP_EOL; + return '导入成功:' . ($highestRow - 1); + } + + private function exportCsv($export_type, $export_limit, $titles, $fields, $filename, $query, $count, $id) + { + $head = ''; + foreach ($titles as $val) { + if ($val == 'line') { + $head .= "\r\n"; + continue; + } + $head .= "\"{$val}\t\","; + } + $head = substr($head, 0, -1) . "\r\n"; + if (file_exists($filename)) { + unlink($filename); + } + if (is_dir(pathinfo($filename, PATHINFO_DIRNAME))) { + file_put_contents($filename, $head); + } else { + mkdir(pathinfo($filename, PATHINFO_DIRNAME), 0777); + file_put_contents($filename, $head); + } + $current = 0; + if ($count <= 3000) { + $ids = []; + $content = ''; + foreach ($query->limit($count)->select() as $item) { + $ids[] = $item->id; + foreach ($fields as $field) { + $content .= "\"" . ($item->$field ?: '') . "\"\t,"; + } + $content = substr($content, 0, -1) . "\r\n"; + $this->setProcess(++$current, $count, $id); + } + FileSystem::appendWriteFile($filename, $content, false); + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + } else { + $info = $query->limit(3000)->select(); + $limit = $count; + while ($limit > 0) { + $ids = []; + $content = ''; + foreach ($info as $item) { + $ids[] = $item->id; + foreach ($fields as $field) { + $content .= "\"" . ($item->$field ?: '') . "\"\t,"; + } + $content = substr($content, 0, -1) . "\r\n"; + $this->setProcess(++$current, $count, $id); + } + FileSystem::appendWriteFile($filename, $content, false); + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + $limit -= 3000; + $end = $info->pop(); + $lastRegisterDate = is_array($end) ? $end['register_date'] : $end->getData('register_date'); + $limit > 0 && ($info = $query->where('register_date', '>=', $lastRegisterDate)->limit($limit >= 3000 ? 3000 : $limit)->select()); + } + } + } + + private function exportExcel($export_type, $export_limit, $titles, $fields, $filename, $query, $count, $id) + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet()->setTitle('sheet1'); + $row = 0; + $i = 0; + foreach ($titles as $col => $val) { + if ($val == 'line') { + $row += 1; + $i += 1; + continue; + } + $sheet->setCellValueByColumnAndRow($col + 1 - $i, $row + 1, $val); + } + if ($count <= 3000) { + $ids = []; + foreach ($query->limit($count)->select() as $item) { + $ids[] = $item->id; + $row += 1; + foreach ($fields as $index => $field) { + $sheet->setCellValueExplicitByColumnAndRow($index + 1, $row + 1, ($item->$field ?: ''), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); + } + $this->setProcess($row, $count * 1.2, $id); + } + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + } else { + $info = $query->limit(3000)->select(); + $limit = $count; + while ($limit > 0) { + $ids = []; + foreach ($info as $item) { + $ids[] = $item->id; + $row += 1; + foreach ($fields as $index => $field) { + $sheet->setCellValueExplicitByColumnAndRow($index + 1, $row + 1, ($item->$field ?: ''), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); + } + $this->setProcess($row, $count * 1.2, $id); + } + $export_limit != 0 && CarInfoT::where('id', 'in', $ids)->update(['is_export_' . $export_type => $id]); + $limit -= 3000; + $end = $info->pop(); + $lastRegisterDate = is_array($end) ? $end['register_date'] : $end->getData('register_date'); + $limit > 0 && ($info = $query->where('register_date', '>=', $lastRegisterDate)->limit($limit >= 3000 ? 3000 : $limit)->select()); + } + } + $writer = new Xlsx($spreadsheet); + $writer->save($filename); + } + + private function setProcess($cur, $count, $id) + { + $process = round($cur / $count * 100, 3); + cache('shell_process_' . $id, $process, 300); + echo '当前进度:' . $process . PHP_EOL; + } + + /** + * @param $export_type + * @param $export_field + * @return array + */ + private function getTitleAndField($export_type, $export_field) + { + $orgTitles = ['区域', '购车日期', '客户姓名', '证件号码', '联系方式', '车架号', '车牌号', '发动机号', '品牌型号', '新车购置价', '保险公司', '商业止保日期', '交强止保日期', '被保险人', '被保险人证件号']; + $bhxTitles = ['line', 'line', '车牌号', '车架号', '发动机号', '车主证件号码', '品牌型号', '注册日期', '去年投保公司', '交强险到期时间', '商业险到期时间', '客户姓名', '客户电话1', '客户电话2', '客户备注', '客户备注2', '客户类别', '业务员姓名', '业务员账号']; + $bmcTitles = ['注册日期', '车牌号', '车架号', '发动机号', '品牌型号', '年款', '排量', '车主', '车主证件号', '联系电话', '新车购置价', '被保险人', '被保险人证件号', '联系电话', '上年承保公司', '商业止保日期', '交强止保日期', 'insurer_type', '联系人', '联系电话', '联系人', '联系电话', '联系人', '联系电话']; + $orgFields = ['duty_no', 'register_date', 'car_man', 'car_number', 'car_phone', 'car_frame_no', 'car_no', 'engine_no', 'factory_model', 'purchase_price', 'compay', 'insurer1_date', 'insurer2_date', 'id_man', 'id_number']; + if (in_array($export_type, ['bhx', 'failed']) && count($export_field) == 1) { + $bhxFields = $export_field[0] == 'car_no' ? ['car_no'] : ['car_empty_item', 'car_frame_no']; + } else { + $bhxFields = ['car_no', 'car_frame_no']; + } + $bmcFields = ['register_date', 'car_no', 'car_frame_no', 'engine_no', 'factory_model', 'car_year', 'displacement', 'car_man', 'car_number', 'car_phone', 'purchase_price', 'id_man', 'id_number', 'id_phone', 'company', 'insurer1_date', 'insurer2_date', 'insurer_type', 'linkman', 'linkphone', 'linkman', 'linkphone', 'linkman', 'linkphone']; + $titles = in_array($export_type, ['bmc','failed_bmc','none_bmc']) ? $bmcTitles : ($export_type == 'repeat' ? $orgTitles : $bhxTitles); + $fields = in_array($export_type, ['bmc','failed_bmc','none_bmc']) ? $bmcFields : ($export_type == 'repeat' ? $orgFields : $bhxFields); + return [$titles, $fields]; + } + + private function addExportLog($total, $export_type, $id) + { + $queue_name = JobsT::where('id',$id)->value('queue'); + $export_log = new ExportLogT; + $export_log->type = $export_type; + $export_log->name = $queue_name; + $export_log->total = $total; + $export_log->create_timestamp = date('Y-m-d H:i:s'); + $export_log->save(); + } +} \ No newline at end of file