<?php
/**
  * @method 产品管理
  * @author soul
  * @copyright 2016/3/31
  */
class B2cProduct extends B2cBase
{
	protected  $operation ='';
	protected  $refresh = true;
	/**
	  * @method 获取配件基本信息
	  * @param  $proIdArr array [11,2222....]
	  * @param  $typeArr ['numMain', 'numAll', 'picMain', 'picAll', 'desc'...]
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
			成功 ["status"=>true, "data"=> [11=>[], ...]] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getAnyProductInfo($proIdArr, $uid = 0, $typeArr = [], $showConf = [], $mod3Id = 0)
	{
		$uid = (int) $uid;
		$proArr = [];
		foreach($proIdArr as $k=>$v)
		{
			$proId = (int) $v;
			$proArr[$proId] = [];
		}
		$proIdArr = array_keys($proArr);
		$typeArr = empty($typeArr)? ['numMain', 'picMain','para']: $typeArr;
		if(!empty($proIdArr))
		{
			$showWhere = [];
			foreach($showConf as $k=>$v)
			{
				$showWhere[] = sprintf(" %s=%d", LibFc::Escape($k), $v);
			}
			$showWhere = empty($showWhere)? '': sprintf(" and (%s)", implode(',', $showWhere));

			$fieldArr = ['pro_prb_id','pro_id', 'prb_name', 'pas_name', 'pro_status', 'pro_name', 'pro_shop_id', 'pro_sale_price', 'pro_promotion_price', 'pro_count', 'pro_user_discount', 'pro_sold_count','pro_self',
			'pro_promotion_btime', 'pro_promotion_etime','pro_part_id', 'pro_ppt_id','pri_code','pri_weight','pri_des','pri_frt_id','pro_sel_des','pro_count','pri_invoice','pri_warranty','pri_return_promise', 'shop_zbnum','shop_smainnum', 'shop_srefnum'];
			if($uid > 0)
				$fieldArr = array_merge($fieldArr, ['pro_price_vip1', 'pro_price_vip2', 'pro_price_vip3', 'pro_price_vip4']);
			if(in_array('desc', $typeArr)) $fieldArr[] = 'pri_des';
			$table = 'bc_product as a join sh_shop on pro_shop_id=shop_id join bc_product_info on pro_id=pri_pro_id left join bc_probrand on pro_prb_id=prb_id left join bc_part_small on pro_pas_id=pas_id';
			$res = $this->get($table, $fieldArr, sprintf(" and pro_id in(%s) %s", implode(',', $proIdArr), $showWhere));
			if(empty($res['data']))
				return LibFc::ReturnData(true, $proArr);
			
			$proPriceArr = [];
			if(in_array('mdPrice',$typeArr) && in_array($res['data'][0]['pro_shop_id'],[732634,965832]))
			{	//明达
				if($res['data'][0]['pro_shop_id'] == 732634)
				{
					$B2cCustom = new B2cCustom();
					$proPriceArr = $B2cCustom->getProInfoByDy($uid,$proIdArr);
				}
				//宝德
				if($res['data'][0]['pro_shop_id'] == 965832)
				{
					$B2cBDCustom = new B2cBDCustom();
					$proPriceArr = $B2cBDCustom->getProInfoByDy($uid,$proIdArr);
				}
				
				if($proPriceArr['data']) $proPriceArr = array_column($proPriceArr['data'],'price','pro_id');
			}
			
			//基本信息
			foreach($res['data'] as $v)
			{	
				if(in_array('para', $typeArr))
				{
					$paraRes = $this->getProductPara($v['pro_id'], $v['pro_part_id']);
					$v['para'] = $paraRes['data'];
				}
				//非会员购买价格
				$v['price'] = $v['pro_promotion_price'] > 0 && $v['pro_promotion_btime'] <= time() && $v['pro_promotion_etime'] >= time()? $v['pro_promotion_price']: $v['pro_sale_price'];
				if($uid > 0&&$v['pro_user_discount']=='Y')
				{
					//获取该会员在店铺里的级别
					$table = 'sh_member_link join sh_member on mem_id=meml_mem_id and mem_status=1 and meml_shop_id=mem_shop_id';
					$levelRes = $this->get($table, ['mem_mel_id'], sprintf(" and meml_shop_id=%d and meml_uid=%d", $v['pro_shop_id'], $uid), true);
					if(!empty($levelRes['data']) && $v['pro_price_vip'.$levelRes['data']['mem_mel_id']] > 0 && ($v['pro_price_vip'.$levelRes['data']['mem_mel_id']] < $v['price'] || $v['price'] <= 0)){
						$v['price'] = $v['pro_price_vip'.$levelRes['data']['mem_mel_id']];
					}
				}
				if(isset($proPriceArr[$v['pro_id']])) $v['price'] = $proPriceArr[$v['pro_id']];
				unset($v['pro_promotion_price']);
				unset($v['pro_promotion_btime']);
				unset($v['pro_promotion_etime']);
				$v['pic'] = [];
				$v['num'] = [
					$v['prb_name'].'@'.$v['pri_code']=>[
						'num_factory'=>$v['prb_name'],
						'num_display'=>$v['pri_code']
					]
				];
				$proArr[$v['pro_id']] = $v;
			}

			//剔除无数据的
			foreach($proArr as $k=>$v)
			{
				if(empty($v)) unset($proArr[$k]);
			}

			$proIdArr = array_keys($proArr);

			//图片
			if(in_array('picMain', $typeArr))
			{
				$resPic = $this->getProductPic($proIdArr, false);
			}
			else if(in_array('picAll', $typeArr))
			{
				$resPic = $this->getProductPic($proIdArr, true);
			}
			if(!empty($resPic['data']))
			{
				foreach($resPic['data'] as $proId=>$picArr)
				{
					$proArr[$proId]['pic'] = $picArr;
				}
			}

			//自编号 主号
			$numFiled = ['num_pro_id', 'num_factory', 'num_display','num_ismain','num_self'];
			if(in_array('numMain', $typeArr))
			{
				$where = sprintf(" and num_pro_id in(%s) and  (num_ismain=1 or num_self=1) order by num_self desc, num_ismain desc", implode(',', $proIdArr));
				$resNum = $this->get('bc_number', $numFiled, $where);
			}
			if(!empty($resNum['data']))
			{
				foreach($resNum['data'] as $v)
				{
					//自编号品牌
					$v['num_factory'] = $v['num_self'] == 1 && isset($proArr[$v['num_pro_id']]['prb_name'])? $proArr[$v['num_pro_id']]['prb_name']: $v['num_factory'];
					$ntype = '';
					if($v['num_self'] == 1) $ntype = 'zb';
					else if($v['num_ismain'] == 1) $ntype = 'main';
					$temp = $v;
					$temp['type'] = $ntype;
					unset($temp['num_pro_id']);
					$proArr[$v['num_pro_id']]['num'][$temp['num_factory'].'@'.$temp['num_display']] = $temp;
				}
			}

			//车型参数
			if(!empty($mod3Id))
			{
				$modelPara = [];

				$where = sprintf(" and pml3_pro_id in (%s) and pml3_mod3_id =%d and pml3_remark != '' group by pml3_pro_id, pml3_remark", implode(',', array_keys($proArr)), $mod3Id);
				$res = $this->get('bc_product_model3_link', ['pml3_pro_id', 'pml3_remark'], $where);
				foreach($res['data'] as $pv)
				{
					$modelPara[$pv['pml3_pro_id']][] = $pv['pml3_remark'];
				}

				$where = sprintf(" and pmp_pro_id in (%s) and pmp_mod3_id =%d and pmp_info != '' group by pmp_pro_id, pmp_info", implode(',', array_keys($proArr)), $mod3Id);
				$res = $this->get('bc_product_model3_para', ['pmp_pro_id', 'pmp_info'], $where);
				foreach($res['data'] as $pv)
				{
					$modelPara[$pv['pmp_pro_id']][] = $pv['pmp_info'];
				}
				foreach($modelPara as $pk=>$pv)
				{
					$proArr[$pk]['mod3_para'] = implode(';', array_unique($pv));
				}
			}
			if(empty(mvc::$cfg['FROM']) || mvc::$cfg['FROM'] != 'gzh')
			{
				foreach($proArr as $pk=>$pv)
				{	
					foreach($pv['num'] as $tk=>$tv)
					{
						//是否隐藏主号码   是否隐藏自编号
						if((empty($pv['shop_smainnum']) && $tv['type'] == 'main') || (empty($pv['shop_zbnum']) && $tv['type'] == 'zb'))
						{
							unset($pv['num'][$tk]);
						}
					}
					$pv['num'] = array_values($pv['num']);
					$proArr[$pk] = $pv;
				}
			}
		}
		return LibFc::ReturnData(true, $proArr);
	}
	
	
	/**
	  * @method 获取配件基本信息
	  * @param  $FieldArr 需要查询的字段名称数组
	  * @param  $Where 查询条件
	  * @param  $OneRow true|false
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
			成功 ["status"=>true, "data"=> $OneRow=false 二维数组 ; $OneRow=true 一维数组] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getProduct($fieldArr, $where = '', $oneRow = false)
	{
		$table = 'bc_product 
		join sh_shop on pro_shop_id=shop_id
		join bc_product_info on pro_id=pri_pro_id
		left join bc_part_small on pro_pas_id=pas_id
		left join bc_probrand on pro_prb_id=prb_id';
		return $this->get($table, $fieldArr, $where, $oneRow);
	}
	

	/**
	  * @method 添加产品
	  * @author soul
	  * @copyright 2017/6/5
	  * @return [["status"]=> bool(true) ["data"]=> $proId ["code"]=> int(0) ]
	  */
	public function addProduct($dataArr,$shopId)
	{
		$this->operation = 'add';
		if(empty($dataArr['base']['pro_shop_id']) || empty($dataArr['base']['pro_part_id']) || !is_array($dataArr))
			return LibFc::ReturnData(false, 'addProduct 提供的参数不正确');
		
		if(empty($dataArr['base']['pro_part_path']))
		{
			$res = $this->get('bc_part join bc_part_tree on part_id=pt_part_id', ['pt_part_id', 'pt_path'], sprintf(" and pt_part_id=%d and pt_ismain=1", $dataArr['base']['pro_part_id']), true);
			if(empty($res['data']))
				return LibFc::ReturnData(false, 'addProduct 提供的分类ID参数不存在！');
			$dataArr['base']['pro_part_path'] = $res['data']['pt_path'].','.$res['data']['pt_part_id'];
		}

		$res = $this->get('sh_shop', ['*'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'setProduct 店铺ID不存在');
		$shopArr = $res['data'];
		$dataArr['base']['pro_show_b2c'] = $shopArr['shop_show_b2c'];
		$dataArr['base']['pro_show_app'] = $shopArr['shop_show_app'];
		$dataArr['base']['pro_show_super'] = $shopArr['shop_show_super'];
		$dataArr['base']['pro_show_pjl'] = $shopArr['shop_show_pjl'];
		$priceArr = ['pro_sale_price','pro_price_vip1','pro_price_vip2','pro_price_vip3','pro_price_vip4'];
		foreach ($priceArr as $val) {
			$dataArr['base'][$val] = (float)$dataArr['base'][$val];
		}
		$B2cKeyword = new B2cKeyword();
		$B2cLog = new B2cLog();
		$this->B2CDb->Begin();

		$partId = $dataArr['base']['pro_part_id'];
		$dataArr['base']['pro_add_time'] = time();
		$dataArr['base']['pro_set_time'] = time();
		if(!$dataArr['base']['pro_add_uid'])
		{
			$dataArr['base']['pro_add_uid'] = $dataArr['base']['pro_set_uid'] = mvc::$cfg['LOGUSER']['uid']?:$_SESSION['_userid'];
		}
		
		if(isset($dataArr['base']['pro_ppt_id'])) $dataArr['base']['pro_ppt_id'] = (int) $dataArr['base']['pro_ppt_id'];
		//名称为空则自动获取零件名称
		
		if(empty($dataArr['base']['pro_name']))
		{
			if(!empty($dataArr['base']['pro_pas_id']))
			{
				$res = $this->get('bc_part_small', ['pas_name as pro_name'], sprintf(" and pas_id=%d", $dataArr['base']['pro_pas_id']), true);
				if(!empty($res['data'])) $dataArr['base']['pro_name'] = $res['data']['pro_name'];
			}
			if(empty($dataArr['base']['pro_name']))
			{
				$res = $this->get('bc_part', ['part_name as pro_name'], sprintf(" and part_id=%d", $dataArr['base']['pro_part_id']), true);
				if(!empty($res['data'])) $dataArr['base']['pro_name'] = $res['data']['pro_name'];
			}
		}
		if(substr($dataArr['base']['pro_part_path'],-1) == ',') $dataArr['base']['pro_part_path'] = rtrim($dataArr['base']['pro_part_path'],',');
		$res = $this->add('bc_product', $dataArr['base']);
		$proId = $res['data'];
		
		$dataArr['info']['pri_pro_id'] = $proId;
		$this->add('bc_product_info', $dataArr['info']);

		$factory = '';
		if($dataArr['base']['pro_prb_id']){
			$facres = $this->get('bc_probrand',['prb_name'],sprintf(" and prb_id=%d",$dataArr['base']['pro_prb_id']),true);
			$factory = $facres['data']['prb_name'];
		}
		
		$this->setProductSelfNum($proId, ['factory'=>$factory,'display'=>$dataArr['info']['pri_code']]);

		//图片
		if(isset($dataArr['imgs']))
		{
			$this->setProductPic($shopId, $proId, $dataArr['imgs']);
		}

		if(isset($dataArr['param']))
		{
			$this->setProductParam($proId, $partId, $dataArr['param']);
		}

		if(isset($dataArr['nums']))
		{
			$this->setProductNum($proId, $dataArr['nums']);
		}
		
		//更新车型
		if(isset($dataArr['modchassis']))
		{
			//底盘件车型
			$this->setProductModChassis($proId, $dataArr['modchassis']);
		}
		else if(isset($dataArr['modengine']))
		{
			//发动机件车型
			$this->setProductModEngine($proId, $dataArr['modengine']);
		}
		else if(isset($dataArr['modall']))
		{
			$this->setProductModel($proId, $dataArr['modall'], 'all');
		}
		else if(isset($dataArr['model']))
		{
			$this->setProductModel($proId, $dataArr['model']);
		}

		if(isset($dataArr['shopSort']))
		{
			$this->setProductShopSort($proId, $dataArr['shopSort']);
		}
		if($this->refresh)
		{
			//刷新配件关键字
			$B2cKeyword->resetProductKeyword([$proId]);
		}
		
		$logItem = [
			'sli_pro_id'=>$proId,
			'sli_shop_id'=>$shopId,
			'sli_etime'=>time(),
			'sli_act'=>'add',
			'sli_txt'=>'添加配件：'.$dataArr['info']['pri_code']
		];
		$B2cLog->addFastLogItem($logItem);
		$item = [
			'log_category'=>1,
			'log_shop_id'=>$shopId,
			'log_atime'=>time(),
			'log_dataid'=>$proId,
			'log_txt'=>'添加配件：'.$dataArr['info']['pri_code']
		];
		$B2cLog->addFastLog($item);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $proId);
	}


	/**
	  * @method 修改产品
	  * @param  $shopId int  店铺ID
	  * @param  $proId  int  产品ID
	  * @author soul
	  * @copyright 2017/6/5
	  * @return [["status"]=> bool(true) ["data"]=> ["code"]=> int(0) ]
	  */
	public function setProduct($shopId, $proId, $dataArr)
	{
		$shopId = (int) $shopId;
		$proId = (int) $proId;
		if($shopId < 1 || $proId < 1 || !is_array($dataArr)) return LibFc::ReturnData(false, 'setProduct 提供的参数不正确');

		$res = $this->get('sh_shop', ['*'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'setProduct 店铺ID不存在');
		$shopArr = $res['data'];
		$dataArr['base']['pro_show_b2c'] = $shopArr['shop_show_b2c'];
		$dataArr['base']['pro_show_app'] = $shopArr['shop_show_app'];
		$dataArr['base']['pro_show_super'] = $shopArr['shop_show_super'];
		$dataArr['base']['pro_show_pjl'] = $shopArr['shop_show_pjl'];
		$priceArr = ['pro_sale_price','pro_price_vip1','pro_price_vip2','pro_price_vip3','pro_price_vip4'];
		foreach ($priceArr as $val) {
			$dataArr['base'][$val] = (float)$dataArr['base'][$val];
		}
		$B2cKeyword = new B2cKeyword();
		$B2cLog = new B2cLog();
		//校验产品是否为改店铺的
		$res = $this->get('bc_product', ['pro_shop_id', 'pro_part_id'], sprintf(" and pro_id = %d", $proId), true);
		if(empty($res['data']))
		{
			return LibFc::ReturnData(false, 'setProduct 此配件不存在或者已被删除');
		}
		else if($res['data']['pro_shop_id'] != $shopId)
		{
			return LibFc::ReturnData(false, 'setProduct 此配件不属于该店铺ID');
		}

		$this->B2CDb->Begin();
		$oldPartId = $res['data']['pro_part_id'];
		$partId = isset($dataArr['base']['pro_part_id']) ? $dataArr['base']['pro_part_id']: $res['data']['pro_part_id'];

		if(isset($dataArr['info']))
		{
			$res = $this->get('bc_product_info', ['pri_pro_id','pri_code'], sprintf(" and pri_pro_id = %d", $proId), true);
			if(empty($res['data']['pri_pro_id']))
			{
				$dataArr['info']['pri_pro_id'] = $proId;
				$this->add('bc_product_info', $dataArr['info']);
			}
			else
			{
				$this->set('bc_product_info', $dataArr['info'], sprintf(" and pri_pro_id = %d", $proId));
				if($res['data']['pri_code']!=$dataArr['info']['pri_code']){
					$logItem = [
						'sli_pro_id'=>$proId,
						'sli_etime'=>time(),
						'sli_act'=>'num',
						'sli_txt'=>"配件自编号由:{$res['data']['pri_code']}变更为：{$dataArr['info']['pri_code']}"
					];
					$B2cLog->addFastLogItem($logItem);
				}
			}
			$factory = '';
			if($dataArr['base']['pro_prb_id']){
				$facres = $this->get('bc_probrand',['prb_name'],sprintf(" and prb_id=%d",$dataArr['base']['pro_prb_id']),true);
				$factory = $facres['data']['prb_name'];
			}
			
			$this->setProductSelfNum($proId, ['factory'=>$factory,'display'=>$dataArr['info']['pri_code']]);
		}

		//图片
		if(isset($dataArr['imgs']))
		{
			$this->setProductPic($shopId, $proId, $dataArr['imgs']);
		}

		if(isset($dataArr['param']))
		{
			$this->setProductParam($proId, $partId, $dataArr['param']);
		}

		if(isset($dataArr['nums']))
		{
			$this->setProductNum($proId, $dataArr['nums']);
		}
		
		//更新车型
		if(isset($dataArr['modchassis']))
		{
			//底盘件车型
			$this->setProductModChassis($proId, $dataArr['modchassis']);
		}
		else if(isset($dataArr['modengine']))
		{
			//发动机件车型
			$this->setProductModEngine($proId, $dataArr['modengine']);
		}
		else if(isset($dataArr['modall']))
		{
			$this->setProductModel($proId, $dataArr['modall'], 'all');
		}
		else if(isset($dataArr['model']))
		{
			$this->setProductModel($proId, $dataArr['model']);
		}

		if(isset($dataArr['shopSort']))
		{
			$this->setProductShopSort($proId, $dataArr['shopSort']);
		}

		$dataArr['base']['pro_set_time'] = time();
		if(!$dataArr['base']['pro_set_uid'])
		{
			$dataArr['base']['pro_set_uid'] = mvc::$cfg['LOGUSER']['uid']?:$_SESSION['_userid'];
		}
		
		if(isset($dataArr['base']['pro_ppt_id'])) $dataArr['base']['pro_ppt_id'] = (int) $dataArr['base']['pro_ppt_id'];
		
		if(substr($dataArr['base']['pro_part_path'],-1) == ',') $dataArr['base']['pro_part_path'] = rtrim($dataArr['base']['pro_part_path'],',');
		$this->set('bc_product', $dataArr['base'], sprintf(" and pro_id = %d", $proId));

		// print_r($_POST);exit();
		if($_POST['pro']['pro_ppt_id'])
		{
			//修改自定义参数
			$this->setShopParam($shopId,$proId,$_POST['pro']['pro_ppt_id'],$_POST['paramVal'],$_POST['paramLabel'],$_POST['paramUnit'],$oriTpl);
		}
		if($this->refresh)
		{
			//刷新配件关键字
			$B2cKeyword->resetProductKeyword([$proId]);
		}
		$item = [
			'log_category'=>1,
			'log_shop_id'=>$shopId,
			'log_atime'=>time(),
			'log_dataid'=>$proId,
			'log_txt'=>'编辑配件：'.$dataArr['info']['pri_code']
		];
		$B2cLog->addFastLog($item);
		//同步车型
		$this->syncModel($shopId,$proId);
		//同步号码
		$this->syncNumber($shopId,$proId);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 给配件添加一个分类参数 | 仅限点选的分类参数
	  * @param  $proId  int  产品ID
	  * @param  $partId int  配件分类ID
	  * @param  $param  str  参数值  [["位置","前"],["轴承","16.5 mm"]] == 
	  *    给某一配件的某一分类参数,如果预选值存在则为点选，pav_id关联即可,如果是输入则无点选0关联即可,数字或字符串类型分别入为不同的两个配件零件参数关联
	  * @author xu
	  * @copyright 2018/03/22
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	public function setBatchPartParam($proId, $partId, $param)
	{
		if(!LibFc::Int($proId) || !LibFc::Int($partId) || empty($param))
			return LibFc::ReturnData(false, 'setBatchPartParam 提供的参数不正确');

		$this->B2CDb->Begin();

		foreach ($param as $v)
		{
			// 初始化配件分类参数
			$where = sprintf(" and ppl_part_id=%d and pal_name='%s'",$partId,LibFc::Escape(current($v)));
			$res = $this->get('bc_part_param_link left join bc_param_label on ppl_pal_id=pal_id',['*'],$where,true);
			$partParamLink = $res['data'];
			if(empty($res['data'])) continue;// 分类不具备该参数
			$this->del('bc_product_param_float',sprintf("and ppf_pro_id=%d and ppf_pal_id=%d",$proId,$partParamLink['ppl_pal_id']));
			$this->del('bc_product_param_string',sprintf("and pps_pro_id=%d and pps_pal_id=%d",$proId,$partParamLink['ppl_pal_id']));	
		}



		foreach ($param as $v)
		{
			$where = sprintf(" and ppl_part_id=%d and pal_name='%s'",$partId,LibFc::Escape(current($v)));
			$res = $this->get('bc_part_param_link left join bc_param_label on ppl_pal_id=pal_id',['*'],$where,true);
			$partParamLink = $res['data'];
			// 分类不具备该参数
			if(empty($res['data'])) continue;


			if($partParamLink['ppl_style'] == 1)
			{
				// 参数值 - 数值型
				if(!is_numeric($v[1])) continue;//过滤掉当前参数 - 数值型非数值
				// 查询预选值表
				$where = sprintf("and pav_pal_id=%d and pav_part_id=%d and pav_value='%s' ",$partParamLink['pal_id'],$partId,$v[1]);
				$res = $this->get('bc_param_value',['pav_id'],$where,true);

				if(empty($res['data']))
				{
					$res = $this->get('bc_product_param_float',['*'],sprintf("and ppf_pro_id=%d and ppf_pal_id=%d",$proId,$partParamLink['ppl_pal_id']));
					if(empty($res['data']))
					{
						// 零件参数值表
						$pps_pav_id = $res['data']['pav_id'];
						$temp = ['ppf_pro_id' => $proId,'ppf_pal_id' =>$partParamLink['ppl_pal_id'],'ppf_value' =>$v[1],'ppf_pav_id' => 0];
						$this->add('bc_product_param_float',$temp);
					}
				}
				else
				{
					// 零件参数值表
					$pps_pav_id = $res['data']['pav_id'];
					$temp = ['ppf_pro_id' => $proId,'ppf_pal_id' =>$partParamLink['ppl_pal_id'],'ppf_value' =>$v[1],'ppf_pav_id' => $pps_pav_id];
					$this->add('bc_product_param_float',$temp);
				}
			}
			else
			{
				// 是否有预选
				$where = sprintf("and pav_pal_id=%d and pav_part_id=%d and pav_value='%s' ",$partParamLink['pal_id'],$partId,$v[1]);
				$res = $this->get('bc_param_value',['pav_id'],$where,true);

				if(empty($res['data']))
				{
					// 无预选 - 只入库第一个作为输入值
					$res = $this->get('bc_product_param_string',['*'],sprintf("and pps_pro_id=%d and pps_pal_id=%d",$proId,$partParamLink['ppl_pal_id']));
					if(empty($res['data']))
					{
						// 零件参数值表
						$temp = ['pps_pro_id' => $proId,'pps_pal_id' =>$partParamLink['ppl_pal_id'],'pps_value' =>$v[1],'pps_pav_id' => 0];
						$this->add('bc_product_param_string',$temp);
					}
				}
				else
				{
					$pps_pav_id = $res['data']['pav_id'];
					$temp = ['pps_pro_id' => $proId,'pps_pal_id' =>$partParamLink['ppl_pal_id'],'pps_value' =>$v[1],'pps_pav_id' => $pps_pav_id];
					$this->add('bc_product_param_string',$temp);
				}
			}
		}

		$this->B2CDb->End();
		
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 批量导入时候修改配件的自定义参数|不管什么参数都加入到默认模板里面
	  * @param  $proId  int  产品ID
	  * @param  $shopId  int  店铺ID
	  * @param  $param  param  [['位置','前轮'],['制动系统','ATE'],['宽度','94.85mm']]
	  * @author xu
	  * @copyright 2018/05/03
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	public function setBatchParam($proId,$shopId,$param,$pptName = '默认模板',$pru_id=0)
	{
		if(!LibFc::Int($proId) || !LibFc::Int($shopId) || empty($param))
			return LibFc::ReturnData(false, 'setBatchParam 提供的参数不正确');
		$pru_id = (int) $pru_id;
		if(empty($pptName)) $pptName = '默认模板';

		$this->B2CDb->Begin();
		//添加默认模板
		$res = $this->get('bc_product_para_tpl',['*'],sprintf("and ppt_name='%s' and ppt_shop_id=%d",$pptName,$shopId),true);
		if(empty($res['data']))
		{
			$temp = ['ppt_shop_id' => $shopId,'ppt_name' => $pptName,'ppt_atime' => time(),];
			$res = $this->add('bc_product_para_tpl',$temp);
			$ppt_id = $res['data'];
		}
		else
		{
			$ppt_id = $res['data']['ppt_id'];
		}


		foreach ($param as $k => $v)
		{
			// 添加参数名
			$res = $this->get('bc_product_label',['prl_id'],sprintf("and prl_name='%s'",current($v)),true);
			if(empty($res['data']))
			{
				$res = $this->add('bc_product_label',['prl_name'=>current($v)]);
				$prl_id = $res['data'];
			}
			else
			{
				$prl_id = $res['data']['prl_id'];
			}
			// 参数-模板关联
			$res = $this->get('bc_product_para_tpl_link',['*'],sprintf("and pptl_ppt_id=%d and pptl_prl_id=%d",$ppt_id,$prl_id),true);
			if(empty($res['data']))
			{
				$this->add('bc_product_para_tpl_link',['pptl_ppt_id'=>$ppt_id,'pptl_prl_id'=>$prl_id,'pptl_pru_id'=>$pru_id]);
			}
			// 添加参数值
			$res = $this->get('bc_product_para_val',['*'],sprintf("and prpv_pro_id=%d and prpv_prl_id=%d",$proId,$prl_id),true);
			if(empty($res['data']))
			{
				$temp = ['prpv_pro_id'=> $proId,'prpv_prl_id'=> $prl_id,'prpv_pru_id'=> $pru_id,'prpv_value'=>LibFc::Escape($v[1])];
				$this->add('bc_product_para_val',$temp);
			}
			else
			{
				$temp = ['prpv_pru_id'=> $pru_id,'prpv_value'=>LibFc::Escape($v[1])];
				$this->set('bc_product_para_val',$temp,sprintf("and prpv_pro_id=%d and prpv_prl_id=%d",$proId,$prl_id));
			}
		}


		// 配件 + 模板关联
		$this->set('bc_product',['pro_ppt_id'=>$ppt_id],sprintf("and pro_id=%d",$proId));
		$this->B2CDb->End();
		
		return LibFc::ReturnData(true, true);
	}





	/**
	  * @method 修改配件的参数
	  * @param  $proId  int  产品ID
	  * @param  $partId int  配件分类ID
	  * @param  $paramArr  array  [11=>'左', 12=>'xxx'....]
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	private function setProductParam($proId, $partId, $paramArr)
	{
		$partId = (int) $partId;
		$proId = (int) $proId;
		if($partId < 1 || $proId < 1 || !is_array($paramArr))
		{
			return LibFc::ReturnData(false, 'setProductParam 提供的参数不正确');
		}
		$this->B2CDb->Begin();

		$res = $this->get('bc_part_param_link join bc_param_label on pal_id=ppl_pal_id', ['ppl_pal_id', 'ppl_style','pal_name'], sprintf(" and ppl_part_id=%d", $partId));
		$partParam = [];
		$labelName = [];
		foreach($res['data'] as $v)
		{	
			$labelName[$v['ppl_pal_id']] = $v['pal_name'];
			$partParam[$v['ppl_pal_id']] = $v['ppl_style'];
		}
		// print_r($paramArr);
		// print_r($partParam);
		//校验用户提交的数据
		$newParamArr = [0=>[], 1=>[]];
		$newValArr=[0=>[], 1=>[]];
		$allNewVal=[];
		foreach($paramArr as $k=>$v)
		{
			if(is_array($v))
			{
				foreach ($v as $valId) 
				{
					if(!isset($partParam[$k]) || $valId == '' || ($partParam[$k] == 1 && !LibFc::Float($valId)))
					{
						continue;
					}
					$allNewVal[]=$valId;
					$newValArr[$partParam[$k]][]=$valId;
					$newParamArr[$partParam[$k]][$k][] = $valId;
				}
			}
			else
			{
				$v = trim($v);
				if(!isset($partParam[$k]) || $v == '' || ($partParam[$k] == 1 && !LibFc::Float($v)))
				{
					continue;
				}
				$newParamArr[$partParam[$k]][$k] = $v;
			}
		}
		//取默认值
		if(count($allNewVal))
		{
			$res=$this->get('bc_param_value',['pav_id','pav_value'],sprintf(' and pav_id in (%s)',implode(',',$allNewVal)));
			$valArr=array_column($res['data'], null,'pav_id');
		}
		
		//字符型
		$res = $this->getFieldUniVal('bc_product_param_string', 'pps_pal_id', sprintf(" and pps_pro_id=%d", $proId));
		$oldPalIdArr = $res['data'];
		$logArr = [];
		//获取旧参数标签
		$oldLabelName = $labelName;
		$res = $this->get('bc_product',['pro_part_id'],sprintf(" AND pro_id=%d",$proId),true);
		if($res['data'] && $partId!=$res['data']['pro_part_id'])
		{
			$table = 'bc_part_param_link join bc_param_label on pal_id =ppl_pal_id';
			$res =	$this->get($table,['pal_id','pal_name'],sprintf(" and ppl_part_id=%d",$res['data']['pro_part_id']));
			$oldLabelName = array_column($res['data'],'pal_name','pal_id');
		}
		$oldValArr = $this->get('bc_product_param_string',['pps_pal_id','pps_value'],sprintf(" and pps_pro_id = %d",$proId));
		$oldValArr = array_column($oldValArr['data'],'pps_value','pps_pal_id');
		//需要删除的标签ID
		$delPalIdArr = array_diff($oldPalIdArr, array_keys($newParamArr[0]));
		if(!empty($delPalIdArr))
		{
			foreach ($delPalIdArr as $delpalId) {
				$logArr[] = $oldLabelName[$delpalId].": \"{$oldValArr[$delpalId]}\" 变更为 \"\" ";
			}
			$this->del('bc_product_param_string', sprintf(" and pps_pro_id=%d and pps_pal_id in (%s)", $proId, implode(',', $delPalIdArr)));
		}
		//需要删除的值ID
		$res=$this->getFieldUniVal('bc_product_param_string','pps_pav_id',sprintf(' and pps_pav_id>0 and pps_pro_id=%d',$proId));
		$oldValIdArr = $res['data'];

		$delValIdArr = array_diff($oldValIdArr, $newValArr[0]);
		if(count($delValIdArr))
		{
			$this->del('bc_product_param_string', sprintf(" and pps_pro_id=%d and pps_pav_id in (%s)", $proId, implode(',', $delValIdArr)));
		}
		foreach($newParamArr[0] as $palId=>$v)
		{
			if(is_array($v))
			{
				foreach ($v as $value) 
				{
					$val=isset($valArr[$value])?$valArr[$value]['pav_value']:'';
					if(in_array($value, $oldValIdArr))
					{
						if($oldValArr[$value] !=$val)
						{	
							$logArr[] =$labelName[$value].": \"{$oldValArr[$value]}\" 变更为 \"{$val}\"";
						}
						
						$this->set('bc_product_param_string', ['pps_pav_id'=>$value,'pps_value'=>$val], sprintf(" and pps_pro_id=%d and pps_pav_id=%d", $proId, $value));
					}
					else
					{
						$logArr[] =$labelName[$palId].": \"\" 变更为 \"{$val}\"";
						$this->add('bc_product_param_string', ['pps_pro_id'=>$proId, 'pps_pal_id'=>$palId, 'pps_pav_id'=>$value,'pps_value'=>$val]);
					}
				}
			}
			else
			{
				if(in_array($palId, $oldPalIdArr))
				{
					if($oldValArr[$palId] !=$v)
					{	
						$logArr[] =$labelName[$palId].": \"{$oldValArr[$palId]}\" 变更为 \"{$v}\"";
					}
					$this->set('bc_product_param_string', ['pps_value'=>$v], sprintf(" and pps_pro_id=%d and pps_pal_id=%d", $proId, $palId));
				}
				else
				{
					$logArr[] =$labelName[$palId].": \"\" 变更为 \"{$v}\"";
					$this->add('bc_product_param_string', ['pps_pro_id'=>$proId, 'pps_pal_id'=>$palId, 'pps_value'=>$v]);
				}
			}
		}

		//数值型
		$res = $this->getFieldUniVal('bc_product_param_float', 'ppf_pal_id', sprintf(" and ppf_pro_id=%d", $proId));
		$oldPalIdArr = $res['data'];
		$oldValArr = $this->get('bc_product_param_float',['ppf_pal_id','ppf_value'],sprintf(" and ppf_pro_id = %d",$proId));
		$oldValArr = array_column($oldValArr['data'],'ppf_value','ppf_pal_id');
		$delPalIdArr = array_diff($oldPalIdArr, array_keys($newParamArr[1]));
		if(!empty($delPalIdArr))
		{
			foreach ($delPalIdArr as $delpalId) {
				$logArr[] = $oldLabelName[$delpalId].": \"{$oldValArr[$delpalId]}\" 变更为 \"\" ";
			}
			$this->del('bc_product_param_float', sprintf(" and ppf_pro_id=%d and ppf_pal_id in (%s)", $proId, implode(',', $delPalIdArr)));
		}
		//需要删除的值ID
		$res=$this->getFieldUniVal('bc_product_param_float','ppf_pav_id',sprintf(' and ppf_pav_id>0 and ppf_pro_id=%d',$proId));
		$oldValIdArr = $res['data'];
		$delValIdArr = array_diff($oldValIdArr, $newValArr[1]);
		if(count($delValIdArr))
		{
			$this->del('bc_product_param_float', sprintf(" and ppf_pro_id=%d and ppf_pav_id in (%s)", $proId, implode(',', $delValIdArr)));
		}
		foreach($newParamArr[1] as $palId=>$v)
		{
			if(is_array($v))
			{
				foreach ($v as $value) 
				{
					$val=isset($valArr[$value])?$valArr[$value]['pav_value']:'';
					if(in_array($value, $oldValIdArr))
					{
						if($oldValArr[$value] !=$val)
						{	
							$logArr[] =$labelName[$value].":\"{$oldValArr[$value]}\" 变更为 \"{$val}\"";
						}
						$this->set('bc_product_param_float', ['ppf_pav_id'=>$value,'ppf_value'=>$val], sprintf(" and ppf_pro_id=%d and ppf_pav_id=%d", $proId, $value));
					}
					else
					{
						$logArr[] =$labelName[$palId].":\"\" 变更为 \"{$val}\" ";
						$this->add('bc_product_param_float', ['ppf_pro_id'=>$proId, 'ppf_pal_id'=>$palId, 'ppf_pav_id'=>$value,'ppf_value'=>$val]);
					}
				}
			}
			else
			{
				if(in_array($palId, $oldPalIdArr))
				{
					if($oldValArr[$palId] !=$v)
					{	
						$logArr[] =$labelName[$palId].": \"{$oldValArr[$palId]}\" 变更为 \"{$v}\"";
					}
					$this->set('bc_product_param_float', ['ppf_value'=>$v], sprintf(" and ppf_pro_id=%d and ppf_pal_id=%d", $proId, $palId));
				}
				else
				{
					$logArr[] =$labelName[$palId].": \"\" 变更为 \"{$v}\"";
					$this->add('bc_product_param_float', ['ppf_pro_id'=>$proId, 'ppf_pal_id'=>$palId, 'ppf_value'=>$v]);
				}
			}
		}
		if($this->operation==''&& $logArr)
		{
			$B2cLog = new B2cLog();
			$logItem = [
				'sli_pro_id'=>$proId,
				'sli_etime'=>time(),
				'sli_act'=>'para',
				'sli_txt'=>implode("\r\n",$logArr)
			];
			$B2cLog->addFastLogItem($logItem);
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}




	/**
	  * @method 修改配件的图片
	  * @param  $shopId int  店铺ID
	  * @param  $proId  int  产品ID
	  * @param  $spiIdArr  array  图片ID数组
	  * @param  $type  string  图片更新模式，'' 默认替换模式,addtop 增加到最前,addlast 增加到最后
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	public function setProductPic($shopId, $proId, $spiIdArr,$type = '')
	{
		$shopId = (int) $shopId;
		$proId = (int) $proId;
		if($shopId < 1 || $proId < 1 || !is_array($spiIdArr))
		{
			return LibFc::ReturnData(false, 'setProductPic 提供的参数不正确');
		}
		$this->B2CDb->Begin();

		//图片
		if(!empty($spiIdArr))
		{
			foreach($spiIdArr as $k=>$v)
			{
				$spiIdArr[$k] = (int) $v;
			}
			$spiIdArr = array_unique($spiIdArr);

			//查找已有的
			$res = $this->getFieldUniVal('bc_product_pic', 'pp_spi_id', sprintf(" and pp_pro_id = %d order by pp_seq asc", $proId));
			$oldIdArr = $res['data'];
			
			if(count($oldIdArr) < 5 )
			{
				if ($type == 'addtop')
				{
					$spiIdArr = array_slice(array_merge($spiIdArr, $oldIdArr), -5, 5);
				} 
				elseif($type == 'addlast') 
				{
					$spiIdArr = array_slice(array_merge($oldIdArr, $spiIdArr), 0, 5);
				}
			}
			else
			{
				if(!empty($type))
				{
					$spiIdArr  = $oldIdArr;
				}
			}
			//删除
			$delIdArr = array_diff($oldIdArr, $spiIdArr);
			if(!empty($delIdArr))
			{
				$this->del('bc_product_pic', sprintf(" and pp_spi_id in (%s) and pp_pro_id=%d", implode(',', $delIdArr), $proId));
			}
			
			$seq = 0;
			foreach($spiIdArr as $spiId)
			{
				if($spiId < 1) continue;
				$isMain = $seq === 0? 1: 0;
				$setArr = ['pp_ismain'=>$isMain, 'pp_seq'=>$seq];
				if(in_array($spiId, $oldIdArr))
				{
					$this->set('bc_product_pic', $setArr, sprintf(" and pp_spi_id=%d and pp_pro_id=%d", $spiId, $proId));
				}
				else
				{
					$setArr['pp_spi_id'] = $spiId;
					$setArr['pp_pro_id'] = $proId;
					$this->add('bc_product_pic', $setArr);
				}
				$seq++;
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}



	/**
	  * @method 修改配件的号码
	  * @param  $proId  int  产品ID
	  * @param  $numArr  array  [11=>['num_factory'=>'', 'num_display'=>''....]....]
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	private function setProductNum($proId, $numArr)
	{
		$proId = (int) $proId;
		if($proId < 1 || !is_array($numArr)) return LibFc::ReturnData(false, 'setProductNum 提供的参数不正确');

		//检测数据
		$newNumArr = [];
		$hideNewArr = [];
		foreach($numArr as $k=>$v)
		{
			if(trim($v['num_factory']) == '' || trim($v['num_display']) == '')
			{
				unset($numArr[$k]);
				continue;
			}
				
			$v['num_factory'] = $v['num_factory'] =='oe'? 'OE': $v['num_factory'];
			unset($v['num_id']);
			$v['num_display'] = strtoupper(trim($v['num_display']));
			$v['num_format'] = LibFc::FormatNum($v['num_display']);
			$v['num_reformat'] = strrev($v['num_format']);
			if(isset($v['num_fromid'])) $v['num_fromid'] = (int) $v['num_fromid'];
			$uniStr = strtoupper(LibFc::formatStr($v['num_factory'], 1).'@'.$v['num_format']);
			if(isset($v['num_show']) && empty($v['num_show']))
			{
				$hideNewArr[$uniStr] = $v;
			}
			else
			{
				$newNumArr[$uniStr] = $v;
			}
		}
		
		//优先自有的
		foreach($hideNewArr as $k=>$v)
		{
			if(empty($newNumArr[$k])) $newNumArr[$k] = $v;
		}
		unset($hideNewArr);

		//已有非自编号号码
		$res = $this->get('bc_number', ['*'], sprintf(" and num_self=0 and num_pro_id=%d", $proId));
		$hasNumArr = [];
		foreach($res['data'] as $v)
		{
			$uniStr = strtoupper(LibFc::formatStr($v['num_factory'], 1).'@'.$v['num_format']);
			$v['uniStr'] = $uniStr;
			$hasNumArr[$uniStr] = $v;
		}

		$this->B2CDb->Begin();

		//开始比较
		$delIdArr = [];
		$delNumArr = $addNumArr = $editNumArr = [];
		$hasNumTempArr = array_column($hasNumArr,null,'num_id');
		//num_key仅用于比对数据操作
		$numKeyArr = array_column($newNumArr,'num_key');
		foreach($hasNumArr as $uniStr=>$v)
		{	
			if ($v['num_show'] == 1  && !in_array($v['num_id'],$numKeyArr)) {
				$delNumArr[] = $v['uniStr'];
			}
			if(($v['num_show'] == 1 || $v['num_from'] == 'ypc') && empty($newNumArr[$uniStr]))
			{
				$delIdArr[] = $v['num_id'];
				if($v['num_from'] == 'ypc') $delNumArr[] = $v['uniStr'];
			}
		}
		if(!empty($delIdArr))
		{
			$this->del('bc_number', sprintf(" and num_pro_id=%d and num_id in (%s)", $proId, implode(',', $delIdArr)));
		}
		
		foreach($newNumArr as $uniStr=>$v)
		{
			if ($v['num_key'] > 0 && $hasNumTempArr[$v['num_key']] && $hasNumTempArr[$v['num_key']]['uniStr']!=$uniStr) {
				$editNumArr[] = "号码 {$hasNumTempArr[$v['num_key']]['uniStr']} 变更为 {$uniStr}";
			}  elseif ($v['num_key'] < 0) {
				$addNumArr[] = $uniStr;
			}
			unset($v['num_key']);
			if(!empty($hasNumArr[$uniStr]['num_id']) && $hasNumArr[$uniStr]['num_id'] > 0)
			{
				$this->set('bc_number', $v, sprintf(" and num_pro_id=%d and num_id=%d", $proId, $hasNumArr[$uniStr]['num_id']));
			}
			else
			{
				$v['num_pro_id'] = $proId;
				$res = $this->add('bc_number', $v);
				$v['num_id'] = $res['data'];
			}
		}
		if($this->operation =='')
		{
			$returnArr  =[];
			if($delNumArr){
				$returnArr[] = '删除号码:'.implode(',',$delNumArr);	
			}
			if($addNumArr){
				$returnArr[] = '新增号码:'.implode(',',$addNumArr);
			}
			if($editNumArr){
				$returnArr[] = implode(',',$editNumArr);
			}
			if($returnArr)
			{
				$B2cLog = new B2cLog();
				$logItem = [
					'sli_pro_id'=>$proId,
					'sli_act'=>'num',
					'sli_txt'=>implode("\r\n",$returnArr)
				];
				$B2cLog->addFastLogItem($logItem);	
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}


	
	/**
	  * @method 将配件的商家编号加入到号码表
	  * @param  $proId  int  产品ID
	  * @param  $dataArr  array  ['factory'=>'', 'display'=>'']
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	private function setProductSelfNum($proId, $dataArr)
	{
		$proId = (int) $proId;
		if($proId < 1 || !is_array($dataArr))
		{
			return LibFc::ReturnData(false, 'setProductSelfNum 提供的参数不正确');
		}
	
		if(!empty($dataArr['display']))
		{
			$setArr = [
				'num_pro_id'=>$proId,
				'num_factory'=>$dataArr['factory'],
				'num_display'=>$dataArr['display'],
				'num_format'=>LibFc::FormatNum($dataArr['display']),
				'num_self'=>1
			];
			$setArr['num_reformat'] = strrev($setArr['num_format']);
		}
		$this->B2CDb->Begin();
		$res = $this->get('bc_number', ['num_id'], sprintf(" and num_pro_id=%d and num_self=1", $proId), true);
		$numId = (int) $res['data']['num_id'];
		if(!empty($setArr))
		{
			//如果数据库中存在一样的编码
			$has = $this->get('bc_number',['num_id'],sprintf(" and num_pro_id=%d and num_factory='%s' and num_format='%s'", $proId,$setArr['num_factory'],$setArr['num_format']),true);
			if($has['data']['num_id'])
			{	
				$numId = $has['data']['num_id'];
				$this->del('bc_number', sprintf(" and num_pro_id=%d and num_id!=%d and num_self=1",$proId, $numId));
			}

			if($numId > 0)
			{
				$this->set('bc_number', $setArr, sprintf(" and num_id=%d", $numId));
			}
			else
			{
				$res = $this->add('bc_number', $setArr);
				$setArr['num_id'] = $res['data'];
			}
		}
		else
		{
			$this->del('bc_number', sprintf(" and num_id =%d", $numId));
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}


	/**
	  * @method 删除配件隐藏的号码
	  * @param  $proId  int  产品ID
	  * @author soul
	  * @copyright 2019/9/29
	  * @return 
	  */
	public function delProductHideYpNum($shopId, $proId)
	{
		//防止误删别的店铺数据
		$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id =%d and pro_shop_id=%d", $proId, $shopId));
		if(!empty($res['data']))
		{
			$this->del('bc_number', sprintf(" and num_show=0 and num_from='yp' and num_pro_id =%d", $proId));
		}
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 通过末级的使用车型ID更新配件的使用品牌、一级、二级、三级车型ID关联
	  * @param  $proId  int  产品ID
	  * @param  $mod3Arr  array  
								方式一：[1,100,200, ...]
								方式二：[['pml3_mod3_id'=>1, 'pml3_remark'=>'']]

	  * @param  $from  string 选填   数据来源 ZHIPEI:智配 NUMBER：号码匹配
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	public function setProductModel($proId, $mod3Arr, $from = '')
	{
		$proId = (int) $proId;
	
		if($proId < 1 || !is_array($mod3Arr))
			return LibFc::ReturnData(false, 'setProductModel 提供的参数不正确');
	
		$res = $this->get('bc_product_model3_link', ['pml3_mod3_id, pml3_remark'], sprintf(" and pml3_pro_id=%d", $proId));
		$oldMod3Arr = array_column($res['data'], null, 'pml3_mod3_id');

		$newMod3Arr = [];
		foreach($mod3Arr as $k=>$v)
		{
			if(is_array($v) && !empty($v['pml3_mod3_id']))
			{
				$newMod3Arr[$v['pml3_mod3_id']] = $v;
			}
			else if(!is_array($v))
			{
				$v = (int) $v;
				$newMod3Arr[$v] = ['pml3_mod3_id'=>$v];
				//沿用旧的信息
				if(!empty($oldMod3Arr[$v])) $newMod3Arr[$v] = $oldMod3Arr[$v];
			}
		}

		$newArr = ['brand'=>[], 'mod1'=>[], 'mod2'=>[]];
		$oldArr = ['brand'=>[], 'mod1'=>[], 'mod2'=>[]];

		if(!empty($newMod3Arr))
		{
			$ComModel = new ComModel();
			$res = $ComModel->get('bc_model3', ['mod3_brand_id as brand_id', 'mod3_mod1_id as mod1_id', 'mod3_mod2_id as mod2_id', 'mod3_id'], sprintf(" and mod3_id in (%s)", implode(',', array_keys($newMod3Arr))));
			$newArr['brand'] = array_unique(array_column($res['data'], 'brand_id'));
			$newArr['mod1'] = array_unique(array_column($res['data'], 'mod1_id'));
			$newArr['mod2'] = array_unique(array_column($res['data'], 'mod2_id'));
			$tmod3Arr = array_unique(array_column($res['data'], 'mod3_id'));
			foreach($newMod3Arr as $k=>$v)
			{
				if(!in_array($k, $tmod3Arr))
					unset($newMod3Arr[$k]);
			}
		}

		$res = $this->get('bc_product_brand_link', ['pbl_brand_id'], sprintf(" and pbl_pro_id=%d", $proId));
		$oldArr['brand'] = array_column($res['data'], 'pbl_brand_id');

		$res = $this->get('bc_product_model1_link', ['pml1_mod1_id'], sprintf(" and pml1_pro_id=%d", $proId));
		$oldArr['mod1'] = array_column($res['data'], 'pml1_mod1_id');

		$res = $this->get('bc_product_model2_link', ['pml2_mod2_id'], sprintf(" and pml2_pro_id=%d", $proId));
		$oldArr['mod2'] = array_column($res['data'], 'pml2_mod2_id');

		$this->B2CDb->Begin();

		foreach($newArr as $type=>$idArr)
		{
			$delIdArr = array_diff($oldArr[$type], $idArr);
			$addIdArr = array_diff($idArr, $oldArr[$type]);
			switch($type)
			{
				case 'brand': 
					if(!empty($delIdArr))
						$this->del('bc_product_brand_link', sprintf(" and pbl_pro_id=%d and pbl_brand_id in (%s)", $proId, implode(',', $delIdArr)));
					if(!empty($addIdArr))
					{
						$addArr = [];
						foreach($addIdArr as $addId)
						{
							$addArr[] = ['pbl_pro_id'=>$proId, 'pbl_brand_id'=>$addId];
						}
						$this->addAny('bc_product_brand_link', array_keys($addArr[0]), $addArr);
					}
				break;
				case 'mod1': 
					if(!empty($delIdArr))
						$this->del('bc_product_model1_link', sprintf(" and pml1_pro_id=%d and pml1_mod1_id in (%s)", $proId, implode(',', $delIdArr)));
					if(!empty($addIdArr))
					{
						$addArr = [];
						foreach($addIdArr as $addId)
						{
							$addArr[] = ['pml1_pro_id'=>$proId, 'pml1_mod1_id'=>$addId];
						}
						$this->addAny('bc_product_model1_link', array_keys($addArr[0]), $addArr);
						//车型选择是self时，保存到sh_shop_model1
						$table = 'sh_shop 
						join bc_product on pro_shop_id=shop_id';
						$where = sprintf(" and pro_id=%d",$proId);
						$res = $this->get($table,['shop_mod_from,shop_id'],$where,true);
						if(!empty($res['data']['shop_mod_from']) && $res['data']['shop_mod_from'] == 'self'){
							$shopId = $res['data']['shop_id'];
							$result = $this->get('sh_shop_model1', ['ssm_mod1_id'], sprintf(" and ssm_mod1_id in (%s)", implode(',',$addIdArr)));
							$oldMod1Arr = array_column($result['data'],'ssm_mod1_id');
							$newMod1IdArr = array_diff($addIdArr,$oldMod1Arr);
							if($newMod1IdArr)
							{
								foreach ($newMod1IdArr as $mod1Id) {
									$shopMod1Arr[] = ['ssm_shop_id'=>$shopId, 'ssm_mod1_id'=>$mod1Id];
								}
								$this->addAny('sh_shop_model1',array_keys($shopMod1Arr[0]),$shopMod1Arr);
							}
						}
					}
				break;
				case 'mod2': 
					if(!empty($delIdArr))
						$this->del('bc_product_model2_link', sprintf(" and pml2_pro_id=%d and pml2_mod2_id in (%s)", $proId, implode(',', $delIdArr)));
					if(!empty($addIdArr))
					{
						$addArr = [];
						foreach($addIdArr as $addId)
						{
							$addArr[] = ['pml2_pro_id'=>$proId, 'pml2_mod2_id'=>$addId];
						}
						$this->addAny('bc_product_model2_link', array_keys($addArr[0]), $addArr);
					}
				break;
			}
		}
		//末级车型

		$delIdArr = array_diff(array_keys($oldMod3Arr), array_keys($newMod3Arr));
		if(!empty($delIdArr))
		{
			$this->del('bc_product_model3_link', sprintf(" and pml3_pro_id=%d and pml3_mod3_id in (%s)", $proId, implode(',', $delIdArr)));
			//忽略
			$this->set('bc_product_model_auto',['pma_status'=>-1,'pma_etime'=>time()],sprintf(" and pma_pro_id=%d and pma_mod3_id in (%s)", $proId, implode(',', $delIdArr)));
		}
			
		
		$addArr = [];
		foreach($newMod3Arr as $m3id=>$mv)
		{
			if(!empty($oldMod3Arr[$m3id]))
			{
				if($mv['pml3_remark'] != $oldMod3Arr[$m3id]['pml3_remark'])
				{
					$set = [
						'pml3_remark'=>isset($mv['pml3_remark'])? $mv['pml3_remark'] : ''
					];
					$this->set('bc_product_model3_link', $set, sprintf(" and pml3_pro_id=%d and pml3_mod3_id=%d", $proId, $m3id));
				}
			}
			else
			{
				//批量加速度快，统一字段顺序
				$addArr[] = [
					'pml3_pro_id'=>$proId,
					'pml3_mod3_id'=>$m3id,
					'pml3_remark'=>isset($mv['pml3_remark'])? $mv['pml3_remark']: '',
					'pml3_from'=>$from,
					'pml3_time'=>time()
				];
			}
		}
		if(!empty($addArr))
		{
			$this->addAny('bc_product_model3_link', array_keys($addArr[0]), $addArr);
			//已添加
			$this->set('bc_product_model_auto',['pma_status'=>1,'pma_etime'=>time()],sprintf(" and pma_pro_id=%d and pma_mod3_id in (%s)", $proId, implode(',',array_column($addArr,'pml3_mod3_id'))));
		}

		
		//置空底盘件、发动机模式
		if($from == 'all')
		{
			$this->set('bc_product', ['pro_smt_code'=>'all'], sprintf(" and pro_id=%d", $proId));
			$this->del('bc_product_modengine', sprintf(" and pme_pro_id=%d", $proId));
			$this->del('bc_product_modchassis', sprintf(" and pmc_pro_id=%d", $proId));
		}
		//编辑才记录
		if($this->operation =='')
		{
			$ComModel = new ComModel();
			$returnArr = [];
			if($delIdArr){
				$delDesArr = [];
				$data = $ComModel->getAllModByAny(['mod3_id'=>implode(',',$delIdArr)]);
				foreach ($data['data'] as  $item) {
					$delDesArr[] = $item['make_name'].$item['mod2_name'].$item['mod3_name'].$item['mod3_year'];
				}
				$returnArr[] = "删除车型:\r\n".implode("\r\n",$delDesArr);
			}
			if($addArr){
				$addDesArr = [];
				$addIdArr = array_column($addArr,'pml3_mod3_id');
				$data = $ComModel->getAllModByAny(['mod3_id'=>implode(',',$addIdArr)]);
				foreach ($data['data'] as  $item) {
					$addDesArr[] = $item['make_name'].$item['mod2_name'].$item['mod3_name'].$item['mod3_year'];
				}
				$returnArr[] = "新增车型:\r\n".implode("\r\n",$addDesArr);
			}
			if($returnArr){
				$B2cLog  = new B2cLog();
				$logItem = [
					'sli_pro_id'=>$proId,
					'sli_act'=>'model',
					'sli_txt'=>implode("\r\n",$returnArr)
				];
				$B2cLog->addFastLogItem($logItem);
			}
		}
		
		//初始化车型参数
		if(!in_array($from, ['chassis', 'engine']))
			$this->resetProductModel($proId);

		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}

	/**
	  * @method 更新产品的底盘件模式车型
	  * @param  $proId  int  产品ID
	  * @param  $modArr array [
			["pmc_mch_code"=>"002fa45a9abfe98b0a2683b073460013", "pmc_remark"]=>"19年后"],
			["pmc_mch_code"=>"002fa45a9abfe98b0a2683b073460013", "pmc_remark"]=>"备注信息"],
			....
		]
	  * @author soul
	  * @copyright 2021/7/9
	  * @return 
	  */
	public function setProductModChassis($proId, $modArr)
	{
		$proId = (int) $proId;
		$modArr = array_column($modArr, null, 'pmc_mch_code');

		$res = $this->get('bc_product_modchassis', ['pmc_mch_code', 'pmc_remark'], sprintf(" and pmc_pro_id=%d", $proId));
		$hasArr = array_column($res['data'], null, 'pmc_mch_code');
		
		$this->B2CDb->Begin();
		$addArr = [];
		foreach($modArr as $code=>$mod)
		{
			$code = trim($code);
			if(!preg_match('/^[0-9a-z]{32}$/i', $code, $match))
			{
				unset($modArr[$code]);
				continue;
			}

			$mod['pmc_remark'] = isset($mod['pmc_remark'])? $mod['pmc_remark']: '';
			if(!empty($hasArr[$code]))
			{
				$this->set('bc_product_modchassis',['pmc_remark'=>$mod['pmc_remark']], sprintf(" and pmc_pro_id=%d and pmc_mch_code='%s'", $proId, $code));
			}
			else
			{
				$addArr[] = [
					'pmc_pro_id'=>$proId,
					'pmc_mch_code'=>$code,
					'pmc_remark'=>$mod['pmc_remark']
				];
			}
		}

		if(!empty($addArr)) $this->addAny('bc_product_modchassis', array_keys($addArr[0]), $addArr);
		$delArr = array_diff(array_keys($hasArr), array_keys($modArr));
		if(!empty($delArr))
			$this->del('bc_product_modchassis', sprintf(" and pmc_pro_id=%d and pmc_mch_code in ('%s')", $proId, implode("','", $delArr)));
		
		//查找相应的车型
		$mod3Arr = [];
		if(!empty($modArr))
		{
			$ComModel = new ComModel();
			$res = $ComModel->get('bc_modchassis_mod3', ['mcm_mch_code, mcm_mod3_id'], sprintf(" and mcm_mch_code in ('%s')", implode("','", array_keys($modArr))));
			$codToM3Arr = [];
			foreach($res['data'] as $v)
			{
				$codToM3Arr[$v['mcm_mch_code']][] = $v['mcm_mod3_id'];
			}
			
			foreach($modArr as $code=>$mod)
			{
				if(empty($codToM3Arr[$code])) continue;
				foreach($codToM3Arr[$code] as $m3id)
				{
					$mod3Arr[] = [
						'pml3_mod3_id'=>$m3id,	
						'pml3_remark'=>$mod['pmc_remark']
					];
				}
			}
		}
		$this->setProductModel($proId, $mod3Arr, 'chassis');
		
		//置空发动机模式
		$this->del('bc_product_modengine', sprintf(" and pme_pro_id=%d", $proId));
		$this->set('bc_product', ['pro_smt_code'=>'chassis'], sprintf(" and pro_id=%d", $proId));
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}
	
	/**
	  * @method 通过产品已有底盘件模式车型更新末级车型
	  * @param  $proId  int  产品ID
	  * @author soul
	  * @copyright 2021/7/9
	  * @return 
	  */
	public function setProductMod3ByChassis($proId)
	{
		//取此模式下的适用末级车型数据
		$ComModel = new ComModel();
		$table = sprintf("%s.bc_product_modchassis JOIN bc_modchassis ON mch_code = pmc_mch_code JOIN bc_modchassis_mod3 ON mcm_mch_code = mch_code", $this->B2CDb->configs['db_name']);
		$res = $ComModel->get($table, ['mcm_mod3_id as pml3_mod3_id, pmc_remark as pml3_remark'], sprintf(" and pmc_pro_id = %d", $proId));
		$mod3Arr = $res['data'];
		$this->B2CDb->Begin();
		$this->setProductModel($proId, $mod3Arr, 'chassis');
		$this->set('bc_product_modchassis', ['pmc_auto_time'=>time()], sprintf(" and pmc_pro_id=%d", $proId));
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}


	/**
	  * @method 更新产品的发动机件模式车型
	  * @param  $proId  int  产品ID
	  * @param  $modArr array [
			["pme_men_code"=>"002fa45a9abfe98b0a2683b073460013", "pme_remark"]=>"19年后"],
			["pme_men_code"=>"002fa45a9abfe98b0a2683b073460013", "pme_remark"]=>"备注信息"],
			....
		]
	  * @author soul
	  * @copyright 2021/7/9
	  * @return 
	  */
	public function setProductModEngine($proId, $modArr)
	{
		$proId = (int) $proId;
		$modArr = array_column($modArr, null, 'pme_men_code');

		$res = $this->get('bc_product_modengine', ['pme_men_code', 'pme_remark'], sprintf(" and pme_pro_id=%d", $proId));
		$hasArr = array_column($res['data'], null, 'pme_men_code');
		
		$this->B2CDb->Begin();
		$addArr = [];
		foreach($modArr as $code=>$mod)
		{
			$code = trim($code);
			if(!preg_match('/^[0-9a-z]{32}$/i', $code, $match))
			{
				unset($modArr[$code]);
				continue;
			}

			$mod['pme_remark'] = isset($mod['pme_remark'])? $mod['pme_remark']: '';
			if(!empty($hasArr[$code]))
			{
				$this->set('bc_product_modengine',['pme_remark'=>$mod['pme_remark']], sprintf(" and pme_pro_id=%d and pme_men_code='%s'", $proId, $code));
			}
			else
			{
				$addArr[] = [
					'pme_pro_id'=>$proId,
					'pme_men_code'=>$code,
					'pme_remark'=>$mod['pme_remark']
				];
			}
		}

		if(!empty($addArr)) $this->addAny('bc_product_modengine', array_keys($addArr[0]), $addArr);
		$delArr = array_diff(array_keys($hasArr), array_keys($modArr));
		if(!empty($delArr))
			$this->del('bc_product_modengine', sprintf(" and pme_pro_id=%d and pme_men_code in ('%s')", $proId, implode("','", $delArr)));
		
		//查找相应的车型
		$mod3Arr = [];
		if(!empty($modArr))
		{
			$ComModel = new ComModel();
			$res = $ComModel->get('bc_modengine_mod3', ['mem_men_code, mem_mod3_id'], sprintf(" and mem_men_code in ('%s')", implode("','", array_keys($modArr))));
			$codToM3Arr = [];
			foreach($res['data'] as $v)
			{
				$codToM3Arr[$v['mem_men_code']][] = $v['mem_mod3_id'];
			}
			
			foreach($modArr as $code=>$mod)
			{
				if(empty($codToM3Arr[$code])) continue;
				foreach($codToM3Arr[$code] as $m3id)
				{
					$mod3Arr[] = [
						'pml3_mod3_id'=>$m3id,	
						'pml3_remark'=>$mod['pme_remark']
					];
				}
			}
		}
		$this->setProductModel($proId, $mod3Arr, 'engine');
		//置空底盘模式
		$this->del('bc_product_modchassis', sprintf(" and pmc_pro_id=%d", $proId));
		$this->set('bc_product', ['pro_smt_code'=>'engine'], sprintf(" and pro_id=%d", $proId));
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}
	
	/**
	  * @method 通过产品已有发动机件模式车型更新末级车型
	  * @param  $proId  int  产品ID
	  * @author soul
	  * @copyright 2021/7/9
	  * @return 
	  */
	public function setProductMod3ByEngine($proId)
	{
		//取此模式下的适用末级车型数据
		$ComModel = new ComModel();
		$table = sprintf("%s.bc_product_modengine JOIN bc_modengine ON men_code = pme_men_code JOIN bc_modengine_mod3 ON mem_men_code = men_code", $this->B2CDb->configs['db_name']);
		$res = $ComModel->get($table, ['mem_mod3_id as pml3_mod3_id, pme_remark as pml3_remark'], sprintf(" and pme_pro_id = %d", $proId));
		$mod3Arr = $res['data'];
		$this->B2CDb->Begin();
		$this->setProductModel($proId, $mod3Arr, 'engine');
		$this->set('bc_product_modengine', ['pme_auto_time'=>time()], sprintf(" and pme_pro_id=%d", $proId));
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}

	

	/**
	  * @method 重新初始化底盘件、发动机件模式车型的末级车型
	  * @param  $shopId  int [选填] 店铺ID 如果不填，刷整个产品库
	  * @author soul
	  * @copyright 2021/7/13
	  * @return 
	  */
	public function initModelByOthModType($shopId = 0)
	{
		$this->operation = 'system';
		$modTypeArr = ['chassis', 'engine'];
		$where = sprintf(" and pro_smt_code in ('%s') and (pro_shop_id in (select aps_shop_id from sh_shop_app where aps_etime > %d) or pro_shop_id in (select ssu_shop_id from sh_super where ssu_shop_id > 0 and ssu_etime > %d))", implode("','", $modTypeArr), time(), time());
		if(!empty($shopId)) $where = sprintf(" and pro_shop_id=%d", $shopId);
		$shopres = $this->get('bc_product', ['pro_shop_id'], $where.' group by pro_shop_id');
		foreach($shopres['data'] as $sv)
		{
			$this->B2CDb->Begin();
			$pres = $this->get('bc_product', ['pro_id, pro_smt_code'], sprintf(" and pro_shop_id=%d and pro_smt_code in ('%s')", $sv['pro_shop_id'], implode("','", $modTypeArr)));
			foreach($pres['data'] as $pv)
			{
				switch($pv['pro_smt_code'])
				{
					case 'chassis':
						$this->setProductMod3ByChassis($pv['pro_id']);
					break;
					case 'engine':
						$this->setProductMod3ByEngine($pv['pro_id']);
					break;
				}
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true);
	}


	
	/**
	  * @method 从备份车型恢复车型
	  * @param  $shopId  int  店铺ID
	  * @param  $version  string  版本号
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  */
	function shopModelFromBackup($shopId, $version)
	{
		if($shopId > 0 && !empty($version))
		{
			$this->B2CDb->Begin();
			$zres = $this->get('bc_product', ['pro_id'], sprintf(" and pro_shop_id =%d", $shopId));
			foreach($zres['data'] as $v)
			{
				$this->del('bc_product_model3_link', sprintf(" and pml3_pro_id=%d", $v['pro_id']));
				$res = $this->get('bc_product_model3_link_ver', ['*'], sprintf(" and pml3b_pro_id =%d and pml3b_shop_id=%d and pml3b_version='%s'", $v['pro_id'], $shopId, LibFc::Escape($version)));
				$m3IdArr = array_column($res['data'], 'pml3b_mod3_id');
				$addArr = [];
				foreach($res['data'] as $mv)
				{
					$addArr[] = [
						'pml3_pro_id'=>$mv['pml3b_pro_id'],	
						'pml3_mod3_id'=>$mv['pml3b_mod3_id'],	
						'pml3_remark'=>$mv['pml3b_pml3_remark'],	
						'pml3_from'=>$mv['pml3b_pml3_from'],	
						'pml3_time'=>$mv['pml3b_pml3_time']
					];
				}
				if(!empty($addArr)) $this->addAny('bc_product_model3_link', array_keys($addArr[0]), $addArr);
				//重置其他关联表
				$this->setProductModel($v['pro_id'], $m3IdArr);
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 初始化产品的车型参数
	  * @param  $proId  int  产品ID
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  */
	public function resetProductModel($proId)
	{
		$proId = (int) $proId;

		//零件ID
		$res = $this->get('bc_product', ['pro_part_id', 'pro_pas_id'], sprintf(" and pro_id=%s", $proId), true);
		if(empty($res['data'])) return LibFc::ReturnData(true, true);
		$spartId = $res['data']['pro_part_id'].'_'.$res['data']['pro_pas_id'];


		$this->B2CDb->Begin();
		$this->del('bc_product_model3_para', sprintf(" and pmp_pro_id=%d", $proId));

		$res = $this->get('bc_product_model3_link', ['pml3_mod3_id'], sprintf(" and pml3_pro_id=%s", $proId));
		if(!empty($res['data']))
		{
			$mod3IdArr = array_column($res['data'], 'pml3_mod3_id');
			$numToNumId = [];
			$res = $this->get('bc_number', ['num_id', 'num_factory', 'num_display', 'num_format'], sprintf(" and num_pro_id=%s", $proId));
			if(!empty($res['data']))
			{
				$numsArr = [];
				foreach($res['data'] as $v)
				{
					$numsArr[] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display']];
				}
				
				$LibYpApi = new LibYpApi();
				$res = $LibYpApi->Get('ypc/getModelNumberPara', [], ['m3ids'=>$mod3IdArr, 'nums'=>$numsArr, 'spartId'=>$spartId]);
				foreach($res['data'] as $k=>$v)
				{
					$mod3Id = substr($k, 1);
					foreach($v as $vv)
					{	
						if(empty($vv['info'])) continue;
						$addArr = [
							'pmp_pro_id'=>$proId,
							'pmp_mod3_id'=>$mod3Id,
							'pmp_factory'=>$vv['factory'],
							'pmp_display'=>$vv['display'],
							'pmp_format'=>LibFc::FormatNum($vv['display']),
							'pmp_info'=>$vv['info'],
						];
						$this->add('bc_product_model3_para', $addArr);
					}
				}
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 更新配件的所属店铺分类
	  * @param  $proId  int  产品ID
	  * @param  $sortIdArr  array  [1,100,200, ...]
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
	  * 成功 ["status"=>true, "data"=>true ]
	  * 失败 ["status"=>false, "data"=>失败原因 ]
	  */
	private function setProductShopSort($proId, $sortIdArr)
	{
		$proId = (int) $proId;
	
		if($proId < 1 || !is_array($sortIdArr))
		{
			return LibFc::ReturnData(false, 'setProductShopSort 提供的参数不正确');
		}
		
		foreach($sortIdArr as $k=>$v)
		{
			$sortIdArr[$k] = (int) $v;
		}

		$res = $this->getFieldUniVal('bc_product_sort', 'prs_sort_id', sprintf(" and prs_pro_id=%d", $proId));
		$oldIdArr = $res['data'];

		$delIdArr = array_diff($oldIdArr, $sortIdArr);
		$addIdArr = array_filter(array_diff($sortIdArr, $oldIdArr));
	
		$this->B2CDb->Begin();

		if(!empty($delIdArr))
		{
			$this->del('bc_product_sort', sprintf(" and prs_pro_id=%d and prs_sort_id in (%s)", $proId, implode(',', $delIdArr)));
		}

		foreach($addIdArr as $addId)
		{
			$this->add('bc_product_sort', ['prs_pro_id'=>$proId, 'prs_sort_id'=>$addId]);
		}

		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}


	/**
	  * @method 删除产品
	  * @param  $shopId int  店铺ID
	  * @param  $proIdArr array  产品ID
	  * @author soul
	  * @copyright 2017/6/5
	  * @return [["status"]=> bool(true) ["data"]=> ["code"]=> int(0) ]
	  */
	public function delProduct($shopId, $proIdArr)
	{
		$shopId = (int) $shopId;
		foreach($proIdArr as $k=>$v)
		{
			$proIdArr[$k]  = (int) $v;
		}
		if($shopId < 1 || !is_array($proIdArr))
		{
			return LibFc::ReturnData(false, 'delProduct 提供的参数不正确');
		}
		//校验产品是否为改店铺的
		$res = $this->get('bc_product', ['pro_id','pro_part_id'], sprintf(" and pro_id in (%s) and pro_shop_id=%d", implode(',', $proIdArr), $shopId));
		if(empty($res['data']))
		{
			return LibFc::ReturnData(true, true);
		}
		$partIdArr = array_column($res['data'], 'pro_part_id');
		$delProIdArr = array_column($res['data'], 'pro_id');
		$B2cLog = new B2cLog();
		$this->B2CDb->Begin();
		$codeRes = $this->get('bc_product_info',['pri_code','pri_pro_id'],sprintf(" and pri_pro_id in (%s)",implode(',',$delProIdArr)));
		$this->del('bc_number', sprintf(" and num_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product', sprintf(" and pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_brand_link', sprintf(" and pbl_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_desc_history', sprintf(" and pdh_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_draft', sprintf(" and prda_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_group_link', sprintf(" and prgl_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_info', sprintf(" and pri_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_keyword', sprintf(" and prk_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_model1_link', sprintf(" and pml1_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_model2_link', sprintf(" and pml2_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_model3_link', sprintf(" and pml3_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_model3_para', sprintf(" and pmp_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_param_float', sprintf(" and ppf_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_param_string', sprintf(" and pps_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_pic', sprintf(" and pp_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_sort', sprintf(" and prs_pro_id in (%s)", implode(',', $delProIdArr)));
		$this->del('bc_product_model_auto',sprintf(" AND pma_pro_id IN (%s)",implode(',', $delProIdArr)));
		$codeArr = array_column($codeRes['data'],'pri_code','pri_pro_id');
		foreach ($delProIdArr as $proId) {
			$logItem = [
				'sli_pro_id'=>$proId,
				'sli_shop_id'=>$shopId,
				'sli_etime'=>time(),
				'sli_act'=>'del',
				'sli_txt'=>'删除配件：'.$codeArr[$proId]
			];
			$B2cLog->addFastLogItem($logItem);
		}
		$item = [
			'log_category'=>1,
			'log_shop_id'=>$shopId,
			'log_atime'=>time(),
			'log_dataid'=>$delProIdArr,
			'log_txt'=>'删除配件：'.implode(',',$codeArr)
		];
		$B2cLog->addFastLog($item);

		//删除 授权同步产品
		$res = $this->get('bc_product', ['pro_id','pro_shop_id'], sprintf(" and pro_dfrom='%s' and pro_dfrom_id in (%s)",'shop_'.$shopId, implode(',',$delProIdArr)));
		if($res['data']){
			$delArr = [];
			foreach ($res['data'] as $key => $val) {
				$delArr[$val['pro_shop_id']][] = $val['pro_id'];
			}
			if($delArr){
				foreach ($delArr as $kshop => $pval) {
					$this->delProduct($kshop,$pval);
				}
			}
		}
		$this->B2CDb->End();
		$LibYpApi = new LibYpApi();
		return $LibYpApi->Get('b2c/delItemWordByEs', [], ['pro_id'=>implode(',', $proIdArr)]);
		return LibFc::ReturnData(true, true);
	}

	public function getProductPara($pid, $partId)
	{
		$pid = (int) $pid;
		$partId = (int) $partId;
		$para = [];
		if($pid > 0 && $partId > 0)
		{
			$table = $where = sprintf("bc_part_param_link 
			join bc_param_label on ppl_pal_id=pal_id and ppl_part_id = %d
			left join bc_product_param_float on ppf_pal_id=pal_id and ppf_pro_id = %d
			left join bc_product_param_string on pps_pal_id=pal_id and pps_pro_id = %d
			left join bc_param_unit on ppl_pau_id = pau_id", $partId, $pid, $pid);
			$where = ' and (ppf_pro_id  is not null or pps_pro_id is not null) order by ppl_seq';
			$res = $this->get($table, ['pal_id', 'pal_name, ppl_style, pps_value, ppf_value, pau_name'], $where);
			foreach($res['data'] as $v)
			{
				$v['pau_name'] = empty($v['pau_name']) ? '': $v['pau_name'];
				$v['val'] = empty($v['pps_value']) ? $v['ppf_value']: $v['pps_value'];
				$para[$v['pal_id']] = ['name'=>$v['pal_name'], 'val'=>$v['val'], 'unit'=>$v['pau_name']];
			}
		}
		$para = array_values($para);
		//自定义参数
		$table = 'bc_product_para_val 
		JOIN bc_product ON prpv_pro_id = pro_id
		JOIN bc_product_label ON prl_id = prpv_prl_id
		LEFT JOIN `bc_product_para_tpl_link` ON  pro_ppt_id = pptl_ppt_id AND pptl_prl_id = prl_id
		LEFT JOIN bc_product_unit ON pru_id = prpv_pru_id';
		$res = $this->get($table, ['prl_name, prpv_value, pru_name'], sprintf(" and prpv_pro_id=%d and prpv_value != '' ORDER BY pptl_seq, prpv_seq, prl_name", $pid));
		foreach($res['data'] as $v)
		{
			$para[] = ['name'=>$v['prl_name'], 'val'=>$v['prpv_value'], 'unit'=>empty($v['pru_name']) ? '': $v['pru_name']];
		}
		return LibFc::ReturnData(true, array_values($para));
	}


	/**
	  * @method 获取配件参数
	  * @param  $proId 配件ID
	  * @author soul
	  * @copyright 2017/6/5
	  * @return ["status"=> true "data"=> [['pal_id'=>, 'pal_name'=>, 'pau_id'=>, 'pau_name'=>], .....]]
	  */
	public function getProductParam($proId)
	{
		$proId = (int) $proId;
		$resArr = [];
		if($proId > 0)
		{
			$res = $this->get('bc_product_param_float', ['ppf_pal_id, ppf_value'], sprintf(" and ppf_pro_id = %d", $proId));
			foreach($res['data'] as $v)
			{
				$resArr[$v['ppf_pal_id']][] = $v['ppf_value'];
			}
			$res = $this->get('bc_product_param_string', ['pps_pal_id, pps_value'], sprintf(" and pps_pro_id = %d", $proId));
			foreach($res['data'] as $v)
			{
				$resArr[$v['pps_pal_id']][] = $v['pps_value'];
			}
		}
		return LibFc::ReturnData(true, $resArr);
	}


	/**
	  * @method 获取配件的图片
	  * @param  $proIdArr int|array 支持多配件ID
	  * @param  $allPic   bool  默认false只取主图，true为所有
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 	  
			$proIdArr 为 int  ["status"=>true, "data"=>[[pp_pro_id=>100029, spi_id=>1, spi_path=>shop1/product/, spi_name=>4936e7662bab3151.jpg], ....] ]
			$proIdArr 为 array  ["status"=>true, "data"=>[ 100029=>[ [pp_pro_id=>100029, spi_id=>1, spi_path=>shop1/product/, spi_name=>4936e7662bab3151.jpg], ....], ....]]
	  */
	public function getProductPic($proIdArr, $allPic = false)
	{
		$returnArr = [];
		if(!empty($proIdArr))
		{
			$arrFlag = true;
			if(is_array($proIdArr))
			{
				foreach($proIdArr as $k=>$v)
				{
					$proIdArr[$k] = (int) $v;
				}
				$where = sprintf(" and pp_pro_id in (%s)", implode(',', $proIdArr));
			}
			else
			{
				$arrFlag = false;
				$where = sprintf(" and pp_pro_id =%d", (int) $proIdArr);
			}
			// $where .= $allPic ?'':' and pp_ismain=1';
			$where .= ' order by pp_pro_id,pp_ismain desc, pp_seq asc,pp_spi_id asc';
			$table = "bc_product_pic left join sh_pic on pp_spi_id = spi_id and spi_cate = 'product'";
			$res = $this->get($table, ['pp_pro_id', 'spi_id', 'spi_path', "concat(spi_name, '.', spi_ext) as spi_name"], $where);
			// print_r($res);
			foreach($res['data'] as $v)
			{
				if($arrFlag)
				{
					if(!$allPic&&!empty($returnArr[$v['pp_pro_id']]))
					{
						continue;
					}
					$returnArr[$v['pp_pro_id']][] = $v;
				}
				else
				{
					if(!$allPic&&!empty($returnArr))
					{
						continue;
					}
					$returnArr[] = $v;
				}
			}
		}
		return LibFc::ReturnData(true, $returnArr);
	}
	

	/**
	  * @method 配件的厂商自动完成
	  * @param  $shopId 店铺ID
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 
			成功 ["status"=>true, "data"=> 一维数组] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getAutoFactory($shopId = 0)
	{
		$shopId = (int) $shopId;
		$YpProduct = new YpProduct();
		$res = $YpProduct->getFactoryByCache();
		$resArr = $res['data'];
		$table = 'bc_number';
		if($shopId > 0)
		{
			$where .= sprintf(" and pro_shop_id=%d", $shopId);
			$table .= ' join bc_product on num_pro_id = pro_id';
		}
		$res = $this->get($table, ['distinct num_factory'], $where);
		foreach($res['data'] as $v)
		{
			if(!empty($v['num_factory'])) $resArr[] = $v['num_factory'];
		}
		$resArr = array_unique($resArr);
		sort($resArr);
		return LibFc::ReturnData(true, $resArr);
	}
	/**
	 * @method    根据条件获取产品列表
	 * @param     [int]         $nowPage [当前页码]
	 * @param     [int]         $perPage [每页条数]
	 * @param     [int]         $total   [总条数]
	 * @param     string         $order   [排序条件 'pro_shop_id,pro_part_id']
	 * @param     string         $where   [筛选条件]
	 * @return    [array]                  [[status] => 1,[data] => Array([0] => Array([pro_id] => 100031,[pro_status] => 1,[pro_part_id] => 143,[pro_name] => 宝马迷你前后刹车片,[pro_shop_id] => 1,[pro_sale_price] => 450,[pro_promotion_price] => ,[pro_count] => 1000,[pro_add_time] => 1499393527,[pro_set_time] => ,[pro_brand] => )]
	 * @author 卢
	 * @copyright 2017-07-25
	 */
	public function getProductList($nowPage,$perPage,$total,$order='pro_shop_id,pro_part_id',$where='',$join='')
	{
		if(LibFc::Int($nowPage)&&LibFc::Int($perPage))
		{
			$where .= sprintf(' order by %s limit %d,%d', $order, ($nowPage-1)*$perPage, $perPage);
			return $this->Get('bc_product '.$join, ['*'], $where);
		}
		return LibFc::ReturnData(false, '参数错误');
	}
	/**
	 * @method    获取店铺信息
	 * @param     [int|array]      $shopId   [店铺ID]
	 * @param     [array]      $fieldArr [字段数组]
	 * @return    [type]                [[status] => 1[data] => Array([0] => Array([shop_name] => 广州宜配网网上商城[shop_id] => 1))]
	 * @author 卢
	 * @copyright 2017-07-21
	 */
	public function getShopInfo($shopId,$fieldArr)
	{
		if(!empty($shopId)&&is_array($fieldArr))
		{
			$fieldArr=array_merge($fieldArr, ['shop_id']);
			if(is_array($shopId))
			{
				$where=sprintf('and shop_id in (%s)',implode(',', $shopId));
			}
			else
			{
				$where=sprintf('and shop_id = (%d)',$shopId);
			}
			$data=$this->Get('sh_shop',$fieldArr,$where);
			return $data;
		}
		return LibFc::ReturnData(false, '参数错误');
	}
	/**
	 * @method    根据路径获取分类
	 * @param     [string]     $path     [0,1,2]
	 * @param     [arr]     $fieldArr [['part_id','part_name']字段]
	 * @return    [array]               [array('status'=>true,'data'=>array('57'=>发动机,'58'=>气缸))]
	 * @author 卢
	 * @copyright 2017-07-21
	 */
	public function getCate($path,$fieldArr)
	{
		if($path!==''&& is_array($fieldArr))
		{
			
			$fieldArr= array_merge($fieldArr,['part_id']);
			$result=array();
			$where=sprintf(' and part_id in (%s)',$path);
			$pathData=$this->Get('bc_part',$fieldArr,$where);
			if(!empty($pathData['data']))
			{
				$partArr=array_column($pathData['data'], null,'part_id');
				$pathArr=explode(',',$path);
				foreach ($pathArr as $v) 
				{
					if($v==0)
						continue;
					$result[$v]=isset($partArr[$v])?$partArr[$v]['part_name']:'';
				}
			}
			return LibFc::ReturnData(true, $result);
		}
		return LibFc::ReturnData(false, '参数错误');
	}
	/**
	 * @method    处理配件
	 * @param     [int]      $shopId [店铺ID]
	 * @param     [str]      $where  [条件]
	 * @param     [str]      $type   [类型 del删除 recommend推荐 unrecommend取消推荐 out下架 sell 上架]
	 * @param     [int|arr]      $proId  [配件ID]
	 * @param     [arr]      $target [字段['pro_status'=>1]]
	 * @return    [arr]              ['status'=>true,'data'=>true]
	 * @author 卢
	 * @copyright 2017-09-11
	 */
	public function dealWithPro($shopId,$where,$type,$proId='',$target='')
	{
		if(LibFc::Int($shopId)&&!empty($where)&&!empty($type))
		{
			$B2cLog = new B2cLog();
			$proArr=is_array($proId)?$proId:[(int)$proId];
			//日志
			$logArr=['log_shop_id'=>$shopId,'log_category'=>1];
			$logArr['log_dataid']=$proArr;
			$this->B2CDb->Begin();

			$codeRes = $this->get('bc_product_info',['pri_code'],sprintf(" and pri_pro_id in (%s)",implode(',',$proArr)));
			$codeArr = $codeRes['data']?array_column($codeRes['data'],'pri_code'):[]; 
			switch ($type) 
			{
				case 'del':
					$this->delProduct($shopId,$proArr);
					$logArr['log_txt']='删除配件：'.implode(',',$codeArr);
					break;
				case 'recommend':
					$logArr['log_txt']='推荐配件：'.implode(',',$codeArr);
					break;
				case 'unrecommend':
					$logArr['log_txt']='取消推荐配件：'.implode(',',$codeArr);
					break;
				case 'out':
					$logArr['log_txt']='下架配件：'.implode(',',$codeArr);
					break;
				case 'sell':
					$logArr['log_txt']='上架配件：'.implode(',',$codeArr);			
					break;
			}
			if(!empty($target))
			{
				$this->set('bc_product',$target,$where);
			}
			$B2cLog->addFastLog($logArr);
			$this->B2CDb->End();
			return LibFc::ReturnData(true, true);
		}
		return LibFc::ReturnData(false, '参数错误');
	}
	/**
	 * @method    根据条件取收藏的配件ID 并按收藏量排序
	 * @param     [int]        $shopId [店铺ID]
	 * @param     string        $where  [条件]
	 * @param     string        $join   [连表查询]
	 * @return    [arr]                [['status'=>true],['data'=>[[100029] => 2,[100038] => 1]]]  配件ID为键，收藏数为值
	 * @author 卢
	 * @copyright 2017-09-13
	 */
	public function getHotKeepPro($where,$join='')
	{
		if(!empty($where))
		{
			$collOrderBy=' group by pro_id order by count desc';
			//根据收藏数排序的配件ID
			$table=sprintf('bc_product %s RIGHT join us_product_collection on prc_pro_id=pro_id',$join);
			$total=$this->get($table,['count(*) count','pro_id'],$where.$collOrderBy);
			foreach ($total['data'] as $k => $v) 
			{
				$data[$v['pro_id']]=$v['count'];
			}
			return LibFc::ReturnData(true, $data);
		}
		return LibFc::ReturnData(false, '参数错误');
	}


	/**
	 * @method    添加|修改配件套餐
	 * @param     array   $packArr array('开始时间','结束时间','店铺ID','套餐名称')
	 * @param     array   $proArr  array(id=>price,id2=>price2,...)
	 * @return    [['status'=>true],['data'=>true]]
	 * @author 	  xu
	 * @copyright 2017-10-17
	 */
	public function setProductPack($pack, $pro)
	{
		// 参数
		if(empty($pack) || !is_array($pack) || empty($pro) || !is_array($pro) || empty($pro=array_filter($pro,'LibFc::Int')))
			return LibFc::ReturnData(false, '参数错误');
		if(count($pro)<2) return LibFc::ReturnData(false, '一个套餐至少需要选择两件商品');
		if(empty($pack['name']))
			return LibFc::ReturnData(false, '套餐名称未填写！');
		if(empty($pack['price']) || empty(sprintf("%.2f",$pack['price'])))
			return LibFc::ReturnData(false, '套餐价格不正确！');
		if(empty($pack['frtId']) || !LibFc::Int($pack['frtId']))
			return LibFc::ReturnData(false, '运费模板未选！');
		if(empty($pack['manjian']) || !in_array($pack['manjian'],['Y','N']))
			return LibFc::ReturnData(false, '满减参数不正确！');
		if(empty($pack['shopId']) || !LibFc::Int($pack['shopId']))
			return LibFc::ReturnData(false, '店铺不存在！');
		if(empty($pack['bTime'])||empty($pack['eTime'])||!strtotime($pack['bTime'])||!strtotime($pack['eTime'])||(strtotime($pack['bTime'])>strtotime($pack['eTime']))) return LibFc::ReturnData(false, '套餐时间不正确！');
		if(!empty($pack['prpaId']) && !LibFc::Int($pack['prpaId']))
			return LibFc::ReturnData(false, '套餐ID不正确！');

		// 执行
		if(!empty($pack['prpaId']))
		{
			// 修改
			$this->B2CDb->Begin();
			$temp = [
				'prpa_price' => $pack['price'],
				'prpa_btime' => strtotime($pack['bTime']),
				'prpa_etime' => strtotime($pack['eTime']),
				'prpa_shop_id' => $pack['shopId'],
				'prpa_name' => $pack['name'],
				'prpa_frt_id' => $pack['frtId'],
				'prpa_manjian' => $pack['manjian']
			];
			$this->set('bc_product_pack',$temp,sprintf(' and prpa_id =%d ',$pack['prpaId']));
			// 关联表
			$this->del('bc_product_pack_link', sprintf(' and prpl_prpa_id=%d ',$pack['prpaId']));
			foreach ($pro as $k => $v)
			{
				$temp = array(
					'prpl_prpa_id' => $pack['prpaId'],
					'prpl_pro_id' => $v,
					'prpl_seq'=> $k+1
				);
				$this->add('bc_product_pack_link',$temp);
			}
			$this->B2CDb->End();
			return LibFc::ReturnData(true,true);
		}

		$this->B2CDb->Begin();
		$temp = [
			'prpa_price' => $pack['price'],
			'prpa_btime' => strtotime($pack['bTime']),
			'prpa_etime' => strtotime($pack['eTime']),
			'prpa_shop_id' => $pack['shopId'],
			'prpa_name' => $pack['name'],
			'prpa_frt_id' => $pack['frtId'],
			'prpa_manjian' => $pack['manjian']
		];
		$data = $this->add('bc_product_pack',$temp);
		$prpaId = $data['data'];
		foreach ($pro as $k => $v)
		{
			$temp = array(
				'prpl_prpa_id' => $prpaId,
				'prpl_pro_id' => $v,
				'prpl_seq'=> $k+1
			);
			$this->add('bc_product_pack_link',$temp);
		}
		//提交事务
		$this->B2CDb->End();
		return LibFc::ReturnData(true,$prpaId);
	}


	/**
	 * @method    查看配件套餐
	 * @param     int    $prpaId [套餐ID]
	 * @return    arr  [['status'=>true],['data'=>[arr] 
	 * @author xu
	 * @copyright 2017-10-17
	 */
	public function getProductPack($prpaId,$shopId)
	{
		// 参数
		if(!LibFc::Int($prpaId))
			return LibFc::ReturnData(false, '参数错误');

		// 查询
		$res = $this->get('bc_product_pack',['*'],sprintf(" and prpa_id=%d and prpa_shop_id=%d ",$prpaId,$shopId),true);
		$pack = $res['data'];
		if(empty($pack)) return LibFc::ReturnData(false, '套餐不存在！');

		// 商品
		$table = ' bc_product_pack_link left join bc_product on prpl_pro_id=pro_id ';
		$where = sprintf(" and prpl_prpa_id=%d and pro_shop_id=%d order by prpl_seq asc ",$prpaId,$shopId);
		$res = $this->get($table,['pro_name','pro_id','pro_sale_price','pro_count','prpl_seq'],$where);
		$pro = $res['data'];
		$proId = array_column($pro, 'pro_id');
		
		// 主图
		$B2cProduct = new B2cProduct();
		$res = $B2cProduct->getProductPic($proId);
		
		// 拼接
		foreach ($pro as $k => $v)
		{
			$pro[$k] = empty($res['data'][$v['pro_id']])?$pro[$k]:array_merge($pro[$k],current($res['data'][$v['pro_id']]));
		}
		$pack['prpa_pro'] = $pro;

		// 返回
		return LibFc::ReturnData(true, $pack);
	}

	/**
	 * @method    删除配件套餐
	 * @param     [array]    $prpaId ['套餐1的id','套餐2的id','套餐3的id'...]
	 * @return    [['status'=>true],['data'=>true]]
	 * @author xu
	 * @copyright 2017-10-17
	 */
	public function delProductPack($prpaId,$shopId)
	{
		// 参数
		if(!is_array($prpaId))
			$prpaId = [$prpaId];
		if(empty($prpaId = array_filter($prpaId,'LibFc::Int')) || !LibFc::Int($shopId))
			return LibFc::ReturnData(false, '参数错误');
		
		// 执行
		$this->B2CDb->Begin();
		$this->del('bc_product_pack', sprintf(" and prpa_id in (%s) and prpa_shop_id ", implode(',', $prpaId)),$shopId);
		$this->del('bc_product_pack_link', sprintf(" and prpl_prpa_id in (%s)", implode(',', $prpaId)));
		$this->B2CDb->End();

		// 返回
		return LibFc::ReturnData(true, true);
	}

	/**
	 * @method    配件属性add
	 * @param     [array]    $dataArr ['长','宽','高'...]
	 * @author    廖
	 * @copyright 2017-11-14
	 * @return    ['status'=>true,'data'=>['长'=>111, '宽'=>222]]
	 */
	function addProLabel($dataArr)
	{
		if(!empty($dataArr))
		{
			$dataArr = array_unique($dataArr);
			$nameArr = array();
			foreach($dataArr as $key => $value) 
			{
				if(LibFc::Escape($value) != '') $nameArr[$key] = LibFc::Escape($value);
			}
			if(!empty($nameArr))
			{
				//查询唯一配件属性
				$res = $this->get('bc_product_label',['prl_id','prl_name'],sprintf(" and prl_name in ('%s')",implode("','",$nameArr)));
				$prl_name = array_column($res['data'], 'prl_name');
				$proLabel = array_column($res['data'],'prl_id','prl_name');
				$diffArr = array_diff($nameArr, $prl_name);
				if(!empty($diffArr))
				{
					$this->B2CDb->Begin();
					foreach($diffArr as $key => $value) 
					{
						$idData = $this->add('bc_product_label',['prl_name'=>$value]);
						$proLabel[$value] = $idData['data'];
					}
					$this->B2CDb->End();
				}
				return LibFc::ReturnData(true,$proLabel);	
			}
		}
		return LibFc::ReturnData(false,'addProLabel 参数不正确');
	}
	/**
	 * @method    配件属性 单位add
	 * @param     [array]    $dataArr ['CM','MM']
	 * @author    廖
	 * @copyright 2017-11-14
	 * @return    ['status'=>true,'data'=>['CM'=>111, 'MM'=>222]]
	 */
	function addProUnit($dataArr)
	{
		if(!empty($dataArr))
		{
			$dataArr = array_unique($dataArr);
			$nameArr = array();
			foreach ($dataArr as $key => $value) 
			{
				if(LibFc::Escape($value) != '') $nameArr[$key] = LibFc::Escape($value);
			}
			if(!empty($nameArr))
			{
				//查询唯一配件属性
				$res = $this->get('bc_product_unit',['pru_id','pru_name'],sprintf(" and pru_name in ('%s')",implode("','",$nameArr)));
				$pru_name = array_column($res['data'], 'pru_name');
				$proUnit = array_column($res['data'],'pru_id', 'pru_name');
				$diffArr = array_diff($nameArr, $pru_name);
				if(!empty($diffArr))
				{
					$this->B2CDb->Begin();
					foreach ($diffArr as $key => $value) 
					{
						$idData = $this->add('bc_product_unit',['pru_name'=>$value]);
						$proUnit[$value] = $idData['data'];
					}
					$this->B2CDb->End();
				}
				return LibFc::ReturnData(true,$proUnit);
			}
		}
		return LibFc::ReturnData(false,'addProUnit 参数不正确');
	}
	/**
	 * @method    参数模版排序
	 * @param     [int]             $shopId   [店铺id]
	 * @param     [array]           $dataArr  ['xxx'=>'xxx'] ['模版id'=>'顺序']
	 * @author     廖
	 * @copyright 2017-11-16
	 * @return    ['status'=>true,'data'=>true]
	 */
	function resetProParamsTplSort($shopId,$dataArr)
	{
		if(LibFc::Int($shopId) && !empty($dataArr))
		{
			foreach ($dataArr as $key => $value) 
			{
				if(!LibFc::Int($key) || !LibFc::Int($value)) unset($dataArr[$key]);
			}
			if(!empty($dataArr))
			{
				$this->B2CDb->Begin();
				foreach ($dataArr as $key => $value) 
				{
					$this->set('bc_product_para_tpl',['ppt_seq'=>$value],sprintf(' and ppt_id=%d and ppt_shop_id=%d',$key,$shopId));
				}
				$this->B2CDb->End();
				return LibFc::ReturnData(true,true);
			}
		}
		return LibFc::ReturnData(false,'resetProParamsTplSort 参数不正确');
	}
	/**
	 * @method    根据配件ID获取参数
	 * @param     [int]        $proId [配件ID]
	 * @return    [arr]               [ Array([0] => Array([pptl_ppt_id] => 1 [pptl_prl_id] => 1 [pptl_pru_id] => 1 [pptl_seq] => [ppt_name] => 测试 [pru_name] => cm [prl_name] => 长 )
	 * @author 卢
	 * @copyright 2017-11-14
	 */
	function getParamByPro($proId)
	{
		if(LibFc::Int($proId))
		{
			//参数值
			$valData=$this->get('bc_product_para_val',['prpv_pro_id','prpv_prl_id','prpv_pru_id','prpv_value','prpv_seq'],sprintf(' and prpv_pro_id=%d order by prpv_seq asc',$proId));
			$data=[];
			if(count($valData['data']))
			{
				//参数ID
				$paramId=array_unique(array_column($valData['data'], 'prpv_prl_id'));
				//单位ID
				$unitId=array_unique(array_column($valData['data'], 'prpv_pru_id'));
				$paramId=array_filter($paramId);
				$unitId=array_filter($unitId);
				//获取参数
				$paramArr=$this->get('bc_product_label',['prl_id','prl_name'],sprintf(' and prl_id in (%s)',implode(',',$paramId)));
				$param=array_column($paramArr['data'], null,'prl_id');
				if(count($unitId))
				{
					//获取单位
					$unitData=$this->get('bc_product_unit',['pru_id','pru_name'],sprintf(' and pru_id in (%s)',implode(',',$unitId)));
					$unitArr=array_column($unitData['data'], null,'pru_id');
				}
				foreach ($valData['data'] as $k=>$v) 
				{
					$temp=isset($unitArr[$v['prpv_pru_id']])?array_merge($unitArr[$v['prpv_pru_id']],$param[$v['prpv_prl_id']]):$param[$v['prpv_prl_id']];
					$data[]=array_merge($v,$temp);
				}
			}
			return LibFc::ReturnData(true,$data);
		}
		return LibFc::ReturnData(false,'getParamByPro 参数不正确');
	}
	/**
	 * @method    修改配件自定义参数
	 * @param     [int]       $shopId   [店铺ID]
	 * @param     [int]       $proId    [配件ID]
	 * @param     [int]       $tplId    [模板ID]
	 * @param     [arr]       $val      [[0]=>xxx,[1]=>xxx]【键名要对应labelArr unitArr】
	 * @param     [arr]       $labelArr [[0]=>xxx,[1]=>xxx]【键名要对应val unitArr】
	 * @param     [arr]       $unitArr  [[0]=>xxx,[1]=>xxx]【键名要对应val labelArr】
	 * @param     [int]       [$oriTpl]  原来模板ID
	 * @return    [arr]			[['status'=>true,'data'=>true]]
	 * @author 卢
	 * @copyright 2017-11-15
	 */
	function setShopParam($shopId,$proId,$tplId,$val,$labelArr,$unitArr,$oriTpl)
	{
		if(LibFc::Int($shopId)&&LibFc::Int($proId)&&LibFc::Int($tplId)&&is_array($val)&&is_array($labelArr)&&is_array($unitArr))
		{
			$oriTplData=$this->get('bc_product_para_val',['prpv_pro_id','prpv_prl_id','prpv_pru_id','prpv_value'],sprintf(' and prpv_pro_id=%d',$proId));
			
			//原来参数ID
			$oriLabel=array_column($oriTplData['data'], 'prpv_prl_id');
			$oriVal=array_column($oriTplData['data'], 'prpv_value', 'prpv_prl_id');
			//取交集为修改的参数ID
			$editArr=array_filter(array_intersect($labelArr,$oriLabel));
			//取差集为添加的参数ID
			$addArr=array_filter(array_diff($labelArr, $oriLabel));
		
			$delArr=[];
			if($oriTpl!=$tplId)
			{
				//更换了模板				
				//需要删除的ID
				$delArr=array_filter(array_diff($oriLabel,$labelArr));
			}
			$this->B2CDb->Begin();
			$returnArr = [];
			if(count($editArr))
			{	
				$table = 'bc_product_para_val join bc_product_label on prl_id = prpv_prl_id';
				$labelName = $this->get($table,['prl_id','prl_name','prpv_value'],sprintf(" AND prpv_pro_id = %d AND prl_id in (%s)",$proId,implode(',',$editArr)));
				$labelNameArr = array_column($labelName['data'],null,'prl_id');
				foreach ($editArr as $k=>$v) 
				{
					if($labelNameArr[$v]['prpv_value']!=$val[$k])
					{
						$returnArr[] = $labelNameArr[$v]['prl_name'].': "'.$labelNameArr[$v]['prpv_value'].'" 变更为 "'.$val[$k].'"'; 
					}
					$this->set('bc_product_para_val',['prpv_value'=>$val[$k],'prpv_pru_id'=>(empty($unitArr[$k])?0: (int)$unitArr[$k])],sprintf(' and prpv_pro_id=%d and prpv_prl_id=%d',$proId,$v));
				}
			}
			if(count($addArr))
			{	
				$labelName = $this->get('bc_product_label',['*'],sprintf(" AND prl_id in (%s)",implode(',',$addArr)));
				$labelNameArr = array_column($labelName['data'],'prl_name','prl_id');
				foreach ($addArr as $k => $v) 
				{
					$returnArr[] = $labelNameArr[$v].': "" 变更为 "'.$val[$k].'"'; 
					$this->add('bc_product_para_val',['prpv_pro_id'=>$proId,'prpv_prl_id'=>$v,'prpv_pru_id'=>(empty($unitArr[$k])?0: (int)$unitArr[$k]),'prpv_value'=>$val[$k]]);
				}
			}
			if(count($delArr))
			{
				$labelName = $this->get('bc_product_label',['*'],sprintf(" AND prl_id in (%s)",implode(',',$delArr)));
				$labelNameArr = array_column($labelName['data'],'prl_name','prl_id');

				foreach ($delArr as $k=> $v) {
					$returnArr[] = $labelNameArr[$v].':"'.$oriVal[$v].'" 变更为 "" ';
				}
	
				$this->del('bc_product_para_val',sprintf(' and prpv_pro_id=%d and prpv_prl_id in (%s)',$proId,implode(',',$delArr)));
			}
			if($this->operation=='' && $returnArr)
			{
				$B2cLog = new B2cLog();
				$logArr = [
					'sli_pro_id'=>$proId,
					'sli_shop_id'=>$shopId,
					'sli_etime'=>time(),
					'sli_act'=>'para',
					'sli_txt'=>implode("\r\n",$returnArr)
				];
				$B2cLog->addFastLogItem($logArr);
			}				
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true,true);
	}
	/**
	 * @method    添加配件参数模板
	 * @param     [array]  $tplName 刹车盘参数模板
	 * @param     [array]  $params array(array('name'=>,'seq'=>,'unit'=>)...)
	 * @param     [int]  $shopId 店铺ID
	 * @return    ['status'=>true,'data'=>[true]]
	 * @author    xu
	 * @copyright 2017-11-14
	 */
	function addProParamsTpl($tplName,$tplSeq,$params,$shopId)
	{
		// 校验参数
		if(!is_array($params) || !LibFc::Int($shopId) || LibFc::Escape($tplName)=="")
		{
			return LibFc::ReturnData(false,'addProParamsTpl 参数不正确');
		}
		foreach ($params as $k => $v)
		{
			if(LibFc::Escape($v['name']) !='')
			{
				$allLable[] = LibFc::Escape($v['name']);
				if(LibFc::Escape($v['unit']) !='')
				{
					$allUnit[] = LibFc::Escape($v['unit']);
				}
			}
			
		}
		$this->B2CDb->Begin();	
		$lableToId = array();
		$unitToId = array();	

		// 获取参数=》ID
		if(!empty($allLable))
		{
			$res = $this->addProLabel($allLable);
			$lableToId = $res['data'];
		}
		// 获取单位=》ID
		if(!empty($allUnit))
		{
			$res = $this->addProUnit($allUnit);
			$unitToId = $res['data'];
		}

		// 入库配件参数模板名称
		$res = $this->add('bc_product_para_tpl',array('ppt_name'=>$tplName,'ppt_atime'=>time(),'ppt_shop_id'=>$shopId, 'ppt_seq'=>$tplSeq));
		$pptId = $res['data'];
		//入库每一个模板ID =》 参数ID =》单位ID
		foreach ($params as $k => $v)
		{
			$data = array(
				'pptl_ppt_id'=>$pptId,
				'pptl_prl_id'=>$lableToId[$v['name']],
				'pptl_pru_id'=>isset($unitToId[$v['unit']])?$unitToId[$v['unit']]:0,
				'pptl_seq'=>$v['seq']
			);
			$this->add('bc_product_para_tpl_link',$data);
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $pptId);
	}


	/**
	 * @method    商家删除自己的配件参数模板
	 * @param     [int/array] $pptId 配件参数模板ID
	 * @param     [int] $shopId 商家店铺ID
	 * @return    [['status'=>true],['data'=>true]]
	 * @author xu
	 * @copyright 2017-10-17
	 */
	public function delProParamsTpl($pptIdArr,$shopId)
	{
		// 校验、过滤数据
		if(!empty($pptIdArr) && LibFc::Int($shopId))
		{
			if(!is_array($pptIdArr)) $pptIdArr = explode(',',$pptIdArr);
			$pptIdArr = array_filter($pptIdArr,'LibFc::Int');
			if(!empty($pptIdArr))
			{
				// 开启事务
				$this->B2CDb->Begin();
				// 删除模板
				$this->del('bc_product_para_tpl', sprintf(" and ppt_id in (%s) and ppt_shop_id=%d ", implode(',',$pptIdArr),$shopId));
				// 删除套餐表
				$this->del('bc_product_para_tpl_link', sprintf(" and pptl_ppt_id in (%s) ",implode(',',$pptIdArr)));
				//提交事务
				$this->B2CDb->End();
				return LibFc::ReturnData(true, true);	
			}
		}
		return LibFc::ReturnData(false, 'delProParamsTpl 参数错误');
	}


	/**
	 * @method    编辑配件参数模板
	 * @param     [int]  $pptId 配件参数模板ID
	 * @param     [array]  $tplName 刹车盘参数模板
	 * @param     [array]  $params array(array('name'=>,'seq'=>,'unit'=>)...)
	 * @param     [int]  $shopId 店铺ID
	 * @return    ['status'=>true,'data'=>[true]]
	 * @author    xu
	 * @copyright 2017-11-14
	 */
	function editProParamsTpl($pptId,$tplName,$params,$shopId)
	{
		// 校验参数
		if(!is_array($params) || !LibFc::Int($shopId) || LibFc::Escape($tplName)=="" || !LibFc::Int($pptId))
		{
			return LibFc::ReturnData(false,'参数不正确');
		}
		// 校验当前pptid属于当前店铺
		$res = $this->get('bc_product_para_tpl',['*'],sprintf(" and ppt_id=%d and  ppt_shop_id=%d ",$pptId,$shopId),true);
		if(empty($res['data']))
		{
			return LibFc::ReturnData(false,'参数不正确');
		}
		$thisTplSeqNumber = $res['data']['ppt_seq'];

		foreach ($params as $k => $v)
		{
			if(LibFc::Escape($v['name']) !='')
			{
				$allLable[] = LibFc::Escape($v['name']);
				if(LibFc::Escape($v['unit']) !='')
				{
					$allUnit[] = LibFc::Escape($v['unit']);
				}
			}
			
		}
		// print_r($allUnit);
		// die;
		$this->B2CDb->Begin();	
		$lableToId = array();
		$unitToId = array();	

		// 获取参数=》ID
		if(!empty($allLable))
		{
			$res = $this->addProLabel($allLable);
			$lableToId = $res['data'];
		}
		// 获取单位=》ID
		if(!empty($allUnit))
		{
			$res = $this->addProUnit($allUnit);
			$unitToId = $res['data'];
		}
		// 更新配件参数模板表
		$res = $this->set('bc_product_para_tpl',array('ppt_name'=>$tplName,'ppt_seq'=>$thisTplSeqNumber),sprintf(" and ppt_id=%d and ppt_shop_id=%d ",$pptId,$shopId));
		// $this->del('bc_product_para_tpl_link',sprintf(" and pptl_ppt_id=%d ",$pptId));
		$res = $this->get('bc_product_para_tpl_link',['pptl_prl_id,pptl_pru_id'],sprintf(" and pptl_ppt_id=%d ",$pptId));
		//原有的
		$oldPrlIdArr =	array_column($res['data'],'pptl_prl_id');
		//新增的
		$addPrlIdArr = array_diff(array_values($lableToId),$oldPrlIdArr);
		//删除的
		$delPrlIdArr = array_diff($oldPrlIdArr,array_values($lableToId));
		//修改的
		$editPrlIdArr = array_intersect($oldPrlIdArr,array_values($lableToId));
		//更新配件参数列表
		foreach ($params as $k => $v)
		{
			$pptl_prl_id = (!empty($lableToId[$v['name']])?$lableToId[$v['name']]:0);
			$pptl_pru_id =(!empty($unitToId[$v['unit']])?$unitToId[$v['unit']]:0);
			if(in_array($pptl_prl_id,$addPrlIdArr)){
				$data = array(
					'pptl_ppt_id'=>$pptId,
					'pptl_prl_id'=>$pptl_prl_id,
					'pptl_pru_id'=>$pptl_pru_id,
					'pptl_seq'=>$v['seq']
				);
				$this->add('bc_product_para_tpl_link',$data);
			}
			if(in_array($pptl_prl_id,$editPrlIdArr)){
				$this->set('bc_product_para_tpl_link',['pptl_pru_id'=>$pptl_pru_id,'pptl_seq'=>$v['seq']],sprintf(" and pptl_ppt_id=%d and pptl_prl_id=%d",$pptId,$pptl_prl_id));
			}	
		}
		if(!empty($delPrlIdArr)){
			$this->del('bc_product_para_tpl_link',sprintf(" and pptl_ppt_id=%d and pptl_prl_id in (%s)",$pptId,implode(',',$delPrlIdArr)));
			$where = sprintf(" and prpv_pro_id in (select pro_id from bc_product where pro_ppt_id =%d) and prpv_prl_id in (%s)",$pptId,implode(',',$delPrlIdArr));
			$this->del('bc_product_para_val',$where);
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}
	/**
	 * @method    获取配件历史版本模板
	 * @param     [int]               $proId  [配件ID]
	 * @param     [int]               $shopId [店铺ID]
	 * @return    [arr]                       [['status'=>true,'data'=>['info'=>'xxxx','desc'=>'xxxx']]]配件详情与介绍 html
	 * @author 卢
	 * @copyright 2017-12-25
	 */
	public function getProductHistoryTpl($proId,$shopId)
	{
		$brandlArr = [];
		if(LibFc::Int($proId)&&LibFc::Int($shopId))
		{
			$res = $this->getProduct(['*'], sprintf(" and pro_id = %d and pro_shop_id=%d", $proId,$shopId), true);
			if(!count($res['data']))
			{
				return LibFc::ReturnData(false, '订单信息错误');
				exit();
			}
			$proArr['base'] = $res['data'];
			$B2cBase = new B2cBase();
			// // 获取店铺满减信息
			$sh_manjian_MSG = $B2cBase->get('sh_manjian',['*'],SPRINTF(" and man_shop_id=%d and man_btime < %d and man_etime > %d ", $proArr['base']['pro_shop_id'],time(),time()));
			$sh_manjian_MSG = $sh_manjian_MSG['data'];
			$data['sh_manjian_MSG']=$sh_manjian_MSG;
			$B2cPart = new B2cPart();
			$res = $B2cPart->getPartParam($proArr['base']['pro_part_id']);
			$ParaArr=$res['data'];
			
			// print_r($proArr['partParam']);
			// die;
			$res = $this->getProductParam($proId);
			$proArr['param'] = $res['data'];
			// print_r($proArr['param']);
			$sort=array();
			if(count($proArr['param'])&&count($ParaArr))
			{
				$sort=array_column($ParaArr, 'ppl_seq');
				array_multisort($sort, SORT_ASC, $ParaArr);
				// print_r($ParaArr);
				// die;
				$valRes=array_column($ParaArr, 'pal_id');
				$res=$B2cPart->get('bc_param_value',['pav_id','pav_part_id','pav_pal_id','pav_seq','pav_value'],sprintf(' and pav_pal_id in (%s)',implode(',', $valRes)));
				$sort=[];
				$valRes=[];
				// print_r($res);
				if(count($res['data']))
				{
					foreach ($res['data'] as $v) 
					{
						// print_r($proArr['param'][$v['pal_id']]);
						// die;
						if(in_array($v['pav_value'], array_values($proArr['param'][$v['pav_pal_id']])))
						{
							$valRes[$v['pav_pal_id']][]=$v;
							$sort[$v['pav_pal_id']][]=$v['pav_seq'];
						}
					}
					// print_r($valRes);
					foreach($ParaArr as $K=>$V)
					{
						if(isset($valRes[$V['pal_id']]))
						{
							array_multisort($sort[$V['pal_id']], SORT_ASC, $valRes[$V['pal_id']]);
							$ParaArr[$K]['valArr']=$valRes[$V['pal_id']];
						}
					}
				}
			}
			$proArr['partParam'] = $ParaArr;
			// print_r($proArr['partParam']);
			//获取自定义配件参数
			$res=$B2cBase->get('bc_product',['pro_ppt_id'],sprintf(' and pro_shop_id=%d and pro_id=%d',$shopId,$proId),true);
			
			if($res['data']['pro_ppt_id'])
			{
				$tplId=$res['data']['pro_ppt_id'];
				$proId=$proId;
				//有值的
				$feild = ['prpv_prl_id', 'prpv_pru_id', 'prpv_value','prl_name','pru_name'];
				$res=$B2cBase->get('bc_product_para_val join bc_product on pro_id= prpv_pro_id left join bc_product_label on prl_id=prpv_prl_id left join bc_product_unit on pru_id=prpv_pru_id', $feild, sprintf(" and pro_id=%d and pro_ppt_id =%d and pro_shop_id=%d and (prpv_value is not null or prpv_value!='')", $proId, $tplId, $shopId));
				$oldValArr = [];
				$oldValArr=array_column($res['data'], null,'prpv_prl_id');
				//新的
				$fieldArr=['pptl_ppt_id','prl_id','pru_id','pptl_seq','prl_name','pru_name'];
				$newlink=$B2cBase->get('bc_product_para_tpl_link left join bc_product_label on prl_id=pptl_prl_id left join bc_product_unit on pru_id=pptl_pru_id',$fieldArr,sprintf(' and pptl_ppt_id=%d order by pptl_seq asc,pptl_prl_id asc',$tplId));
				$newArr=array_column($newlink['data'], null,'prl_id');
				if(count($oldValArr))
				{
					foreach ($oldValArr as $k => $v) 
					{
						$newArr[$k]=isset($newArr[$k])?array_merge($v,$newArr[$k]):$v;
					}
				}
			}
			$data['proParams'] = $newArr;
			$res = $this->getProductPic($proId,true);
			//累计评价
			$evaluateData=$B2cBase->get('or_evaluate_product',['count(*) count'],' and evp_pro_id='.$proId,true);
			$proArr['base']['evaluate']=$evaluateData['data']['count'];
			$dataCount = $B2cBase->Get('us_product_collection',['count(*) as count'],' and prc_pro_id='.$proArr['base']['pro_id'],true);
			$proArr['base']['collCount'] = $dataCount['data']['count'];
			$proArr['imgs'] = $res['data'];
			$res = $B2cPart->getAllPart();
			$data['partArr']=$res['data'];
			$B2cShopSort = new B2cShopSort();
			$thisShopSort = $B2cShopSort->getShopSort($proArr['base']['pro_shop_id']);
			$data['thisShopSort']=$thisShopSort['data'];
			$data['proArr']=$proArr;
			LibTpl::Set('data',$data);
			//绑定车型
			$res = $B2cBase->get('bc_product_brand_link',['pbl_brand_id'],'and pbl_pro_id='.$proId);
			$brandId = array_column($res['data'], 'pbl_brand_id');
			// //一级车型
			// $res1 = $B2cBase->get('bc_product_model1_link',['pml1_mod1_id'],'and pml1_pro_id='.$proId);
			// //二级车型
			// $res2 = $B2cBase->get('bc_product_model2_link',['pml2_mod2_id'],'and pml2_pro_id='.$proId);
			//三级车型
			$res3 = $B2cBase->get('bc_product_model3_link',['pml3_mod3_id'],'and pml3_pro_id='.$proId);
			$modId = array_filter(array_column($res3['data'], 'pml3_mod3_id'),'LibFc::Int');
			if(!empty($brandId))
			{
				$ComModel = new ComModel();
				$res = $ComModel->getAllBrand();
				foreach($brandId as $brandId=>$v)
				{
					if(!empty($res['data'][$v])) $brandlArr[$v] = $res['data'][$v];
				}
				if(!empty($modId) && !empty($brandlArr))
				{
					$ComModel = new ComModel();
					$where = sprintf(" and mod3_id in (%s) order by brand_seq, brand_initial, make_seq, make_initial, mod1_name, mod2_name, mod3_name", implode(',', $modId));
					$res = $ComModel->getModel(3, ['*'], $where);
					$fitTotal=0;
					if(!empty($res['data']))
					{
						foreach ($res['data'] as $key => $value) 
						{
							foreach ($brandlArr as $k => $v)
							{
								if($value['mod3_brand_id']==$v['brand_id'])
								{
									$modArr[$v['brand_id']][$key] = $value;
									$fitTotal++;
								}
							}
						}
					}
				}
			}
			LibTpl::Set('fitTotal', $fitTotal);
			LibTpl::Set('isAll', count($brandlArr));
			LibTpl::Set('modArr',$modArr);
			LibTpl::Set('carArr', $brandlArr);
			//号码
			// 获取当前配件的参考号码
			// $res = $this->get('bc_number', ['num_id', 'num_factory', 'num_display', 'num_format', 'num_ismain'], sprintf(" and num_self=0 and num_pro_id=%d order by num_factory, num_format", $proId));
			// $proNum = $res['data'];
			// if(count($proNum))
			// {
			// 	// 拆成三组
			// 	LibTpl::Set('totalNum',count($proNum));
			// 	$proNum = array_chunk($proNum,ceil(count($proNum)/3));
			// 	LibTpl::Set('proNum',$proNum);
				
			// }
			// 传递数据
			$info=LibTpl::Fetch('/item/itemInfo.php');
			$desc=LibTpl::Fetch('/item/itemDesc.php');
			return LibFc::ReturnData(true, ['info'=>$info,'desc'=>$desc]);
		}
		return LibFc::ReturnData(false, 'getProductHistoryTpl 参数错误');
	}
	/**
	 * @method    添加配件历史版本记录
	 * @param     [int]            $proId  [配件ID]
	 * @param     [int]            $shopId [店铺ID]
	 * @return   [arr]				['status'=>true,'data'=>'2'] 返回版本ID
	 * @author 卢
	 * @copyright 2017-12-25
	 */
	public function addProductHistory($proId,$shopId)
	{
		ini_set('memory_limit', '1024M');
		if(LibFc::Int($proId)&&LibFc::Int($shopId))
		{			
			//配件信息
			$data=$this->getProductHistoryTpl($proId,$shopId);
			//判断是否产生过订单
			$res=$this->get('or_order_product',['count(1) count'],sprintf(' and orp_pro_id=%d',$proId),true);
			$target['prh_has_order']=0;
			$delArr=null;
			if($res['data']['count'])
			{
				$target['prh_has_order']=1;
			}
			else
			{
				//判断数量是否多于10条
				$res=$this->get('bc_product_history',['prh_id'],sprintf(' and prh_pro_id=%d and prh_has_order<1 order by prh_end_time asc',$proId));				
				if(count($res['data'])>=10)
				{
					$delArr=$res['data'][0]['prh_id'];//需要删除的历史ID
				}	
			}
			//判断是md5否相同
			$text=json_encode($data['data'],JSON_UNESCAPED_UNICODE);
			// print_r($text);
			$res=$this->get('bc_product_history',['prh_id'],sprintf(" and prh_pro_id=%d and prh_text_md5='%s'",$proId,md5($text)),true);
			$this->B2CDb->Begin();
			if(count($res['data']))
			{
				$prhId=$res['data']['prh_id'];
				$this->set('bc_product_history',['prh_end_time'=>time()],sprintf(' and prh_pro_id=%d and prh_id=%d',$proId,$prhId));
			}
			else
			{
				$target['prh_pro_id']=$proId;
				$target['prh_text']=$text;
				$target['prh_add_time']=time();
				$target['prh_text_md5']=md5($text);
				$target['prh_end_time']=time();
				$target['prh_shop_id']=$shopId;
				$res=$this->add('bc_product_history',$target);
				$prhId=$res['data'];
			}
			//需要删除的历史ID
			if($delArr)
			{
				$this->del('bc_product_history',sprintf(' and prh_id=%d and prh_pro_id=%d',$delArr,$proId));
			}
			$this->B2CDb->End();
			return LibFc::ReturnData(true, $prhId);
		}
		return LibFc::ReturnData(false, 'addProductHistory 参数错误');
	}

	/**
	 * @method    店铺商品唯一性校验
	 * @param     [int] $shopId [店铺ID]
	 * @param     [int] $pri_code
	 * @return    [arr] ['status'=>true,'data'=>[pro_id]]]
	 * @author xu
	 * @copyright 2017-10-16
	 */
	public function getSameProId($shopId,$priCode)
	{
		if(!LibFc::Int($shopId) || empty($priCode)) return  LibFc::ReturnData(true,[]);

		$where = sprintf(" and pro_shop_id=%d and pri_code='%s'",$shopId,$priCode);
		// 查询
		$res = $this->get('bc_product join bc_product_info on pro_id=pri_pro_id',['pro_id'],$where,true);
		return LibFc::ReturnData(true,$res['data']);
	}

	/**
	 * @method    批量导入的时候检测零件分类
	 * @param     [str] $part [零件分类]
	 * @param     [str] $autoAdd [不存在时候是否自动增加]
	 * @return    [arr] ['status'=>true,'data'=>[pro_id]]]
	 * @author xu
	 * @copyright 2017-10-16
	 */
	public function checkPart($part,$autoAdd=false)
	{	
		$part = LibFc::Escape(trim($part));
		//先从子类找
		$where = sprintf(" and part_is_end=1 and pas_name='%s'",$part);
		$res = $this->get('bc_part_small JOIN bc_part ON pas_part_id = part_id JOIN bc_part_tree ON part_id=pt_part_id',['pas_id', 'part_id','pt_path', 'part_name'], $where, true);
		$temp = [];
		if(!empty($res['data']))
		{
			$temp = $res['data'];
		}
		else
		{
			$where = sprintf(" and part_is_end=1 and part_name='%s'",$part);
			$res = $this->get('bc_part left join bc_part_tree on part_id=pt_part_id',['0 as pas_id', 'part_id','pt_path', 'part_name'],$where,true);
			if(!empty($res['data']))
			{
				$temp = $res['data'];
			}
			else if($autoAdd)
			{
				// 新增
				$B2cPart=new B2cPart();
				$res = $this->get('bc_part left join bc_part_tree on pt_part_id=part_id',['part_id'],"and pt_level=1 and pt_path='0' and part_name='其他'",true);
				$parentId = $res['data']['part_id'];
				$temp = array(
						'part_name' => $part,
						'part_keyword' => $part, 
						'part_virtual' => 0,
						'part_is_end' => 1,
						'IsMain' => $parentId
					);
				$B2cPart->AddPart($temp, [$parentId]);
				// 再次获取
				$res = $this->get('bc_part left join bc_part_tree on part_id=pt_part_id',['0 as pas_id', 'part_id','pt_path', 'part_name'],$where,true);
				$temp = $res['data'];
			}
		}
		if(!empty($temp['part_id']))
		{
			$temp['part'] = $temp['part_id'];
			$temp['part_path'] = $temp['pt_path'].','.$temp['part_id'];
		}
		return LibFc::ReturnData(true,$temp);
	}

	/**
	  * @method 批量操作的图片上传
	  * @author xu
	  * @copyright 2018/03/05
	  */
	function batchUploadImg($picPath,$shopId, $errorStop = true)
	{
		//检查图片空间是否存在  
		//是否有水印
		$res = $this->get('sh_shop', ['shop_warter'], sprintf(" and shop_id=%d", $shopId),true);
		$warterstr = '';
		if(!empty($res['data']['shop_warter']))
		{
			$url = mvc::$cfg['FILE_CENTER']['b2c']['url_get'].'&c=warter&f='.str_replace('/100/', '/800/', $res['data']['shop_warter']).mvc::$cfg['FILE_CENTER']['b2c']['get_uri'];
			$LibHttp = new LibHttp();
			$warterstr = $LibHttp->fetch($url); 
		}
		$crc32 = LibFc::GetCrc32(file_get_contents($picPath).$warterstr);
		$res = $this->get('sh_pic', ['*'], sprintf(" and spi_crc32='%s' and spi_cate='product' and spi_shop_id=%d", LibFc::Escape($crc32), $shopId),true);
		if(!empty($res['data']))
		{
			return LibFc::ReturnData(true, $res['data']);
		}
		// 拼接入库
		$file = array('name'=>basename($picPath),'type'=>LibFc::GetFileType($picPath),'tmp_name'=>$picPath,'error'=>0,'size'=>filesize($picPath));
		$dataArr = ['cate'=>'product', 'file'=>$file];
		$dataArr['path'] = 'shop'.$shopId.'/product/';
		$dataArr['spi_style']=0;

		// 上传文件
		$OthFileCenter = new OthFileCenter();
		$fileRes = $OthFileCenter->upload($dataArr,'b2c', $errorStop);
		if(!empty($fileRes['data']['name']))
		{
			//入库
			$B2cBase = new B2cBase();
			$fileRes['data']['oriname'] = empty($fileRes['data']['oriname'])? $fileRes['data']['name']: $fileRes['data']['oriname'];
			$temArr = [
				'spi_cate'=>$dataArr['cate'],
				'spi_shop_id'=>$shopId,
				'spi_path'=>$fileRes['data']['path'],
				'spi_name'=>$fileRes['data']['name'],
				'spi_oriname'=>$fileRes['data']['oriname'],
				'spi_ext'=>$fileRes['data']['ext'],
				'spi_crc32'=>$fileRes['data']['crc32'],
				'spi_size'=>(int)$fileRes['data']['size'],
				'spi_width'=>(int)$fileRes['data']['width'],
				'spi_height'=>(int)$fileRes['data']['heigth'],
				'spi_atime'=>time(),
				'spi_style'=>$dataArr['spi_style']
			];
			$res = $B2cBase->Add('sh_pic', $temArr);
			$fileRes['data']['spi_id'] = $res['data'];
		}
		if(!$res['status'] && !$errorStop) return $fileRes;
		return LibFc::ReturnData(true, $fileRes['data']);
	}
	/**
	 * @method    admin更改配件状态
	 * @param     [int|arr]         $proId  [配件ID]
	 * @param     [int]         $status [状态  [0,1,-1]  ]
	 * @param     [str]         $remark [备注]
	 * @return    [arr]                 [[status=>true,'data'=>true]]
	 * @author 卢
	 * @copyright 2018-03-13
	 */
	public function adminChangePro($proId,$status,$remark='')
	{
		if(!empty($proId)&&in_array($status, [0,1,-1]))
		{
			$B2cLog=new B2cLog();
			$target=array('pro_status'=>$status,'pro_status_notice'=>$remark,'pro_status_ltime'=>time());
			$proArr=is_array($proId)?$proId:[$proId];
			$res=$this->get('bc_product',['pro_shop_id','pro_status','pro_id'],sprintf(' and pro_id in (%s)',implode(',',$proArr)));
			if(count($res['data']))
			{
				$this->B2CDb->Begin();
				foreach ($res['data'] as $v) 
				{
					if($v['pro_status']==$status)
						continue;
					switch ($status) {
						case '0':
							$info='下架';
							break;
						case '1':
							$info='上架';
							break;
						case '-1':
							$info='违规';
							break;
					}
					//日志
					$logArr['log_uid'] = mvc::$cfg['LOGUSER']['uid'];
					$logArr['log_uname'] = mvc::$cfg['LOGUSER']['urname'];
					$logArr['log_category']=1;
					$logArr['log_shop_id']=$v['pro_shop_id'];
					$logArr['log_dataid']=$v['pro_id'];
					$logArr['log_txt']='配件ID：'.$v['pro_id'].' '.$info;
					$B2cLog->addLog($logArr);
					$this->set('bc_product',$target,sprintf(' and pro_id=%d',$v['pro_id']));
				}
				$this->B2CDb->End();
			}
			return LibFc::ReturnData(true,true);
		}
		return LibFc::ReturnData(false,'adminChangePro 参数错误');
	}


	/**
	 * @method 通过号码匹配车型（匹配数据包括EPC、号码、宜配、TCD）
	 * @param  $shopId  int [shopId、proIdArr二选一] 店铺ID
	 * @param  $proIdArr  array[shopId、proIdArr二选一]  产品ID
	 * @param  $type   string   增量式add（默认）|replace
	 * @author soul
	 * @copyright 2018-03-13
	 */
	public function resetModelsByMatch($shopId = 0, $proIdArr = [], $type = 'add')
	{
		$where = '';
		if($shopId > 0) $where = sprintf(" and pro_shop_id = %d", $shopId);
		if(!empty($proIdArr))
		{
			foreach($proIdArr as $k=>$v)
			{
				$proIdArr[$k] = (int) $v;
			}
			$where .= sprintf(" and pro_id in (%s)", implode(',', $proIdArr));
		}
		if(empty($where)) return LibFc::ReturnData(true);

		$pres = $this->get('bc_product', ['pro_id', 'pro_part_id', 'pro_pas_id'], $where.' order by pro_id');
		$proArr = [];
		$this->B2CDb->Begin();
		$LibYpApi = new LibYpApi();
		foreach($pres['data'] as $k=>$v)
		{
			$proArr[$v['pro_id']] = ['proId'=>$v['pro_id'], 'spartId'=>$v['pro_part_id'].'_'.$v['pro_pas_id']];
			if($k%5 == 4 || ($k+1) == count($pres['data']))
			{
				$eProArr = [];
				$mres = $LibYpApi->get('b2c/matchB2cAnyItemModel', [], ['proIds'=>$proArr]);
				foreach($mres['data'] as $mk=>$mv)
				{
					if(!empty($mv['m3ids'])) $eProArr[$mk] = $mv['m3ids'];
				}
				if(!empty($eProArr))
				{
					if($type != 'replace')
					{
						$res = $this->get('bc_product_model3_link', ['*'], sprintf(" and pml3_pro_id in (%s)", implode(',', array_keys($eProArr))));
						foreach($res['data'] as $v)
						{
							$eProArr[$v['pml3_pro_id']][] = $v['pml3_mod3_id'];
						}
					}
					
					foreach($eProArr as $proId=>$mod3IdArr)
					{
						$this->setProductModel($proId, $mod3IdArr, 'NUMBER');
					}
				}
				$proArr = [];
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}

	/**
	 * @method    根据配件的OE号码更新配件的适用车型
	 * @param  $proIdArr  array  如果配件查不到适用车型则此配件适用车型不变
	 * @param  $keep   bool  是否保留适用车型 true false
	 * @author soul
	 * @copyright 2018-03-13
	 */
	public function resetModelsByOes($proIdArr, $keep = true)
	{
		if(!empty($proIdArr))
		{
			foreach($proIdArr as $k=>$v)
			{
				$proIdArr[$k] = (int) $v;
			}
			$proIdArr = array_unique($proIdArr);
			$proArr = [];
			$res = $this->get('bc_number', ['num_format', 'num_pro_id'], sprintf(" and num_pro_id in (%s) and num_factory='OE'", implode(',', $proIdArr)));
			if(empty($res['data'])) return LibFc::ReturnData(true);

			foreach($res['data'] as $v)
			{
				$proArr[$v['num_pro_id']][] = $v['num_format'];
			}

			$prom3Arr = [];
			$LibYpApi = new LibYpApi();
			foreach($proArr as $proId=>$v)
			{
				$res = $LibYpApi->get('ypc/getM3idsByNum', [], ['nums'=>$v]);
				if(!empty($res['data']))
				{
					$prom3Arr[$proId] = $res['data'];
				}
			}
			if(empty($prom3Arr)) return LibFc::ReturnData(true);

			if($keep)
			{
				$res = $this->get('bc_product_model3_link', ['*'], sprintf(" and pml3_pro_id in (%s)", implode(',', array_keys($prom3Arr))));
				foreach($res['data'] as $v)
				{
					$prom3Arr[$v['pml3_pro_id']][] = $v['pml3_mod3_id'];
				}
			}
			$this->B2CDb->Begin();
			foreach($prom3Arr as $proId=>$mod3IdArr)
			{
				$this->setProductModel($proId, $mod3IdArr, 'NUMBER');
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true);
	}
	/**
	 * @method  批量修改配件分类
	 * @param  $shopid  int  店家id
	 * @param  $proIdArr  array  配件id
	 * @param  $sortId   array   分类id
	 * @author liao
	 * @copyright 2018-03-23
	 */
	public function changeProSort($shopId,$proIdArr,$sortIdArr)
	{
		if(LibFc::Int($shopId) && is_array($proIdArr) && !empty($proIdArr) && is_array($sortIdArr) && !empty($sortIdArr))
		{
			$proIdArr = array_filter($proIdArr,'LibFc::Int');
			$sortIdArr = array_filter($sortIdArr,'LibFc::Int');
			if(!empty($proIdArr) && !empty($sortIdArr))
			{
				//验证判断
				$res = $this->get('bc_product',['pro_id'],sprintf('and pro_id in (%s) and pro_shop_id=%d',implode(',', $proIdArr),$shopId));
				$proIdArr = array_column($res['data'], 'pro_id');
				$res = $this->get('sh_sort',['sort_id'],sprintf('and sort_id in (%s) and sort_shop_id=%d',implode(',', $sortIdArr),$shopId));
				$sortIdArr = array_column($res['data'], 'sort_id');
				if(!empty($proIdArr) && !empty($sortIdArr))
				{
					$this->B2CDb->Begin();
					$this->del('bc_product_sort',sprintf('and prs_pro_id in (%s)',implode(',',$proIdArr)));
					foreach($proIdArr as $value)
					{
						foreach($sortIdArr as $v)
						{
							$this->add('bc_product_sort',['prs_pro_id'=>$value,'prs_sort_id'=>$v]);
						}
					}
					// 日志
					$B2cLog=new B2cLog();
					$codeRes = $this->get('bc_product_info',['pri_code'],sprintf(" and pri_pro_id in (%s)",implode(',',$proIdArr)));
					$codeArr = $codeRes['data'] ? array_column($codeRes['data'], 'pri_code') : [];
					$item = [
						'log_category'=>1,
						'log_shop_id'=>$shopId,
						'log_atime'=>time(),
						'log_dataid'=>$proIdArr,
						'log_txt'=>'修改配件分类：'.implode(',',$codeArr)
					];
					$B2cLog->addFastLog($item);
					$this->B2CDb->End();
					return LibFc::ReturnData(true,true);
				}
			}

		}
		return LibFc::ReturnData(false,'参数不正确!');
	}
	public function setProFrt($shopId,$dataArr,$frtid)
	{
		if(LibFc::Int($shopId)&&count($dataArr)&&LibFc::Int($frtid))
		{
			$B2cLog=new B2cLog();
			$dataArr=array_filter($dataArr,'LibFc::Int');
			if(count($dataArr))
			{
				$this->B2CDb->Begin();
				$this->set('bc_product_info',['pri_frt_id'=>$frtid],sprintf(' and pri_pro_id in (%s)',implode(',',$dataArr)));
				$codeRes = $this->get('bc_product_info',['pri_code'],sprintf(" and pri_pro_id in (%s)",implode(',',$dataArr)));
				$codeArr = $codeRes['data']? array_column($codeRes['data'],'pri_code'):[];
				$fieldArr=['log_category'=>1,'log_shop_id'=>$shopId,'log_atime'=>time(),'log_dataid'=>$dataArr,'log_txt'=>'修改配件运费：'.implode(',',$codeArr)];
				$B2cLog->addFastLog($fieldArr);
				$this->B2CDb->End();
				return LibFc::ReturnData(true,true);
			}
		}
		return LibFc::ReturnData(true,'setProFrt参数错误');
	}



	public function setProDesTpl($shopId,$dataArr,$pdtid)
	{
		if(LibFc::Int($shopId)&&count($dataArr)&&LibFc::Int($pdtid))
		{
			$res = $this->get('bc_product_desc_tpl', ['*'], sprintf(' and pdt_id=%d and pdt_shop_id=%d',$pdtid,$shopId), true);
			if(empty($res['data'])) return LibFc::ReturnData(true,'描叙模板不存在');
			$tplArr = $res['data'];
			$B2cLog=new B2cLog();
			$dataArr=array_filter($dataArr,'LibFc::Int');
			if(count($dataArr))
			{
				$this->B2CDb->Begin();
				$this->set('bc_product_info',['pri_des'=>$tplArr['pdt_txt']],sprintf(' and pri_pro_id in (%s)',implode(',',$dataArr)));
				$codeRes = $this->get('bc_product_info',['pri_code'],sprintf(" and pri_pro_id in (%s)",implode(',',$dataArr)));
				$codeArr = $codeRes['data']? array_column($codeRes['data'],'pri_code'):[];
				$fieldArr=['log_category'=>1,'log_shop_id'=>$shopId,'log_atime'=>time(),'log_dataid'=>$dataArr,'log_txt'=>'修改配件描叙模板：'.implode(',',$codeArr)];
				$B2cLog->addFastLog($fieldArr);
				$this->B2CDb->End();
				return LibFc::ReturnData(true,true);
			}
		}
		return LibFc::ReturnData(true,'setProDesTpl参数错误');
	}



	/**
	  * @method 获取配件售后保障
	  * @param  $proId 
	  * @author xu
	  * @copyright 2018/04/19
	  * @return 
			成功 ["status"=>true, "data"=> arr] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getProAfterSellService($proId)
	{
		// 参数
		if(!LibFc::Int($proId))
			return LibFc::ReturnData(true,'getProServicePdt参数错误！');

		$returnData = array();
		// 保证金
		$res = $this->get('bc_product',['pro_shop_id'],sprintf(' and pro_id=%d',$proId),true);
		if(empty($res['data']))
			LibFc::ajaxJsonEncode(['status'=>true,'data'=>""]);
		$shopId = $res['data']['pro_shop_id'];
		$res = $this->get('sh_shop',['shop_money_bail'],sprintf(' and shop_id=%d',$shopId),true);
		$returnData['promise'] = ($res['data']['shop_money_bail']>0?$res['data']['shop_money_bail']:0);
		
		// 无忧退货
		$where = sprintf(' and shop_service_status=1 and shop_id=%d',$shopId);
		$res = $this->get('sh_shop',['shop_service','shop_service_status'],$where,true);
		$returnData['free'] = empty($res['status'])?"":json_decode($res['data']['shop_service'],true);

		// 卖家服务
		$table = "bc_product_info left join bc_product_desc_tpl on pdt_id=pri_service_pdt_id";
		$where = sprintf(" and pri_pro_id=%d and pdt_type=1",$proId);
		$res = $this->get($table,['pdt_name','pdt_remark','pri_pro_id','pdt_txt','pdt_add_time','pdt_type','pdt_shop_id'],$where);
		$returnData['service'] = current($res['data']);

		// 返回
		return LibFc::ReturnData(true,$returnData);
	}


	/**
	  * @method 删除图片空间
	  * @param  $spiIds 图片ID
	  * @param  $shopId int
	  * @author xu
	  * @copyright 2018/04/23
	  * @return 
			成功 ["status"=>true, "data"=> $OneRow=false 二维数组 ; $OneRow=true 一维数组] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function delPiczonePic($spiIds, $shopId, $force = 0)
	{
		if(!is_array($spiIds))
			$spiIds = [$spiIds];
		if(empty($spiIds = array_filter($spiIds,'LibFc::Int')) || !LibFc::Int($shopId))
			return LibFc::ReturnData(false,'delPiczonePic 参数错误！');

		// 过滤非自身店铺
		$where = sprintf(' and spi_shop_id=%d and spi_id in (%s) ',$shopId,implode(',',$spiIds));
		$res = $this->get('sh_pic',['spi_id','spi_shop_id','spi_cate','spi_name','spi_ext'],$where);
		$spiIds = array_column($res['data'], 'spi_id');
		$pic = $res['data'];
		if(empty($spiIds))
			return LibFc::ReturnData(false,'您只能删除本店铺内图片！');

		// 检测是否被店铺内商品使用
		$res = $this->get('bc_product_pic',['pp_pro_id'],sprintf("and pp_spi_id in (%s)",implode(',',$spiIds)));
		if(!empty($res['data']) && !$force)
			return LibFc::ReturnData(false,'删除会导致某些配件描述图片不显示，是否继续！');

		$this->B2CDb->Begin();
		// 文件中心接口
		$OthFileCenter = new OthFileCenter();
		foreach ($pic as $v) {
			$temp = array('cate'=>$v['spi_cate'],
						 'files'=>array(
					 		$v['spi_path'].'100/'.$v['spi_name'].'.'.$v['spi_ext'],
					 		$v['spi_path'].'240/'.$v['spi_name'].'.'.$v['spi_ext'],
					 		$v['spi_path'].'640/'.$v['spi_name'].'.'.$v['spi_ext'],
					 		$v['spi_path'].'400/'.$v['spi_name'].'.'.$v['spi_ext'],
					 		$v['spi_path'].$v['spi_name'].'.'.$v['spi_ext']
					 	)
					);
			$OthFileCenter->del($temp);
		}
		// 删除sh_pic记录
		$this->del('sh_pic',sprintf("and spi_id in (%s)",implode(',',$spiIds)));
		// 配件图片关联
		$this->del('bc_product_pic',sprintf("and pp_spi_id in (%s)",implode(',',$spiIds)));
		$this->B2CDb->End();

		return LibFc::ReturnData(true,true);
	}
	/**
	 * @method    更新图片
	 * @param     [int]     $shopId  [店铺ID]
	 * @param     [int]     $proId   [配件ID]
	 * @param     [arr|int]     $dataArr [需要添加/修改的图片ID]
	 * @param     [arr|int]     $delArr  [需要删除的图片Id]
	 * @param     int    $seq     [顺序]
	 * @return    [arr]              ['status'=>true,'data'=>true]
	 * @author 卢
	 * @copyright 2018-05-07
	 */
	function editProPic($shopId,$proId,$dataArr,$delArr,$seq=0)
	{
		if(empty($dataArr)&&empty($delArr))
			return LibFc::ReturnData(false,'editProPic参数错误');
		$dataArr=is_array($dataArr)?$dataArr:[$dataArr];
		$delArr=is_array($delArr)?$delArr:[$delArr];
		//查找已有的
		$res = $this->getFieldUniVal('bc_product_pic', 'pp_spi_id', sprintf(" and pp_pro_id = %d", $proId));
		$oldIdArr = $res['data'];
		$delIdArr=[];
		if(!empty($delArr))
		{
			foreach ($delArr as $k => $v) 
			{
				if(!empty($v))
					$delIdArr[]=(int)$v;
			}
		}
		if(!empty($dataArr))
		{
			$this->B2CDb->Begin();
			$seq = empty($seq)?0:$seq;
			foreach($dataArr as $spiId)
			{
				if($spiId < 1) continue;
				$isMain = $seq === 0? 1: 0;
				$setArr = ['pp_ismain'=>$isMain, 'pp_seq'=>$seq];
				if(in_array($spiId, $oldIdArr))
				{
					$this->set('bc_product_pic', $setArr, sprintf(" and pp_spi_id=%d and pp_pro_id=%d", $spiId, $proId));
				}
				else
				{
					$setArr['pp_spi_id'] = $spiId;
					$setArr['pp_pro_id'] = $proId;
					$this->add('bc_product_pic', $setArr);
				}
				$seq++;
			}
		}
		//删除
		if(!empty($delIdArr))
		{
			$this->del('bc_product_pic', sprintf(" and pp_spi_id in (%s) and pp_pro_id=%d", implode(',', $delIdArr), $proId));
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true,true);
		
	}


	/**
	 * @method    通过excel批量添加、更新店铺配件
	 * @param $proArr array [ ["pro_name"]=> string(22) "缸盖螺栓 06 07 685" ["part_name"]=> string(12) "缸盖螺栓" ["pro_number"]......]
	 * @param $shopId int 商家店铺ID
	 * @param $unique string pro_id||pri_code||main_number 唯一标识  通过此标识判断获取产品ID
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importProduct($shopId, $proArr, $unique = null)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, 'importProduct 店铺不存在');
		if(empty($proArr) || !is_array($proArr)) return LibFc::ReturnData(false, 'importProduct proArr参数不正确');
			
		//检查店铺是否存在
		$res = $this->get('sh_shop', ['shop_status'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'importProduct 店铺不存在');

		$B2cPart = new B2cPart();
		$B2cBrand = new B2cBrand();
		$B2cShopSort = new B2cShopSort();
		
		$chkProArr = [];
		$errorArr = [];
		$reArr = ['：'=>':',"；"=>";","，"=>","];
		$this->B2CDb->Begin();
		foreach($proArr as $row=>$pro)
		{
			$tempArr = [];
			$tempErr = [];
			$numseq = 0;
			//if(empty($pro['part_name'])) continue;
			foreach($pro as $filed=>$val)
			{
				$filed = trim($filed);
				$val = trim($val);
				if($val == '') continue;
				switch($filed)
				{
					/****基本表***/
					case 'pro_brand': //配件品牌
						$tempArr['base']['pro_prb_id'] = 0;	
						if(trim($val) != '')
						{
							$res = $B2cBrand->addShopBrand($shopId, $val);
							$tempArr['base']['pro_prb_id'] = (int) $res['data'];
						}
					break;
					case 'pro_name':
					case 'pro_sel_des':
						$tempArr['base'][$filed] = $val;
					break;
					case 'ppt_name':
						$tempArr[$filed] = $val;
					break;
					case 'pro_sale_price': //销售价
					case 'pro_cost_price': //成本价
					case 'pro_price_vip1': //VIP价
					case 'pro_price_vip2': //VIP价
					case 'pro_price_vip3': //VIP价
					case 'pro_price_vip4': //VIP价
						$tempArr['base'][$filed] = sprintf('%.2f', $val);
					break;

					case 'pro_count':
						$tempArr['base'][$filed] = (int) $val;
					break;

					case 'pro_promoted'://橱窗推荐 Y|N
					case 'pro_user_discount'://店铺VIP Y|N
					case 'pro_manjian'://参与满减 Y|N
					case 'pro_host'://热销 Y|N
						 $tempArr['base'][$filed] = $val == 'Y'? 'Y': 'N';
					break;

					/****扩展表***/
					case 'pri_des': //描叙
						$tempArr['info'][$filed] = str_replace("\n", '<br>', $val);
					break;
					case 'pri_code': //自编号
					case 'pri_self_remark':
						$tempArr['info'][$filed] = $val;
					break;
					case 'pri_set_inventory': //减库存:0付款减  1拍下减
					case 'pri_invoice': //发票0|1
					case 'pri_warranty': //保修0|1
					case 'pri_return_promise': //保修0|1
						$tempArr['info'][$filed] = $val == 1? 1: 0;
					break;

					case 'pri_weight': //重量KG/件
						$tempArr['info'][$filed] = sprintf('%.2f', $val);
					case 'publish':
						if($val =='立即上架')
						{	// 售卖中
							$tempArr['info']['pri_publish_time'] = time();
							$tempArr['base']['pro_status'] = 1;
						}
						else if(strtotime($val) && strtotime($val)>time())
						{	// 预售
							$tempArr['info']['pri_publish_time'] = strtotime($val);
							$tempArr['base']['pro_status'] = 2;
						}
						else
						{	// 放入仓库
							$tempArr['info']['pri_publish_time'] = 0;
							$tempArr['base']['pro_status'] = 0;
						}
					break;
					case 'part_name': //配件分类
						$res = $this->checkPart($val,true);
						if(!empty($res['data']))
						{
							$tempArr['base']['pro_part_id'] = (int) $res['data']['part'];
							$tempArr['base']['pro_part_path'] = $res['data']['part_path'];
							$tempArr['base']['pro_pas_id'] = (int) $res['data']['pas_id'];
						}
					break;
					case 'part_param': //位置:前,后;厚度:16.5mm   删除位置参数(位置:;厚度:16.5mm)
						$val = LibFc::GetSemiangle($val);
						foreach(explode(';', $val) as $xv)
						{
							if(trim($xv) == '') continue;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '')
							{
								$valArr = [];
								foreach(explode(',', $yv[1]) as $kv)
								{
									$kv = trim($kv);
									if($kv != '') $valArr[] = $kv;
								}
								$tempArr['part_param'][] = ['label'=>$yv[0], 'vals'=>$valArr];
							}
							else
							{
								$tempErr[] = '配件分类参数不正确('.$val.')，样例【位置:前,后;厚度:16.5mm   删除位置参数(位置:;厚度:16.5mm】。';
							}
						}
					break;
					case 'main_number': //主号码
						//全角转半角
						$val = trim(LibFc::GetSemiangle($val), ':');
						$val = stripos($val, ':') === false ? 'OE:'.$val: $val;
						$yv = explode(':', $val);
						if(count($yv) >= 2 && trim($yv[0]) != '' && trim($yv[1]) != '')
						{
							$mainNum = ['num_factory'=>$yv[0], 'num_display'=>$yv[1], 'num_ismain'=>1];
							$tempArr['nums'][--$numseq] = $mainNum;
						}
					break;
					case 'pro_number': //互换号 多个逗号分隔
						//全角转半角
						$val = LibFc::GetSemiangle($val);
						$val = strtr($val, [","=>";","\n"=>";"]);
						foreach(explode(';', $val) as $xv)
						{
							$xv = trim($xv, ':');
							$xv = stripos($xv, ':') === false ? 'OE:'.$xv: $xv;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '' && trim($yv[1]) != '')
							{
								$tempArr['nums'][--$numseq] = ['num_factory'=>$yv[0], 'num_display'=>$yv[1], 'num_ismain'=>0];
							}
							/*else if(count($yv) >= 2)
							{
								$tempErr[] = '互换号不正确('.$val.')，样例【TRW:GDB900;OE:0060 750 413】。';
							}*/
						}
					break;
					case 'freight': //运费模板
						if($val != '')
						{
							$res = $this->get('sh_freight_tpl',['frt_id'],sprintf(" and frt_name='%s' and frt_shop_id=%d ", LibFc::Escape($val), $shopId), true);
							if(!empty($res['data']))
							{
								$tempArr['info']['pri_frt_id'] = $res['data']['frt_id'];
							}
							else
							{
								$tempErr[] = '运费模板不存在('.$val.')。';
							}
						}
					break;
					case 'shop_sort': //店铺分类 多个逗号分隔
						$val = strtr($val, $reArr);
						foreach(explode(';', $val) as $xv)
						{
							if($xv != '')
							{
								$tempArr['shop_sort'][] = $xv;
							}
						}
					break;
					case 'pro_param': //配件自定义参数
						$val = strtr($val, $reArr);
						foreach(explode(';', $val) as $xv)
						{	
							if(trim($xv) == '') continue;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '')
							{
								//$tempArr['pro_param'][] = ['label'=>$yv[0], 'val'=>$yv[1]];
								$tempArr['pro_param'][] = [$yv[0], $yv[1]];
							}
							else
							{
								$tempErr[] = '配件自定义参数不正确('.$val.')，样例【长:100mm;厚度:16.5mm   删除位置参数(长:;厚度:16.5mm】。';
							}
						}
					break;
				}
			}

			//寻找唯一标识确认产品ID
			switch($unique)
			{
				case 'pro_id':
					$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id=%d and pro_shop_id=%d", $pro['pro_id'], $shopId), true);
					if(!empty($res['data']))
					{
						$tempArr['base']['pro_id'] = $res['data']['pro_id'];
					}
					else
					{
						$tempErr[] = '配件ID('.$val.')不存在。';
					}
				break;
				case 'pri_code':
					if(!empty($tempArr['info']['pri_code']))
					{
						$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_format='%s' and pro_shop_id=%d", LibFc::FormatNum($tempArr['info']['pri_code']), $shopId), true);
						if(!empty($res['data']))
						{
							$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
						}
					}
				break;
				case 'main_number':
					if(!empty($mainNum))
					{
						$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_ismain=1', ['num_pro_id'], sprintf(" and num_factory='%s' and num_format='%s' and pro_shop_id=%d", LibFc::Escape($mainNum['num_factory']), LibFc::FormatNum($mainNum['num_display']), $shopId), true);
						if(!empty($res['data']))
						{
							$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
						}
					}
				break;
			}

			if(empty($tempArr['base']['pro_id']))
			{
				if(empty($tempArr['base']['pro_part_id']))
				{
					if(empty($tempArr['base']['pro_name'])) break;
					$tempErr[] = '配件分类不存在。';
				}
				else if(empty($tempArr['shop_sort']))
				{
					$tempArr['shop_sort'] = [$pro['part_name']];
				}

				if(!empty($tempArr['nums']))
					$tempArr['nums'][-1]['num_ismain'] = 1;
				
				if(empty($tempArr['info']['pri_publish_time']))
				{
					$tempArr['info']['pri_publish_time'] = 0;
					$tempArr['base']['pro_status'] = 0;
				}

			}

			$chkProArr[] = $tempArr;
			if(!empty($tempErr))
			{
				if(empty($tempArr['base']['pro_id']) && empty($tempArr['info']['pri_code']) && empty($tempArr['info']['part_name']))
				{}
				else
				{
					$errorArr[$row] = $tempErr;
				}
			}
		}

		if(!empty($errorArr))
		{
			return LibFc::ReturnData(true, ['imp'=>false, 'chkerr'=>$errorArr]);
		}

		//入库
		$B2cShopSort = new B2cShopSort();
		foreach($chkProArr as $pro)
		{
			//店铺分类
			if(!empty($pro['shop_sort']))
			{
				$res = $B2cShopSort->getAddShopSortId($shopId, $pro['shop_sort']);
				$sortIdArr = array_values($res['data']);
				$pSortIdArr = $B2cShopSort->getShopParentById($shopId,$sortIdArr);
				$pro['shopSort'] = array_unique(array_merge($sortIdArr,$pSortIdArr['data']));

			}

			//零件参数
			if(!empty($pro['part_param']) && $pro['base']['pro_part_id'] > 0)
			{
				$labelArr = [];
				$res = $this->get('bc_part_param_link join bc_param_label on pal_id=ppl_pal_id', ['pal_id', 'pal_name'], sprintf(" and ppl_part_id=%d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelArr[strtoupper($vv['pal_name'])] = $vv['pal_id'];
				}
				
				$labelValArr = [];
				$res = $this->get('bc_param_value',['pav_id', 'pav_pal_id', 'pav_value'],sprintf(" and pav_part_id = %d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelValArr[$vv['pav_pal_id']][strtoupper($vv['pav_value'])] = $vv['pav_id'];
				}
				foreach($pro['part_param'] as $vv)
				{
					if(($palId = $labelArr[strtoupper(trim($vv['label']))]) > 0)
					{
						
						foreach($vv['vals'] as $vvv)
						{
							
							if(($pavId = $labelValArr[$palId][strtoupper(trim($vvv))]) > 0)
							{
								$pro['param'][$palId][] = $pavId;
							}
						}
						if(empty($pro['param'][$palId]))
							$pro['param'][$palId] = implode(',', $vv['vals']);
					}
				}
			}
			unset($pro['part_param']);
			
			if(empty($pro['base']['pro_id']))
			{
				$pro['base']['pro_show_b2c'] = 1;
				$pro['base']['pro_show_app'] = 1;
				$pro['base']['pro_shop_id'] = $shopId;
				$pro['base']['pro_count'] = empty($pro['base']['pro_count'])? 1: $pro['base']['pro_count'];

				//运费模板
				if(empty($pro['info']['pri_frt_id']))
				{
					$res = $this->get('sh_freight_tpl',['frt_id'],sprintf(" and frt_shop_id=%d order by frt_default desc", $shopId), true);
					if(!empty($res['data']))
					{
						$pro['info']['pri_frt_id'] = $res['data']['frt_id'];
					}
				}
				$res = $this->addProduct($pro,$shopId);
				$pro['base']['pro_id'] = $res['data'];
			}
			else
			{
				$this->setProduct($shopId, $pro['base']['pro_id'], $pro);
			}
			if(!empty($pro['pro_param']))
				$this->setBatchParam($pro['base']['pro_id'], $shopId, $pro['pro_param'], $pro['ppt_name']);
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, ['imp'=>true, 'chkerr'=>$errorArr]);
	}


	/**
	 * @method    通过excel批量添加、更新店铺配件图片
	 * @param $shopId int 商家店铺ID
	 * @param $imgfile string 图片压缩包路径
	 * @param $proArr array [ ["pro_name"]=> string(22) "缸盖螺栓 06 07 685" ["part_name"]=> string(12) "缸盖螺栓" ["pro_number"]......]
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importProductImg($shopId, $imgfile, $proArr)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, 'importProduct 店铺不存在');
		if(!file_exists($imgfile)) return LibFc::ReturnData(false, '图片压缩包不存在');
		if(empty($proArr) || !is_array($proArr)) return LibFc::ReturnData(false, 'importProductImg proArr参数不正确');
			
		//检查店铺是否存在
		$res = $this->get('sh_shop', ['shop_status'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'importProduct 店铺不存在');


		 // 解压文件存储路径
        $savePath = mvc::$cfg['PATH_ROOT'].'tmp/'.uniqid().'/';
        $ZipArchive = new ZipArchive();
        if($ZipArchive->open($imgfile)!==TRUE) return LibFc::ReturnData(false, '请先添加zip文件！');
        if(!$ZipArchive->extractTo($savePath)) 
            return LibFc::ReturnData(false, 'zip文件错误！');
        $ZipArchive->close();
        $picPath = $savePath.'images/';
			
		$B2cPart = new B2cPart();
		$B2cBrand = new B2cBrand();
		$B2cShopSort = new B2cShopSort();
		
		$chkProArr = [];
		$errorArr = [];
		$reArr = ['：'=>';',"；"=>";",","=>";","，"=>";"];
		foreach($proArr as $row=>$pro)
		{
			$proId = 0;
			if(!empty($pro['pro_id']))
			{
				$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id=%d and pro_shop_id=%d", $pro['pro_id'], $shopId), true);
				if(!empty($res['data']))
				{
					$proId = $res['data']['pro_id'];
				}
			}

			if($proId < 1 && !empty($pro['pri_code']))
			{
				$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_format='%s' and pro_shop_id=%d", LibFc::FormatNum($pro['pri_code']), $shopId), true);
				if(!empty($res['data']))
				{
					$proId = $res['data']['num_pro_id'];
				}
			}

			if($proId < 1 && !empty($pro['main_number']))
			{
				$pro['main_number'] = LibFc::GetSemiangle($pro['main_number']);
				$yv = explode(':', $pro['main_number']);
				if(count($yv) >= 2 && trim($yv[0]) != '' && trim($yv[1]) != '')
				{
					$mainNum = ['num_factory'=>$yv[0], 'num_display'=>$yv[1], 'num_ismain'=>1];
					$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_ismain=1', ['num_pro_id'], sprintf(" and num_factory='%s' and num_format='%s' and pro_shop_id=%d", LibFc::Escape($mainNum['num_factory']), LibFc::FormatNum($mainNum['num_display']), $shopId), true);
					if(!empty($res['data']))
					{
						$proId = $res['data']['num_pro_id'];
					}
				}
			}

			$imgArr = [];
			if(!empty($pro['images']))
			{
				$pro['images'] = strtr($pro['images'], $reArr);
				foreach(explode(';', $pro['images']) as $vv)
				{
					$extArr = ['', '.jpg', '.JPG', '.png', '.PNG'];
					foreach($extArr as $ext)
					{
						if(file_exists($picPath.$vv.$ext))
						{
							$imgArr[] = $picPath.$vv.$ext;
							break;
						}
					}
				}
			}

			if($proId > 0 && !empty($imgArr))
			{
				$chkProArr[$proId] = $imgArr;
			}
		}

		// 数据过滤完成-开始入库数据
		$OthFileCenter = new OthFileCenter();
		foreach ($chkProArr as $proId=>$imgArr)
		{
			$this->B2CDb->Begin();
			$spiIdArr = [];
			foreach ($imgArr as $img) 
			{
				$res = $this->batchUploadImg($img, $shopId);
				if(!empty($res['data']))
					$spiIdArr[] = $res['data']['spi_id'];
			}
			
			if(!empty($spiIdArr))
				$this->setProductPic($shopId, $proId, $spiIdArr);
			$this->B2CDb->End();
		}
		// 删除解压文件夹
		LibDir::DeleteDir($savePath);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, ['imp'=>true, 'chkerr'=>$errorArr]);
	}


	/**
	 * @method    通过excel批量添加、更新产品适用车型
	 * @param $modelArr array [ [车型ID]=>[号码1，号码2...]......]
	 * @param $shopId int 商家店铺ID
	 * @param $style string merge合并  replace替换
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importProductModel($shopId, $modelArr, $style = 'merge')
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, 'importProduct 店铺不存在');
		if(empty($modelArr) || !is_array($modelArr)) return LibFc::ReturnData(false, '车型导入参数不正确');
			
		//检查店铺是否存在
		$res = $this->get('sh_shop', ['shop_status'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'importProduct 店铺不存在');
		
		$formatModelArr = [];
		$allNumArr = [];
		foreach($modelArr as $mod3Id=>$numArr)
		{
			$mod3Id = (int) $mod3Id;
			$numArr = array_unique($numArr);
			foreach($numArr as $num)
			{
				$num = LibFc::FormatNum($num);
				if(empty($num)) continue;
				$allNumArr[] = $num; 
				$formatModelArr[$mod3Id][] = $num;
			}
		}
		unset($modelArr);

		//号码和产品的对应关系
		if(!empty($allNumArr))
		{
			$numToProArr = [];
			$where = sprintf(" and pro_shop_id =%d and num_show = 1 and num_format in ('%s')", $shopId, implode("','", $allNumArr));
			$res = $this->get('bc_number join bc_product on pro_id = num_pro_id', ['pro_id', 'num_format'], $where);
			$numToProArr = array_column($res['data'], 'pro_id', 'num_format');
			unset($allNumArr);
			
			$proModelArr = [];
			foreach($formatModelArr as $mod3Id=>$numv)
			{
				$numv = array_unique($numv);
				foreach($numv as $num)
				{
					if(!empty($numToProArr[$num]))
					{
						$proModelArr[$numToProArr[$num]][] = $mod3Id; 
					}
				}
			
			}
		}

		if(!empty($proModelArr))
		{
			//已有的车型ID
			if($style != 'replace')
			{
				$tres = $this->get('bc_product_model3_link', ['pml3_pro_id, pml3_mod3_id'], sprintf(" and pml3_pro_id in(%s)", implode(',', array_keys($proModelArr))));
				foreach($tres['data'] as $tv)
				{
					$proModelArr[$tv['pml3_pro_id']][] = $tv['pml3_mod3_id'];
				}
			}

			$this->B2CDb->Begin();
			foreach($proModelArr as $proId=>$mids)
			{
				$this->setProductModel($proId, $mids);
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true, ['imp'=>true, 'chkerr'=>[]]);
	}



	/**
	 * @method   导出商城产品或者下载产品模板
	 * @param $type  b2c：商城模板   super：目录模板
	 * @param $colsFiled  自定义导出字段
	 * @param $proArr  需要导出的产品数据
	 * @author	soul
	 * @copyright 2019/9/2
	 */
	public function exportB2cItem($colsFiled = [], $proArr = [], $filename = '')
	{
		if(empty($colsFiled)) $colsFiled = [
			['name'=>'配件ID', 'fname'=>'pro_id', 'width'=>10],	
			['name'=>'零件分类', 'fname'=>'part_name', 'color'=>'FF0000', 'width'=>15],	
			//['name'=>'零件参数', 'fname'=>'part_param', 'width'=>15],	
			['name'=>'店铺分类', 'fname'=>'shop_sort', 'width'=>15],	
			['name'=>'配件名称', 'fname'=>'pro_name', 'color'=>'FF0000', 'width'=>25],	
			['name'=>'配件品牌', 'fname'=>'prb_name', 'width'=>15],	
			['name'=>'商家编码', 'fname'=>'pri_code', 'color'=>'FF0000', 'width'=>20],	
			['name'=>'互换号', 'fname'=>'number', 'width'=>30],
			['name'=>'销售价', 'fname'=>'pro_sale_price', 'width'=>15],
			['name'=>'库存', 'fname'=>'pro_count', 'width'=>10],
			['name'=>'自定义参数', 'fname'=>'pro_param', 'width'=>30],
			['name'=>'配件卖点', 'fname'=>'pro_sel_des', 'width'=>20],
			['name'=>'配件描述', 'fname'=>'pri_des', 'width'=>20],
			['name'=>'商家备注', 'fname'=>'pri_self_remark', 'width'=>20],
			['name'=>'维修厂价', 'fname'=>'pro_price_vip1', 'width'=>15],
			['name'=>'小型经销商价', 'fname'=>'pro_price_vip2', 'width'=>15],
			['name'=>'中型经销商价', 'fname'=>'pro_price_vip3', 'width'=>15],
			['name'=>'大型经销商价', 'fname'=>'pro_price_vip4', 'width'=>15],
		];
		$OthExcel = new OthExcel();
		$objPHPExcel = new PHPExcel();
		$objPHPExcel->getProperties()->setTitle('export')->setDescription('none');
		$objPHPExcel->setActiveSheetIndex(0);
		//左对齐
		$objPHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
	
		$colIndex = [ 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
		'AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ',
		'BA','BB','BC','BD','BE','BF','BG','BH','BI','BJ','BK','BL','BM','BN','BO','BP','BQ','BR','BS','BT','BU','BV','BW','BX','BY','BZ',
		'CA','CB','CC','CD','CE','CF','CG','CH','CI','CJ','CK','CL','CM','CN','CO','CP','CQ','CR','CS','CT','CU','CV','CW','CX','CY','CZ',
		'DA','DB','DC','DD','DE','DF','DG','DH','DI','DJ','DK','DL','DM','DN','DO','DP','DQ','DR','DS','DT','DU','DV','DW','DX','DY','DZ'
		];

		//表头
		$notice = "1、请勿修改表头（1至4行）的内容，红色字体列为必填项。\n2、输入多个互换号用换行或分号;分割，互换号由厂商和号码组成，例如 OE:006 420 68 20;FMSI:D1630\n3、第一个互换号将自动设置为此配件的主要号码。\n4、系统将会按照以下顺序（配件ID、商家编码、第一个互换号）依次判断产品是否存在，如果产品不存在将自动创建。\n5、自定义参数格式（参数名:参数值），多个用用换行或分号;分割， 例如 位置:前轮;制动系统:ATE;宽度:94.8 mm;";
		$objPHPExcel->getActiveSheet()->setCellValue('A1', $notice);
		$objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setWrapText(true);
		$objPHPExcel->getActiveSheet()->mergeCells('A1:Z1');
		$objPHPExcel->getActiveSheet()->getRowDimension('1')->setRowHeight(75);
		
		$col = 0;
		$brow = 2;
		$bcol = $col;
		foreach($colsFiled as $fk=>$fv)
		{
			$objPHPExcel->getActiveSheet()->setCellValue($colIndex[$col].($brow), '基本信息');
			$objPHPExcel->getActiveSheet()->getStyle($colIndex[$col].($brow))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
			$objPHPExcel->getActiveSheet()->setCellValue($colIndex[$col].($brow+1), $fv['name']);
			$objPHPExcel->getActiveSheet()->setCellValue($colIndex[$col].($brow+2), $fv['fname']);
			$objPHPExcel->getActiveSheet()->getColumnDimension($colIndex[$col])->setWidth($fv['width']);
			if(!empty($fv['color']))
			{
				$objPHPExcel->getActiveSheet()->getStyle($colIndex[$col].($brow+1))->getFont()->getColor()->setRGB($fv['color']);
				$objPHPExcel->getActiveSheet()->getStyle($colIndex[$col].($brow+2))->getFont()->getColor()->setRGB($fv['color']);
			}
			$col++;
		}
		//样式
		$cssSet =[
			'font'=> [
				'bold'=> true
			],
		   'fill' =>[
				'type'=> PHPExcel_Style_Fill::FILL_SOLID, 
				'startcolor' => ['argb' => 'FFFFFF00']
			]
		];
		
		$tcol = $colIndex[0].($brow).':'.$colIndex[($col-1)].($brow);
		$objPHPExcel->getActiveSheet()->mergeCells($tcol);
		$objPHPExcel->getActiveSheet()->getStyle($tcol)->applyFromArray($cssSet);

		$tcol = $colIndex[$bcol].($brow+1).':'.$colIndex[($col-1)].($brow+1);
		$objPHPExcel->getActiveSheet()->getStyle($tcol)->applyFromArray($cssSet);
		$cssSet['font']['bold'] = false;
		$tcol = $colIndex[$bcol].($brow+2).':'.$colIndex[($col-1)].($brow+2);
		$objPHPExcel->getActiveSheet()->getStyle($tcol)->applyFromArray($cssSet);

		$i = 0;
		$brow = 5;
		//内容
		foreach($proArr as $v)
		{
			$col = 0;
			foreach($colsFiled as $fk=>$fv)
			{
				$val = isset($v[$fv['fname']]) ? $v[$fv['fname']]: '';
				if($fv['fname'] == 'part_name') $val = !empty($v['pas_name']) ? $v['pas_name']: $v['part_name'];
				$val = is_array($val)? implode("\n", $val): $val;
				$objPHPExcel->getActiveSheet()->setCellValue($colIndex[$col].($brow), $val);
				if(stripos($val, "\n")) $objPHPExcel->getActiveSheet()->getStyle($colIndex[$col].($brow))->getAlignment()->setWrapText(true);
				$col++;
			}
			$brow++;
		}
		$OthExcel->download($objPHPExcel, $filename);
		exit;
	}



	/**
	 * @method   检测excel表格商城配件的数据
	 * @param $shopId int 目录店铺ID
	 * @param $proArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function checkImportB2cItem($shopId, $proArr)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '商铺不存在');
		if(empty($proArr) || !is_array($proArr)) return LibFc::ReturnData(false, '未检测到相关配件数据');
	
		//检查店铺是否存在
		$res = $this->get('sh_shop', ['shop_status'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, 'importProduct 店铺不存在');

		$B2cPart = new B2cPart();
		$B2cBrand = new B2cBrand();
		$B2cShopSort = new B2cShopSort();
		$chkProArr = [];
		$errorArr = [];
		$reArr = ['：'=>';',"；"=>";",","=>";","，"=>";", "\n"=>";"];
		$this->B2CDb->Begin();
		$proids = array_filter(array_column($proArr,'pro_id'));
		$chkReaptArr = [];
		foreach($proArr as $row=>$pro)
		{
			$tempArr = [];
			$tempErr = [];
			$numseq = 0;
			$mainNum = [];
			foreach($pro as $filed=>$val)
			{
				$filed = trim($filed);
				$val = is_array($val) ? $val:trim($val);
				switch($filed)
				{
					case 'pro_id':
						if(!empty($val))
						{
							$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id=%d and pro_shop_id=%d", (int) $val, $shopId), true);
							if(!empty($res['data']))
							{
								$tempArr['base']['pro_id'] = $res['data']['pro_id'];
							}
							else
							{
								$tempErr[] = '配件ID（'.$val.'）不存在。';
							}
						}
					break;
					case 'pro_name':
					case 'pro_sel_des':
						$tempArr['base'][$filed] = $val;
					break;
					case 'ppt_name':
						$tempArr[$filed] = $val;
					break;
					case 'prb_name':
						$tempArr['base']['pro_prb_id'] = 0;	
						if(trim($val) != '')
						{
							$res = $B2cBrand->addShopBrand($shopId, $val);
							$tempArr['base']['pro_prb_id'] = (int) $res['data'];
						}
					break;
					case 'pri_code': //自编号
					case 'pri_self_remark':
						$tempArr['info'][$filed] = $val;
					break;
					case 'number': //互换号 多个逗号分隔
						//全角转半角
						$val = LibFc::GetSemiangle($val);
						$val = strtr($val, [","=>";","\n"=>";"]);
						$main = null;
						$tempArr['nums'] = [];
						foreach(explode(';', $val) as $xk=>$xv)
						{
							$xv = trim($xv, ':');
							$xv = stripos($xv, ':') === false ? 'OE:'.$xv: $xv;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '' && trim($yv[1]) != '')
							{
								$main = $main === null? 1: 0;
								$tempArr['nums'][--$numseq] = ['num_factory'=>$yv[0], 'num_display'=>$yv[1], 'num_ismain'=>$main];
								if($main) $mainNum = $tempArr['nums'][$numseq];
							}
						}
					break;

					case 'pro_sale_price': //销售价
					case 'pro_cost_price': //成本价
					case 'pro_price_vip1': //VIP价
					case 'pro_price_vip2': //VIP价
					case 'pro_price_vip3': //VIP价
					case 'pro_price_vip4': //VIP价
						$tempArr['base'][$filed] = sprintf('%.2f', $val);
					break;

					case 'pro_count':
						$tempArr['base'][$filed] = (int) $val;
					break;
					case 'pro_promoted'://橱窗推荐 Y|N
					case 'pro_user_discount'://店铺VIP Y|N
					case 'pro_manjian'://参与满减 Y|N
					case 'pro_host'://热销 Y|N
						 $tempArr['base'][$filed] = $val == 'Y'? 'Y': 'N';
					break;

					/****扩展表***/
					case 'pri_des': //描叙
						$tempArr['info'][$filed] = str_replace("\n", '<br>', $val);
					break;
					case 'pri_set_inventory': //减库存:0付款减  1拍下减
					case 'pri_invoice': //发票0|1
					case 'pri_warranty': //保修0|1
					case 'pri_return_promise': //保修0|1
						$tempArr['info'][$filed] = $val == 1? 1: 0;
					break;
					case 'pri_weight': //重量KG/件
						$tempArr['info'][$filed] = sprintf('%.2f', $val);
					case 'publish':
						if($val =='立即上架')
						{	// 售卖中
							$tempArr['info']['pri_publish_time'] = time();
							$tempArr['base']['pro_status'] = 1;
						}
						else if(strtotime($val) && strtotime($val)>time())
						{	// 预售
							$tempArr['info']['pri_publish_time'] = strtotime($val);
							$tempArr['base']['pro_status'] = 2;
						}
						else
						{	// 放入仓库
							$tempArr['info']['pri_publish_time'] = 0;
							$tempArr['base']['pro_status'] = 0;
						}
					break;
					case 'part_name': //配件分类
						if(!empty($val))
						{
							$res = $this->checkPart($val,true);
							if(!empty($res['data']))
							{
								$tempArr['base']['pro_part_id'] = (int) $res['data']['part'];
								$tempArr['base']['pro_part_path'] = $res['data']['part_path'];
								$tempArr['base']['pro_pas_id'] = (int) $res['data']['pas_id'];
							}
						}else{
							$tempErr[] = '零件分类不可为空';
						}
					break;
					case 'part_param': //位置:前,后;厚度:16.5mm   删除位置参数(位置:;厚度:16.5mm)
						$val = LibFc::GetSemiangle($val);
						foreach(explode(';', $val) as $xv)
						{
							if(trim($xv) == '') continue;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '')
							{
								$valArr = [];
								foreach(explode(',', $yv[1]) as $kv)
								{
									$kv = trim($kv);
									if($kv != '') $valArr[] = $kv;
								}
								$tempArr['part_param'][] = ['label'=>$yv[0], 'vals'=>$valArr];
							}
							else
							{
								$tempErr[] = '配件分类参数不正确('.$val.')，样例【位置:前,后;厚度:16.5mm   删除位置参数(位置:;厚度:16.5mm】。';
							}
						}
					break;
					case 'freight': //运费模板
						if($val != '')
						{
							$res = $this->get('sh_freight_tpl',['frt_id'],sprintf(" and frt_name='%s' and frt_shop_id=%d ", LibFc::Escape($val), $shopId), true);
							if(!empty($res['data']))
							{
								$tempArr['info']['pri_frt_id'] = $res['data']['frt_id'];
							}
							else
							{
								$tempErr[] = '运费模板不存在('.$val.')。';
							}
						}
					break;
					case 'shop_sort': //店铺分类 多个逗号分隔
						$val = strtr($val, $reArr);
						foreach(explode(';', $val) as $xv)
						{
							if($xv != '')
							{
								$tempArr['shop_sort'][] = $xv;
							}
						}
					break;
					case 'pro_param': //配件自定义参数
						$val = strtr($val, $reArr);
						foreach(explode(';', $val) as $xv)
						{	
							if(trim($xv) == '') continue;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '')
							{
								$tempArr['pro_param'][] = [$yv[0], $yv[1]];
							}
							else
							{
								$tempErr[] = '配件自定义参数不正确('.$val.')，样例【长:100mm;厚度:16.5mm   删除位置参数(长:;厚度:16.5mm】。';
							}
						}
					break;
					case 'pro_dfrom':
						$tempArr['base'][$filed] = $val;
					break;
					case 'pro_dfrom_id':
						$tempArr['base'][$filed] = (int) $val;
					break;
					case 'pro_status':
						if(!$val||$val=='上架'){
							$tempArr['base'][$filed] = 1;
						}elseif($val=='下架'){
							$tempArr['base'][$filed] = 0;
						}
						break;
					case 'pro_add_uid':
						
						if(!empty($val))
						{	
							$res = $this->get('sh_worker',['wor_uid'],sprintf(" AND wor_real_name='%s' AND wor_shop_id=%d",LibFc::Escape($val),$_SESSION['_shopid']),true);
							if($res['data']){
								$tempArr['base'][$filed] = $res['data']['wor_uid'];
							}else{
								$YpwBase = new YpwBase();
								$res = $YpwBase->get('yp_user',['u_id'],sprintf(" AND u_name='%s'",$val),true);
								if($res['data']){
									$tempArr['base'][$filed] = $res['data']['u_id'];
								}
							}
						}
						break;
					case 'pro_set_uid':
						if(!empty($val))
						{
							$res = $this->get('sh_worker',['wor_uid'],sprintf(" AND wor_real_name='%s'",LibFc::Escape($val)),true);
							if($res['data']){
								$tempArr['base'][$filed] = $res['data']['wor_uid'];
							}
						}
						break;

				}
			}

			
			if($tempArr['info']['pri_code']){
				
				$uniqueKey = $tempArr['base']['pro_prb_id'].'_'.$tempArr['info']['pri_code'];
				if(!in_array($uniqueKey,$chkReaptArr)){
					$chkReaptArr[] = $tempArr['base']['pro_prb_id'].'_'.$tempArr['info']['pri_code'];
					//产品id存在时，更改 品牌与商家编码 不可重复
					if($proids && !empty($tempArr['base']['pro_id']))
					{
						$res = $this->get('bc_product join bc_product_info on pro_id=pri_pro_id', ['count(*) as count'], sprintf(" and pro_id not in (%s) and pro_prb_id = %d and pri_code='%s' and pro_shop_id=%d", implode(',', $proids), $tempArr['base']['pro_prb_id'], $tempArr['info']['pri_code'], $shopId), true);
						if ($res['data']['count']) {
							$tempErr[] = '数据库中' .  ($pro['prb_name'] ? '配件品牌:' . $pro['prb_name'] : '') . ' 商家编码:' . $pro['pri_code'] . '存在重复数据';
						}
					}
				}else{
					$tempErr[] = 'xlsx中'.($pro['prb_name']?'配件品牌:'.$pro['prb_name']:'').' 商家编码:'.$pro['pri_code'].'存在重复数据';
				}
			}
			
			if(empty($tempArr['base']['pro_id']) && !empty($tempArr['info']['pri_code']))
			{
				if($tempArr['base']['pro_prb_id'])
				{
					$res = $this->get('bc_product join bc_product_info on pro_id=pri_pro_id',['pro_id as num_pro_id'],sprintf(" and pro_prb_id = %d and pri_code='%s' and pro_shop_id=%d",$tempArr['base']['pro_prb_id'],$tempArr['info']['pri_code'], $shopId),true);
				}
				else
				{
					$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_format='%s' and pro_shop_id=%d", LibFc::FormatNum($tempArr['info']['pri_code']), $shopId), true);
				}
				if(!empty($res['data']))
				{
					$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
				}
			}

			// if(empty($tempArr['base']['pro_id']) && !empty($mainNum))
			// {
			// 	$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_ismain=1', ['num_pro_id'], sprintf(" and num_factory='%s' and num_format='%s' and pro_shop_id=%d", LibFc::Escape($mainNum['num_factory']), LibFc::FormatNum($mainNum['num_display']), $shopId), true);
			// 	if(!empty($res['data']))
			// 	{
			// 		$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
			// 	}
			// }

			if(empty($tempArr['base']['pro_id']) && empty($tempArr['base']['pro_part_id']))
			{
				continue;
			}

			if(!empty($tempErr))
			{
				$errorArr[$row] = $tempErr;
			}
			else
			{
				$tempArr['row'] = $row;
				$chkProArr[] = $tempArr;
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, ['items'=>$chkProArr, 'chkerr'=>$errorArr]);
	}

	/**
	 * @method  将检测后的数据入库
	 * @param $shopId int 目录店铺ID
	 * @param $proArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importB2cItem($shopId, $proArr)
	{
		$this->refresh = false;
		$this->B2CDb->Begin();
		$B2cShopSort = new B2cShopSort();
		$proIdArr = [];
		foreach($proArr as $pro)
		{
			//店铺分类
			if(!empty($pro['shop_sort']))
			{
				$res = $B2cShopSort->getAddShopSortId($shopId, $pro['shop_sort']);
				$sortIdArr = array_values($res['data']);
				$pSortIdArr = $B2cShopSort->getShopParentById($shopId,$sortIdArr);
				$pro['shopSort'] = array_unique(array_merge($sortIdArr,$pSortIdArr['data']));
			}

			//零件参数
			if(!empty($pro['part_param']) && $pro['base']['pro_part_id'] > 0)
			{
				$labelArr = [];
				$res = $this->get('bc_part_param_link join bc_param_label on pal_id=ppl_pal_id', ['pal_id', 'pal_name'], sprintf(" and ppl_part_id=%d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelArr[strtoupper($vv['pal_name'])] = $vv['pal_id'];
				}
				
				$labelValArr = [];
				$res = $this->get('bc_param_value',['pav_id', 'pav_pal_id', 'pav_value'],sprintf(" and pav_part_id = %d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelValArr[$vv['pav_pal_id']][strtoupper($vv['pav_value'])] = $vv['pav_id'];
				}
			
				foreach($pro['part_param'] as $vv)
				{
					if(($palId = $labelArr[strtoupper(trim($vv['label']))]) > 0)
					{
						
						foreach($vv['vals'] as $vvv)
						{
							
							if(($pavId = $labelValArr[$palId][strtoupper(trim($vvv))]) > 0)
							{
								$pro['param'][$palId][] = $pavId;
							}
						}
						if(empty($pro['param'][$palId]))
							$pro['param'][$palId] = implode(',', $vv['vals']);
					}
				}
			}
			unset($pro['part_param']);

			//再次检查自编号是否存在
			if(empty($pro['base']['pro_id']) && !empty($pro['info']['pri_code']))
			{
				if($pro['base']['pro_prb_id'])
				{
					$res = $this->get('bc_product join bc_product_info on pro_id = pri_pro_id',['pro_id as num_pro_id'],sprintf(" and pro_prb_id = %d and pri_code='%s' and pro_shop_id=%d",$pro['base']['pro_prb_id'],$pro['info']['pri_code'] ,$shopId),true);
				}
				else
				{
					$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_format='%s' and pro_shop_id=%d",LibFc::FormatNum($pro['info']['pri_code']), $shopId), true);
				}

				if(!empty($res['data']))
				{
					$pro['base']['pro_id'] = $res['data']['num_pro_id'];
				}
			}

			if(empty($pro['base']['pro_id']))
			{
				$pro['base']['pro_show_b2c'] = 1;
				$pro['base']['pro_show_app'] = 1;
				$pro['base']['pro_shop_id'] = $shopId;
				$pro['base']['pro_count'] = empty($pro['base']['pro_count'])? 1: $pro['base']['pro_count'];

				//运费模板
				if(empty($pro['info']['pri_frt_id']))
				{
					$res = $this->get('sh_freight_tpl',['frt_id'],sprintf(" and frt_shop_id=%d order by frt_default desc", $shopId), true);
					if(!empty($res['data']))
					{
						$pro['info']['pri_frt_id'] = $res['data']['frt_id'];
					}
				}
				$res = $this->addProduct($pro,$shopId);
				$pro['base']['pro_id'] = $res['data'];
			}
			else
			{
				$this->setProduct($shopId, $pro['base']['pro_id'], $pro);
			}
			if(!empty($pro['pro_param']))
				$this->setBatchParam($pro['base']['pro_id'], $shopId, $pro['pro_param'],$pro['ppt_name']);

			$proIdArr[] = $pro['base']['pro_id'];
		}
		$B2cKeyword = new B2cKeyword();
		$B2cKeyword->resetProductKeyword($proIdArr);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $proIdArr);
	}






	/**
	 * @method  导出品牌目录产品
	 * @author	soul
	 * @copyright 2019/9/2
	 */
	public function exportSupertItem($colsFiled, $partIdArr, $proArr = [], $filename = '')
	{	
		if(empty($colsFiled))
			$colsFiled = [
				['name'=>'配件ID', 'fname'=>'pro_id', 'width'=>10],	
				['name'=>'零件分类', 'fname'=>'part_name', 'color'=>'FF0000', 'width'=>20],	
				['name'=>'配件名称', 'fname'=>'pro_name', 'width'=>30],	
				['name'=>'配件品牌', 'fname'=>'prb_name', 'width'=>15],	
				['name'=>'商家编码', 'fname'=>'pri_code', 'color'=>'FF0000', 'width'=>20],	
				['name'=>'互换号', 'fname'=>'number', 'width'=>30],
				['name'=>'配件关键字', 'fname'=>'pri_keyword', 'width'=>30],
				['name'=>'配件状态', 'fname'=>'pro_status', 'width'=>10],
                ['name'=>'自定义参数模板名', 'fname'=>'ppt_name', 'width'=>30],
                ['name'=>'自定义参数', 'fname'=>'pro_param', 'width'=>30],
				['name'=>'配件卖点', 'fname'=>'pro_sel_des', 'width'=>30],
                ['name'=>'商家备注', 'fname'=>'pri_self_remark', 'width'=>30],
			];
		$partParaArr = [];
		if(!empty($partIdArr))
		{
			$res = $this->get('bc_part', ['part_id','part_name'], sprintf(" and part_id in(%s) order by part_name", implode(',', $partIdArr)));
			foreach($res['data'] as $v)
			{
				$partParaArr[$v['part_id']] = [
					'base'=>$v,
					'label'=>[]
				];
			}
			$table = 'bc_part_param_link join bc_part on ppl_part_id = part_id join bc_param_label on ppl_pal_id=pal_id left join bc_param_unit on ppl_pau_id = pau_id';
			$res = $this->get($table, ['part_id','part_name', 'pal_id', 'pal_name', 'pau_name'], sprintf(" and ppl_part_id in(%s) order by part_name, ppl_seq", implode(',', $partIdArr)));
			foreach($res['data'] as $v)
			{
				$partParaArr[$v['part_id']]['label'][$v['pal_id']] = ['id'=>'para_'.$v['pal_id'], 'name'=>$v['pal_name'].(empty($v['pau_name'])? '': '['.$v['pau_name'].']')];
			}
		}

		$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
		$objSheet = $spreadsheet->getActiveSheet();  //获取当前操作sheet的对象
		// $OthExcel = new OthExcel();
		// $objPHPExcel = new PHPExcel();
		// $objPHPExcel->getProperties()->setTitle('export')->setDescription('none');
		// $objPHPExcel->setActiveSheetIndex(0);
		//左对齐
		// $objPHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
	
		$colIndex = [ 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
		'AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ',
		'BA','BB','BC','BD','BE','BF','BG','BH','BI','BJ','BK','BL','BM','BN','BO','BP','BQ','BR','BS','BT','BU','BV','BW','BX','BY','BZ',
		'CA','CB','CC','CD','CE','CF','CG','CH','CI','CJ','CK','CL','CM','CN','CO','CP','CQ','CR','CS','CT','CU','CV','CW','CX','CY','CZ',
		'DA','DB','DC','DD','DE','DF','DG','DH','DI','DJ','DK','DL','DM','DN','DO','DP','DQ','DR','DS','DT','DU','DV','DW','DX','DY','DZ'
		];

		//表头
		$notice = "1、请勿修改表头（1至4行）的内容，红色字体列为必填项。\n2、输入多个互换号用换行或分号;分割，互换号由厂商和号码组成，例如 OE:006 420 68 20;FMSI:D1630\n3、第一个互换号将自动设置为此配件的主要号码。\n4、系统将会按照以下顺序（配件ID、商家编码、第一个互换号）依次判断产品是否存在，如果产品不存在将自动创建。\n5、配件参数（跑街官方定义）格式（参数名:参数值）， 例如 位置:前轮;制动系统:ATE;宽度:94.8 mm。\n6、自定义参数格式（参数名:参数值），多个用用换行或分号;分割， 例如 位置:前轮;制动系统:ATE;宽度:94.8 mm。\n7、多个关键字逗号分隔（如:刹车皮,摩擦片）";
		$objSheet->setCellValue('A1', $notice);
		$objSheet->getStyle('A1')->getAlignment()->setWrapText(true);
		$objSheet->mergeCells('A1:Z1');
		$objSheet->getRowDimension('1')->setRowHeight(90);
		
		$col = 0;
		$brow = 2;
		$bcol = $col;
		foreach($colsFiled as $fk=>$fv)
		{
			$objSheet->setCellValue($colIndex[$col].($brow), '基本信息');
			$objSheet->getStyle($colIndex[$col].($brow))->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
			$objSheet->setCellValue($colIndex[$col].($brow+1), $fv['name']);
			$objSheet->setCellValue($colIndex[$col].($brow+2), $fv['fname']);
			$objSheet->getColumnDimension($colIndex[$col])->setWidth($fv['width']);
			if(!empty($fv['color']))
			{
				$objSheet->getStyle($colIndex[$col].($brow+1))->getFont()->getColor()->setRGB($fv['color']);
				$objSheet->getStyle($colIndex[$col].($brow+2))->getFont()->getColor()->setRGB($fv['color']);
			}
			$col++;
		}
		//样式
		$cssSet =[
			'font'=> [
				'bold'=> true
			],
			'fill' => [
				'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, // 设置填充类型为纯色
				'startColor' => ['rgb' => 'FFFF00'] // 设置填充颜色为浅黄色
			],
		];

		
		
		$tcol = $colIndex[0].($brow).':'.$colIndex[($col-1)].($brow);
		$objSheet->mergeCells($tcol);
		$objSheet->getStyle($tcol)->applyFromArray($cssSet);

		$tcol = $colIndex[$bcol].($brow+1).':'.$colIndex[($col-1)].($brow+1);
		$objSheet->getStyle($tcol)->applyFromArray($cssSet);
		$cssSet['font']['bold'] = false;
		$tcol = $colIndex[$bcol].($brow+2).':'.$colIndex[($col-1)].($brow+2);
		$objSheet->getStyle($tcol)->applyFromArray($cssSet);
		

		//零件参数
		//不同零件变色
		$color = ['F0FFE3E3', 'FFCCFFFF'];
		$i = 0;
		foreach($partParaArr as $partId=>$partV)
		{
			$bcol = $col;
			$objSheet->setCellValue($colIndex[$col].($brow), $partV['base']['part_name']);
			if(!empty($partV['label']))
			{
				foreach($partV['label'] as $palId=>$palV)
				{
					$objSheet->setCellValue($colIndex[$col].($brow+1), $palV['name']);
					$objSheet->setCellValue($colIndex[$col].($brow+2), $palV['id']);
					$objSheet->getColumnDimension($colIndex[$col])->setWidth(15);
					$col++;
				}
				// $color[$i%2]
				$cssSet =[
					'font'=> [
						'bold'=> true
					],
				   'fill' =>[
						'fillType'=> \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 
						'startcolor' => ['rgb' => $color[$i%2]]
				   ],
				   'borders' => [
						'allBorders' => [ // 设置所有边框
							'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, // 边框样式为细线
							'color' => ['rgb' =>  $color[$i%2]] // 边框颜色为黑色
						],
					],
				];
				$tcol = $colIndex[$bcol].($brow).':'.$colIndex[($col-1)].($brow);
				
				$objSheet->mergeCells($tcol);
				$objSheet->getStyle($tcol)->applyFromArray($cssSet);
				$objSheet->getStyle($colIndex[$bcol].($brow))->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
				

				$tcol = $colIndex[$bcol].($brow+1).':'.$colIndex[($col-1)].($brow+1);
				$objSheet->getStyle($tcol)->applyFromArray($cssSet);

				$cssSet['font']['bold'] = false;
				$tcol = $colIndex[$bcol].($brow+2).':'.$colIndex[($col-1)].($brow+2);
				$objSheet->getStyle($tcol)->applyFromArray($cssSet);
			}
			//样式
			$i++;
		}
		
		function processBatchData($batchData, $colsFiled, $partParaArr, $colIndex, &$wrapTextRanges, &$brow) {
			foreach ($batchData as $v) {
				$row = [];
				$col = 0;

				// 写入主数据
				foreach ($colsFiled as $fk => $fv) {
					$val = isset($v[$fv['fname']]) ? $v[$fv['fname']] : '';
					if ($fv['fname'] == 'part_name') {
						$val = !empty($v['pas_name']) ? $v['pas_name'] : $v['part_name'];
					}
					$val = is_array($val) ? implode("\n", $val) : $val;
					$row[$col] = $val;

					// 如果值中包含 \n，记录单元格范围
					if (stripos($val, "\n") !== false) {
						$wrapTextRanges[] = $colIndex[$col] . $brow;
					}
					$col++;
				}

				// 写入 partParaArr 数据
				foreach ($partParaArr as $partId => $partV) {
					foreach ($partV['label'] as $palId => $palV) {
						$val = isset($v['para'][$palV['id']]) ? $v['para'][$palV['id']] : '';
						$row[$col] = $val;
						$col++;
					}
				}

				$brow++; // 更新行号
				yield $row; // 使用 yield 返回当前行
			}
		}

		// 主逻辑
		$brow = 5;
		$batchSize = 1000; // 每次处理 1000 条数据
		$totalRows = count($proArr);

		for ($i = 0; $i < $totalRows; $i += $batchSize) {
			$batchData = array_slice($proArr, $i, $batchSize); // 获取当前批次数据
			$data = [];
			$wrapTextRanges = [];
			$startRow = $brow; // 记录当前批次的起始行号
			// 使用生成器逐行处理数据
			foreach (processBatchData($batchData, $colsFiled, $partParaArr, $colIndex, $wrapTextRanges, $brow) as $row) {
				$data[] = $row;
			}

			// 批量写入数据到表格
			if (!empty($data)) {
				$objSheet->fromArray($data, null, 'A' . $startRow);
			}
			// 批量设置换行样式
			if (!empty($wrapTextRanges)) {
				foreach ($wrapTextRanges as $cell) {
					$objSheet->getStyle($cell)->getAlignment()->setWrapText(true);
				}
			}

			
		}

		// 输出文件
		ob_clean();
		if (empty($filename)) {
			$filename = sprintf('%d.xlsx', time());
		}
		header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
		header('Content-Disposition: attachment;filename="' . $filename . '"');
		header('Cache-Control: max-age=0');
		$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
		$writer->save('php://output');

		// 释放内存
		$spreadsheet->disconnectWorksheets();
		unset($spreadsheet);
	}


	/**
	 * @method   检测excel表格目录配件的数据
	 * @param $shopId int 目录店铺ID
	 * @param $proArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function checkImportSuperItem($shopId, $proArr)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '目录不存在');
		if(empty($proArr) || !is_array($proArr)) return LibFc::ReturnData(false, 'importSuperItem 产品参数不正确');
			
		//检查目录是否存在
		$res = $this->get('sh_super', ['*'], sprintf(" and ssu_shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, '目录不存在');
		$supArr = $res['data'];
		
		//查询此目录开通的零件分类和包含的参数名称
		$B2cPart = new B2cPart();
		$res = $B2cPart->getShopSuperSPart($shopId);
		$partIdArr = array_column($res['data'], 'part_id');
		// if(empty($partIdArr)) return LibFc::ReturnData(false, '请先开通目录支持的配件分类');
		if(!empty($partIdArr))
		{
			$partNameArr = [];
			foreach($res['data'] as $v)
			{
				$partNameArr[strtoupper($v['name'])] = $v;
			}
			$res = $this->get('bc_part_param_link', ['*'], sprintf(" and ppl_part_id in(%s)", implode(',', $partIdArr)));
			$partParaArr = [];
			foreach($res['data'] as $v)
			{
				$partParaArr[$v['ppl_part_id']][$v['ppl_pal_id']] = $v;
			}
		}

		$B2cBrand = new B2cBrand();
		$chkProArr = [];
		$errorArr = [];
		$reArr = ['：'=>';',"；"=>";",","=>";","，"=>";", "\n"=>";"];
		$this->B2CDb->Begin();
		$chkReaptArr = [];
		$proids = array_filter(array_column($proArr,'pro_id'));
		foreach($proArr as $row=>$pro)
		{
			$tempArr = [];
			$tempErr = [];
			$numseq = 0;
			$mainNum = [];
			foreach($pro as $filed=>$val)
			{
				$filed = trim($filed);
				$val = is_array($val) ? $val:trim($val);
				switch($filed)
				{
					case 'pro_id':
						if(!empty($val))
						{
							$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id=%d and pro_shop_id=%d", (int) $val, $shopId), true);
							if(!empty($res['data']))
							{
								$tempArr['base']['pro_id'] = $res['data']['pro_id'];
							}
							else
							{
								$tempErr[] = '配件ID（'.$val.'）不存在。';
							}
						}
					break;
					case 'pro_name':
						if(mb_strlen($val)>255){
							$tempErr[] = '超过限制长度';
						}else{
							$tempArr['base'][$filed] = $val;
						}
						break;
					case 'pro_sel_des':
						$tempArr['base'][$filed] = $val;
					break;
					case 'ppt_name':
						$tempArr[$filed] = $val;
					break;
					case 'prb_name':
						$tempArr['base']['pro_prb_id'] = 0;	
						if(trim($val) != '')
						{
							$res = $B2cBrand->addShopBrand($shopId, $val);
							$tempArr['base']['pro_prb_id'] = (int) $res['data'];
						}
					break;
					case 'pri_des': //描述
						$tempArr['info'][$filed] = str_replace("\n", '<br>', $val);
						break;
					case 'pri_code': //自编号
					case 'pri_keyword':
						$tempArr['info'][$filed] = $val;
					break;
					case 'pri_self_remark':
						if(mb_strlen($val)>255){
							$tempErr[] = '超过限制长度';
						}else{
							$tempArr['info'][$filed] = $val;
						}
					break;
					case 'part_name': //配件分类
						if(!empty($val))
						{
							if(empty($partIdArr))
							{
								$res = $this->checkPart($val,true);
								if(!empty($res['data']))
								{
									$tempArr['base']['pro_part_id'] = (int) $res['data']['part'];
									$tempArr['base']['pro_part_path'] = $res['data']['part_path'];
									$tempArr['base']['pro_pas_id'] = (int) $res['data']['pas_id'];
								}
							}
							else
							{
								if(!empty($partNameArr[strtoupper($val)]))
								{	
									$tempArr['base']['pro_part_path'] = $partNameArr[strtoupper($val)]['pt_path'].','.$partNameArr[strtoupper($val)]['part_id'];
									$tempArr['base']['pro_part_id'] = $partNameArr[strtoupper($val)]['part_id'];
									$tempArr['base']['pro_pas_id'] = (int) $partNameArr[strtoupper($val)]['pas_id'];
								}
								else
								{
									$tempErr[] = '配件分类（'.$val.'）不存在。';
								}
							}
						}
						else{
							$tempErr[] = '零件分类不可为空';
						}
					break;
					case 'part_param':
						if(!empty($tempArr['base']['pro_part_id']) && !empty($partParaArr[$tempArr['base']['pro_part_id']]))
						{
							$tempArr['param'] = [];
							foreach($partParaArr[$tempArr['base']['pro_part_id']] as $palId=>$palV)
							{
								$tempArr['param'][$palId] = '';
								if(isset($val[$palId]) && $val[$palId] !== null && trim($val[$palId]) != '')
								{
									$tempArr['param'][$palId] = $val[$palId];
								}
							}
						}
					break;
					case 'number': //互换号 多个逗号分隔
						//全角转半角
						$val = LibFc::GetSemiangle($val);
						$val = strtr($val, [","=>";","\n"=>";"]);
						$main = null;
						$tempArr['nums'] = [];
						foreach(explode(';', $val) as $xk=>$xv)
						{
							$xv = trim($xv, ':');
							$xv = stripos($xv, ':') === false ? 'OE:'.$xv: $xv;
							$yv = explode(':', $xv);
							if(count($yv) >= 2 && trim($yv[0]) != '' && trim($yv[1]) != '')
							{	
								//如果匹配到跟商家编码+商品品牌一致的数据就跳过，编码后面新增时数据库报错
								if($yv[0] == $pro['prb_name'] && LibFc::FormatNum($yv[1]) == LibFc::FormatNum($pro['pri_code'])){
									continue;
								}
								$main = $main === null? 1: 0;
								$tempArr['nums'][--$numseq] = ['num_factory'=>$yv[0], 'num_display'=>$yv[1], 'num_ismain'=>$main];
								if($main) $mainNum = $tempArr['nums'][$numseq];
							}
						}
					break;
                    case 'pro_param': //配件自定义参数
                        $val = strtr($val, $reArr);
                        foreach(explode(';', $val) as $xv)
                        {
                            if(trim($xv) == '') continue;
                            $yv = explode(':', $xv);
                            if(count($yv) >= 2 && trim($yv[0]) != '')
                            {
                                $tempArr['pro_param'][] = [$yv[0], $yv[1]];
                            }
                            else
                            {
                                $tempErr[] = '配件自定义参数不正确('.$val.')，样例【长:100mm;厚度:16.5mm   删除位置参数(长:;厚度:16.5mm】。';
                            }
                        }
                        break;
					case 'shop_sort': //店铺分类 多个逗号分隔
						$val = strtr($val, $reArr);
						foreach (explode(';', $val) as $xv) {
							if ($xv != '') {
								$tempArr['shop_sort'][] = $xv;
							}
						}
						break;
					case 'pro_sale_price': //销售价
					case 'pro_price_vip1': //VIP价
					case 'pro_price_vip2': //VIP价
					case 'pro_price_vip3': //VIP价
					case 'pro_price_vip4': //VIP价
						$tempArr['base'][$filed] = sprintf('%.2f', $val);
						break;
					case 'pro_count':
						$tempArr['base'][$filed] = (int) $val;
						break;
					case 'param': //
						$val = LibFc::GetSemiangle($val);
						$val = strtr($val, $reArr);
						foreach (explode(';', $val) as $xv) {
							if (trim($xv) == '') continue;
							$yv = explode(':', $xv);
							if (count($yv) >= 2 && trim($yv[0]) != '') {
								$valArr = [];
								foreach (explode(',', $yv[1]) as $kv) {
									preg_match('/(\d+\.?\d*)/',trim($kv),$str) ;
									$kv =  $str[0];
									if ($kv != '') $valArr[] = $kv;
								}
								$tempArr['part_param'][] = ['label' => $yv[0], 'vals' => $valArr];
							} else {
								$tempErr[] = '配件分类参数不正确(' . $val . ')，样例【位置:前,后;厚度:16.5mm   删除位置参数(位置:;厚度:16.5mm】。';
							}
						}
						break;
					case 'pro_status':
						if(!$val||$val=='上架'){
							$tempArr['base'][$filed] = 1;
						}elseif($val=='下架'){
							$tempArr['base'][$filed] = 0;
						}
						break;
					case 'pro_add_uid':
						
						if(!empty($val))
						{	
							$res = $this->get('sh_worker',['wor_uid'],sprintf(" AND wor_real_name='%s' AND wor_shop_id=%d",LibFc::Escape($val),$_SESSION['_shopid']),true);
							if($res['data']){
								$tempArr['base'][$filed] = $res['data']['wor_uid'];
							}else{
								$YpwBase = new YpwBase();
								$res = $YpwBase->get('yp_user',['u_id'],sprintf(" AND u_name='%s'",$val),true);
								if($res['data']){
									$tempArr['base'][$filed] = $res['data']['u_id'];
								}
							}
						}
						break;
					case 'pro_set_uid':
						if(!empty($val))
						{
							$res = $this->get('sh_worker',['wor_uid'],sprintf(" AND wor_real_name='%s'",LibFc::Escape($val)),true);
							if($res['data']){
								$tempArr['base'][$filed] = $res['data']['wor_uid'];
							}
						}
						break;
				}
			}
			
			if($tempArr['info']['pri_code'] ){
				
				$uniqueKey = $tempArr['base']['pro_prb_id'].'_'.$tempArr['info']['pri_code'];
				if(!in_array($uniqueKey,$chkReaptArr)){
					$chkReaptArr[] = $tempArr['base']['pro_prb_id'].'_'.$tempArr['info']['pri_code'];
					//产品id存在时，更改 品牌与商家编码 不可重复
					if($proids && !empty($tempArr['base']['pro_id']))
					{
						$res = $this->get('bc_product join bc_product_info on pro_id=pri_pro_id', ['count(*) as count'], sprintf(" and pro_id not in (%s) and pro_prb_id = %d and pri_code='%s' and pro_shop_id=%d", implode(',', $proids), $tempArr['base']['pro_prb_id'], $tempArr['info']['pri_code'], $shopId), true);
						if ($res['data']['count']) {
							$tempErr[] = '数据库中' .  ($pro['prb_name'] ? '配件品牌:' . $pro['prb_name'] : '') . ' 商家编码:' . $pro['pri_code'] . '存在重复数据';
						}
					}
				}else{
					
					$tempErr[] = 'xlsx中'.($pro['prb_name']?'配件品牌:'.$pro['prb_name']:'').' 商家编码:'.$pro['pri_code'].'存在重复数据';
				}
			}
			if(empty($tempArr['base']['pro_id']) && !empty($tempArr['info']['pri_code']))
			{
				if($tempArr['base']['pro_prb_id'])
				{
					$res = $this->get('bc_product join bc_product_info on pri_pro_id=pro_id', ['pro_id as num_pro_id'], sprintf(" and pro_prb_id = %d and pri_code='%s' and pro_shop_id=%d",$tempArr['base']['pro_prb_id'], $tempArr['info']['pri_code'], $shopId), true);
				}
				else
				{
					$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_format='%s' and pro_shop_id=%d",LibFc::FormatNum($tempArr['info']['pri_code']), $shopId), true);
				}
				if(!empty($res['data']))
				{
					$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
				}
			}

			// if(empty($tempArr['base']['pro_id']) && !empty($mainNum))
			// {
			// 	$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_ismain=1', ['num_pro_id'], sprintf(" and num_factory='%s' and num_format='%s' and pro_shop_id=%d", LibFc::Escape($mainNum['num_factory']), LibFc::FormatNum($mainNum['num_display']), $shopId), true);
			// 	if(!empty($res['data']))
			// 	{
			// 		$tempArr['base']['pro_id'] = $res['data']['num_pro_id'];
			// 	}
			// }

			if(!empty($tempErr))
			{
				if(empty($tempArr['base']['pro_id']) && empty($tempArr['info']['pri_code']) && empty($tempArr['info']['part_name']))
				{}
				else
				{
					$errorArr[$row] = $tempErr;
				}
			}
			else if(!empty($tempArr['base']['pro_id']) || !empty($tempArr['info']['pri_code']))
			{
				$tempArr['row'] = $row;
				$chkProArr[] = $tempArr;
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, ['items'=>$chkProArr, 'chkerr'=>$errorArr]);
	}

	/**
	 * @method  将检测后的数据入库
	 * @param $shopId int 目录店铺ID
	 * @param $proArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importSuperItem($shopId, $proArr)
	{
		$this->refresh = false;
		$this->B2CDb->Begin();
		$B2cShopSort = new B2cShopSort();
		$proIdArr = [];
		foreach($proArr as $pro)
		{
			//店铺分类
			if(!empty($pro['shop_sort']))
			{
				$res = $B2cShopSort->getAddShopSortId($shopId, $pro['shop_sort']);
				$sortIdArr = array_values($res['data']);
				$pSortIdArr = $B2cShopSort->getShopParentById($shopId,$sortIdArr);
				$pro['shopSort'] =array_unique(array_merge($sortIdArr,$pSortIdArr['data']));
			}
			//零件参数
			if(!empty($pro['part_param']) && $pro['base']['pro_part_id'] > 0)
			{
				$labelArr = [];
				$res = $this->get('bc_part_param_link join bc_param_label on pal_id=ppl_pal_id', ['pal_id', 'pal_name'], sprintf(" and ppl_part_id=%d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelArr[strtoupper($vv['pal_name'])] = $vv['pal_id'];
				}
				
				$labelValArr = [];
				$res = $this->get('bc_param_value',['pav_id', 'pav_pal_id', 'pav_value'],sprintf(" and pav_part_id = %d", $pro['base']['pro_part_id']));
				foreach($res['data'] as $vv)
				{
					$labelValArr[$vv['pav_pal_id']][strtoupper($vv['pav_value'])] = $vv['pav_id'];
				}
			
				foreach($pro['part_param'] as $vv)
				{
					if(($palId = $labelArr[strtoupper(trim($vv['label']))]) > 0)
					{
						
						foreach($vv['vals'] as $vvv)
						{
							
							if(($pavId = $labelValArr[$palId][strtoupper(trim($vvv))]) > 0)
							{
								$pro['param'][$palId][] = $pavId;
							}
						}
						if(empty($pro['param'][$palId]))
							$pro['param'][$palId] = implode(',', $vv['vals']);
					}
				}
			}
			unset($pro['part_param']);
			//再次检查自编号是否存在
			if(empty($pro['base']['pro_id']) && !empty($pro['info']['pri_code']))
			{
				if($pro['base']['pro_prb_id'])
				{
					$res = $this->get('bc_product join bc_product_info on pro_id = pri_pro_id', ['pro_id as num_pro_id'],sprintf(" and pro_prb_id=%d and pri_code ='%s' and pro_shop_id=%d",$pro['base']['pro_prb_id'], $pro['info']['pri_code'], $shopId),true);
				}
				else
				{
					$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id'], sprintf(" and num_factory='%s' and num_format='%s' and pro_shop_id=%d",LibFc::Escape($pro['factory']), LibFc::FormatNum($pro['info']['pri_code']), $shopId), true);
				}

				if(!empty($res['data']))
				{
					$pro['base']['pro_id'] = $res['data']['num_pro_id'];
				}
			}

			if(empty($pro['base']['pro_id']))
			{
				if(!empty($pro['info']['pri_code']))
				{
					$pro['base']['pro_show_super'] = 1;
					$pro['base']['pro_shop_id'] = $shopId;
					$res = $this->addProduct($pro,$shopId);
					$pro['base']['pro_id'] = $res['data'];
				}
			}
			else
			{
				$this->setProduct($shopId, $pro['base']['pro_id'], $pro);
			}
			if($pro['base']['pro_id'])
			{
				if(!empty($pro['pro_param']))
					$this->setBatchParam($pro['base']['pro_id'], $shopId, $pro['pro_param'], $pro['ppt_name']);
				$proIdArr[] = $pro['base']['pro_id'];
			}
		}
		$B2cKeyword = new B2cKeyword();
		$B2cKeyword->resetProductKeyword($proIdArr);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $proIdArr);
	}


	/**
	 * @method  将检测后的数据入库
	 * @param $shopId int 目录店铺ID
	 * @param $type 更新模式 增量式：add 替换式：replace
	 * @param $proIdArr 
	 * @param $log 记录
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function refreshItemModel($shopId, $type, $proIdArr)
	{
		if(!empty($shopId) && !empty($type) && !empty($proIdArr))
		{
			foreach($proIdArr as $k=>$v)
			{
				$proIdArr[$k] = (int) $v;
			}
			
			$where = sprintf(" and pro_shop_id=%d and (pro_smt_code = '' or pro_smt_code = 'all') and num_self=0 and num_pro_id in (%s)", $shopId, implode(',', $proIdArr));
			$proArr = [];
			$res = $this->get('bc_number join bc_product on pro_id = num_pro_id', ['pro_part_id', 'pro_pas_id', 'num_pro_id', 'num_factory', 'num_display'], $where);
			if(empty($res['data'])) return LibFc::ReturnData(true);
	
			foreach($res['data'] as $v)
			{
				$proArr[$v['num_pro_id']]['base'] = $v;
				$proArr[$v['num_pro_id']]['nums'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display']];
			}
			
			//增量式，合并旧的
			if($type == 'add')
			{
				$res = $this->get('bc_product_model3_link', ['*'], sprintf(" and pml3_pro_id in (%s)", implode(',', array_keys($proArr))));
				foreach($res['data'] as $v)
				{
					$proArr[$v['pml3_pro_id']]['mod3'][] = $v['pml3_mod3_id'];
				}
			}

			$this->B2CDb->Begin();

			$LibYpApi = new LibYpApi();
			foreach($proArr as $proId=>$v)
			{
				$res = $LibYpApi->Get('ypc/getModelByYpcNum', [], ['nums'=>$v['nums'], 'spartId'=>$v['base']['pro_part_id'].'_'.$v['base']['pro_pas_id']]);
				if(!empty($res['data']))
				{
					$mod3IdArr = empty($proArr[$proId]['mod3']) ? $res['data']: array_merge($proArr[$proId]['mod3'], $res['data']);
					$this->setProductModel($proId, $mod3IdArr, 'NUMBER');
				}
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true);
	}



	/**
	 * @method  将检测后的数据入库
	 * @param $shopId int 目录店铺ID
	 * @param $type 更新模式 增量式：add 替换式：replace
	 * @param $facArr ['FMSI','TRW','AK']
	 * @param $proIdArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function refreshYpItem($shopId, $type, $facArr, $proIdArr)
	{
		if(!empty($shopId) && !empty($type) && !empty($proIdArr) && !empty($facArr))
		{
			foreach($proIdArr as $k=>$v)
			{
				$proIdArr[$k] = (int) $v;
			}

			foreach($facArr as $k=>$v)
			{
				$v = strtoupper(LibFc::Escape($v));
				$facArr[$k] = $v;
			}

			$where = sprintf(" and pro_shop_id=%d and num_show=1 and num_pro_id in (%s) and UPPER(num_factory) in ('%s')", $shopId, implode(',', $proIdArr), implode("','", $facArr));
			$proArr = [];
			$res = $this->get('bc_number join bc_product on pro_id = num_pro_id', ['num_pro_id', 'upper(num_factory) num_factory', 'num_format'], $where);
			if(empty($res['data'])) return LibFc::ReturnData(true);
	
			foreach($res['data'] as $v)
			{
				$proArr[$v['num_pro_id']]['newNums'] = [];
				$proArr[$v['num_pro_id']]['nums'][$v['num_factory']][] = $v['num_format'];
			}
			
			//查找宜配对应的产品
			$YpBase = new YpBase();
			foreach($proArr as $proId=>$pv)
			{
				$proArr[$proId]['yp'] = [];
				foreach($facArr as $fac)
				{
					if(empty($pv['nums'][$fac])) continue;
					foreach($pv['nums'][$fac] as $num)
					{
						$where = sprintf(" and upper(f.factory) ='%s' and n.format ='%s' group by pid", $fac, $num);
						$res = $YpBase->Get('yp_number AS n JOIN yp_factory AS f ON n.fid=f.fid', ['pid, factory, display'], $where);
						if(!empty($res['data'])){
							$proArr[$proId]['yp'] = $res['data'];
							break;
						}
					}
					if(!empty($proArr[$proId]['yp'])) break;
				}
			}

			$where = sprintf(" and num_self=0 and num_pro_id in (%s)", implode(',', array_keys($proArr)));
			//替换式的只需要显示的号码
			if($type == 'replace') $where .= ' and num_show = 0';
			$res = $this->get('bc_number', ['*'], $where);
			foreach($res['data'] as $v)
			{
				$proArr[$v['num_pro_id']]['newNums'][] = $v;
			}
			
			$this->B2CDb->Begin();
			foreach($proArr as $proId=>$pv)
			{
				if(count($pv['yp']) == 1)
				{
					$fromProId = $pv['yp'][0]['pid'];
					$ypres = $YpBase->Get('yp_number AS n JOIN yp_factory AS f ON n.fid=f.fid', ['f.factory, n.display'], sprintf(" and n.pid=%d", $fromProId));
					foreach($ypres['data'] as $yv)
					{
						$pv['newNums'][] = [
							'num_factory'=>$yv['factory'],
							'num_display'=>$yv['display'],
							'num_show'=>0,
							'num_from'=>'yp',
							'num_fromid'=>$fromProId
						];
					}
					$this->setProductNum($proId, $pv['newNums']);
				}
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true);
	}



	/**
	 * @method   检测图片包的产品图片
	 * @param $shopId int 目录店铺ID
	 * @param $optArr [dir: xxx, ext: zip, filename: 149894_03872305d4fd51e53fd1ea9a4f9f6146, split:@]
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function checkImportItemImgZip($shopId, $optArr)
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$optArr['split'] = empty($optArr['split'])? '@(': str_replace(' ', '', $optArr['split']);
		$reg = '\\'.implode('\\', str_split($optArr['split']));
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$maxsize = 3;
		//解压，遍历文件夹
		$ext = strtolower(trim($optArr['ext']));
		if(!in_array($ext, ['zip', 'rar'])) return LibFc::ReturnData(false, '不支持'.$ext.'的压缩包！');
		$zipFile = $optArr['dir'].$optArr['filename'].'.'.$ext;
		$arr = ['imgs'=>0, 'items'=>[], 'nopro'=>[], 'chkerr'=>[]];
		if(file_exists($zipFile))
		{
			$toname = 'imgs_'.$optArr['filename'];
			$arr['dir'] = $toname.'/';
			$imgDir = $optArr['dir'].$arr['dir'];
			@mkdir($imgDir);
			
			if($optArr['ext'] == 'zip')
			{
				$zip = new ZipArchive();
				if($zip->open($zipFile) !==TRUE) return LibFc::ReturnData(false, '解压失败，请稍后重试！');
				$zip->extractTo($imgDir);
				$zip->close();
			}
			else
			{
				$rar = @rar_open($zipFile);
				if ($rar)
				{
					$entries = @rar_list($rar);
					if(!$entries) return LibFc::ReturnData(false, '解压失败，请检查压缩包！');
					foreach ($entries as $entry)
					{
						$entry->extract($imgDir);
					}
					@rar_close($rar);
				}
			}
			
			$imgFileArr = $this->getAllFile($imgDir);
			sort($imgFileArr);

			$timgArr = [];
			// $arr['imgs'] = count($imgFileArr);
			$sort = [];
			$chkNumToPidArr = [];
			foreach($imgFileArr as $k=>$orgfile)
			{
				$arr['imgs']++;
				$filepath = ltrim(str_replace($imgDir, '', $orgfile), '/');
				$size = filesize($orgfile)/1024/1024;
				if($size > $maxsize){
					$arr['chkerr'][] = $filepath.' 文件超过最大'.$maxsize.'M限制';
					continue;
				}
				$vArr = LibFc::GetPathInfo($filepath);
				if(!in_array($vArr['ext'], ['jpg','jpeg','png', 'gif'])) continue;
				$reArr = ['＠'=>'@', '＃'=>'#','＆'=>'&','（'=>'(', '）'=>')', '——'=>'-', '－'=>'-', '【'=>'[', '】'=>']', '｜'=>'|', '＼'=>'\\'];
				$vArr['name'] = strtr($vArr['name'], $reArr);
				
				$tnumArr = [];
				$tpath = explode('/', trim($vArr['path'], '/'));
				//是否为文件夹形式 号码/1.jpg....
				$tnumArr[] = ['num'=>array_pop($tpath), 'seq'=>$vArr['name'], 'f'=>$filepath];
				if(strlen($vArr['name']) >= 2)
				{
					if(preg_match('/(.{2,})['.$reg.'](-?\d+)/', $vArr['name'], $match))
					{//号码@顺序
						$tnumArr[] = ['num'=>$match[1], 'seq'=>$match[2], 'f'=>$filepath];
					}
					else
					{//纯号码
						$tnumArr[] = ['num'=>$vArr['name'], 'seq'=>0, 'f'=>$filepath];
					}
				}
				
				$match = false;
				foreach($tnumArr as $tnum)
				{
					$tnumFormat = LibFc::FormatNum($tnum['num']);
					if(strlen($tnumFormat) == 0) continue;
					if(!isset($chkNumToPidArr[$tnumFormat]))
					{
						$where = sprintf(" and pro_shop_id =%d and num_format = '%s' and num_show=1 order by num_self desc, num_ismain desc",$shopId, $tnumFormat);
						$res = $this->get('bc_number join bc_product on pro_id = num_pro_id', ['pro_id'], $where);
						$chkNumToPidArr[$tnumFormat] = array_column($res['data'],'pro_id');
					}
					
					if(!empty($chkNumToPidArr[$tnumFormat]))
					{
						$tnum['pro_id'] = $chkNumToPidArr[$tnumFormat];
						$timgArr[] = $tnum;
						$sort['pro_id'][] = $tnum['pro_id'];
						$sort['seq'][] = $tnum['seq'];
						$match = true;
						break;
					}
				}
				if(!$match)
				{
					$arr['nopro'][] = $filepath;
				}
			}
			
			if(!empty($timgArr))
			{
				array_multisort($sort['pro_id'], SORT_ASC, $sort['seq'], SORT_ASC, $timgArr);
				$proImg = [];
				foreach($timgArr as $t=>$v)
				{
					if(is_array($v['pro_id']))
					{
						foreach ($v['pro_id'] as $vv) 
						{
							$proImg[$vv][] = $v['f'];
						}
					}
					else
					{
						$proImg[$v['pro_id']][] = $v['f'];
					}
				}
				foreach($proImg as $proId=>$pimgs)
				{
					$arr['items'][] = ['pro_id'=>$proId, 'imgs'=>$pimgs];
				}
			}
		}
		return LibFc::ReturnData(true, $arr);
	}

	/**
	 * @method 导入配件图片
	 * @param $shopId int 目录店铺ID
	 * @param $optArr [type:replace|addtop|addlast, dir: xxx, ext: zip, filename: 149894_03872305d4fd51e53fd1ea9a4f9f6146 ]
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importItemImg($shopId, $optArr)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'].$optArr['dir'];
		$imgdir = $optArr['dir'];
		$uploadCache = $imgdir.'uploadCache.php';
		$cacheArr = [];
		if(file_exists($uploadCache)) $cacheArr = include($uploadCache);
		$arr = [];
		if(file_exists($imgdir))
		{
			foreach($optArr['items'] as $pro)
			{
				$spiIdArr = [];
				foreach($pro['imgs'] as $imgv)
				{
					if(!empty($cacheArr[$imgv]))
					{
						$spiIdArr[] = $cacheArr[$imgv];
					}
					else if(file_exists($imgdir.$imgv))
					{
						$res = $this->batchUploadImg($imgdir.$imgv, $shopId);
						if(!empty($res['data']))
						{
							$cacheArr[$imgv] = $res['data']['spi_id'];
							$spiIdArr[] = $res['data']['spi_id'];
						}
					}
				}
				if(!empty($spiIdArr))
				{
					$this->setProductPic($shopId, $pro['pro_id'], $spiIdArr, $optArr['type']);
					$arr[] = $pro['pro_id'];
				}
			}
			LibFc::ArraySave($cacheArr, $uploadCache);
		}
		return LibFc::ReturnData(true, $arr);
	}



	//遍历所有文件
	private function getAllFile($dir, $fileArr = [])
	{
		if(!is_dir($dir)) return true;
        if($handle = opendir($dir))
		{
            while(($file = readdir($handle))!==false)
			{
                if($file!='.' && $file!='..')
				{
                    if(is_dir($dir.$file))
					{
                       $fileArr = $this->getAllFile($dir.$file.'/', $fileArr);
                    }
					else
					{
                        $fileArr[] = $dir.$file;
                    }
                }
            }
            closedir($handle);
            @clearstatcache();
        }
		return $fileArr;
	}

	//根据配置同步数据到某店铺
	public function copyShopPro($toShopId)
	{
		$toShopId = (int) $toShopId;
		$res = $this->get('bc_copy_product', ['*'], sprintf(" and cp_to_shop_id = %d", $toShopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, '此店铺无同步配置');
		$cfg = $res['data'];
		$cfg['cp_config'] = json_decode($cfg['cp_config'], true);
		if(!isset($cfg['cp_config']['part'])) return LibFc::ReturnData(false, '同步配置：分类缺失');
		$where = sprintf(" and pro_shop_id = %d", $cfg['cp_from_shop_id']);
		if(!empty($cfg['cp_config']['part'])) $where .= sprintf(" and pro_part_id in (%s)", implode(',', $cfg['cp_config']['part']));
		$pres = $this->get('bc_product', ['*'], $where.' order by pro_id');
		$this->B2CDb->Begin();
		foreach($pres['data'] as $cpro)
		{
			$cproId = $cpro['pro_id'];
			$dataArr['base'] = $cpro;
			$dataArr['base']['pro_shop_id'] = $cfg['cp_to_shop_id'];
			$dataArr['base']['pro_dfrom'] = 'shop_'.$cpro['pro_shop_id'];
			$dataArr['base']['pro_dfrom_id'] = $cproId;
			unset($dataArr['base']['pro_add_time']);
			unset($dataArr['base']['pro_set_time']);
			unset($dataArr['base']['pro_status_ltime']);
			unset($dataArr['base']['pro_status_notice']);
			unset($dataArr['base']['pro_id']);
			
			$res = $this->get('bc_product_info', ['*'], sprintf(" and pri_pro_id=%d", $cproId), true);
			$dataArr['info'] = $res['data'];
			unset($dataArr['info']['pri_pro_id']);

			$res = $this->get('bc_number', ['*'], sprintf(" and num_pro_id=%d", $cproId));
			$dataArr['nums'] = $res['data'];
			foreach($dataArr['nums'] as &$tv)
			{
				unset($tv['num_pro_id']);
				unset($tv['num_id']);
			}
		
			$res = $this->get('bc_product_pic', ['pp_spi_id'], sprintf(" and pp_pro_id=%d order by pp_ismain desc, pp_seq", $cproId));
			$dataArr['imgs'] = array_column($res['data'], 'pp_spi_id');
			
			$dataArr['param'] = [];
			$res = $this->get('bc_product_param_float', ['ppf_pal_id, ppf_value'], sprintf(" and ppf_pro_id=%d", $cproId));
			$dataArr['param'] = array_column($res['data'], 'ppf_value', 'ppf_pal_id');

			$res = $this->get('bc_product_param_string', ['pps_pal_id, pps_value'], sprintf(" and pps_pro_id=%d", $cproId));
			foreach($res['data'] as $tv)
			{
				$dataArr['param'][$tv['pps_pal_id']] = $tv['pps_value'];
			}

			$res = $this->get('bc_product_model3_link', ['pml3_mod3_id'], sprintf(" and pml3_pro_id=%d", $cproId));
			$dataArr['model'] = array_column($res['data'], 'pml3_mod3_id');
			
			$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_shop_id = %d and pro_dfrom='%s' and pro_dfrom_id=%d", $dataArr['base']['pro_shop_id'], $dataArr['base']['pro_dfrom'], $dataArr['base']['pro_dfrom_id']), true);
			if(!empty($res['data']))
			{
				$this->setProduct($cfg['cp_to_shop_id'], $res['data']['pro_id'], $dataArr);
			}
			else
			{
				$this->addProduct($dataArr, $cfg['cp_to_shop_id']);
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}




	/**
	 * @method   检测导入配件车型备注
	 * @param $shopId int 目录店铺ID
	 * @param $optArr [dir: xxx, ext: zip, filename: 149894_03872305d4fd51e53fd1ea9a4f9f6146]
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function checkItemModelRemark($shopId, $optArr)
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$ext = strtolower(trim($optArr['ext']));
		if(!in_array($ext, ['xls', 'xlsx'])) return LibFc::ReturnData(false, '不支持'.$ext.'的表格！');
		$file = $optArr['dir'].$optArr['filename'].'.'.$ext;
		if(file_exists($file))
		{
			$OthSExcel = new OthSExcel();
			$res = $OthSExcel->read($file, 'all', ['mod3_id'=>'mod3_id', 'mch_code'=>'mch_code', 'men_code'=>'men_code', 'pri_code'=>'自编号', 'remark'=>'车型备注']);
			$allArr = [];
			$mtype = '';
			foreach($res['data'] as $sidex=>$sdata)
			{
				foreach($sdata as $rowk=>$rowd)
				{
					if(empty($mtype))
					{
						if(!empty($rowd['mod3_id'])) $mtype = 'all';
						else if(!empty($rowd['mch_code'])) $mtype = 'chassis';
						else if(!empty($rowd['men_code'])) $mtype = 'engine';
					}
					$rowd['pri_code'] = LibFc::FormatNum($rowd['pri_code']);
					if(empty($mtype) || empty($rowd['pri_code']) || !isset($rowd['remark'])) continue;
					$allArr[] = $rowd;
				}
			}
			//补充产品ID
			$cacheFile = $optArr['dir'].$optArr['filename'].'.php';
			$cacheArr = ['rows'=>$allArr, 'mtype'=>$mtype];
			LibFc::ArraySave($cacheArr, $cacheFile);
		}
		$arr = $optArr;
		unset($arr['dir']);
		$arr['total'] = count($allArr);
		return LibFc::ReturnData(true, $arr);
	}

	/**
	 * @method 导入配件车型备注
	 * @param $shopId int 目录店铺ID
	 * @param $optArr [dir: xxx, ext: zip, filename: 149894_03872305d4fd51e53fd1ea9a4f9f6146 ]
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importItemModelRemark($shopId, $optArr)
	{
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$cacheFile = $optArr['dir'].$optArr['filename'].'.php';
		if(!file_exists($cacheFile)) return LibFc::ReturnData(false, '文件不存在，请重新上传！');
		$cacheArr = include($cacheFile);
		if(!is_array($cacheArr)) return LibFc::ReturnData(false, '文件不存在，请重新上传！');

		$arr = [];
		$end = $optArr['begin'] + $optArr['per'];
		$allSetArr = [];
		for($rowk = $optArr['begin']; $rowk < $end; $rowk++)
		{
			if(empty($cacheArr['rows'][$rowk])) continue;
			$allSetArr[] = $cacheArr['rows'][$rowk];
		}
		//找产品ID
		if(!empty($allSetArr))
		{
			$ComModel = new ComModel();
			$mtype = $cacheArr['mtype'];
			$where = sprintf(" and num_format in ('%s') and pro_shop_id=%d", implode("','", array_unique(array_column($allSetArr, 'pri_code'))), $shopId);
			$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id', 'num_format', 'pro_smt_code'], $where);
			$numPidArr = array_column($res['data'], null, 'num_format');
		
			$this->B2CDb->Begin();
			foreach($allSetArr as $rowd)
			{
				if(empty($numPidArr[$rowd['pri_code']])) continue;
				$proArr = $numPidArr[$rowd['pri_code']];
				
				//模式不一致不允许更新
				if($proArr['pro_smt_code'] != $mtype) continue;
				$pid = $proArr['num_pro_id'];

				switch($mtype)
				{
					case 'all':
						if(!empty($rowd['mod3_id']))
							$this->set('bc_product_model3_link', ['pml3_remark'=>$rowd['remark']], sprintf(" and pml3_pro_id=%d and pml3_mod3_id=%d", $pid, $rowd['mod3_id']));
					break;
					case 'chassis':
						if(!empty($rowd['mch_code']))
						{
							$rowd['mch_code'] = LibFc::Escape($rowd['mch_code']);
							$m3res = $ComModel->get('bc_modchassis_mod3', ['mcm_mod3_id as mod3_id'], sprintf(" and mcm_mch_code = '%s'", $rowd['mch_code']));
							if(!empty($res['data']))
							{
								$where = sprintf(" and pml3_pro_id=%d and pml3_mod3_id in (%s)", $pid, implode(',', array_column($m3res['data'], 'mod3_id')));
								$this->set('bc_product_model3_link', ['pml3_remark'=>$rowd['remark']], $where);
							}
							$this->set('bc_product_modchassis', ['pmc_remark'=>$rowd['remark']], sprintf(" and pmc_pro_id=%d and pmc_mch_code= '%s'", $pid, $rowd['mch_code']));
						}
					break;
					case 'engine':
						if(!empty($rowd['men_code']))
						{
							$rowd['men_code'] = LibFc::Escape($rowd['men_code']);
							$m3res = $ComModel->get('bc_modengine_mod3', ['mem_mod3_id as mod3_id'], sprintf(" and mem_men_code = '%s'", $rowd['men_code']));
							if(!empty($res['data']))
							{
								$where = sprintf(" and pml3_pro_id=%d and pml3_mod3_id in (%s)", $pid, implode(',', array_column($m3res['data'], 'mod3_id')));
								$this->set('bc_product_model3_link', ['pml3_remark'=>$rowd['remark']], $where);
							}
							$this->set('bc_product_modengine', ['pme_remark'=>$rowd['remark']], sprintf(" and pme_pro_id=%d and pme_men_code = '%s'", $pid, $rowd['men_code']));
						}
					break;
				}
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true, $arr);
	}

	/**
	 * @param  [int] $shopId
	 * @method 根据店铺类型导出不同的demo
	 * @author zhengweihua 
	 * @copyright 2022-06-17
	 */
	public function exportDifferentDemo($shopId, $partIdArr = [], $proArr = [], $filename = '配件导入模板.xlsx')
	{
		//通用版
		$colsFiled = [
			['name'=>'配件ID', 'fname'=>'pro_id', 'width'=>10],	
			['name'=>'零件分类', 'fname'=>'part_name', 'color'=>'FF0000', 'width'=>20],	
			['name'=>'店铺分类', 'fname'=>'shop_sort', 'width'=>20],	
			['name'=>'配件名称', 'fname'=>'pro_name', 'width'=>30],	
			['name'=>'配件品牌', 'fname'=>'prb_name', 'width'=>15],	
			['name'=>'商家编码', 'fname'=>'pri_code', 'color'=>'FF0000', 'width'=>20],	
			['name'=>'互换号', 'fname'=>'number', 'width'=>30],
			['name'=>'配件关键字', 'fname'=>'pri_keyword', 'width'=>30],
			['name'=>'配件状态', 'fname'=>'pro_status', 'width'=>10],
		];
		if(empty($partIdArr)){
			$res = $this->get('sh_super_part', ['distinct sup_part_id'], sprintf(" and sup_shop_id=%d",(int)$shopId));
			if($res['data']){
				$partIdArr = array_filter(array_column($res['data'], 'sup_part_id'));
			}
		}
		
		if(empty($partIdArr)) $colsFiled[] = ['name'=>'配件参数', 'fname'=>'param', 'width'=>30];
		
		$colsFiled[] = ['name'=>'自定义参数模板名', 'fname'=>'ppt_name', 'width'=>20];
		$colsFiled[] = ['name'=>'自定义参数', 'fname'=>'pro_param', 'width'=>30];
		$colsFiled[] = ['name'=>'商家备注', 'fname'=>'pri_self_remark', 'width'=>30];
		$colsFiled[] = ['name'=>'配件描述','fname'=>'pri_des','width'=>30];	
		$colsFiled[] = ['name'=>'添加人','fname'=>'pro_add_uid','width'=>30];	
		//商城版
		if(mvc::$cfg['isGzhShop'])
		{	
			$colsFiled[] = ['name'=>'销售价','fname'=>'pro_sale_price','width'=>30];
			$colsFiled[] = ['name'=>'库存', 'fname'=>'pro_count', 'width'=>10];
			$colsFiled[] = ['name'=>'配件卖点','fname'=>'pro_sale_des','width'=>30];
			$colsFiled[] = ['name'=>'维修厂价', 'fname'=>'pro_price_vip1', 'width'=>15];
			$colsFiled[] = ['name'=>'小型经销商价', 'fname'=>'pro_price_vip2', 'width'=>15];
			$colsFiled[] = ['name'=>'中型经销商价', 'fname'=>'pro_price_vip3', 'width'=>15];
			$colsFiled[] = ['name'=>'大型经销商价', 'fname'=>'pro_price_vip4', 'width'=>15];
		}
		else
		{
			$res = 	$this->get('sh_super',['ssu_super_gzh,ssu_module'],sprintf(" and ssu_shop_id = %d",(int)$shopId),true);
			//定制版
			if($res['data']['ssu_super_gzh'] == 2)
			{
				$moduleArr = explode(',',$res['data']['ssu_module']);
				
				//有价格模块
				if(in_array('price',$moduleArr))
				{
					$colsFiled[] = ['name'=>'销售价','fname'=>'pro_sale_price','width'=>30];
					if(in_array('user',$moduleArr))
					{
						$colsFiled[] = ['name'=>'维修厂价', 'fname'=>'pro_price_vip1', 'width'=>15];
						$colsFiled[] = ['name'=>'小型经销商价', 'fname'=>'pro_price_vip2', 'width'=>15];
						$colsFiled[] = ['name'=>'中型经销商价', 'fname'=>'pro_price_vip3', 'width'=>15];
						$colsFiled[] = ['name'=>'大型经销商价', 'fname'=>'pro_price_vip4', 'width'=>15];
					}
				}
			}
		}
		return	$this->exportSupertItem($colsFiled, $partIdArr, $proArr, $filename);
	}
	
	/**
	 * @param  int $shopId
	 * @param  Array $query
	 * @method 批量删除商品图片
	 * @author zhengweihua 
	 * @copyright 2022-08-09
	 */
	public function batchDelProImage($shopId,$query  =[])
	{
		$shopId = (int) $shopId;
		if ($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		if (empty($query['proIds'])) return LibFc::ReturnData(false, '参数错误');

		//校验产品是否为该店铺的
		$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id in (%s) and pro_shop_id=%d", $query['proIds'], $shopId));
		if (empty($res['data'])) {
			return LibFc::ReturnData(true, true);
		}

		$delProIdArr = array_column($res['data'], 'pro_id');
		$B2cLog = new B2cLog();
		$this->B2CDb->Begin();

		$where = sprintf(" and pp_pro_id in (%s)", implode(',', $delProIdArr));
		$table = "bc_product_pic left join sh_pic on pp_spi_id = spi_id and spi_cate = 'product'";
		$res = $this->get($table, ['pp_pro_id', 'spi_id', 'spi_path', 'spi_cate', "concat(spi_name, '.', spi_ext) as spi_name"], $where);

		$OthFileCenter = new OthFileCenter();
		foreach ($res['data'] as $v) {
			
			$countres = $this->get('bc_product_pic', ["count('pp_pro_id') as count"], sprintf(" and pp_spi_id = %d and pp_pro_id =%d",$v['spi_id'] ,$v['pp_pro_id']), true);
			//如果其他商品共用图片	
			if ($countres['data']['count'] > 0) {
				continue;
			}
			$delData = ['cate' => $v['spi_cate'], 'files' => $v['spi_path'] . $v['spi_name']];
			$res = $OthFileCenter->del($delData);
		}
		$this->del('bc_product_pic', sprintf(" and pp_pro_id in (%s)", implode(',', $delProIdArr)));
		$codeRes = $this->get('bc_product_info',['pri_code'],sprintf(" and pri_pro_id in (%s)",implode(',',$delProIdArr)));
		$codeArr = $codeRes['data'] ? array_column($codeRes['data'], 'pri_code') : [];
		$item = [
			'log_category'=>1,
			'log_shop_id'=>$shopId,
			'log_atime'=>time(),
			'log_dataid'=>$delProIdArr,
			'log_txt'=>'批量删除配件图片：'.implode(',',$codeArr)
		];
		$B2cLog->addFastLog($item);
		$this->B2CDb->End();

		return LibFc::ReturnData(true, true);
	}

	/**
	 * @method   检测商城同步数据
	 * @param $shopId int 目录店铺ID
	 * @param $optArr [dir: xxx, ext: zip, filename: 149894_03872305d4fd51e53fd1ea9a4f9f6146]
	 * @author	zhengweihua
	 * @copyright 2018/6/8
	 */
	public function checkShopSync($shopId, $optArr,$mode='other')
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$toShopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');

		if($mode=='self')
		{
			$fromShopId = $toShopId;
		}
		elseif($mode=='other')
		{
			$res = $this->get('sh_shop_synch', ['*'], sprintf(" and sss_shop_id_to = %d", $toShopId), true);
			if (empty($res['data'])) return LibFc::ReturnData(false, '此店铺无同步配置');
			$cfg = $res['data'];
			$fromShopId = $cfg['sss_shop_id_from'];
			$cfg['sss_act'] = json_decode($cfg['sss_act'], true);
			if (empty($cfg['sss_act'])) return libfc::ReturnData(false, '没有相关设置');
		}

		$ext = strtolower(trim($optArr['ext']));
		if(!in_array($ext, ['xls', 'xlsx'])) return LibFc::ReturnData(false, '不支持'.$ext.'的表格！');
		$file = $optArr['dir'].$optArr['filename'].'.'.$ext;

		if(!file_exists($file)) return LibFc::ReturnData(false, '文件不存在，请重新上传文件');
		$tableList = [];
		switch ($optArr['type']) {
			case 'model':
				$OthSExcel = new OthSExcel();
				$res = $OthSExcel->read($file, 0);
				$tableList = $res['data']?$res['data'][0]:[];
				if($tableList[0]){
					unset($tableList[0]);
				}
				if(empty($tableList))  return LibFc::ReturnData(false, '表单错误');
				//格式化所有号码
				// $tableList = array_map(function ($number){
				// 	return array_map(array("LibFc","FormatNum"),$number);
				// },$tableList);
				//key:当前店铺得号码;value:导入店铺得号码
				$tableList = array_filter(array_column($tableList,0,1));
		
				//函数去重,把数组每个元素变成引号,方便mysql in
				$function = function($array)
				{
					$array = array_unique($array);
					$array = array_map(function ($v){
						return sprintf("'%s'",$v);
					},$array);
					return $array;
				};

				$toShopNumber = $function(array_keys($tableList));

				$table = 'bc_number as n 
				join bc_product as p on pro_id=num_pro_id';
				$toShopModelLinks = $this->get($table,['pro_id','num_display'],sprintf(" and num_display in (%s) and pro_shop_id =%d and num_self=1 and num_show = 1",implode(',',$toShopNumber),$toShopId));

				if(empty($toShopModelLinks['data'])) return LibFc::ReturnData(false,'找不到当前店铺的号码信息');

				$arr =  array_column($toShopModelLinks['data'],'num_display');
				
				$errorToArr  = array_diff(array_keys($tableList),$arr);
	
				$fromShopNumber = $function(array_values($tableList));

				$table = 'bc_number as n 
				join bc_product as p on pro_id=num_pro_id';
				$fromShopModelLinks = $this->get($table,['pro_id','num_display'],sprintf(" and num_display in (%s) and pro_shop_id =%d and num_self=1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));

				if(empty($fromShopModelLinks['data'])) return LibFc::ReturnData(false,'找不到源店铺的号码信息');

				$arr =  array_column($fromShopModelLinks['data'],'num_display');
				$errorFromArr  = array_diff(array_values($tableList),$arr);

				$addArr = [];
				foreach ($tableList as $key => $value) {

					if(in_array($key,$errorToArr)){
						continue;
					}
					if(in_array($value,$errorFromArr)){
						continue;
					}
					$where = sprintf(" and sssp_shop_id_from = %d 
					and sssp_shop_id_to = %d  and sssp_pri_code_to = '%s'",$fromShopId,$toShopId,$key);
					$rows = $this->get('sh_shop_synch_product',['*'],$where,true);

					if(empty($rows['data']))
					{
						$addArr[] = [
							'sssp_shop_id_from'=>$fromShopId,
							'sssp_shop_id_to'=>$toShopId,
							'sssp_pri_code_from'=>$value,
							'sssp_pri_code_to'=>$key
						];
					}else{
						$upArr  = ['sssp_pri_code_from' => $value];
						$this->set('sh_shop_synch_product',$upArr,$where);
					}
				}
				
				if($addArr) $this->addAny('sh_shop_synch_product',array_keys($addArr[0]) ,$addArr);
			break;
		
		}	
		
		$arr = $optArr;
		unset($arr['dir']);
		$arr['total'] = count($tableList);
		$arr['errorToArr'] = array_values($errorToArr);
		$arr['errorFromArr'] =array_values($errorFromArr);
		return LibFc::ReturnData(true, $arr);
	}

	/**
	* @param  int $shopId
	* @param  Array $query
	* @method 执行同步操作
	* @author zhengweihua 
	* @copyright 2022-08-10
	*/
	public function doShopSync($shopId,$query =[],$mode='other')
	{
		$toShopId = (int) $shopId;
		if(empty($toShopId)) return LibFc::ReturnData(false, '参数错误');
		
		if($mode=='self')
		{
			$res = $this->get('sh_shop_synch', ['*'], sprintf(" and sss_shop_id_to = %d and sss_shop_id_from=%d", $toShopId,$toShopId), true);
			if(!empty($res['data'])){
				$cfg = $res['data'];
				$cfg['sss_act'] = json_decode($cfg['sss_act'], true);
			}else{
				$cfg['sss_act'] = ["model"=>"add","number"=>"add"];
			}
			$fromShopId = $toShopId;
		}
		elseif($mode=='other')
		{
			$res = $this->get('sh_shop_synch', ['*'], sprintf(" and sss_shop_id_to = %d and sss_shop_id_from!=%d", $toShopId,$toShopId), true);
			if (empty($res['data'])) return LibFc::ReturnData(false, '此店铺无同步配置');
			$cfg = $res['data'];
			$cfg['sss_act'] = json_decode($cfg['sss_act'], true);
			if (empty($cfg['sss_act'])) return libfc::ReturnData(false, '没有相关设置');
			$fromShopId = $cfg['sss_shop_id_from'];

		}
		
		
		//函数去重,把数组每个元素变成引号,方便mysql in
		$function = function($array)
		{
			$array = array_unique($array);
			$array = array_map(function ($v){
				return sprintf("'%s'",$v);
			},$array);
			return $array;
		};

		$where = sprintf(" and sssp_shop_id_to = %d and sssp_shop_id_from=%d",$shopId,$fromShopId);
		//如果有传值过来只处理传值
		if(isset($query['priCodeArr']) && !empty($query['priCodeArr']))
		{	
			$priCodeArr = $function($query['priCodeArr']);
			$where .= sprintf(" and sssp_pri_code_to in (%s)",implode(',',$priCodeArr));
		}

		$listres = $this->get('sh_shop_synch_product',['*'],$where);	

		if(empty($listres['data'])) return libfc::ReturnData(false, '请先导入数据');
		$this->B2CDb->Begin();

		switch ($query['type']) {
			case 'model':
				$style  = $cfg['sss_act']['model'];

				$tableList = array_column($listres['data'],'sssp_pri_code_from','sssp_pri_code_to');
			
				$formShopNumber = $function(array_values($tableList));
				$formShopModelLinkRes = $this->getProModelBynumber($fromShopId,$formShopNumber);
				if(empty($formShopModelLinkRes['data'])) return LibFc::ReturnData(false,'找不到源店铺的号码');
				$formShopModelLink = $formShopModelLinkRes['data'];

				$toShopNumber = $function(array_keys($tableList));
				$toShopModelLinkRes = $this->getProModelBynumber($toShopId,$toShopNumber);
				$toShopModelLink = $toShopModelLinkRes['data'];
				//同一天同一个产品只保留最后的
				//备份车型数据库
				$this->backupModel3Link($toShopId,array_column($toShopModelLink,'pro_id'));
				//遍历当前店铺
				foreach ($toShopModelLink as $index => $item)
				{
					//通过tableList key-value 属性 找到 formShopModelLink 的num_format
					if(isset($tableList[$index]) &&
						isset($formShopModelLink[$tableList[$index]])
					) {
						
						//获取到目标产品的车型关系
						$pro_type =  $formShopModelLink[$tableList[$index]]['type'];
						$temp = $formShopModelLink[$tableList[$index]]['data'];
						if(empty($temp)) $temp = [];
						if(empty($item)) $item = [];
						
						//如果是增量式增加，就把原来的当前店铺的车型关系合并
						if($style == 'add' && $pro_type == $item['type'])
						{
							if(!empty($item['data']))
							{
								if($pro_type == 'all')
								{
									foreach ($item['data'] as $val) {
										if(!$temp[$val['pml3_mod3_id']]){
											$temp[$val['pml3_mod3_id']] = $val;
										}
									}
								}else{
									$temp = array_merge($item['data'],$temp);
								}
							}
						}

						if($pro_type == 'engine')
						{
							if(isset($item['pro_id'])) $this->setProductModEngine($item['pro_id'],$temp);	
						}
						elseif($pro_type =='chassis')
						{
							if(isset($item['pro_id'])) $this->setProductModChassis($item['pro_id'],$temp);
						}
						else{
							//通过末级的使用车型ID更新配件的使用品牌、一级、二级、三级车型ID关联
							if(isset($item['pro_id'])) $this->setProductModel($item['pro_id'],$temp,'SHOP');
						}
						//释放内存
						unset($temp,$toShopModelLink[$index]);
					}
				}
				$this->set('sh_shop_synch',['sss_runtime'=>time()],sprintf(" and sss_shop_id_to = %d and sss_shop_id_from = %d",$toShopId,$fromShopId));
			break;
			case 'num':
				$style  = $cfg['sss_act']['number']??'add';
				$tableList = array_column($listres['data'],'sssp_pri_code_from','sssp_pri_code_to');
		
				$fromShopNumber = $function(array_values($tableList));
				$table = 'bc_number join bc_product on pro_id=num_pro_id';
				$fromShopNumRes = $this->get($table,['num_pro_id','num_format'],sprintf(" and num_format in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));

				$fromShopNumRes1 = $this->get($table,['num_pro_id','num_display as num_format'],sprintf(" and num_display in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));
				$fromShopNumRes['data'] = array_merge($fromShopNumRes['data'],$fromShopNumRes1['data']);
				
				if(empty($fromShopNumRes['data'])) return LibFc::ReturnData(false,'找不到源店铺的号码');
				$formShopNumLink = [];
				$fromProIdArr = array_column($fromShopNumRes['data'],'num_pro_id','num_format');
				$field = ['num_pro_id','num_factory','num_self','num_display','num_show','num_from','num_fromid','num_ismain'];
				$fromNumRes  =	$this->get('bc_number',$field,sprintf(" and num_pro_id in (%s)",implode(',',$fromProIdArr)));
				foreach ($fromProIdArr as $key => $item) 
				{
					$formShopNumLink[$key] = [];
					foreach ($fromNumRes['data'] as $itemnum) 
					{
						if($item == $itemnum['num_pro_id'] && $itemnum['num_self'] !=1)
						{
							unset($itemnum['num_pro_id']);
							$formShopNumLink[$key][] = $itemnum;
						}	
					}
				}
				$toShopNumber = $function(array_keys($tableList));
				$toShopNumRes = $this->get($table,['num_pro_id','num_format'],sprintf(" and num_format in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$toShopNumber),$toShopId));
				$toShopNumRes1 = $this->get($table,['num_pro_id','num_display as num_format'],sprintf(" and num_display in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$toShopNumber),$toShopId));
				$toShopNumRes['data'] = array_merge($toShopNumRes['data'],$toShopNumRes1['data']);	
				
				if(empty($toShopNumRes['data'])) return  LibFc::ReturnData(false,'找不到目标店铺的号码');
				$toProIdArr = array_column($toShopNumRes['data'],'num_pro_id','num_format');
			
				$toNumRes = $this->get('bc_number',$field,sprintf(" and num_pro_id in (%s)",implode(',',$toProIdArr)));
				$toShopNumLink = [];
				foreach ($toProIdArr as $key => $item) 
				{
					$toShopNumLink[$key] = [];
					foreach ($toNumRes['data'] as $itemnum) 
					{
						if($item == $itemnum['num_pro_id']  && $itemnum['num_self'] !=1) 
						{
							$toShopNumLink[$key][] = $itemnum;
						}	
					}
				}
				foreach ($toShopNumLink as $key => $numLink) 
				{
					if(!isset($tableList[$key]) || !isset($formShopNumLink[$tableList[$key]]))
					{
						continue;
					}
					$temp =$formShopNumLink[$tableList[$key]];
					if(empty($temp)) $temp = [];
					if(empty($numLink)) $numLink = [];
					if($style == 'add')
					{
						$temp = array_merge($temp,$numLink);
					}
					$proId = isset($numLink['0'])?$numLink['0']['num_pro_id']:$toProIdArr[$key];
					if(isset($proId)) $this->setProductNum($proId,$temp);
					unset($temp,$toShopNumLink[$key]);
				}
				$this->set('sh_shop_synch',['sss_runtime'=>time()],sprintf(" and sss_shop_id_to = %d and sss_shop_id_from = %d",$toShopId,$fromShopId));
			break;
			case 'param':
				$tableList = array_column($listres['data'],'sssp_pri_code_from','sssp_pri_code_to');
		
				$fromShopNumber = $function(array_values($tableList));
				$table = 'bc_number join bc_product on pro_id=num_pro_id';
				$fromShopNumRes = $this->get($table,['num_pro_id','pro_part_id','pro_part_path','num_format'],sprintf(" and num_format in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));

				$fromShopNumRes1 = $this->get($table,['num_pro_id','pro_part_id','pro_part_path','num_display as num_format'],sprintf(" and num_display in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));
				$fromShopNumRes['data'] = array_merge($fromShopNumRes['data'],$fromShopNumRes1['data']);
				
				if(empty($fromShopNumRes['data'])) return LibFc::ReturnData(false,'找不到源店铺的号码');

				$fromPro = array_column($fromShopNumRes['data'],null,'num_format');
				$fromIds = implode(',',array_column($fromPro,'num_pro_id'));
				//配件参数
				$formShopParamLink = [];
				$res = $this->get('bc_product_param_float', ['ppf_pro_id','ppf_pal_id, ppf_value'], sprintf(" and ppf_pro_id in (%s)", $fromIds));
				foreach ($fromPro as $key => $val) {
					$formShopParamLink[$key] = [];
					foreach ($res['data'] as $fv) {
						if($val['num_pro_id']==$fv['ppf_pro_id']){
							$formShopParamLink[$key][$fv['ppf_pal_id']] = $fv['ppf_value'];
						}
					}
				}
				

				$res = $this->get('bc_product_param_string', ['pps_pro_id,pps_pal_id, pps_value'], sprintf(" and pps_pro_id in (%s)", $fromIds));
				foreach ($fromPro as $key => $val) {
					if(!isset($formShopParamLink[$key])){
						$formShopModelLink[$key] = [];
					}
					foreach($res['data'] as $tv)
					{
						if($val['num_pro_id']==$fv['ppf_pro_id']){
							$formShopParamLink[$key][$tv['pps_pal_id']] = $tv['pps_value'];
						}
					}
				}

				//自定义参数
				$table = 'bc_product_para_val 
				JOIN bc_product ON prpv_pro_id = pro_id
				JOIN bc_product_label ON prl_id = prpv_prl_id
				JOIN bc_product_para_tpl on ppt_id = pro_ppt_id
				LEFT JOIN `bc_product_para_tpl_link` ON  pro_ppt_id = pptl_ppt_id AND pptl_prl_id = prl_id
				LEFT JOIN bc_product_unit ON pru_id = prpv_pru_id';
				$res = $this->get($table, ['prpv_pro_id,prl_name, prpv_value,pru_id,pru_name,ppt_name'], sprintf(" and prpv_pro_id in (%s) and prpv_value != '' ORDER BY pptl_seq, prpv_seq, prl_name", $fromIds));
				
				if($res['data']){
					$selfParamLink = [];
					$pptNameLink = [];
					foreach ($fromPro as $key => $val) {
						$selfParamLink[$key] = [];
						foreach ($res['data'] as $kk => $vv) {
							if($val['num_pro_id']==$vv['prpv_pro_id']){
								$selfParamLink[$key][] =[$vv['prl_name'],$vv['prpv_value'],$vv['pru_name']];
								$pptNameLink[$vv['prpv_pro_id']] = $vv['ppt_name'];
							}
						}
					}
					
				}
				$toShopNumber = $function(array_keys($tableList));
				$table = 'bc_number join bc_product on pro_id=num_pro_id';
				$toShopNumRes = $this->get($table,['num_pro_id','num_format'],sprintf(" and num_format in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$toShopNumber),$toShopId));
				$toShopNumRes1 = $this->get($table,['num_pro_id','num_display as num_format'],sprintf(" and num_display in (%s) and pro_shop_id = %d and num_self =1 and num_show = 1",implode(',',$toShopNumber),$toShopId));
				$toShopNumRes['data'] = array_merge($toShopNumRes['data'],$toShopNumRes1['data']);	
				
				if(empty($toShopNumRes['data'])) return  LibFc::ReturnData(false,'找不到目标店铺的号码');
				$toProIdArr = array_column($toShopNumRes['data'],'num_pro_id','num_format');

				foreach ($toProIdArr as $key => $proId) 
				{
					if(!isset($tableList[$key])){
						continue;
					}
					//更新配件参数
					if(isset($formShopParamLink[$tableList[$key]]) && $formShopParamLink[$tableList[$key]]){
						$partId = $fromPro[$tableList[$key]]['pro_part_id'];
						$pro_part_path = $fromPro[$tableList[$key]]['pro_part_path'];
						$this->set('bc_product',['pro_part_id'=>$partId,'pro_part_path'=>$pro_part_path],sprintf(" AND pro_id=%d",$proId));
						$this->setProductParam($proId,$partId,$formShopParamLink[$tableList[$key]]);
					}

					//更新自定义参数
					if($selfParamLink[$tableList[$key]]){
						$fromProId = $fromPro[$tableList[$key]]['num_pro_id'];
						$pptName = $pptNameLink[$fromProId]??'默认模板';
						$this->batchChangeParam($proId,$toShopId,$selfParamLink[$tableList[$key]],$pptName);
					}
					
				}
			break;
		}
		
		$this->B2CDb->End();	
		return LibFc::ReturnData(true, true);
	}

	/**
	* @param  int $shopId
	* @param  Array $proCodeIdArr 店铺自编码
	* @method 删除同步的商品数据 
	* @author zhengweihua 
	* @copyright 2022-08-12
	*/
	public function delShopSyncProduct($shopId,$proCodeIdArr)
	{
		$shopId = (int) $shopId;
		foreach($proCodeIdArr as $k=>$v)
		{
			$proCodeIdArr[$k]  = $v;
		}
		if($shopId < 1 || !is_array($proCodeIdArr))
		{
			return LibFc::ReturnData(false, '提供的参数不正确');
		}
		$proCodeIdArr = array_map(function ($v){
			return sprintf("'%s'",$v);
		},$proCodeIdArr);
		//校验
		$res = $this->get('sh_shop_synch_product', ['sssp_pri_code_to'], sprintf(" and sssp_pri_code_to in (%s) and sssp_shop_id_to=%d", implode(',', $proCodeIdArr), $shopId));
		if(empty($res['data']))
		{
			return LibFc::ReturnData(true, true);
		}
		$delIdArr = array_column($res['data'], 'sssp_pri_code_to');
		$delIdArr = array_map(function ($v){
			return sprintf("'%s'",$v);
		},$delIdArr);
		$this->del('sh_shop_synch_product', sprintf(" and sssp_pri_code_to in (%s) and sssp_shop_id_to=%d", implode(',', $delIdArr),$shopId));
		return LibFc::ReturnData(true, true);
	}
	/**
	* @param  int $shopId
	* @param  Array $param 店铺自编码
	* @method 通过文本管理同步的商品车型 
	* @author zhengweihua 
	* @copyright 2022-09-05
	*/
	public function doShopSyncByText($shopId,$param = [],$mode='other')
	{
		$toShopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');

		if($mode=='other')
		{
			$res = $this->get('sh_shop_synch', ['*'], sprintf(" and sss_shop_id_to = %d", $toShopId), true);
			if (empty($res['data'])) return LibFc::ReturnData(false, '此店铺无同步配置');
			$cfg = $res['data'];
			$fromShopId = $cfg['sss_shop_id_from'];
			$cfg['sss_act'] = json_decode($cfg['sss_act'], true);
			if (empty($cfg['sss_act'])) return libfc::ReturnData(false, '没有相关设置');
		}
		else
		{
			$fromShopId = $toShopId;
		}
		

		//格式化所有号码
		// $tableList = array_map(function ($number){
		// 	return array_map(array("LibFc","FormatNum"),$number);
		// },$param);
		$tableList = $param;
		//key:当前店铺的号码;value:导入店铺的号码
		$tableList = array_column($tableList,'sssp_pri_code_from','sssp_pri_code_to');
		//函数去重,把数组每个元素变成引号,方便mysql in
		$function = function($array)
		{
			$array = array_unique($array);
			$array = array_map(function ($v){
				return sprintf("'%s'",$v);
			},$array);
			return $array;
		};

		$toShopNumber = $function(array_keys($tableList));

		$table = 'bc_number as n 
		join bc_product as p on pro_id=num_pro_id 
		left join bc_product_model3_link as l on pml3_pro_id = pro_id';
		$toShopModelLinks = $this->get($table,['pro_id','num_display','pml3_mod3_id'],sprintf(" and num_display in (%s) and pro_shop_id =%d and num_self=1 and num_show = 1",implode(',',$toShopNumber),$toShopId));

		if(empty($toShopModelLinks['data'])) return LibFc::ReturnData(false,'找不到当前店铺的号码信息');
		$toShopModelLink = [];
		foreach ($toShopModelLinks['data'] as $key => $item) {
			
			$toShopModelLink[$item['num_display']][] = $item;
		}
		
		$arr =  array_unique(array_column($toShopModelLinks['data'],'num_display'));
		//当前店铺不存在的自编码
		$errorToArr  = array_diff(array_keys($tableList),$arr);

		//来源店铺自编码
		$fromShopNumber = $function(array_values($tableList));
		$fromShopModelLinks = $this->get($table,['pro_id','num_display','pml3_mod3_id'],sprintf(" and num_display in (%s) and pro_shop_id =%d and num_self=1 and num_show = 1",implode(',',$fromShopNumber),$fromShopId));

		if(empty($fromShopModelLinks['data'])) return LibFc::ReturnData(false,'找不到源店铺的号码信息');

		$formShopModelLink = [];
		foreach ($fromShopModelLinks['data'] as $key => $item) {
			$formShopModelLink[$item['num_display']][] = $item['pml3_mod3_id'];
		}
		$arr = array_unique(array_column($fromShopModelLinks['data'],'num_display'));
		//源店铺不存在的自编码
		$errorFromArr  = array_diff(array_values($tableList),$arr);

		$this->B2CDb->Begin();

		$addArr = [];
		//遍历当前店铺
		foreach ($toShopModelLink as $index => $item)
		{
			//通过tableList key-value 属性 找到 formShopModelLink 的num_format
			if(isset($tableList[$index]) &&
				isset($formShopModelLink[$tableList[$index]])
			) {
				
				$where = sprintf(" and sssp_shop_id_from = %d 
				and sssp_shop_id_to = %d  and sssp_pri_code_to = '%s'",$fromShopId,$toShopId,$index);
				$rows = $this->get('sh_shop_synch_product',['*'],$where,true);

				if(empty($rows['data']))
				{
					$addArr[] = [
						'sssp_shop_id_from'=>$fromShopId,
						'sssp_shop_id_to'=>$toShopId,
						'sssp_pri_code_from'=>$tableList[$index],
						'sssp_pri_code_to'=>$index
					];
				}else{
					$upArr  = ['sssp_pri_code_from' => $tableList[$index]];
					$this->set('sh_shop_synch_product',$upArr,$where);
				}
			}
		}
		if($addArr) $this->addAny('sh_shop_synch_product',array_keys($addArr[0]) ,$addArr);
		
		$this->B2CDb->End();

		$arr = [];
		if($errorToArr) $arr['errorToArr'] = array_values($errorToArr);
		if($errorFromArr) $arr['errorFromArr'] =array_values($errorFromArr);
		return LibFc::ReturnData(true, $arr);
	}

	/**
	* @param  int $shopId
	* @param  int $proId 商品id
	* @method 同步商品车型 
	* @author zhengweihua 
	* @copyright 2022-09-06
	*/
	public function syncModel($shopId,$proId)
	{
		//是否有同步设置
		$where = sprintf("and sss_shop_id_from = %d and sss_act !='' and sss_shop_id_to != 0", $shopId);
		$synchSetting =	$this->get("sh_shop_synch", ['*'], $where);
		if(empty($synchSetting['data'])) return LibFc::ReturnData(true);
		
		
		$table = 'bc_number as n 
		join bc_product as p on pro_id=num_pro_id';
		
		$where =  sprintf(" and pro_id = %d and pro_shop_id =%d and num_self=1 and num_show = 1", $proId, $shopId);
		$fromShopModelLinks = $this->get($table, ['pro_id', 'num_format','num_display','pro_smt_code'],$where,true);
		//自编码是否存在
		if(empty($fromShopModelLinks['data'])){
			return LibFc::ReturnData(true);
		}
		$fnumFormat = $fromShopModelLinks['data']['num_format'];
		$fnumDisplay = $fromShopModelLinks['data']['num_display'];
		$formShopModelLink = [];
		$codetype = $fromShopModelLinks['data']['pro_smt_code'];
		switch ($codetype) {
			case 'engine':
				$res = $this->get('bc_product_modengine', ['pme_men_code, pme_remark'], sprintf(" and pme_pro_id=%d", $proId));
				$formShopModelLink = array_column($res['data'], null, 'pme_men_code');
				break;
			case 'chassis':
				$res = $this->get('bc_product_modchassis', ['pmc_mch_code', 'pmc_remark'], sprintf(" and pmc_pro_id=%d", $proId));
				$formShopModelLink = array_column($res['data'], null, 'pmc_mch_code');
				break;
			default:
				$codetype ='all';
				$res = $this->get('bc_product_model3_link', ['pml3_mod3_id', 'pml3_remark'], sprintf(" and pml3_pro_id=%d", $proId));
				$formShopModelLink = array_column($res['data'], null, 'pml3_mod3_id');
				break;
		}

		$toShopIdArr = array_column($synchSetting['data'],'sss_shop_id_to');
		$toShopId = implode(',',$toShopIdArr);
		$whereSql = sprintf(" and sssp_pri_code_from = '%s' and sssp_shop_id_to in (%s) and sssp_shop_id_from = %d", $fnumFormat,$toShopId, $shopId);
		$synchProductInfo = $this->get('sh_shop_synch_product', ['sssp_shop_id_to,sssp_shop_id_from,sssp_pri_code_to'], $whereSql);
		//是否存在商品配置
		if(empty($synchProductInfo['data'])){
			$whereSql = sprintf(" and sssp_pri_code_from = '%s' and sssp_shop_id_to in (%s) and sssp_shop_id_from = %d", $fnumDisplay,$toShopId, $shopId);
			$synchProductInfo = $this->get('sh_shop_synch_product', ['sssp_shop_id_to,sssp_shop_id_from,sssp_pri_code_to'], $whereSql);
			if(empty($synchProductInfo['data'])) return LibFc::ReturnData(true);
		}
		$tnumFormatArr = array_column($synchProductInfo['data'],'sssp_pri_code_to');
		$tnumFormatArr = array_map(function($item){
			return sprintf("'%s'",$item);
		},$tnumFormatArr); 
		$tnumFormat =implode(',',$tnumFormatArr);
		$where = sprintf(" and num_format in (%s) and pro_shop_id in (%s) and num_self=1 and num_show = 1", $tnumFormat, $toShopId);
		$toShopModelLinks = $this->get($table, ['pro_id', 'num_format', 'pro_shop_id','pro_smt_code'],$where);
		//目标自编码是否存在	
		if(empty($toShopModelLinks['data'])){
			$where = sprintf(" and num_display in (%s) and pro_shop_id in (%s) and num_self=1 and num_show = 1", $tnumFormat, $toShopId);
			$toShopModelLinks = $this->get($table, ['pro_id', 'num_display as num_format', 'pro_shop_id','pro_smt_code'],$where);
			if(empty($toShopModelLinks['data'])) return LibFc::ReturnData(true);
		}
		$toShopModelLink  = [];
		foreach ($toShopModelLinks['data'] as $value) {
			$toShopModelLink[$value['pro_shop_id']][$value['pro_id']]['type'] =$value['pro_smt_code'];
			switch ($value['pro_smt_code']) {
				case 'engine':
					$res = $this->get('bc_product_modengine', ['pme_men_code, pme_remark'], sprintf(" and pme_pro_id=%d", $value['pro_id']));
					$toShopModelLink[$value['pro_shop_id']][$value['pro_id']]['data'] = array_column($res['data'],null,'pme_men_code');
					break;
				case 'chassis':
					$res = $this->get('bc_product_modchassis', ['pmc_mch_code', 'pmc_remark'], sprintf(" and pmc_pro_id=%d", $value['pro_id']));
					$toShopModelLink[$value['pro_shop_id']][$value['pro_id']]['data'] = array_column($res['data'],null,'pmc_mch_code');
					break;
				default:
					$toShopModelLink[$value['pro_shop_id']][$value['pro_id']]['type'] = 'all';
					$res = $this->get('bc_product_model3_link', ['pml3_mod3_id', 'pml3_remark'], sprintf(" and pml3_pro_id=%d", $value['pro_id']));
					$toShopModelLink[$value['pro_shop_id']][$value['pro_id']]['data'] = array_column($res['data'],null,'pml3_mod3_id');
					break;
			}
			
		}
		foreach ($synchSetting['data'] as $sItem) {
			$sss_act = json_decode($sItem['sss_act'], true);
			$style = $sss_act['model'];
			if(!isset($toShopModelLink[$sItem['sss_shop_id_to']]) || !$style) continue;

			foreach ($toShopModelLink[$sItem['sss_shop_id_to']] as $key => $item) 
			{
				$temp = $formShopModelLink;
				if($style == 'add' && $codetype == $item['type'])
				{
					// 如果两者车型类型一致则合并
					if(!empty($item['data']) && !empty($temp))
					{
						if($item['type'] =='all'){
							foreach ($item['data'] as $val) {
								if(!$temp[$val['pml3_mod3_id']]){
									$temp[$val['pml3_mod3_id']] = $val;
								}
							}
						}else{
							$temp = array_merge($item['data'],$temp);
						}
					}
				}
				switch ($codetype) {
					case 'engine':
						$this->setProductModEngine($key,$temp);
						break;
					case 'chassis':
						$this->setProductModChassis($key,$temp);
						break;
					default:
						$this->setProductModel($key,$temp,'SHOP');
						break;
				}
				
			}
		}
		return LibFc::ReturnData(true);
	}

	/**
	* @param  int $shopId
	* @param  int $proId 商品id
	* @method 同步商品号码 
	* @author zhengweihua 
	* @copyright 2022-09-20
	*/
	public function syncNumber($shopId,$proId)
	{
		$where = sprintf("and sss_shop_id_from = %d and sss_act !='' and sss_shop_id_to !=0", $shopId);
		$synchSetting =	$this->get("sh_shop_synch", ['*'], $where);
		if (empty($synchSetting['data'])) {
			return LibFc::ReturnData(true);
		}
		
		$field = ['num_pro_id','num_factory','num_self','num_display','num_show','num_from','num_fromid','num_ismain','num_format'];
		$numberArr = $this->get('bc_number',$field,sprintf(" and num_pro_id = %d",$proId));
		
		if(empty($numberArr['data'])) return LibFc::ReturnData(true);
		$arr = [];
		$selfitem = [];
		foreach ($numberArr['data'] as $key => $value) {
			unset($value['num_pro_id']);
			if(empty($value['num_self'])){
				$arr[]  = $value;
			}else{
				$selfitem = $value;
			}
		}
		if(empty($selfitem)) return LibFc::ReturnData(true);
		$toShopArr = array_column($synchSetting['data'],'sss_shop_id_to');
		$toShopId = implode(',',$toShopArr);
		$whereSql = sprintf(" and sssp_pri_code_from = '%s' and sssp_shop_id_to in (%s) and sssp_shop_id_from = %d", $selfitem['num_format'], $toShopId, $shopId);
		$synchProductInfo = $this->get('sh_shop_synch_product', ['*'], $whereSql);
		//是否存在商品配置
		if(empty($synchProductInfo['data'])){
			$whereSql = sprintf(" and sssp_pri_code_from = '%s' and sssp_shop_id_to in (%s) and sssp_shop_id_from = %d", $selfitem['num_display'], $toShopId, $shopId);
			$synchProductInfo = $this->get('sh_shop_synch_product', ['*'], $whereSql);	
			if(empty($synchProductInfo['data'])) return LibFc::ReturnData(true);
		}
		//目标自编码对应商品信息
		$tnumFormatArr =array_column($synchProductInfo['data'],'sssp_pri_code_to');
		$tnumFormatArr = array_map(function($item){
			return sprintf("'%s'",$item);
		},$tnumFormatArr);
		$tnumFormat = implode(',',$tnumFormatArr);
		//目标自编码对应的产品id
		$toProdcutInfo  = $this->get('bc_number join bc_product on pro_id=num_pro_id',['num_pro_id'],sprintf(" and num_format in (%s) and pro_shop_id in (%s)",$tnumFormat, $toShopId));
		if(empty($toProdcutInfo['data'])){
			$toProdcutInfo  = $this->get('bc_number join bc_product on pro_id=num_pro_id',['num_pro_id'],sprintf(" and num_display in (%s) and pro_shop_id in (%s)",$tnumFormat, $toShopId));
			if(empty($toProdcutInfo['data']))  return LibFc::ReturnData(true);
		}
		
		$numProArr = array_column($toProdcutInfo['data'],'num_pro_id');
		$numProId = implode(',',$numProArr);
		//目标自编码对应的产品已存在的编码
		$field = ['num_factory','num_self','num_display','num_show','num_from','num_fromid','num_ismain','num_format','num_pro_id','pro_shop_id'];
		$toProdcutRes = $this->get('bc_number join bc_product on pro_id=num_pro_id',$field,sprintf(" and num_self=0 and num_pro_id in (%s) and pro_shop_id in (%s)",$numProId, $toShopId));
		$toProdcutNumArr = [];
		foreach ($toProdcutRes['data'] as $tItem) {
			$pro_shop_id = $tItem['pro_shop_id'];
			$num_pro_id = $tItem['num_pro_id'];
			unset($tItem['pro_shop_id'],$tItem['num_pro_id']);
			$toProdcutNumArr[$pro_shop_id][$num_pro_id][] = $tItem;
		}
		foreach ($synchSetting['data'] as $sItem) {
			$sss_act = json_decode($sItem['sss_act'], true);
			$style = $sss_act['number'];
			if(!$style || !isset($toProdcutNumArr[$sItem['sss_shop_id_to']])) continue; 
			foreach ($toProdcutNumArr[$sItem['sss_shop_id_to']] as $proId => $pItem) {

				$temp = $arr;
				if($style == 'add')
				{
					if(!empty($pItem))
					{
						$temp = array_merge($temp,$pItem);
					}
				}
				$this->setProductNum($proId,$temp);
			}
		}
		
		return LibFc::ReturnData(true);
	}

	/**
	* @param  int $fromShopId
	* @param  int $toShopId
	* @param  int $proId 商品id
	* @method 同步产品
	* @author zhengweihua 
	* @copyright 2022-10-21
	*/
	public function copyProduct($fromShopId, $toShopId, $fromProId,$sysAct = [])
	{
		$defaultsysAct = [
			'price'=>1,
			'shopsort'=>0,
			'params'=>1,
			'pic'=>1
		];
		$sysAct = array_merge($defaultsysAct,$sysAct);
		
		$where = sprintf(" and pro_shop_id = %d  and pro_id = %d", $fromShopId,$fromProId);
		$pres = $this->get('bc_product left join bc_product_para_tpl on ppt_id = pro_ppt_id', ['bc_product.*,ppt_name'], $where,true);
		
		$dataArr['base'] = array_filter($pres['data']);
		$dataArr['base']['pro_shop_id'] = $toShopId;
		$dataArr['base']['pro_dfrom'] = 'shop_'.$fromShopId;
		$dataArr['base']['pro_dfrom_id'] = $fromProId;
		$ppt_name = $dataArr['base']['ppt_name']?:'默认模板';
		
		
		unset($dataArr['base']['ppt_name']);
		unset($dataArr['base']['pro_add_time']);
		unset($dataArr['base']['pro_set_time']);
		unset($dataArr['base']['pro_status_ltime']);
		unset($dataArr['base']['pro_status_notice']);
		unset($dataArr['base']['pro_id']);

		$res = $this->get('bc_product_info', ['*'], sprintf(" and pri_pro_id=%d", $fromProId), true);
		$dataArr['info'] = array_filter($res['data']);
		unset($dataArr['info']['pri_pro_id']);

		$res = $this->get('bc_number', ['*'], sprintf(" and num_self=0 and num_pro_id=%d", $fromProId));
		$dataArr['nums'] = $res['data'];
		foreach($dataArr['nums'] as &$tv)
		{
			unset($tv['num_pro_id']);
			unset($tv['num_id']);
		}
		unset($tv);
		//同步图片
		if($sysAct['pic']==1)
		{
			$res = $this->get('bc_product_pic', ['pp_spi_id'], sprintf(" and pp_pro_id=%d order by pp_ismain desc, pp_seq", $fromProId));
			$dataArr['imgs'] = array_column($res['data'], 'pp_spi_id');
		}

		if($dataArr['base']['pro_smt_code']=='engine'){
			$res = $this->get('bc_product_modengine', ['pme_men_code','pme_remark'], sprintf(" and pme_pro_id=%d", $fromProId));
			$dataArr['modengine'] = $res['data'];
		}elseif ($dataArr['base']['pro_smt_code']=='chassis') {
			$res = $this->get('bc_product_modchassis', ['pmc_mch_code','pmc_remark'], sprintf(" and pmc_pro_id=%d", $fromProId));
			$dataArr['modchassis'] = $res['data'];
		}else{
			$res = $this->get('bc_product_model3_link', ['pml3_mod3_id','pml3_remark'], sprintf(" and pml3_pro_id=%d", $fromProId));
			$dataArr['model'] = $res['data'];
		}
		$res = $this->get('bc_product', ['*'], sprintf(" and pro_shop_id = %d and pro_dfrom='%s' and pro_dfrom_id=%d", $dataArr['base']['pro_shop_id'], $dataArr['base']['pro_dfrom'], $dataArr['base']['pro_dfrom_id']), true);
		$toProInfo = $res['data'];
		//同步价格 (不同步则取原来价格)
		if($sysAct['price']!=1)
		{
			$dataArr['base']['pro_cost_price'] = $toProInfo['pro_cost_price']??0;
			$dataArr['base']['pro_sale_price'] = $toProInfo['pro_sale_price']??0;
			$dataArr['base']['pro_price_vip1'] = $toProInfo['pro_price_vip1']??0;
			$dataArr['base']['pro_price_vip2'] = $toProInfo['pro_price_vip2']??0;
			$dataArr['base']['pro_price_vip3'] = $toProInfo['pro_price_vip3']??0;
			$dataArr['base']['pro_price_vip4'] = $toProInfo['pro_price_vip4']??0;
		}
		//同步参数
		if($sysAct['params']==1)
		{
			$pro_param  =[];
			$table = 'bc_product_para_val 
			join bc_product_label on prl_id = prpv_prl_id
			left join bc_product_unit on pru_id = prpv_pru_id';
			$selfParamRes  = $this->get($table,['*'],sprintf(" and prpv_pro_id=%d",$fromProId));
			if($selfParamRes['data']){
				foreach ($selfParamRes['data'] as $key => $val) {
					$pro_param[] = [$val['prl_name'],$val['prpv_value'],$val['pru_name']];
				} 
			}

			$dataArr['param'] = [];
			$res = $this->get('bc_product_param_float', ['ppf_pal_id, ppf_value'], sprintf(" and ppf_pro_id=%d", $fromProId));
			$dataArr['param'] = array_column($res['data'], 'ppf_value', 'ppf_pal_id');

			$res = $this->get('bc_product_param_string', ['pps_pal_id, pps_value'], sprintf(" and pps_pro_id=%d", $fromProId));
			foreach($res['data'] as $tv)
			{
				$dataArr['param'][$tv['pps_pal_id']] = $tv['pps_value'];
			}
		}

		//同步店铺分类
		if($sysAct['shopsort']==1)
		{
			$dataArr['shopSort'] = [];
			$table = 'bc_product_sort 
			join sh_sort on prs_sort_id = sort_id
			join sh_sort_tree on sot_sort_id = sort_id';
			$res = $this->get($table,['*'],sprintf(" and prs_pro_id=%d", $fromProId));
			if($res['data'])
			{
				$proShopSort = [];
				foreach ($res['data'] as $key => $val) 
				{		
					if($val['sot_psort_id']==0){
						$proShopSort[$val['sot_sort_id']]['level1']=$val['sort_name'];
					}
					if($val['sot_psort_id']!=0){
						$proShopSort[$val['sot_psort_id']]['level2'][]=$val['sort_name'];
					}
				}
				$curProShopSort = [];
				foreach ($proShopSort as $fsortId => $val) 
				{
					if($val['level2'])
					{
						foreach ($val['level2'] as $vv) {
							$curProShopSort[] = ['level1'=>$proShopSort[$fsortId]['level1'],'level2'=>$vv];
						}
					}else{

						$curProShopSort[] = ['level1'=>$proShopSort[$fsortId]['level1'],'level2'=>''];
					}
				}
				$B2cShopSort = new B2cShopSort();
				$B2cShopSort->batchAddShopSort($toShopId,$curProShopSort);
				$allShopSortRes = $B2cShopSort->getAllShopSort($toShopId,false);
				$allShopSortArr = $allShopSortRes['data'];
				$arr1 = [];
				$arr2 = [];
				foreach ($allShopSortArr as $sortId => $sortArr) {
					if($sortArr['psort_id']==0){
						$arr1[$sortArr['sort_name']] = $sortArr['sort_id'];
					}else{
						$arr2[$sortArr['psort_id']][$sortArr['sort_name']] = $sortArr['sort_id'];
					}
				}
				$shopSort = [];
				foreach($curProShopSort as $val)
				{	
					if($arr1[$val['level1']]){
						$shopSort[] =$arr1[$val['level1']];
						
						if($arr2[$arr1[$val['level1']]][$val['level2']])
						{
							$shopSort[] =$arr2[$arr1[$val['level1']]][$val['level2']];
						}
					}	
				}
				$dataArr['shopSort'] = array_unique($shopSort);
			}
			
		}

		$this->B2CDb->Begin();
		if(!empty($toProInfo))
		{
			$this->setProduct($toShopId, $toProInfo['pro_id'], $dataArr);
			$proId = $toProInfo['pro_id'];
		}
		else
		{
			$res = $this->addProduct($dataArr, $toShopId);
			$proId = $res['data'];
		}

		if($pro_param){
			$this->batchChangeParam($proId, $toShopId, $pro_param,$ppt_name);
		}
		
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}
	
	/**
	 * @method 设置店铺产品同步
	 * @param  $shopid int [必填] 店铺ID
	 * @param   $params array 其他参数
	 * @author zhengweihua 
	 * @copyright 2022-10-21
	 */
	public function setProSyn($shopid,$params = [])
	{
		if(empty($params)) return LibFc::ReturnData(false, '获取信息失败');
		$sps_id = $params['sps_id']??'';
		$where = sprintf(" and ((sps_from_shop_id = %d and sps_to_shop_id = %d) or (sps_from_shop_id = %d and sps_to_shop_id = %d))",$shopid,$params['sps_to_shop_id'],$params['sps_to_shop_id'],$shopid);
		if($sps_id){
			$where .= sprintf(" and sps_id !=%d",$sps_id);
		} 

		$synres = $this->get('sh_prosyn',['sps_id'],$where,true);
		if($synres['data']) return LibFc::ReturnData(false, '目标代理商已存在配置，不可重复设置');

		$this->B2CDb->Begin();
		$data = [
			'sps_status' => $params['sps_status'],
			'sps_from_shop_id' => $shopid,
			'sps_to_shop_id' => $params['sps_to_shop_id'],
			'sps_atime' => time(),
			'sps_remark' => $params['sps_remark'],
			'sps_act'=>$params['sps_act']?json_encode($params['sps_act']):''
		];
		$logtxt = '添加';
		if($sps_id)
		{	
			$orgdata = $this->get('sh_prosyn',['*'],sprintf(" and sps_id=%d",$sps_id),true);
			$logtxt = '编辑';
			if($orgdata['data']['sps_status']!=$data['sps_status']){
				$logtxt2 = '状态变更为'.($data['sps_status']==1?"启用":"暂停");
			}
			$res = $this->set('sh_prosyn',$data,sprintf(" and sps_id = %d",$sps_id));	
		}else{
			$res = $this->add('sh_prosyn',$data);
			$sps_id = $res['data'];
		}
		if($sps_id)
		{	
			//配件分类
			$oldSpsres = $this->get('sh_prosyn_part',['spp_part_id'],sprintf(" and spp_sps_id = %d",$sps_id));
			$oldSpsArr =  $oldSpsres['data']?array_column($oldSpsres['data'],'spp_part_id'):[];
			$newSpsArr = $params['sps_part_id']? explode(',',$params['sps_part_id']):[];
			$delSpsArr = array_diff($oldSpsArr,$newSpsArr);
			$addSpsArr = array_diff($newSpsArr,$oldSpsArr);
	
			if($delSpsArr){
				$this->del('sh_prosyn_part',sprintf(" and spp_part_id in (%s) and spp_sps_id = %d",implode(',',$delSpsArr),$sps_id));
			}
			if($addSpsArr){
				$arr = [];
				foreach ($addSpsArr as $key => $addItem) {
					$arr[] = ['spp_sps_id'=>$sps_id,'spp_part_id'=>$addItem];
				}
				$this->addAny('sh_prosyn_part',['spp_sps_id','spp_part_id'],$arr);
			}

			//店铺分类
			$oldSpsres = $this->get('sh_prosyn_sort',['spt_sort_id'],sprintf(" and spt_sps_id = %d",$sps_id));
			$oldSpsArr =  $oldSpsres['data']?array_column($oldSpsres['data'],'spt_sort_id'):[];
			$newSpsArr = $params['spt_sort_id']? explode(',',$params['spt_sort_id']):[];
			$delSpsArr = array_diff($oldSpsArr,$newSpsArr);
			$addSpsArr = array_diff($newSpsArr,$oldSpsArr);
	
			if($delSpsArr){
				$this->del('sh_prosyn_sort',sprintf(" and spt_sort_id in (%s) and spt_sps_id = %d",implode(',',$delSpsArr),$sps_id));
			}
			if($addSpsArr){
				$arr = [];
				foreach ($addSpsArr as $key => $addItem) {
					$arr[] = ['spt_sps_id'=>$sps_id,'spt_sort_id'=>$addItem];
				}
				$this->addAny('sh_prosyn_sort',['spt_sps_id','spt_sort_id'],$arr);
			}
			//配件品牌
			$oldPrbres = $this->get('sh_prosyn_probrand',['spb_prb_id'],sprintf(" and spb_sps_id = %d",$sps_id));
			$oldPrbArr =  $oldPrbres['data'] ? array_column($oldPrbres['data'], 'spb_prb_id') : [];
			$newPrbArr = $params['spb_prb_id']? array_filter($params['spb_prb_id']):[];

			$delPrbArr = array_diff($oldPrbArr,$newPrbArr);
			$addPrbArr = array_diff($newPrbArr,$oldPrbArr);
			if($delPrbArr){
				$this->del('sh_prosyn_probrand',sprintf(" and spb_prb_id in (%s) and spb_sps_id = %d",implode(',',$delPrbArr),$sps_id));
			}
			if($addPrbArr){
				$arr = [];
				foreach ($addPrbArr as $key => $addItem) {
					$arr[] = ['spb_sps_id'=>$sps_id,'spb_prb_id'=>$addItem];
				}
				$this->addAny('sh_prosyn_probrand',['spb_sps_id','spb_prb_id'],$arr);
			}
		}
		$B2cLog = new B2cLog();
		$shopinfo = $this->get('sh_shop',['shop_name'],sprintf(" and shop_id = %d",$params['sps_to_shop_id']),true);	
		$item = [
			'log_category'=>21,
			'log_shop_id'=>$shopid,
			'log_atime'=>time(),
			'log_dataid'=>$sps_id,
			'log_txt'=>$logtxt.'代理商授权：'.$shopinfo['data']['shop_name'].$logtxt2,
			'log_orgdata'=>json_encode($orgdata['data']?:$params),
		];
		$B2cLog->addFastLog($item);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $sps_id);
	}
	/**
	* @param  int $shopId  商城id
	* @param  array $syncParams  [[分类id],[店铺id],[配件品牌id]]
	* @param  string $act  set 更新（需代理商确认）
	* @method 获取产品同步配置
	* @author zhengweihua 
	* @copyright 2022-10-21
	*/
	protected function getProSynSet($shopId,$syncParams = [],$act = 'set')
	{
		
		$where = sprintf(" and sps_from_shop_id = %d and sps_status =1", $shopId);
		if($act == 'set')
		{
			$where .= " and sps_chkstatus = 1";
		}
		$toShopArr = [];
		if($syncParams['partId']){
			$table = 'sh_prosyn join sh_prosyn_part on spp_sps_id = sps_id';
			$where1 = $where.sprintf(" and spp_part_id in (%s)",implode(',',$syncParams['partId']) );

			$prosynres = $this->get($table,['distinct sps_to_shop_id,sps_act'],$where1);
			$toShopArr =$prosynres['data']? array_column($prosynres['data'],null,'sps_to_shop_id'):$toShopArr;
		}
		if($syncParams['sortId']){
			$table = 'sh_prosyn join sh_prosyn_sort on spt_sps_id = sps_id';
			$where2 = $where.sprintf(" and spt_sort_id in (%s)",implode(',',$syncParams['sortId']) );
			$prosynres = $this->get($table,['distinct sps_to_shop_id,sps_act'],$where2);
			$toShopArr  =  $prosynres['data']? array_merge(array_column($prosynres['data'],null,'sps_to_shop_id'),$toShopArr):$toShopArr;
		}
		if($syncParams['prbId']){
			$table = 'sh_prosyn join sh_prosyn_probrand on spb_sps_id = sps_id';
			$where2 = $where.sprintf(" and spb_prb_id=%d",$syncParams['prbId']);
			$prosynres = $this->get($table,['distinct sps_to_shop_id,sps_act'],$where2);
			$toShopArr  =  $prosynres['data']? array_merge(array_column($prosynres['data'],null,'sps_to_shop_id'),$toShopArr):$toShopArr;
		}
		
		return array_filter($toShopArr);
	}
	/**
	* @param  int $shopId
	* @param  array $spsIds  产品同步配置ID
	* @param  array $from  daili 代理商操作 shouquan 授权商操作
	* @param  int  $delStatus 保留1 删除0
	* @method 删除产品同步配置
	* @author zhengweihua 
	* @copyright 2022-10-21
	*/
	public function delProSyn($shopId,$from ='',$spsIds = [],$delStatus = 0)
	{
		if(empty($spsIds)||!in_array($from,['daili','shouquan'])) return LibFc::ReturnData(false, '提供的参数不正确');
		$this->B2CDb->Begin();

		$where = '';
		if($from == 'daili'){
			$where = sprintf(" and sps_to_shop_id = %d",$shopId);
		}elseif($from == 'shouquan'){
			$where = sprintf(" and sps_from_shop_id = %d",$shopId);
		}
		$res = $this->get('sh_prosyn',['sps_to_shop_id','sps_from_shop_id','sps_id'],sprintf(" %s and sps_id in (%s)",$where,implode(',',$spsIds)));
		if(empty($res['data'])) return LibFc::ReturnData(false, '提供的参数不正确');

		$spsIds = array_column($res['data'],'sps_id');

		$this->del('sh_prosyn',sprintf(" and sps_id in (%s)",implode(',',$spsIds)));
		$this->del('sh_prosyn_part',sprintf(" and spp_sps_id in (%s)",implode(',',$spsIds)));
		$this->del('sh_prosyn_sort',sprintf(" and spt_sps_id in (%s)",implode(',',$spsIds)));
		if($from == 'daili')
		{
			$fromShopArr = array_column($res['data'],'sps_from_shop_id');
			$shopIdArr =array_map(function($item){
				return sprintf("'shop_%s'",$item);
			},$fromShopArr);
			$where = sprintf(" and pro_shop_id = %d and pro_dfrom in (%s)",$shopId,implode(',',$shopIdArr));
		}else if($from == 'shouquan'){
			$shopIdArr = array_column($res['data'],'sps_to_shop_id');
			$where = sprintf(" and pro_shop_id in (%d) and pro_dfrom = '%s'",implode(',',$shopIdArr),'shop_'.$shopId);
		}

		$toProArr = [];
		$toProArrRes = $this->get('bc_product',['pro_id','pro_shop_id'],$where);

		if($toProArrRes['data'] )
		{
			if($delStatus ==0)
			{
				foreach ($toProArrRes['data'] as $item) {
					$toProArr[$item['pro_shop_id']][] = $item['pro_id'];
				}
				foreach ($toProArr as $key => $proArr) {
					$this->delProduct($key,$proArr);
				}
			}
			elseif($delStatus ==1)
			{	
				$proIdArr =	array_column($toProArrRes['data'],'pro_id');
				$where = sprintf(" and pro_id in (%s)",implode(',',$proIdArr));
				$toProArrRes = $this->set('bc_product',['pro_dfrom'=>'','pro_dfrom_id'=>0],$where);
			}
			
		}
		//操作日志
		$B2clog = new B2cLog();
		if($from == 'daili')
		{
			$shopIdArr = array_column($res['data'],null,'sps_from_shop_id');
		}else{
			$shopIdArr = array_column($res['data'],null,'sps_to_shop_id');
		}
		foreach ($shopIdArr as $skey => $sval) 
		{	
			$shopinfo = $this->get('sh_shop',['shop_name'],sprintf(" and shop_id = %d",$skey),true);
			$logtxt = $shopinfo['data']['shop_name'];
			$logtxt .= $delStatus == 0 ? '(删除数据)' : '(保留数据)';
			$item = [
				'log_category'=>21,
				'log_shop_id'=>$shopId,
				'log_atime'=>time(),
				'log_dataid'=>$sval['sps_id'],
				'log_txt'=>'删除代理商授权：'.$logtxt,
				'log_orgdata'=>json_encode($sval),
			];
			$B2clog->addFastLog($item);
		}
		
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}
	/**
	* @param  int $shopId  来源店铺id
	* @param  array $sps_id  产品同步配置ID
	* @method 执行产品同步配置
	* @author zhengweihua 
	* @copyright 2022-10-21
	 */
	public function doProSyn($shopid,$sps_id)
	{
		
		$table = 'sh_prosyn';
		$where = sprintf(" and sps_id = %d and sps_from_shop_id = %d", $sps_id,$shopid);
		$proSynRes = $this->get($table,['sps_to_shop_id,sps_act'],$where,true);
		if(empty($proSynRes['data'])) return LibFc::ReturnData(false,'参数错误');

		$toShopId = $proSynRes['data']['sps_to_shop_id'];
		$defaultsysAct = [
			'price'=>1,
			'shopsort'=>0,
			'params'=>1,
			'pic'=>1
		];
		//同步配置
		$sysAct = $proSynRes['data']['sps_act']?json_decode($proSynRes['data']['sps_act'],true):[];
		$sysAct = array_merge($defaultsysAct,$sysAct);
		if($sysAct['type']=='part')
		{
			//配件分类关联的产品
			$table = 'sh_prosyn_part join bc_product on spp_part_id = pro_part_id';
			$proRes = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spp_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes['data'],'pro_id');
		}
		
		if($sysAct['type']=='sort')
		{
			//店铺分类关联的产品
			$table = 'sh_prosyn_sort 
			join bc_product_sort on prs_sort_id = spt_sort_id
			join bc_product on pro_id = prs_pro_id';
			$proRes1 = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spt_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes1['data'],'pro_id');
		}
		
		if($sysAct['type']=='brand')
		{
			//配件品牌关联的产品
			$table = 'bc_product
			join sh_prosyn_probrand on pro_prb_id = spb_prb_id';
			$proRes2 = $this->get($table,['pro_id'],sprintf(" AND pro_shop_id=%d AND spb_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes2['data'],'pro_id');
		}
		
		
		$where = sprintf(" and pro_shop_id = %d and pro_dfrom = '%s' ",$toShopId,'shop_'.$shopid);
		$toProRes = $this->get('bc_product',['pro_dfrom','pro_dfrom_id','pro_id'],$where);
		$toProIdArr = $toProRes['data']?array_column($toProRes['data'],'pro_dfrom_id'):[];
		$toProArr = $toProRes['data']?array_column($toProRes['data'],'pro_id','pro_dfrom_id'):[];
		$delIdArr = array_diff($toProIdArr,$proArr);

		$this->B2CDb->Begin();
		if($delIdArr)
		{
			$toDelIdArr = [];
			foreach ($delIdArr as $delId) {
				$toDelIdArr[] = $toProArr[$delId];
			}
			if($toDelIdArr) $this->delProduct($toShopId,$toDelIdArr);
		}
		if($proArr)
		{
			foreach ($proArr as $pro_id) 
			{
				$this->copyProduct($shopid,$toShopId,$pro_id,$sysAct);
			}
		}
		$B2cLog = new B2cLog();
		if($_SESSION['_shopid']==$toShopId){
			$shopInfo = $this->get('sh_shop',['shop_id','shop_name'],sprintf(" and shop_id = %d",$shopid),true);
			$logtxt = '授权店铺：'.$shopInfo['data']['shop_name'];
		}else{
			$shopInfo = $this->get('sh_shop',['shop_id','shop_name'],sprintf(" and shop_id = %d",$toShopId),true);
			$logtxt = '代理店铺：'.$shopInfo['data']['shop_name'];
		}
		$item = [
			'log_category'=>21,
			'log_shop_id'=>$_SESSION['_shopid'],
			'log_atime'=>time(),
			'log_dataid'=>$sps_id,
			'log_txt'=>'代理配件同步'.$logtxt
		];
		$B2cLog->addFastLog($item);
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}

	/**
	 * @param  [type] $shopid
	 * @param  [type] $sps_id
	 * @method 获取当前可以同步产品总数
	 * @author zhengweihua 
	 * @copyright 2025-11-10
	 */
	public function getProSynProd($shopid,$sps_id)
	{
		$table = 'sh_prosyn';
		$where = sprintf(" and sps_id = %d and sps_from_shop_id = %d", $sps_id,$shopid);
		$proSynRes = $this->get($table,['sps_to_shop_id,sps_act'],$where,true);
		if(empty($proSynRes['data'])) return LibFc::ReturnData(false,'参数错误');
		$toShopId = $proSynRes['data']['sps_to_shop_id'];
		$defaultsysAct = [
			'price'=>1,
			'shopsort'=>0,
			'params'=>1,
			'pic'=>1
		];
		//同步配置
		$sysAct = $proSynRes['data']['sps_act']?json_decode($proSynRes['data']['sps_act'],true):[];
		$sysAct = array_merge($defaultsysAct,$sysAct);
		if($sysAct['type']=='part')
		{
			//配件分类关联的产品
			$table = 'sh_prosyn_part join bc_product on spp_part_id = pro_part_id';
			$proRes = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spp_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes['data'],'pro_id');
		}
		
		if($sysAct['type']=='sort')
		{
			//店铺分类关联的产品
			$table = 'sh_prosyn_sort 
			join bc_product_sort on prs_sort_id = spt_sort_id
			join bc_product on pro_id = prs_pro_id';
			$proRes1 = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spt_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes1['data'],'pro_id');
		}
		
		if($sysAct['type']=='brand')
		{
			//配件品牌关联的产品
			$table = 'bc_product
			join sh_prosyn_probrand on pro_prb_id = spb_prb_id';
			$proRes2 = $this->get($table,['pro_id'],sprintf(" AND pro_shop_id=%d AND spb_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes2['data'],'pro_id');
		}

			
		$B2cLog = new B2cLog();
		if ($_SESSION['_shopid'] == $toShopId) {
			$shopInfo = $this->get('sh_shop', ['shop_id', 'shop_name'], sprintf(" and shop_id = %d", $shopid), true);
			$logtxt = '授权店铺：' . $shopInfo['data']['shop_name'];
		} else {
			$shopInfo = $this->get('sh_shop', ['shop_id', 'shop_name'], sprintf(" and shop_id = %d", $toShopId), true);
			$logtxt = '代理店铺：' . $shopInfo['data']['shop_name'];
		}
		$item = [
			'log_category' => 21,
			'log_shop_id' => $_SESSION['_shopid'],
			'log_atime' => time(),
			'log_dataid' => $sps_id,
			'log_txt' => '代理配件同步' . $logtxt
		];
		$B2cLog->addFastLog($item);

		return LibFc::ReturnData(true, $proArr);
	}

	/**
	 * @param int $shopid 来源店铺id
	 * @param array $sps_id 产品同步配置ID
	 * @param array $proIds 需要同步的产品ID数组
	 * @method 分批执行产品同步
	 * @author zhengweihua 
	 */
	public function doBatchProSyn($shopid, $sps_id, $proIds)
	{		
		$table = 'sh_prosyn';
		$where = sprintf(" and sps_id = %d and sps_from_shop_id = %d", $sps_id,$shopid);
		$proSynRes = $this->get($table,['sps_to_shop_id,sps_act'],$where,true);
		if(empty($proSynRes['data'])) return LibFc::ReturnData(false,'参数错误');

		$toShopId = $proSynRes['data']['sps_to_shop_id'];
		$defaultsysAct = [
			'price'=>1,
			'shopsort'=>0,
			'params'=>1,
			'pic'=>1
		];
		//同步配置
		$sysAct = $proSynRes['data']['sps_act']?json_decode($proSynRes['data']['sps_act'],true):[];
		$sysAct = array_merge($defaultsysAct,$sysAct);
		
		// 同步产品
		if (!empty($proIds)) {
			foreach ($proIds as $pro_id) {
				$this->copyProduct($shopid, $toShopId, $pro_id, $sysAct);
			}
		}

		return LibFc::ReturnData(true, true);
	}
	/**
	 * @param  [type] $shopid
	 * @param  [type] $sps_id
	 * @method 删除不在配置中的商品
	 * @author zhengweihua 
	 * @copyright 2025-11-10
	 */
	public function doDeleteProSyn($shopid,$sps_id)
	{	
		$table = 'sh_prosyn';
		$where = sprintf(" and sps_id = %d and sps_from_shop_id = %d", $sps_id,$shopid);
		$proSynRes = $this->get($table,['sps_to_shop_id,sps_act'],$where,true);
		if(empty($proSynRes['data'])) return LibFc::ReturnData(false,'参数错误');

		$toShopId = $proSynRes['data']['sps_to_shop_id'];
		$defaultsysAct = [
			'price'=>1,
			'shopsort'=>0,
			'params'=>1,
			'pic'=>1
		];
		//同步配置
		$sysAct = $proSynRes['data']['sps_act']?json_decode($proSynRes['data']['sps_act'],true):[];
		$sysAct = array_merge($defaultsysAct,$sysAct);
		if($sysAct['type']=='part')
		{
			//配件分类关联的产品
			$table = 'sh_prosyn_part join bc_product on spp_part_id = pro_part_id';
			$proRes = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spp_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes['data'],'pro_id');
		}
		
		if($sysAct['type']=='sort')
		{
			//店铺分类关联的产品
			$table = 'sh_prosyn_sort 
			join bc_product_sort on prs_sort_id = spt_sort_id
			join bc_product on pro_id = prs_pro_id';
			$proRes1 = $this->get($table,['pro_id'],sprintf("and pro_shop_id=%d and spt_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes1['data'],'pro_id');
		}
		
		if($sysAct['type']=='brand')
		{
			//配件品牌关联的产品
			$table = 'bc_product
			join sh_prosyn_probrand on pro_prb_id = spb_prb_id';
			$proRes2 = $this->get($table,['pro_id'],sprintf(" AND pro_shop_id=%d AND spb_sps_id=%d",$shopid,$sps_id));
			$proArr = array_column($proRes2['data'],'pro_id');
		}

		$where = sprintf(" and pro_shop_id = %d and pro_dfrom = '%s' ",$toShopId,'shop_'.$shopid);
		$toProRes = $this->get('bc_product',['pro_dfrom','pro_dfrom_id','pro_id'],$where);
		$toProIdArr = $toProRes['data']?array_column($toProRes['data'],'pro_dfrom_id'):[];
		$toProArr = $toProRes['data']?array_column($toProRes['data'],'pro_id','pro_dfrom_id'):[];
		$delIdArr = array_diff($toProIdArr,$proArr);
		
		if($delIdArr)
		{
			$toDelIdArr = [];
			foreach ($delIdArr as $delId) {
				$toDelIdArr[] = $toProArr[$delId];
			}
			if($toDelIdArr) $this->delProduct($toShopId,$toDelIdArr);
		}

		return LibFc::ReturnData(true, true);
	}

	public function importProModel($shopId,$optArr)
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$ext = strtolower(trim($optArr['ext']));
		if(!in_array($ext, ['xls', 'xlsx'])) return LibFc::ReturnData(false, '不支持'.$ext.'的表格！');
		$file = $optArr['dir'].$optArr['filename'].'.'.$ext;
		if($file){
			$OthExcel = new OthExcel();
			$res = $OthExcel->read($file, 0);
			$tempArr = $res['data'];
			$colHeader = $tempArr[1];
			$colArr = [];
			foreach($colHeader as $fk=>$filed)
			{
				if(stripos($filed, '车型ID') !== false)
				{
					$colArr['mod3Id'] = $fk;
				}
				else if(stripos($filed, '号码') !== false)
				{
					$colArr['num'][] = $fk;
				}
			}
			$modelArr = [];
			foreach($tempArr as $val)
			{
				if(!preg_match('/\d/', $val[$colArr['mod3Id']])) continue;
				$mod3Id = (int) $val[$colArr['mod3Id']];
				foreach($colArr['num'] as $fk)
				{
					if(!empty($val[$fk]))
					{
						$reArr = ["\r\n", "\n",'，', ',', '；'];
						$val[$fk] = str_replace($reArr, ';', $val[$fk]);
						foreach(explode(';', $val[$fk]) as $num)
						{
							$modelArr[$mod3Id][] = $num;
						}
					}
				}
			}
			return $this->importProductModel($shopId, $modelArr, $optArr['style']);
		}
		return LibFc::ReturnData(false,'文件不存在');
	}

	public function checkRelationAndRemark($shopId,$optArr)
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$ext = strtolower(trim($optArr['ext']));
		if(!in_array($ext, ['xls', 'xlsx'])) return LibFc::ReturnData(false, '不支持'.$ext.'的表格！');
		$file = $optArr['dir'].$optArr['filename'].'.'.$ext;
		if(file_exists($file))
		{	
			//系统默认的模式
			$res = $this->get('sh_super join sh_shop on shop_id = ssu_shop_id', ['shop_smt_code'],  sprintf(" and ssu_shop_id=%d", $shopId), true);
			$shop_smt_code = $res['data']['shop_smt_code'];

			$B2cPart = new B2cPart();
			$res = $B2cPart->getProductPart($shopId);
			$supPartNameArr = array_column($res['data'],'name');
		
			$OthExcel = new OthExcel();
			$res = $OthExcel->read($file,0);

			$tempArr = $res['data'];
			$colHeader = $tempArr[1];
			unset($tempArr[1]);
			$colArr = [
				'remark'=>'',
				'num'=>[]
			];
			$mtype = '';
			
			foreach($colHeader as $fk=>$filed)
			{	
				if($filed == 'mod3_id'){
					$colArr['mod3_id']	=  $fk;
					$mtype = 'all';
				}elseif($filed == 'mch_code'){
					$colArr['mch_code']	=  $fk;
					$mtype = 'chassis';
				}elseif($filed == 'men_code'){
					$colArr['men_code']	=  $fk;
					$mtype = 'engine';
				}
				if(in_array($filed,$supPartNameArr))
				{
					$colArr['num'][] = $fk;
				}
				if(stripos($filed, '号码') !== false)
				{
					$colArr['num'][] = $fk;
				}
				if((stripos($filed, '商家编码') !== false))
				{
					$colArr['num'][] = $fk;
				}
				if(stripos($filed, '车型备注') !== false)
				{
					$colArr['remark'] = $fk;
				}
			}
			$originalArr = [];//缓存一下最初形态的商家编码
			$allArr = [];
			$numArr = [];
			$noRemarkCol = true;
			switch ($mtype) {
				case 'all':
					$mainkey = 'mod3_id';
					break;
				case 'chassis':
					$mainkey = 'mch_code';
					break;
				case 'engine':
					$mainkey = 'men_code';
					break;
			}

			foreach($tempArr as $key=> $val)
			{	
				$modelArr =[
					'num'=>[],
					'mod3_id'=>'',
					'mch_code'=>'',
					'men_code'=>'',
					'remark'=>'',
					'remarkArr'=>[]
				];
				$modelArr[$mainkey] = $val[$colArr[$mainkey]];
				if($colArr['remark']){
					$noRemarkCol = false;
					$modelArr['remark'] = $val[$colArr['remark']]?:'';
				}
				$numarr = [];
				foreach($colArr['num'] as $fk)
				{
					if(empty($val[$fk])) continue;
					$numarr = array_unique(array_merge($numarr,explode(';',$val[$fk])));
				}
				foreach ($numarr as $nitem) {
					if(strpos($nitem,'@')!==false)
					{
						$arr = explode('@',$nitem);
						$arr0 = LibFc::FormatNum($arr[0]);
						$modelArr['num'][] =  $arr0;
						$modelArr['remarkArr'][$arr0] = $arr[1];
						$originalArr[$arr0] = $arr[0];
					}else{
						$fornitem = LibFc::FormatNum($nitem);
						$modelArr['num'][] = $fornitem;
						$originalArr[$fornitem] = $nitem;
					}
					
				}
				$numArr = array_merge($numArr,$modelArr['num']);
				if($modelArr['num']){
					$allArr[] = $modelArr;
				}
			}
			$numArr = array_filter(array_unique($numArr));
			$where = sprintf(" and num_format in ('%s') and pro_shop_id=%d", implode("','", $numArr), $shopId);
			$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id', 'num_format', 'pro_smt_code'], $where);
			$numPidArr = array_column($res['data'], null, 'num_format');
			//不存在的商家编码
			$chkerr = array_diff($numArr,array_keys($numPidArr));
			if($chkerr){
				// 将数组A的值转换为键
				$chkerr = array_flip($chkerr);
				// 使用这些键与数组B进行交集操作
				$result = array_values(array_intersect_key($originalArr, $chkerr));
				return LibFc::ReturnData(true, ['chkerr'=>$result,'nomatchType'=>[],'total'=>count($result)]);	
			}
			$proModelArr = [];
			$nomatchType = [];
			foreach ($allArr as $modit) 
			{
				if(empty($modit['num'])) continue;
				$numv = array_unique($modit['num']);
				$remark = $modit['remark'];
				foreach ($numv as $num) 
				{
					if (empty($numPidArr[$num])) continue;
					$proArr = $numPidArr[$num];
					//如果模式为空，则默认为系统的模式
					if(empty($proArr['pro_smt_code']))
					{
						$proArr['pro_smt_code'] = $shop_smt_code;
					}
					if ($proArr['pro_smt_code'] != $mtype)
					{
						$nomatchType[] = $num;
						continue;
					} 
					$proId = $proArr['num_pro_id'];
					$canUpdate = false;	
					if(!$modit['remark'] && !empty($modit['remarkArr']))
					{
						$remark = $modit['remarkArr'][$num]?$modit['remarkArr'][$num]:'';
					}
					if($remark) $canUpdate = true;
					switch ($mtype) 
					{
						case 'all':
							$proModelArr[$proId][$modit['mod3_id']] = ['pml3_mod3_id' =>$modit['mod3_id'],'pml3_remark' => $remark,'canUpdate'=>$canUpdate];
						break;
						case 'chassis':
							$proModelArr[$proId][$modit['mch_code']] = ['pmc_mch_code' => $modit['mch_code'], 'pmc_remark' => $remark,'canUpdate'=>$canUpdate];
						break;
						case 'engine':
							$proModelArr[$proId][$modit['men_code']] = ['pme_men_code' => $modit['men_code'], 'pme_remark' => $remark,'canUpdate'=>$canUpdate];
						break;
					}
				}
			}
			//补充产品ID
			$cacheFile = $optArr['dir'].$optArr['filename'].'.php';
			$cacheArr = ['rows'=>$proModelArr, 'mtype'=>$mtype,'noRemarkCol'=>$noRemarkCol];
			LibFc::ArraySave($cacheArr, $cacheFile);
			//备份
			$ver = date('YmdHi');
			$sql = sprintf("INSERT into bc_product_model3_link_ver (pml3b_pro_id, pml3b_mod3_id, pml3b_pml3_remark, pml3b_pml3_from, pml3b_pml3_time, pml3b_version, pml3b_shop_id)
			select pml3_pro_id, pml3_mod3_id, pml3_remark, pml3_from, pml3_time, '%s', pro_shop_id from bc_product_model3_link join bc_product on pro_id = pml3_pro_id where pro_shop_id = %d", $ver, $shopId);
			$this->query($sql);
		}
		$returnArr = $optArr;
		unset($returnArr['dir']);
		$returnArr['nomatchType'] = array_unique($nomatchType??[]);
		$returnArr['total'] = count($proModelArr);
		return LibFc::ReturnData(true, $returnArr);
	}

	/**
	 * 导入车型关系和备注
	 */
	public function importRelationAndRemark($shopId,$optArr)
	{
		$optArr['dir'] = mvc::$cfg['ROOT_BIGFILE'];
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺ID不存在');
		$cacheFile = $optArr['dir'].$optArr['filename'].'.php';
		if(!file_exists($cacheFile)) return LibFc::ReturnData(false, '文件不存在，请重新上传！');
		$cacheArr = include($cacheFile);
		if(!is_array($cacheArr)) return LibFc::ReturnData(false, '文件不存在，请重新上传！');

		$allSetArr = [];
		$allSetArr = array_slice($cacheArr['rows'],$optArr['begin'],$optArr['per'],true);
		if(!empty($allSetArr))
		{	
			$mtype = $cacheArr['mtype'];
			$noRemarkCol = $cacheArr['noRemarkCol'];
			$this->B2CDb->Begin();
			foreach ($allSetArr as $pid => $modArr) 
			{
				switch ($mtype) 
				{
					case 'all':
						$res = $this->get('bc_product_model3_link', ['pml3_mod3_id', 'pml3_remark'], sprintf(" and pml3_pro_id=%d", $pid));
						$oldArr = array_column($res['data'],null,"pml3_mod3_id");
						foreach ($modArr as $key => $modItem) 
						{	
							//无车型备注列进行覆盖导入，不应该清除已有备注 ,取旧的覆盖
							if($oldArr[$key] && $noRemarkCol && !$modItem['canUpdate'])
							{
								$modArr[$key]['pml3_remark'] = $oldArr[$key]['pml3_remark'];
							}
						}	
						if ($optArr['style'] != 'replace') 
						{
							foreach ($oldArr as $key => $oldItem) 
							{
								if(empty($modArr[$key])) $modArr[$key] = $oldItem;
							}
						}
						$this->setProductModel($pid, $modArr);
						break;
					case 'chassis':
						$res = $this->get('bc_product_modchassis', ['pmc_mch_code', 'pmc_remark'], sprintf(" and pmc_pro_id=%d", $pid));
						$oldArr = array_column($res['data'],null,'pmc_mch_code');
						$modchassisArr = $modArr;
						foreach ($modchassisArr as $key => $modchassisItem) 
						{
							if($oldArr[$key] && $noRemarkCol && !$modchassisItem['canUpdate'])
							{
								$modchassisArr[$key]['pmc_remark'] = $oldArr[$key]['pmc_remark'];
							}
						}
						if ($optArr['style'] != 'replace') 
						{
							$modchassisArr = array_merge($oldArr, $modchassisArr);
						}
						$this->setProductModChassis($pid, $modchassisArr);
						break;
					case 'engine':
						$res = $this->get('bc_product_modengine', ['pme_men_code, pme_remark'], sprintf(" and pme_pro_id=%d", $pid));
						$oldArr = array_column($res['data'],null,'pme_men_code');
						$modengineArr = $modArr;
						foreach ($modengineArr as $key => $modengineItem) 
						{
							if($oldArr[$key] && $noRemarkCol && !$modengineItem['canUpdate'])
							{
								$modengineArr[$key]['pen_remark'] = $oldArr[$key]['pen_remark'];
							}
						}
						if ($optArr['style'] != 'replace') 
						{
							$modengineArr = array_merge($oldArr, $modengineArr);
						}
						$this->setProductModEngine($pid, $modengineArr);
						break;
				}
			}
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true, $arr);
	}

	public function importRDemo($mtype = 'all')
	{
		if($mtype=='all'){
			$colsFiled[] = ['name'=>'mod3_id', 'fname'=>'mod3_id','width'=>20];
		}
		if($mtype=='engine'){
			$colsFiled[] = ['name'=>'men_code', 'fname'=>'men_code','width'=>20];
		}
		if($mtype=='chassis'){
			$colsFiled[] = ['name'=>'mch_code', 'fname'=>'mch_code','width'=>20];
		}
		$colsFiled[] = ['name'=>'商家编码', 'fname'=>'pri_code','width'=>20];	
		$colsFiled[] =	['name'=>'车型备注', 'fname'=>'number', 'width'=>30];

		$OthExcel = new OthExcel();
		$objPHPExcel = new PHPExcel();
		$objPHPExcel->getProperties()->setTitle('export')->setDescription('none');
		$objPHPExcel->setActiveSheetIndex(0);
		//左对齐
		$objPHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
	
		$colIndex = [ 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
		$col = 0;
		$brow = 1;
		foreach($colsFiled as $fk=>$fv)
		{
			$objPHPExcel->getActiveSheet()->getStyle($colIndex[$col].($brow))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
			$objPHPExcel->getActiveSheet()->setCellValue($colIndex[$col].($brow), $fv['name']);
			$objPHPExcel->getActiveSheet()->getColumnDimension($colIndex[$col])->setWidth($fv['width']);
			$col++;
		}
		$OthExcel->download($objPHPExcel, '配件关系与备注导入模板.xls');
		exit;
	}

	/**
	*  通过号码获取产品车型信息
	*/
	protected function getProModelBynumber($shopid,$number)
	{
		if(empty($shopid)||empty($number))  return LibFc::ReturnData(true, []);

		if(!is_array($number)) $number = [$number];

		$table = 'bc_number as n join bc_product as p on pro_id=num_pro_id'; 
	
		$shopModelLinks = $this->get($table,['pro_id,pro_smt_code,num_format'],sprintf(" and num_format in (%s) and pro_shop_id =%d and num_show = 1",implode(',',$number),$shopid));
		//此处兼容 同步车型以导入num_display为准
		$shopModelLinks1 = $this->get($table,['pro_id,pro_smt_code,num_display as num_format'],sprintf(" and num_display in (%s) and pro_shop_id =%d and num_show = 1",implode(',',$number),$shopid));
		$shopModelLinks['data'] = array_merge($shopModelLinks['data'],$shopModelLinks1['data']);
			
		
		if(empty($shopModelLinks['data'])) return LibFc::ReturnData(true,[]);
		$arr = [];
		$tempArr = [];
		foreach ($shopModelLinks['data'] as $val) {
			$type = $val['pro_smt_code']?:'all';
			$arr[$type][] = $val['pro_id'];
		}
		foreach ($arr as $pro_smt_code => $pro_ids) {
			if($pro_smt_code =='engine')
			{
				$res = $this->get('bc_product_modengine',['pme_pro_id,pme_men_code, pme_remark'], sprintf(" and pme_pro_id in (%s)", implode(',',$pro_ids)));	
				foreach ($res['data'] as $engineItem) {
					$tempArr[$engineItem['pme_pro_id']][$engineItem['pme_men_code']] = $engineItem;
				}
			}
			elseif ($pro_smt_code =='chassis') 
			{
				$res = $this->get('bc_product_modchassis',['pmc_pro_id,pmc_mch_code', 'pmc_remark'], sprintf(" and pmc_pro_id in (%s)", implode(',',$pro_ids)));
				foreach ($res['data'] as $chassisItem) {
					$tempArr[$chassisItem['pmc_pro_id']][$chassisItem['pmc_mch_code']] = $chassisItem;
				}
			}
			else
			{
				$res = $this->get('bc_product_model3_link',['pml3_pro_id,pml3_mod3_id','pml3_remark'], sprintf(" and pml3_pro_id in (%s)", implode(',',$pro_ids)));
				foreach ($res['data'] as $modelItem) {
					$tempArr[$modelItem['pml3_pro_id']][$modelItem['pml3_mod3_id']] = $modelItem;
				}
			}
		}
		$arr = [];
		$shopModelLink = []; 
		foreach ($shopModelLinks['data'] as $value)
		{	
			$arr['data'] = isset($tempArr[$value['pro_id']])?$tempArr[$value['pro_id']]:[];
			$arr['pro_id'] = $value['pro_id'];
			$arr['type'] = $value['pro_smt_code']?:'all';
			$shopModelLink[$value['num_format']] = $arr;
		}
		return LibFc::ReturnData(true,$shopModelLink);
	}


	/**
	 * 批量设置零件分类
	 */
	public function batchChangePart($proId,$dataArr)
	{
		if(!$dataArr['partPath']||!$proId) return LibFc::ReturnData(false,'参数错误');

		$partPathArr =	explode(',', $dataArr['partPath']);
		$temp = [];
		foreach ($partPathArr as $k => $v) {
			$temp[] = (int) $v;
		}
		$temp = array_unique($temp);
		$data['pro_part_path'] = $dataArr['partPath'];
		$data['pro_part_id'] = array_pop($temp);
		$data['pro_pas_id'] = $dataArr['pro_pas_id']? $dataArr['pro_pas_id'] : 0;

		$res = $this->get('bc_product', ['pro_id', 'pro_part_id', 'pro_part_path', 'pro_pas_id'], sprintf(" and pro_id in (%s)", $proId));
		if (empty($res['data'])) return	LibFc::ReturnData(false, '配件数据不存在');
		$proIdArr = $res['data'];
		$this->B2CDb->Begin();
		foreach ($proIdArr as $key => $val) 
		{
			$this->set('bc_product',$data,sprintf(" AND pro_id = %d",$val['pro_id']));
			//切换零件分类时清除原有分类参数
			if ($data['pro_part_id'] != $val['pro_part_id'])
			{
				$this->del('bc_product_param_float',sprintf(" AND ppf_pro_id = %d",$val['pro_id']));
				$this->del('bc_product_param_string',sprintf(" AND pps_pro_id = %d",$val['pro_id']));
			}
			// $this->setProductParam($val['pro_id'],$data['pro_part_id'],[]);
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}

	public function batchChangeParam($proId,$shopId,$param,$pptName = '默认模板')
	{
		if(!LibFc::Int($proId) || !LibFc::Int($shopId) || empty($param))
			return LibFc::ReturnData(false, 'batchChangeParam 提供的参数不正确');
		

		$this->B2CDb->Begin();
		//添加默认模板
		$res = $this->get('bc_product_para_tpl',['*'],sprintf("and ppt_name='%s' and ppt_shop_id=%d",$pptName,$shopId),true);
		if(empty($res['data']))
		{
			$temp = ['ppt_shop_id' => $shopId,'ppt_name' => $pptName,'ppt_atime' => time(),];
			$res = $this->add('bc_product_para_tpl',$temp);
			$ppt_id = $res['data'];
		}
		else
		{
			$ppt_id = $res['data']['ppt_id'];
		}


		foreach ($param as $k => $v)
		{
			$pru_id =0;
			// 添加参数名
			$res = $this->get('bc_product_label',['prl_id'],sprintf("and prl_name='%s'",current($v)),true);
			if(empty($res['data']))
			{
				$res = $this->add('bc_product_label',['prl_name'=>current($v)]);
				$prl_id = $res['data'];
			}
			else
			{
				$prl_id = $res['data']['prl_id'];
			}
			//单位
			if(isset($v[2]))
			{	
				$res = $this->get('bc_product_unit',['pru_id'],sprintf("and pru_name='%s'",LibFc::Escape($v[2])),true);
				if(empty($res['data']))
				{
					$res = $this->add('bc_product_unit',['pru_name'=>LibFc::Escape($v[2])]);
					$pru_id = $res['data'];
				}
				else
				{
					$pru_id = $res['data']['pru_id'];
				}
			}
			
			// 参数-模板关联
			$res = $this->get('bc_product_para_tpl_link',['*'],sprintf("and pptl_ppt_id=%d and pptl_prl_id=%d",$ppt_id,$prl_id),true);
			if(empty($res['data']))
			{
				$this->add('bc_product_para_tpl_link',['pptl_ppt_id'=>$ppt_id,'pptl_prl_id'=>$prl_id,'pptl_pru_id'=>$pru_id]);
			}
			else
			{
				$this->set('bc_product_para_tpl_link',['pptl_pru_id'=>$pru_id],sprintf(" AND pptl_ppt_id=%d AND pptl_prl_id=%d",$ppt_id,$prl_id));
			}
			// 添加参数值
			$res = $this->get('bc_product_para_val',['*'],sprintf("and prpv_pro_id=%d and prpv_prl_id=%d",$proId,$prl_id),true);
			if(empty($res['data']))
			{
				$temp = ['prpv_pro_id'=> $proId,'prpv_prl_id'=> $prl_id,'prpv_pru_id'=> $pru_id,'prpv_value'=>LibFc::Escape($v[1])];
				$this->add('bc_product_para_val',$temp);
			}
			else
			{
				$temp = ['prpv_pru_id'=> $pru_id,'prpv_value'=>LibFc::Escape($v[1])];
				$this->set('bc_product_para_val',$temp,sprintf("and prpv_pro_id=%d and prpv_prl_id=%d",$proId,$prl_id));
			}
		}


		// 配件 + 模板关联
		$this->set('bc_product',['pro_ppt_id'=>$ppt_id],sprintf("and pro_id=%d",$proId));
		$this->B2CDb->End();
		
		return LibFc::ReturnData(true, true);
	}

	/**
	 * 车型智能匹配保存所选关联
	 */
	public function saveAutoSearch($pmaIdArr,$remarkArr,$all =false)
	{
		if(!$pmaIdArr) return LibFc::ReturnData(false,'参数错误');
		
		$res  = $this->get('bc_product_model_auto',['*'],sprintf(" AND pma_status=0 AND pma_id IN (%s)",implode(',',$pmaIdArr)));
		if(!$res['data']) return LibFc::ReturnData(true);
		$arr = [];
		foreach ($res['data'] as $key => $val) {
			if($all){
				$arr[$val['pma_pro_id']][$val['pma_from']][] = $val['pma_mod3_id'];
			}else{
				$arr[$val['pma_pro_id']][$val['pma_from']][] = ['pml3_mod3_id'=>$val['pma_mod3_id'], 'pml3_remark'=>$remarkArr[$val['pma_id']]]??'';
			}
		}
		
		$res = $this->get('bc_product_model3_link', ['*'], sprintf(" and pml3_pro_id in (%s)", implode(',', array_keys($arr))));
		foreach($res['data'] as $v)
		{
			$prom3Arr[$v['pml3_pro_id']][] = $v['pml3_mod3_id'];
		}
		$this->B2CDb->Begin();
		foreach ($arr as $key => $val) 
		{
			foreach ($val as $from => $vv) 
			{
				$prom3Arr[$key] = array_merge($prom3Arr[$key]??[],$vv);
				$this->setProductModel($key, $prom3Arr[$key], $from);
			}
		}
		$res  = $this->set('bc_product_model_auto',['pma_status'=>1],sprintf(" AND pma_status=0 AND pma_id IN (%s)",implode(',',$pmaIdArr)));	
		$this->B2CDb->End();
		return LibFc::ReturnData(true,'');
		
	}


	/**
	  * @method 店铺的智配车型自动处理到任务表中
	  * @param  
	  * @author soul
	  * @copyright 
	  * @return 
	  */
	public function zhiPeiAutoModel($shopId, $zpShop)
	{
		$from = 'ZHIPEI';
		$zpShop = LibFc::Escape($zpShop);
		$shopId = (int) $shopId;
		if($shopId  < 1) return LibFc::ReturnData(false, '店铺不存在！');
		if(empty($zpShop)) return LibFc::ReturnData(false, 'zhiPeiAutoModel 参数不正确！');
			
		//检查店铺是否存在
		$res = $this->get('sh_shop', ['shop_status'], sprintf(" and shop_id=%d", $shopId), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, '店铺不存在');
		
		$B2cZhipei = new B2cZhipei();
		$res = $B2cZhipei->ZpBase->get('auto_product', ['pro_user'], sprintf(" and pro_user = '%s' limit 1", $zpShop), true);
		if(empty($res['data'])) return LibFc::ReturnData(false,  $zpShop.'无产品数据！');
		$version = date('Ymd');

		//确定产品对应关系
		$res = $this->get('bc_product', ['pro_id,pro_dfrom_id'], sprintf(" and pro_dfrom='ZHIPEI' and pro_shop_id=%d", $shopId));
		$hasLinkId = array_column($res['data'], 'pro_id', 'pro_dfrom_id');
		
		$res = $this->get('bc_product join bc_product_info on pri_pro_id=pro_id', ['pro_id, pri_code'], sprintf(" and pro_shop_id=%d", $shopId));
		$hasLinkCode = array_column($res['data'], 'pro_id', 'pri_code');

		$res = $this->get('bc_number join bc_product on num_pro_id=pro_id and num_self=1', ['num_pro_id pro_id, num_format'], sprintf(" and pro_shop_id=%d", $shopId));
		$hasLinkCode2 = array_column($res['data'], 'pro_id', 'num_format');

		//通过自编号确认产品ID对应关系
		$res = $B2cZhipei->ZpBase->get('auto_product', ['pro_id, pro_format'], sprintf(" and pro_user = '%s' and pro_format != ''", $zpShop));
		foreach($res['data'] as $tv){
			$ypProId = 0;
			if($hasLinkId[$tv['pro_id']]){
				$ypProId = $hasLinkId[$tv['pro_id']];
			}else if($hasLinkCode[$tv['pro_format']]){
				$ypProId = $hasLinkCode[$tv['pro_format']];
			}else{
				$format = LibFc::FormatNum($tv['pro_format']);
				if($hasLinkCode2[$format]){
					$ypProId = $hasLinkCode2[$format];
				}
			}
			//仅处理刚才新增的
			if($zpActArr['item'] == 'onlynew' && !in_array($ypProId, $needSetPidArr)) continue;
			$ypToZpIdArr[$ypProId] = $tv['pro_id'];
		}

		if(empty($ypToZpIdArr)) return LibFc::ReturnData(true);
		$this->B2CDb->Begin();
		foreach($ypToZpIdArr as $proId=>$zpProId)
		{
			$res = $B2cZhipei->matchItemModel($zpProId);
			if(empty($res['data'])) continue;
			$newModArr = [];
			foreach($res['data'] as $tkk=>$tvv){
				$newModArr[$tkk] = ['pml3_mod3_id'=>$tkk, 'pml3_remark'=>implode('; ',$tvv)];
			}
			$newIdArr = array_keys($newModArr);
			
			//已经有的
			$res = $this->get('bc_product_model3_link', ['pml3_mod3_id mod3_id, pml3_remark remark'], sprintf(" and pml3_pro_id=%d and pml3_mod3_id in (%s)", $proId, implode(',', $newIdArr)));
			$hasBindArr = array_column($res['data'], null, 'mod3_id');
			$res = $this->get('bc_product_model_auto', ['pma_id, pma_status, pma_from, pma_mod3_id mod3_id, pma_remark remark'], sprintf(" and pma_pro_id=%d", $proId));
			$hasAutoArr = $res['data'];

			$addIdArr = array_diff($newIdArr, array_keys($hasBindArr), array_column($hasAutoArr, 'mod3_id'));

			//需要删除的匹配
			$delArr = [];
			foreach($hasAutoArr as $v){
				//任务待处理中, 已经绑定或者新匹配时无此车型
				if($v['pma_status'] == 0 && ($hasBindArr[$v['mod3_id']] || ($v['pma_from'] == $from && !in_array($v['mod3_id'], $newIdArr)))){
					$delArr[] = $v['pma_id'];
				}
			}
			if(!empty($delArr)) $this->del('bc_product_model_auto', sprintf(" and pma_status=0 and pma_pro_id=%d and pma_id in (%s)", $proId, implode(',', $delArr)));
			
			if(!empty($addIdArr)){
				$addArr = [];
				foreach($addIdArr as $id){
					$addArr[] = [
						'pma_shop_id'=>$shopId,
						'pma_pro_id'=>$proId,
						'pma_version'=>$version,
						'pma_mod3_id'=>$id,
						'pma_remark'=>$newModArr[$tkk]['pml3_remark'],
						'pma_from'=>$from,
						'pma_atime'=>time(),
						'pma_etime'=>time(),
					];
				}
				$this->addAny('bc_product_model_auto', array_keys($addArr[0]), $addArr);
			}
		}
		$this->set('bc_product', ['pro_automodel_zp'=>$version], sprintf(" and pro_id in (%s)", implode(',', array_keys($ypToZpIdArr))));
		$this->B2CDb->End();
		return LibFc::ReturnData(true);
	}

	/**
	 * @param  int $shopId
	 * @param  int $proId
	 * @param  Array $dataArr
	 * @method 编辑/添加产品时同步更新
	 * @author zhengweihua 
	 * @copyright 2024-05-15
	 */
	public function setProSynUpdate($shopId,$proId,$dataArr)
	{	
		set_time_limit(0);
		
		if(!$shopId ||!$proId ||!$dataArr) return LibFc::ReturnData(true);
		
		$proSyncSet = $this->getProSynSet($shopId,$dataArr);
		//先把符合设置的产品更新
		if ($proSyncSet) {
			foreach ($proSyncSet as $prosyn) {
				$sysAct = $prosyn['sps_act']?json_decode($prosyn['sps_act'],true):[];
				$this->copyProduct($shopId, $prosyn['sps_to_shop_id'], $proId,$sysAct);
			}
		} elseif (empty($proSyncSet)) {
			$where = sprintf(" and pro_dfrom = '%s' and pro_dfrom_id = %d", 'shop_' . $shopId, $proId);
			$toProRes =	$this->get('bc_product', ['pro_shop_id', 'pro_id'], $where);
			if ($toProRes['data']) {
				foreach ($toProRes['data'] as $key => $toPro) {
					$this->delProduct($toPro['pro_shop_id'], [$toPro['pro_id']]);
				}
			}
		}
	}

	

	/**
	 * @param  int $proId
	 * @param  string $vin
	 * @method 添加适配车型的VIN查询历史记录
	 * @author zhengweihua 
	 * @copyright 2024-07-29
	 */
	public function setModelVin($proId,$vin)
	{
		$res = $this->get('bc_product_model_vin',['*'],sprintf(" AND bpmv_pro_id=%d AND bpmv_vin='%s'",$proId,$vin),true);
		if($res['data'])
		{
			$this->set('bc_product_model_vin',['bpmv_etime'=>time()],sprintf(" AND bpmv_id=%d ",$res['data']['bpmv_id']));
		}else{
			$res = $this->add('bc_product_model_vin',[
				'bpmv_pro_id'=>$proId,
				'bpmv_vin'=>$vin,
				'bpmv_etime'=>time(),
			]);
		}
		LibFc::ReturnData(true);
	}

	/**
	 * @param  array  $items 配件ID
	 * @param  string $modtype 车型模型
	 * @method 变更配件车型
	 * @author zhengweihua 
	 * @copyright 2024-11-14
	 */
	public function changeProMod($items = [],$modtype='all')
	{
		if(empty($items)) return LibFc::ReturnData(false,'参数错误');

		$proIdArr = $items;
		$proIds = implode(',',$proIdArr);
		
		$this->B2CDb->Begin();

		if($modtype == 'chassis'){
			$func = 'setProductModChassis';
		}else if($modtype == 'engine'){
			//发动机件车型
			$func = 'setProductModEngine';
		}else{
			$func = 'setProductModel';
		}

		foreach ($proIdArr as $proId) {
			$this->$func($proId, [], $modtype);
		}

		$this->set('bc_product',['pro_smt_code'=>$modtype],sprintf(" AND pro_id IN (%s)",$proIds));

		$this->B2CDb->End();
		
		return LibFc::ReturnData(true,true);
		
	}

	public function shopSyncSet($shopId,$param)
	{
		$where  = sprintf("and sss_shop_id_from =%d and sss_shop_id_to = %d",(int)$param['sss_shop_id_from'],(int)$shopId);
		$rows =	$this->get('sh_shop_synch',['*'],$where,true);

		$this->B2CDb->Begin();
		if(empty($rows['data'])){
			$dataArr = [
				'sss_shop_id_to'=>$shopId,
				'sss_shop_id_from'=>$param['sss_shop_id_from'],
				'sss_act' =>$param['sss_act']? json_encode($param['sss_act']):'{}',
				'sss_etime' => time()
			];
			$this->add('sh_shop_synch',$dataArr);
		}else{
			$dataArr = [
				'sss_act' =>$param['sss_act']? json_encode($param['sss_act']):'{}',
				'sss_etime' => time()
			];
			
			$res = $this->set('sh_shop_synch',$dataArr,$where);
		}
		$B2cLog = new B2cLog();
		if($param['sss_shop_id_from']==$shopId){
			$logtxt = '编辑店铺内同步设置';
		}else{
			$shopInfo = $this->get('sh_shop',['shop_name'],sprintf(" AND shop_id=%d",$shopId),true);
			$logtxt = "编辑{$shopInfo['data']['shop_name']}店铺内同步设置";
		}
		$item = [
			'log_category'=>21,
			'log_shop_id'=>$shopId,
			'log_atime'=>time(),
			'log_dataid'=>$shopId,
			'log_txt'=>$logtxt,
			'log_orgdata'=>json_encode($rows['data']?$rows['data']:[]),
		];
		$B2cLog->addFastLog($item);
		$this->B2CDb->End();
		
		return LibFc::ReturnData(true,true);
	}

	/**
	 * 备份车型数据 同一天同一个产品 只保留最新版本
	 */
	public function backupModel3Link($shopId,$proIdArr = []) {
		$ver = date('YmdHi');
		$date = date('Ymd');
		$dwhere = '';
		$iwhere = '';
		if($proIdArr){
			$dwhere = sprintf(" AND pml3b_pro_id IN (%s)", implode(',', $proIdArr));
			$iwhere = sprintf(" AND pml3_pro_id IN (%s)", implode(',', $proIdArr));
		}
		$this->B2CDb->Begin();
		
		// 删除当天旧数据
		$this->del('bc_product_model3_link_ver', sprintf(" %s AND pml3b_shop_id=%d AND pml3b_version LIKE '%s%%'",$dwhere,$shopId, $date));
		
		// 插入新数据
		$sql = sprintf("INSERT into bc_product_model3_link_ver (pml3b_pro_id, pml3b_mod3_id, pml3b_pml3_remark, pml3b_pml3_from, pml3b_pml3_time, pml3b_version, pml3b_shop_id)
				select pml3_pro_id, pml3_mod3_id, pml3_remark, pml3_from, pml3_time, '%s', pro_shop_id from bc_product_model3_link join bc_product on pro_id = pml3_pro_id where pro_shop_id = %d %s", $ver, $shopId,$iwhere);
		$bakres  = $this->query($sql);
		$this->B2CDb->End();
		if(empty($bakres['status'])) return libfc::ReturnData(false, '操作太频繁，请稍后再操作');
		return libfc::ReturnData(true, '操作成功');
	}

}