<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\RequestException;

class indexAction extends baseAction
{
	function index()
	{
		$OthIm = new OthIm();
		$OthIm->addImActUser([1,2], 'im');
	}

	function testwx()
	{
		LibLog::write(file_get_contents('php://input')."\n_GET".json_encode($_GET)."\n_POST".json_encode($_POST));
		//echo '{"code": 0,"message": "success","data": {"type": 5000,"info":{"text": "跑街"}}}';
	}

	function cusRobot()
	{
		echo json_encode(["saymsg"=>$_POST], JSON_PARTIAL_OUTPUT_ON_ERROR);
	}

	/*function hdprice()
	{
		$YpwBase = new YpwBase();
		$sqlArr = [
			"UPDATE yp_paojieling.dl_order_list SET dml_money_gstc = '399.00', dml_money_selftc = '100.00', dml_money_ywytc = '100.00' 
			WHERE dml_atime >= 1668096000 AND dml_style = 'shop' AND dml_money_pay = '499.00' AND dml_dco_id = 1 and dml_dwo_uid not IN (172999)",

			"UPDATE yp_paojieling.dl_order_list SET dml_money_gstc = dml_money_pay-150.00, dml_money_selftc = '150.00', dml_money_ywytc = '150.00' 
			WHERE dml_atime >= 1668096000 AND dml_style = 'shop' AND dml_money_pay IN ('599.00', '699.00') AND dml_dco_id = 1 and dml_dwo_uid not IN (172999)",

			"UPDATE yp_paojieling.dl_order_list SET dml_money_gstc = '381.00', dml_money_selftc = dml_money_pay-381.00, dml_money_ywytc = dml_money_pay-381.00
			WHERE dml_atime >= 1668096000 AND dml_style = 'shop' AND dml_money_pay IN ('499.00', '599.00', '699.00') AND dml_dco_id != 1 and dml_dwo_uid not IN (172999)",
				
			"UPDATE yp_paojieling.dl_order_list SET dml_money_gstc = dml_money_pay, dml_money_selftc = '0.00', dml_money_ywytc = '0.00'
			WHERE dml_atime >= 1668096000 AND dml_style = 'shop' AND dml_money_pay IN ('499.00', '599.00', '699.00') AND dml_dwo_uid IN (172999)",

			"UPDATE yp_paojieling.bu_yeji_list, yp_paojieling.dl_order_list SET yl_user_money = dml_money_selftc, yl_com_money = dml_money_gstc 
			WHERE yl_dml_id = dml_id AND dml_atime >= 1668096000 AND dml_style = 'shop' AND yl_pay_money IN ('499.00', '599.00', '699.00')"
		];
		$YpwBase->exeAnySql($sqlArr, false);
		echo 'ok';
	}*/


	function wxbot()
	{
		LibLog::write(json_encode($_POST, JSON_PARTIAL_OUTPUT_ON_ERROR));
		echo '{"code": 0,"message": "success","data": {"type": 5000,"info":{"text": "跑街"}}}';
	}

	//测试跑街VIN识别准确率?file=xxx
	function chkPjlVinOcr()
	{
		$Params = mvc::$URL_PARAMS;
		$imgsDir = rtrim($Params['file'],'\/\\').'/';
		$LibHttp = new LibHttp();
		$MainOcr = new MainOcr();
		$url = 'http://192.168.1.118:8062/ocr/prediction';
		$result = ['all'=>0, 'ok'=>0, 'ok2'=>0, 'rate'=>0];
		foreach(glob($imgsDir.'*') as $file)
        {
			if(!is_file($file)) continue;
			$result['all']++;
			$imageData = base64_encode(file_get_contents($file));
			$res = $MainOcr->vin($imageData);
			$YtVin = $res['data'];

			$data = json_encode(["key"=>["image"], "value"=>[$imageData]]);
			$LibHttp->httpheader = ['Content-Type:application/json'];
			$html = $LibHttp->fetch($url, $data);
			$data = json_decode($html, true);
			$textArr = [];
			foreach($data['value'] as $rv)
			{
				$tArr = json_decode($rv, true);
				$textArr = array_merge($textArr, array_column($tArr, 'text'));
			}
			$pjVin = implode(',', $textArr);
			if(!empty($YtVin) && $YtVin == $pjVin){
				$result['ok']++;
				$result['ok2']++;
			}else if(!empty($YtVin) && stripos($pjVin, $YtVin) !== false){
				$result['ok2']++;
				echo $file, ' 译图：', $YtVin, ' 跑街：', $pjVin, ' 包含<br>';
			}else{
				similar_text($YtVin, $pjVin, $pencent);
				echo $file, ' 译图：', $YtVin, ' 跑街：', $pjVin, ' 相识度：', (int) $pencent,'%<br>';
			}
        }
		echo '完整：'.$result['ok'].'/'.$result['all'].' 匹配率：'.round($result['ok']/$result['all']*100, 2).'%<br>';
		echo '包含：'.$result['ok2'].'/'.$result['all'].' 匹配率：'.round($result['ok2']/$result['all']*100, 2).'%<br>';
	}


	//测试跑街VIN识别准确率 ?file=D:\CCPDPRO/val.txt
	function chkCcpdOcr()
	{
		$Params = mvc::$URL_PARAMS;
		$txt = $Params['file'];
		$dir = 'D:\CCPDPRO/';
		$txtArr = explode("\n", file_get_contents($txt));
		$MainOcr = new MainOcr();
		$url = 'http://192.168.1.118:8063/ocr/prediction';
		$result = ['all'=>0, 'ok'=>0, 'ok2'=>0, 'rate'=>0];
		foreach($txtArr as $txt){
			$row = explode("\t", $txt);
			$file = $dir.$row[0];
			if(!file_exists($file) || !is_file($file)) continue;
			$real = json_decode($row[1], true)[0]['transcription'];
			$result['all']++;
			$imageData = base64_encode(file_get_contents($file));
			$ocrCfg = [
				'style'=>'ccpd',
			];
			$res = $MainOcr->paddleOcr($imageData, $ocrCfg);
			$pjVal = $res['data'][0];
			if($pjVal == $real){
				$result['ok']++;
			}else{
				similar_text($real, $pjVal, $pencent);
				echo $file, ' 源：', $real, ' 跑街：', $pjVal, ' 相识度：', (int) $pencent,'%<br>';
			}
		}
		echo '完整：'.$result['ok'].'/'.$result['all'].' 匹配率：'.round($result['ok']/$result['all']*100, 2).'%<br>';
	}

	function imgdata()
	{
		echo base64_encode(file_get_contents($_GET['file']));
	}


	function get_image_type_from_base64($base64_str) {
    // Decode the base64 string
    $image_binary = base64_decode($base64_str);

    // Get image size and type information from the binary data
    $image_info = getimagesizefromstring($image_binary);

    if ($image_info !== false) {
        return $image_info['mime']; // Return the MIME type, e.g., 'image/jpeg', 'image/png'
    } else {
        return 'Unknown'; // If image type cannot be determined
    }
}

function getJpegQuality($filename)
{
    $fp = fopen($filename, 'rb');
    if (!$fp) return 75; // 默认 75

    fseek($fp, 2);

    while (!feof($fp)) {
        $marker = unpack('n', fread($fp, 2))[1];

        // 跳过 APP0-APP15
        if ($marker >= 0xFFE0 && $marker <= 0xFFEF) {
            $size = unpack('n', fread($fp, 2))[1];
            fseek($fp, $size - 2, SEEK_CUR);
            continue;
        }

        // 找到 DQT（量化表）
        if ($marker == 0xFFDB) {
            $size = unpack('n', fread($fp, 2))[1];
            $dqtData = fread($fp, $size - 2);
            fclose($fp);
            return $this->estimateQualityByQTable($dqtData);
        }
    }
    fclose($fp);
    return 75;
}

function estimateQualityByQTable($data)
{
    // 标准亮度量化表
    $std_luma_qt = [
        16,11,10,16,24,40,51,61,
        12,12,14,19,26,58,60,55,
        14,13,16,24,40,57,69,56,
        14,17,22,29,51,87,80,62,
        18,22,37,56,68,109,103,77,
        24,35,55,64,81,104,113,92,
        49,64,78,87,103,121,120,101,
        72,92,95,98,112,100,103,99
    ];

    // 读取量化表前 64 个
    $qt = array_values(unpack('C*', substr($data, 1, 64)));

    $sumRatio = 0;
    for ($i = 0; $i < 64; $i++) {
        if ($std_luma_qt[$i] == 0) continue;
        $sumRatio += $qt[$i] / $std_luma_qt[$i];
    }

    $relativeQ = $sumRatio / 64;
    $quality = round(5000 / $relativeQ) - 50;

    return max(1, min(100, $quality));
}


	function test()
	{
		$TcdmBase = new TcdmBase();
		$saveDir = 'D:\www\YPB2C\home\static\images\tlogo/';
		//已有的去括号匹配
		$res = $TcdmBase->get('tof_manufacturers', ['*']);
		$mfaArr = [];
		foreach($res['data'] as $v){
			$v['sname'] = [];
			$v['names'] = [$v['mfa_brand'], $v['mfa_brand_cn']];
			if(preg_match('/^(.*?)\s*\(/', $v['mfa_brand'], $m)){
				$v['sname'][] = trim($m[1]);
			}
			if(preg_match('/^(.*?)\s*\(/', $v['mfa_brand_cn'], $m)){
				$v['sname'][] = trim($m[1]);
			}
			if($v['mfa_logo'] != ''){
				$mfaArr['ok'][$v['mfa_id']] = $v;
			}else{
				$mfaArr['no'][$v['mfa_id']] = $v;
			}
		}

		$html = file_get_contents('D:\www/tcdlogo.html');
		$pattern = '/<a\s[^>]*>.*?<img\s[^>]*src\s*=\s*["\']([^"\']+)["\'][^>]*>.*?<p[^>]*>([^<]+)<\/p>.*?<\/a>/si';
		preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
		foreach ($matches as $match) {
			$logo = $match[1];
			$name = trim($match[2]);
			$sname = LibFc::ToEmglishCase($name);
			$org = 'D:\tlogo/'.str_replace('https://assets.tecalliance.net/manufacturers/', '', $logo);
			foreach($mfaArr['no'] as $kid=>$v){
				if(in_array($name, $v['names']) || in_array($sname, $v['names'])){
					$file = $saveDir.$v['mfa_id'].'.png';
					if(copy($org, $file)){
						$v['mfa_logo'] = $v['mfa_id'].'.png';
						$TcdmBase->set('tof_manufacturers', ['mfa_logo'=>$v['mfa_logo']], sprintf(" and mfa_id=%d", $v['mfa_id']));
						$mfaArr['ok'][$v['mfa_id']] = $v;
						unset($mfaArr['no'][$v['mfa_id']]);
					}
				}
			}
		}

		foreach($mfaArr['no'] as $kid=>$v){
			foreach($mfaArr['ok'] as $kk=>$vv){
				if($v['sname'] && $vv['sname']){
					if(array_intersect($v['sname'], $vv['sname']) || stripos($v['mfa_brand'], $vv['mfa_brand'].' ') === 0 || stripos($v['mfa_brand_cn'], $vv['mfa_brand_cn'].' ') === 0){
						$file = $saveDir.$v['mfa_id'].'.png';
						$org = $saveDir.$vv['mfa_id'].'.png';
						if(copy($org, $file)){
							$v['mfa_logo'] = $v['mfa_id'].'.png';
							$TcdmBase->set('tof_manufacturers', ['mfa_logo'=>$v['mfa_logo']], sprintf(" and mfa_id=%d", $v['mfa_id']));
							$mfaArr['ok'][$v['mfa_id']] = $v;
							unset($mfaArr['no'][$v['mfa_id']]);
						}
					}
				}
			}

		}

		$saveDir = 'D:\www\YPB2C\home\static\images\tlogo/';
		$res = $TcdmBase->get('yp_car.yp_brand', ['*'], '');
		$cnlogo = array_column($res['data'], null, 'b_name');
		$rename = [
			'沃尔沃亚太'=>'沃尔沃','海马汽车'=>'海马','东南汽车'=>'东南','乘龙'=>'乘龙汽车','五菱 (上汽通用五菱)'=>'五菱汽车','五菱 (柳州五菱)'=>'五菱汽车',
			'南京依维柯'=>'依维柯','厦门金旅'=>'金旅','吉奥'=>'广汽吉奥','哪吒 (合众汽车)'=>'哪吒汽车','赛力斯'=>'SERES赛力斯','长安商用'=>'长安','风光'=>'东风风光',
			'风神'=>'东风风神','魏派'=>'魏牌','广汽乘用车'=>'广汽集团','广汽新能源'=>'广汽集团','帝豪 (吉利)'=>'吉利','一汽奔腾'=>'奔腾'
		];
		foreach($mfaArr['no'] as $kid=>$v){
			$has = [];
			foreach(array_merge($v['names'], $v['sname']) as $vv){
				if($cnlogo[$vv]){
					$has = $cnlogo[$vv];
					break;
				}else if($cnlogo[strtr($vv, ['汽车'=>''])]){
					$has = $cnlogo[strtr($vv, ['汽车'=>''])];
					break;
				}else if($cnlogo[$vv.'汽车']){
					$has = $cnlogo[$vv.'汽车'];
					break;
				}else if($cnlogo[strtr($vv, $rename)]){
					$has = $cnlogo[strtr($vv, $rename)];
					break;
				}
			}
			if($has){
				$file = $saveDir.$v['mfa_id'].'.png';
				$org = $org = 'D:\www\YPB2C\home\static\images\chebiao\70/'.$has['b_code'].'.png';
				if(copy($org, $file)){
					$v['mfa_logo'] = $v['mfa_id'].'.png';
					$TcdmBase->set('tof_manufacturers', ['mfa_logo'=>$v['mfa_logo']], sprintf(" and mfa_id=%d", $v['mfa_id']));
					$mfaArr['ok'][$v['mfa_id']] = $v;
					unset($mfaArr['no'][$v['mfa_id']]);
				}
			}

		}

		exit;
		echo base64_encode(file_get_contents('C:\Users\soul\Desktop/2888d02c472733e9.png'));exit();
		$orgFile = 'D:\20240523/02e86e4633c3bb00.jpg';
		$toFile = 'D:\20240523/02e86e4633c3bb00_.jpg';
		$MainOcr = new MainOcr();
		$quality = 90;
		$imagedata = base64_encode(file_get_contents($orgFile));
		$res = $MainOcr->getVinInfoArea($imagedata);
		if($res['data']['pos']){
			$res = LibFc::cropImage($imagedata, $res['data']['pos'], 'base64', 'blob', $quality);
			file_put_contents($toFile, $res['data']);
			//var_dump($res);
		}
		
	

		/*$YpwVin = new YpwVin();

			$table = "(SELECT sce_id, sce_vin vin, sce_engine6 engine6, sce_reg_code site FROM stand_catch_list WHERE sce_reg_code='csvw' LIMIT 1000) t";
			$res = $YpwVin->get($table, ['aa*'], " order by rand() limit 10");
			exit;
		$LibHttp = new LibHttp();
		$time = time().rand(100, 999);
		$url  = 'https://searchadapter.eastmoney.com/api/suggest/get?cb=json&input=512880&type=8&token=D43BF722C8E33BDC906FB84D85E326E8&markettype=&mktnum=&jys=&classify=&securitytype=&status=&count=4&_='.$time;
		$res = $LibHttp->fetch($url);
		$res = substr($res, 5, -1);
		$resArr = json_decode($res, true);
		foreach($resArr['GubaCodeTable']['Data'] as $v){
			if(preg_match('/^[shsz]*([6|0|3|5]\d{5})$/i', $v['OuterCode'], $match)){
				$stockArr[] = ['name'=>$v['ShortName'], 'code'=>$match[1]];
			}
		}
		var_dump($stockArr);
*/
		echo 11;
		var_dump($_GET);
		exit;
	}


	//识别计算验证码
	function loadocrimg()
	{
		$cachefile = mvc::$cfg['PATH_CACHE'].'captcha.php';
		$cacheArr = file_exists($cachefile)? include($cachefile):[];
		$dir = 'D:\www\other\cnn_captcha\image/';
		$MainOcr = new MainOcr();
		$OthBaiduOcr = new OthBaiduOcr();
		if($handle = opendir($dir))
		{
            while(($file = readdir($handle))!==false)
			{
                if($file!='.' && $file!='..')
				{
					$dirfile = $dir.$file;
					if(!is_file($dirfile)) continue;
					$nameArr = explode('_', $file);
					//if(count($nameArr) > 2) continue;
					if(empty($cacheArr[$file]))
					{
						$imageData = base64_encode(file_get_contents($dirfile));
						/*$res = $MainOcr->baiduOcr($imageData, 1);
						$ocrtxt = json_decode($res['data']['html'], true);
						$ocrtxt = $ocrtxt['words_result'][0]['words'];
						*/
						$res = $OthBaiduOcr->ocr(['image'=>$imageData]);
						$ocrtxt = $res['data'];

						$re = ['*'=>'x','\u00d7'=>'x','X'=>'x', '×'=>'x','=?'=>'','=7'=>'', '-?'=>'', '?'=>''];
						$ocrtxt = strtr($ocrtxt, $re);
						$cacheArr[$file] = $ocrtxt;
						LibFc::ArraySave($cacheArr, $cachefile);
					}
					else
					{
						$ocrtxt = $cacheArr[$file];
					}
					$re2 = ['x'=>'*'];
					$txt2 = strtr($ocrtxt, $re2);
					if(preg_match('/\d[\+\-\*]\d[\+\-\*]\d/', $txt2, $match))
					{
						$txt2 = $match[0];
						eval("\$result = $txt2;");
						if($result == $nameArr[0])
						{
							$new = strtr($txt2, ['*'=>'x']);
							rename($dir.$file, $dir.'ok/'.$new.'_'.$file);
						}
					}
                }
            }
            closedir($handle);
        }
		echo 'ok';
	}
	
	//vecc 验证码
	function veccImgCode()
	{
		$dir = 'D:\www\other\cnn_captcha\image_vecc/';
		@mkdir($dir);
		$count = 1000;
		for($i = 0; $i < $count; $i++)
		{
			$imageData = file_get_contents('https://info.vecc.org.cn/ve/kaptcha.jpg?t=0.01341727193022102');
			file_put_contents($dir.date('md').$i.'.jpg', $imageData);
		}
	}
	
	//改名 训练 值_md5(imgdata).jpg
	function renameImgCode()
	{
		$rename = ['加'=>'+', '减'=>'-', '乘'=>'x'];
		$dir = 'D:\www\other\cnn_train\img_vecc2\origin/';
		$len = 3;
		if($handle = opendir($dir))
		{
            while(($file = readdir($handle))!==false)
			{
                if($file!='.' && $file!='..')
				{
					$t = explode('_', strtr($file, ['.'=>'_']));
					if(strlen(strtr($t[0], $rename)) != $len)
					{
						echo $dir.$file, '<br>';
						unlink($dir.$file);
						continue;
					}
					$newname = strtr($t[0], $rename).'_'.md5(file_get_contents($dir.$file)).'.'.$t[count($t)-1];
					rename($dir.$file, $dir.$newname);
                }
            }
            closedir($handle);
            @clearstatcache();
        }
		echo 'ok';
	}

	
	//通过IP补统计表的省份
	function buTjProvice()
	{
		$OthPct = new OthPct();
		$PjltjBase = new PjltjBase();
		$where = " and tj_site = 'PJL' AND tj_act = 'data/numberSearch' AND JSON_UNQUOTE(tj_param->'$.pct_ids') IS NULL GROUP BY tj_ip";
		$tres = $PjltjBase->get('at_tongji', ['tj_ip'], $where);
		foreach($tres['data'] as $tv)
		{
			$res = $OthPct->getIpPCT($tv['tj_ip']);
			$PjltjBase->set('at_tongji', ['tj_param'=>"#@JSON_SET(tj_param, '$.pct_ids', '".((int) $res['data']['pctids'][0])."')"], sprintf(" and tj_ip='%s'", $tv['tj_ip']));
		}
		echo 'ok';
	}

	function jdfapiao()
	{
		$btime = strtotime('2026-01-01');
		$dir = 'E:\发票\2026/';
		// 请求头设置
		$headers = [
			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
			"Accept-Encoding: gzip, deflate, br, zstd",
			"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",
			"Cache-Control: no-cache",
			"Connection: keep-alive",
			"Content-Length: 6",
			"Content-Type: application/x-www-form-urlencoded",
			"Cookie: hshshfpa=af3c9c89-e43a-3d73-15e8-2c848b60ef18-1600994719; shshshfpx=af3c9c89-e43a-3d73-15e8-2c848b60ef18-1600994719; b_corpBehavior=2; pinId=Z0uWyN5HovK5USg3UqJBXw; pin=2959360159; unick=soulocy; corpBehavior=2; __jdu=17008040310611849691009; TrackID=13NlEaBGEz7IRKJ6ZhkGPuh1boXrCHjS5fZszCqnRLeL7xauBdHa3nrjuiMPhn3aB9u5kK4bUn73w9y-BaAb6JYJvp60PaQYR6xM61BxyuVg; light_key=AASBKE7rOxgWQziEhC_QY6yaWFXSSW_oHjemmlwRneeV8gkkYeaV7EDGDZOLG8jgzD79wmFQ; __jdv=76161171|8.138.107.126|-|referral|-|1767575330930; areaId=19; ipLoc-djd=19-1601-50258-129167; 3AB9D23F7A4B3CSS=jdd03WT6XYZ3MQ3UYZOTL3F3UOG2SIBSKMBPIWRFYIFCO75E2RGOZFOXE5MJ5ZI6PB3BKQISJX5XEQA6SA6QKMLZSATHQ44AAAAM3YXJW6JYAAAAADJ5VIK2LK2IRH4X; mail_times=4%2C1%2C1768550526642; umc_count=1; shshshfpb=BApXWigLbxv5AyjKZFn3Tx6chRfMwpl7CB0LYQDZX9xJ1OI4CKN-FxEq62XIrItp1E9Y246eDi8Ewd-s2vq9at9ir-WvZ; source=PC; platform=pc; flash=3_t9gA8pW2AYNiJ47c1tpP7tPSi_7KW8SkQI8vp4yn5dk26oD9kpGzY7wQQeOFI8ut7_TnpL_9ybnLl_j41RBOYbLZsT2MgxivNPtzhht4mGeC0P00EDNHrC_bXoMk-qmv9zqOzKRRi2ARKPrS5cFqKkJjqMQlZZS3-Dmnz819blsm6k**; __jda=236447133.17008040310611849691009.1700804031.1768457369.1768550526.110; __jdc=236447133; __jdb=236447133.45.17008040310611849691009|110.1768550526; 3AB9D23F7A4B3C9B=WT6XYZ3MQ3UYZOTL3F3UOG2SIBSKMBPIWRFYIFCO75E2RGOZFOXE5MJ5ZI6PB3BKQISJX5XEQA6SA6QKMLZSATHQ44",
			"Host: myivc.jd.com",
			"Origin: https://myivc.jd.com",
			"Pragma: no-cache",
			"Referer: https://myivc.jd.com/fpzz.html",
			"Sec-Fetch-Dest: document",
			"Sec-Fetch-Mode: navigate",
			"Sec-Fetch-Site: same-origin",
			"Sec-Fetch-User: ?1",
			"Upgrade-Insecure-Requests: 1",
			"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
			"content-type: application/x-www-form-urlencoded",
			'sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138", "Google Chrome";v="138"',
			"sec-ch-ua-mobile: ?0",
			'sec-ch-ua-platform: "Windows"'
		  ];

		$OthPdfOcr = new OthPdfOcr();
		$LibHttp = new LibHttp();
		
		$isend = false;
		for($page = 1; $page < 100; $page++)
		{
			$LibHttp->httpheader = $headers;
			$listhtml = $LibHttp->fetch('https://myivc.jd.com/fpzz/index.action', ['page'=>$page]);
			echo $page, '页<br>';
			if(preg_match_all('/<tbody>.*<span class="dealtime"[^>]*>([^<]+)<\/span>.*<a href="([^"]+)"[^>]*>发票详情<\/a>/iUs', $listhtml, $match))
			{
				foreach($match[1] as $tk=>$tv)
				{
					if(strtotime($tv) < $btime)
					{
						$isend = true;
						break;
					}
					else
					{
						$url = 'https://myivc.jd.com'.$match[2][$tk];
						$curl = curl_init();
						curl_setopt_array($curl, [
						  CURLOPT_URL => $url,
						  CURLOPT_RETURNTRANSFER => true,
						  CURLOPT_ENCODING => "",
						  CURLOPT_MAXREDIRS => 10,
						  CURLOPT_TIMEOUT => 30,
						  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
						  CURLOPT_CUSTOMREQUEST => "GET",
						  CURLOPT_POSTFIELDS => "page=2",
						  CURLOPT_HTTPHEADER => $headers
						]);

						$html = curl_exec($curl);
						$err = curl_error($curl);
						if(preg_match('/href="([^"]+)"[^>]*><i><\/i><em>查看发票/', $html, $tmatch)){
							$fpurl = $tmatch[1];
							//echo '<a href="'.$fpurl.'" target="_blank">'.$fpurl.'</a>', '<br>';
							$pdfFile = $dir.'FP'.strtoupper(dechex(crc32(($fpurl)))).'.pdf';
							if(!file_exists($pdfFile))
							{
								$LibHttp->httpheader = [];
								$html = $LibHttp->fetch($fpurl);
								if(stripos($html, 'pdf') === false || strlen($html) < 1024*5)
								{
									echo $fpurl.'下载失败'.$html;
									exit;
								}
								file_put_contents($pdfFile, $html);
							}
						}else{
							echo $url.'匹配失败';
						}
					}
				}
			}
			if($isend) break;
		}
		echo 'ok';
	}

	function jdfapiaoje()
	{
		$sPath = 'E:\发票\202301\欧昌宇';
		$sSum = 0;
		$aPath = $this->glob_file($sPath);
		foreach ($aPath as $sKey => $sVal) {
			$sSum = bcadd($sSum, pathinfo($sVal, PATHINFO_FILENAME), 2);
		}
		var_dump($sSum);
	
	}

	 /**
     * 获取文件列表
     */
    function glob_file($sPath, $aReturn = [])
    {
        $sPath = rtrim($sPath, '/');
        foreach(glob($sPath . '/*') as $sDir)
        {
            if (is_dir($sDir)) {
                $aReturn = array_merge($aReturn, glob_file($sDir));
            } else {
                $aReturn[] = $sDir;
            }
        }
        return $aReturn;
    }


	function vinOcr()
	{
		$file = 'D:/010.jpg';
		$imageData = base64_encode(file_get_contents($file));
		$MainOcr = new MainOcr();
		$res = $MainOcr->vin($imageData);
		var_dump($res);
	}


	public function track17()
	{
		LibLog::write(json_encode($POST, JSON_PARTIAL_OUTPUT_ON_ERROR), mvc::$cfg['PATH_CACHE'].'track17.txt');
		LibLog::write(file_get_contents('php://input'), mvc::$cfg['PATH_CACHE'].'track172.txt');
		echo 'ok';
	}


	function addDbByTxt()
	{
		exit;
		$YpwVin = new YpwVin();
		$file = fopen("D:/vins20240103.txt", "r");
		$add = [];
		while(!feof($file)){
			$line = fgets($file);
			$line = LibFc::FormatNum($line);
			if(strlen($line) == 17){
				$add[] = ['cat_vin'=>LibFc::FormatNum($line)];
				if(count($add) == 20000){
					$YpwVin->addAny('ztemp.vin_only', array_keys($add[0]), $add);
					$add = [];
				}
			}
		}
		if(count($add) > 0){
			$YpwVin->addAny('ztemp.vin_only', array_keys($add[0]), $add);
		}
		fclose($file);
	}

	
	//?act=img  ?act=ocr
	function formatVinOcrImg()
	{
		$Params = mvc::$URL_PARAMS;
		$act = $Params['act'];
		$hostArr = [
			'vinimg_1'=>'https://file.paojd.cn/files/vinimg/',
			'vinimg_2'=>'http://192.168.1.67:83/vinimg/',	
		];
		$imgdir = 'D:\/vinTrainImg2/';
		@mkdir($imgdir);
		$YpwVin = new YpwVin();
		$LibHttp = new LibHttp();
		$MainOcr = new MainOcr();
		if($act == 'img'){
			$per = 500;
			for($page = 1; $page < 100; $page++){
				$vres = $YpwVin->get('(select * from ocr_vin_train where ovt_status=0  limit 10000) t', ['*'], ' order by rand() limit '.$per);
				foreach($vres['data'] as $v){
					$v['ovt_newname'] = $v['ovt_vin'].'_'.basename($v['ovt_img']);
					$file = $imgdir.$v['ovt_newname'];
					if(!file_exists($file)){
						
						$url = $hostArr['vinimg_'.$v['ovt_host']].$v['ovt_img'];
						$html = $LibHttp->fetch($url);
						if(strlen($html) > 1024) file_put_contents($file, $html);
					}
					if(file_exists($file)) $YpwVin->set('ocr_vin_train', ['ovt_status'=>1, 'ovt_newname'=>$v['ovt_newname']], ' and ovt_status=0 and ovt_id='.$v['ovt_id']);
				}
				if(count($vres['data']) < $per) break;
			}
		}

		if($act == 'ocr'){
			$per = 500;
			for($page = 1; $page < 100; $page++){
				$vres = $YpwVin->get('ocr_vin_train', ['*'], ' and ovt_status=1 order by rand() limit '.$per);
				foreach($vres['data'] as $v){
					$file = $imgdir.$v['ovt_newname'];
					if(file_exists($file)){
						$image = base64_encode(file_get_contents($file));
						$ocrCfg = ['type'=>'all', 'style'=>'cn'];
						$result = $MainOcr->paddleOcr($image, $ocrCfg);
						$v['ovt_paddleocr'] = json_encode($result['data'], JSON_UNESCAPED_UNICODE);
					}
					if(!empty($v['ovt_paddleocr'])) 
						$YpwVin->set('ocr_vin_train', ['ovt_status'=>2, 'ovt_paddleocr'=>$v['ovt_paddleocr']], ' and ovt_status=1 and ovt_id='.$v['ovt_id']);
				}
				if(count($vres['data']) < $per) break;
			}
		}

		if($act == 'vinpos'){
			$per = 500;
			for($page = 1; $page < 100; $page++){
				$vres = $YpwVin->get('ocr_vin_train', ['*'], " and ovt_status=2 and JSON_UNQUOTE(ovt_vinpos->'$.text') is null order by rand() limit ".$per);
				foreach($vres['data'] as $v){
					$v['ovt_paddleocr'] = json_decode($v['ovt_paddleocr'], true);
					$vinpos = ['text'=>''];
					foreach($v['ovt_paddleocr'] as $vv){
						if($v['ovt_vin'] == $vv['text']){
							$vinpos = $vv;
							break;
						}
					}
					$set = ['ovt_vinpos'=>	json_encode($vinpos, JSON_UNESCAPED_UNICODE)];
					if($vinpos['text']) $set['ovt_status'] = 3;
					$YpwVin->set('ocr_vin_train', $set, ' and ovt_status=2 and ovt_id='.$v['ovt_id']);
				}
				if(count($vres['data']) < $per) break;
			}
		}

		if($act == 'det'){
			$baseDir = 'D:\/vinTrainImgDet/';
			LibDir::ClearDir($baseDir);
			$imagesTrainDir = $baseDir . 'images/train/';
			$imagesValDir = $baseDir . 'images/val/';
			$labelsTrainDir = $baseDir . 'labels/train/';
			$labelsValDir = $baseDir . 'labels/val/';
			$trainFile = $baseDir . 'train.txt';
			$valFile = $baseDir . 'val.txt';
			$classesFile = $baseDir . 'classes.names';
			LibDir::CreateDir($imagesTrainDir);
			LibDir::CreateDir($imagesValDir);
			LibDir::CreateDir($labelsTrainDir);
			LibDir::CreateDir($labelsValDir);
			file_put_contents($classesFile, "vin\n");
			
			$vres = $YpwVin->get('ocr_vin_train', ['*'], " and ovt_status=3");
			$data = $vres['data'];
			// 打乱数据集
			shuffle($data);
			// 计算训练和测试集的数量
			$total = count($data);
			$trainCount = round($total * 0.95);

			$trainData = array_slice($data, 0, $trainCount);
			$valData = array_slice($data, $trainCount);

			$trainFileList = [];
			$valFileList = [];

			$this->processDataset($trainData, $imagesTrainDir, $labelsTrainDir, $trainFileList);
			$this->processDataset($valData, $imagesValDir, $labelsValDir, $valFileList);

			// 写入训练和测试文件列表
			$trainTxt = str_replace($baseDir, './', implode("\n", $trainFileList));
			file_put_contents($trainFile, $trainTxt);
			$valTxt = str_replace($baseDir, './', implode("\n", $valFileList));
			file_put_contents($valFile, $valTxt);
		}

		if($act == 'rec'){
			$baseDir = 'D:\/vinTrainImgRec/';
			LibDir::ClearDir($baseDir);
			$imgPath = $baseDir . 'images/';
			$trainPath = $baseDir . 'train/';
			$valPath = $baseDir . 'val/';
			$testPath = $baseDir . 'test/';
			LibDir::CreateDir($imgPath);
			LibDir::CreateDir($trainPath);
			LibDir::CreateDir($valPath);
			LibDir::CreateDir($testPath);
			LibDir::CreateDir($baseDir);
			
			$vres = $YpwVin->get('ocr_vin_train', ['*'], " and ovt_status=3");
			$dataArr = $vres['data'];
			// 打乱数据集
			shuffle($dataArr);
			$total = count($dataArr);
			$trainCount = (int) ($total * 0.9);
			$valCount = (int) ($total * 0.05);
			$testCount = $total - $trainCount - $valCount;
			$trainFileList = [];
			$valFileList = [];
			$testFileList = [];

			foreach ($dataArr as $key => $row) {
				$vin = $row['ovt_vin'];
				$vinPos = json_decode($row['ovt_vinpos'], true);
				$imageName = $row['ovt_newname'];
				$pos = $vinPos['pos']; // 左上、右上、右下、左下

				// 读取原始图像
				$originalImage = imagecreatefromjpeg($imgdir.$row['ovt_newname']);
				// 计算车架号区域的边界框
				$left = min($pos[0][0], $pos[3][0]);
				$top = min($pos[0][1], $pos[1][1]);
				$right = max($pos[1][0], $pos[2][0]);
				$bottom = max($pos[2][1], $pos[3][1]);
				$width = $right - $left;
				$height = $bottom - $top;

				// 创建新的车架号图像
				$newVinImage = imagecreatetruecolor($width, $height);

				// 从原始图像中截取车架号区域
				imagecopy($newVinImage, $originalImage, 0, 0, $left, $top, $width, $height);

				// 保存新的车架号图像
				$newVinImagePath = $imgPath.$imageName;
				imagejpeg($newVinImage, $newVinImagePath);

				// 释放资源
				imagedestroy($originalImage);
				imagedestroy($newVinImage);

				// 生成标签文件内容
				$labelContent = "$newVinImagePath $vin\n";
				// 决定数据集划分
				if ($key < $trainCount) {
					$trainFileList[] = $labelContent;
				} elseif ($key < $trainCount + $valCount) {
					$valFileList[] = $labelContent;
				} else {
					$testFileList[] = $labelContent;
				}
			}
			
			$trainTxt = str_replace($baseDir, './', implode("\n", $trainFileList));
			file_put_contents($trainPath.'labels.txt', $trainTxt);
			$valTxt = str_replace($baseDir, './', implode("\n", $valFileList));
			file_put_contents($valPath.'labels.txt', $valTxt);
			$testTxt = str_replace($baseDir, './', implode("\n", $testFileList));
			file_put_contents($testPath.'labels.txt', $testTxt);
		}
		echo 'ok';
	}


	// 处理数据并生成注释文件
    function processDataset($data, $imagesDir, $labelsDir, &$fileList) {
		$imgdir = 'D:\/vinTrainImg/';
        foreach ($data as $row) {
            $vin = $row['ovt_vin'];
            $imagePath = $imgdir.$row['ovt_newname'];
            $vinPos = json_decode($row['ovt_vinpos'], true);

            // 获取边界框位置并计算YOLO格式所需的值
            $pos = $vinPos['pos'];
            $x_min = min($pos[0][0], $pos[3][0]);
            $x_max = max($pos[1][0], $pos[2][0]);
            $y_min = min($pos[0][1], $pos[1][1]);
            $y_max = max($pos[2][1], $pos[3][1]);

            $imageSize = getimagesize($imagePath);
            $imageWidth = $imageSize[0];
            $imageHeight = $imageSize[1];

            $x_center = (($x_min + $x_max) / 2.0) / $imageWidth;
            $y_center = (($y_min + $y_max) / 2.0) / $imageHeight;
            $width = ($x_max - $x_min) / $imageWidth;
            $height = ($y_max - $y_min) / $imageHeight;

            // 创建YOLO注释文件内容
            $classId = 0; // 假设车架号类别ID为0
            $annotationContent = "$classId $x_center $y_center $width $height\n";

            // 写入注释文件
            $annotationFileName = pathinfo($imagePath, PATHINFO_FILENAME) . '.txt';
            $labelFilePath = $labelsDir . $annotationFileName;
            file_put_contents($labelFilePath, $annotationContent);

            // 复制图像文件到指定目录
            $targetImagePath = $imagesDir . basename($imagePath);
            if (!copy($imagePath, $targetImagePath)) {
                echo "Failed to copy $imagePath...\n";
            }
            // 添加文件路径到列表
            $fileList[] = $targetImagePath;
        }
    }


	public function cleanData()
	{
		$TcdmItem = new TcdmItem();
		$res = $TcdmItem->cleanData($_POST);
		LibFc::EchoJson($res);
	}

	//获取指定内容的位置信息
	public function getValMatchPos($imgfile, $orgVal, $ocrstr)
	{
		$imgfile = '';
		$orgVal = 'LFV2A2153K6170759';
		$ocrstr = '[{"pos": [[53, 123], [318, 139], [317, 160], [52, 144]], "text": "中国一汽-大众汽车有限公司制造", "match": "0.9536791"}, {"pos": [[54, 141], [313, 162], [312, 183], [52, 162]], "text": "品牌：大众牌整车型号：FV7152NABCG", "match": "0.97709846"}, {"pos": [[56, 162], [101, 166], [99, 182], [55, 178]], "text": "车辆识", "match": "0.99922323"}, {"pos": [[60, 179], [104, 181], [103, 201], [59, 198]], "text": "别代号", "match": "0.99799585"}, {"pos": [[113, 174], [303, 189], [301, 209], [112, 194]], "text": "LFV2A2153K6170759", "match": "0.99559414"}, {"pos": [[71, 198], [120, 202], [119, 220], [69, 215]], "text": "制造年孔", "match": "0.41179544"}, {"pos": [[114, 202], [171, 205], [170, 222], [113, 218]], "text": "2019-09-04", "match": "0.99133843"}, {"pos": [[73, 213], [111, 217], [108, 234], [71, 230]], "text": "来垒人责", "match": "0.51295066"}, {"pos": [[189, 208], [291, 216], [290, 234], [188, 226]], "text": "最大允许总质量：1730", "match": "0.92379117"}, {"pos": [[135, 221], [148, 221], [148, 236], [135, 236]], "text": "5", "match": "0.99747074"}, {"pos": [[205, 225], [253, 230], [251, 247], [203, 241]], "text": "发动机排量：", "match": "0.9769955"}, {"pos": [[71, 229], [113, 233], [112, 250], [69, 246]], "text": "发动机型号", "match": "0.8525871"}, {"pos": [[132, 233], [159, 237], [157, 254], [130, 250]], "text": "DMB", "match": "0.99249345"}, {"pos": [[249, 228], [291, 234], [288, 251], [247, 245]], "text": "1498", "match": "0.9966949"}, {"pos": [[189, 240], [251, 247], [250, 262], [187, 255]], "text": "发动机最大净功率：", "match": "0.8609599"}, {"pos": [[300, 234], [312, 234], [312, 252], [300, 252]], "text": "E", "match": "0.35682008"}, {"pos": [[262, 248], [279, 248], [279, 264], [262, 264]], "text": "83", "match": "0.9975379"}, {"pos": [[300, 251], [315, 251], [315, 267], [300, 267]], "text": "kW", "match": "0.8877783"}]';
		$ocrArr = json_decode($ocrstr, true);
		$arr = [];
		$last = 90;
		foreach($ocrArr as $v){
			similar_text($orgVal, $v['text'], $rate);
			if(preg_match('/^[a-zA-Z0-9]{13,}$/', $v['text'], $match) && $rate > $last){
				$arr = $v;
				$arr['rate'] = $rate;
				$pos = $v['pos'];
				$x_min = min($pos[0][0], $pos[3][0]);
				$x_max = max($pos[1][0], $pos[2][0]);
				$y_min = min($pos[0][1], $pos[1][1]);
				$y_max = max($pos[2][1], $pos[3][1]);
				if($rate > 95) break;
			}
		}
		if($arr){
			$imgsize = getimagesize($imgfile);
            $imgw = $imgsize[0];
            $imgh = $imgsize[1];
            $x_center = (($x_min + $x_max) / 2.0) / $imgw;
            $y_center = (($y_min + $y_max) / 2.0) / $imgh;
            $width = ($x_max - $x_min) / $imgw;
            $height = ($y_max - $y_min) / $imgh;
            $classId = 0; // 假设车架号类别ID为0
            $arr['yolo'] = "$classId $x_center $y_center $width $height\n";
		}
		return $arr;
	}


	public function expShopPro()
	{
		$shopid = 408916;
		$file = 'D:/shoppro_'.$shopid.'.json';
		$B2cProduct = new B2cProduct();
		$Ypc2Model = new Ypc2Model();
		
		$table = 'bc_product 
			join sh_shop on pro_shop_id=shop_id
			join bc_product_info on pro_id=pri_pro_id 
			join bc_part on pro_part_id = part_id 
			left join bc_part_small on part_id = pas_part_id and pro_pas_id = pas_id
			left join bc_probrand on pro_prb_id=prb_id';
		$res = $B2cProduct->get($table, ['pro_id', 'prb_name', 'part_name', 'pas_name', 'pro_name','pri_code'], sprintf(" and pro_shop_id = %d and pro_status=1", $shopid));
		$proArr = [];
		$chAllArr = array_chunk($res['data'], 100, true);
		$exArr = [
			'fields'=>[
				'pro_id'=>'产品ID',
				'pro_name'=>'产品品牌',
				'pro_code'=>'自编号',
				'nums'=>'互换号',
				'models'=>'适用车型',
			]
		];
		foreach($chAllArr as $chArr){
			$pids = implode(',', array_column($chArr, 'pro_id'));
			//号码
			$numArr = [];
			$table = 'bc_number 
			JOIN bc_product ON num_pro_id = pro_id
			JOIN bc_product_info ON pro_id = pri_pro_id';
			$res = $B2cProduct->get($table, ['pro_id, CASE WHEN num_self = 1 THEN pri_code ELSE num_factory END num_factory, num_display , num_format'], sprintf(" and pro_id in (%s)", $pids));
			foreach($res['data'] as $vv){
				$numArr[$vv['pro_id']][] = $vv;
			}
			
			$modArr = [];
			$table = '`ypb2c`.`bc_product_model3_link` 
			JOIN bc_model3 ON mod3_id  = pml3_mod3_id 
			JOIN bc_model2 ON mod3_mod2_id = mod2_id
			JOIN bc_model1 ON mod2_mod1_id = mod1_id
			JOIN bc_make ON mod1_make_id = make_id
			JOIN bc_brand ON mod1_brand_id = brand_id';
			$res = $Ypc2Model->get($table, ['pml3_pro_id pro_id, mod3_id, brand_name, make_name, mod2_name, mod2_start_year, mod2_end_year, mod3_name, mod3_start_year,mod3_end_year,mod3_engine, mod3_kw, mod3_cc, mod3_cc_name, mod3_transmission, mod3_fuel,mod3_body, mod3_drive, mod3_start_stop, mod3_chassis,mod3_front_brake, mod3_rear_brake,mod3_parking_brake'], sprintf(" and pml3_pro_id in (%s)", $pids));
			foreach($res['data'] as $vv){
				$name = $vv['brand_name'];
				if($vv['brand_name'] != $vv['make_name']) $name .= ' '.$vv['make_name'];
				$name .= ' '.$vv['mod2_name'];
				$name .= ' '.$vv['mod3_name'];
				$name .= '（发动机：'.$vv['mod3_engine'];
				$name .= ' 排量：'.$vv['mod3_cc_name'];
				$name .= ' 变速箱：'.$vv['mod3_transmission'];
				$name .= ' 驱动：'.$vv['mod3_drive'];
				$name .= ')';
				$modArr[$vv['pro_id']][] = ['mod3_id'=>$vv['mod3_id'], 'full_name'=>$name];
			}

			foreach($chArr as $pv){
				$pid = $pv['pro_id'];
				$pv['nums'] = $numArr[$pid]? $numArr[$pid]: [];
				$pv['model'] = $modArr[$pid]? $modArr[$pid]: [];
				$proArr[] = $pv;
				$exArr[] = [
					'pro_id'=>$pv['pro_id'],
					'pro_name'=>$pv['pro_name'],
					'pro_code'=>$pv['prb_name'].':'.$pv['pri_code'],
					'nums'=>implode("\n", array_column($pv['nums'], 'num_display')),
					'models'=>implode("\n", array_column($pv['model'], 'full_name')),
				];
			}
		}
		file_put_contents($file, json_encode($proArr, JSON_UNESCAPED_UNICODE));

		$OthSExcel = new OthSExcel();
		$res = $OthSExcel->writer($exArr);
		//echo 'ok';
	}


	public function mergeGa()
	{
		$orgfile = 'D:/9-1110.xlsx';
		$newfile = '小类对应TCD分类.xlsx';
		$OthSExcel = new OthSExcel();
		$TcdmItem = new TcdmItem();
		$res = $OthSExcel->read($orgfile, 0, [], 0);
		$rows = $res['data'][0];
		$header = $rows[0];
		$header2 = array_flip($header);
		//产品名称	产品所属类别	原TDC	修改TDC
		$cateArr = [];
		foreach($rows as $k=>$v){
			if($k == 0){
				$fields = $rows[0];
				continue;
			}
			foreach(explode("\n", $v[1]) as $vv){
				if(preg_match('/(.*)\[(\d+)\]/', $vv, $match))
				if(!empty($vv)) $cateArr[$v[0]][$match[1]] += $match[2];
			}
		}
		
		$data = [];
		foreach($cateArr as $k=>$v){
			arsort($v);
			$tvs = [];
			foreach($v as $kk=>$vv){
				$tvs[] = $kk.'['.$vv.']';
			}
			$data[] = [$k, implode("\n", $tvs)];
		}
		$OthSExcel->writer($data, $newfile);
	}


	public function formatArtGa()
	{
		$orgfile = 'D:\PDM上线数据5.19.xlsx';
		$newfile = '匹配PDM上线数据5.19.xlsx';
		$OthSExcel = new OthSExcel();
		$TcdmItem = new TcdmItem();
		$res = $OthSExcel->read($orgfile, 0, [], 0);
		$rows = $res['data'][0];
		$header = $rows[0];
		$header2 = array_flip($header);
		foreach($rows as $k=>$v){
			if($k == 0){
				$rows[$k][] = 'TCD分类';
				continue;
			} 
			$oes = [];
			foreach(['OE', '去除后缀后OE'] as $oef){
				if($v[$header2[$oef]]){
					$format = LibFc::FormatNum($v[$header2[$oef]]);
					if(strlen($format) > 3) $oes[] = $format;
				}
			}
			$gas = [];
			if($oes){
				$table = 'tof_articles JOIN tof_article_number ON arl_art_id = art_id and arl_kind =3 join tof_generic_articles on ga_id = art_ga_id';
				$res = $TcdmItem->get($table, ['ga_name_cn', 'count(distinct art_id) art_count'], sprintf(" and arl_format in ('%s') group by ga_name_cn order by count(distinct art_id) desc", implode("','", $oes)));
				foreach($res['data'] as $vv){
					$gas[] = $vv['ga_name_cn'].'['.$vv['art_count'].']';
				}
			}
			$rows[$k][] = implode("\n", $gas);
		}
		$OthSExcel->writer($rows, $newfile);
	}

	function catchTask()
	{
		$maxErr = 10;
		$maxErrWait = 60;
		$nullTaskWait = 60;
		$maxPer = 3; // 并发数控制

		$errCount = 0;
		while (true) {
			$client = new Client();
			$baseurl = 'https://www.csvw.com/epps/publicityController/queryEpVehicle';
			$YpwVin = new YpwVin();

			$table = "(SELECT sce_id, sce_vin vin, sce_engine6 engine6, sce_reg_code site FROM stand_catch_list WHERE sce_reg_code='csvw' LIMIT 1000) t";
			$res = $YpwVin->get($table, ['*'], " order by rand() limit 10");

			$taskArr = array_column($res['data'], null, 'sce_id');

			if (empty($taskArr)) {
				echo "无任务，休眠 {$nullTaskWait} 秒...<hr>";
				sleep($nullTaskWait);
				continue;
			}

			// 准备任务请求
			$requests = function () use ($taskArr, $baseurl) {
				foreach ($taskArr as $kid => $row) {
					yield $kid => new Request('POST', $baseurl, [
						'Content-Type' => 'application/x-www-form-urlencoded'
					], http_build_query(['vin' => $row['vin']]));
				}
			};

			$pool = new Pool($client, $requests(), [
				'concurrency' => $maxPer,
				'fulfilled' => function ($response, $index) use (&$errCount, $taskArr) {
					$orgData = $taskArr[$index];
					$content = $response->getBody()->getContents();
					$errCount = 0;

					echo date('H:i:s') . " 成功：VIN={$orgData['vin']}<hr>";
					var_dump($orgData, $content);
				},
				'rejected' => function ($reason, $index) use (&$errCount, $taskArr, $maxErr, $maxErrWait) {
					$orgData = $taskArr[$index];
					echo "错误 VIN={$orgData['vin']} - " . $reason->getMessage() . "<hr>";

					$errCount++;
					if ($errCount >= $maxErr) {
						echo "连续错误超过 {$maxErr} 次，休眠 {$maxErrWait} 秒...<hr>";
						sleep($maxErrWait);
						$errCount = $errCount > 5 ? $errCount - 5 : 0;
					}
				}
			]);

			// 阻塞直到所有请求完成
			$promise = $pool->promise();
			$promise->wait();
		}
	}
}