<?php
/**
  * @method 产品管理
  * @author soul
  * @copyright 2016/3/31
  */
class B2cProduct extends B2cBase
{
	/**
	  * @method 获取配件基本信息
	  * @param  $proIdArr array [11,2222....]
	  * @param  $uid int 用户ID
	  * @param  $typeArr ['numMain', 'picMain', 'picAll', 'desc', 'noPrice']
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
			成功 ["status"=>true, "data"=> [11=>[], ...]] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getAnyProductInfo($proIdArr, $uid = 0, $typeArr = [], $mod3Id = 0)
	{
		if(stripos($mod3Id, ',') || empty($mod3Id)) $mod3Id = 0;
		$proArr = [];
		foreach($proIdArr as $k=>$v)
		{
			$proId = (int) $v;
			$proArr[$proId] = [];
		}
		$proIdArr = array_keys($proArr);
		$typeArr = empty($typeArr)? ['numMain', 'picMain']: $typeArr;
		$uid = (int) $uid;
		if(!empty($proIdArr))
		{
			$priceRes = $this->getAnyProductPrice($proIdArr, $uid);
			$proPriceArr = $priceRes['data'];

			$fieldArr = ['pro_id', 'prb_name', 'pro_status', 'part_name', 'pas_name', 'pro_name', 'pro_shop_id','pro_count', 'pro_sold_count','pro_part_id','pri_code','pri_weight','pri_frt_id','pro_sel_des','pro_count','pri_invoice','pri_warranty','pri_return_promise','shop_zbnum','shop_smainnum','shop_srefnum','pro_show_b2c', 'pro_show_super'];
			if(in_array('desc', $typeArr)) $fieldArr[] = 'pri_des';

			$table = 'bc_product 
				join sh_shop on pro_shop_id=shop_id
				join bc_product_info on pro_id=pri_pro_id 
				join bc_part on pro_part_id = part_id 
				left join bc_part_small on part_id = pas_part_id and pro_pas_id = pas_id
				left join bc_probrand on pro_prb_id=prb_id';
			$res = $this->get($table, $fieldArr, sprintf(" and pro_id in(%s)", implode(',', $proIdArr)));
			if(empty($res['data']))
				return LibFc::ReturnData(true, $proArr);
			
			//基本信息
			foreach($res['data'] as $v)
			{
				if(!empty($proPriceArr[$v['pro_id']])) $v = array_merge($v, $proPriceArr[$v['pro_id']]);
				
				if(in_array('para', $typeArr))
				{
					$paraRes = $this->getProductPara($v['pro_id'], $v['pro_part_id']);
					$v['para'] = $paraRes['data'];
				}
				$v['pro_price'] = ['title'=>'销售价', 'price'=>$v['price']];
				if(empty($v['pro_show_b2c']) || in_array('noPrice', $typeArr))
				{
					$v['pro_price'] = ['title'=>'销售价', 'price'=>'0.00'];
					$v['price'] = '0.00';
				}
				$v['pic'] = [];
				$v['num'] = [];
				$v['mod3_para'] = '';
				$proArr[$v['pro_id']] = $v;
			}

			//剔除无数据的
			foreach($proArr as $k=>$v)
			{
				if(empty($v)) unset($proArr[$k]);
			}

			$proIdArr = array_keys($proArr);
			if(empty($proIdArr)) return LibFc::ReturnData(true, $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_self', 'num_ismain'];
			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';
					$proArr[$v['num_pro_id']]['num'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display'], 'type'=>$ntype];
				}
			}
			
			//车型参数
			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));
				}
			}

			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  $proIdArr array [11,2222....]
	  * @param  $uid int 用户ID
	  * @param  $melId string  会员级别 多个逗号分隔
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
	  */
	public function getAnyProductPrice($proIdArr, $uid = 0, $melIds = '-1')
	{
		if($melIds === '') $melIds = '-1';
		$proArr = [];
		foreach($proIdArr as $k=>$v)
		{
			$proId = (int) $v;
			$proArr[$proId] = [];
		}
		$proIdArr = array_keys($proArr);
		if(!empty($proIdArr))
		{
			$fieldArr = ['pro_id', 'pro_shop_id', 'pro_sale_price', 'pro_promotion_price', 'pro_user_discount', 'pro_promotion_btime', 'pro_promotion_etime'];
			if($uid > 0 || $melIds != '-1') $fieldArr = array_merge($fieldArr, ['pro_price_vip1', 'pro_price_vip2', 'pro_price_vip3', 'pro_price_vip4']);
			$res = $this->get('bc_product', $fieldArr, sprintf(" and pro_id in(%s)", implode(',', $proIdArr)));
			if(empty($res['data']))
				return LibFc::ReturnData(true, $proArr);
			$priceType = [
				1=>'销售价',
				2=>'促销价',
				3=>'会员价',
			];
			foreach($res['data'] as $v)
			{
				$v['price'] = $v['pro_sale_price'];
				$v['price_type'] = 1;
				if($uid > 0)
				{//按会员取
					if($v['pro_user_discount'] =='Y' && $v['pro_promotion_price'] > 0 && $v['pro_promotion_btime'] <= time() && $v['pro_promotion_etime'] >= time()){
						$v['price'] = $v['pro_promotion_price'];
						$v['price_type']= 2;//价格类型  1：销售价 2 促销价 3 会员价
					}
					//获取该会员在店铺里的级别
					$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']['mem_mel_id'])){
						$melId = $levelRes['data']['mem_mel_id'];
						if(isset($v['pro_price_vip'.$melId]) && $v['pro_price_vip'.$melId] > 0 && ($v['pro_price_vip'.$melId] < $v['price'] || $v['price'] <= 0)){
							$v['price'] = $v['pro_price_vip'.$melId];
							$v['price_type']=3;
						}
					}
				}else if($melIds != '-1'){//直接取级别价格
					$v['prices'] = [];
					$res = $this->get("sh_member_level LEFT JOIN sh_member ON mem_mel_id = mel_id", ["mel_id, mel_name, men_alias"], sprintf(" and mem_shop_id=%d", $v['pro_shop_id']));
					$melArr = array_column($res['data'], null, 'mel_id');
					foreach(explode(',', $melIds) as $tmelId){
						$price = $tmelId < 1? $v['pro_sale_price']: $v['pro_price_vip'.$tmelId];
						if($price > 0){
							$v['prices'][] = [
								'mel_id'=>$tmelId, 
								'mel_name'=>$melArr[$tmelId]['mel_name'],
								'men_alias'=>$melArr[$tmelId]['men_alias'],
								'price'=>$price
							];
						}
					}
				}
				
				unset($v['pro_promotion_price']);
				unset($v['pro_promotion_btime']);
				unset($v['pro_promotion_etime']);
				unset($v['pro_price_vip1']);
				unset($v['pro_price_vip2']);
				unset($v['pro_price_vip3']);
				unset($v['pro_price_vip4']);
				unset($v['pro_sale_price']);
				$v['price_name'] = $priceType[$v['price_type']];
				$proArr[$v['pro_id']] = $v;
			}

			//剔除无数据的
			foreach($proArr as $k=>$v)
			{
				if(empty($v)) unset($proArr[$k]);
			}
		}
		return LibFc::ReturnData(true, $proArr);
	}


	/**
	  * @method 获取目录配件基本信息
	  * @param  $proIdArr array [11,2222....]
	  * @param  $uid int 用户ID
	  * @param  $typeArr ['para', 'numMain', 'picMain', 'picAll', 'desc']
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
			成功 ["status"=>true, "data"=> [11=>[], ...]] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getSuperProductInfo($proIdArr, $uid = 0, $typeArr = [], $mod3Id = 0)
	{
		if(stripos($mod3Id, ',') || empty($mod3Id)) $mod3Id = 0;
		$proArr = [];
		foreach($proIdArr as $k=>$v)
		{
			$proId = (int) $v;
			$proArr[$proId] = [];
		}
		$proIdArr = array_keys($proArr);
		$typeArr = empty($typeArr)? ['numMain', 'picMain']: $typeArr;
		if(!empty($proIdArr))
		{
			$fieldArr = ['ssu_id', 'pro_id', 'prb_name', 'pro_status', 'pro_name', 'pro_shop_id', 'pro_count','pro_part_id','pri_code','pri_frt_id','pro_sel_des','pri_invoice','pri_warranty','pri_return_promise', 'part_name', 'pas_name', 'pro_pas_id', 'shop_zbnum', 'shop_smainnum', 'shop_srefnum'];
			if(in_array('desc', $typeArr)) $fieldArr[] = 'pri_des';

			$table = 'bc_product 
			join sh_super on pro_shop_id=ssu_shop_id
			join sh_shop on pro_shop_id=shop_id
			join bc_product_info on pri_pro_id = pro_id
			join bc_part on pro_part_id = part_id
			left join bc_probrand on pro_prb_id = prb_id
			left join bc_part_small on pro_pas_id = pas_id';
			$prores = $this->get($table, $fieldArr, sprintf(" and pro_id in(%s)", implode(',', $proIdArr)));
			if(empty($prores['data']))
				return LibFc::ReturnData(true, $proArr);

			$B2cShop = new B2cShop();
			$shopRuleArr = [];
			foreach(array_unique(array_column($prores['data'], 'pro_shop_id')) as $shopid)
			{
				$res = $B2cShop->getSuperUseRule($shopid, $uid);
				$shopRuleArr[$shopid] = array_column($res['data'], 'smr_code');
			}
			$priceRes = $this->getAnyProductPrice($proIdArr, $uid);
			$proPriceArr = $priceRes['data'];
			
			//基本信息
			foreach($prores['data'] as $v)
			{
				if(!empty($proPriceArr[$v['pro_id']])) $v = array_merge($v, $proPriceArr[$v['pro_id']]);
				$v['pro_spart_id'] = $v['pro_part_id'].'_'.$v['pro_pas_id'];
				if(in_array('para', $typeArr))
				{
					$paraRes = $this->getProductPara($v['pro_id'], $v['pro_part_id']);
					$v['para'] = $paraRes['data'];
				}

				if(!empty($shopRuleArr[$v['pro_shop_id']]) && in_array('item_price', $shopRuleArr[$v['pro_shop_id']]))
				{
					$v['pro_price'] = ['title'=>'销售价', 'price'=>$v['price']];
				}

				unset($v['price']);
				unset($v['pro_part_id']);
				unset($v['pro_pas_id']);
				unset($v['pro_sale_price']);
				$v['pic'] = [];
				$v['num'] = [];
				$v['mod3_para'] = '';
				$proArr[$v['pro_id']] = $v;
			}

			//剔除无数据的
			foreach($proArr as $k=>$v)
			{
				if(empty($v)) unset($proArr[$k]);
			}

			$proIdArr = array_keys($proArr);
			if(empty($proIdArr)) return LibFc::ReturnData(true, $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_self', 'num_ismain'];
			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';
					$proArr[$v['num_pro_id']]['num'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display'], 'type'=>$ntype];
				}
			}

			//车型参数
			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));
				}
			}
			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]);
					}
					//自编号权限
					if(!empty($shopRuleArr[$pv['pro_shop_id']]) && !in_array('item_selfnum', $shopRuleArr[$pv['pro_shop_id']]) && $tv['type'] == 'zb')
					{
						unset($pv['num'][$tk]);
					}
					//主号码权限
					if(!empty($shopRuleArr[$pv['pro_shop_id']]) && !in_array('item_mainnum', $shopRuleArr[$pv['pro_shop_id']]) && $tv['type'] == 'main')
					{
						unset($pv['num'][$tk]);
					}
				}
				if(!in_array('item_pic', $shopRuleArr[$pv['pro_shop_id']])) $pv['pic'] = [];
				$pv['num'] = array_values($pv['num']);
				$proArr[$pk] = $pv;
			}
		}
		return LibFc::ReturnData(true, $proArr);
	}

	/**
	  * @method 获取API配件基本信息
	  * @param  $proIdArr array [11,2222....]
	  * @param  $shopid int 店铺ID
	  * @param  $typeArr ['picMain', 'picAll', 'desc', 'numAll', 'para', 'modelAll']
	  * @param  $mod3Id int 车型ID
	  * @param  $melId int 会员级别ID
	  * @author soul
	  * @copyright 2017/7/7
	  * @return 
			成功 ["status"=>true, "data"=> [11=>[], ...]] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function getApiProductInfo($shopid, $proIdArr, $typeArr = [], $mod3Id = '', $melId = -1, $othArr = [])
	{
		$mod3Ids = [];
		foreach(explode(',', $mod3Id) as $t)
		{
			if(!empty($t)) $mod3Ids[] = (int) $t;
		}
		$mod3Ids = array_unique($mod3Ids);

		$proArr = [];
		foreach($proIdArr as $k=>$v)
		{
			$proId = (int) $v;
			$proArr[$proId] = [];
		}
		$proIdArr = array_keys($proArr);
		$typeArr = empty($typeArr)? ['numMain', 'picMain']: $typeArr;
		$uid = (int) $uid;
		if(!empty($proIdArr))
		{
			$fieldArr = ['pro_id', 'prb_name', 'part_name', 'pas_name', 'pro_name', 'pro_count', 'pro_part_id','pri_code','pri_weight','pro_sel_des', 'pro_sale_price', 'pro_price_vip1', 'pro_price_vip2', 'pro_price_vip3', 'pro_price_vip4', 'pri_keyword'];
			if(in_array('desc', $typeArr)) $fieldArr[] = 'pri_des';
			$table = 'bc_product 
				join sh_shop on pro_shop_id=shop_id
				join bc_product_info on pro_id=pri_pro_id 
				join bc_part on pro_part_id = part_id 
				left join bc_part_small on part_id = pas_part_id and pro_pas_id = pas_id
				left join bc_probrand on pro_prb_id=prb_id';
			$res = $this->get($table, $fieldArr, sprintf(" and pro_id in(%s) and pro_shop_id=%d", implode(',', $proIdArr), $shopid));
			if(empty($res['data']))
				return LibFc::ReturnData(true, $proArr);
			
			$proPriceArr = [];
			if($melId > -1)
			{
				$priceRes = $this->getAnyProductPrice($proIdArr, 0, $melId);
				$proPriceArr = $priceRes['data'];
			}

			//基本信息
			foreach($res['data'] as $v)
			{
				if(!empty($proPriceArr[$v['pro_id']])) $v = array_merge($v, $proPriceArr[$v['pro_id']]);

				if(in_array('para', $typeArr))
				{
					$paraRes = $this->getProductPara($v['pro_id'], $v['pro_part_id']);
					$v['para'] = $paraRes['data'];
				}
				$v['pic'] = [];
				$v['num'] = [];
				$v['mod3_para'] = '';
				if(in_array('numAll', $typeArr)) $v['numall'] = [];
				if(in_array('modelAll', $typeArr)) $v['models'] = [];
				$proArr[$v['pro_id']] = $v;
			}

			//剔除无数据的
			foreach($proArr as $k=>$v)
			{
				if(empty($v)) unset($proArr[$k]);
			}

			$proIdArr = array_keys($proArr);
			if(empty($proIdArr)) return LibFc::ReturnData(true, $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_self', 'num_ismain'];
			$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';
					$proArr[$v['num_pro_id']]['num'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display'], 'type'=>$ntype];
				}
			}
			
			//全部号码
			if(in_array('numAll', $typeArr))
			{
				$where = sprintf(" and num_pro_id in (%s) and num_show = 1 and num_self = 0 order by num_factory, num_format", implode(',', $proIdArr));
				$res = $this->get('bc_number', ['num_pro_id, num_factory, num_display'], $where);
				foreach($res['data'] as $v)
				{
					$proArr[$v['num_pro_id']]['numall'][] = ['oe'=> $v['num_factory'] == 'OE' ? 1: 0, 'factory'=>$v['num_factory'], 'display'=>$v['num_display']];
				}
			}

			//指定显示某厂商的号码
			if(!empty($othArr['factory'])){
				$where = sprintf(" and num_pro_id in (%s) and num_factory='%s' and num_show = 1 order by num_self desc, num_ismain desc, num_format", implode(',', $proIdArr), LibFc::Escape($othArr['factory']));
				$res = $this->get('bc_number', ['num_pro_id', 'num_factory', 'num_display', 'num_self', 'num_ismain'], $where);
				foreach($res['data'] as $v){
					$ntype = '';
					if($v['num_self'] == 1) $ntype = 'zb';
					else if($v['num_ismain'] == 1) $ntype = 'main';
					$proArr[$v['num_pro_id']]['numfac'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_display'], 'type'=>$ntype];
				}
			}
		

			//车型参数
			if(!empty($mod3Ids))
			{
				$modelPara = [];
				$where = sprintf(" and pml3_pro_id in (%s) and pml3_mod3_id in (%s) and pml3_remark != '' group by pml3_pro_id, pml3_remark", implode(',', array_keys($proArr)), implode(',', $mod3Ids));
				$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 in (%s) and pmp_info != '' group by pmp_pro_id, pmp_info", implode(',', array_keys($proArr)), implode(',', $mod3Ids));
				$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(in_array('modelAll', $typeArr))
			{
				$where = sprintf(" and pml3_pro_id in (%s)", implode(',', array_keys($proArr)));
				$res = $this->get('bc_product_model3_link', ['pml3_pro_id, pml3_mod3_id'], $where);
				foreach($res['data'] as $v)
				{
					$proArr[$v['pml3_pro_id']]['models'][] = $v['pml3_mod3_id'];
				}
			}

		}
		return LibFc::ReturnData(true, $proArr);
	}


	/**
	  * @method 获取配件的号码
	  * @param  $proId int 配件ID
	  * @param  $type string  oe|ref|all
	  * @param  $page int 第几页
	  * @param  $per int 每页数量
	  * @author soul
	  * @copyright 2017/6/5
	  * @return  ["status"=>true, "data"=>[{"factory":"FERODO","display":"2114023"},...] ]
	  */
	public function getItemNumber($proId, $type, $page, $per)
	{
		$proId = (int) $proId;
		$arr = [];

		//不显示互换号
		$res = $this->get('bc_product join sh_shop on shop_id=pro_shop_id', ['shop_srefnum'], sprintf(" and pro_id = %d",  $proId), true);
		if(empty($res['data']['shop_srefnum'])) return LibFc::ReturnData(true, $arr);

		$per = empty($per) || $per < 1 ? 20: (int) $per;
		$page = empty($page) || $page < 1 ? 1: (int) $page;
		$where = sprintf(" and num_pro_id=%d and num_show=1", $proId, ($page-1)*$per, $per);
		switch($type)
		{
			case 'oe':
				$where .= " and num_factory = 'OE'";
			break;
			case 'ref':
				$where .= " and num_factory != 'OE'";
			break;
		}
		
		if($type != 'OE')
		{
			$res = $this->get('bc_product left join bc_probrand on pro_prb_id=prb_id', ['prb_name'], sprintf(" and pro_id = %d",  $proId), true);
			$proArr = $res['data'];
		}
		$res = $this->get('bc_number', ['num_factory, num_display, num_self'], $where.sprintf(" order by num_factory, num_format limit %d, %d", ($page-1)*$per, $per));
		foreach($res['data'] as $v)
		{
			$v['num_factory'] = $v['num_self'] == 1 && isset($proArr['prb_name'])? $proArr['prb_name']: $v['num_factory'];
			$arr[] = ['oe'=> $v['num_factory'] == 'OE' ? 1: 0, 'factory'=>$v['num_factory'], 'display'=>$v['num_display']];
		}
		return LibFc::ReturnData(true, $arr);
	}


	/**
	  * @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 .= ' 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_path', "concat(spi_name, '.', spi_ext) as spi_name"], $where);
			foreach($res['data'] as $v)
			{
				$img = mvc::$cfg['FILE_CENTER']['b2c']['url_get'].'&c=product&f='.$v['spi_path'].'400/'.$v['spi_name'].mvc::$cfg['FILE_CENTER']['b2c']['get_uri'];
				if($arrFlag)
				{
					if(!$allPic&&!empty($returnArr[$v['pp_pro_id']]))
					{
						continue;
					}
					$returnArr[$v['pp_pro_id']][] = $img;
				}
				else
				{
					if(!$allPic&&!empty($returnArr))
					{
						continue;
					}
					$returnArr[] = $img;
				}
			}
		}
		return LibFc::ReturnData(true, $returnArr);
	}


	/**
	  * @method 获取产品参数
	  * @param  
	  * @author soul
	  * @copyright 2016/3/30
	  * @return array(3) 
	  */
	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  $number 
	  * @author soul
	  * @copyright 2017/6/5
	  * @return 	  
	  */
	public function getItemByNumber($number, $othWhere = '', $uid = 0)
	{
		$arr = [];
		$B2cBase = new B2cBase();
		$formatNum = LibFc::FormatNum($number);
		$where = $othWhere.sprintf(" and pro_status=1 and num_format = '%s'", LibFc::Escape($formatNum));
		$table = 'bc_number join bc_product on pro_id = num_pro_id join sh_shop on pro_shop_id=shop_id and shop_status = 1 and shop_istest != 1';
		$res = $B2cBase->get($table, ['distinct num_pro_id'], $where);
		if(!empty($res['data']))
		{
			$res = $this->getAnyProductInfo(array_column($res['data'], 'num_pro_id'), ['numMain', 'picMain']);
			$arr = $res['data'];
		}
		return LibFc::ReturnData(true, $arr);
	}


	/**
	  * @method 店铺配件搜索  条件：keyword关键字、mod3Id末级车型ID、sortId店铺分类、minPrice maxPrice价格区间
	  * @param  $Params URL参数
	  * @param  $perPage 每页显示多少条
	  * @author soul
	  * @copyright 2017/9/22
	  * @return 
			成功 ["status"=>true, "data"=> ] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	public function searchShopItem($Params, $perPage = 20,$isPart=false)
	{
		$returnArr=[];
		$typeArr = [$Params['type']];
		foreach($typeArr as $type)
		{
			$table = 'bc_product join sh_shop on pro_shop_id=shop_id and shop_status = 1 and pro_status = 1';
			if(stripos($Params['show'], 'pro_show_pjl') !== false) $table .= ' and pro_show_pjl = 1';
			if(stripos($Params['show'], 'pro_show_b2c') !== false) $table .= ' and pro_show_b2c = 1';
			$whereArr = [];
			switch($type)
			{
				case 'number':
					
				break;
				case 'all':
				case 'item':
				case 'model':
					$Params['m3Id'] = (int) $Params['m3Id'];
					if($Params['m3Id'] > 0)
					{
						$table .= ' right join bc_product_model3_link on pro_id = pml3_pro_id';
						$whereArr['mod3'] = sprintf(" and pml3_mod3_id=%d", $Params['m3Id']);
					}
					
					//店铺分类
					if(!empty($Params['sortId']))
					{
						$sortArr=explode(',',$Params['sortId']);
						$sortArr=array_filter($sortArr,'LibFc::Int');
						if(!empty($sortArr))
						{
							$whereArr['sort'] = sprintf(" and pro_part_id in(%s)", implode(',',$sortArr));
						}else{
							$whereArr['sort']=' and pro_part_id<0';
						}
					}
					if(!empty($Params['part_id']))
					{
						$tarr = [];
						foreach(explode(',', $Params['part_id']) as $tv)
						{
							if(!empty($tv)) $tarr[] = (int) $tv;
						}
						$tarr = array_unique($tarr);
						if(!empty($tarr)) 
							$whereArr['part'] = sprintf(" and pro_part_id in (%s)", implode(',', $tarr));
					}

					//配件关键字
					if($Params['keyword'] != '')
					{
						//关键词
						$keywordArr = LibFc::keyword($Params['keyword']);
						$blparams = ['word'=>implode(' ',$keywordArr),'count'=>10000];
						if(!empty($whereArr)){//限制少量产品
							$res = $this->get($table, ['distinct pro_id'], implode(' ', $whereArr));
							$blparams['pro_id'] = array_values(array_filter(array_column($res['data'], 'pro_id')));
						}
						$B2cElastic = new B2cElastic();
						$res = $B2cElastic->searchProId($blparams);
						if(!empty($res['data']))
						{
							$Params['orderPids'] = $res['data'];
							$tempWhere = sprintf(" and pro_id in (%s)", implode(',',$res['data']));
						}
						else
						{
							$tempWhere = sprintf(" and pro_name like '%%%s%%'", LibFc::Escape($Params['keyword']));
						}
						$whereArr['word'] = $tempWhere;
					}
				break;
			}
		}
		
		//价格区间
		if(!empty($Params['minPrice']) || !empty($Params['maxPrice']))
		{
			$whereArr['price']= !empty($Params['minPrice']) ? sprintf(' and (case when pro_promotion_btime <= %d and pro_promotion_etime >= %d then pro_promotion_price else pro_sale_price end) >=%.2f',time(),time(),$Params['minPrice']) : '';
			$whereArr['price'] .= !empty($Params['maxPrice']) ? sprintf(' and (case when pro_promotion_btime <= %d and pro_promotion_etime >= %d then pro_promotion_price else pro_sale_price end) <=%.2f',time(),time(),$Params['maxPrice']) : '';
		}
		$Params['page']= empty($Params['page'])? 1: (int) $Params['page'];
		$perPage = empty($perPage)? 20: (int) $perPage;
		$res = $this->get($table, ['count(distinct(pro_id)) count'], implode(' ', $whereArr), true);
		$returnArr['total'] = $res['data']['count'];
		if($returnArr['total'] > 0)
		{
			if(!empty($Params['orderPids'])) $Params['order'] = 'pids';
			//默认销量排序
			$res = $this->getSearchProductOrder($Params);
			$orderBy = $res['data'];
			$where = sprintf(" and pro_id in (select pro_id from %s where 1=1 %s group by pro_id) group by pro_id %s limit %d, %d", $table, implode(' ', $whereArr), $orderBy, ($Params['page']-1)*$perPage, $perPage);
			$res = $this->get('bc_product join sh_shop on pro_shop_id=shop_id', ['pro_id'], $where);
			$returnArr['proIds'] = array_column($res['data'], 'pro_id');
		}
		return LibFc::ReturnData(true, $returnArr); 
	}
	/**
	  * @method 获取配件搜索的排序条件
	  * @param  $Params URL参数  new-desc | price-asc | price-desc
	  * @author soul
	  * @copyright 2017/9/22
	  * @return 
			成功 ["status"=>true, "data"=>'order by pro_sold_count desc'] 
			失败 ["status"=>false, "data"=> 错误信息] 
	  */
	private function getSearchProductOrder($Params)
	{
		$orderBy = ' order by shop_money_bail desc, pro_promoted asc,pro_host asc,pro_sold_count desc,pro_id asc';
		switch($Params['order'])
		{
			//新品
			case 'new-desc':
				$orderBy = ' order by pro_id desc';
			break;
			//价格从底到高
			case 'price-asc':
				$orderBy = sprintf(' order by (case when pro_promotion_btime<=%d and pro_promotion_etime>=%d then pro_promotion_price else pro_sale_price end) asc',time(),time());
			break;
			//价格从高到底
			case 'price-desc':
				$orderBy = sprintf(' order by (case when pro_promotion_btime<=%d and pro_promotion_etime>=%d then pro_promotion_price else pro_sale_price end) desc',time(),time());
			break;
			case 'sold-count':
				$orderBy = ' order by pro_sold_count desc';
			break;
			//跑街随机 2023/7/5
			case 'pjlrand':
				$date = date('j');
				$orderBy = " order by mod(pro_id, {$date}),pro_id";
			break;
			case 'sort_part_proname':
				$orderBy = " order by GROUP_CONCAT(LPAD(sort_seq,5,'0') ORDER BY sort_seq SEPARATOR ''), pt_seq, pas_seq, part_initial, pro_name";
			break;
			case 'pids': 
				$orderBy = sprintf(" order by FIELD(pro_id, %s)",implode(',', $Params['orderPids']));
			break;
		}
		return LibFc::ReturnData(true, $orderBy);
	}
	/**
	 * @method    商城分类搜索
	 * @http get  
	 * @param   m3Id  int  [可选] 车型id
	 * @param   keyword str  [可选] 关键字
	 * @param   minPrice  float  [可选] 筛选价格的最低价
	 * @param   maxPrice  float  [可选] 筛选价格的最高价
	 * @param   order  str  [可选]   new-desc[新品]|price-asc[价格升]|price-desc|sold-count[销量倒序]
	 * @return    [json]     {"status":true,"data":{"total":573,"itemArr":[{"pro_id":"101237","prb_name":"信义","pro_status":"1","pro_name":"刹车片刹车皮盘式片\/大众,斯柯达,奔腾","pro_shop_id":"172999","pro_sale_price":"0.08","pro_count":"82","pro_user_discount":"Y","pro_sold_count":"18","pro_part_id":"2927","pri_code":"XYD133","pri_weight":"1.000","pri_frt_id":"3098","pro_sel_des":"一线品牌，性价比超高，放心购买！","pri_invoice":"0","pri_warranty":"0","pri_return_promise":"1","price":"0.08","price_type":1,"pro_price":{"title":"销售价","price":"0.08"},"pic":["http:\/\/192.168.1.42\/file_center\/center\/read.php?site=b2c&c=product&f=shop172999\/product\/400\/9572a9ba8751c46d.jpg&i=42"],"num":[{"factory":"信义","display":"XYD133"},{"factory":"OE","display":"272 016 15 20"}]}]},"code":0,"encry":0,"runtime":495}
	 *pro_id 产品id   prb_name 品牌  pro_status 0未上架   1售卖中  -1违规  2预售  pro_name 名称  pro_shop_id 店铺id  pro_sale_price 销售价 pro_count 库存
	 *pro_sold_count  销量  pro_part_id 分类ID   pri_code 商家型号    price_type 1：销售价 2 促销价 3 会员价  pro_price  展示价格  pic 图片  num 号码
	 * 
	 * @author lu
	 * @copyright 2019-01-08
	 */
	public function getSearchPart($Params)
	{
		$table = 'bc_product join sh_shop on pro_shop_id=shop_id and shop_status = 1 and pro_status =1';
		$whereArr = [];
		$Params['mod3Id'] = (int) $Params['mod3Id'];
		if($Params['mod3Id'] > 0)
		{
			$table .= ' right join bc_product_model3_link on pro_id = pml3_pro_id';
			$whereArr['mod3'] = sprintf(" and pml3_mod3_id=%d", $Params['mod3Id']);
		}
		//配件关键字
		if($Params['keyword'] != '')
		{
			$keywordArr = LibFc::keyword($Params['keyword']);
			$B2cKeyword = new B2cKeyword();
			$res = $B2cKeyword->getKeywordKeyIds($keywordArr);
			if(!empty($res['data']))
			{
				$tempWhere = sprintf(" and pro_id in (select prk_pro_id from bc_product_keyword where prk_key_id in (%s) group by prk_pro_id having count(*) = %d)", implode(',', $res['data']), count($res['data']));
			}
			else
			{
				$tempWhere = sprintf(" and pro_name like '%%%s%%'", LibFc::Escape($Params['keyword']));
			}
			$whereArr['word'] = $tempWhere;
		}
		//价格区间
		if(!empty($Params['minPrice']) || !empty($Params['maxPrice']))
		{
			$whereArr['price']= !empty($Params['minPrice']) ? sprintf(' and (case when pro_promotion_btime<=%d and pro_promotion_etime>=%d then pro_promotion_price else pro_sale_price end) >=%.2f',time(),time(),$Params['minPrice']) : '';
			$whereArr['price'] .= !empty($Params['maxPrice']) ? sprintf(' and (case when pro_promotion_btime<=%d and pro_promotion_etime>=%d then pro_promotion_price else pro_sale_price end) <=%.2f',time(),time(),$Params['maxPrice']) : '';
		}
		$res = $this->get($table, ['distinct pro_part_id'], implode(' ', $whereArr));
		$returnArr['sortIds']=array_values(array_column($res['data'], 'pro_part_id'));
		return LibFc::ReturnData(true, $returnArr); 
	}
	/**
	 * @method    根据id获取分类
	 * @param     [arr]     $partArr [分类id]
	 * @return    [type]              [description]
	 * @author lu
	 * @copyright 2019-01-09
	 */
	public function getPart($partArr)
	{
		$dataArr=[];
		$partArr=array_filter($partArr);
		if(!empty($partArr))
		{
			$res=$this->get('bc_part right join bc_part_tree on pt_part_id=part_id',['part_id','pt_parent_part_id','part_name','pt_path'],sprintf(' and part_id in(%s) and pt_ismain=1 order by pt_seq asc,part_id asc',implode(',',$partArr)));
			$dataArr=$res['data'];
		}
		return LibFc::ReturnData(true, $dataArr); 
	}

	

	/**
	 * @method 通过号码或者产品ID  匹配车型
	 * @param  $proId  int[$proId、$numArr二选一，优先产品ID]  产品ID  
	 * @param  $numArr array[$proId、$numArr二选一，优先产品ID]  [
							[
								'factory'=>'OE',
								'display'=>'123-456-789'
							]...
						]
	 * @param  $spartId  string [选填] 商城分类ID	1111_22
	 * @author soul12
	 * @copyright 2020/6/10
	 */
	public function matchB2cItemModel($proId = 0, $numArr = [], $spartId = '')
	{
		$arr = ['m3ids'=>[]];
		if($proId > 0)
		{
			$res = $this->get('bc_number', ['num_factory as factory, num_format as display'], sprintf(" and num_pro_id =%d and num_self = 0 and num_factory != ''", $proId));
			$numArr = $res['data'];
		}
		else
		{
			foreach($numArr as $k=>$v)
			{
				$t = LibFc::FormatNum($v['display']);
				if(strlen($t) < 3 || empty($v['factory']))
				{
					unset($numArr[$k]);
				}
				else
				{
					$numArr[$k]['display'] = LibFc::FormatNum($v['display']);
				}
			}
		}
		if(empty($numArr)) return LibFc::ReturnData(true, $arr); 
		$YpcModel = new YpcModel();
		$res = $YpcModel->getM3idByNum($numArr, $spartId);
		$arr['m3ids'] = $res['data'];

		//EPC找不到，找宜配
		if(empty($arr['m3ids']))
		{
			$tw = [];
			foreach($numArr as $v)
			{
				$tw[] = sprintf("(UPPER(f.factory) = '%s' and n.format='%s')", strtoupper(LibFc::Escape($v['factory'])), LibFc::Escape($v['display']));
			}
			$YpsProduct = new YpsProduct();
			$res = $YpsProduct->get('yp_number AS n JOIN yp_factory AS f ON n.fid = f.fid', ['DISTINCT pid'], sprintf(" and (%s)", implode(' or ', $tw)));
			if(!empty($res['data']))
			{
				$arr['yp_proids'] = array_column($res['data'], 'pid');
				$res = $YpsProduct->getYpcModelId($arr['yp_proids']);
				$arr['m3ids'] = array_merge($arr['m3ids'], $res['data']);
			}
		}
		//宜配找不到，找TCD
		if(empty($arr['m3ids']))
		{
			/*$tw = [];
			foreach($numArr as $v)
			{
				$tw[] = sprintf("(UPPER(f.factory) = '%s' and n.format='%s')", strtoupper(LibFc::Escape($v['factory'])), LibFc::Escape($v['display']));
			}
			$YpsProduct = new YpsProduct();
			$res = $YpsProduct->get('yp_number AS n JOIN yp_factory AS f ON n.fid = f.fid', ['DISTINCT pid'], sprintf(" and (%s)", implode(' or ', $tw)));
			if(!empty($res['data']))
			{
				$arr['yp_proids'] = array_column($res['data'], 'pid');
				$res = $YpsProduct->getYpcModelId($arr['yp_proids']);
				$arr['m3ids'] = array_merge($arr['m3ids'], $res['data']);
			}*/
		}
		return LibFc::ReturnData(true, $arr); 
	}

	
	/**
	  * @method 新增或更新配件
	  * @http	post
	  * @param  $dataArr            array [必填]
	  * @author soul
	  * @copyright 2024/2/20
	  * @return {"status":true,"data":100,"code":0,"runtime":304}
	  */
	public function updateItemByApi($shopId, $proArr)
	{
		$proId = 0;
		$res = $this->checkImportSuperItem($shopId, $proArr);
		if(!empty($res['data']['items'])){
			$items = $res['data']['items'];
			$res = $this->get('sh_shop_app', ['aps_shop_id'], sprintf(" and aps_status=1 and aps_shop_id=%d and aps_etime >=%d", $shopId, time()), true);
			if(!empty($res['data'])){
				$res = $this->importB2cItem($shopId, $items);
			}else{
				$res = $this->importSuperItem($shopId, $items);
			}
			if(!empty($res['data'][0])) $proId = $res['data'][0];
		}else{
			return LibFc::ReturnData(false, json_encode($res['data']['chkerr'], JSON_UNESCAPED_UNICODE));
		}
		return LibFc::ReturnData(true, $proId);
	}


	/**
	  * @method 更新配件图片
	  * @http	post
	  * @param  $proId              int [必填] 配件ID
	  * @param  $dataArr            array [必填] ["图片内容的base64","图片内容的base64"] 图片内容的base64，多张逗号分隔，为空则清空
	  * @author soul
	  * @copyright 2024/2/20
	  * @return {"status":true,"data":100,"code":0,"runtime":304}
	  */
	public function updateItemImageByApi($shopId, $proId, $imgArr)
	{
		$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id =%d and pro_shop_id=%d", $proId, $shopId));
		if(empty($res['data'])) return LibFc::ReturnData(false, '此配件不属于该店铺ID');
		if(empty($imgArr)){
			$this->del('bc_product_pic', sprintf(" and pp_pro_id =%d", $proId));
			return LibFc::ReturnData(true, $proId);
		}
		$spiIdArr = [];
		//echo base64_encode(file_get_contents("D:/62b18d1484032.jpg"));exit;
		foreach ($imgArr as $img) 
		{
			if(empty($img)) continue;
			$imgdata = base64_decode($img);
			$imginfo = getimagesizefromstring($imgdata);
			$name = md5($img);
			if(stripos($imginfo['mime'], 'png') !== false){
				$name .= '.png';
			}else if(stripos($imginfo['mime'], 'gif') !== false){
				$name .= '.png';
			}else if(stripos($imginfo['mime'], 'bmp') !== false){
				$name .= '.bmp';
			}else if(stripos($imginfo['mime'], 'jpeg') !== false){
				$name .= '.jpeg';
			}else{
				$name .= '.jpg';
			}
			$img = mvc::$cfg['PATH_CACHE'].$name;
			if(!file_exists($img)) file_put_contents($img, $imgdata);
			$res = $this->batchUploadImg($img, $shopId);
			@unlink($img);
			if(!empty($res['data']))
				$spiIdArr[] = $res['data']['spi_id'];
		}
		if(!empty($spiIdArr)) $this->setProductPic($shopId, $proId, $spiIdArr);
		return LibFc::ReturnData(true, $proId); 
	}


	/**
	  * @method 更新配件车型
	  * @param  $proId              int [必填] 配件ID
	  * @param  $modArr            array [必填] [{"mod3_id":"10", "remark":"前左"}...]为空则清空
	  * @author soul
	  * @copyright 2024/2/20
	  * @return {"status":true,"data":100,"code":0,"runtime":304}
	  */
	public function updateItemModelByApi($shopId, $proId, $modArr)
	{
		$res = $this->get('bc_product', ['pro_id'], sprintf(" and pro_id =%d and pro_shop_id=%d", $proId, $shopId));
		if(empty($res['data'])) return LibFc::ReturnData(false, '此配件不属于该店铺ID');
		$this->setProductModel($proId, $modArr);
		return LibFc::ReturnData(true, $proId); 
	}


	/**
	 * @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':
					case 'pro_sel_des':
						$tempArr['base'][$filed] = $val;
					break;
					case 'pro_sale_des':
						$tempArr['base']['pro_sel_des'] = $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': //描述
					case 'pri_code': //自编号
					case 'pri_self_remark':
						$tempArr['info'][$filed] = $val;
					break;
					case 'pri_keyword':
						$tempArr['info'][$filed] = LibFc::fromatKeyword($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_id'] = $partNameArr[strtoupper($val)]['part_id'];
									$tempArr['base']['pro_pas_id'] = (int) $partNameArr[strtoupper($val)]['pas_id'];
								}
								else
								{
									$tempErr[] = '配件分类（'.$val.'）不存在。';
								}
							}
						}
					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': //互换号 多个逗号分隔
						//全角转半角
						$tempArr['nums'] = [];
						$val = LibFc::GetSemiangle($val);
						$val = strtr($val, [","=>";","\n"=>";"]);
						$main = null;
						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_param': //配件自定义参数
						$tempArr['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': //店铺分类 多个逗号分隔
						$tempArr['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 'pro_status':
						$tempArr['base'][$filed] = empty($val)? 0: 1;
						break;
					case 'param': //
						$tempArr['part_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;
				}
			}
			//产品id存在时，更改 品牌与商家编码 不可重复
			if($tempArr['info']['pri_code'] && !empty($tempArr['base']['pro_id'])){
				
				$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'];
					$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 importB2cItem($shopId, $proArr)
	{
		$this->B2CDb->Begin();
		$B2cShopSort = new B2cShopSort();
		$proIdArr = [];
		foreach($proArr as $pro)
		{
			if(isset($pro['shop_sort'])) $pro['shopSort'] = [];
			if(isset($pro['part_param'])) $pro['param'] = [];
			//店铺分类
			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(isset($pro['pro_param']))
				$this->setBatchParam($pro['base']['pro_id'], $shopId, $pro['pro_param']);

			$proIdArr[] = $pro['base']['pro_id'];
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $proIdArr);
	}

	/**
	 * @method  将检测后的数据入库
	 * @param $shopId int 目录店铺ID
	 * @param $proArr 
	 * @author	soul
	 * @copyright 2018/6/8
	 */
	public function importSuperItem($shopId, $proArr)
	{
		$this->B2CDb->Begin();
		$B2cShopSort = new B2cShopSort();
		$proIdArr = [];
		
		foreach($proArr as $pro)
		{
			if(isset($pro['shop_sort'])) $pro['shopSort'] = [];
			if(isset($pro['part_param'])) $pro['param'] = [];
			//店铺分类
			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(isset($pro['pro_param']))
					$this->setBatchParam($pro['base']['pro_id'], $shopId, $pro['pro_param'], $pro['ppt_name']);
				$proIdArr[] = $pro['base']['pro_id'];
			}
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, $proIdArr);
	}

	
	/**
	  * @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(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']);

		$this->setProductSelfNum($proId, ['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']);
		}
		//刷新配件关键字
		$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);
		//同步产品
		$sortIdArr = array_filter($dataArr['shopSort']?:[]);
		$proSyncSet = $this->getProSynSet($shopId,[$partId],$sortIdArr);
	
		if($proSyncSet)
		{
			foreach ($proSyncSet as $prosyn) {
				$this->copyProduct($shopId,$prosyn,$proId);
			}
		}
		$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);
				}
			}
			
			$this->setProductSelfNum($proId, ['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(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));
		//刷新配件关键字
		$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);
		//同步产品
		$sortIdArr =array_filter($dataArr['shopSort']?:[]);
		
		$proSyncSet = $this->getProSynSet($shopId,[$partId],$sortIdArr);
		//先把符合设置的产品更新
		if ($proSyncSet) {
			foreach ($proSyncSet as $prosyn) {
				$this->copyProduct($shopId, $prosyn, $proId);
			}
		} 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']]);
				}
			}
		}
		
		$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))
			return LibFc::ReturnData(false, 'setBatchParam 提供的参数不正确');
		$pru_id = (int) $pru_id;
		if(empty($pptName)) $pptName = '默认模板';

		if(empty($param)){
			$this->del('bc_product_para_val', sprintf("and prpv_pro_id=%d",$proId));
			return LibFc::ReturnData(true, true);
		}

		$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     [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 修改配件的号码
	  * @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))
		{
			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 更新配件的所属店铺分类
	  * @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)));
		$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();
		$B2cElastic = new B2cElastic();
		$B2cElastic->delItemWord($proIdArr);
		return LibFc::ReturnData(true, true);
	}

	/**
	  * @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 通过末级的使用车型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))
		{
			$Ypc2Model = new Ypc2Model();
			$res = $Ypc2Model->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)));
		
		$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);
		
		//置空底盘件、发动机模式
		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));
		}
		$this->B2CDb->End();
		return LibFc::ReturnData(true, true);
	}

	/**
	* @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_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 $shopId  商城id
	* @param  array $partId  分类id
	* @param  array $sortId 店铺分类id
	* @param  string $act  set 新增/更新（需代理商确认） del 删除
	* @method 获取产品同步配置
	* @author zhengweihua 
	* @copyright 2022-10-21
	*/
	protected function getProSynSet($shopId,$partId = [],$sortId = [],$act = 'set')
	{
		
		$where = sprintf(" and sps_from_shop_id = %d and sps_status =1", $shopId);
		if($act == 'set')
		{
			$where .= " and sps_chkstatus = 1";
		}
		$toShopId = [];
		if($partId){
			$table = 'sh_prosyn join sh_prosyn_part on spp_sps_id = sps_id';
			$where1 = $where.sprintf(" and spp_part_id in (%s)",implode(',',$partId) );

			$prosynres = $this->get($table,['distinct sps_to_shop_id'],$where1);
			$toShopId = array_column($prosynres['data'],'sps_to_shop_id');
		}
		if($sortId){
			$table = 'sh_prosyn join sh_prosyn_sort on spt_sps_id = sps_id';
			$where2 = $where.sprintf(" and spt_sort_id in (%s)",implode(',',$sortId) );
			$prosynres = $this->get($table,['distinct sps_to_shop_id'],$where2);
			$toShopId =  array_merge(array_column($prosynres['data'],'sps_to_shop_id'),$toShopId);
		}
		
		return array_filter($toShopId);
	}


	/**
	  * @method 跑街产品车型自动匹配任务
	  * @param  $cfg array  [
				'shopid'=>369676,	// 店铺ID
				'from'=>'NUMBER',	// string ZHIPEI:智配 NUMBER：号码匹配
				'proids'=>[], //NUMBER时可以指定产品	
			]
	  * @author soul
	  * @copyright 
	  * @return 
	  */
	public function autoYpb2cItemModel($cfg)
	{
		$version = date('Ymd');
		$shopId = (int) $cfg['shopid'];
		if($cfg['from'] == 'NUMBER'){
			$where = sprintf(" and pro_shop_id = %d AND num_factory != '' and pro_automodel_num < %d", $shopId, $version);
			if(isset($cfg['proids']) && is_array($cfg['proids']) && !empty($cfg['proids'])) $where .= sprintf(" and pro_id in (%s)", implode(',', $cfg['proids']));
			$res = $this->get('bc_product JOIN bc_number ON pro_id = num_pro_id', ['pro_id, pro_part_id, pro_pas_id, num_factory, num_format'], $where);
			if(empty($res['data'])) return LibFc::ReturnData(true);

			$proArr = [];
			foreach($res['data'] as $v){
				if(empty($proArr[$v['pro_id']])){
					$proArr[$v['pro_id']] = ['part_id'=>$v['pro_part_id'], 'pas_id'=>$v['pro_pas_id'], 'nums'=>[]];
				}
				$proArr[$v['pro_id']]['nums'][] = ['factory'=>$v['num_factory'], 'display'=>$v['num_format']];
			}
			$YpcModel = new YpcModel();
			$this->B2CDb->Begin();
			foreach($proArr as $proId=>$tv){
				$res = $YpcModel->getM3idByNum($tv['nums'], $tv['pas_id']);
				if(empty($res['data'])) continue;
				
				$newIdArr = $res['data'];
				//已经有的
				$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'] == $cfg['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'=>'',
							'pma_from'=>$cfg['from'],
							'pma_atime'=>time(),
							'pma_etime'=>time(),
						];
					}
					$this->addAny('bc_product_model_auto', array_keys($addArr[0]), $addArr);
				}
			}
			$this->set('bc_product', ['pro_automodel_num'=>$version], sprintf(" and pro_id in (%s)", implode(',', array_keys($proArr))));
			$this->B2CDb->End();
		}
		return LibFc::ReturnData(true);
	}
}