添加entend目录

master
zhaocheng 4 years ago
parent dd98a98b57
commit e8b3aa4c33
  1. 224
      extend/crontab/CronParser.php
  2. 21
      extend/excel/Analysis.php
  3. 186
      extend/excel/Excel.php
  4. 26
      extend/excel/ReadAheadFilter.php
  5. 250
      extend/file/FileSystem.php
  6. 250
      extend/file/FileSystem.php.bak
  7. 443
      extend/library/Tree.php
  8. 626
      extend/service/CarInfoHandle.php
  9. 626
      extend/service/CarInfoHandle.php.bak

@ -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,443 @@
<?php
namespace library;
class Tree
{
/**
* 内容数组
* @var array
*/
public $data = array();
/**
* 节点数组
* @var array
*/
public $cateArray = array();
public $res = array();
public function __construct($arr = array())
{
$this->data = $arr;
$this->res = '';
return is_array($arr);
}
public function setNode($id, $value, $parent = 0)
{
$this->data[$id] = $value;
$this->cateArray[$id] = $parent;
}
public function getAllChildrenNodes($id = 0,\Closure $compFunc = null,\Closure $retFunc = null)
{
$result = [];
$children = array_keys($this->cateArray, $id);
if ($id > 0 && $compFunc && $compFunc($this->data[$id])) {
$result = $retFunc === null ? $id : $retFunc($this->data[$id]);
} else if (count($children) > 0) {
foreach ($children as $child) {
$result = array_merge($result, $this->getAllChildrenNodes($child, $compFunc, $retFunc));
}
} else {
$result = $retFunc === null ? $id: $retFunc($this->data[$id]);
}
return $result;
}
public function getChildsTree($id = 0)
{
$childs = array();
foreach ($this->cateArray as $child => $parent) {
if ($parent == $id) {
$childs[$child] = $this->getChildsTree($child);
}
}
return $childs;
}
public function getParentsTree($id = 0)
{
$parents = array();
foreach ($this->cateArray as $child => $parent) {
if ($child == $id) {
$parents[$parent] = $this->getParentsTree($parent);
}
}
return $parents;
}
public function getChilds($id = 0)
{
$childArray = array();
$childs = $this->getChild($id);
foreach ($childs as $child) {
$childArray[] = $child;
$childArray = array_merge($childArray, $this->getChilds($child));
}
return $childArray;
}
public function getChild($id)
{
$childs = array();
foreach ($this->cateArray as $child => $parent) {
if ($parent == $id) {
$childs[$child] = $child;
}
}
return $childs;
}
public function getParents($id)
{
$parentArray = array();
$parents = $this->getParent($id);
foreach ($parents as $parent) {
$parentArray[] = $parent;
$parentArray = array_merge($parentArray, $this->getParents($parent));
}
return $parentArray;
}
public function getParent($id)
{
$parents = array();
foreach ($this->cateArray as $child => $parent) {
if ($child == $id) {
$parents[$parent] = $parent;
}
}
return $parents;
}
//单线获取父节点
public function getNodeLever($id)
{
$parents = array();
if (key_exists($this->cateArray[$id], $this->cateArray)) {
$parents[] = $this->cateArray[$id];
$parents = array_merge($parents, $this->getNodeLever($this->cateArray[$id]));
}
return $parents;
}
public function getLayer($id, $preStr = '|-')
{
return str_repeat($preStr, count($this->getNodeLever($id)));
}
public function getValue($id)
{
return $this->data[$id];
}
//获取所有节点数据生成树
public function getTreeShow($id = 0, $str = "|-")
{
if ($id != 0) {
$str = $str . "|-";
}
//遍历所有数组检查parent是否有id
foreach ($this->cateArray as $child => $parent) {
//检查是否有相等的ID
if ($parent == $id) {
$showname = $this->getValue($child);
if(is_string($showname)){
$this->res[$child] = $str . $showname;
}else if(is_array($showname) && isset($showname['name'])){
$this->res[$child] = $str . $showname['name'];
}else {
$this->res[$child] = $str . $child;
}
$this->getTreeShow($child, $str);
}
}
}
}
//class Tree
//{
// /**
// * 生成树型结构所需要的2维数组
// * @var array
// */
// public $arr = array();
//
// /**
// * 生成树型结构所需修饰符号,可以换成图片
// * @var array
// */
// public $icon = array('│', '├', '└');
// public $nbsp = " ";
//
// /**
// * @access private
// */
// public $ret = '';
//
// /**
// * 构造函数,初始化类
// * @param array 2维数组,例如:
// * array(
// * 1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'),
// * 2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'),
// * 3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'),
// * 4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'),
// * 5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'),
// * 6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'),
// * 7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二')
// * )
// */
// public function init($arr = array())
// {
// $this->arr = $arr;
// $this->ret = '';
// return is_array($arr);
// }
//
// /**
// * 得到父级数组
// * @param int
// * @return array
// */
// public function get_parent($myid)
// {
// $newarr = array();
// if (!isset($this->arr[$myid])) return false;
// $pid = $this->arr[$myid]['parentid'];
// $pid = $this->arr[$pid]['parentid'];
// if (is_array($this->arr)) {
// foreach ($this->arr as $id => $a) {
// if ($a['parentid'] == $pid) $newarr[$id] = $a;
// }
// }
// return $newarr;
// }
//
// /**
// * 得到子级数组
// * @param int
// * @return array
// */
// public function get_child($myid)
// {
// $a = $newarr = array();
// if (is_array($this->arr)) {
// foreach ($this->arr as $id => $a) {
// if ($a['parentid'] == $myid) $newarr[$id] = $a;
// }
// }
// return $newarr ? $newarr : false;
// }
//
// /**
// * 得到当前位置数组
// * @param int
// * @return array
// */
// public function get_pos($myid, &$newarr)
// {
// $a = array();
// if (!isset($this->arr[$myid])) return false;
// $newarr[] = $this->arr[$myid];
// $pid = $this->arr[$myid]['parentid'];
// if (isset($this->arr[$pid])) {
// $this->get_pos($pid, $newarr);
// }
// if (is_array($newarr)) {
// krsort($newarr);
// foreach ($newarr as $v) {
// $a[$v['id']] = $v;
// }
// }
// return $a;
// }
//
// /**
// * 得到树型结构
// * @param int ID,表示获得这个ID下的所有子级
// * @param string 生成树型结构的基本代码,例如:"<option value=\$id \$selected>\$spacer\$name</option>"
// * @param int 被选中的ID,比如在做树型下拉框的时候需要用到
// * @return string
// */
// public function get_tree($myid, $str, $sid = 0, $adds = '', $str_group = '')
// {
// $number = 1;
// $child = $this->get_child($myid);
// if (is_array($child)) {
// $total = count($child);
// foreach ($child as $id => $value) {
// $j = $k = '';
// if ($number == $total) {
// $j .= $this->icon[2];
// } else {
// $j .= $this->icon[1];
// $k = $adds ? $this->icon[0] : '';
// }
// $spacer = $adds ? $adds . $j : '';
// $selected = $id == $sid ? 'selected' : '';
// @extract($value);
// $parentid == 0 && $str_group ? eval("\$nstr = \"$str_group\";") : eval("\$nstr = \"$str\";");
// $this->ret .= $nstr;
// $nbsp = $this->nbsp;
// $this->get_tree($id, $str, $sid, $adds . $k . $nbsp, $str_group);
// $number++;
// }
// }
// return $this->ret;
// }
//
// /**
// * 同上一方法类似,但允许多选
// */
// public function get_tree_multi($myid, $str, $sid = 0, $adds = '')
// {
// $number = 1;
// $child = $this->get_child($myid);
// if (is_array($child)) {
// $total = count($child);
// foreach ($child as $id => $a) {
// $j = $k = '';
// if ($number == $total) {
// $j .= $this->icon[2];
// } else {
// $j .= $this->icon[1];
// $k = $adds ? $this->icon[0] : '';
// }
// $spacer = $adds ? $adds . $j : '';
//
// $selected = $this->have($sid, $id) ? 'selected' : '';
// @extract($a);
// eval("\$nstr = \"$str\";");
// $this->ret .= $nstr;
// $this->get_tree_multi($id, $str, $sid, $adds . $k . ' ');
// $number++;
// }
// }
// return $this->ret;
// }
//
// /**
// * @param integer $myid 要查询的ID
// * @param string $str 第一种HTML代码方式
// * @param string $str2 第二种HTML代码方式
// * @param integer $sid 默认选中
// * @param integer $adds 前缀
// */
// public function get_tree_category($myid, $str, $str2, $sid = 0, $adds = '')
// {
// $number = 1;
// $child = $this->get_child($myid);
// if (is_array($child)) {
// $total = count($child);
// foreach ($child as $id => $a) {
// $j = $k = '';
// if ($number == $total) {
// $j .= $this->icon[2];
// } else {
// $j .= $this->icon[1];
// $k = $adds ? $this->icon[0] : '';
// }
// $spacer = $adds ? $adds . $j : '';
//
// $selected = $this->have($sid, $id) ? 'selected' : '';
// @extract($a);
// if (empty($html_disabled)) {
// eval("\$nstr = \"$str\";");
// } else {
// eval("\$nstr = \"$str2\";");
// }
// $this->ret .= $nstr;
// $this->get_tree_category($id, $str, $str2, $sid, $adds . $k . ' ');
// $number++;
// }
// }
// return $this->ret;
// }
//
// /**
// * 同上一类方法,jquery treeview 风格,可伸缩样式(需要treeview插件支持)
// * @param $myid 表示获得这个ID下的所有子级
// * @param $effected_id 需要生成treeview目录数的id
// * @param $str 末级样式
// * @param $str2 目录级别样式
// * @param $showlevel 直接显示层级数,其余为异步显示,0为全部限制
// * @param $style 目录样式 默认 filetree 可增加其他样式如'filetree treeview-famfamfam'
// * @param $currentlevel 计算当前层级,递归使用 适用改函数时不需要用该参数
// * @param $recursion 递归使用 外部调用时为FALSE
// */
// function get_treeview($myid, $effected_id = 'example', $str = "<span class='file'>\$name</span>", $str2 = "<span class='folder'>\$name</span>", $showlevel = 0, $style = 'filetree ', $currentlevel = 1, $recursion = FALSE)
// {
// $child = $this->get_child($myid);
// if (!defined('EFFECTED_INIT')) {
// $effected = ' id="' . $effected_id . '"';
// define('EFFECTED_INIT', 1);
// } else {
// $effected = '';
// }
// $placeholder = '<ul><li><span class="placeholder"></span></li></ul>';
// if (!$recursion) $this->str .= '<ul' . $effected . ' class="' . $style . '">';
// foreach ($child as $id => $a) {
//
// @extract($a);
// if ($showlevel > 0 && $showlevel == $currentlevel && $this->get_child($id)) $folder = 'hasChildren'; //如设置显示层级模式@2011.07.01
// $floder_status = isset($folder) ? ' class="' . $folder . '"' : '';
// $this->str .= $recursion ? '<ul><li' . $floder_status . ' id=\'' . $id . '\'>' : '<li' . $floder_status . ' id=\'' . $id . '\'>';
// $recursion = FALSE;
// if ($this->get_child($id)) {
// eval("\$nstr = \"$str2\";");
// $this->str .= $nstr;
// if ($showlevel == 0 || ($showlevel > 0 && $showlevel > $currentlevel)) {
// $this->get_treeview($id, $effected_id, $str, $str2, $showlevel, $style, $currentlevel + 1, TRUE);
// } elseif ($showlevel > 0 && $showlevel == $currentlevel) {
// $this->str .= $placeholder;
// }
// } else {
// eval("\$nstr = \"$str\";");
// $this->str .= $nstr;
// }
// $this->str .= $recursion ? '</li></ul>' : '</li>';
// }
// if (!$recursion) $this->str .= '</ul>';
// return $this->str;
// }
//
// /**
// * 获取子栏目json
// * Enter description here ...
// * @param unknown_type $myid
// */
// public function creat_sub_json($myid, $str = '')
// {
// $sub_cats = $this->get_child($myid);
// $n = 0;
// if (is_array($sub_cats)) foreach ($sub_cats as $c) {
// $data[$n]['id'] = iconv(CHARSET, 'utf-8', $c['catid']);
// if ($this->get_child($c['catid'])) {
// $data[$n]['liclass'] = 'hasChildren';
// $data[$n]['children'] = array(array('text' => ' ', 'classes' => 'placeholder'));
// $data[$n]['classes'] = 'folder';
// $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']);
// } else {
// if ($str) {
// @extract(array_iconv($c, CHARSET, 'utf-8'));
// eval("\$data[$n]['text'] = \"$str\";");
// } else {
// $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']);
// }
// }
// $n++;
// }
// return json_encode($data);
// }
//
// private function have($list, $item)
// {
// return (strpos(',,' . $list . ',', ',' . $item . ','));
// }
//}

@ -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…
Cancel
Save