parent
dd98a98b57
commit
e8b3aa4c33
@ -0,0 +1,224 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace crontab; |
||||||
|
|
||||||
|
|
||||||
|
class CronParser |
||||||
|
{ |
||||||
|
|
||||||
|
protected static $tags = []; |
||||||
|
|
||||||
|
protected static $weekMap = [ |
||||||
|
0 => '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, '/')); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace excel; |
||||||
|
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter; |
||||||
|
|
||||||
|
class Analysis implements IReadFilter |
||||||
|
{ |
||||||
|
public $startRow; |
||||||
|
public $endRow; |
||||||
|
public $worksheetName; |
||||||
|
public function readCell($column, $row, $worksheetName = '') |
||||||
|
{ |
||||||
|
if ($worksheetName == $this->worksheetName && $row >= ($this->startRow + 1) && $row <= ($this->endRow + 1)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,186 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace excel; |
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; |
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory; |
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Exception; |
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx; |
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
||||||
|
use file\FileSystem; |
||||||
|
|
||||||
|
class Excel |
||||||
|
{ |
||||||
|
|
||||||
|
private static $ret = array('code' => 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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace excel; |
||||||
|
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter; |
||||||
|
|
||||||
|
class ReadAheadFilter implements IReadFilter |
||||||
|
{ |
||||||
|
public $record = array(); |
||||||
|
private $lastRow = ''; |
||||||
|
public function readCell($column, $row, $worksheetName = '') |
||||||
|
{ |
||||||
|
if (isset($this->record[$worksheetName])) { |
||||||
|
if ($this->lastRow != $row) { |
||||||
|
$this->record[$worksheetName]++; |
||||||
|
$this->lastRow = $row; |
||||||
|
} |
||||||
|
} else { |
||||||
|
$this->record[$worksheetName] = 1; |
||||||
|
$this->lastRow = $row; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,250 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace file; |
||||||
|
|
||||||
|
|
||||||
|
class FileSystem |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $rootPath; |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $appPath; |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $runtimePath; |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文件名 |
||||||
|
* @param $file |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function getFileName($file) |
||||||
|
{ |
||||||
|
return explode('.', basename($file))[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文件扩展名 |
||||||
|
* @param $file |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function getFileExt($file) |
||||||
|
{ |
||||||
|
return explode('.', basename($file))[1]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取应用根目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getRootPath() |
||||||
|
{ |
||||||
|
if(!self::$rootPath) { |
||||||
|
if ('cli' == PHP_SAPI) { |
||||||
|
$scriptName = realpath($_SERVER['argv'][0]); |
||||||
|
} else { |
||||||
|
$scriptName = $_SERVER['SCRIPT_FILENAME']; |
||||||
|
} |
||||||
|
|
||||||
|
$path = realpath(dirname($scriptName)); |
||||||
|
if (!is_file($path . DIRECTORY_SEPARATOR . 'command')) { |
||||||
|
$path = dirname($path); |
||||||
|
} |
||||||
|
self::$rootPath = $path . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$rootPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取应用目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getAppPath() |
||||||
|
{ |
||||||
|
if(!self::$appPath){ |
||||||
|
self::$appPath = self::getRootPath() . 'app' . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$appPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取运行时目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getRuntimePath() |
||||||
|
{ |
||||||
|
if(!self::$runtimePath){ |
||||||
|
self::$runtimePath = self::getRootPath() . 'runtime' . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$runtimePath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 搜索文件 |
||||||
|
* @param $path |
||||||
|
* @param string $type |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function scanFile($path, $type = null) |
||||||
|
{ |
||||||
|
$result = array(); |
||||||
|
$files = scandir($path); |
||||||
|
foreach ($files as $file) { |
||||||
|
if ($file != '.' && $file != '..') { |
||||||
|
if (is_dir($path . '/' . $file)) { |
||||||
|
$result[$file] = self::scanFile($path . '/' . $file); |
||||||
|
} elseif ($type && explode('.', $file)[1] == $type) { |
||||||
|
$result[] = $path . '/' . $file; |
||||||
|
} elseif (!$type){ |
||||||
|
$result[] = $path . '/' . $file; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存文件 |
||||||
|
* @param $filename |
||||||
|
* @param $data |
||||||
|
* @return false|int |
||||||
|
*/ |
||||||
|
public static function saveFile($filename, $data = '') |
||||||
|
{ |
||||||
|
$dir = substr($filename,'0',strrpos($filename,'/')); |
||||||
|
if (!file_exists($dir)) { |
||||||
|
mkdir($dir, 777, true); |
||||||
|
} |
||||||
|
return file_put_contents($filename, json_encode($data)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清空目录文件 |
||||||
|
* @param $dir |
||||||
|
* @param null $type |
||||||
|
*/ |
||||||
|
public static function clearDir($dir,$type = null){ |
||||||
|
$files = scandir($dir); |
||||||
|
foreach ($files as $file) { |
||||||
|
if ($file != '.' && $file != '..') { |
||||||
|
if (is_dir($dir . '/' . $file)) { |
||||||
|
self::clearDir($dir . '/' . $file); |
||||||
|
@rmdir($dir . '/' . $file); |
||||||
|
} else { |
||||||
|
@unlink($dir . '/' . $file); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取文件某一行记录 |
||||||
|
* @param $file |
||||||
|
* @param $line |
||||||
|
* @return bool|false|string |
||||||
|
*/ |
||||||
|
public static function getFileLine($file, $line) |
||||||
|
{ |
||||||
|
$n = 0; |
||||||
|
$handle = fopen($file, 'r'); |
||||||
|
if ($handle) { |
||||||
|
while (!feof($handle)) { |
||||||
|
++$n; |
||||||
|
$out = fgets($handle, 4096); |
||||||
|
if ($line == $n) break; |
||||||
|
} |
||||||
|
fclose($handle); |
||||||
|
} |
||||||
|
if ($line == $n) { |
||||||
|
$encode = mb_detect_encoding($out, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5')); |
||||||
|
$str = mb_convert_encoding($out, 'UTF-8', $encode); |
||||||
|
return $str; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 文件追加写入 |
||||||
|
* @param $file |
||||||
|
* @param $content |
||||||
|
* @param bool $is_new_line |
||||||
|
* @return false|int |
||||||
|
*/ |
||||||
|
public static function appendWriteFile($file,$content,$is_new_line = true){ |
||||||
|
if($is_new_line){ |
||||||
|
$content .= PHP_EOL; |
||||||
|
} |
||||||
|
$handle = fopen($file, "a"); |
||||||
|
$ret = fwrite($handle, $content); |
||||||
|
fclose($handle); |
||||||
|
return $ret; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文本文件行数 |
||||||
|
* @param $filename |
||||||
|
* @param string $ending |
||||||
|
* @return int |
||||||
|
*/ |
||||||
|
public static function getTxtFileLines($filename, $ending = PHP_EOL) |
||||||
|
{ |
||||||
|
$fp = fopen($filename, 'r'); |
||||||
|
$lines = 0; |
||||||
|
while (stream_get_line($fp, filesize($filename),$ending)) { |
||||||
|
$lines++; |
||||||
|
} |
||||||
|
fclose($fp); |
||||||
|
return $lines; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 块级读取文件记录 |
||||||
|
* @param $file |
||||||
|
* @param int $start |
||||||
|
* @param int $end |
||||||
|
* @param string $callback |
||||||
|
* @return array |
||||||
|
* @throws \Exception |
||||||
|
*/ |
||||||
|
public static function getFileBlockData($file, $start = 0, $end = 0, $callback = '') |
||||||
|
{ |
||||||
|
$n = 0; |
||||||
|
$data = []; |
||||||
|
$handle = fopen($file, 'r'); |
||||||
|
if (!$handle) { |
||||||
|
throw new \Exception('文件'.$file.'不存在'); |
||||||
|
} |
||||||
|
$start = $start >=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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,250 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace file; |
||||||
|
|
||||||
|
|
||||||
|
class FileSystem |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $rootPath; |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $appPath; |
||||||
|
/** |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
private static $runtimePath; |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文件名 |
||||||
|
* @param $file |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function getFileName($file) |
||||||
|
{ |
||||||
|
return explode('.', basename($file))[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文件扩展名 |
||||||
|
* @param $file |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function getFileExt($file) |
||||||
|
{ |
||||||
|
return explode('.', basename($file))[1]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取应用根目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getRootPath() |
||||||
|
{ |
||||||
|
if(!self::$rootPath) { |
||||||
|
if ('cli' == PHP_SAPI) { |
||||||
|
$scriptName = realpath($_SERVER['argv'][0]); |
||||||
|
} else { |
||||||
|
$scriptName = $_SERVER['SCRIPT_FILENAME']; |
||||||
|
} |
||||||
|
|
||||||
|
$path = realpath(dirname($scriptName)); |
||||||
|
if (!is_file($path . DIRECTORY_SEPARATOR . 'command')) { |
||||||
|
$path = dirname($path); |
||||||
|
} |
||||||
|
self::$rootPath = $path . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$rootPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取应用目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getAppPath() |
||||||
|
{ |
||||||
|
if(!self::$appPath){ |
||||||
|
self::$appPath = self::getRootPath() . 'app' . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$appPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取运行时目录 |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public static function getRuntimePath() |
||||||
|
{ |
||||||
|
if(!self::$runtimePath){ |
||||||
|
self::$runtimePath = self::getRootPath() . 'runtime' . DIRECTORY_SEPARATOR; |
||||||
|
} |
||||||
|
return self::$runtimePath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 搜索文件 |
||||||
|
* @param $path |
||||||
|
* @param string $type |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public static function scanFile($path, $type = null) |
||||||
|
{ |
||||||
|
$result = array(); |
||||||
|
$files = scandir($path); |
||||||
|
foreach ($files as $file) { |
||||||
|
if ($file != '.' && $file != '..') { |
||||||
|
if (is_dir($path . '/' . $file)) { |
||||||
|
$result[$file] = self::scanFile($path . '/' . $file); |
||||||
|
} elseif ($type && explode('.', $file)[1] == $type) { |
||||||
|
$result[] = $path . '/' . $file; |
||||||
|
} elseif (!$type){ |
||||||
|
$result[] = $path . '/' . $file; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存文件 |
||||||
|
* @param $filename |
||||||
|
* @param $data |
||||||
|
* @return false|int |
||||||
|
*/ |
||||||
|
public static function saveFile($filename, $data = '') |
||||||
|
{ |
||||||
|
$dir = substr($filename,'0',strrpos($filename,'/')); |
||||||
|
if (!file_exists($dir)) { |
||||||
|
mkdir($dir, 777, true); |
||||||
|
} |
||||||
|
return file_put_contents($filename, json_encode($data)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清空目录文件 |
||||||
|
* @param $dir |
||||||
|
* @param null $type |
||||||
|
*/ |
||||||
|
public static function clearDir($dir,$type = null){ |
||||||
|
$files = scandir($dir); |
||||||
|
foreach ($files as $file) { |
||||||
|
if ($file != '.' && $file != '..') { |
||||||
|
if (is_dir($dir . '/' . $file)) { |
||||||
|
self::clearDir($dir . '/' . $file); |
||||||
|
@rmdir($dir . '/' . $file); |
||||||
|
} else { |
||||||
|
@unlink($dir . '/' . $file); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取文件某一行记录 |
||||||
|
* @param $file |
||||||
|
* @param $line |
||||||
|
* @return bool|false|string |
||||||
|
*/ |
||||||
|
public static function getFileLine($file, $line) |
||||||
|
{ |
||||||
|
$n = 0; |
||||||
|
$handle = fopen($file, 'r'); |
||||||
|
if ($handle) { |
||||||
|
while (!feof($handle)) { |
||||||
|
++$n; |
||||||
|
$out = fgets($handle, 4096); |
||||||
|
if ($line == $n) break; |
||||||
|
} |
||||||
|
fclose($handle); |
||||||
|
} |
||||||
|
if ($line == $n) { |
||||||
|
$encode = mb_detect_encoding($out, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5')); |
||||||
|
$str = mb_convert_encoding($out, 'UTF-8', $encode); |
||||||
|
return $str; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 文件追加写入 |
||||||
|
* @param $file |
||||||
|
* @param $content |
||||||
|
* @param bool $is_new_line |
||||||
|
* @return false|int |
||||||
|
*/ |
||||||
|
public static function appendWriteFile($file,$content,$is_new_line = true){ |
||||||
|
if($is_new_line){ |
||||||
|
$content .= PHP_EOL; |
||||||
|
} |
||||||
|
$handle = fopen($file, "a"); |
||||||
|
$ret = fwrite($handle, $content); |
||||||
|
fclose($handle); |
||||||
|
return $ret; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文本文件行数 |
||||||
|
* @param $filename |
||||||
|
* @param string $ending |
||||||
|
* @return int |
||||||
|
*/ |
||||||
|
public static function getTxtFileLines($filename, $ending = PHP_EOL) |
||||||
|
{ |
||||||
|
$fp = fopen($filename, 'r'); |
||||||
|
$lines = 0; |
||||||
|
while (stream_get_line($fp, filesize($filename),$ending)) { |
||||||
|
$lines++; |
||||||
|
} |
||||||
|
fclose($fp); |
||||||
|
return $lines; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 块级读取文件记录 |
||||||
|
* @param $file |
||||||
|
* @param int $start |
||||||
|
* @param int $end |
||||||
|
* @param string $callback |
||||||
|
* @return array |
||||||
|
* @throws \Exception |
||||||
|
*/ |
||||||
|
public static function getFileBlockData($file, $start = 0, $end = 0, $callback = '') |
||||||
|
{ |
||||||
|
$n = 0; |
||||||
|
$data = []; |
||||||
|
$handle = fopen($file, 'r'); |
||||||
|
if (!$handle) { |
||||||
|
throw new \Exception('文件'.$file.'不存在'); |
||||||
|
} |
||||||
|
$start = $start >=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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,626 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace service; |
||||||
|
|
||||||
|
|
||||||
|
use app\model\CarInfoT; |
||||||
|
use app\model\ExportLogT; |
||||||
|
use app\model\JobsT; |
||||||
|
use app\model\PeerPhoneT; |
||||||
|
use app\model\RepeatFrameT; |
||||||
|
use excel\Excel; |
||||||
|
use file\FileSystem; |
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory; |
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; |
||||||
|
use SpreadsheetReader; |
||||||
|
use think\facade\Db; |
||||||
|
use think\facade\Env; |
||||||
|
|
||||||
|
class CarInfoHandle |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @param $data |
||||||
|
* @param $id |
||||||
|
* @return bool |
||||||
|
* @throws \Exception |
||||||
|
*/ |
||||||
|
public function import($data, $id) |
||||||
|
{ |
||||||
|
if(pathinfo($data['filename'])['extension'] != 'csv'){ |
||||||
|
return '操作失败:上传文件必须为csv文件'; |
||||||
|
} |
||||||
|
$filename = public_path('public/storage') . $data['filename']; |
||||||
|
$lines = FileSystem::getTxtFileLines($filename); |
||||||
|
echo '总计:' . $lines . PHP_EOL; |
||||||
|
cache('shell_process_' . $id, 0, 300); |
||||||
|
Db::execute('ALTER TABLE car_info_t DISABLE KEYS;'); |
||||||
|
for ($i = 2; $i < $lines; $i += 2000) { |
||||||
|
$insert_data = FileSystem::getFileBlockData($filename, $i, $i + 2000, function ($str) use ($id) { |
||||||
|
$keys = ['duty_no', 'register_date', 'car_man', 'car_number', 'car_phone', 'car_frame_no', 'car_no', 'engine_no', 'factory_model', 'purchase_price', 'source']; |
||||||
|
$keys_len = count($keys); |
||||||
|
$arr = explode(',', $str); |
||||||
|
array_walk($arr, function (&$value, $key) { |
||||||
|
$value = trim(trim($value, '"')); |
||||||
|
}); |
||||||
|
$values = array_slice($arr, 0, $keys_len); |
||||||
|
$values[$keys_len - 1] = $id; |
||||||
|
return array_combine($keys, $values); |
||||||
|
}); |
||||||
|
Db::name('car_info_t')->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(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,626 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace service; |
||||||
|
|
||||||
|
|
||||||
|
use app\model\CarInfoT; |
||||||
|
use app\model\ExportLogT; |
||||||
|
use app\model\JobsT; |
||||||
|
use app\model\PeerPhoneT; |
||||||
|
use app\model\RepeatFrameT; |
||||||
|
use excel\Excel; |
||||||
|
use file\FileSystem; |
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory; |
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; |
||||||
|
use SpreadsheetReader; |
||||||
|
use think\facade\Db; |
||||||
|
use think\facade\Env; |
||||||
|
|
||||||
|
class CarInfoHandle |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @param $data |
||||||
|
* @param $id |
||||||
|
* @return bool |
||||||
|
* @throws \Exception |
||||||
|
*/ |
||||||
|
public function import($data, $id) |
||||||
|
{ |
||||||
|
if(pathinfo($data['filename'])['extension'] != 'csv'){ |
||||||
|
return '操作失败:上传文件必须为csv文件'; |
||||||
|
} |
||||||
|
$filename = public_path('public/storage') . $data['filename']; |
||||||
|
$lines = FileSystem::getTxtFileLines($filename); |
||||||
|
echo '总计:' . $lines . PHP_EOL; |
||||||
|
cache('shell_process_' . $id, 0, 300); |
||||||
|
Db::execute('ALTER TABLE car_info_t DISABLE KEYS;'); |
||||||
|
for ($i = 2; $i < $lines; $i += 2000) { |
||||||
|
$insert_data = FileSystem::getFileBlockData($filename, $i, $i + 2000, function ($str) use ($id) { |
||||||
|
$keys = ['duty_no', 'register_date', 'car_man', 'car_number', 'car_phone', 'car_frame_no', 'car_no', 'engine_no', 'factory_model', 'purchase_price', 'source']; |
||||||
|
$keys_len = count($keys); |
||||||
|
$arr = explode(',', $str); |
||||||
|
array_walk($arr, function (&$value, $key) { |
||||||
|
$value = trim(trim($value, '"')); |
||||||
|
}); |
||||||
|
$values = array_slice($arr, 0, $keys_len); |
||||||
|
$values[$keys_len - 1] = $id; |
||||||
|
return array_combine($keys, $values); |
||||||
|
}); |
||||||
|
Db::name('car_info_t')->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(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue