<?php
namespace model\pro;
use \model\pro\cate;
use \model\pro\factory;
use \model\pro\param;
use \model\pro\paramset;
use \model\carmodel;
use \model\tags;
use \model\check;
use \model\pro\numidx;
use \model\pro\promodel;
use \model\collocation;
use \model\country;
use \model\files;
use \model\rcaApi;
use \model\sample\sampleDate;
use \model\ypRcaApi;
use \model\ypApi;
use model\alioss;

class pro extends \model
{
    public $table = 'pro';
    public $key = 'p_id';
	public $joinWhere = [];
    public $cate;
    public $factory;
    public $paramset;
    public $param;
    public $paramStrenvalKeyValues = []; //参数翻译
    public $paramType;
    public $tags;
	public $formatRowCache = [];
	public $codeFields = [];
	public $defaultFieldName= [];
	public $allPos = [];
	public $group = [];
	public $join = [];

	public function __construct()
    {
        $db = new \lib\db(\mvc::$cfg['db']['main']);
		parent::__construct($db);
        $this->cate = new cate();
        $this->factory = new factory();
        $this->paramset = new paramset();
        $this->param = new param();
        $this->tags = new tags();
		$this->paramType = [
			'int'=>'int',
			'double'=>'double',
			'string'=>'string',
			'smalltxt'=>'smalltxt',
			'bigtxt'=>'smalltxt',
			'list'=>'int',
			'radio'=>'int',
			'checkbox'=>'string'
		];

		$this->codeFields = ['p_state_main'=>'主状态','p_state_remark'=>"主状态备注",'p_item_type'=>"物料类型",'p_cn_name'=>'产品中文名','p_en_name'=>'产品英文名','p_py_name'=>'产品俄文名',
			'p_cn_model'=>'车型中文名','p_en_model'=>'车型英文名','p_py_model'=>'车型俄文名','p_auto_assign'=>'是否自动分配','p_unit'=>'基本单位','p_en_guige'=>'规格英文',
			'p_py_guige'=>'规格俄文','p_chassis'=>'底盘','p_model_year_range'=>'车型年限','p_engine'=>'发动机','p_cc'=>'排量','p_inter_develop'=>'内部研发',
			'p_develop_no'=>'开发号','p_progroup'=>'产品组','pe_category'=>'产品分类','pe_sales_warranty'=>'产品销售质保期','pe_install_remark'=>'安装注意事项','pe_warehouse_date'=>'入仓日期',
			'pe_safety_stock'=>'安全库存','pe_max_stock'=>'库存上限','pe_min_stock'=>'库存下限','pe_assign_user'=>'分配组员','pe_sqe'=>'SQE名称','pe_purchase'=>'采购组',
			'pe_purchase_leader'=>'采购组长','pe_purchase_manager'=>'采购负责人','pe_purchase_follower'=>'采购跟单员','pe_purchase_follower2'=>'备选采购跟单员',"pn_main_formart"=>'主OE'
			,'p_pos1'=>lg('前/后轴'),'p_pos2'=>lg('前/后'),'p_pos3'=>lg('左/右'),'p_pos4'=>lg('外/中/内'),'p_pos5'=>lg('上/中/下')
		];
		$this->defaultFieldName = [
			'pro_bom_assemble'=>['mainkey'=>['pba_p_id'],'pba_name'=>'名称','pba_count'=>'数量'],

			'pro_bom_pack'=>['mainkey'=>['pbp_id'],'pbp_name'=>'名称','pbp_count'=>'数量'],

			'pro_source_link'=>['mainkey'=>['psl_p_id'],'psl_code'=>'国标码','psl_from'=>'来源','psl_from_id'=>'来源ID'],
			'pro_exchange'=>[
				'mainkey'=>['pe_p_id1','pe_p_id2'],'pe_param1'=>'属性1','pe_param2'=>'属性2','pe_remark'=>'备注','pe_frometo'=>'通用方向'
			],
			'pro_pair'=>[
				'mainkey'=>['pp_p_id1','pp_p_id2'],'pp_pos'=>'安装位置1','pp_pos2'=>'安装位置2','pp_remark'=>'备注','pp_group'=>'组号'
			],
			'pro_fatherson'=>[
				'mainkey'=>['pf_father_pid','pf_son_pid']
			]
		];

		//位置配置
		$this->allPos = [
			'pos1'=>['name'=>lg('前/后轴'),'gd'=>[""=>"", "F"=>"F", "R"=>"R"], 'edit'=>'F:F,R:R'],
			'pos2'=>['name'=>lg('前/后'),'gd'=>[""=>"", "F"=>"F", "R"=>"R"], 'edit'=>'F:F,R:R'],
			'pos3'=>['name'=>lg('左/中/右'),'gd'=>[""=>"", "L"=>"L", "C"=>"C", "R"=>"R"], 'edit'=>'L:L,C:C,R:R'],
			'pos4'=>['name'=>lg('外/中/内'),'gd'=>[""=>"", "O"=>"O", "C"=>"C", "I"=>"I"], 'edit'=>'O:O,C:C,I:I'],
			'pos5'=>['name'=>lg('上/中/下'),'gd'=>[""=>"", "U"=>"U", "C"=>"C", "L"=>"L"], 'edit'=>'U:U,C:C,L:L'],
		];
	}


	/**
     * 获取SKU品牌的新物料编码 [待完善]
     * @param int $pb_id SKU品牌ID
     * @param int $cat_id 小类ID
     * @param int $tb_id 汽车品牌ID
     * @return string
     */
	function buildBrandInnum($pb_id, $cat_id, $tb_id, $item_type)
	{
		$codenum = '';
		$rule = $this->db->get('pro_brand', ['pb_id', 'pb_'.LG_NAME.'(pb_name)', 'pb_code_rule', 'pb_rules'], ['pb_id'=>$pb_id]);
		if(empty($rule['pb_rules'])) return ['codenum'=>$codenum, 'msg'=>$rule['pb_name'].'编码规则尚未定义'];
		$rule['pb_rules'] = explode('@', $rule['pb_rules']);
		$rule['cate'] = $this->db->get('pro_cate(cat)', ['[><]pro_rule_link(prl)'=>['cat.id'=>'prl_val_id']], ['cat.'.LG_NAME.'(cate_name)', 'cat_item_type', 'prl_code_a', 'cat_seqrule'], ['prl_type'=>'cate', 'prl_val_id'=>$cat_id, 'prl_pb_id'=>1]);
		if(empty($item_type)) $item_type = $rule['cate']['cat_item_type'];
		// $rule['mod'] = $this->db->debug()->get('tag_brand(tb)', ['[<]pro_rule_link(prl)'=>['tb.tb_id'=>'prl_val_id']], ['tb.tb_'.LG_NAME.'(tb_name)','prl_code_a', 'prl_code_b'], ['prl_type'=>'brand', 'prl_val_id'=>$tb_id, 'prl_pb_id'=>1]);
		// 汽车品牌的临时处理
		$rule['mod'] = $this->db->get('tag_brand(tb)', ['[<]pro_rule_link(prl)'=>['tb.tb_id'=>'prl_val_id']], ['tb.tb_'.LG_NAME.'(tb_name)','prl_code_a', 'prl_code_b'], ['prl_type'=>'cate', 'prl_val_id'=>$tb_id, 'prl_pb_id'=>1]);
		
		$codefull = ['begin'=>'', 'seq'=>'', 'end'=>''];
		foreach($rule['pb_rules'] as $type){
			switch($type){
				case 'M'://汽车品牌
					if($pb_id == 1){
						$val = $item_type == 101? 'C': 'B';
						if(empty($codefull['seq'])){
							$codefull['begin'] .= $val;
						}else{
							$codefull['end'] .= $val;
						}
					}else{
						$field = $item_type == 101? 'prl_code_a': 'prl_code_b';
						if(empty($rule['mod'][$field])) return ['codenum'=>$codenum, 'msg'=>$rule['pb_name'].'汽车品牌'.$rule['mod']['tb_name'].'编码尚未定义'];
						if(empty($codefull['seq'])){
							$codefull['begin'] .= $rule['mod'][$field];
						}else{
							$codefull['end'] .= $rule['mod'][$field];
						}
					}
					break;
				case 'C'://小类
					if(empty($rule['cate']['prl_code_a']))  return ['codenum'=>$codenum, 'msg'=>$rule['pb_name'].'小类'.$rule['cate']['cate_name'].'编码尚未定义']; 
					if(empty($codefull['seq'])){
						$codefull['begin'] .= $rule['cate']['prl_code_a'];
					}else{
						$codefull['end'] .= $rule['cate']['prl_code_a'];
					}
					break;
				case 'S'://流水
					$codefull['seq'] = $rule['cate']['cat_seqrule'] > 3? '[0-9]{3,'.$rule['cate']['cat_seqrule'].'}':'[0-9]{'.$rule['cate']['cat_seqrule'].'}';
					$codefull['seq_len'] = $rule['cate']['cat_seqrule'];
					break;
				case 'B'://品牌标识码
					
					if(empty($rule['pb_code_rule'])) return ['codenum'=>$codenum, 'msg'=>$rule['pb_name'].'品牌编码尚未定义'];
					if(empty($codefull['seq'])){
						$codefull['begin'] .= $rule['pb_code_rule'];
					}else{
						$codefull['end'] .= $rule['pb_code_rule'];
					}
					break;
			}
		}
		$sql = sprintf("SELECT MAX(CAST(SUBSTRING(p_innum, %d, LENGTH(p_innum)-%d) AS UNSIGNED)) AS max_seq FROM pro WHERE p_innum REGEXP '^%s%s%s$'", strlen($codefull['begin'])+1 , strlen($codefull['begin'])+ strlen($codefull['end']), $codefull['begin'], $codefull['seq'], $codefull['end']);
		$row = $this->db->query($sql)->fetch(\PDO::FETCH_ASSOC);
		$newseq = $row['max_seq'] === null ? 0: $row['max_seq']+1;
		$newseq = str_pad($newseq, $codefull['seq_len'], "0", STR_PAD_LEFT);
		$codenum = $codefull['begin'].$newseq.$codefull['end'];
		return ['codenum'=>$codenum, 'seqno'=>$newseq, 'msg'=>''];
	}


	function getDb(){
	    return $this->db;
	}
	
	function list($rules, $where='',$page=0,$pagesize=0,$sidx='',$sord='asc',$orderby=''){
        $table = $this->table.'(p)';
        $this->fields = ['p.*', 'pb_'.LG_NAME.'(pb_name)'];
		$refiled = [
			'pb_name'=>'pb.pb_'.LG_NAME,
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);
        $this->join = [
			"[>]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"]
		];
		$this->joinWhere = [];
		$this->group = [];
		$whereRegi = 0;
		$othWhere = [];
        $where = $this->filter2medoo($where,function(&$field,&$op,&$data)use(&$rules,&$whereRegi,&$othWhere){
            $field = strtr( $field, $this->get('refiled'));
			$whereRegi++;
            switch($field){
                case 'p_cate':
                    $op = 'eq';
                    $data = $this->cate->like($data);
                    if(empty($data)) $data = [0];
                    break;
                case 'p_bigcate':
					$field = 'p_cate';
                    $op = 'eq';
                    $data = $this->cate->likeAndChilds($data);
                    if(empty($data)) $data = [0];
                    break;
                case 'p_cateas':
					$field = 'p_cate';
                    $op = 'eq';
                    $data = $this->cate->likeAs($data);
                    if(empty($data)) $data = [0];
                    break;
                case 'hasnumidx':
					$op = null;
					/*if($data=='1'){
						$this->join['[><]pro_numidx(t_pn)'] = [
							'p.p_id'=>'pn_p_id',
							"AND" => 'pn_is_sys=0'
						];
					}else{
						$this->join['[>]pro_numidx(t_pn)'] = [
							'p.p_id'=>'pn_p_id',
							"AND" => 'pn_is_sys=0'
						];
						$this->joinWhere['t_pn.pn_is_sys'] = null;
					}*/
					if($data=='1'){
						$data = raw(" p_id in (select distinct pn_p_id from pro_numidx where pn_is_sys=0)");
					}else{
						$data = raw(" p_id not in (select distinct pn_p_id from pro_numidx where pn_is_sys=0)");
					}
					$op = 'RAW_'.$field;
                    break;
                case 'hasmodel':
					$op = null;
					/*if($data=='1'){
						$this->join['[><]pro_model_link(t_pml)'] = ['p.p_id'=>'pml_p_id'];
					}else{
						$this->join['[>]pro_model_link(t_pml)'] = ['p.p_id'=>'pml_p_id'];
						$this->joinWhere['t_pml.pml_p_id'] = null;
					}*/
					if($data=='1'){
						$data = raw(" p_id in (select distinct pml_p_id from pro_model_link)");
					}else{
						$data = raw(" p_id not in (select distinct pml_p_id from pro_model_link)");
					}
					$op = 'RAW_'.$field;
                    break;
			    case 'main_pic':
                    $field = 'p_pic';
                    $op = ($data==1) ? 'gt' : 'eq';
                    $data = 0;
                    break;
			    case 'p_lineimg':
                    $op = ($data==1) ? 'ni' : 'eq';
                    $data = '';
                    break;
			    case 'mk_name':
                    $op = '~';
                    $field = 'mk.mk_'.LG_NAME;
                    break;
			    case 'ms_name':
                    $op = '~';
                    $field = 'ms.ms_name';
                    break;
			    case 'mm_name':
                    $op = '~';
                    $field = 'mm.mm_name';
                    break;
                case 'g':
                    $rules['numbers'] = [$data];
                    $rules['numfac'] = 4;
                    $rules['numlike'] = ($op=='eq') ? 0 : 1;
                    $op = null;
                    break;
                case 'enertek':
                    $rules['numbers'] = [$data];
                    $rules['numfac'] = 6;
                    $rules['numlike'] = ($op=='eq') ? 0 : 1;
                    $op = null;
                    break;
                case 'barcode':
                case 'g_barcode':
                case 'enertek_barcode':
                    $rules['barcode'] = trim($data);
                    $op = null;
                    break;
			    case 'year':
			        if(strpos($data,'/')!==false){
			            list($year,$month) = explode('/',$data);
			        }else{
			            $year=$data;
			        }
                    $sql = qgprintf("(
                        CASE WHEN mm_year_from=0 THEN YEAR(NOW()) ELSE mm_year_from END <= '{1}' AND
                        CASE WHEN mm_year_to=0 THEN YEAR(NOW()) ELSE mm_year_from END >= '{1}'
                    )
                    ",$year);
                    if($month){
                        $sql .= qgprintf(" AND (
                            CASE WHEN mm_month_from=0 THEN MONTH(NOW()) ELSE mm_month_from END <= '{1}' AND
                            CASE WHEN mm_month_to=0 THEN MONTH(NOW()) ELSE mm_month_to END >= '{1}'
                        )
                        ",$month);
                    }
                    $this->joinWhere['RAW_whereRegi'.$whereRegi] = raw($sql);
                    $op = null;
                    break;
                case 'ckresult2':
                    $field = 'o.'.LG_NAME;
                    break;
				case 'main_update_time': //主图更新时间
				    //$data = raw("EXISTS (select 1 from pro_pic where ppic_type='beautify' and ppic_p_id = p.p_id and update_time='".$data."')");
				    //$op = 'RAW_'.$field.$op;
				    $field = 'pro_pic.update_time';
				    $op='ge';
					break;
				case 'ps_notcattle_state': //牛油包图待更新状态
				    if($data==0)
					    $othWhere['OR #ps_notcattle_state'] = ['ps_notcattle_state #1'=>0,'ps_notcattle_state #2'=>null];
				    else
					    $othWhere['ps_notcattle_state'] = 1;
					$op = null;
					break;
				case 'ps_beautify_state': //待更新状态
				    if($data==0)
					    $othWhere['OR #ps_beautify_state'] = ['ps_beautify_state #1'=>0,'ps_beautify_state #2'=>null];
				    else
					    $othWhere['ps_beautify_state'] = 1;
					break;
					$op = null;
				case 'ps_tecdoc_state': //待更新状态
				    if($data==0)
					    $othWhere['OR #ps_tecdoc_state'] = ['ps_beautify_state #1'=>0,'ps_tecdoc_state #2'=>null];
				    else
					    $othWhere['ps_tecdoc_state'] = 1;
					$op = null;
    				break;	
				case 'mmk_name':
					$op = '~';
					$field = 'mmk.mk_'.LG_NAME;
					break;
				case 'tb_names':
					$data = raw(sprintf(" p_id in (select distinct ptb_p_id from pro_tag_brand join tag_brand on ptb_tb_id=tb_id where tb_".LG_NAME." like '%s%%')",$data));
					$op = 'RAW_'.$field;
					break;
				default:
					//参数查询
					if(substr($field,0,strlen('param_')) == 'param_'){
						$ptpa_id = substr($field,strlen('param_'));
						$this->formartParamSearch2($ptpa_id, $op, $data, $this->join, $this->joinWhere);
						$op = null;
					}
					//图片列过滤
					if(substr($field,0,strlen('pic_')) == 'pic_'){
						$picRegI = substr($field,strlen('pic_'));
						if(!isset($rules['imageCount']) || $rules['imageCount'][0] < $picRegI){
						    $rules['imageCount'] = [$picRegI,$data];
						}
						$op = null;
					}
					break;
			}
        });//where
		if($where==null) $where = [];
		if(!empty($othWhere)){
		    $where = array_merge($where,$othWhere);
		}
		if(!empty($rules)){
		    if(!empty($rules['keys'])){
		        $where['p_id'] = $rules['keys'];
		    }
			//号码查询
			if(!empty($rules['numbers'])){
				if($rules['numfac']=='2'){ //外部编码
                    $this->join['[><]pro_numidx(pn)'] = ['p.p_id'=>'pn_p_id'];
                    $this->join['[>]pro_factory(pf)'] = ['pn.pn_pf_id'=>'pf_id'];
                    $where['pn.pn_is_sys'] = 1;
                    $where['pn.pn_pf_id'] = [2,4,5,6];
                    $where['pn_type'] = 'none';
                    if($rules['numlike']){//模糊
						foreach($rules['numbers'] as $nk=>$number){
							$sub = sprintf("pn.pn_formart like '%%%s%%'",$number);
							$andStr[] = $sub;
						}
						$where['RAW #numlike'] = raw('('.implode(' OR ',$andStr).')');
						$where['GROUP'] = 'p.p_id';
                    }else{
                        $where['pn.pn_formart'] = $rules['numbers'];
                    }
					$this->fields[] = 'pn.pn_number (pn_number)';
					$this->fields[] = 'pn.pn_type (pn_type)';
					$this->fields[] = 'pf.pf_name (pf_name)';
				}else if($rules['numfac']=='3'){ //内部编码
					$initNumbers = arryNums(\mvc::$req['numbers']);
					if($initNumbers){
						$where['p_innum'.($rules['numlike'] ?'[~]':'')] = $initNumbers;
					}
				}else{
					$andArr = [];
					$this->join['[><]pro_numidx(pn)'] = ['p.p_id'=>'pn_p_id'];
					if($rules['numfac']){
						if($rules['numfac']=='2'){
							$where['pn.pn_is_sys'] = 1;
							$where['pn.pn_pf_id'] = [2,4,5,6];
						}else{
							$where['pn.pn_pf_id'] = $rules['numfac'];
						}
					}
					if($rules['numlike']){//模糊
						foreach($rules['numbers'] as $nk=>$number){
							$sub = sprintf("pn.pn_formart like '%%%s%%'",$number);
							$andStr[] = $sub;
						}
						$where['RAW #numlike'] = raw('('.implode(' OR ',$andStr).')');
					}else{
						$where['pn_formart'] = $rules['numbers'];
					}
					/*foreach($rules['numbers'] as $nk=>$number){
						if(isset($rules['numfac']) && !empty($rules['numfac'])){
						    if($rules['numfac']=='2'){ //GSP旗下编码
    							$formart = ($rules['numlike']) ? "pn.pn_formart like '%%%s%%'" : "pn.pn_formart='%s'";
    							$sub = sprintf("(".$formart." AND pn.pn_is_sys=1 AND pn.pn_pf_id<>3)",$number);
						    }else{
    							$formart = ($rules['numlike']) ? "pn.pn_formart like '%%%s%%'" : "pn.pn_formart='%s'";
    							$sub = sprintf("(".$formart." AND pn.pn_pf_id='%s')",$number,$rules['numfac']);
						    }
						}else{
							$formart = ($rules['numlike']) ? "pn.pn_formart like '%%%s%%'" : "pn.pn_formart='%s'";
							$sub = sprintf($formart,$number);
						}
						$andStr[] = $sub;
					}*/
					$this->fields[] = 'pn.pn_id (pn_id)';
					$this->fields[] = 'pn.pn_is_sys (pn_is_sys)';
					$this->fields[] = 'pn.pn_pf_id (pn_pf_id)';
					$this->fields[] = 'pn.pn_number (pn_number)';
					$this->fields[] = 'pn.pn_type (pn_type)';
					$this->fields[] = 'pn.pn_barcode (pn_barcode)';
					$this->fields[] = 'o.'.LG_NAME.' (ckresult2)';
					$this->fields[] = 'pf.pf_name (pf_name)';
					/*$this->join['[><]pro_numidx(pn)'] = [
						'p.p_id'=>'pn_p_id',
						"AND" => '('.implode(' OR ',$andStr).')'
					];*/
				    $this->join['[>]pro_factory(pf)'] = ['pn.pn_pf_id'=>'pf_id'];
					$this->join['[>]object(o)'] = ['pn.ckresult2'=>'o_id'];
				    if(!$rules['modelsAll'] && !$rules['modelsRows'] && !is_null($rules['numfac'])){
    					$this->group['GROUP'] = 'p.p_id';
						$this->joinWhere['ORDER'] = ['pn_pf_id','pn_number'];
				    }
				}
			}

			//零件查询
			if(isset($rules['p_cate']) && !empty($rules['p_cate'])){
			    if(!is_array($rules['p_cate'])) $rules['p_cate'] = explode(',',$rules['p_cate']);
				$where['p_cate'] = $rules['p_cate'];
			}

			//条码查询
			if(isset($rules['barcode']) && !empty($rules['barcode'])){
				$where['RAW #barcode'] = raw(sprintf("EXISTS(SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id AND pn_barcode='%s' LIMIT 1)",$rules['barcode']));
			}
			
			//竞品
			if(isset($rules['sel_fac']) && !empty($rules['sel_fac']) && $rules['sel_fac']!='undefined'){
				$where['RAW #sel_fac'] = raw(sprintf("EXISTS(SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id AND pn_pf_id in(%s) LIMIT 1)",$rules['sel_fac']));
			}
			
			//竞品同品牌号码超过2个
			if(isset($rules['null_fac']) && !empty($rules['null_fac'])){
				$where['RAW #null_fac'] = raw(sprintf("EXISTS(SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id AND pn_pf_id='%s' GROUP BY pn_pf_id HAVING COUNT(1)>1 LIMIT 1)",$rules['null_fac']));
			}
            
			//区域查询
			if(isset($rules['area'])){
				if(!isset($this->join['[>]pro_model_link(pml)'])) 
				    $this->join['[>]pro_model_link(pml)'] = ['p.p_id'=>'pml_p_id'];
				if(!isset($this->join['[>]pro_model_area_link(pmal)'])) 
				    $this->join['[>]pro_model_area_link(pmal)'] = ['pml.pml_id'=>'pma_pml_id'];
				$this->joinWhere['pma_ma_id'] =  explode(',',$rules['area']);
				if(!$rules['modelsAll'] && !$rules['modelsRows']){
				    $this->group['GROUP'] = 'p.p_id';
				}
			}

			//版本查询
			if(isset($rules['ver'])){
				$this->join['[>]tags_link(tl)'] = [
					"p.p_id" => "tl_value_id",
					"AND" => "tl_type='pro'"
				];
				$this->joinWhere['RAW_ver-1'] = raw(sprintf("tl_t_id > tl_t_id ^ %d",$rules['ver']));
				if(!$rules['modelsAll'] && !$rules['modelsRows']){
				    $this->group['GROUP'] = 'p.p_id';
				}
			}

			//汽车品牌查询
			if(isset($rules['tagBrand'])){
				$this->join['[>]pro_tag_brand(ptb)'] = [
					"p.p_id" => "ptb_p_id"
				];
				$this->join['[><]tag_brand(tb)'] = [
					"ptb.ptb_tb_id" => "tb_id"
				];
				$this->fields[] = 'tb_'.LG_NAME.'(tb_name)';
				$this->joinWhere['ptb_tb_id'] = $rules['tagBrand'];
			}

			//车型查询
			if(isset($rules['models']) || isset($rules['modelsAll'])  || isset($rules['modelsRows']) || isset($rules['modelsOne'])){
				$rulesModels =  explode(',',$rules['models']);
			    $modelDisplayFields = explode(',',$rules['modelDisplayFields']);
				if(!isset($this->join['[>]pro_model_link(pml)'])) 
					$this->join['[>]pro_model_link(pml)'] = ['p.p_id'=>'pml_p_id'];
				
				$this->join['[>]m_model(mm)'] = ['pml.pml_mm_id'=>'mm_id'];
				$this->join['[>]m_series(ms)'] = ['mm.mm_ms_id'=>'ms_id'];
				$this->join['[>]m_make(mk)'] = ['mm.mm_mk_id'=>'mk_id'];
				$this->fields[] = 'mm.mm_id(mm_id)';
				$this->fields[] = 'mk.mk_'.LG_NAME.'(mk_name)';
				$this->fields[] = 'ms.ms_name(ms_name)';
				$this->fields[] = 'mm.mm_name(mm_name)';
				$this->fields[] = 'pml.*';
				$this->fields['year'] = raw("CONCAT(mm_year_from,'/',mm_month_from,'  ',mm_year_to,'/',mm_month_to)");
				if(!isset($rules['models']) && ($rules['modelsAll'] || $rules['modelsRows'])){
				    //全部车型
    				$this->joinWhere['ORDER'] = ['mk_name','ms_name','mm_name'];
				}else if(!isset($rules['models']) && $rules['modelsOne']){
				    //只取一条车型
    				$this->joinWhere['ORDER'] = ['mk_name','ms_name','mm_name'];
				    $this->group['GROUP'] = 'p.p_id';
				}else if(empty($rules['modelFields'])){
				    //性能模式
    				$this->joinWhere['pml_mm_id[=]'] = $rulesModels;
    				$this->joinWhere['ORDER'] = $modelDisplayFields;
				}else{
				    //自由模式
				    $modelFields = explode(',',$rules['modelFields']);
				    $modelFilterFields = array_merge([],$modelFields);
				    
				    foreach($modelFilterFields as $k=>$v){
				        if($v=='mk_name') array_push($modelFilterFields,'mm_mk_id');
				        if($v=='ms_name') array_push($modelFilterFields,'mm_ms_id');
				        if($v=='mm_name') array_push($modelFilterFields,'name');
				        if(in_array($v,['mm_id','mk_name','ms_name','mm_name'])){
				            unset($modelFilterFields[$k]);
				        }
				    }
				    $frows = $this->db->select('m_model','*',['mm_id'=>$rulesModels]);
				    foreach($frows as $fi => $frow){
				        $modelSubWhere = [];
				        foreach($frow as $fkey => $fval){
				            if(in_array($fkey,$modelFilterFields)){
				                if($fkey=='name'){
				                    $modelSubWhere['mm.mm_name'] = $fval;
				                }else{
				                    $modelSubWhere[$fkey] = $fval;
				                }
				            }
				        }
    				    $this->joinWhere['OR #modelWhere']['AND #modelSubWhere'.$fi] = $modelSubWhere;
				    }
				    
				    $this->joinWhere['ORDER'] = $modelFields;
				    foreach($modelDisplayFields as $k=>$v){
				        if($v=='mk_name') $v = 'mk.mk_'.LG_NAME;
				        if($v=='ms_name') $v = 'ms.ms_name';
				        if($v=='mm_name') $v = 'mm.mm_name';
				        $modelDisplayFields[$k] = $v;
				        if($v=='year'){
				            unset($modelDisplayFields[$k]);
				        }
				    }
				    
				    $this->group['GROUP'] = array_merge(['p_id'],$modelDisplayFields);
				}
				
				//车型显示列
			    foreach($modelDisplayFields as $v){
			        if(!in_array($v,['mm_id','mk_name','ms_name','mm_name','year'])){
			            $this->fields[] = $v;
			        }
			    }
			    
			}//END 车型查询

			//中国车型查询
			if(isset($rules['cnmodels']) || isset($rules['modelsAll'])  || isset($rules['modelsRows']) || isset($rules['modelsOne'])){
				$rulesModels =  explode(',',$rules['cnmodels']);
			    $cnmodelDisplayFields = explode(',',$rules['cnmodelDisplayFields']);
				if(!isset($this->join['[>]pro_model_cn_link(pmcl)'])) 
				    $this->join['[>]pro_model_cn_link(pmcl)'] = ['p.p_id'=>'pml_p_id'];
				$this->join['[>]m_cn_model(mcm)'] = ['pmcl.pml_mod3_id'=>'mod3_id'];
				$this->fields[] = 'mcm.*';
				if(!isset($rules['cnmodels']) && ($rules['modelsAll'] || $rules['modelsRows'])){
				    //全部车型
    				$this->joinWhere['ORDER'] = ['make_name','mod2_name','mod3_name'];
				}else if(!isset($rules['cnmodels']) && $rules['modelsOne']){
				    //只取一条车型
    				$this->joinWhere['ORDER'] = ['make_name','mod2_name','mod3_name'];
				    $this->group['GROUP'] = 'p.p_id';
				}else if(empty($rules['cnmodelFields'])){
				    //性能模式
    				$this->joinWhere['pml_mod3_id[=]'] = $rulesModels;
    				$this->joinWhere['ORDER'] = $modelDisplayFields;
				}else{
				    //自由模式
				    $cnmodelFields = explode(',',$rules['cnmodelFields']);
				    $cnmodelFilterFields = array_merge([],$cnmodelFields);
				    
				    $frows = $this->db->select('m_cn_model','*',['mod3_id'=>$rulesModels]);
				    foreach($frows as $fi => $frow){
				        $modelSubWhere = [];
				        foreach($frow as $fkey => $fval){
				            if(in_array($fkey,$cnmodelFilterFields)){
				                $modelSubWhere[$fkey] = $fval;
				            }
				        }
    				    $this->joinWhere['OR #modelWhere']['AND #modelSubWhere'.$fi] = $modelSubWhere;
				    }
				    
				    $this->joinWhere['ORDER'] = $modelFields;
				    foreach($cnmodelDisplayFields as $k=>$v){
				        $cnmodelDisplayFields[$k] = $v;
				    }
				    
				    $this->group['GROUP'] = array_merge(['p_id'],$cnmodelDisplayFields);
				}
				
				//车型显示列
			    foreach($cnmodelDisplayFields as $v){
			        $this->fields[] = $v;
			    }
			    
			}//END 中国车型查询
			    
			//参数
			$cid = 0;
			if($rules['p_cate'] && count($rules['p_cate'])==1){
			    $cid = $rules['p_cate'][0];
			    $hasParams = \p::params('1100',$cid);
			    if($hasParams) $hasParams = explode(',',$hasParams);
			    $paramList = $this->db->select('part_param',['ptpa_id','ptpa_type','ptpa_decimal'],['ptpa_cate_id'=>$cid,'ptpa_in_showlist'=>1]);
			    foreach($paramList as $param){
			        $ptpa_id = $param['ptpa_id'];
			        if($hasParams && !in_array($ptpa_id,$hasParams)){
			            continue;
			        }
			        $type = $this->paramType[$param['ptpa_type']];
			        $decimal = $param['ptpa_decimal'] ? $param['ptpa_decimal'] : 0;
            		$alias = "param_".$ptpa_id;
            		$ppv = $alias.'.ppv_val_'.$type;
            		$this->join["[>]pro_param_val(".$alias.")"] = [
            		    "p.p_id" => "ppv_p_id",
            		    "AND" => $alias.".ppv_ptpa_id=".$ptpa_id
            		];
            		if($type=='double' || (!empty($decimal))){
            		    $this->fields[$alias] = raw('ROUND('.$ppv.','.$decimal.')');
            		}else{
            		    $this->fields[] = $ppv.'('.$alias.')';
            		}
			    }
			}

			//零件查询
			if(isset($rules['proBrand']) && !empty($rules['proBrand'])){
			    if(!is_array($rules['proBrand'])) $rules['proBrand'] = explode(',',$rules['proBrand']);
				$where['p_pb_id'] = $rules['proBrand'];
			}
			
			//是否有交叉索引
			if(isset($rules['hasnumidx'])){
				$this->fields['hasnumidx'] = raw("(select 1 from pro_numidx where pn_is_sys=0 and pn_p_id = p.p_id limit 1)");
			}
			//是否车型
			if(isset($rules['hasmodel'])){
				$this->fields['hasmodel'] = raw("(select 1 from pro_model_link where pml_p_id = p.p_id limit 1)");
			}
			//显示合并型号
			if(isset($rules['hasmergeto'])){
				$this->fields['mergeto'] = raw("(select mpro.`p_comnum` from pro mpro where mpro.p_id = p.p_id limit 1)");
			}
			
			//是否有图片
			if(isset($rules['propictype']) && isset($rules['propictypeOption'])){
			    $this->listForImage2($rules);
			}else if(isset($rules['propictype'])){
			    $this->listForImage($rules);
			}

    		//库存
    		if(isset($rules['showstock'])){
    			//$row['stock'] = $this->db->get('pro_stock','ps_qty',['ps_outnum'=>$row['p_comnum']]);
    			$this->fields[] = 'ps_qty';
    			$this->join['[>]pro_stock'] = ['p.p_comnum'=>'ps_outnum'];
    		}

    		//审核时间
    		if(isset($rules['showcktime'])){
    			$this->fields[] = 'cktime3';
    		}
		
			
			//查非
			if(!empty($rules['findNulls'])){
			    $this->findNullsSearch($rules['findNulls'], $this->join, $this->joinWhere);
			}

		}//END rules

        //权限 - 小类
        $cates = \p::cates('1100');
        if(!\p::isAdmin() && $cates){
			$where['AND #rule_cate'] = ['p_cate'=>explode(',',$cates)];
        }
        
        //权限 - 商品品牌
        $proBrands = \p::areas('B100');
        if(!\p::isAdmin() && $proBrands){
			$where['AND #rule_brand'] = ['p_pb_id'=>explode(',',$proBrands)];
       	}

        //权限 - 版本
        $vers = \p::vers('1100');
        if(!\p::isAdmin() && $vers){
            if(!isset($this->join['[>]tags_link(tl)'])){
				$this->join['[>]tags_link(tl)'] = [
					"p.p_id" => "tl_value_id",
					"AND" => "tl_type='pro'"
				];
            }
            $arr = [];
            foreach(explode(',',$vers) as $k=>$ver){
				$arr[] = sprintf("tl_t_id > tl_t_id ^ %d",$ver);
            }
			$this->joinWhere['RAW_ver-2'] = raw(implode(' OR ',$arr));
       }
        
        
		if(!empty($this->joinWhere)){
			$where = array_merge($where, $this->joinWhere);
		}
		if(!empty($this->group)){
			$where = array_merge($where, $this->group);
		}
		switch($sidx){
			case 'p_bigcate':   $sidx = 'p_cate'; $where['ORDER']=null; break;
			case 'main_pic':    $sidx = 'p_pic'; $where['ORDER']=null; break;
			case 'year':        $sidx = 'mm_year_from '.$sord.',mm_month_from '.$sord.',mm_year_to '.$sord.',mm_month_to '.$sord; $where['ORDER']=null; break;
			case 'main_update_time': 
			    $sidx = 'main_update_time';
			    $where['ORDER']=null;
			    break;
		}
		
		if(substr($sidx,0,strlen('pml_'))=='pml_'){ //车型位置排序
		    $where['ORDER']=null;
			$sidx = 'pml.'.$sidx;
		}
		
        $where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
        if(isset($rules['getSQL']) && $rules['getSQL']){
            return $this->db->selectContextSql($table,$this->join,$this->fields,$where);
        }
        
		if($page>0 && $pagesize>0){
            if(empty($this->join)){
                $pages = $this->paging($table,$where,$page,$pagesize);
            }else{
                $pages = $this->paging($table,$this->join,'p.p_id',$where,$page,$pagesize);
            }
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
        if(empty($this->join)){
            $rows = $this->db->select($table,$this->fields,$where);
        }else{
            $rows = $this->db->select($table,$this->join,$this->fields,$where);
        }
        if(isset($rules['getDoneSQL']) && $rules['getDoneSQL']){
            return $this->db->last();
        }
        if(DEBUG && $cid!=0 && getOpuser()=='gsp.admin'){
		    //dd($this->db->last());
        }
        //dd($this->db->last(),count($rows));
        if(!empty($rows)) foreach($rows as $k=>&$row){
            $row = $this->formatRow($row,$rules);
        }
		
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $rows
		];
		return $data;
	} //list END
	
    /**查非
     * @return 
     */
    public function findNullsSearch($findNulls,&$join,&$where)
    {
        if(is_string($findNulls)) return;
        foreach($findNulls as $item){
            $name = $item['name'];
            $value = $item['value'];
            $op = $value ? ' EXISTS ' : ' NOT EXISTS ';
            switch($name){
                case 'null_param':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_param_val WHERE ppv_p_id = p.p_id  OR (p.p_lnk_p_id > 0 AND ppv_p_id = p.p_lnk_p_id) LIMIT 1)");
                    break;
                case 'null_cnmodel':
                    if($value) {
						// 存在中国车型
						$tsql = "EXISTS (SELECT 1 FROM pro_model_cn_link WHERE pml_p_id = p.p_id LIMIT 1)";
						
						$tsql .= " OR EXISTS (SELECT 1 FROM pro_model_cn_link WHERE pml_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					} else {
						// 不存在中国车型
						$tsql = "NOT EXISTS (SELECT 1 FROM pro_model_cn_link WHERE pml_p_id = p.p_id LIMIT 1)";
						
						$tsql .= " AND NOT EXISTS (SELECT 1 FROM pro_model_cn_link WHERE pml_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					}
                    break;
				case 'null_namodel':
					if($value) {
						// 存在北美车型（按商品对应零件ID判断，含关联主商品）
						$tsql = "EXISTS (SELECT 1 FROM oe_model_na WHERE oml_oe_id = p.p_oe_id LIMIT 1)";
						$tsql .= " OR EXISTS (
							SELECT 1
							FROM oe_model_na
							WHERE oml_oe_id = (SELECT p2.p_oe_id FROM pro p2 WHERE p2.p_id = p.p_lnk_p_id LIMIT 1)
							LIMIT 1
						)";
						$tsql = "($tsql)";
					} else {
						// 不存在北美车型（按商品对应零件ID判断，含关联主商品）
						$tsql = "NOT EXISTS (SELECT 1 FROM oe_model_na WHERE oml_oe_id = p.p_oe_id LIMIT 1)";
						$tsql .= " AND NOT EXISTS (
							SELECT 1
							FROM oe_model_na
							WHERE oml_oe_id = (SELECT p2.p_oe_id FROM pro p2 WHERE p2.p_id = p.p_lnk_p_id LIMIT 1)
							LIMIT 1
						)";
						$tsql = "($tsql)";
					}
					break;
				case 'null_model':
					if($value) {
						// 存在国际车型
						$tsql = "EXISTS (SELECT 1 FROM pro_model_link WHERE pml_p_id = p.p_id LIMIT 1)";
						
						$tsql .= " OR EXISTS (SELECT 1 FROM pro_model_link WHERE pml_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					} else {
						// 不存在国际车型
						$tsql = "NOT EXISTS (SELECT 1 FROM pro_model_link WHERE pml_p_id = p.p_id LIMIT 1)";
					
						$tsql .= " AND NOT EXISTS (SELECT 1 FROM pro_model_link WHERE pml_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					}
					break;
				case 'null_numidx':
					if($value) {
						// 存在号码索引
						$tsql = "EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id LIMIT 1)";
						
						$tsql .= " OR EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					} else {
						// 不存在号码索引
						$tsql = "NOT EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id LIMIT 1)";
						
						$tsql .= " AND NOT EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_lnk_p_id LIMIT 1)";
						
						$tsql = "($tsql)";
					}
					break;
				case 'null_oe':
					if($value) {
						// 存在OE号码 (pn_pf_id = 1)
						$tsql = "EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id and pn_pf_id = 1 LIMIT 1)";
						
						$tsql .= " OR EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_lnk_p_id and pn_pf_id = 1 LIMIT 1)";
						
						$tsql = "($tsql)";
					} else {
						// 不存在OE号码
						$tsql = "NOT EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_id and pn_pf_id = 1 LIMIT 1)";
						
						$tsql .= " AND NOT EXISTS (SELECT 1 FROM pro_numidx WHERE pn_p_id = p.p_lnk_p_id and pn_pf_id = 1 LIMIT 1)";
						
						$tsql = "($tsql)";
					}
					break;
				case 'null_name':
					$tsqlArr = [];
					foreach(\mvc::$cfg['LANGS'] as $lk=>$lv){
						if($value){
							$tsqlArr[] = " p_{$lv['field']} != ''";
						}else{
							$tsqlArr[] = " p_{$lv['field']} = ''";
						}
					}
					$tsql = $value? '('.implode(" and ",$tsqlArr).')': " (".implode(" or ",$tsqlArr).")";
					break;
				case 'null_img':
					$tsql = $op.sprintf("(SELECT 1 FROM pro_pic WHERE pic_p_id = p.p_id and pic_type = 'img' LIMIT 1)");
					break;
				case 'null_line':
					$tsql = $op.sprintf("(SELECT 1 FROM pro_pic WHERE pic_p_id = p.p_id and pic_type = 'line' LIMIT 1)");
					break;
				case 'null_other':
					$tsql = $op.sprintf("(SELECT 1 FROM pro_pic WHERE pic_p_id = p.p_id and pic_type = 'other' LIMIT 1)");
					break;
				case 'null_pair':
					if($value) {
						// 存在配对关系
						$tsql = "EXISTS (SELECT 1 FROM oe_link WHERE ol_type='pair' and p.p_oe_id = ol_oe_id1 and ol_oe_id2>0 LIMIT 1)";
						$tsql = "($tsql)";
					} else {
						// 不存在配对关系
						$tsql = "NOT EXISTS (SELECT 1 FROM oe_link WHERE ol_type='pair' and p.p_oe_id = ol_oe_id1 and ol_oe_id2>0 LIMIT 1)";
						$tsql = "($tsql)";
					}
					break;
				case 'null_pro':
					if($value=='one'){
						$tsql = sprintf("p.p_oe_id in (SELECT oe_id FROM oe_item JOIN pro ON oe_id = p_oe_id AND p_pb_id=1 GROUP BY oe_id HAVING COUNT(p_id) =1)");
					}elseif ($value=='any') {
						$tsql = sprintf("p.p_oe_id in (SELECT oe_id FROM oe_item JOIN pro ON oe_id = p_oe_id AND p_pb_id=1 GROUP BY oe_id HAVING COUNT(p_id) > 1)");
					}
					break;
			
            }
            $where['RAW #'.$name] = raw($tsql);
        }
    }


    /**list For Image
     * @return 
     */
    public function listForImage($rules)
    {
        $tsql = '';
        switch($rules['propictype']){
            case 'init_add':
                $cates = \p::cates('D311');
                if(!\p::isAdmin() && $cates){
        			$this->joinWhere['AND #init_add_cate'] = ['p_cate'=>explode(',',$cates)];
                }
	            //上传原始照片 清单未提交+上传原始照片有未审核+原始图退回
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic_task WHERE ppt_p_id=p.p_id and ppt_submit_time IS NULL limit 1)
			        OR
			        exists (SELECT 1 FROM pro_pic WHERE pic_style in('init_add','init_back','init_replay') AND pic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'init_del':
	            //删除
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE pic_style='init_del' AND pic_p_id=p.p_id limit 1))";
                break;
            case 'init_back':
	            //退回+重拍
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic WHERE pic_style in ('init_back','init_replay') AND pic_p_id=p.p_id limit 1))";
                break;
            case 'init_check':
	            //原始图审核 只要有一张没有审就显示
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic WHERE pic_style='init_add' AND pic_status=0 AND pic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'designer':
	            //设计师, 已审核但没有精修图,并且没有不入精修图标识
	            $this->join['[>]pro_pic(picI)'] = ['p.p_id'=>'pic_p_id', "RAWpic_isbeautify" => "@picI.pic_isbeautify = '1'",];
	            $this->joinWhere['picI.pic_style'] = 'init';
	            $this->joinWhere['picI.pic_status'] = 1;
	            $this->joinWhere['picI.pic_isbeautify'] =1;
	            //如果不存在精修图有同名的
			    $tsql = "not exists (SELECT 1 FROM pro_pic WHERE pic_style in ('beautify_add','beautify') AND pic_p_id=p.p_id AND pic_filebase = picI.pic_filebase limit 1)";
			    if($rules['checkOption']=='1'){
    			    $this->joinWhere['picI.pic_desexport_time[!]'] = null; //已导出
			    }else if($rules['checkOption']=='-1'){
    			    $this->joinWhere['picI.pic_desexport_time'] = null; //未导出
			    }
			    $this->group['GROUP'] = 'p.p_id';
                break;
            case 'init':
	            //原始图
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE pic_style='init' AND pic_p_id=p.p_id limit 1))";
                break;
            case 'beautify_add':
	            //上传精修海报, 已审核但没有精修图
	            $this->join['[>]pro_pic(picI)'] = ['p.p_id'=>'pic_p_id'];
				$this->joinWhere['OR #picI.pic_style'] = [
					'AND #picI.ppic_type_1'=>[
						'picI.pic_style'=>'init',
						'pic_status'=>1
					],
					'AND #picI.ppic_type_2'=>[
						'picI.pic_style'=>'beautify_back'
					],
				];

	            $this->joinWhere['picI.pic_isbeautify'] = 1;
	            //如果不存在精修图有同名并审核的
			    $tsql = "(
					not exists (SELECT 1 FROM pro_pic WHERE pic_style in ('beautify') AND pic_p_id=p.p_id AND pic_filebase = picI.pic_filebase limit 1)
					OR
			        exists (SELECT 1 FROM pro_pic WHERE pic_style in('beautify_add','beautify_back','beautify_replay') AND pic_p_id=p.p_id limit 1)
				)";
			    $this->group['GROUP'] = 'p.p_id';
                break;
            case 'beautify_check':
	            //审精修海报 只要有一张没有审就显示
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic WHERE pic_style='beautify_add' and pic_status=0 AND pic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'beautify_back':
	            //精修图 退回
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE pic_style in('beautify_back','beautify_replay') AND pic_p_id=p.p_id limit 1))";
                break;
            case 'beautify':
	            //精修图
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE pic_style='beautify' AND pic_p_id=p.p_id limit 1))";
                break;
        }
	    if($tsql!=''){ 
	        $this->joinWhere['RAW #image'] = raw($tsql);
	    }
	   
	   
	    if($rules['propictype']=='init'){
	        $this->join['[>]pro_pic'] = [
	            "p.p_id" => "pic_p_id",
	            "RAWppic_type" => "@pro_pic.pic_style = 'beautify'",
	         ];
	
	    }
	    
	    if($rules['propictype']=='beautify'){
	      
	        $this->join['[>]pro_pic'] = [
	            "p.p_id" => "pic_p_id",
	            "RAWppic_type" => "@pro_pic.pic_style = 'beautify'",
	            
	         ];
	        $this->fields[] = "pro_pic.update_time(main_update_time)";
	    }
		
	    //图片列过滤
	    if(isset($rules['imageCount'])){
	        list($count,$has) = $rules['imageCount'];
	        $count = $count + 1;
			$sswhere = '';
			if($rules['propictype']=='video')
			{
				$sswhere = sprintf("pic_type='%s'",$rules['propictype']);
			}else{
				$sswhere = sprintf("pic_style='%s'",$rules['propictype']);
			}
			if($has){
				$sql = sprintf(" EXISTS (SELECT COUNT(1) total FROM pro_pic  WHERE pic_p_id = p.p_id AND %s HAVING total>=%d)",$sswhere,$count);
			}else{
				$sql = sprintf(" EXISTS (SELECT COUNT(1) total FROM pro_pic  WHERE pic_p_id = p.p_id AND %s HAVING total<%d)",$sswhere,$count);
			}
	        
	        $this->joinWhere['RAW #imageCount'] = raw($sql);
	    }
        $this->joinWhere['GROUP'] = 'p_id';
    }

	public function getPicType($fileid)
	{
		$trow = $this->db->get('pro_pic', ['ppic_type'], ['ppic_fileid'=>$fileid]);
		return $trow['ppic_type'];
	}


    /**修正要显示的数据
     * @param int|array $row
     * @return array
     */
    public function formatRow($row,$rules=null){
        if(!is_array($row)){
            $row = $this->getRowByKey($row);
        }
		//图片
		if(!empty($row['p_pic'])){
			$row['main_pic'] = \mvc::$cfg['path']['files'].'/pro/catalog_gsp/'.($row['p_id'] % 100).'/'.$row['p_id'].'big.jpg';
		}else{
			$row['main_pic'] = '';
		}

		if(!empty($row['p_lnk_p_id'])){
			$row['lnk_pro'] = $this->db->get('pro','*',['p_id'=>$row['p_lnk_p_id']]);
		}

		//查关联汽车品牌（品牌标签）
		$tbres = $this->db->get('pro_tag_brand(ptb)',['[><]tag_brand(tb)'=>['ptb.ptb_tb_id'=>'tb_id']],['tb_names'=>raw('GROUP_CONCAT(tb_'.LG_NAME.' ORDER BY CONVERT(tb_'.LG_NAME.' USING gbk))')],['ptb_p_id'=>$row['p_id']]);
		$row['tb_names'] = $tbres['tb_names']?:'';
		//产品线与小类
        if(!empty($row['p_cate'])){
			if(empty($this->formatRowCache['cate'][$row['p_cate']])){
				 $cateRow = $this->cate->getRowByKey($row['p_cate']);
				 $this->formatRowCache['cate'][$row['p_cate']] = $cateRow;
			}else{
				 $cateRow = $this->formatRowCache['cate'][$row['p_cate']];
			}

			if(empty($this->formatRowCache['cate'][$cateRow['parent_id']])){
				 $bigCateRow = $this->cate->getRowByKey($cateRow['parent_id']);
				 $this->formatRowCache['cate'][$cateRow['parent_id']] = $bigCateRow;
			}else{
				 $bigCateRow = $this->formatRowCache['cate'][$cateRow['parent_id']];
			}
            $row['captions']['p_bigcate'] = $bigCateRow[cateName()];
            $row['captions']['p_cate'] = $cateRow[cateName()];
            $row['captions']['p_cateas'] = $cateRow['as'];
            $row['langs']['p_cate']['en'] = $cateRow['en_name'];
            $row['langs']['p_cate']['cn'] = $cateRow['cn_name'];
			$row['langs']['p_cate']['py'] = $cateRow['py_name'];
            $row['langs']['p_bigcate']['en'] = $bigCateRow['en_name'];
            $row['langs']['p_bigcate']['cn'] = $bigCateRow['cn_name'];
			$row['langs']['p_bigcate']['py'] = $bigCateRow['py_name'];
        }

		if(!empty($row['pf_alias'])){
			$row['pf_name'] = $row['pf_alias'];
		}
		//燃油方式
		if(isset($row['mm_fuel']) && $row['mm_fuel']!=''){
			$row['mm_fuel'] = (new \model\collocation())->getRowByKey($row['mm_fuel'])[cateName()];
		}
		//Aspiration增压方式
		if(isset($row['mm_turbo']) && $row['mm_turbo']!=''){
			$row['mm_turbo'] = (new \model\collocation())->getRowByKey($row['mm_turbo'])[cateName()];
		}
		//Cyl发动机汽缸排列方式
		if(isset($row['mm_cylinders']) && $row['mm_cylinders']!=''){
			$row['mm_cylinders'] = (new \model\collocation())->getRowByKey($row['mm_cylinders'])[cateName()];
		}
		//Drive驱动方式
		if(isset($row['mm_drive_type']) && $row['mm_drive_type']!=''){
			$row['mm_drive_type'] = (new \model\collocation())->getRowByKey($row['mm_drive_type'])[cateName()];
		}
		$row['cktime3'] = shortDate($row['cktime3']);
		$row['create_time'] = shortDate($row['create_time']);
		$row['update_time'] = shortDate($row['update_time']);
		$tag = $this->tags->getOneTag('pro',$row['p_id']);
		$row['link_tags'] = implode(',',explodeXor($tag));
		
		//年月
 		if(!empty($row['year'])){
			//$row['year'] = str_replace('0/0','-',$row['year']);
			$row['year'] = str_replace('/0','-',$row['year']);
			$row['year'] = str_replace(' 0-','',$row['year']);
			if($row['year']=='0- ') $row['year']='';
		}
		
		//G 和 ENERTEK 品牌号
		if(!empty($rules['band_g']) || !empty($rules['band_enertek']) || !empty($rules['band_g_barcode'])  || !empty($rules['band_barcode']) || !empty($rules['band_enertek_barcode'])){
           $gspbandRows = $this->db->select('pro_numidx',['pn_pf_id'=>['pn_number','pn_barcode']],[
               'pn_p_id'=>$row['p_id'],'pn_pf_id'=>[2,4,6],
               'pn_ma_id'=>0,
               'ORDER'=>['pn_barcode'=>'ASC']
            ]);
           if(isset($gspbandRows[2])){
              $row['barcode'] = $gspbandRows[2]['pn_barcode'];
           }
           if(isset($gspbandRows[4])){
              $row['g'] = $gspbandRows[4]['pn_number'];
              $row['g_barcode'] = $gspbandRows[4]['pn_barcode'];
           }
           if(isset($gspbandRows[6])){
              $row['enertek'] = $gspbandRows[6]['pn_number'];
              $row['enertek_barcode'] = $gspbandRows[6]['pn_barcode'];
           }
		}
		if(isset($rules['models']) && !empty($rules['models'])){
			$row['p_id'] = sprintf("%d-m%d",$row['p_id'],$row['mm_id']);
		}
		//参数翻译
		foreach($row as $field => $value){
	        $row[$field] = $this->getParamLangText(substr($field,6),$value);
		}
		
		$row['captions']['p_state_main']=\mvc::$cfg['PROSTATUS'][$row['p_state_main']]? \mvc::$cfg['PROSTATUS'][$row['p_state_main']]: '';
		
        return $row;
    }
    
    /**参数翻译
     */
    public function getParamLangText($paramId,$value){
        $result = $value;
        if(LANG!='zh_cn' && $value!='' && !is_numeric($value)){
            if(!isset($this->paramStrenvalKeyValues[$paramId])){
                $arr = $this->db->select('pro_param_strenval',['ppsl_cn_name','ppsl_en_name'],['ppsl_ptpa_id'=>$paramId]);
                if(!empty($arr)){
                    $arr = array_column($arr,'ppsl_en_name','ppsl_cn_name');
                }
                $this->paramStrenvalKeyValues[$paramId] = $arr;
            }
            if(!empty($this->paramStrenvalKeyValues[$paramId]) && !empty($this->paramStrenvalKeyValues[$paramId][$value])){
                $result = $this->paramStrenvalKeyValues[$paramId][$value];
            }
        }
        return $result;
    }
  

    /**
     * 修正要保存的数据
     * @param array $data
     * @return array
     */
    function formartSaveData($data){
        $saveData = $data;
        return $saveData;
    }

    /**
     * 格式化参数查询
     * @param int $ptpa_id 参数ID
     * @param string $op 操作符
     * @param var $data 查询值
     * @param array $join 一般为 $this->join
     * @param array $where 一般为 $this->where
     * @return void
     */
    function formartParamSearch($ptpa_id,$op, $data,&$join,&$where){
        $data = trim($data);
		$paramCfg = $this->paramset->getRowByKey($ptpa_id);
		$type = $this->paramType[$paramCfg['ptpa_type']];
		$alias = "param_".$ptpa_id;
		$ppv = $alias.'.ppv_val_'.$type;
		$join["[>]pro_param_val(".$alias.")"] = [
		    "p.p_id" => "ppv_p_id",
		    "AND" => $alias.".ppv_ptpa_id=".$ptpa_id
		];
		//$where[$alias.".ppv_ptpa_id"] = $ptpa_id;
		if($op=='bt' && in_array($type,['int','double','string'])){
			//区间
			if(strpos($data,'-')>0){
				$arr = explode('-',$data);
				$arr[0] = trim($arr[0]);
				if(is_numeric($arr[0])){
					$where[$ppv."[>=]"] = trim($arr[0]);
				}else{
					$where[$ppv."[>]"] = -65535;
				}
				if(isset($arr[1]) && is_numeric(trim($arr[1])) ){
					$where[$ppv."[<=]"] = trim($arr[1]);
				}
			//多值
			}else if(strpos($data,',')>0){
				$arr = explode(',',$data);
				$vArr = [];
				foreach($arr as $v){
					$v = trim($v);
					if(is_numeric($v)) $vArr[] = $v;
				}
				if(!empty($vArr))
					$where[$ppv."[=]"] = $vArr;
				else
					$where[$ppv."[>]"] = -65535;
			}else{
				$where[$ppv."[=]"] = $data;
			}
		}else if($op=='bw'){
			$where[$ppv."[~]"] = $data;
		}else if($op=='nu'){
			$where[$ppv."[>]"] = '0';
		}else if($op=='nn'){
			$where["OR #".$ppv] = [
			    $ppv=>[0,'0',''],
			    $ppv.'[=]'=>null,
			];
		}else{
			$where[$ppv."[".$this->getMedooOp($op)."]"] = $data;
		}
	}


    /**
     * 格式化参数查询2 PRO已有 JOIN
     * @param int $ptpa_id 参数ID
     * @param string $op 操作符
     * @param var $data 查询值
     * @param array $join 一般为 $this->join
     * @param array $where 一般为 $this->where
     * @return void
     */
    function formartParamSearch2($ptpa_id,$op, $data,&$join,&$where){
        $data = trim($data);
		$paramCfg = $this->paramset->getRowByKey($ptpa_id);
		$type = $this->paramType[$paramCfg['ptpa_type']];
		$alias = "param_".$ptpa_id;
		$ppv = $alias.'.ppv_val_'.$type;
		if($op=='bt' && in_array($type,['int','double','string'])){
			//区间
			if(strpos($data,'-')>0){
				$arr = explode('-',$data);
				$arr[0] = trim($arr[0]);
				if(is_numeric($arr[0])){
					$where[$ppv."[>=]"] = raw("CONCAT('',".trim($arr[0]).")");
				}else{
					$where[$ppv."[>]"] = -65535;
				}
				if(isset($arr[1]) && is_numeric(trim($arr[1])) ){
					$where[$ppv."[<=]"] = raw("CONCAT('',".trim($arr[1]).")");
				}
			//多值
			}else if(strpos($data,',')>0){
				$arr = explode(',',$data);
				$vArr = [];
				foreach($arr as $v){
					$v = trim($v);
					if(is_numeric($v)) $vArr[] = $v;
				}
				if(!empty($vArr))
					$where[$ppv."[=]"] = $vArr;
				else
					$where[$ppv."[>]"] = -65535;
			}else{
				$where[$ppv."[=]"] = $data;
			}
		}else if($op=='bw'){
			$where[$ppv."[~]"] = $data;
		}else if($op=='nu'){
			$where[$ppv."[>]"] = '0';
		}else if($op=='nn'){
			$where["OR #".$ppv] = [
			    $ppv=>[0,'0',''],
			    $ppv.'[=]'=>null,
			];
		}else{
			$where[$ppv."[".$this->getMedooOp($op)."]"] = $data;
		}
	}

    /**
     * 通过产品ID 获取小类
     * @param array|int $p_id 产品id 或者是产品记录
     * @return array
     */
    function getCate($var){
		$row = $var;
		if(!is_array($row)){
			$row = $this->getRowByKey($var);
		}
		$cateRow = $this->cate->lrtree->getNode($row['p_cate']);
        return $cateRow;
    }

    /**
     * 通过产品ID 获取产品线
     * @param array|int $p_id 产品id 或者是产品记录
     * @return array
     */
    function getBigCate($var){
		$row = $var;
		if(!is_array($row)){
			$row = $this->getRowByKey($var);
		}
		$cateRow = $this->cate->lrtree->getParent($row['p_cate']);
		if(!empty($cateRow))
			$cateRow = $cateRow[0];
		else
			$cateRow = [];
        return $cateRow;
    }
	
	//仅获取主品牌物料编码的产品ID
	public function getLinkPidByInnum($innum){
		return $this->db->get('pro','p_id',['p_innum_format'=>formatNum($innum), 'p_pb_id'=>1]);
	}

	//获取物料编码的产品ID
    public function getPidByNumber($innum)
    {
		return $this->db->get('pro','p_id',['p_innum_format'=>formatNum($innum)]);
    }

    public function getNumberAndBrandByPid($filed,$value,$brand)
    {
		if($filed=='p_comnum'){
			$filed = 'p_comnum_format';
			$value = formatNum($value);
		}
        return $this->db->get($this->table,'p_id',[$filed => $value]);
    }

  

    /**
     * 添加一条记录
     * @param array $data 字段与值数组
     * @return bool
     */
	function baseAdd($data,$link_tags){
        $this->db->Begin();
        $saveData = $this->formartSaveData($data);
        $this->db->insert($this->table,$saveData);
        $key = $this->db->id();
        $this->tags->setOneToTags('pro', $key, $link_tags);
        $this->db->End();
        return ['key'=>$key,'op'=>'add'];
    }

	/**
	 * @param  [type] $pid 主键ID
	 * @param  [type] $data 数组
	 * @method 保存编码相关的字段
	 * @author zhengweihua 
	 * @copyright 2024-11-26
	 */
	function saveCodeBase($pid,$data)
	{
		$pro = $this->db->get('pro','*',['p_id'=>$pid]);
		if(empty($pro))  exitJson('产品不存在');

		$oldArr = $this->getDetail($pid);

		$oldArr['pn_main_formart'] = $this->getProMainOe($pid);

		$this->db->Begin();

		$codeArr = [];
		$extArr = [];
		$pnumArr = [];
		$paramArr = [];
		$posArr = [];
		foreach($data as $field=>$val){
			if(stripos($field, 'p_') === 0){
				if(stripos($field, 'pos')!==false && is_array($data[$field]))
				{
					$data[$field] = implode('/',$data[$field]);
					$posArr[$field] =$data[$field];
				} 
				$codeArr[$field] = $data[$field];
			}
			if(stripos($field, 'pe_') === 0){
				$extArr[$field] = $data[$field];
			}
			if(stripos($field, 'pn_') === 0){
				$pnumArr[$field] = $data[$field];
			}
			if(stripos($field,'para') === 0){
				$paramArr[$field] = $data[$field];
			}
		}
		if(!empty($codeArr)){
			$opuser = getOpuser();
			$datetime = getNowTime();
			$codeArr['p_opuser'] = $opuser;
			$codeArr['p_update_time'] = $datetime;

			$this->db->update('pro', $codeArr, ['p_id'=>$pid]);

			if($posArr && !$pro['p_lnk_p_id']){
				$this->db->update('pro', $posArr, ['p_lnk_p_id'=>$pid]);
			}
		}

		if(!empty($extArr)){
			$opuser = getOpuser();
			$datetime = getNowTime();
			$extArr['pe_opuser'] = $opuser;
			$extArr['pe_update_time'] = $datetime;
			$this->db->update('pro_ext', $extArr, ['pe_p_id'=>$pid]);
		}

		if(!empty($paramArr)){
			$paramArr = json_decode($paramArr['para'],true);
			$paramModel = new param();
			$paramModel->setParam($paramArr,$pid);
		}

		if(!empty($pnumArr['pn_main_formart'])){

			$this->db->update('pro_numidx',['pn_ismain'=>0],['pn_pf_id'=>1,'pn_p_id'=>$pid]);

			$pn_id = $this->db->get('pro_numidx',['pn_id'],['pn_pf_id'=>1,'pn_formart'=>$pnumArr['pn_main_formart'],'pn_p_id'=>$pid]);	
			if(!$pn_id){
				$tempnum = $this->db->get('pro_numidx',["[><]pro" => ["pn_p_id"=>"p_id"]],['pro_numidx.*'],['pn_pf_id'=>1,'pn_p_id'=>$pro['p_lnk_p_id'],'pn_formart'=>$pnumArr['pn_main_formart']]);
				unset($tempnum['pn_id']);
				$tempnum['pn_p_id'] = $pid;
				$tempnum['pn_ismain'] = 1;
				$this->db->insert('pro_numidx',$tempnum);
			}else{
				
				$this->db->update('pro_numidx',['pn_ismain'=>1],['pn_id'=>$pn_id]);
			}
		}

		$devArr = $data['devNo']?json_decode($data['devNo'],true):[];
		$this->saveDevelopNo($pid,$devArr);

		//日志
		$changeArr = [];
		//获取新的
		$newArr = $this->getDetail($pid);
		
		foreach ($this->codeFields as $field => $name) 
		{
			if(isset($oldArr[$field]) && isset($data[$field]) && trim($oldArr[$field]) != trim($data[$field]))
			{
				$changeArr[] = ['field'=>$field,'name'=>$name,'old'=>$oldArr['captions'][$field]??$oldArr[$field], 'new'=>$newArr['captions'][$field]??$newArr[$field]];
			}
		}
		if(!empty($changeArr))
		{
			$log = [
				'cl_type'=>'pro',
				'cl_act'=>'edit',
				'cl_dataid'=>$pid,
				'cl_change'=>json_encode(['code'=>$changeArr], JSON_UNESCAPED_UNICODE),
				'cl_opuser'=>getOpuser(),
				'cl_create_time'=>getNowTime(),
			];
			$this->db->insert('change_log', $log);
		}
		$this->addProSynLog([$pid], 'set', 'text');
		$this->db->End();
		return ['key'=>$pid];
	}

    /**
     * 修改记录
     * @param int $key 主键值
     * @param array $data 字段与值数组
     * @return bool
     */
	function baseEdit($key,$data,$link_tags){
        $this->db->Begin();
        $saveData = $this->formartSaveData($data);
        $this->db->update($this->table,$saveData,[$this->key=>$key]);
        $this->tags->setOneToTags('pro', $key, $link_tags);
        $this->db->End();
        return ['key'=>$key,'op'=>'edit'];
    }

	/**
     * 取父零件
     * @param int $p_id
     * @return array
     */
	function getFather($p_id){
		$join = [
			"[>]pro" => ["pf_father_pid" => "p_id"],
			"[>]pro_cate" => ["pro.p_cate" => "id"]
		];
		$fields = [
			'pf_id',
			'p_id(pid)',
			'p_innum(innum)',
			'p_comnum(outnum)',
			'pro_cate.en_name(en_name)',
			'pro_cate.cn_name(cn_name)',
		];
		$where = [
			'pf_son_pid' => $p_id,
		];
        $rows = $this->db->select('pro_fatherson',$join,$fields,$where);
		if(!empty($rows)){
			foreach($rows as &$row){
				$row['name'] = $row[LG_NAME];
			}
		}
		return $rows;
    }
	/**
     * 是否存在某父零件
     * @param int $p_id
     * @return array
     */
	function hasFather($p_id,$father_pid){
		return $this->db->has('pro_fatherson',['pf_father_pid'=>$father_pid,'pf_son_pid'=>$p_id]);
	}

	/**
     * 取子零件
     * @param int $p_id
     * @return array
     */
	function getSon($p_id){
		$join = [
			"[>]pro" => ["pf_son_pid" => "p_id"],
			"[>]pro_cate" => ["pro.p_cate" => "id"]
		];
		$fields = [
			'pf_id',
			'p_id(pid)',
			'p_innum(innum)',
			'p_comnum(outnum)',
			'pro_cate.en_name(en_name)',
			'pro_cate.cn_name(cn_name)',
		];
		$where = [
			'pf_father_pid' => $p_id,
		];
        $rows = $this->db->select('pro_fatherson',$join,$fields,$where);
		if(!empty($rows)){
			foreach($rows as &$row){
				$row['name'] = $row[LG_NAME];
			}
		}
		return $rows;
    }
	/**
     * 是否存在某子零件
     * @param int $p_id
     * @return array
     */
	function hasSon($p_id,$son_pid){
		return $this->db->has('pro_fatherson',['pf_father_pid'=>$p_id,'pf_son_pid'=>$son_pid]);
	}

    /**
     * 添加父子零件
     * @param int $p_id
     * @param int $son_p_id
     * @return array
     */
	function addFatherSon($data){
        if(!$this->db->has('pro_fatherson',$data)){
			$this->db->begin();
				$this->db->insert('pro_fatherson',$data);
				$this->addLinkToNumidx($data['pf_father_pid'],$data['pf_son_pid'],'fatherson',$this->db->id());
			$this->db->end();
		}
		return true;
    }

    /**
     * 删除子零件
     * @param int $p_id
     * @param array|string $ids
     * @return array
     */
	function deleteSon($p_id,$ids){
		if(!is_array($ids)) $ids = explode(',',$ids);
		$this->db->begin();
        $this->db->delete('pro_fatherson',['pf_id'=>$ids]);
		$this->deleteLinkFromNumidx('fatherson',$ids);
		$this->db->end();
		return true;
    }
	/**
     * 从交叉索引表中删除号码关系
     * @param int $p_id
     * @return array
     */
	function deleteLinkFromNumidx($type,$ids){
		if(!is_array($ids)) $ids = explode(',',$ids);
		$where['pn_type_id'] = $ids;
		if($type=='fatherson'){
			$where['pn_type'] = ['father','son'];
		}else{
			$where['pn_type'] = $type;
		}
		$this->db->begin();
        $this->db->delete('pro_numidx',$where);
		$this->db->end();
	}

	/**
     * 号码关系存入交叉索引表
     * @return
     */
	function addLinkToNumidx($pid1,$pid2,$type,$type_id){
		$item1 = $this->getRowByKey($pid1);
		$item2 = $this->getRowByKey($pid2);
		if(!empty($item1) && !empty($item2) && !empty($type_id)){
			$fid = GSP_BRANDS['OUTNUM']['id'];
			$type1 = $type;
			$type2 = $type;
			if($type=='fatherson'){
				$type1 = 'son';
				$type2 = 'father';
			}
			$data = [
				[
					'pn_p_id'=> $pid1,
					'pn_is_sys'=>1,
					'pn_pf_id'=>$fid,
					'pn_number'=>$item2['p_comnum'],
					'pn_formart'=>formatNum($item2['p_comnum']),
					'pn_type'=>$type1,
					'pn_type_id'=>$type_id,
				],
				[
					'pn_p_id'=> $pid2,
					'pn_is_sys'=>1,
					'pn_pf_id'=>$fid,
					'pn_number'=>$item1['p_comnum'],
					'pn_formart'=>formatNum($item1['p_comnum']),
					'pn_type'=>$type2,
					'pn_type_id'=>$type_id,
				],
			];
			$this->db->replace('pro_numidx',$data, ['pn_p_id','pn_type','pn_type_id']);
		}
	}

	/**
	  * @method 根据号码查询查询对应的产品ID 优先级：内部编码》集团编码》第三方编码
	  * @param  $params array [必填] ['innum'=>'', 'outnum'=>'', 'pf_id'=>'', 'number'=>'','mk_id'=>'']
	  * @author soul
	  */
	public function chkProIdByAny($params)
	{
		$pidArr = [];
		if(empty($pidArr) && !empty($params['innum']))
		{
			$rows = $this->db->select('pro_numidx', ['pn_p_id'], ['pn_type'=>'none','pn_pf_id'=>3, 'pn_formart'=>formatNum($params['innum'])]);
			if(!empty($rows)) $pidArr = array_column($rows, 'pn_p_id');
		}
		if(empty($pidArr) && !empty($params['outnum']))
		{
			$rows = $this->db->select('pro_numidx', ['pn_p_id'], ['pn_type'=>'none','pn_pf_id'=>[2,5], 'pn_formart'=>formatNum($params['outnum'])]);
			if(!empty($rows)) $pidArr = array_column($rows, 'pn_p_id');
		}

		//第三方号码 有OEmake
		if(empty($pidArr) && !empty($params['pf_id']) && !empty($params['number']) && !empty($params['mk_id']))
		{
			$rows = $this->db->select('pro_numidx', ['pn_p_id'], ['pn_type'=>'none','pn_pf_id'=>$params['pf_id'], 'pn_formart'=>formatNum($params['number']), 'pn_mk_id'=>formatNum($params['mk_id'])]);
			if(!empty($rows)) $pidArr = array_column($rows, 'pn_p_id');
		}

		//第三方号码
		if(empty($pidArr) && !empty($params['pf_id']) && !empty($params['number']))
		{
			$rows = $this->db->select('pro_numidx', ['pn_p_id'], ['pn_type'=>'none','pn_pf_id'=>$params['pf_id'], 'pn_formart'=>formatNum($params['number'])]);
			if(!empty($rows)) $pidArr = array_column($rows, 'pn_p_id');
		}
		return array_unique($pidArr);
	}


	/**
	 * edit ceil 值修改
	 * @return array
	 */
	function setValue($key,$field,$value,$remark=''){
        $result = 200;
        if($result== 200) {
			$this->db->update($this->table,[$field=>$value],[$this->key=>$key]);
			$this->db->update($this->table,['update_time'=>getNowTime()],[$this->key=>$key]);
		}
		return $result;
	}

	/**
	 * edit ceil 值修改
	 * @return array
	 */
	function setAttaqty($key,$field,$value){
        $result = 200;
        if($result== 200) {
			$this->db->replace('pro_attaqty',['pa_p_id'=>$key,$field=>$value],['pa_p_id']);
		}
		return $result;
	}

	/**
	 * edit ceil 值修改
	 * @return array
	 */
	function getAttaqtyByPid($key){
		return $this->db->get('pro_attaqty','*',['pa_p_id'=>$key]);;
	}

	/**
	  * @method 号码自动完成
	  * @param  $params [
					type string  [选填] [默认] innum  linkinnum:主品牌物料编码 comnum  comin oth:非系统品牌号  all:不限制 
					num|query string  [必填] 号码
				]
	  * @author soul
	  */
	public function autocomNum($params)
	{
		$params['num'] = empty($params['num'])? $params['query']: $params['num'];
		$where = ['pn_type'=>'none', 'pn_formart[=~]'=>formatNum($params['num'])];
		switch($params['type'])
		{
			case 'comnum':
				$where['pn_is_sys'] = 1;
				$where['pn_pf_id'] = 2;
			break;
			case 'linkinnum':
				$where['p_pb_id'] = 1;
				$where['pn_is_sys'] = 1;
				$where['pn_pf_id'] = 3;
			break;
			case 'oth':
				$where['pn_is_sys'] = 0;
			break;
			case 'comin':
				$where['pn_is_sys'] = 1;
				$where['pn_pf_id'] = [2,3];
			break;
			default:
				$where['pn_is_sys'] = 1;
				$where['pn_pf_id'] = [3];
			break;
		}
		$where['LIMIT'] = empty($params['limit'])? 20: (int) $params['limit'];
		$where['GROUP'] = 'pn_number';
		$where['ORDER'] = 'pn_number';
		$join = ["[><]pro(p)" => ["num.pn_p_id" => "p_id"]];
		$rows = $this->db->select('pro_numidx(num)', $join, ['pn_number'], $where);
		$data = [];
        foreach($rows as $k=>$v){
            $data[$k]=['key'=>$v['pn_number'], 'value'=>$v['pn_number']];
        }
        return $data;
	}


	public function autoCate($params)
	{
		 $where = ['OR'=>[
				'cn_name[~]'=>$params['num'],
				'en_name[~]'=>$params['num'],
				'py_name[~]'=>$params['num']
			]
		];
		$rows = $this->db->select('pro_cate', ['id', cateName().'(cat_name)'], $where);
		$data = [];
        foreach($rows as $k=>$v){
            $data[$k]=['key'=>$v['id'], 'value'=>$v['cat_name']];
        }
        return $data;
	}


	/**
	  * @method 产品比较
	  * @param  $params [
	  				'maxItem'=>4,
					'pids'=>'1,2,3...',
					'nums'=>['GSP001AK', ...]
				]
	  * @author soul
	  */
	public function getCompare($params)
	{
		$arr = ['items'=>[], 'para'=>[]];
		//按照传入顺序
		$itemArr = [];
		$linkPidArr = [];
		$linkItemArr =[];
		if(!empty($params['pids']))
		{
			$params['pids'] = array_unique(explode(',', $params['pids']));
			foreach($params['pids'] as $pid)
			{
				$row = $this->db->get('pro', '*', ['p_id'=>$pid]);
				if(!empty($row))
				{
					$itemArr[$row['p_id']] = $row;
					//存在关联的p_id
					if($row['p_lnk_p_id'])
						$linkPidArr[$row['p_lnk_p_id']][] = $row['p_id'];
				}
				if(count($itemArr) >= $params['maxItem']) break;
			}
		}
		if(!empty($params['nums']))
		{
			$params['nums'] = array_unique($params['nums']);
			$pcate = null;
			foreach($params['nums'] as $num)
			{
				$num = formatNum($num);
				if(strlen($num) < 3) continue;
				$where = ['pn_type'=>'none', 'pn_pf_id'=>explode(',', $params['fac']), 'pn_formart'.($params['islike']? '[=~]': '')=>$num];
				$join = ["[><]pro(p)" => ["num.pn_p_id" => "p_id"]];
				$rows = $this->db->select('pro_numidx(num)', $join, '*', $where);
				foreach($rows as $row)
				{
					//对比模糊查询限制同小类下的模糊
					if($params['islike'])
					{
						if(!$pcate) $pcate = $row['p_cate'];
						if($pcate != $row['p_cate']) continue;
					}
					$itemArr[$row['p_id']] = $row;
					if(count($itemArr) >= $params['maxItem']) break;
				}
			}
		}
		if(empty($itemArr)) return $arr;
		$pidArr = array_keys($itemArr);

		if($linkPidArr) $pidArr = array_unique(array_merge($pidArr,array_values($linkPidArr)));

		//主图
		$picRes = $this->db->select('pro_pic',['[><]files'=>['pic_fileid'=>'fileid']],'*',['pic_p_id'=>$pidArr,'pic_type'=>'img','pic_ismain'=>1]);
		$picArr = [];
		foreach ($picRes as $pic) {
			if($pic['pic_type']=='img' && $pic['filetype']=='image'){
				$picArr[$pic['pic_p_id']]['bigImg'] = $pic['filepath'].'/'.$pic['filebasename'].'big.'.$pic['fileextname'];
				$picArr[$pic['pic_p_id']]['smallImg'] = $pic['filepath'].'/'.$pic['filebasename'].'small.'.$pic['fileextname'];
			}
		}
		//参数字段
		$cateIdArr = array_unique(array_column($itemArr, 'p_cate'));

		$where = ['ptpa_cate_id'=>$cateIdArr, 'GROUP'=>[LG_NAME], 'ORDER'=>['ptpa_col_order', LG_NAME]];
		$arr['para'] = $this->db->select('part_param', [LG_NAME.'(para_name)', 'sam_count'=>raw('count(*)'), 'ptpa_unit'], $where);
		$arr['para_oth'] = false;
		foreach($arr['para'] as $k=>$v)
		{
			$v['same'] = $v['sam_count'] == count($cateIdArr)? 1: 0;
			if(!$v['same']) $arr['para_oth'] = true;
			$arr['para'][$k] = $v;
		}

		foreach($itemArr as $pid=>$v)
		{
			$v['main_pic'] = '';
			if(!empty($v['p_pic']) && $picArr[$pid])
			{	
				$v['main_pic'] = \mvc::$cfg['urls']['outfiles'].'/'.$picArr[$pid]['smallImg'];
			}

			// if(!empty($v['p_lineimg']))
			// 	$v['p_lineimg'] = \mvc::$cfg['path']['files'].'/pro/line/'.$v['p_lineimg'];

			$v['paras'] = $this->param->getProParamByPid($v['p_lnk_p_id']>0?$v['p_lnk_p_id']:$pid);
			$v['cnmodels'] = [];
			$v['models'] = [];
			$v['nums'] = [];
			$v['imgs'] = [];
			$itemArr[$pid] = $v;
		}
		$carmodel = new carmodel();
		$collocation = new collocation();
		$collArr = $collocation->getCollItems('number');

		//号码
		$join = ["[><]pro_factory(fac)" => ["num.pn_pf_id" => "pf_id"]];
		$where = ['pn_is_sys'=>0, 'pn_p_id'=>$pidArr, 'ORDER'=>['fac.pf_name', 'pn_formart']];
		$rows = $this->db->select('pro_numidx(num)', $join, ['fac.pf_name','pn_p_id(p_id)', 'pn_number', 'pn_mk_id'], $where);
		foreach($rows as $v)
		{	
			$v['unikey'] = $v['pf_name'].':'.$v['pn_number'];
			$v['oe_make'] = '';
			if(!empty($v['pn_mk_id']))
			{
				$oemake = $carmodel->getMakes(explode(',', $v['pn_mk_id']));
				$v['oe_make'] = implode(',', array_column($oemake, 'name'));
			}
			$itemArr[$v['p_id']]['nums'][$v['unikey']] = $v;

			if(isset($linkPidArr[$v['p_id']])) $linkItemArr[$v['p_id']]['nums'][$v['unikey']] = $v;
				
		}

		//国际车型
		$join = [
			"[><]m_model(mm)" => ["pml.pml_mm_id" => "mm_id"],
			"[><]m_series(ms)" => ["mm.mm_ms_id" => "ms_id"],
			"[><]m_make(mk)" => ["mm.mm_mk_id" => "mk_id"]
		];
		$where = ['pml_p_id'=>$pidArr, 'ORDER'=>['mk.mk_'.LG_NAME,'mm.mm_name', 'mm_year_from','mm_month_from']];
		$filed = ['pml_p_id(p_id)', 'mm.mm_id','mk.mk_id', 'mk.mk_'.LG_NAME.'(mk_name)', 'ms.ms_id', 'ms.ms_name','mm.mm_name',  'mm_year_from', 'mm_year_to', 'mm_month_from', 'mm_month_to'];
		$rows = $this->db->select('pro_model_link(pml)', $join, $filed, $where);

		foreach($rows as $v)
		{
			$v['unikey'] = $v['mk_name'].$v['ms_name'].$v['mm_name'];
			$itemArr[$v['p_id']]['models'][$v['unikey']] = $v;
			if(isset($linkPidArr[$v['p_id']])) $linkItemArr[$v['p_id']]['models'][$v['unikey']] = $v;
		}

		//中国车型
		$join = [
			"[><]m_cn_model(mm)" => ["pml.pml_mod3_id" => "mod3_id"],
		];
		$where = ['pml_p_id'=>$pidArr, 'ORDER'=>['mm.make_name','mm.mod2_name','mm.mod3_name']];
		$filed = ['pml_p_id(p_id)','mm.brand_id','mm.mod2_name','mm.make_id', 'mm.make_name','mm.mod3_name'];
		$rows = $this->db->select('pro_model_cn_link(pml)', $join, $filed, $where);

		foreach($rows as $v)
		{
			$v['unikey'] =$v['make_name'].$v['mod2_name'].$v['mod3_name'];
			$itemArr[$v['p_id']]['cnmodels'][$v['unikey']] = $v;

			if(isset($linkPidArr[$v['p_id']])) $linkItemArr[$v['p_id']]['cnmodels'][$v['unikey']] = $v;
		}
		
		foreach ($itemArr as $pkey => &$val) 
		{
			if($val['p_lnk_p_id']>0 && $linkPidArr[$val['p_lnk_p_id']] && $linkItemArr[$val['p_lnk_p_id']]){
				$val['cnmodels']  = array_merge($val['cnmodels'],$linkItemArr[$val['p_lnk_p_id']]['cnmodels']);
				$val['models']  = array_merge($val['models'],$linkItemArr[$val['p_lnk_p_id']]['models']);
				$val['nums']  = array_merge($val['nums'],$linkItemArr[$val['p_lnk_p_id']]['nums']);
			}
		}
		unset($val,$linkItemArr,$linkPidArr);
		$arr['items'] = array_values($itemArr);
		return $arr;
	}


	/**
	  * @method 获取选择器的数据
	  * @param  $table  string  [必填] factory | make
	  * @param  $rules  string
	  * @param  $ids  string
	  * @author soul
	  * @return id 或者 null
	  */
	public function getSelect($table, $rules = [],$ids=[])
	{
		$cofAllArr = [
			'bigcate'=>[
				'table'=>'pro_cate',
				'key'=>'id',
				'fileds'=>[cateName().'(name)','id'],
				'order'=>['name']
			],
			'cate'=>[
				'table'=>'pro_cate',
				'key'=>'id',
				'fileds'=>[cateName().'(name)','id'],
				'order'=>['name']
			],
			'cateParams'=>[
				'table'=>'part_param',
				'key'=>'ptpa_id',
				'fileds'=>[cateName().'(name)','ptpa_id(id)'],
				'order'=>['name']
			],
			'factory'=>[
				'table'=>'pro_factory',
				'key'=>'pf_id',
				'fileds'=>['pf_name(name)','pf_id(id)'],
				'order'=>['pf_name']
			],
			'make'=>[
				'table'=>'m_make',
				'key'=>'mk_id',
				'fileds'=>['mk_'.LG_NAME.'(name)','mk_id(id)'],
				'order'=>['mk_'.LG_NAME]
			],
			'cnmake'=>[
				'table'=>'m_cn_model',
				'key'=>'brand_id',
				'fileds'=>['brand_name(name)','brand_id(id)','brand_initial(letter)'],
				'order'=>['letter'],
				'group'=>['brand_id'],
			],
			'ver'=>[
				'table'=>'tags',
				'key'=>'t_id',
				'fileds'=>[LG_NAME.'(name)','t_id(id)'],
				'order'=>['t_id']
			],
			'area'=>[
				'table'=>'m_area',
				'key'=>'ma_id',
				'fileds'=>[LG_NAME.'(name)','ma_id(id)'],
				'order'=>[LG_NAME]
			],
			'user'=>[
				'table'=>'adm_user',
				'key'=>'au_id',
				'fileds'=>['au_name(name)','au_id(id)'],
				'order'=>['name'],
				'where'=>['au_id[!]'=>['gsp.admin','admin']]
			],
			'cnmakesql'=>[
				'sql'=>'select brand_name name, brand_id id, brand_initial letter from m_cn_model group by brand_id order by brand_initial',
				'db'=>'main',
			],
			'bmPdmItems'=>[
				'table'=>'copy_smt_api_pdm_items',
				'key'=>'part_type',
				'fileds'=>['part_type(name)','part_type(id)'],
				'order'=>['part_type'],
				'where'=>['GROUP'=>['part_type'],'brand'=>'DRJN']
			],
			'mxgPdmItems'=>[
				'table'=>'copy_smt_api_pdm_items',
				'key'=>'part_type',
				'fileds'=>['part_type(name)','part_type(id)'],
				'order'=>['part_type'],
				'where'=>['GROUP'=>['part_type'],'brand[!]'=>'DRJN']
			],
			'pcInnum'=>[
				'table'=>'pro',
				'key'=>'p_id',
				'fileds'=>['p_innum(name)','p_id(id)'],
				'order'=>['p_id'],
				'where'=>['p_pb_id'=>1]
			],
			'supplier'=>[
				'table'=>'supplier',
				'key'=>'sup_id',
				'fileds'=>['sup_name(name)','sup_id(id)']
			],
			'brand'=>[
				'table'=>'pro_brand',
				'key'=>'pb_id',
				'fileds'=>['pb_'.LG_NAME.'(name)','pb_id(id)']
			],
			'cnbrand'=>[
				'table'=>'m_cn_model',
				'key'=>'brand_id',
				'fileds'=>['brand_name(name)','brand_id(id)','brand_initial(letter)'],
				'order'=>['brand_initial'],
				'group'=>['brand_name']
			],
			'namake'=>[
				'table'=>'na_vehicle_base',
				'key'=>'base_make_id',
				'fileds'=>['base_make_name(name)','base_make_id(id)'],
				'order'=>['base_make_name'],
				'group'=>['base_make_id']
			],
			'tagbrand'=>[
				'table'=>'tag_brand',
				'key'=>'tb_id',
				'fileds'=>['tb_'.LG_NAME.'(name)','tb_id(id)'],
			],
			'company'=>[
				'table'=>'company',
				'key'=>'com_id',
				'fileds'=>['com_'.LG_NAME.'(name)','com_id(id)']
			],
			'factory'=>[
				'table'=>'factory',
				'key'=>'fac_id',
				'fileds'=>['fac_name(name)','fac_id(id)'],
			]
		];
		if(empty($cofAllArr[$table])) exitJson($table.' 规则尚未配置');
		$cofArr = $cofAllArr[$table];
		
		if(!empty($cofArr['sql']) && !empty($cofArr['db']))
		{
			$this->sdb = new \lib\db(\mvc::$cfg['db'][$cofArr['db']]);
			return $this->sdb->query($cofArr['sql'])->fetchAll(\PDO::FETCH_ASSOC);
		}
		else
		{
			$where = $rules;
			if($ids){
				$where = array_merge($where,[$cofAllArr[$table]['key']=>$ids]);
			}
			if(isset($cofAllArr[$table]['where'])){
				$where = array_merge($where,$cofAllArr[$table]['where']);
			}
			$where['ORDER'] = $cofArr['order'];
			if(isset($cofArr['group']) && !empty($cofArr['group'])){
				$where['GROUP'] = $cofArr['group'];
			}
			return $this->db->select($cofArr['table'], $cofArr['fileds'], $where);
		}
	}


	/*通过编码找p_id*/
    public function getPcId($value)
	{
		$where = ['p_comnum'=>$value];
		return $this->db->get('pro',"p_id",$where);
    }




	/**
	  * @method 编码库  
	  * @author soul
	  */
	public function getCodeList($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];
		$this->joinWhere = [];
		$refiled = [
			'cat_name'=>'cat.'.cateName(),
			'pb_name'=>'pb.pb_'.LG_NAME,
			'p_name'=>'p.p_'.LG_NAME,
			'p_model_name'=>'p.p_model_'.LG_NAME,
			'p_des_name'=>'p.p_des_'.LG_NAME,
			'cat_name_cn'=>'cat.cn_name',
			'cat_name_en'=>'cat.en_name',
			'pcat_name'=>'pcat.'.cateName(),
			'p_oe'=>'p_oe_format',
			'oe_oe'=>'oe.oe_oe_format',
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro(p)';
		$join = [
			"[>]pro_cate(cat)" => ["p.p_cate" => "id"],
			"[>]pro_cate(pcat)" => ["cat.parent_id" => "id"],
			"[><]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"],
			"[>]pro_ext(ext)" => ["p.p_id" => "pe_p_id"],
			"[>]oe_item(oe)" => ["p.p_oe_id" => "oe_id"],
			"[><]pro_factory(fac)" => ["p.p_pf_id" => "pf_id"],
			// "[>]cd_make(cm)"=>['p.p_cm_id'=>'cm_id'],
		];
	
		$this->set('carmodel', new carmodel());
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
			if(in_array($field, ['p_pos1','p_pos2','p_pos3','p_pos4','p_pos5']))
			{
				if(in_array($op, ['cn', 'eq']))
				{
					$data = raw(sprintf("concat('/',%s,'/') like '%%/%s/%%'", $field, $data));
					$op = 'RAW_'.$field.$op;
				}
				else if(in_array($op, ['ni']))
				{
					$data = raw(sprintf("concat('/',%s,'/') not like '%%/%s/%%'", $field, $data));
					$op = 'RAW_'.$field.$op;
				}
			}
			if($field == 'tags')
			{
				$res = $this->get('carmodel')->medooAnyLink($field, 'p_id', $op, $data, ['tl_type'=>'pro']);
				$data = $res['data'];
				$op = $res['op'];
			}elseif($field == 'pic'){
				$op = 'RAW_'.$field;
				if($data==1){
					$data = raw(" p_id in (select distinct pic_p_id from pro_pic join files on pic_fileid=fileid where pic_type='img')");
				}else{
					$data = raw(" p_id not in (select distinct pic_p_id from pro_pic join files on pic_fileid=fileid where pic_type='img')");
				}
			}else if($field == 'p_oe_format'){
				$data = formatNum($data);
			}else if($field == 'oe.oe_oe_format'){
				$data = formatNum($data);
			}
        });
		
		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$tnums = [];
					foreach($val as $tk=>$tv){
						$tnums = array_merge($tnums, reSearchNum($tv));
					}
					$tnums = array_unique($tnums);
					if($rules['numlike']) {
						// 使用EXISTS优化模糊查询
						$likeConditions = [];
						foreach ($tnums as $num) {
							if(!$num) continue;
							$likeConditions[] = sprintf("pn_formart LIKE '%s%%'", $num);
						}
						
						if (!empty($likeConditions)) {
							$likeWhere = implode(' OR ', $likeConditions);
							$sql = sprintf("
								SELECT 1 
								FROM pro_numidx 
								WHERE (pn_p_id = p.p_id OR pn_p_id = p.p_lnk_p_id) 
								  AND (%s)
								LIMIT 1
							", $likeWhere);
							
							$where['RAW_'.$filed] = raw(sprintf("EXISTS (%s)", $sql));
						}
					} else {
						// 使用EXISTS优化精确查询
						if (!empty($tnums)) {
							$numstr = implode(',', array_map(function($num) { 
								return "'".formatNum($num)."'"; 
							}, $tnums));
							
							$sql = sprintf("
								SELECT 1 
								FROM pro_numidx 
								WHERE (pn_p_id = p.p_id OR pn_p_id = p.p_lnk_p_id) 
								  AND pn_formart IN (%s)
								LIMIT 1
							", $numstr);
							
							$where['RAW_'.$filed] = raw(sprintf("EXISTS (%s)", $sql));
						}
					}
				break;
				case 'p_cate': $where['p_cate'] = explode(',', $rules['p_cate']); break;
				case 'proBrand': $where['p_pb_id'] = explode(',', $rules['proBrand']); break;
				case 'mk_id':
					 // 使用IN优化，同时考虑p_lnk_p_id关联
					$mkIds = is_array($val) ? $val : explode(',', $val);
					$mkIds = array_map('intval', $mkIds);
					$mkIdsList = implode(',', $mkIds);
					
					// 先查询所有符合条件的p_id（包括主品牌和关联品牌）
					$sql = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_link pml ON p.p_id = pml.pml_p_id
						LEFT JOIN m_model mm ON pml.pml_mm_id = mm.mm_id
						WHERE mm.mm_mk_id IN (%s)
					", $mkIdsList);
					
					$pIds = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'ms_id':
					// 使用IN优化，同时考虑p_lnk_p_id关联
					$msIds = is_array($val) ? $val : explode(',', $val);
					$msIds = array_map('intval', $msIds);
					$msIdsList = implode(',', $msIds);
					
					$sql = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_link pml ON p.p_id = pml.pml_p_id
						LEFT JOIN m_model mm ON pml.pml_mm_id = mm.mm_id
						LEFT JOIN m_series ms ON mm.mm_ms_id = ms.ms_id
						WHERE ms.ms_id IN (%s)
					", $msIdsList);
					
					$pIds = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'brand_id':
					// 使用IN优化，同时考虑p_lnk_p_id关联
					$brandIds = is_array($val) ? $val : explode(',', $val);
					$brandIds = array_map('intval', $brandIds);
					$brandIdsList = implode(',', $brandIds);
					
					$sql = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_cn_link pmcl ON p.p_id = pmcl.pml_p_id
						LEFT JOIN m_cn_model mcm ON pmcl.pml_mod3_id = mcm.mod3_id
						WHERE mcm.brand_id IN (%s)
					", $brandIdsList);
					
					$pIds = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'make_id':
					// 使用IN优化，同时考虑p_lnk_p_id关联
					$makeIds = is_array($val) ? $val : explode(',', $val);
					$makeIds = array_map('intval', $makeIds);
					$makeIdsList = implode(',', $makeIds);
					
					$sql = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_cn_link pmcl ON p.p_id = pmcl.pml_p_id
						LEFT JOIN m_cn_model mcm ON pmcl.pml_mod3_id = mcm.mod3_id
						WHERE mcm.make_id IN (%s)
					", $makeIdsList);
					
					$pIds = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'mod2_id':
					// 使用IN优化，同时考虑p_lnk_p_id关联
					$mod2Ids = is_array($val) ? $val : explode(',', $val);
					$mod2Ids = array_map('intval', $mod2Ids);
					$mod2IdsList = implode(',', $mod2Ids);
					
					$sql = sprintf("SELECT DISTINCT 
							p_id
						FROM pro p
						LEFT JOIN pro_model_cn_link pmcl ON (p.p_id = pmcl.pml_p_id OR p.p_lnk_p_id = pmcl.pml_p_id)
						LEFT JOIN m_cn_model mcm ON pmcl.pml_mod3_id = mcm.mod3_id
						WHERE mcm.mod2_id IN (%s)
					", $mod2IdsList);
					
					$pIds = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					if (!empty($pIds)) {
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'model_engine':
					$engineVal = $this->db->quote($val);
            
					$sql1 = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_cn_link pmcl ON p.p_id = pmcl.pml_p_id
						LEFT JOIN m_cn_model mcm ON pmcl.pml_mod3_id = mcm.mod3_id
						WHERE FIND_IN_SET(%s, mcm.mod3_engine) > 0
					", $engineVal);
					
					$sql2 = sprintf("SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_link pml ON p.p_id = pml.pml_p_id
						LEFT JOIN m_model mm ON pml.pml_mm_id = mm.mm_id
						WHERE FIND_IN_SET(%s, mm.mm_engine) > 0
					", $engineVal);
					
					$pIds1 = $this->db->query($sql1)->fetchAll(\PDO::FETCH_COLUMN);
					$pIds2 = $this->db->query($sql2)->fetchAll(\PDO::FETCH_COLUMN);
					$pIds = array_unique(array_merge($pIds1, $pIds2));
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}

					} 
					// 添加p_engine直接匹配的条件
					$where['OR #model_engine'] = [
						'p_engine[~]' => $val,
						'p_id' => empty($pIds) ? [-1] : $pIds
					];
					break;
				case 'model_keyword':
					$keyword = $this->db->quote('%' . $val . '%');
            
					$sql = sprintf("
						SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_link pml ON p.p_id = pml.pml_p_id
						LEFT JOIN m_model mm ON pml.pml_mm_id = mm.mm_id
						LEFT JOIN m_make mk ON mm.mm_mk_id = mk.mk_id
						LEFT JOIN m_series ms ON mm.mm_ms_id = ms.ms_id
						WHERE mm.mm_name LIKE %s 
						   OR mk.mk_cn_name LIKE %s 
						   OR mk.mk_en_name LIKE %s 
						   OR mk.mk_py_name LIKE %s 
						   OR ms.ms_name LIKE %s
					", $keyword, $keyword, $keyword, $keyword, $keyword);
					
					$sql2 = sprintf("
						SELECT DISTINCT p_id
						FROM pro p
						LEFT JOIN pro_model_cn_link pmcl ON p.p_id = pmcl.pml_p_id
						LEFT JOIN m_cn_model mcm ON pmcl.pml_mod3_id = mcm.mod3_id
						WHERE mcm.mod3_name LIKE %s OR mcm.mod2_name LIKE %s
					", $keyword, $keyword);
					
					$pIds1 = $this->db->query($sql)->fetchAll(\PDO::FETCH_COLUMN);
					$pIds2 = $this->db->query($sql2)->fetchAll(\PDO::FETCH_COLUMN);
					$pIds = array_unique(array_merge($pIds1, $pIds2));
					
					if (!empty($pIds)) {
						//再查一下关联p_lnk_p_id的p_id
						$linkedMainPIds = $this->db->select('pro','p_id',['p_lnk_p_id'=>$pIds,'GROUP'=>'p_id']);
						if (!empty($linkedMainPIds)) {
							$pIds = array_unique(array_merge($pIds, $linkedMainPIds));
						}
						$where['p_id'] = isset($where['p_id']) ? 
							array_intersect((array)$where['p_id'], $pIds) : 
							$pIds;
					} else {
						$where['p_id'] = -1;
					}
					break;
				case 'ver': 
					$join["[><]tags_link(tl)"] = ["p.p_id" => "tl_value_id"];
					$where['tl_type'] = 'pro';
					$where['tl_t_id[>]'] = raw(sprintf("tl_t_id ^ %d",$rules['ver']));
				break;
			}
		}
		
		//是否有图片
		if(isset($rules['propictype']) && isset($rules['propictypeOption'])){
			
		}else if(isset($rules['propictype'])){
			$this->listForImage($rules);
		}

		//查非
		if(!empty($rules['findNulls'])){
			$this->findNullsSearch($rules['findNulls'], $this->join, $this->joinWhere);
		}
		//汽车品牌查询
		if(isset($rules['tagBrand'])){
			if(!is_array($rules['tagBrand'])) $rules['tagBrand'] = explode(',', $rules['tagBrand']);
			
			$comnumarr = $this->db->select('pro_tag_brand(ptb)',['[><]pro(p2)'=>['ptb.ptb_p_id'=>'p_id']], ['p_comnum_format'=>raw('DISTINCT p_comnum_format')], ['ptb_tb_id'=>$rules['tagBrand']]);
			
			$this->joinWhere['p_comnum_format'] = array_column($comnumarr,'p_comnum_format');
		}


		if(!empty($params['keys'])) $where['p_id'] = explode(',', $params['keys']);
		if(!empty($params['p_id'])) $where['p_id'] = $params['p_id'];
		
		if(isset($params['ck3'])) $where['ck3'] = $params['ck3'];
		if(empty($where['ORDER']))$where['ORDER'] = ['p_id'=>'DESC'];
		
		if(!empty($rules['coutype'])){
			$country = new \model\country();
			$couwhere = $country->formatSearchWhere('pro', $rules, $rules);
			if(!empty($couwhere)) $where = array_merge($where, $couwhere);
		}

		//权限 - 商品品牌
        $proBrands = \p::areas('B100');
        if(!\p::isAdmin() && $proBrands){
    		$where['AND #rule_brand'] = ['p_pb_id'=>explode(',',$proBrands)];
       	}

		$check = new \model\check();
		$ruleWhere = $check->getPowerWhere('pro', 'B100');
		$where = array_merge($where, $ruleWhere);
		if(!empty($this->joinWhere)){
			$where = array_merge($where, $this->joinWhere);
		}
		if(!empty($this->join)){
			$join = array_merge($join, $this->join);
		}
		
        $where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($page>0 && $pagesize>0){
			$fields = '*';
			$pages = $this->paging($table,$join,$fields,$where,$page,$pagesize);
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}

		$fields = ['cat.id(cat_id)', 'cat.cat_pos1','cat.cat_pos2','cat.cat_pos3','cat.cat_pos4','cat.cat_pos5','cat.cat_hsbm','cat.cat_invoice','cat.cat_ktsl', 'cat.cat_unit_customs','pcat.'.cateName().'(pcat_name)', 'cat.'.cateName().'(cat_name)', 'cat.cn_name(cat_name_cn)','cat.en_name(cat_name_en)', 'pb_'.LG_NAME.'(pb_name)','p.*', 'p.p_des_'.LG_NAME.'(p_des_name)','p.p_model_'.LG_NAME.'(p_model_name)','p.p_'.LG_NAME.'(p_name)','ext.*','fac.pf_name','oe.oe_chkpro_info','oe.oe_chkpro_id','oe.oe_chkpro_from'];

		$arr = $this->db->select($table,$join,$fields,$where);
		if(!empty($arr))
		{	
			if(!$rules['propictype'])
			{
				$table = 'oe_item(oi)';
				$join = [
					"[><]pro_factory(pf)" => ["oi.oe_pf_id" => "pf_id"],
				];
				$fields = ['oe_id', 'pf_name(oe_pf_name)', 'oe_oe', 'oe_etk_info'];
				$oeArr = $this->db->select($table,$join,$fields, ['oe_id'=>array_column($arr, 'p_oe_id')]);
				$oeArr = array_column($oeArr, null, 'oe_id');

				$tags = new tags();
				$collocation = new collocation();
				$collArr = $collocation->getCollItems('pro');
				$verArr = $tags->getTypeValTags('pro', array_column($arr, 'p_id'));
				$verArr = array_column($verArr, 'tags', 'tl_value_id');

				$pidArr = array_column($arr, 'p_id');
				//主图
				$picRes = $this->db->select('pro_pic',['[><]files'=>['pic_fileid'=>'fileid']],'*',['pic_p_id'=>$pidArr,'pic_type'=>'img','pic_ismain'=>1]);
				$picArr = [];
				foreach ($picRes as $pic) {
					if($pic['pic_type']=='img' && $pic['filetype']=='image'){
						$picArr[$pic['pic_p_id']]['bigImg'] = $pic['filepath'].'/'.$pic['filebasename'].'big.'.$pic['fileextname'];
						$picArr[$pic['pic_p_id']]['smallImg'] = $pic['filepath'].'/'.$pic['filebasename'].'small.'.$pic['fileextname'];
						if($params['isExport'])
						{
							$picArr[$pic['pic_p_id']]['type'] = 'image';
							$picArr[$pic['pic_p_id']]['filename'] = \mvc::$cfg['dir']['files'].'/'.$picArr[$pic['pic_p_id']]['smallImg'];

							list($width, $height, $type, $attr) = getimagesize($picArr[$pic['pic_p_id']]['filename']);
							$picArr[$pic['pic_p_id']]['widthScale'] = 1;
							$picArr[$pic['pic_p_id']]['heightScale'] = 1;
							$picArr[$pic['pic_p_id']]['rowHeight'] = $height;
						}
						
					}
				}
				//参数
				$fields = ['ppv_p_id', 'ptpa_id', 'ptpa_type', 'ptpa_unit', 'ptpa_decimal', 'ppv_val_int', 'ppv_val_double', 'ppv_val_string', 'ptpa_col_order'];
				$fields = langSqlFields($fields, 'pa.', 'ptpa_', true);
				$fields = langSqlFields($fields, 'pps.', 'ppv_val_', true);
				$fields = langSqlFields($fields, 'ppsu.', 'ptpa_unit_', true);
				$sqltpl =sprintf("SELECT ".implode(',', $fields)."  FROM `pro_param_val` pv
				JOIN part_param pa ON ptpa_id = ppv_ptpa_id
				LEFT JOIN part_param_sche pps ON ((pps.pps_ptpa_id = ptpa_id AND ppv_val_string = pps.cn_name) or (pps.pps_ptpa_id = ptpa_pid and pps_id = ppv_val_int))
				LEFT JOIN part_param_sche ppsu ON ppsu.pps_ptpa_id = 0 and ptpa_unit = ppsu.cn_name
				WHERE ppv_p_id in (%s) ORDER BY ptpa_pid DESC,ptpa_id ASC",implode(',',$pidArr));
				$rows = $this->db->query($sqltpl)->fetchAll();
				foreach($rows as $row){
					
					if($row['ppv_val_int']){
						$row['ppv_val'] = $row['ppv_val_'.LG_NAME].($row['ptpa_unit_'.LG_NAME]?:$row['ptpa_unit']);
						$paramArr[$row['ppv_p_id']][] = ['name'=>$row['ptpa_'.LG_NAME],'value'=>$row['ppv_val']];
						continue;
					}
					if($row['ptpa_type']=='string'){
						$row['ppv_val'] = $row['ppv_val_'.LG_NAME];
					}elseif($row['ptpa_type']=='double'){
						$row['ppv_val'] = floatval(number_format($row['ppv_val_double'], $row['ptpa_decimal'],".",""));
					}
					$paramArr[$row['ppv_p_id']][] = ['name'=>$row['ptpa_'.LG_NAME],'value'=>$row['ppv_val'].($row['ptpa_unit_'.LG_NAME]?:$row['ptpa_unit'])];
				}
				if($rules['show_base'])
				{
					//省市县
					$pctIdArr = [];
					foreach ($arr as $val) {
						if($val['p_source_province_id']) $pctIdArr[] = $val['p_source_province_id'];
						if($val['p_source_city_id']) $pctIdArr[] = $val['p_source_city_id'];  
					}
					if($pctIdArr){
						$allPctArr = $this->db->select('province_city',['pc_id','pc_name'],['pc_id'=>array_unique($pctIdArr)]);
						$allPctArr = array_column($allPctArr,'pc_name','pc_id');
					}
					//开发号
					$devNum = [];
					$devNumArr = $this->db->select('pro_developno',['[>]supplier(sup)'=>['pde_sup_id'=>'sup_id']],'*',['pde_p_id'=>$pidArr]);
					foreach ($devNumArr as $val) {
						$devNum[$val['pde_p_id']][] = ($val['sup_name']?$val['sup_name'].':':"").$val['pde_number'];
					}
				}
				//查操作人
				$opuser = array_unique(array_filter(array_column($arr, 'p_opuser')));
				if($opuser){
					$nameRes = $this->db->select('adm_user',['au_name','au_id'],['au_id'=>$opuser]);
					$aunameArr = array_column($nameRes,'au_name','au_id');
				}
			}
			//查汽车品牌
			$pb = [];
			$tb = [];
			foreach ($arr as $val) 
			{
				if($val['p_pb_id']==1){
					$pb[] = $val['p_id'];
				}else{
					$tb[] = $val['p_comnum_format'];
				}
			}
			if($tb){
				$tbArr = $this->db->select('pro',['p_id','p_comnum_format'],['p_comnum_format'=>$tb,'p_pb_id'=>1]);
				$tbArr = array_column($tbArr,'p_id','p_comnum_format');
				
				$pb = array_merge($pb,$tbArr?array_keys($tbArr):[]);
			} 
			if($pb)
			{
				$pbArr = $this->db->select('pro_tag_brand',['[><]tag_brand'=>['ptb_tb_id'=>'tb_id']],['ptb_p_id','tb_name'=>raw("GROUP_CONCAT(tb_".LG_NAME." ORDER BY CONVERT(tb_".LG_NAME." USING gbk))")],['GROUP'=>['ptb_p_id']]);
				$pbArr = array_column($pbArr,'tb_name','ptb_p_id');
			}
			
			foreach($arr as &$v)
			{	
				if(!$rules['propictype'])
				{
					$v['pic'] = $picArr[$v['p_id']]??[];

					$paramArr2 = [];
					foreach ($this->allPos as $pos => $val) {
						if($v['cat_'.$pos] && $v['p_'.$pos]) {
							$pos = array_intersect(explode('/',$v['p_'.$pos]),explode(',',$v['cat_'.$pos]));
							if($pos) $paramArr2[] = ['name'=>$val['name'],'value'=>implode('/',$pos)];
						}
					}
					
					$paramArr[$v['p_id']]  = array_merge($paramArr2,$paramArr[$v['p_id']]??[]);
					$v['param'] = $paramArr[$v['p_id']]?$paramArr[$v['p_id']]: [];
					$paramsopt = [];
					foreach ($v['param'] as $value) {
						$paramsopt[] = $value['name'].': '.$value['value'];
					}

					$v['cate_posArr'] = [
						'cat_pos1'=>$v['cat_pos1']?explode(',',$v['cat_pos1']):[],
						'cat_pos2'=>$v['cat_pos2']?explode(',',$v['cat_pos2']):[],
						'cat_pos3'=>$v['cat_pos3']?explode(',',$v['cat_pos3']):[],
						'cat_pos4'=>$v['cat_pos4']?explode(',',$v['cat_pos4']):[],
						'cat_pos5'=>$v['cat_pos5']?explode(',',$v['cat_pos5']):[],
					];
					$pe_category = [];
					if(!empty($v['pe_category'])){
						foreach(explode(',', $v['pe_category']) as $t){
							$pe_category[] = $collArr[$t];
						}
					}
					if($oeArr[$v['p_oe_id']]){
						$v = array_merge($v, $oeArr[$v['p_oe_id']]);
						$v['oe_etk_info'] = json_decode($v['oe_etk_info'], true);
					}

					$v['oe_chkpro_info'] = empty($v['oe_chkpro_info'])? []:json_decode($v['oe_chkpro_info'], true);
					$v['p_para'] = empty($v['p_para'])? []:json_decode($v['p_para'], true);
				}
				$v['tags'] = empty($verArr[$v['p_id']]) ? '': implode(',', array_column($verArr[$v['p_id']], 't_id'));
				$v['captions'] = [
					'p_pb_id'=>$v['pb_name'],
					'p_item_type'=>!empty($collArr[$v['p_item_type']])? $collArr[$v['p_item_type']]: '',
					'p_unit'=>!empty($collArr[$v['p_unit']])? $collArr[$v['p_unit']]: '',
					'cat_unit_customs'=>!empty($collArr[$v['cat_unit_customs']])? $collArr[$v['cat_unit_customs']]: '',
					'p_state_main'=>\mvc::$cfg['PROSTATUS'][$v['p_state_main']]? \mvc::$cfg['PROSTATUS'][$v['p_state_main']]: '',
					'tags'=> empty($verArr[$v['p_id']]) ? '': implode(',', array_column($verArr[$v['p_id']], LG_NAME)),
					'pe_category'=>implode(',', $pe_category),
					'p_opuser'=>$aunameArr[$v['p_opuser']]??'',
					'param'=>implode('<br>', $paramsopt),
					'p_material'=>!empty($collArr[$v['p_material']])? $collArr[$v['p_material']]: '',
					'p_source_province_id' => $allPctArr[$v['p_source_province_id']],
                    'p_source_city_id' => $allPctArr[$v['p_source_city_id']],
					'p_develop_status'=>!empty($collArr[$v['p_develop_status']])? $collArr[$v['p_develop_status']]: '',
					'p_devno'=>$devNum[$v['p_id']]?implode("\r\n",$devNum[$v['p_id']]):'',
					// 'p_cm_id'=>$v['cm_name'],
					'p_tb_id'=>$v['p_pb_id']==1?$pbArr[$v['p_id']]:$pbArr[$tbArr[$v['p_comnum_format']]],
					'p_fuel_type'=>!empty($collArr[$v['p_fuel_type']])? $collArr[$v['p_fuel_type']]: '',
				];
			}
		}
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	/**
	  * @method 编辑编码库
	  * @param  $p_id  int  [必填] p_id
	  * @param  $setArr  array  [必填] ['p_state_main'=>'',....]
	  * @author soul
	  */
	public function setCodeCell($p_id, $setArr)
	{
		$result = '';
		//$canSetFiled = ['p_cate', 'p_state_main', 'p_state_sub', 'p_comnum', 'p_rule_1', 'p_rule_a', 'p_rule_b', 'p_rule_c', 'p_usa_make', 'p_state_remark', 'tags', 'p_remark', 'p_sales_qty', 'p_vio', 'p_release_time', 'p_release_vers','nosale_cn'];
		
		if(!empty($p_id) && !empty($setArr))
		{
			$list = $this->getCodeList(['p_id'=>$p_id]);
			$old = $list['rows'][0];
			if(empty($old)) exitJson('记录不存在');

			if(!\p::catesEdit('B100', $old['p_cate'])) exitJson('无此小类权限');

			$cateRow = $this->db->get('pro_cate','*',['id'=>$old['p_cate']]);
			
			$setProArr = [];

			foreach($setArr as $filed=>$val)
			{
				if(stripos($filed,'_pos')!==false){
					$key= str_replace('p_','cat_',$filed);
					if(!$cateRow[$key] ){
						exitJson(lg('该产品不支持修改此位置'));
					}
					$temp = explode('/',$val);
					$pval = explode(',',$cateRow[$key]);
					if(array_diff($temp,$pval)) exitJson(lg('该产品不支持修改此位置'));
				}

				//审核后部分字段不允许修改
				if((!empty($old['ck3']) && in_array($filed, ['p_comnum']))
				){
					unset($setArr[$filed]);
				}
			}
			if(isset($setArr['p_comnum']) && $setArr['p_comnum']){
				if($this->db->has('pro',['p_id[!]'=>$p_id,'p_comnum'=>$setArr['p_comnum']])){
					exitJson(lg('自动编码').': '.$setArr['p_comnum'].lg('已经被使用'));
				}
			}

			if(isset($setArr['p_oe']) && $setArr['p_oe']){
				$setArr['p_oe_format'] = formatNum($setArr['p_oe']);
			}
			$tmpsetArr  = $setArr;
			$this->db->Begin();
			if(isset($setArr['tags']))
			{
				$tags = new tags();
				$tagsLinkArr = [['t_id'=>$val, 'value_id'=>$p_id]];
				$tags->changeTagsLink('pro', 'replace', $tagsLinkArr);
				unset($setArr['tags']);
			}
			if(!empty($setArr))
			{
				$opuser = getOpuser();
				$datetime = getNowTime();
				$setArr['p_opuser'] = $opuser;
				$setArr['p_update_time'] = $datetime;
				$this->db->update('pro', $setArr, ['p_id'=>$p_id]);
			}
			//产品日志
			$changeArr =[];
			//获取新的
			$list = $this->getCodeList(['p_id'=>$p_id]);
			$newArr = $list['rows'][0];
			foreach ($tmpsetArr as $field => $val) {
				if(isset($old[$field]) && $old[$field]!=$val){
					$changeArr[] = ['field'=>$field,'name'=>$this->codeFields[$filed],'new'=>$newArr['captions'][$field]??$val,'old'=>$old['captions'][$field]??$old[$field]];
				}
			}
			if($changeArr){
				$logdata = [
					'cl_type'=>'pro',
					'cl_act'=>'edit',
					'cl_dataid'=>$p_id,
					'cl_change'=>json_encode(['code'=>$changeArr], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
				$this->db->insert('change_log',$logdata);
			}
			$this->addProSynLog([$p_id], 'set', 'text');
			$this->db->End();
		}
		return $result;
	}
	
	/**
	  * @method 变更小类
	  * @param  ids  string  [必填] p_id  多个逗号分隔
	  * @param  cat_id  int  [必填] 小类ID
	  * @author soul
	  */
	public function setCodeCate($ids, $cat_id)
	{
		$pcodeArr = $this->db->select('pro',['[><]pro_cate'=>['p_cate'=>'id']],['p_id','p_cate',LG_NAME], ['p_id'=>explode(',', $ids), 'p_cate[!]'=>$cat_id]);
		$pidArr = array_column($pcodeArr,'p_id');

		$pcodeArr = array_column($pcodeArr,null,'p_id');
		
		if(!empty($pidArr))
		{
			$this->db->Begin();
			$opuser = getOpuser();
			$datetime = getNowTime();
			$setArr = [
				'opuser'=>$opuser,
				'update_time'=>$datetime,
				'p_cate'=>$cat_id,
			];
			$this->db->update('pro', $setArr, ['p_id'=>$pidArr]);

			$this->db->delete('pro_param_val', ['ppv_p_id'=>$pidArr]);
			// $this->db->update('pro_model_link_temp', ['pmlt_cate'=>$cat_id], ['pmlt_p_id'=>$pidArr]);
			$newcate = $this->db->get('pro_cate',LG_NAME,['id'=>$cat_id]);
			foreach ($pidArr as $pid) {
				$changeArr = ['field'=>'p_cate','name'=>'小类','new'=>$newcate,'old'=>$pcodeArr[$pid][LG_NAME]];
				$logdata[] = [
					'cl_type'=>'pro',
					'cl_act'=>'edit',
					'cl_dataid'=>$pid,
					'cl_change'=>json_encode(['code'=>[$changeArr]], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
			}
			$this->db->insert('change_log',$logdata);
			$this->addProSynLog($pidArr, 'set', 'text');
			$this->db->End();
		}
		return[];
	}


	/**
	  * @method 变更主状态
	  * @param  ids  string  [必填] p_id  多个逗号分隔
	  * @author soul
	  */
	public function changeStateMain($idArr, $dataArr)
	{
		$this->db->Begin();
		if(!empty($idArr) && !empty($dataArr['p_state_main']) && !empty($dataArr['p_state_remark']))
		{
			$setArr = [
				'p_state_main'=>$dataArr['p_state_main'],
				'p_state_remark'=>$dataArr['p_state_remark'],
			];
			foreach($idArr as $p_id)
			{
				$this->setCodeCell($p_id, $setArr);
			}
		}
		$this->db->End();
		return [];
	}


	/**
	  * @method 删除编码库  已审或者来自样品的不允许
	  * @param  ids  string  [必填] p_id  多个逗号分隔
	  * @author soul
	  */
	public function delCode($idArr)
	{
		if(!empty($idArr))
		{
			//物理删除
			$arr = $this->db->select('pro', '*', ['p_id'=>$idArr]);
			foreach ($arr as $item){
				if($item['p_state_main'] != 99) exitJson('请将主状态改为“删除”后再删除');
				//集团号删除必须先删除事业部商品
				$used = $this->db->get('pro', '*', ['p_lnk_p_id'=>$item['p_id']]);
				if($used) exitJson('商品被其他品牌引用，请先删除其他品牌的商品后再删除');
			}
			$this->db->Begin();
			
			//删除记录
			foreach ($arr as $item){
				$pid = $item['p_id'];
				$orgArr = [];
				$deltables = [
					['table'=>'pro_bom_assemble', 'where'=>['pba_p_id'=>$pid]],
					['table'=>'pro_bom_pack', 'where'=>['pbp_id'=>$pid]],
					['table'=>'pro_developno', 'where'=>['pde_p_id'=>$pid]],
					['table'=>'pro_ext', 'where'=>['pe_p_id'=>$pid]],
					['table'=>'pro_link_company', 'where'=>['plc_p_id'=>$pid]],
					['table'=>'pro_model_cn_link', 'where'=>['pml_p_id'=>$pid]],
					['table'=>'pro_model_link', 'where'=>['pml_p_id'=>$pid]],
					['table'=>'pro_model_na', 'where'=>['pml_p_id'=>$pid]],
					['table'=>'pro_model_na_link', 'where'=>['pps_p_id'=>$pid]],
					['table'=>'pro_numidx', 'where'=>['pn_p_id'=>$pid]],
					['table'=>'pro_numidx_tag_brand', 'where'=>['pntb_p_id'=>$pid]],
					['table'=>'pro_pack', 'where'=>['pp_p_id'=>$pid]],
					['table'=>'pro_pack_ext', 'where'=>['ppe_p_id'=>$pid]],
					['table'=>'pro_param_val', 'where'=>['ppv_p_id'=>$pid]],
					['table'=>'pro_pic', 'where'=>['pic_p_id'=>$pid]],
					['table'=>'pro_source_link', 'where'=>['psl_p_id'=>$pid]],
					['table'=>'pro_supplier', 'where'=>['psu_p_id'=>$pid]],
					['table'=>'pro_tag_brand', 'where'=>['ptb_p_id'=>$pid]],
					['table'=>'pro_fatherson', 'where'=>['OR'=>['pf_father_pid'=>$pid,'pf_son_pid'=>$pid]]],
					['table'=>'pro_exchange', 'where'=>['OR'=>['pe_p_id1'=>$pid,'pe_p_id2'=>$pid]]],
					['table'=>'pro_pair', 'where'=>['OR'=>['pp_p_id1'=>$pid,'pp_p_id2'=>$pid]]],
					['table'=>'pro', 'where'=>['p_id'=>$pid]],
				];
				foreach($deltables as $dt){
					if(empty($dt['where'])) exitJson('删除产品配置参数错误');
					$rows = $this->db->select($dt['table'], '*', $dt['where']);
					$orgArr[$dt['table']] = $rows? $rows: [];
					$this->db->delete($dt['table'], $dt['where']);
				}

				$log = [
					'cl_type'=>'pro',
					'cl_act'=>'del',
					'cl_dataid'=>$item['p_id'],
					'cl_change'=>json_encode($orgArr, JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
				$this->db->insert('change_log', $log);
				$this->addProSynLog([$pid], 'del', 'text');
			}
			$this->db->End();
		}
		return [];
	}


	//型号通用汇总（通用，父子，通用手工）
	public function getExchageAllList($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];

		$fields = '*';
        $tableSql = "SELECT 
                    '通用' etype,
                    pe_p_id1 pid1,
                    pe_p_id2 pid2,
                    pe_param1 param1,
                    pe_param2 param2,
                    pe_remark remark,
                    pe_frometo fromto,
                    pro1.p_comnum outnum1,
                    pro1.p_cate cate1,
                    pro_cate1.cn_name cate1_cn_name,
                    pro_cate1.en_name cate1_en_name,
                    pro2.p_comnum outnum2,
                    pro2.p_cate cate2,
                    pro_cate2.cn_name cate2_cn_name,
                    pro_cate2.en_name cate2_en_name
                    FROM pro_exchange
                    JOIN pro pro1 ON pro1.p_id=pe_p_id1
                    JOIN pro_cate pro_cate1 ON pro_cate1.id=pro1.p_cate
                    JOIN pro pro2 ON pro2.p_id=pe_p_id2
                    JOIN pro_cate pro_cate2 ON pro_cate2.id=pro2.p_cate
                    UNION ALL
                    SELECT 
                    '父子' etype,
                    pf_father_pid pid1,
                    pf_son_pid pid2,
                    '' param1,
                    '' param2,
                    '' remark,
                    '' fromto,
                    pro1.p_comnum outnum1,
                    pro1.p_cate cate1,
                    pro_cate1.cn_name cate1_cn_name,
                    pro_cate1.en_name cate1_en_name,
                    pro2.p_comnum outnum2,
                    pro2.p_cate cate2,
                    pro_cate2.cn_name cate2_cn_name,
                    pro_cate2.en_name cate2_en_name
                    FROM pro_fatherson
                    JOIN pro pro1 ON pro1.p_id=pf_father_pid
                    JOIN pro_cate pro_cate1 ON pro_cate1.id=pro1.p_cate
                    JOIN pro pro2 ON pro2.p_id=pf_son_pid
                    JOIN pro_cate pro_cate2 ON pro_cate2.id=pro2.p_cate
                    UNION ALL
                    SELECT 
                    '通用手工' etype,
                    pemn_p_id1 pid1,
                    pemn_p_id2 pid2,
                    '' param1,
                    '' param2,
                    pemn_remark remark,
                    pemn_frometo fromto,
                    pro1.p_comnum outnum1,
                    pro1.p_cate cate1,
                    pro_cate1.cn_name cate1_cn_name,
                    pro_cate1.en_name cate1_en_name,
                    pro2.p_comnum outnum2,
                    pro2.p_cate cate2,
                    pro_cate2.cn_name cate2_cn_name,
                    pro_cate2.en_name cate2_en_name
                    FROM pro_exchange_model_numidx
                    JOIN pro pro1 ON pro1.p_id=pemn_p_id1
                    JOIN pro_cate pro_cate1 ON pro_cate1.id=pro1.p_cate
                    JOIN pro pro2 ON pro2.p_id=pemn_p_id2
                    JOIN pro_cate pro_cate2 ON pro_cate2.id=pro2.p_cate
                    ";
		$table = "@(".$tableSql.") p";
		$join = [];
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
            switch($field){
                case 'cate1Name':
                    $op = 'eq';
                    $field = 'cate1';
                    $data = $this->cate->like($data);
                    if(empty($data)) $data = [0];
                    break;
                case 'cate2Name':
                    $op = 'eq';
                    $field = 'cate2';
                    $data = $this->cate->like($data);
                    if(empty($data)) $data = [0];
                    break;
            }
        });
		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$where["AND #num"] = [
						"OR" => [
							'outnum1'.($rules['numlike']? '[~]': '') => $val,
							'outnum2'.($rules['numlike']? '[~]': '') => $val,
						]
					];
				break;
			}
		}
        //权限 - 小类
        $cates = \p::cates('BD00');
        if(!\p::isAdmin() && $cates){
			$where['AND #power_cate_and'] = [
			    'OR  #power_cate_or' => [
    			    'cate1'=>explode(',',$cates),
    			    'cate2'=>explode(',',$cates),
    			 ]
			];
        }
		
        $where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($page>0 && $pagesize>0){
			$fields = '*';
			$pages = $this->paging($table,$join,$fields,$where,$page,$pagesize);
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
		
        $rows = $this->db->select($table,$join,$fields,$where);
        foreach($rows as $k=>$row){
            $row['cate1Name'] = $row['cate1_'.LG_NAME];
            $row['cate2Name'] = $row['cate2_'.LG_NAME];
            $rows[$k] = $row;
        }
        //dd($this->db->last());
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $rows
		];
		return $data;
	}


	//检测产品是否允许编辑
	public function canSetPro($pid)
	{
		return [];
		$state = $this->db->get('pro', 'p_state_main', ['p_id'=>$pid]);
		if(in_array($state, ['Y5']))
			return ['msg'=>lg($state.'状态禁止操作')];
		return [];
	}

	//统计非多产品线数量
	public function total()
	{
	    $join = ['[>]pro_cate'=>['p_cate'=>'id']];
	    $where = ['is_moreline'=>0];
		$total = $this->db->count('pro', $join,'*', $where);
		return ['total'=>$total];
	}

	//统计非多产品线通用数量
	public function totalCommon($states)
	{
	    $join = ['[>]pro_cate'=>['p_cate'=>'id']];
	    $where = [
	        'is_moreline'=>0,
	        'p_state_main'=>$states
	    ];
		$total = $this->db->count('pro', $join,'*', $where);
		return ['total'=>$total];
	}


	//审核OE库到产品库需要的信息
	function getBuildProByOeInfo($oe_id){
		$arr = $this->db->get('oe_item(oi)', ["[><]pro_cate(cat)" => ["oi.oe_cate_id" => "id"]], ['oe_id', 'oe_oe', 'oe_cate_id', 'cat_item_type'], ['oe_id'=>$oe_id]);
		if(empty($arr)) exitJson('零件不存在');
		$arr['mod_brand'] = $this->db->select('oe_tag_brand(otb)', ["[><]tag_brand(tb)" => ["otb.otb_tb_id"=>"tb_id"]], ['otb_tb_id(tb_id)', 'tb_'.LG_NAME.'(tb_name)'], ['otb_oe_id'=>$oe_id,'ORDER'=>raw('CONVERT(tb_'.LG_NAME.' USING gbk)'),]);
		//if(empty($arr['mod_brand'])) exitJson('请先完善零件的汽车品牌');
		//已存在的产品
		$arr['haspro'] = $this->db->select('oe_numidx(oen)', ["[><]pro_numidx(pn)" => ["oen.on_pf_id"=>"pn_pf_id", "oen.on_formart"=>'pn_formart'], "[><]pro" => ["pn.pn_p_id"=>"p_id"]], ['p_id', 'p_innum'], ['p_pb_id'=>1, 'on_oe_id'=>$oe_id, 'GROUP'=>'p_id']);
		$arr['pbrands'] = $this->db->select('pro_brand', ['pb_id', 'pb_'.LG_NAME.'(pb_name)']);
		// $arr['cmmakes'] = $this->db->select('cd_make', ['cm_id', 'cm_'.LG_NAME.'(cm_name)'], ['ORDER'=>'cm_id']);
		$arr['material'] = $this->db->select('object', ['o_id', LG_NAME.'(o_name)'], ['o_parent_id'=>16]);
		$arr['item_type'] = $this->db->select('object', ['o_id', LG_NAME.'(o_name)'], ['o_parent_id'=>1]);
		return $arr;
	}

	//批量获取审核OE库到产品库需要的信息
	function getBatchBuildProByOeInfo($oe_id){
		$arr = $this->db->select('oe_item(oi)', ["[><]pro_cate(cat)" => ["oi.oe_cate_id" => "id"]], ['oe_id', 'oe_oe', 'oe_cate_id', 'cat_item_type'], ['oe_id'=>$oe_id,'ORDER'=>['oe_id'=>'DESC']]);
		if(empty($arr)) exitJson('零件不存在');
		$material = $this->db->select('object', ['o_id', LG_NAME.'(o_name)'], ['o_parent_id'=>16]);
		foreach ($arr as $key => &$val) {
			
			$val['haspro'] = $this->db->select('oe_numidx(oen)', ["[><]pro_numidx(pn)" => ["oen.on_pf_id"=>"pn_pf_id", "oen.on_formart"=>'pn_formart'], "[><]pro" => ["pn.pn_p_id"=>"p_id"]], ['p_id', 'p_innum'], ['p_pb_id'=>1, 'on_oe_id'=>$val['oe_id'], 'p_cate'=>$val['oe_cate_id'], 'GROUP'=>'p_id']);

		}
		unset($val);
		return ['pro'=>$arr,'material'=>$material];
	}
	
	//生成指定品牌的物料编码
	function buildProAutoCode($cate_id, $tb_id, $pb_ids = [], $item_type)
	{
		$where = [];
		if($pb_ids) $where['pb_id'] = $pb_ids;
		$arr = $this->db->select('pro_brand', ['pb_id', 'pb_'.LG_NAME.'(pb_name)'], $where);
		foreach($arr as &$bv){
			$bv['innum'] = $this->buildBrandInnum($bv['pb_id'], $cate_id, $tb_id, $item_type);
		}
		return $arr;
	}

	
	//OE审核到产品库
	function buildProByOe($oe_id, $dataArr, $p_id = 0,$returnPro = false)
	{
		$oeInfo = $this->db->get('oe_item(oi)', ["[><]pro_cate(cat)" => ["oi.oe_cate_id" => "id"]], '*', ['oe_id'=>$oe_id]);
		if(empty($oeInfo)) exitJson('零件记录不存在');
		$this->db->Begin();
		$pids = [];
		if($p_id > 0){
			$pcArr = $this->db->get('pro', '*', ['p_id'=>$p_id]);
			if($pcArr['p_cate'] != $oeInfo['oe_cate_id']) exitJson('小类不一致，禁止操作');
			$this->updateProByPoe($p_id, $oe_id);
			$this->addProSynLog([$p_id], 'set', 'text');
		}else{
			$pbrand = [];
			//$tb_id = (int) $dataArr['tb_id'];
			$tb_id = 0;
			// $cm_id = (int) $dataArr['cm_id'];
			$p_material = (int) $dataArr['material'];
			$item_type = (int) $dataArr['item_type'];
			if(empty($item_type)) $item_type = $oeInfo['cat_item_type'];
			if(empty($item_type)) $item_type = 101;
			$cate_id = $oeInfo['oe_cate_id'];
			
			//宜配科技
			$pb_id = 1;
			//FGIO商品唯一性  物料类型+商品品牌+小类+OE+属性（小类定义）
			//事业部商品唯一性  物料类型+商品品牌+汽车品牌+小类+OE+属性（小类定义）
			$uniwhere = ['p_cate'=>$cate_id, 'p_item_type'=>$item_type, 'p_pb_id'=>$pb_id, 'pn_pf_id'=>1, 'pn_formart'=>$oeInfo['oe_oe_format']];
			if($oeInfo['cat_prouni_material']) $uniwhere['p_material'] = $p_material;
			$join = ["[><]pro_numidx(pn)" => ["p.p_id" => "pn_p_id"]];
			$chk = $this->db->get('pro(p)', $join, 'p_innum', $uniwhere);
			if($chk) exitJson('商品：'.$chk.'已存在，去重规则：物料类型+商品品牌+小类+OE+属性[小类定义]');

			$row = $this->buildBrandInnum(1, $cate_id, $tb_id, $item_type);
			if(empty($row['codenum'])) exitJson($row['msg']);
			$comnum = $row['codenum'];
			$seqno = $row['seqno'];

			$comnum_format = formatNum($comnum);
			$opuser = getOpuser();
			$datetime = getNowTime();
			$pcArr = [
				'p_oe_id'=>$oe_id,
				'p_lnk_p_id'=>0,
				'p_pb_id'=>$pb_id,
				'p_tb_id'=>$tb_id,
				// 'p_cm_id'=>$cm_id,
				'p_pf_id'=>1,
				'p_oe'=>$oeInfo['oe_oe'],
				'p_oe_format'=>$oeInfo['oe_oe_format'],
				'p_cate'=>$oeInfo['oe_cate_id'],
				'p_standard_name'=>$oeInfo['oe_cn_name'],
				'p_item_type'=>$item_type,
				'p_comnum'=>$comnum,
				'p_comnum_format'=>$comnum_format,
				'p_innum'=>$comnum,
				'p_innum_format'=>$comnum_format,
				'p_state_main'=>'00',
				'p_material'=>$p_material,
				'p_unit'=>$oeInfo['cat_unit'],
				'p_chassis'=>$oeInfo['oe_chassis'],
				'p_model_year'=>$oeInfo['oe_model_year'],
				'p_engine'=>$oeInfo['oe_engine'],
				'p_pos1'=>$oeInfo['oe_pos1'],
				'p_pos2'=>$oeInfo['oe_pos2'],
				'p_pos3'=>$oeInfo['oe_pos3'],
				'p_pos4'=>$oeInfo['oe_pos4'],
				'p_pos5'=>$oeInfo['oe_pos5'],
				'p_para'=>$oeInfo['oe_para'],
				'p_source_province_id'=>\mvc::$cfg['sourcePcId']['province'],
				'p_source_city_id'=>\mvc::$cfg['sourcePcId']['city'],
				'p_seqno'=>$seqno,
				'p_opuser'=>$opuser,
				'p_create_time'=>$datetime,
				'p_update_time'=>$datetime
			];
			//多语言
			$pcArr = langGetVals($pcArr, $oeInfo, ['p_'=>'oe_', 'p_model_'=>'oe_model_', 'p_des_'=>'oe_des_']);
		
			$mm_ids = $this->db->select('oe_model_link', 'oml_mm_id', ['oml_oe_id'=>$oe_id]);
			$mod3_ids = $this->db->select('oe_model_cn_link', 'oml_mod3_id', ['oml_oe_id'=>$oe_id]);
			$carmodel = new carmodel();
			$vals = $carmodel->formatValsFromModel($mm_ids, $mod3_ids);
			
			
			if($oeInfo['is_engine'] && $vals['cc']) $pcArr['p_cc'] = $vals['cc'];
			if($vals['fuel_type']) $pcArr['p_fuel_type'] = $vals['fuel_type'];

			$this->db->insert('pro', $pcArr);
			$p_id = $this->db->id();
			$pids[] = $p_id;
			$addNumArr = [
				[
					'pn_is_sys'=>0,
					'pn_pf_id'=>1,
					'pn_ismain'=>1,
					'pn_number'=>$pcArr['p_oe'],
					'pn_formart'=>$pcArr['p_oe_format'],
				],
				[
					'pn_is_sys'=>1,
					'pn_pf_id'=>3,
					'pn_number'=>$pcArr['p_innum'],
					'pn_formart'=>$pcArr['p_innum_format'],
				],
				[
					'pn_is_sys'=>1,
					'pn_pf_id'=>2,
					'pn_number'=>$pcArr['p_comnum'],
					'pn_formart'=>$pcArr['p_comnum_format'],
				]
			];
			$this->addNumToPro($p_id, $addNumArr);
			
			$this->updateProByPoe($p_id, $oe_id);
			
			//扩展表
			$ext = [
				'pe_p_id'=>$p_id,
				'pe_opuser'=>$opuser,
				'pe_create_time'=>$datetime,
				'pe_update_time'=>$datetime
			];
			$this->db->insert('pro_ext', $ext);
			
			//零件图片到商品
			$this->syncOePicToPro($p_id);
			$this->addProSynLog($pids, 'add', 'text');
			
		}
		$set = [
			'ck1'=>1,
			'ckuser1'=>$opuser,
			'cktime1'=>$datetime,
			'ckremark1'=>$dataArr['ckremark1'],
			'oe_update_time'=>$datetime,
			'oe_opuser'=>$opuser
		];
		$this->db->update('oe_item', $set, ['oe_id'=>$oe_id]);
		$this->db->End();

		if($returnPro){
			$proArr = $this->db->select('pro', ['p_id', 'p_innum'], ['p_id'=>$pids?:$p_id]);
			return $proArr;
		}

		return $pids;
	}

	//复制产品
	public function copyPro($pb_id, $from_p_id)
	{
		if($pb_id == 1) exitJson('不支持复制到宜配科技商品，请从零件库生成');
		$pcArr = $this->db->get('pro', '*', ['p_id'=>$from_p_id]);
		if(empty($pcArr)) exitJson('商品'.$from_p_id.'记录不存在');
		if($pcArr['p_pb_id'] != 1) exitJson('选中了非宜配科技商品，请重新选择');
		$opuser = getOpuser();
		$datetime = getNowTime();
		
		// 获取暂时的tb_id,默认第一个 注意这是暂时的逻辑
		$list = $this->getProTbList($from_p_id);
		$tb_id = $list[0]['tb_id']?? 1;

		$this->db->Begin();

		// $row = $this->buildBrandInnum($pb_id, $pcArr['p_cate'], $pcArr['p_tb_id'], $pcArr['p_item_type']);
		$row = $this->buildBrandInnum($pb_id, $pcArr['p_cate'], $tb_id, $pcArr['p_item_type']);
		if(empty($row['codenum'])) exitJson($row['msg']);
		$innum = $row['codenum'];
		$seqno = $row['seqno'];

		$format = formatNum($innum);
		$exists = $this->db->get('pro', 'p_id', ['p_innum_format'=>$format]);
		if($exists) exitJson($row['pb_name'].'物料编码：'.$innum.'已被使用');

		$newPcArr = $pcArr;
		unset($newPcArr['p_id']);
		unset($newPcArr['p_pic']);
		if($pcArr['p_pb_id'] == 1) $newPcArr['p_lnk_p_id'] = $pcArr['p_id'];
		$newPcArr['p_pb_id'] = $pb_id;
		$newPcArr['p_innum'] = $innum;
		$newPcArr['p_innum_format'] = $format;
		$newPcArr['p_seqno'] = $seqno;
		$newPcArr['p_opuser'] = $opuser;
		$newPcArr['p_create_time'] = $datetime;
		$newPcArr['p_update_time'] = $datetime;
		$this->db->insert('pro', $newPcArr);
		$p_id = $this->db->id();
		
		//扩展表
		$new = $this->db->get('pro_ext', '*', ['pe_p_id'=>$from_p_id]);
		$new['pe_p_id'] = $p_id;
		$new['pe_opuser'] = $opuser;
		$new['pe_create_time'] = $datetime;
		$new['pe_update_time'] = $datetime;
		$this->db->insert('pro_ext', $new);
		
		//号码
		$addNumArr = [
			[
				'pn_is_sys'=>0,
				'pn_pf_id'=>1,
				'pn_ismain'=>1,
				'pn_number'=>$pcArr['p_oe'],
				'pn_formart'=>$pcArr['p_oe_format'],
				'pn_mk_id'=>''
			],
			[
				'pn_is_sys'=>1,
				'pn_pf_id'=>3,
				'pn_number'=>$newPcArr['p_innum'],
				'pn_formart'=>$newPcArr['p_innum_format']
			],
			[
				'pn_is_sys'=>1,
				'pn_pf_id'=>2,
				'pn_number'=>$pcArr['p_comnum'],
				'pn_formart'=>$pcArr['p_comnum_format']
			]
		];
		$this->addNumToPro($p_id, $addNumArr);
		$this->db->End();
		return $p_id;
	}

	//追加号码
	public function addNumToPro($p_id, $addNumArr)
	{
		$opuser = getOpuser();
		$datetime = getNowTime();
		$this->db->Begin();
		$addArr = [];
		foreach($addNumArr as $add){
			if(!empty($add['pn_pf_id']) && !empty($add['pn_formart'])){
				$add['pn_p_id'] = $p_id;
				$add['opuser'] = $opuser;
				$add['create_time'] = $datetime;
				$add['update_time'] = $datetime;
				$uniwhere = [
					'pn_p_id'=>$add['pn_p_id'],
					'pn_is_sys'=>$add['pn_is_sys'],
					'pn_pf_id'=>$add['pn_pf_id'],	
					'pn_formart'=>$add['pn_formart']
				];
				$exists = $this->db->get('pro_numidx', ['pn_id','pn_ismain'], $uniwhere);
				if(empty($exists)){
					$addArr[] = $add;
				}elseif (!empty($add['pn_ismain']) && $add['pn_ismain'] == 1 && $exists['pn_ismain'] != 1){
					$this->setOeMain($exists['pn_id']);
				}
			}
		}
		if($addArr) $this->db->insert('pro_numidx', $addArr);
		$this->db->End();
		return [];
	}


	
	/**
	  * @method 通过零件库更新数据到商品库(号码 车型 参数)
	  * @param  $p_id  int  [必填] 
	  * @author soul
	  */
	public function updateProByPoe($p_id, $oe_id = 0, $act = '')
	{
		$pcArr = $this->db->get('pro', '*', ['p_id'=>$p_id]);
		if(empty($pcArr)) exitJson($p_id.'记录不存在');
		$opuser = getOpuser();
		$datetime = getNowTime();
		$p_id = $pcArr['p_id'];
		$this->db->Begin();
		
		$addNumArr = [];
		
		//宜配科技追加 OE库数据
		if($pcArr['p_pb_id'] == 1 && !empty($oe_id)){
			//参数
			$rows = $this->db->select('oe_param_val', '*', ['ppv_oe_id'=>$oe_id]);
			foreach($rows as $v){
				$exists = $this->db->get('pro_param_val', 'ppv_ptpa_id', ['ppv_p_id'=>$p_id, 'ppv_ptpa_id'=>$v['ppv_ptpa_id']]);
				if(empty($exists)){
					$add = [
						'ppv_p_id'=>$p_id,
						'ppv_pc_id'=>$pcArr['p_cate'],
						'ppv_ptpa_id'=>$v['ppv_ptpa_id'],
						'ppv_val_int'=>$v['ppv_val_int'],
						'ppv_val_double'=>$v['ppv_val_double'],
						'ppv_val_string'=>$v['ppv_val_string'],
						'ppv_val_smalltxt'=>$v['ppv_val_smalltxt']
					];
					$this->db->insert('pro_param_val', $add);
				}
			}
			
			//号码
			$rows = $this->db->select('oe_numidx', '*', ['on_oe_id'=>$oe_id]);
			foreach($rows as $v){
				$addNumArr[] = [
					'pn_is_sys'=>0,
					'pn_pf_id'=>$v['on_pf_id'],
					'pn_number'=>$v['on_number'],
					'pn_formart'=>$v['on_formart'],
					'pn_from'=>$v['on_from'],
					'pn_mk_id'=>$v['on_mk_id'],
					'pn_isborrow'=>$v['on_isborrow'],
				];
			}

			//国际车型
			$rows = $this->db->select('oe_model_link', '*', ['oml_oe_id'=>$oe_id]);
			foreach($rows as $v){
				$exists = $this->db->get('pro_model_link', 'pml_id', ['pml_p_id'=>$p_id, 'pml_mm_id'=>$v['oml_mm_id']]);
				if(empty($exists)){
					$add = [
						'pml_p_id'=>$p_id,
						'pml_mm_id'=>$v['oml_mm_id'],
						'pml_remark'=>$v['oml_remark'],
						'pml_para'=>$v['oml_para'],
						'pml_from'=>$v['oml_from'],
						'opuser'=>$opuser,
						'create_time'=>$datetime,
						'update_time'=>$datetime
					];
					$this->db->insert('pro_model_link', $add);
				}
			}

			//中国车型
			$rows = $this->db->select('oe_model_cn_link', '*', ['oml_oe_id'=>$oe_id]);
			foreach($rows as $v){
				$exists = $this->db->get('pro_model_cn_link', 'pml_id', ['pml_p_id'=>$p_id, 'pml_mod3_id'=>$v['oml_mod3_id']]);
				if(empty($exists)){
					$add = [
						'pml_p_id'=>$p_id,
						'pml_mod3_id'=>$v['oml_mod3_id'],
						'pml_remark'=>$v['oml_remark'],
						'pml_from'=>$v['oml_from'],
						'opuser'=>$opuser,
						'create_time'=>$datetime,
						'update_time'=>$datetime
					];
					$this->db->insert('pro_model_cn_link', $add);
				}
			}

			// 北美车型
			$rowsBase = $this->db->select('oe_model_na', '*', ['oml_oe_id'=>$oe_id]);
			foreach($rowsBase as $v){
				$exists = $this->db->get('pro_model_na', 'pml_id', ['pml_p_id'=>$p_id, 'pml_base_id'=>$v['oml_base_id'], 'pml_pos'=>$v['oml_pos'], 'pml_attrs'=>$v['oml_attrs'], 'pml_remark'=>$v['oml_remark'] ]);
				if(empty($exists)){
					$this->db->Begin();
					$add = [
						'pml_p_id'=>$p_id,
						'pml_base_id'=>$v['oml_base_id'],
						'pml_veh_id'=>$v['oml_veh_id'],
						'pml_pos'=>$v['oml_pos'],
						'pml_attrs'=>$v['oml_attrs'],
						'pml_remark'=>$v['oml_remark'],
						'pml_from_id'=>$v['oml_from_id'],
						'pml_opuser'=>$opuser,
						'pml_create_time'=>$datetime,
						'pml_update_time'=>$datetime
					];
					$this->db->insert('pro_model_na', $add);
					$id = $this->db->id();
					// 获取所有基本车型下的关联参数表（这个表是用于后续搜索北美车型的基本车型下的一些详细数据）
					$rowParamLink = $this->db->select('oe_model_na_link', '*', ['ops_oe_id'=>$oe_id, 'ops_oml_id'=>$v['oml_id']]);
					$addLink = [];
					foreach($rowParamLink as $v2){
						$addLink[] = [
							'pps_pml_id'=>$id,
							'pps_p_id'=>$p_id,
							'pps_type'=>$v2['ops_type'],
							'pps_cat'=>$v2['ops_cat'],
							'pps_dataid'=>$v2['ops_dataid'],
						];
					}
					if($addLink) $this->db->insert('pro_model_na_link', $addLink);
					$this->db->End();
				}
			}
		}
		if($addNumArr) $this->addNumToPro($p_id, $addNumArr);
		$this->initTagBrand([$p_id]);
		/*if(!empty($oe_id)){
			$this->synProByOe($oe_id,['base','params']);
		}*/
		
		$this->db->End();

		return ['p_id'=>$p_id, 'p_comnum'=>$pcArr['p_comnum']];
	}


	function getProBrandId($value)
	{
		$where =  ['OR'=>[
			'pb_cn_name[~]'=>$value,
			'pb_en_name[~]'=>$value,
			'pb_py_name[~]'=>$value,
			]
		];
		$ids = $this->db->select('pro_brand','pb_id',$where);
		$ids = array_unique($ids);
		return $ids;
	}

	function getProBrand($where= '')
	{
		return $this->db->select('pro_brand',['pro_brand.*', 'pb_'.LG_NAME.'(pb_name)'],$where);
	}

	function getProRelOe($pid,$param = [])
	{		
		if(!$pid) return [];
		$arr = [$pid];	
		$res = $this->db->get('pro','p_lnk_p_id',['p_id'=>$pid]);
		if($res){
			$arr[] = $res;
		}
		$where = ['pn_pf_id'=>1,'pn_p_id'=>$arr,'GROUP'=>'pn_formart'];
		if($param['query']){
			$where['pn_formart[~]']= formatNum($param['query']);
		}
		$result = $this->db->select('pro_numidx',['pn_number(key)','pn_number(value)'],$where);
		return $result;
	}

	function getProMainOe($pid)
	{
		$result = $this->db->get('pro_numidx','pn_formart',['pn_ismain'=>1,'pn_pf_id'=>1,'pn_p_id'=>$pid]);
		return $result;
	}


	/**
	 * @param  [type] $pid 主键ID
	 * @param  [type] $data 数组
	 * @method 保存编码相关的字段
	 * @author zhengweihua 
	 * @copyright 2024-11-26
	 */
	function saveProPack($pid,$data)
	{	
		$packing = new packing();
		$pro = $packing->getProPack($pid);

		if(empty($pro['p_id']))  exitJson('产品不存在');
		$oldPackArr = $pro;

		$packArr = [];
		$extArr = [];
		foreach($data as $field=>$val){
			if(stripos($field, 'pp_') === 0){
				$packArr[$field] = $data[$field];
			}
			if(stripos($field,'ppe_')===0){
				$extArr[$field] = $data[$field];
			}
		}
		$this->db->Begin();

		if(!empty($packArr)){
			$opuser = getOpuser();
			$datetime = getNowTime();
			$packArr['pp_opuser'] = $opuser;
			$packArr['pp_update_time'] = $datetime;
			if($pro['pp_p_id']){
				$this->db->update('pro_pack', $packArr, ['pp_p_id'=>$pid]);
			}else{
				$packArr['pp_create_time'] = $datetime;
				$packArr['pp_p_id'] = $pid;
				$this->db->insert('pro_pack', $packArr);
			}
		}

		if(!empty($extArr)){
			foreach (['inpocket','tag','material'] as $type) {

				$arr =array_filter(explode(',', $extArr['ppe_'.$type]));
				$old = $this->db->select('pro_pack_ext','ppe_pbe_id',['ppe_p_id'=>$pid,'ppe_type'=>$type]);

				$addArr = array_diff($arr,$old);
				$delArr = array_diff($old,$arr);
				if(!$addArr && !$delArr){
					continue;
				}
				if($delArr){
					$this->db->delete('pro_pack_ext',['ppe_p_id'=>$pid,'ppe_pbe_id'=>$delArr,'ppe_type'=>$type]);
				}
				
				if($addArr){
					$addAnyArr = [];
					foreach ($addArr as $key => $val) {
						$addAnyArr[] = [
							'ppe_p_id'=>$pid,
							'ppe_type'=>$type,
							'ppe_pbe_id'=>$val
						];
					}
					$this->db->insert('pro_pack_ext', $addAnyArr);
				}
			}
		}

		$chkFields = [
			'pp_outbox'=>'外盒',
			'pp_inbox'=>'内盒',
			'pp_inpocket_count'=>'内袋装袋数',
			'pp_inbox_count'=>'内盒装盒数',
			'pp_outbox_count'=>'外盒装箱数',
			'pp_weight_per'=>'单个净重',
			'pp_weight_box'=>'整箱毛重',
			'pp_modeltxt'=>'打印车型',
			'pp_weight_pro'=>'单个产品毛重',
			'pp_weight_unit'=>'重量单位',
			'pp_pack_standard' =>'装箱标准',
			'pp_pack_status'=>'包装状态',
			'pp_pack_style'=>'包装方式',
			'pp_outstyle_remark'=>'外包方式备注',
			'ppe_inpocket'=>'内袋',
			'ppe_material'=>'辅料',
			'ppe_tag'=>'标签'
		];
		$changeArr = [];
		$newArr = $packing->getProPack($pid);
		foreach ($chkFields as $field => $name) {
			//转成数字
			if(in_array($field,['pp_inpocket_count','pp_inbox_count','pp_outbox_count','pp_weight_per','pp_weight_box','pp_weight_pro'])){
				$newArr[$field] = (float)$newArr[$field];
			} 
			$old = $oldPackArr['captions'][$field]??$oldPackArr[$field];
			$new = $newArr['captions'][$field]??$newArr[$field];
			if(isset($data[$field]) && $old != $new)
			{
				$changeArr[] = ['field'=>$field,'name'=>$name,'old'=>$old, 'new'=>$new];
			}
		}
		if($changeArr) {
			$logdata = [
				'cl_type'=>'pro',
				'cl_act'=>'edit',
				'cl_dataid'=>$pid,
				'cl_change'=>json_encode(['pack'=>$changeArr], JSON_UNESCAPED_UNICODE),
				'cl_opuser'=>getOpuser(),
				'cl_create_time'=>getNowTime(),
			];
			$this->db->insert('change_log',$logdata);
		}
		$this->addProSynLog([$pid], 'set', 'text');
		$this->db->End();
		return ['key'=>$pid];
	}

	/**
	 * @param  [type] $params
	 * @param  array  $rules
	 * @method 获取包装列表
	 * @author zhengweihua 
	 * @copyright 2024-12-06
	 */
	public function getPackList($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];

		$refiled = [
			'pb_name'=>'pb.pb_'.LG_NAME,
			'opuser'=>'pp.opuser',
			'create_time'=>'pp.update_time',
			'update_time'=>'pp.update_time',
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro(p)';
		$join = [
			"[><]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"],
			"[>]pro_pack(pp)" => ["p.p_id" => "pp_p_id"],
			"[>]pro_pack_ext(ppe)"=>["p.p_id"=>"ppe_p_id"]
		];
		$where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
			switch ($field) {
				case 'pp_tag':
					$field = 'RAW #pp_tag';
					$data = raw(sprintf(" ppe_type='tag' AND ppe_pbe_id IN (SELECT DISTINCT pbe_id FROM pro_brand_ext WHERE pbe_type='tag' AND pbe_val LIKE '%%%s%%')",$data));
					
					break;
				case 'pp_inpocket':
					$field = 'RAW #pp_inpocket';
					$data = raw(sprintf(" ppe_type='inpocket' AND ppe_pbe_id IN (SELECT DISTINCT pbe_id FROM pro_brand_ext WHERE pbe_type='inpocket' AND pbe_val LIKE '%%%s%%')",$data));
					
					break;
				case 'pp_material':
					$field = 'RAW #pp_material';
					$data = raw(sprintf(" ppe_type='material' AND ppe_pbe_id IN (SELECT DISTINCT pbe_id FROM pro_brand_ext WHERE pbe_type='inbox' AND pbe_val LIKE '%%%s%%')",$data));
					
					break;
				case 'pp_inbox':
					$field = 'RAW #pp_inbox';
					$data = raw(sprintf(" pp_inbox IN (SELECT DISTINCT pbe_id FROM pro_brand_ext WHERE pbe_type='inbox' AND pbe_val LIKE '%%%s%%')",$data));
					break;
				case 'pp_outbox':
					$field = 'RAW #pp_outbox';
					$data = raw(sprintf(" pp_outbox IN (SELECT DISTINCT pbe_id FROM pro_brand_ext WHERE pbe_type='outbox' AND pbe_val LIKE '%%%s%%')",$data));
					break;
			}
		});
		
		$where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);

		$where['GROUP'] ='p.p_id';
		$where['pp.pp_p_id[>]'] = 0;
		$where['ppe.ppe_p_id[>]'] = 0;
		if($page>0 && $pagesize>0){
			$fields = ["*"];
			$pages = $this->paging($table,$join,$fields,$where,$page,$pagesize);
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
		$fields = ["pp.*","p.p_id","p_innum","p_pb_id","pb_".LG_NAME.'(pb_name)',"ppe.*"];
		
		$arr = $this->db->select($table,$join,$fields,$where);
		if(!empty($arr))
		{		
			$pidArr = array_column($arr,'p_id');
			//ext属性
			$ext = $this->db->select('pro_pack_ext',['[><]pro_brand_ext'=>['ppe_pbe_id'=>'pbe_id']],['ppe_p_id','ppe_type','pbe_id_str'=>raw('GROUP_CONCAT(ppe_pbe_id SEPARATOR \'\r\n\')'),'pbe_val_str'=>raw('GROUP_CONCAT(pbe_val SEPARATOR \'\r\n\')')], ['ppe_p_id'=>$pidArr,'GROUP'=>['ppe_p_id','ppe_type']]);
			$extArr = [];
			if($ext){
				foreach ($ext as $key => $val) {
					$extArr[$val['ppe_p_id']][$val['ppe_type']] = $val;
				}
			}
			//外盒
			$outArr = array_filter(array_unique(array_column($arr,'pp_outbox')));
			if($outArr){
				$outBrandArr = $this->db->select('pro_brand_ext',['pbe_id','pbe_val'], ['pbe_id'=>$outArr]);
				$outBrandArr = array_column($outBrandArr,'pbe_val','pbe_id');
			}

			//内盒
			$inArr = array_filter(array_unique(array_column($arr,'pp_inbox')));
			if($inArr){
				$inBrandArr = $this->db->select('pro_brand_ext',['pbe_id','pbe_val'], ['pbe_id'=>$inArr]);
				$inBrandArr = array_column($inBrandArr,'pbe_val','pbe_id');
			}

			$collocation = new collocation();
			foreach($arr as &$v)
			{
				$pp_pack_status = $collocation->getRowByKey($v['pp_pack_status'])[cateName()];
				$pp_weight_unit = $collocation->getRowByKey($v['pp_weight_unit'])[cateName()];
				$v['captions'] = [
					'pp_tag' => $extArr[$v['p_id']]['tag']['pbe_val_str']??'',
					'pp_inpocket' => $extArr[$v['p_id']]['inpocket']['pbe_val_str']??'',
					'pp_material'=> $extArr[$v['p_id']]['material']['pbe_val_str']??'',
					'pp_outbox'=> $outBrandArr[$v['pp_outbox']]??'',
					'pp_inbox'=>$inBrandArr[$v['pp_inbox']]??'',
					'pp_pack_status'=>$pp_pack_status,
					'pp_weight_unit'=>$pp_weight_unit
				];
			}
		}
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	/**
	 * @param  [type] $ids
	 * @method 删除包装
	 * @author zhengweihua 
	 * @copyright 2024-12-06
	 */
	public function delPack($ids)
	{
		if(!is_array($ids)) $ids = explode(',',$ids);
		$this->db->begin();
        $this->db->delete('pro_pack',['pp_p_id'=>$ids]);
		$this->db->delete('pro_pack_ext',['ppe_p_id'=>$ids]);
		$this->db->end();
		return true;
	}


	public function deleteElementRows($cfg,$ids)
	{
		if(!is_array($ids)){
            $ids = explode(',',$ids);
        }
		//旧数据
		$itemsArr = $this->db->select($cfg['table'],'*',[$cfg['key']=>$ids]);
		//当前element的p_id字段
		
		$mainkey = $this->defaultFieldName[$cfg['elename']]['mainkey'];
	
		if(!$mainkey) return exitJson(false,'删除错误');

		if(!is_array($mainkey)) $mainkey = [$mainkey];
		$changeArr = [];
 		foreach ($itemsArr as $item) 
		{	
			foreach ($mainkey as $pidfield) {
				$pid = $item[$pidfield];
				$changeArr[$pid][] = $item;
			}
		}
		$logdata = [];
		$elename =  str_replace('pro_','',$cfg['elename']);
		if($changeArr)
		{
			foreach ($changeArr as $pid => $arr) {
		
				$logdata[] = [
					'cl_type'=>'pro',
					'cl_act'=>'del',
					'cl_dataid'=>$pid,
					'cl_change'=>json_encode([$elename=>$arr], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
			}
		}
		
		$this->db->Begin();
		if($logdata) $this->db->insert('change_log',$logdata);
	
		$this->db->delete($cfg['table'],[$cfg['key']=>$ids]);
		$this->db->End();

		return true;
	}

	/**
	 * @param  Array $cfg
	 * @param  int $id
	 * @param  string $field
	 * @param  string $value
	 * @method 产品相关属性的编辑操作
	 * @author zhengweihua 
	 * @copyright 2024-12-11
	 */
	public function editElementCell($cfg,$id,$field,$value)
	{	
		$default = $this->defaultFieldName;

		$curField = $default[$cfg['table']];
		if(!$curField) return [];
		if(!is_array($default[$cfg['table']]['p_id'])) $default[$cfg['table']]['p_id'] = [$default[$cfg['table']]['p_id']];

		$searchFields = array_merge([$field],$default[$cfg['table']]['p_id']);
		$old = $this->db->get($cfg['table'],$searchFields,[$cfg['key']=>$id]);
		$this->db->Begin();
		if($value!=$old[$field]){
			$elename =  str_replace('pro_','',$cfg['elename']);
			$changeArr[] = [$cfg['key']=>$id,'field'=>$field,'name'=>$default[$cfg['table']][$field],'new'=>$value,'old'=>$old[$field]];
			
			foreach ($default[$cfg['table']]['p_id'] as $pid) {
				$logdata[] = [
					'cl_type'=>'pro',
					'cl_act'=>'edit',
					'cl_dataid'=>$old[$pid],
					'cl_change'=>json_encode([$elename=>$changeArr], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
			}
			$this->db->insert('change_log',$logdata);
		}
		$updata = [$field=>$value];
		if(isset($elecfg['fields']['opuser'])){
			$updata[$elecfg['fields']['opuser']] = getOpuser();
		}
		if(isset($elecfg['fields']['update_time'])){
			$updata[$elecfg['fields']['update_time']] = getNowTime();
		}
		$this->db->update($cfg['table'],$updata,[$cfg['key']=>$id]);
		$this->db->End();
		return [];
	}


	function getBaseTj()
	{
		$arr = [];
		$arr['work-data'] = $this->db->count('work_data_list');
		//$arr['work-ask'] = $this->db->count('work_ask');
		//$arr['work-oe'] = $this->db->count('work_oe');
		$arr['pro'] = $this->db->count('pro');
		$arr['oepro'] = $this->db->count('oe_item');
		return $arr;
	}

	
	//从宜配数据参数中格式化系统参数值
	function formatParaFromTcd($cat_id, $pvals, $p_id = 0)
	{
		$rows = $this->db->select('part_param', ['ptpa_id', 'tcd_name', 'ptpa_type', 'ptpa_decimal'], ['ptpa_cate_id'=>$cat_id, 'tcd_name[!]'=>'']);
		$labels = [];
		foreach($rows as $rv){
			$rv['tcd_names'] = [];
			foreach(explode(',', strtr(strtoupper($rv['tcd_name']), [';'=>',', '；'=>',', '，'=>','])) as $nv){
				$rv['tcd_names'][] = trim($nv);
			}
			$labels[$rv['ptpa_id']] = $rv;
		}
		$paras = [];
		$pos = [];
		//获取当前分类限定的位置
		$catinfo = $this->db->get('pro_cate','*',['id'=>$cat_id]);
		foreach($pvals as $pv){
			if($pv['cn_name']=='安装位置'){
				foreach (\mvc::$cfg['PosKeyVal'] as $poskey => $arr) {
					$posval = trim($pv['val']);
					$catpos = $catinfo['cat_'.$poskey]?explode(',',$catinfo['cat_'.$poskey]):[];
					if($arr[$posval] && $catpos && in_array($arr[$posval],$catpos)){
						$pos['p_'.$poskey][] = $arr[$posval];
					}
				}
				continue;
			}
			foreach($labels as $lk=>$lv){
				if(($pv['name'] && in_array(strtoupper($pv['name']), $lv['tcd_names'])) || ($pv['cn_name'] && in_array(strtoupper($pv['cn_name']), $lv['tcd_names']))){
					if($lv['ptpa_type'] == 'double' && $lv['ptpa_decimal']){
						$pv['val'] = number_format($pv['val'], $lv['ptpa_decimal']);
					}
					$paras[] = [
						'ppv_p_id'=>$p_id,
						'ppv_pc_id'=>$cat_id,
						'ppv_ptpa_id'=>$lk,
						'ppv_val_'.$lv['ptpa_type']=>$pv['val']
					];
					break;
				}
			}
		}
		return ['paras'=>$paras,'pos'=>$pos];
	}

	//检测引用状态后决定是否删除
	function deleteRowsByChk($elename,$ids)
	{	
		if(!$elename && !$ids) return [];

		if(!is_array($ids)){
            $ids = explode(',',$ids);
        }
		$where = [];
		switch ($elename) {
			case 'pro_brand':
				$arr = $this->db->select('pro_brand',['[><]pro'=>['pb_id'=>'p_pb_id']],'pb_id',['p_pb_id'=>$ids]);
				$where = ['pb_id'=>$ids];
				break;
			case 'pro_factory':
				$where = ['pf_id'=>$ids];

				$arr = $this->db->select('work_data_item_format','wdif_pf_id',['wdif_pf_id'=>$ids]);
				if(!empty($arr)) return exitJson('402', '已有数据工单号码引用所选号码厂商，不可删除');

				$arr = $this->db->select('oe_numidx','on_pf_id',['on_pf_id'=>$ids]);
				if(!empty($arr)) return exitJson('402', '已有新增待进入库参考号引用所选号码厂商，不可删除');

				$arr = $this->db->select('pro_numidx','pn_pf_id',['pn_pf_id'=>$ids]);
				if(!empty($arr)) return exitJson('402', '已有参考号引用所选号码厂商，不可删除');

				$arr = $this->db->select('supplier_pro','spr_pf_id',['spr_pf_id'=>$ids]);
				if(!empty($arr)) return exitJson('402', '已有供应商目录引用所选号码厂商，不可删除');

				$arr = $this->db->select('pro_factory',['[><]pro'=>['pf_id'=>'p_pf_id']],'pf_id',['p_pf_id'=>$ids]);
				break;
		}
		
		if(!empty($arr)) 
			return exitJson('402', '已有产品引用该选项，不可删除');

		if($where){
			$this->db->Begin();
			$this->db->delete($elename,$where);
			$this->db->End();
		}	
	
		return [];
	}


	function seachAllNum($number, $fac = '', $req = [])
	{
		$arr = ['pro'=>[], 'super'=>[], 'work'=>[], 'poe'=>[], 'oe_nums'=>[]];
		$format = reSearchNum($number);
		if(empty($format)) return $arr;

		$pfid = 0;
		if($fac){
			$factory = new factory();
			$pfid = $factory->getFacId($fac);
		}
		$islike = $req['islike']?'[~]':'';
		//商品库
		$table = 'pro(p)';
		$join = [
			"[><]pro_cate(cat)" => ["p.p_cate" => "id"],
			"[><]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"],
			"[><]pro_cate(pcat)" => ["cat.parent_id" => "id"],
			"[><]pro_numidx(num)" => ["p.p_id" => "pn_p_id"],
			"[<]pro_factory(pf)" => ["num.pn_pf_id" => "pf_id"],
		];
		$fields = ['pcat.'.cateName().'(pcat_name)', 'cat.'.cateName().'(cat_name)', 'pn_p_id(p_id)', 'p_innum', 'p_comnum', 'pb_'.LG_NAME.'(pb_name)', 'pf_name', 'pn_number'];
        $where = ['pn_formart'.$islike=>$format, 'GROUP'=>'p_id'];
		if($pfid) $where['pn_pf_id'] = $pfid;
		$arr['pro'] = $this->db->select($table, $join, $fields, $where);
		
		//零件供应商
		$join = [
			"[><]supplier(sup)" => ["spr.spr_sup_id" =>"sup_id"],
			"[><]oe_numidx(woi)" => ["spr.spr_oe_id" =>"on_oe_id"]
		];
		$where = ['on_formart'.$islike=>$format, 'ORDER'=>'sup_name', 'GROUP'=>['sup_id']];
		if($pfid) $where['on_pf_id'] = $pfid;
		$supnameField = \p::has('C500','view')? 'sup_name': 'sup_code as sup_name';
		$arr['super'] = $this->db->select('supplier_pro(spr)', $join, ['sup_id', $supnameField, 'sup_code','spr_id'], $where);


		$comnum = array_column($arr['pro'],'p_comnum');
		//事业部
		if($comnum)
		{
			$join = [
				"[><]pro"=>['plc.plc_p_id'=>'p_id'],
				"[><]company(cmp)" => ["plc.plc_com_id" => "com_id"],
			];
			$arr['company'] = $this->db->select('pro_link_company(plc)',$join,['plc_id','plc_p_id','com_id','com_'.LG_NAME.'(com_name)'],['p_comnum_format'=>$comnum,'GROUP'=>'plc_com_id','ORDER'=>'plc_com_id']);
		}


		if($format)
		{	
			$hasEdc = \p::fieldhas('1200','edc');
			$hasHdc = \p::fieldhas('1200','hdc');

			$arr['resource'] =[];
			$rcaApi = new rcaApi();
			$ypRcaApi = new ypRcaApi();
			foreach ($format as $numb) {
				$search = [
					'input'=>$numb,
					'priority'=>1,
					'fromPlatform'=>'web'
				];
				//文档资源
				if($hasEdc)
				{
					$resarr = $rcaApi->Get('resources/searchbyindex',[], $search);
					//都是同一个查询号码因此返回一条记录
					if($resarr['data'])
					{	
						$arr['resource'][$number] = [
							'number'=>$numb,
							'name'=>implode(',',array_unique(array_column($resarr['data'], 'resourceFactoryName'))) 
						];	
					}
				}
				if($hasHdc)
				{
					$resarr = $ypRcaApi->Get('resources/searchbyindex',[], $search);
					if($resarr['data'])
					{	
						$arr['ypresource'][$number] = [
							'number'=>$numb,
							'name'=>implode('<br>',array_unique(array_column($resarr['data'], 'resourceFactoryName'))) 
						];	
					}
				}
				//宜配资源
			}
		}
		//数据单
		$join = [
			'[><]work_data_item(wdi)'=>['wdif.wdif_wdi_id'=>'wdi_id'],
			'[><]work_data_list(wdl)'=>['wdi.wdi_wdlist_id'=>'wdlist_id']
		];
		$where = ['wdif_type'=>'Number', 'wdif_search'.$islike=>$format, 'GROUP'=>['wdlist_id'], 'ORDER'=>['wdi_id'=>'DESC']];
		if($pfid) $where['wdif_pf_id'] = $pfid;
		$arr['work'] = $this->db->select('work_data_item_format(wdif)', $join, ['wdlist_id', 'wdlist_title'], $where);
		
		
		//零件库
		$join = [
			
			'[><]oe_item(woe)'=>['woi.on_oe_id'=>'oe_id'],
			"[><]pro_factory(pf)" => ["woe.oe_pf_id" => "pf_id"],
			"[<]pro_factory(pf2)" => ["woi.on_pf_id" => "pf_id"],
			'[><]pro_cate(cate)'=>['woe.oe_cate_id'=>'id']
		];
		$where = ['on_formart'.$islike=>$format, 'GROUP'=>['oe_id'], 'ORDER'=>['oe_id'=>'DESC']];
		if($pfid) $where['on_pf_id'] = $pfid;
		$arr['poe'] = $this->db->select('oe_numidx(woi)', $join, ['oe_id',cateName().'(cate_name)','pf.pf_name', 'oe_oe', 'pf2.pf_name(pf_name_s)', 'on_number'], $where);

		$arr['tb_brands'] = [];
		$arr['oe_nums'] = [];
		if($arr['poe']){
			$arr['tb_brands'] = $this->db->select('oe_tag_brand(otb)', ['[><]tag_brand(tb)'=>['otb.otb_tb_id'=>'tb_id']], ['tb_id', 'tb_'.LG_NAME.'(tb_name)'], ['otb_oe_id'=>array_column($arr['poe'], 'oe_id'), 'GROUP'=>'tb_id', 'ORDER'=>raw('CONVERT(tb_'.LG_NAME.' USING gbk)')]);
			
			$join = [
				'[>]oe_numidx_tag_brand(otb)'=>['oen.on_id'=>'ontb_on_id'],
				'[>]tag_brand(tb)'=>['otb.ontb_tb_id'=>'tb_id'],
			];
			$arr['oe_nums'] = $this->db->select('oe_numidx(oen)', $join, ['on_number', 'oe_makes'=>raw('group_concat(tb_cn_name)')], ['on_pf_id'=>1, 'on_oe_id'=>array_column($arr['poe'], 'oe_id'), 'GROUP'=>'on_formart', 'ORDER'=>'on_formart']);
		}
		return $arr;
	}


	function seachEpcNum($number, $req = [])
	{
		$arr = [];
		$apiPost = ['type'=>'etk', 'number'=>json_encode([['factory'=>'OE', 'number'=>$number]], JSON_UNESCAPED_UNICODE)];
		$ypApi = new ypApi();
		$res = $ypApi->Get('tcd/checkNumberData', [], $apiPost);
		if($res['data']['data']['etk']){
			$arr = $res['data']['data']['etk']['pros'][0];
		}
		//dump($arr);
		return $arr;
	}

	
	/**
	 * @method  初始化商品的品牌标签
	 * @param  $ids [int/array] 为空则整库
	 * @copyright
	 */
	function initTagBrand($ids = [])
	{
		if(!empty($ids)){
			if(!is_array($ids)) $ids = [$ids];
			$ids = array_map(function($id) {return (int) $id; }, $ids);
		}else{
			$ids = $this->db->select('pro', 'p_id');
		}
		$chus = array_chunk($ids, 1000);
		$this->db->Begin();
		foreach($chus as $idArr){
			$hasArr = [];
			//已有的
			$rows = $this->db->select('pro_tag_brand', ['ptb_p_id(p_id)', 'ptb_tb_id(tb_id)'], ['ptb_p_id'=>$idArr]);
			foreach($rows as $v){
				$hasArr[$v['p_id']][$v['tb_id']] = $v['tb_id'];
			}

			//车型关联的
			$newArr = [];

			//中国车型
			$join =[
				'[><]m_cn_model(cm)'=>['ol.pml_mod3_id'=>'mod3_id'],
				'[><]tag_brand_cnbrand(tb)'=>['cm.brand_id'=>'tbm_brand_id'],
			];
			$rows = $this->db->select('pro_model_cn_link(ol)', $join, ['pml_p_id(p_id)', 'tbm_tb_id(tb_id)'], ['pml_p_id'=>$idArr, 'GROUP'=>['pml_p_id', 'tbm_tb_id']]);
			foreach($rows as $v){
				$newArr[$v['p_id']][$v['tb_id']] = $v['tb_id'];
			}

			//国际车型库
			$join =[
				'[><]m_model(cm)'=>['ol.pml_mm_id'=>'mm_id'],
				'[><]tag_brand_make(tb)'=>['cm.mm_mk_id'=>'tbm_mk_id'],
			];
			$rows = $this->db->select('pro_model_link(ol)', $join, ['pml_p_id(p_id)', 'tbm_tb_id(tb_id)'], ['pml_p_id'=>$idArr, 'GROUP'=>['pml_p_id', 'tbm_tb_id']]);
			foreach($rows as $v){
				$newArr[$v['p_id']][$v['tb_id']] = $v['tb_id'];
			}

			foreach($idArr as $id){
				//车型匹配为空的跳过，人工加入
				if(empty($newArr[$id])) continue;
				$old = $hasArr[$id] ? $hasArr[$id]: [];
				$add = []; $del = [];
				foreach($newArr[$id] as $tbid){
					if(!$old[$tbid]) $add[$tbid] = ['ptb_p_id'=>$id, 'ptb_tb_id'=>$tbid];
				}
				$del = array_diff($old, $newArr[$id]);
				if($add) $this->db->insert('pro_tag_brand', array_values($add));
				if($del) $this->db->delete('pro_tag_brand', ['ptb_p_id'=>$id, 'ptb_tb_id'=>$del]);
			}
		}
		$this->db->End();
		return [];
	}

	/**
	 * 获取商品供应商
	 */
	function getListSupplier($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];
		$refiled = [
			'pb_name'=>'pb.pb_'.LG_NAME,
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);
		$table = 'pro(p)';
		$join = [
			"[><]pro_numidx(pn)" => ["p.p_id" => "pn_p_id"],
			"[><]supplier_pro(spr)" => ["p.p_cate"=>"spr_cat_id","pn.pn_pf_id" => "spr_pf_id","pn.pn_formart" => "spr_format"],
			"[><]pro_supplier(psu)" => ["spr.spr_id" => "psu_spr_id"],
			"[><]pro_brand(pb)" => ["psu.psu_pb_id" => "pb_id"],
			"[><]supplier(sup)" => ["spr.spr_sup_id" => "sup_id"],
		];
		
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
        });
		
		if(!empty($params['keys'])) $where['p_id'] = explode(',', $params['keys']);
		if(!empty($params['p_id'])) $where['p_id'] = $params['p_id'];
		

		$where['RAW #Brand'] = raw(sprintf(" CASE WHEN p_lnk_p_id=0 THEN TRUE ELSE psu_pb_id = p_pb_id END"));

        $where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($page>0 && $pagesize>0){
			$fields = '*';
			$pages = $this->paging($table,$join,$fields,$where,$page,$pagesize);

			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
		$fields = ['spr.*','psu.*','sup.sup_name','sup.sup_code','pb.pb_'.LG_NAME.'(pb_name)'];
        $arr = $this->db->select($table,$join,$fields,$where);

		$collocation = new collocation();
		foreach($arr as &$v){

			$v['captions'] = [
				'spr_price_status'=>$v['spr_price_status']=='Y'	? '有效': '无效',
				'spr_has'=>$v['spr_has']=='Y'	? '是': '否',
				'spr_hasample'=>$v['spr_hasample']=='Y'	? '是': '否',
			];
			$v['captions']['psu_bgdw'] = $collocation->getRowByKey($v['psu_bgdw'])[cateName()];;
			$v['captions']['spr_material'] = '';
			if($v['spr_material']){
				$v['captions']['spr_material'] = $collocation->getRowByKey($v['spr_material'])[cateName()];
			}	
		}
		unset($v);
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	/**
	 * @param  [type] $oe_id
	 * @param  [type] $data
	 * @method 更新商品库参数、位置信息
	 * @author zhengweihua 
	 * @copyright 2025-01-10
	 */
	function setProParaAndPos($p_id,$data)
	{
		if(!$data['paras'] && !$data['pos']) return [];
		$paramModel = new param();
		$this->db->Begin();
		if($data['paras']) $paramModel->setParam($data['paras'],$p_id);
		if($data['pos']){
			$updateArr = [];
			foreach ($data['pos'] as $key => $val) 
			{
				$updateArr[$key] = implode('/',$val);
			}
			$this->db->update('pro',$updateArr,['p_id'=>$p_id]);
		}

		$this->db->End();
		return [];
		
	}

	function getProParams($p_id)
	{
		$table = 'pro(p)';
		$join = [
			"[>]oe_item(oe)" => ["p.p_oe_id" => "oe_id"],
		];
		$field = ['p.p_id','p.p_para','p.p_oe_id','oe.oe_chkpro_info'];
		$data = $this->db->get($table,$join,$field,['p_id'=>$p_id]);
		if($data){
			$data['p_para'] = $data['p_para']?json_decode($data['p_para'],true):[];
			$data['oe_chkpro_info'] = $data['oe_chkpro_info']?json_decode($data['oe_chkpro_info'],true):[];
		}
		return $data;
	}

	/**
	 * @param  int $fileid
	 * @param int  $pid
	 * @method 设置主图
	 * @author zhengweihua 
	 * @copyright 2025-01-14
	 */
	public function setProMainPic($fileid,$pid,$type)
	{
		//无需文件ID,支持自动设置
		if(empty($fileid)){
			$main = $this->db->get('pro_pic', 'pic_fileid', ['pic_p_id'=>$pid, 'pic_type'=>$type, 'pic_ismain'=>1]);
			if($main) return [];
			$fileid = $this->db->get('pro_pic', 'pic_fileid', ['pic_p_id'=>$pid, 'pic_type'=>$type, 'ORDER'=>['pic_fileid']]);
		}
		$fileid = (int) $fileid;
		$this->db->Begin();
		if($type=='img')
		{
			$this->db->update('pro',['p_pic'=>$fileid],['p_id'=>$pid]);
		}
		if($type=='line')
		{
			// $this->db->update('pro',['pro_linepic'=>$fileid],['p_id'=>$pid]);
		}
		$this->db->update('pro_pic',['pic_ismain'=>0],['pic_fileid[!]'=>$fileid,'pic_p_id'=>$pid,'pic_type'=>$type]);
		$this->db->update('pro_pic',['pic_ismain'=>1],['pic_fileid'=>$fileid,'pic_p_id'=>$pid,'pic_type'=>$type]);
		$this->db->End();
		return [];
	}

	/**
	 * @param  [type] $sup_id
	 * @param  [type] $fileid
	 * @param  [type] $pid
	 * @method 变更图片供应商
	 * @author zhengweihua 
	 * @copyright 2025-01-14
	 */
	public function setPicLineSup($pid,$sup_id,$fileid = [])
	{
		$this->db->update('pro_pic',['pic_sup_id'=>$sup_id],['pic_fileid'=>$fileid,'pic_p_id'=>$pid]);
		return [];
	}

	/**
	 * @param  [type] $params
	 * @param  array  $rules
	 * @method 获取零件图片列表
	 * @author zhengweihua 
	 * @copyright 2025-01-14
	 */
	public function getListPic($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? 'pic_ismain': $params['sidx'];
		$sord = empty($params['sord'])? 'desc': $params['sord'];
		$orderby = $params['orderby'];

		$table = 'pro_pic(pic)';
		$join = [
			"[><]pro(pro)" => ["pic.pic_p_id" => "p_id"],
			"[><]files(file)"=>["pic.pic_fileid"=>"fileid"],
			"[>]supplier(sup)"=>['pic.pic_sup_id'=>'sup_id'],
			"[>]adm_user(au)"=>['pic.pic_opuser'=>'au_id'],
			'[>]object_tags_link(otl)' => [
				'pic.pic_fileid' => 'otl_val_id',
				'AND' => "otl.otl_table = 'pro' AND otl.otl_type = 'pic'"
			]
		];
		
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			if($field == 'main_pic'){
				$op = 'RAW_'.$field;
				if($data =='Y'){
					$data = raw("pic_ismain =1 and pic_type='img'");
				}else{
					$data = raw("pic_ismain =0 and pic_type='img'");
				}
			}

			if($field == 'main_linepic'){
				$op = 'RAW_'.$field;
				if($data =='Y'){
					$data = raw("pic_ismain =1 and pic_type='line'");
				}else{
					$data = raw("pic_ismain =0 and pic_type='line'");
				}
				
			}

			if($field == 'pic_tags'){
				$field = 'otl_o_id';
			}
        });
		if(!empty($params['type'])) $where['pic_type'] = $params['type'];
		if(!empty($params['keys'])) $where['pic_fileid'] = explode(',', $params['keys']);
		if(!empty($params['pid'])) $where['pic_p_id'] = $params['pid'];
		if($params['type']!='video'){
			$where['pic.pic_status'] = 1;
		}
		
		$where['GROUP'] = ['pic.pic_fileid'];

        $where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($page>0 && $pagesize>0){
			$fields = '*';
			$pages = $this->paging($table,$join,$fields,$where,$page,$pagesize);
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
		
		$where['ORDER'] = raw("CASE WHEN pic_from=99 THEN -1 WHEN pic_from=1116 THEN 0 ELSE 1 END ASC,pic_ismain DESC,pic_sort ASC");
		
		$fields = ['pic.*','sup_name','file.*','p_oe','au_name'];
        $arr = $this->db->select($table,$join,$fields,$where);
		$collocation = new collocation();
		$collArr = $collocation->getCollItems('other');
		$picStyle = ['selfup'=>'自上传','oem'=>'原厂','competitor'=>'竞品','other'=>'其他'];
		$LANG= \mvc::$cfg['LANGS'];
		if($arr){
			$alioss = new alioss();
			foreach ($arr as $key => &$val) {
				// 获取图片标签
				$tagJoin = [
					'[>]object(o)' => ['otl_o_id'=>'o_id']
				];
				$tagWhere = ['otl_table'=>'pro','otl_type'=>'pic','otl_val_id'=> $val['pic_fileid']];
				$picTagRes = $this->db->select('object_tags_link',$tagJoin,'o.'.LG_NAME,$tagWhere);

				if($val['filetype']=='image' && $val['pic_type']=='img'){
					$val['bigImg'] = $val['filepath'].'/'.$val['filebasename'].'big.'.$val['fileextname'];
					$val['smallImg'] = $val['filepath'].'/'.$val['filebasename'].'small.'.$val['fileextname'];
				}elseif ($val['filetype']=='video' && $val['file_isoss']==1) {
					$val['fileurl'] =  \model\alioss::getPublicUrl($val['file_oss_path']);
				}
				
				$val['main_pic'] = $val['pic_type']=='img' && $val['pic_ismain']?'Y':'';
				$val['main_linepic'] = $val['pic_type']=='line' && $val['pic_ismain']?'Y':'';
				$val['captions'] = [
					'pic_opuser'=>$val['au_name'],
					'pic_from'=>$collArr[$val['pic_from']],
					'pic_style'=>$picStyle[$val['pic_style']]??'',
					'pic_lang'=>$LANG[$val['pic_lang']]['name']??'',
					'pic_tags'=>implode(',',$picTagRes),
				];

			}
			unset($val);
		}
		
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	public function delProPic($param)
	{	
		if($param['ids'] && $param['pid'] && $param['type']){
			$ids = explode(',',$param['ids']);
			$this->db->delete('pro_pic',['pic_p_id'=>$param['pid'],'pic_fileid'=>$ids,'pic_type'=>$param['type']]);
			$this->setProMainPic(0, $param['pid'], $param['type']);
		}
		return [];
	}

	/**
	 * @param  int $p_id
	 * @method 产品详情页数据获取
	 * @author zhengweihua 
	 * @copyright 2025-02-11
	 */
	public function getDetail($p_id)
	{
		$table = 'pro(p)';
		$join = [
			"[>]pro_cate(cat)" => ["p.p_cate" => "id"],
			"[>]pro_cate(pcat)" => ["cat.parent_id" => "id"],
			"[><]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"],
			"[>]pro_ext(ext)" => ["p.p_id" => "pe_p_id"],
			"[>]oe_item(oe)" => ["p.p_oe_id" => "oe_id"],
			"[>]pro_factory(fac1)" => ["oe.oe_pf_id" => "pf_id"],
			"[>]pro_factory(fac)" => ["p.p_pf_id" => "pf_id"],
			"[>]adm_user(au)"=>['p.p_opuser'=>'au_id'],
			"[>]tag_brand(tb)"=>['p.p_tb_id'=>'tb_id']
		];

		$fields = ['cat.is_engine','cat.id(cat_id)', 'cat.cat_pos1','cat.cat_pos2','cat.cat_pos3','cat.cat_pos4','cat.cat_pos5','cat.cat_hsbm','cat.cat_invoice','cat.cat_ktsl', 'cat.cat_unit_customs','pcat.'.cateName().'(pcat_name)', 'cat.'.cateName().'(cat_name)', 'cat.cn_name(cat_name_cn)','cat.en_name(cat_name_en)', 'pb_'.LG_NAME.'(pb_name)','p.*', 'ext.*','fac.pf_name','oe.oe_id','fac1.pf_name(oe_pf_name)','oe.oe_chkpro_info', 'oe_etk_info','oe_etk_epa_id','oe.oe_chkpro_id','oe.oe_chkpro_from','au_name','tb_'.LG_NAME.'(tb_name)','oe_amount(p_amount)'];
        $where = ['p_id'=>$p_id];
		$arr = $this->db->get($table,$join,$fields,$where);

		if($arr)
		{
			
			$arr['p_para'] = empty($arr['p_para'])? []:json_decode($arr['p_para'], true);
		
			$arr['cate_posArr'] = [
				'cat_pos1'=>$arr['cat_pos1']?explode(',',$arr['cat_pos1']):[],
				'cat_pos2'=>$arr['cat_pos2']?explode(',',$arr['cat_pos2']):[],
				'cat_pos3'=>$arr['cat_pos3']?explode(',',$arr['cat_pos3']):[],
				'cat_pos4'=>$arr['cat_pos4']?explode(',',$arr['cat_pos4']):[],
				'cat_pos5'=>$arr['cat_pos5']?explode(',',$arr['cat_pos5']):[],
			];

			$collocation = new collocation();
			$collArr = $collocation->getCollItems('pro');

			$pe_category = [];
			if(!empty($arr['pe_category'])){
				foreach(explode(',', $arr['pe_category']) as $t){
					$pe_category[] = $collArr[$t];
				}
			}
			//省市县
            $pctIdArr = [];
            $pctIdArr[] = $arr['p_source_province_id'];
            $pctIdArr[] = $arr['p_source_city_id'];  

            if($pctIdArr){
                $allPctArr = $this->db->select('province_city',['pc_id','pc_name'],['pc_id'=>array_unique($pctIdArr)]);
                $allPctArr = array_column($allPctArr,'pc_name','pc_id');
            }
			$arr['captions']['p_source_province_id'] = $allPctArr[$arr['p_source_province_id']];
			$arr['captions']['p_source_city_id'] = $allPctArr[$arr['p_source_city_id']];
			$arr['captions']['pe_category'] = implode(',', $pe_category);
			$arr['captions']['p_opuser'] = $arr['au_name'];
			// $arr['captions']['p_cm_id'] = $arr['cm_name'];
			
			$arr['captions']['p_develop_status'] = $collArr[$arr['p_develop_status']];
			$arr['captions']['cat_unit_customs'] = $collArr[$arr['cat_unit_customs']];
			$arr['captions']['p_item_type'] = $collArr[$arr['p_item_type']];
			$arr['captions']['p_material'] = $collArr[$arr['p_material']];
			//p_fuel_type
			$arr['captions']['p_fuel_type'] = $collArr[$arr['p_fuel_type']];
			$arr['captions']['p_unit'] = $collArr[$arr['p_unit']];
			//数据标签
			$tags = new tags();
			$verArr = $tags->getTypeValTags('pro', [$p_id]);
			$verArr = array_column($verArr, 'tags', 'tl_value_id');
			$arr['tags'] = $verArr[$p_id]?implode(',', array_column($verArr[$p_id], LG_NAME)):'';
			//研发号
			$devNoRes = $this->db->select('pro_developno',["[>]supplier"=>["pde_sup_id"=>"sup_id"]],['pro_developno.*','sup_name'],['pde_p_id'=>$arr['p_id']]);
			foreach ($devNoRes as $key => $val) {
				$arr['devNoList'][] = $val;
			}
			//FGIO产品
			if($arr['p_pb_id']==1){

				$arr['relBrand'] = $this->db->select('pro',['[><]pro_brand'=>['p_pb_id'=>'pb_id']],['p_id','pb_'.LG_NAME.'(pb_name)','p_innum'],['p_comnum'=>$arr['p_comnum']]);

				$tb_name = $this->db->get('pro_tag_brand',['[><]tag_brand'=>['ptb_tb_id'=>'tb_id']],['tb_ids'=>raw("GROUP_CONCAT(tb_id)"),'tb_name'=>raw("GROUP_CONCAT(tb_".LG_NAME." ORDER BY CONVERT(tb_".LG_NAME." USING gbk))")],['ptb_p_id'=>$arr['p_id']]);
				$arr['captions']['p_tb_id'] = $tb_name['tb_name'];
				$arr['tb_ids'] = $tb_name['tb_ids'];

				
			}else{
				//事业部产品通过当前p_id获取引用的p_id
				$pro = new pro();
				$tempp_id = $arr['p_lnk_p_id']?:$pro->getQuoteIdbyPid($arr['p_id']);
				// $p_id = $tempp_id ? $tempp_id : $arr['p_id'];
				$tb_name = $this->db->get('pro_tag_brand',['[><]tag_brand'=>['ptb_tb_id'=>'tb_id']],['tb_ids'=>raw("GROUP_CONCAT(tb_id)"),'tb_name'=>raw("GROUP_CONCAT(tb_".LG_NAME." ORDER BY CONVERT(tb_".LG_NAME." USING gbk))")],['ptb_p_id'=>$tempp_id]);
				$arr['captions']['p_tb_id'] = $tb_name['tb_name'];
				$arr['tb_ids'] = $tb_name['tb_ids'];
				//获取数量
				$orgpro = $this->db->get('pro',['[><]oe_item'=>['pro.p_oe_id'=>'oe_id']],['oe_amount','p_oe_id','p_pos1','p_pos2','p_pos3','p_pos4','p_pos5'],['p_id'=>$tempp_id]);
				$arr = array_merge($arr,$orgpro);
				$arr['p_amount'] = $orgpro['oe_amount'];
				
				$arr['relCompany'] =$this->db->select('pro_link_company',['[><]company'=>['plc_com_id'=>'com_id']],['com_'.LG_NAME.'(com_name)','com_id','plc_id'],['plc_p_id'=>$arr['p_id'],'GROUP'=>'com_id']);
				
				$arr['p_lnk_p_id'] = $tempp_id;
			}
			if(!empty($arr['p_lnk_p_id'])){
				$arr['lnk_pro'] = $this->db->get('pro','*',['p_id'=>$arr['p_lnk_p_id']]);
			}
			$country = new country();
			$tItem = $country->getDataCountryId([$arr], 'pro');
			$tItem = $country->formatDataCountry($tItem, 1);
			$arr = $tItem[0];

			//关联零件
			if($arr['p_oe_id'] && $arr['oe_id'])
			{
				$table = 'oe_item(oi)';
				$join = [
					"[><]pro_factory(pf)" => ["oi.oe_pf_id" => "pf_id"],
				];
				$fields = ['oe_id', 'pf_name(oe_pf_name)', 'oe_oe', 'oe_etk_info','oe_etk_epa_id'];
				$oeArr = $this->db->get($table,$join,$fields, ['oe_id'=>$arr['p_oe_id']]);
				$arr = array_merge($arr,$oeArr?:[]);
				//配对商品（关联数据）
				list($arr['pairArr'],$arr['fatherArr'],$arr['sonArr']) = $this->getProPairData($arr['p_oe_id']);
			}
			//etk_info
			if($arr['oe_etk_epa_id']){
				$epainfo = $this->db->get('etk_partitem','*', ['epa_id'=>$arr['oe_etk_epa_id']]);
				$arr['oe_etk_partitem'] = empty($epainfo['epa_partitem'])? []:json_decode($epainfo['epa_partitem'], true);
			}

			$arr['imgs'] = [];
			$join = ["[><]files"=>["pic_fileid"=>'fileid'],"[>]supplier"=>["pic_sup_id"=>"sup_id"]];
			$picrows = $this->db->select('pro_pic',$join,'*',['pic_p_id'=>$p_id,'ORDER'=>['pic_ismain'=>'DESC']]);
			foreach ($picrows as  $pic) {
				if($pic['pic_type']=='img' && $pic['filetype']=='image'){
					$pic['bigImg'] = $pic['filepath'].'/'.$pic['filebasename'].'big.'.$pic['fileextname'];
					$pic['smallImg'] = $pic['filepath'].'/'.$pic['filebasename'].'small.'.$pic['fileextname'];
				}
				$arr['imgs'][$pic['pic_type']][] = $pic;
			}

			$arr['oe_chkpro_info'] = empty($arr['oe_chkpro_info'])? []:json_decode($arr['oe_chkpro_info'], true);
			$arr['oe_etk_info'] = empty($arr['oe_etk_info'])? []:json_decode($arr['oe_etk_info'], true);
		}
		return $arr;
	}

	function setProPicByFile($param){
		if(!$param['p_id']||!$param['imgs']) return exitJson(-1,'参数错误');
		$p_id = $this->db->get('pro', 'p_id',['p_id'=>$param['p_id']]);
		if(!$p_id) return exitJson(-1,'产品不存在');
		$result = [];
		foreach ($param['imgs'] as $key => $val) 
		{
			$val = json_decode(base64_decode($val),true);
			$res = $this->downloadAndSaveImage($p_id,$val['big'],'search',$val);
			if($res['code']==-1){
				$result[] = $val['text'].$res['msg'];
			}
		}
		if($result){
			return exitJson(-1,implode('<br>',$result));
		}
		return  [];
	}

	/**
	 * @param  int $p_id
	 * @param  string $url 图片网址或者本地图片路径
	 * @param  string $type 默认为空， search:搜图模式
	 * @param  Array $options 搜图模式可提供额外参数
	 * @method 下载并保存图片
	 * @author zhengweihua 
	 * @copyright 2025-01-15
	 */
	function downloadAndSaveImage($p_id,$url,$type='',$options = [])
	{
		if(!$p_id ||!$url) return ['code'=>-1,'msg'=>'参数错误']; 
		$path = parse_url($url, PHP_URL_PATH);
		// 获取路径中的文件名
		$filename = basename($path);
		// 获取文件扩展名
		$validImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
		$extname = pathinfo($filename, PATHINFO_EXTENSION);
		//  如果文件名不是图片扩展名，则使用默认名称
		if (!in_array(strtolower($extname), $validImageExtensions)) {
			$filename = 'image_'.time().'_'.rand(1000,9999).'.jpg'; // 默认使用jpg扩展名
			$extname = 'jpg';
		}

		// 将 MIME 类型转换为文件扩展名
		$mimeMap = [
			'image/jpeg' => 'jpg',
			'image/png' => 'png',
			'image/gif' => 'gif',
			'image/bmp' => 'bmp',
			'image/webp' => 'webp'
		];
		$params = ['p_id'=>$p_id];

		//是否是有效网址
		if(filter_var($url, FILTER_VALIDATE_URL))
		{
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置超时时间为5秒
			$data = curl_exec($ch);

			//如果不是图片，则二次请求 
			$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
			$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
			if($type=='search' && (strpos($contentType, 'image/') !== 0||$httpCode!=200))
			{
				$url = sprintf("http://pic.amozi.com/robot/index.php?from=big&search=%s",$url);
				$ch = curl_init($url);
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
				curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置超时时间为5秒
				$data = curl_exec($ch);
				$arr = json_decode($data,true);
				if($arr['data']['img']!=-1){
					$base64String = $arr['data']['img'];
					$oribase64 = $base64String;
					// 去掉base64头部信息
					$base64String = preg_replace('/^data:image\/\w+;base64,/', '', $base64String);
					$base64String = str_replace(' ', '+', $base64String);
					// 解码base64数据
					$data = base64_decode($base64String);
				}else{
					$data = false;
				}
			}else{
				if(!$extname) $extname = $mimeMap[$contentType]??'';
			}
			curl_close($ch);
		}else{
			$data = file_get_contents($url);
			if(!$extname) {
				// 获取文件的 MIME 类型
				$finfo = finfo_open(FILEINFO_MIME_TYPE);
				$mimeType = finfo_file($finfo, $url);
				finfo_close($finfo);
				$extname = $mimeMap[$mimeType]??'';
			}
		}
		//小图
		if(!$data && $type=='search' && $options['img'])
		{
			$oribase64 = $options['img'];
			// 去掉base64头部信息
			$base64String = preg_replace('/^data:image\/\w+;base64,/', '', $options['img']);
			$base64String = str_replace(' ', '+', $base64String);
			// 解码base64数据
			$data = base64_decode($base64String);
		}
		if(!$data) return ['code'=>-1,'ms'=>'获取图片失败'];
		
		//后缀不存在就从base64中获取
		if (!$extname && $oribase64 && preg_match('/^data:(\w+\/\w+);base64,/', $oribase64, $matches)) {
			$mimeType = $matches[1];
			$extname = $mimeMap[$mimeType]?$mimeMap[$mimeType] : 'jpg';
		}

		//已存在直接跳过
		$crc32 = strtoupper(dechex(crc32($data)));
		$has = $this->db->get('pro_pic',['[><]files'=>['pic_fileid'=>'fileid']],'*',['file_crc32'=>$crc32,'file_category'=>'pro','pic_p_id'=>$p_id,'pic_type'=>'img']);
		if($has) {
			$file_exists = \mvc::$cfg['dir']['files'].'/'.$has['filename'];
            if(file_exists($file_exists)){
                return ['fileid'=>$has['fileid']];
            }
		}
		//保存到files里
		$category = 'pro';
		$item = 'img';
		$uploadID =  guid();
		$cfg = \mvc::$cfg['upload']['category'][$category]['items'][$item];

		if($has['fileid'])
		{	
			$dir = $has['filepath'];
			$filebase = $has['filebasename'];
		}
		else
		{
			if(isset($cfg['path'])){
				$dir = call_user_func_array($cfg['path'], [$uploadID,$item,$extname,$params,$filename]);
			}else{
				$dir = call_user_func_array(\mvc::$cfg['upload']['category'][$category]['path'],[$uploadID,$item,$extname,$params,$filename]);
			}
			if(isset($cfg['filebase'])){
				$filebase = call_user_func_array($cfg['filebase'],[$uploadID,$item,$extname,$params,$filename]);
			}else{
				$filebase = call_user_func_array(\mvc::$cfg['upload']['category'][$category]['filebase'], [$uploadID,$item,$extname,$params,$filename]);
			}
		}

		$absdir = \mvc::$cfg['dir']['files'].'/'.$dir;

		mkdirs($absdir);
		$picstatus = file_put_contents($absdir.'/'.$filebase.'.'.$extname, $data);
		if(!$picstatus) return ['code'=>-1,'msg'=>'保存图片失败'];
		$fileType = $cfg['filetype'];
		$remark = str_replace('.'.strtolower($extname),'',strtolower(basename($filename)));
		if($options['text']) $remark = $options['text'];
		if(isset($cfg['tojpeg']) && $cfg['tojpeg'] && $extname!='jpg'){
			$image = make(\lib\image::class,100);
			$dist = $absdir.'/'.$filebase.'.jpg';
			$image->ToJPG($absdir.'/'.$filebase.'.'.$extname,$dist,false);
			$extname = 'jpg';
		}
		$filename = $absdir.'/'.$filebase.'.'.$extname;
		$this->db->Begin();
		if(!$has['fileid'])
		{
			$fileData = [
				'filename' => $dir.'/'.$filebase.'.'.$extname,
				'fileextname'=>$extname,
				'fileremark' => $remark,
				'filetype' => $fileType,
				'file_category' => $category,
				'file_item' => $item,
				'file_time' => getNowTime(),
				'file_crc32'=>$crc32,
				'filepath'=>$dir,
				'filebasename'=>$filebase
			];
			$this->db->insert('files',$fileData);
			$fileid = $this->db->id();
		}else{
			$fileid = $has['fileid'];
		}
		$files = new files();
		if($fileType=='image'){
			$image = make(\lib\image::class,100);
			
			if(isset($cfg['size'])){
			    //由大到小生成缩略图
			    $arrSize = $cfg['size'];
                uksort($arrSize,function($a,$b)use($arrSize){
                   return $arrSize[$b][0] - $arrSize[$a][0];
                });
			    $sizefilename = $absdir.'/'.$filebase.'.'.$extname;
				$orisizefilename = $absdir.'/'.$filebase.'.'.$extname;
				foreach($arrSize as $key=>$size){
					$dist = $dir.'/'.$filebase.$key.'.jpg';
					if($key=='small'){
						$sizefilename =  $orisizefilename;
					}
					$watermark = \mvc::$cfg['dir']['static'].'/images/watermark/'.$category.'/'.$item.'.png';
					if(file_exists($watermark)){
					    try {
    						$image->ResizeWatermark($sizefilename,\mvc::$cfg['dir']['files'].'/'.$dist,$size[0],$size[1],$watermark);
					    } catch (\Exception $e) {
					        $fileid=0;
					    }
					}else{
					    try {
    						$image->Resize($sizefilename,\mvc::$cfg['dir']['files'].'/'.$dist,$size[0],$size[1]);
					    } catch (\Exception $e) {
					        $fileid=0;
					    }
						$sizefilename = \mvc::$cfg['dir']['files'].'/'.$dist;
					}
				}
			}
    		if($fileid==0){
    		    @unlink($filename);
				return ['code'=>-1, 'msg'=>'缩略图生成失败'];
    		}
		}
		if(!$has['pic_fileid'])
		{
			$data = [
				'pic_p_id'=>$p_id,
				'pic_fileid'=>$fileid,
				'pic_type'=>$item,
				'pic_filebase'=>$remark,
				'pic_from'=>99,
				'pic_opuser'=>getOpuser(),
				'pic_create_time'=>getNowTime(),
				'pic_update_time'=>getNowTime(),
			];
			if($options['pic_remark']); $data['pic_remark'] = $options['pic_remark'];
			if($options['pic_from']); $data['pic_from'] = $options['pic_from'];
			$this->db->insert('pro_pic',$data);
		}
		$mainpic = $this->db->get('pro_pic', 'pic_fileid', ['pic_p_id'=>$p_id, 'pic_type'=>$item, 'pic_ismain'=>1]);
		if(!$mainpic) $this->setProMainPic($fileid,$p_id,$item);
		$this->db->End();
		return ['fileid'=>$fileid];
	}

	/**
	 * @param  Array $param
	 * @method 设置零件图为主图
	 * @author zhengweihua 
	 * @copyright 2025-01-20
	 */
	public function setImgToMain($param)
	{
		if(!$param['p_id']||!$param['imgs']) return exitJson(-1,'参数错误');
		$pId = $this->db->get('pro', 'p_id',['p_id'=>$param['p_id']]);
		if(!$pId) return exitJson(-1,'商品不存在');

		$imgs = json_decode(base64_decode($param['imgs']),true);
		$this->db->Begin();
		$res = $this->downloadAndSaveImage($pId,$imgs['big'],'search',$imgs);
		if($res['fileid']){
			$this->setProMainPic($res['fileid'],$param['p_id'],'img');
		}
		$this->db->End();
		return  [];
	}

	/**检测上传
     * @param 
     * @return
     */
	public function uploadCheck($filecount,$reqfilename,$reqfilesize,$uploadID,$extname,$category,$item,$params)
	{
		$pid = $params['pid'];
		if(empty($pid)) {
			throw new \Exception ( '上传图片时，商品库ID丢失' );
		}
		$cfg = \mvc::$cfg['upload']['category'][$category]['items'][$item];

		$count = 0;
		$photos = $this->db->select('pro_pic','pic_fileid',['pic_p_id'=>$pid]);
		
		if($photos){
		   
			$count = count($photos);
		}
		if( ($count+1) > $cfg['maxfile']){
			return lg('超出此项的最大允许的文件数量') .','. lg('最大允许').' '.$cfg['maxfile'].' '.lg('个文件');
		}else{
			return true;
		}
	}


    /**接收上传的图片处理
     * @param 
     * @return
     */
	public function uploadGet($fileid,$filename,$dir,$filebase,$extname,$category,$item,$params)
	{
		$pid = $params['pid'];

		if(empty($pid)) {
			throw new \Exception ( '上传图片时，商品库ID丢失' );
		}	
		$join =[
			'[>]pro_pic(pic1)'=>['pro.p_pic'=>'pic_fileid'],
		];
		$proinfo = $this->db->get('pro',$join,['p_pic','p_id','pic1.pic_fileid(pro_pic_fileid)'],['p_id'=>$pid]);
		//图片
		$flag = false;
		if(!$proinfo['pro_pic_fileid'] && $item =='img')
		{
			$flag  = true;
			$this->db->update('pro',['p_pic'=>$fileid],['p_id'=>$pid]);
		}
		if($item=='line'){
			$hasmain = $this->db->get('pro_pic','*',['pic_p_id'=>$pid,'pic_type'=>'line','pic_ismain'=>1]);
			if(!$hasmain) $flag  = true;
		}

		//同零件同类型下是否已存在
		$has  = $this->db->get('pro_pic','*',['pic_p_id'=>$pid,'pic_type'=>$item,'pic_fileid'=>$fileid]);
		if(!$has)
		{
			$fileinfo = $this->db->get('files', '*', ['fileid' => $fileid]);
			$data = [
				'pic_p_id'=>$pid,
				'pic_fileid'=>$fileid,
				'pic_type'=>$item,
				'pic_filebase'=>$fileinfo['fileremark'],
				'pic_opuser'=>getOpuser(),
				'pic_create_time'=>getNowTime(),
				'pic_update_time'=>getNowTime(),
				'pic_ismain'=>$flag?1:0
			];
			$this->db->insert('pro_pic',$data);
		}
		
	}

	public function setOeMain($pn_id)
	{
		$this->db->Begin();
		$row = $this->db->get('pro_numidx',['[><]pro'=>['pn_p_id'=>'p_id']],'*',['pn_id'=>$pn_id]);

		if(!$row) return exitJson(-1,'该零件号码不存在');
		$updata = [
			'p_pf_id'=>$row['pn_pf_id'],
			'p_oe'=>$row['pn_number'],
			'p_oe_format'=>$row['pn_formart'],
			'p_update_time'=>getNowTime()
		];
		$this->db->update('pro',$updata,['p_id'=>$row['pn_p_id']]);
		$this->db->update('pro_numidx',['pn_ismain'=>1,'update_time'=>getNowTime(),'opuser'=>getOpuser()],['pn_p_id'=>$row['pn_p_id'],'pn_id'=>$pn_id]);
		$this->db->update('pro_numidx',['pn_ismain'=>0,'update_time'=>getNowTime(),'opuser'=>getOpuser()],['pn_p_id'=>$row['pn_p_id'],'pn_ismain'=>1, 'pn_id[!]'=>$pn_id]);
		$this->addProSynLog([$row['pn_p_id']], 'set', 'text');


		$this->db->end();
		return [];
	}

	/**
	 * @param  [type] $param
	 * @method 编辑研发号
	 * @author zhengweihua 
	 * @copyright 2025-03-18
	 */
	public function saveDevelopNo($p_id,$numArr)
	{
		if(!$p_id) return [];
		$numArr = $numArr?:[];
		$oldIds = $this->db->select('pro_developno','pde_id',['pde_p_id'=>$p_id]);

		$this->db->Begin();
		
		foreach ($numArr as $val) {
			unset($val['sup_name']);
			$val['pde_format'] = formatNum($val['pde_number']);
			$val['pde_p_id'] = $p_id;
			if(in_array($val['pde_id'],$oldIds)){
				$this->db->update('pro_developno',$val,['pde_id'=>$val['pde_id']]);
			}else{
				unset($val['pde_id']);
				$this->db->insert('pro_developno',$val);
			}
		}
		$newIds = array_column($numArr,'pde_id');
		$delArr = array_diff($oldIds,$newIds);
		if($delArr){
			$this->db->delete('pro_developno',['pde_id'=>$delArr]);
		}
		$this->db->End();
		
		return [];
	}
	
	/**
	 * @method 添加产品同步日志
	 * @param  $pidArr array 
	 * @param  $act string  增删改 add|set|del 
	 * @param  $type string 文本信息|文件信息 text|file 
	 */
	public function addProSynLog($pidArr, $act, $type)
	{
		$pidArr = array_unique($pidArr);
		$opuser = getOpuser();
		$datetime = getNowTime();
		$addArr = [];
		foreach($pidArr as $p_id){
			if(!$p_id) continue;
			$addArr[] = [
				'psy_p_id'=>$p_id,
				'psy_act'=>$act,
				'psy_type'=>$type,
				'psy_opuser'=>$opuser,
				'psy_create_time'=>$datetime,
			];
		}
		if($addArr) $this->db->insert('pro_synlog',$addArr);
		return [];
	}

	/**
	 * @method 从零件库同步到商品
	 * @param  $oe_id 
	 * @param  $p_ids  默认所有零件的商品
	 * @param  $typeArr 默认所有 ['base', 'params', 'nums', 'model', 'cnmodel', 'link']
	 */
	public function synProByOe($oe_id, $typeArr = [], $syncFgio = false,$othsCfg = [],$p_ids=[])
	{
		$allType = ['base', 'params', 'nums', 'model', 'cnmodel', 'link'];
		if(empty($typeArr)) $typeArr = $allType;
		$oeArr = $this->db->get('oe_item', '*', ['oe_id'=>$oe_id]);
		if(empty($oeArr)) return [];
		//可以更新指定的商品
		if($p_ids){
			$proArr = $this->db->select('pro', '*', ['p_id'=>$p_ids,'p_oe_id'=>$oe_id]);
		}else{
			$proArr = $this->db->select('pro', '*', ['p_oe_id'=>$oe_id]);
		}
		
		if(empty($proArr)) return [];

		$basefields = ['p_cate'=>'oe_cate_id', 'p_unit'=>'oe_unit', 'p_chassis'=>'oe_chassis', 'p_model_year'=>'oe_model_year', 'p_engine'=>'oe_engine', 'p_cc'=>'oe_cc', 'p_cc'=>'oe_cc', 'p_fuel_type'=>'oe_fuel_type', 'p_isdevelop'=>'oe_isdevelop', 'p_develop_status'=>'oe_develop_status','p_para'=>'oe_para'];
		foreach(\mvc::$cfg['LANGS'] as $lk=>$lv){
			//2025/8/21 $basefields['p_'.$lv['field']] = 'oe_'.$lv['field'];
			$basefields['p_model_'.$lv['field']] = 'oe_model_'.$lv['field'];
			//2025/8/19 $basefields['p_des_'.$lv['field']] = 'oe_des_'.$lv['field'];
		}
		$paramsFields = ['p_pos1'=>'oe_pos1','p_pos2'=>'oe_pos2','p_pos3'=>'oe_pos3','p_pos4'=>'oe_pos4','p_pos5'=>'oe_pos5'];
		//不同步底盘
		if(!$othsCfg['syncChassis']){
			unset($basefields['p_chassis']);
		}	
		$opuser = getOpuser();
		$datetime = getNowTime();
		
		$fgioArr = [];
		foreach($proArr as $pArr){
			if($pArr['p_pb_id']==1){
				$fgioArr[] = $pArr['p_id'];
			}
			$p_id = $pArr['p_id'];
			$ischage = false;
			$this->db->Begin();
			//基本信息
			if(in_array('base', $typeArr)){
				//如果是没有勾选同步FGIO，则不更新基本信息
				//如果是事业部产品，则不更新基本信息
				if($syncFgio && $pArr['p_pb_id']==1)
				{
					$set = [];//变更的信息
					foreach($basefields as $pfield=>$ofield){
						if(isset($oeArr[$ofield]) && $pArr[$pfield] != $oeArr[$ofield]){
							$set[$pfield] = $oeArr[$ofield];
						}
					}
					if($set){
						$ischage = true;
						$set['p_opuser'] = $opuser;
						$set['p_update_time'] = $datetime;
						$this->db->update('pro', $set, ['p_id'=>$p_id]);
					}
					//研发号...
					$new = $this->db->select('oe_item_developno', ['oid_number(pde_number)', 'oid_format(pde_format)', 'oid_sup_id(pde_sup_id)'], ['oid_oe_id'=>$oe_id, 'ORDER'=>['oid_format', 'oid_number', 'pde_sup_id']]);
					$old = $this->db->select('pro_developno', ['pde_number', 'pde_format', 'pde_sup_id'], ['pde_p_id'=>$p_id, 'ORDER'=>['pde_format', 'pde_sup_id', 'pde_number']]);
					if($new != $old){
						$ischage = true;
						$sqlArr = [
							"delete from pro_developno where pde_p_id={$p_id} and (pde_number, pde_format, pde_sup_id) not in (select oid_number, pde_format, pde_sup_id from oe_item_developno where oid_oe_id={$oe_id})",
							"insert into pro_developno(pde_p_id, pde_number, pde_format, pde_sup_id) select {$p_id}, oid_number, oid_format, oid_sup_id from oe_item_developno where oid_oe_id={$oe_id} and (oid_number, oid_format, oid_sup_id) not in (select pde_number, pde_format, pde_sup_id from pro_developno where pde_p_id={$p_id})",
						];
						foreach($sqlArr as $sql){
							$this->db->query($sql);
						}
					}
					//如果没有车型数据，但是编辑了汽车品牌
					$sql = sprintf('SELECT oml_id FROM oe_model_cn_link WHERE oml_oe_id = %d 
					UNION SELECT oml_id FROM oe_model_link WHERE oml_oe_id = %d',$oe_id,$oe_id);
					$hasModel = $this->db->query($sql)->fetch();
					if(!$hasModel){
						$new = $this->db->select('oe_tag_brand', ['otb_tb_id(ptb_tb_id)'], ['otb_oe_id'=>$oe_id, 'ORDER'=>['otb_tb_id']]);
						$old = $this->db->select('pro_tag_brand', ['ptb_tb_id'], ['ptb_p_id'=>$p_id, 'ORDER'=>['ptb_tb_id']]);
						if($new!=$old){
							$ischage = true;
							$sqlArr = [
								"delete from pro_tag_brand where ptb_p_id={$p_id} and (ptb_tb_id) not in (select otb_tb_id from oe_tag_brand where otb_oe_id={$oe_id})",
								"insert into pro_tag_brand(ptb_p_id, ptb_tb_id) select {$p_id}, otb_tb_id from oe_tag_brand where otb_oe_id={$oe_id} and (otb_tb_id) not in (select ptb_tb_id from pro_tag_brand where ptb_p_id={$p_id})",
							];
							foreach($sqlArr as $sql){
								$this->db->query($sql);
							}
						}	
					}
				}

			}
			if(in_array('params', $typeArr)){
				//只有当syncFgio为true且是主品牌产品时才同步参数
				if($syncFgio && $pArr['p_pb_id']==1)
				{
					$set = [];//变更的信息
					foreach($paramsFields as $pfield=>$ofield){
						if(isset($oeArr[$ofield]) && $pArr[$pfield] != $oeArr[$ofield]){
							$set[$pfield] = $oeArr[$ofield];
						}
					}
					if($set){
						$ischage = true;
						$set['p_opuser'] = $opuser;
						$set['p_update_time'] = $datetime;
						$this->db->update('pro', $set, ['p_id'=>$p_id]);
					}

					//参数
					$oeParam = $this->db->select('oe_param_val', ['ppv_pc_id','ppv_ptpa_id','ppv_val_int','ppv_val_double','ppv_val_string','ppv_val_smalltxt'],['ppv_oe_id'=>$oe_id]);
					$proParam = $this->db->select('pro_param_val',['ppv_pc_id','ppv_ptpa_id','ppv_val_int','ppv_val_double','ppv_val_string','ppv_val_smalltxt'],['ppv_p_id'=>$p_id]);
					if($oeParam!=$proParam){
						$ischage = true;
						$sqlArr = [
							"DELETE FROM pro_param_val WHERE ppv_p_id={$p_id} AND (ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt) NOT IN (SELECT ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt FROM oe_param_val WHERE ppv_oe_id={$oe_id})",
							"insert into pro_param_val(ppv_p_id,ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt) select {$p_id}, ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt from oe_param_val where ppv_oe_id={$oe_id} and (ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt) not in (select ppv_pc_id,ppv_ptpa_id,ppv_val_int,ppv_val_double,ppv_val_string,ppv_val_smalltxt from pro_param_val where ppv_p_id={$p_id})",
						];
						foreach($sqlArr as $sql){
							$this->db->query($sql);
						}
						
					}
				}
			}
			if(in_array('nums',$typeArr)){
				//号码
				$oeNum = $this->db->select('oe_numidx', ['on_pf_id','on_number','on_formart','on_mk_id','on_from','on_isborrow','on_ismain'], ['on_oe_id'=>$oe_id]);
				$proNum = $this->db->select('pro_numidx', ['pn_pf_id','pn_number','pn_formart','pn_mk_id','pn_from','pn_isborrow','pn_ismain'=>raw(" CASE 
				WHEN pn_ismain = 1 THEN 'Y'
				WHEN pn_ismain = 0 THEN 'N' END")], ['pn_p_id'=>$p_id,'pn_is_sys'=>0]);
				// 转换为可比较的格式
				$oeMap = [];
				foreach ($oeNum as $item) {
					$key = $item['on_pf_id'].'|'.$item['on_formart'].'|'.$item['on_mk_id'].'|'.$item['on_from'];
					$oeMap[$key] = $item;
				}
				
				$proMap = [];
				foreach ($proNum as $item) {
					$key = $item['pn_pf_id'].'|'.$item['pn_formart'].'|'.$item['pn_mk_id'].'|'.$item['pn_from'];
					$proMap[$key] = $item;
				}
				ksort($oeMap);
				ksort($proMap);
				if($oeMap!=$proMap){
					$ischage = true;
					//如果是事业部产品或者没有勾选同步，则不更新主号码
					if(!$syncFgio || $pArr['p_pb_id']!=1){
						$sqlArr = [
							"DELETE FROM pro_numidx WHERE pn_p_id={$p_id} AND pn_is_sys!=1 AND pn_ismain!=1 AND (pn_pf_id,pn_number,pn_mk_id,pn_from) NOT IN (SELECT on_pf_id,on_number,on_mk_id,on_from FROM oe_numidx WHERE on_oe_id={$oe_id} )",
							"INSERT INTO pro_numidx(pn_p_id,pn_pf_id,pn_number,pn_formart,pn_mk_id,pn_isborrow,pn_ismain,pn_from,opuser,create_time,update_time) SELECT {$p_id}, on_pf_id,on_number,on_formart,on_mk_id,on_isborrow,CASE WHEN on_ismain = 'Y' THEN 1 WHEN on_ismain = 'N' THEN 0 END as on_ismain,on_from,on_opuser,on_create_time,on_update_time FROM oe_numidx WHERE on_oe_id={$oe_id} AND on_ismain!='Y' AND (on_pf_id,on_number,on_mk_id,on_from) NOT IN (SELECT pn_pf_id,pn_number,pn_mk_id,pn_from FROM pro_numidx WHERE pn_p_id={$p_id} AND pn_ismain!=1)",
							
						];
					}else{
						$sqlArr = [
							"DELETE FROM pro_numidx WHERE pn_p_id={$p_id} AND pn_is_sys!=1 AND (pn_pf_id,pn_number,pn_mk_id,CASE WHEN pn_ismain = 1 THEN 'Y' WHEN pn_ismain = 0 THEN 'N' END,pn_from) NOT IN (SELECT on_pf_id,on_number,on_mk_id,on_ismain,on_from FROM oe_numidx WHERE on_oe_id={$oe_id})",
							"insert into pro_numidx(pn_p_id,pn_pf_id,pn_number,pn_formart,pn_mk_id,pn_isborrow,pn_ismain,pn_from,opuser,create_time,update_time) select {$p_id}, on_pf_id,on_number,on_formart,on_mk_id,on_isborrow,CASE WHEN on_ismain = 'Y' THEN 1 WHEN on_ismain = 'N' THEN 0 END as on_ismain,on_from,on_opuser,on_create_time,on_update_time from oe_numidx where on_oe_id={$oe_id} and (on_pf_id,on_number,on_mk_id,on_ismain,on_from) not in (select pn_pf_id,pn_number,pn_mk_id,CASE WHEN pn_ismain = 1 THEN 'Y' WHEN pn_ismain = 0 THEN 'N' END,pn_from from pro_numidx where pn_p_id={$p_id})",
							"UPDATE pro JOIN pro_numidx ON p_id=pn_p_id SET p_pf_id=pn_pf_id,p_oe=pn_number,p_oe_format=pn_formart WHERE pn_p_id={$p_id} AND pn_ismain=1",
						];
					}
					// dump($sqlArr);
					$sqlArr[] = "UPDATE pro_numidx pn JOIN oe_numidx on_idx ON pn.pn_pf_id=on_idx.on_pf_id AND pn.pn_number=on_idx.on_number AND pn.pn_mk_id=on_idx.on_mk_id AND pn.pn_from=on_idx.on_from SET pn.pn_isborrow=on_idx.on_isborrow WHERE pn.pn_p_id={$p_id} AND on_idx.on_oe_id={$oe_id} AND pn.pn_is_sys!=1";
					foreach($sqlArr as $sql){
						$this->db->query($sql);
					}
				}
				// 删除不再关联的品牌
				$sqlDelete = "DELETE pntb FROM pro_numidx_tag_brand pntb 
							JOIN pro_numidx pn ON pntb.pntb_pn_id = pn.pn_id
							WHERE pn.pn_p_id = {$p_id}
							AND pntb.pntb_tb_id NOT IN (
								SELECT ontb_tb_id FROM oe_numidx_tag_brand ontb
								JOIN oe_numidx on_idx ON ontb.ontb_on_id = on_idx.on_id
								WHERE on_idx.on_oe_id = {$oe_id}
							)";
				$this->db->query($sqlDelete);
				 
				// 插入新增的品牌关联
				$sqlInsert = "INSERT INTO pro_numidx_tag_brand (pntb_pn_id, pntb_tb_id, pntb_p_id, pntb_opuser, pntb_update_time)
							SELECT pn.pn_id, ontb.ontb_tb_id, {$p_id}, ontb.ontb_opuser, ontb.ontb_update_time
							FROM oe_numidx_tag_brand ontb
							JOIN oe_numidx on_idx ON ontb.ontb_on_id = on_idx.on_id
							JOIN pro_numidx pn ON pn.pn_pf_id = on_idx.on_pf_id 
								AND pn.pn_number = on_idx.on_number 
							WHERE on_idx.on_oe_id = {$oe_id}
								AND pn.pn_p_id = {$p_id}
								AND ontb.ontb_tb_id NOT IN (
									SELECT pntb_tb_id FROM pro_numidx_tag_brand 
									WHERE pntb_pn_id = pn.pn_id
								)";
				$this->db->query($sqlInsert);
			}
			//'model', 'cnmodel', 'link'
			if(in_array('model',$typeArr)){
				//国际车型
				$oeModel = $this->db->select('oe_model_link', ['oml_mm_id','oml_remark','oml_para','oml_from'], ['oml_oe_id'=>$oe_id]);
				$proModel = $this->db->select('pro_model_link', ['pml_mm_id','pml_remark','pml_para','pml_from'], ['pml_p_id'=>$p_id]);	
				if($oeModel!=$proModel){
					$ischage = true;
					$sqlArr = [
						"DELETE FROM pro_model_link WHERE pml_p_id={$p_id} AND (pml_mm_id,pml_remark,pml_para,pml_from) NOT IN (SELECT oml_mm_id,oml_remark,oml_para,oml_from FROM oe_model_link WHERE oml_oe_id={$oe_id})",
						"insert into pro_model_link(pml_p_id,pml_mm_id,pml_remark,pml_para,pml_from,opuser,create_time,update_time) select {$p_id}, oml_mm_id,oml_remark,oml_para,oml_from,oml_opuser,oml_create_time,oml_update_time from oe_model_link where oml_oe_id={$oe_id} and (oml_mm_id,oml_remark,oml_para,oml_from) not in (select pml_mm_id,pml_remark,pml_para,pml_from from pro_model_link where pml_p_id={$p_id})",
					];
					foreach($sqlArr as $sql){
						$this->db->query($sql);
					}
					$this->initTagBrand([$p_id]);
				}
			}
			if(in_array('cnmodel',$typeArr)){
				//国际车型
				$oeModelcn = $this->db->select('oe_model_cn_link', ['oml_mod3_id','oml_remark','oml_from'], ['oml_oe_id'=>$oe_id]);
				$proModelcn = $this->db->select('pro_model_cn_link', ['pml_mod3_id','pml_remark','pml_from'], ['pml_p_id'=>$p_id]);	
				if($oeModelcn!=$proModelcn){
					$ischage = true;
					$sqlArr = [
						"DELETE FROM pro_model_cn_link WHERE pml_p_id={$p_id} AND (pml_mod3_id,pml_remark,pml_from) NOT IN (SELECT oml_mod3_id,oml_remark,oml_from FROM oe_model_cn_link WHERE oml_oe_id={$oe_id})",
						"insert into pro_model_cn_link(pml_p_id,pml_mod3_id,pml_remark,pml_from,opuser,create_time,update_time) select {$p_id}, oml_mod3_id,oml_remark,oml_from,oml_opuser,oml_create_time,oml_update_time from oe_model_cn_link where oml_oe_id={$oe_id} and (oml_mod3_id,oml_remark,oml_from) not in (select pml_mod3_id,pml_remark,pml_from from pro_model_cn_link where pml_p_id={$p_id})",
					];
					foreach($sqlArr as $sql){
						$this->db->query($sql);
					}
					$this->initTagBrand([$p_id]);
				}
			}
			//同步日志
			if($ischage) $this->addProSynLog([$p_id], 'set', 'text');
			$this->db->End();
		}
		
		return [];
	}

	public function getListProLink($p_id,$params,$rules = [])
	{
		$oe_id = $this->db->get('pro','p_oe_id',['p_id'=>$p_id]);
		if(!$oe_id) return [];
	
		$filters = $params['filters'];

		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];

		$where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			
        });

		$where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);

		$table = sprintf("( SELECT p_oe,p_innum,p_id,oe_link.*,au_name,pf_name FROM oe_link 
		JOIN pro ON  ol_oe_id1 = p_oe_id AND ol_oe_id2={$oe_id} OR ol_oe_id2 = p_oe_id AND ol_oe_id1={$oe_id}
		JOIN pro_factory ON p_pf_id = pf_id 
		LEFT JOIN adm_user on au_id = ol_opuser
		WHERE ol_type='link' GROUP BY p_id ) as pro_link");
		if($page>0 && $pagesize>0){

			$count  = $this->db->count($table,$where);
			$pages  = ['limit'=>($page-1)*$pagesize,'records'=>$count,'total'=>ceil($count/$pagesize)];

			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
		$fields = '*';
		$arr = $this->db->select($table,$fields,$where);
		
		if($arr)
		{
			$collocation = new collocation();
			foreach ($arr as &$v) {
				$v['captions']['ol_from'] = $collocation->getRowByKey($v['ol_from'])[cateName()];
				$v['captions']['ol_opuser'] = $v['au_name'];
			}
		}
		
		unset($v);
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records']??0,
			'rows' => $arr
		];
		return $data;
		// $arr = $this->db->select('oe_link',['*'],['OR'=>['ol_oe_id1'=>$oe_id,'ol_oe_id2'=>$oe_id]]);
	}

	/**
	 * @param  Array $params
	 * @method 获取所有的物料编码的key-Value
	 * @author zhengweihua 
	 * @copyright 2025-04-22
	 */
	public function getAllInnum($params)
	{
		$params['num'] = empty($params['num'])? $params['query']: $params['num'];
		if($params['num']){
			$where['p_innum_format[~]'] = formatNum($params['num']);
		}
		
		$where['LIMIT'] = empty($params['limit'])? 20: (int) $params['limit'];
		$where['ORDER'] = 'p_innum';
		
		$rows = $this->db->select('pro(p)',['p_id','p_innum'], $where);

		$data = [];
		foreach($rows as $k=>$v){
			$data[$k]=['key'=>$v['p_innum'], 'value'=>$v['p_innum']];
		}
		return $data;
	}

	/**
	 * @method 检测有主图但是文件不存在
	 * @author zhengweihua 
	 * @copyright 2025-04-22
	 */
	public function checkProPicEmpty()
	{	
		//无图片的
		/*$sql = 'select p_id from pro where p_id not in (select distinct pic_p_id from pro_pic)';
		$arr = $this->db->query($sql)->fetchAll();
	
		$data = array_column($arr,'p_id');*/
		$data = [];
		//有主图的
		$join = [
			'[><]files'=>['pic.pic_fileid'=>'fileid'],
		];
		$arr = $this->db->select('pro_pic(pic)',$join,['pic_p_id','pic.pic_fileid','files.*'],['pic.pic_ismain'=>1]);
		
		$absdir = \mvc::$cfg['dir']['files'];

		foreach ($arr as $val) 
		{	
			$filesname = $absdir.'/'.$val['filename'];
			if(!file_exists($filesname) || filesize($filesname) < 1024)
			{
				$data[] = $val['pic_p_id'];
			}
		}
		return array_unique($data);
	}

	/**
	 * @param  int  $p_id 商品ID
	 * @method 将零件的EPC、和主图 同步到商品
	 * @author zhengweihua 
	 * @copyright 2025-04-22
	 */
	public function syncOePicToPro($p_id)
	{
		$oe_id = $this->db->get('pro','p_oe_id',['p_id'=>$p_id,'p_pb_id'=>1]);
		if($oe_id)
		{
			$arr = $this->db->select('oe_pic',['[><]files'=>['oe_pic.pic_fileid'=>'fileid']],'*',['pic_oe_id'=>$oe_id,'pic_type'=>'img','OR'=>['pic_from'=>1070,'pic_ismain'=>1]]);
		
			if($arr)
			{	
				$procrcArr = $this->db->select('pro_pic',['[><]files'=>['pro_pic.pic_fileid'=>'fileid']],'file_crc32',['pic_p_id'=>$p_id,'pic_type'=>'img']);

				$oecrcArr = array_column($arr,null,'file_crc32');
				$add = array_diff(array_keys($oecrcArr),$procrcArr?:[]);
				if($add)
				{	
					//商品主图
					$pro_main = $this->db->get('pro_pic','pic_fileid',['pic_p_id'=>$p_id,'pic_type'=>'img','pic_ismain'=>1]);
					$synProPic = new synProPic();
					foreach ($add as $file_crc) 
					{	
						//商品本身存在主图
						if($oecrcArr[$file_crc]['pic_ismain'] ==1 && $pro_main)
						{
							$oe_fileid[$file_crc]['pic_ismain'] = 0;
						}
						$data = file_get_contents(\mvc::$cfg['dir']['files'].'/'.$oecrcArr[$file_crc]['filename']);

						$synProPic->saveProPic($p_id,$data,$oecrcArr[$file_crc]['filename'],$oecrcArr[$file_crc]['fileextname'],[
							'is_main'=>$oecrcArr[$file_crc]['pic_ismain'],
							'pic_from'=>$oecrcArr[$file_crc]['pic_from'],
						]);
						
					}
				}
			}
		}
		return [];
	}

	/**
	 * @method 获取产品的所有商品品牌
	 * @author zhengweihua 
	 * @copyright 2025-06-19
	 */
	public function getProPbList()
	{	
		$where = ['p_pb_id[!]'=>1,'GROUP'=>'p_pb_id'];
		//权限 - 商品品牌
		$proBrands = \p::areas('B600');
		if(!\p::isAdmin() && $proBrands){
			$where['AND #rule_brand'] = ['p_pb_id'=>explode(',',$proBrands)];
		}
		$arr = $this->db->select('pro',['[><]pro_brand'=>['p_pb_id'=>'pb_id']],['pb_id','pb_'.LG_NAME.'(pb_name)'],$where);
		return $arr;
	}

	/**
	 * @method 获取所有的品牌
	 * @author hongzhang
	 * @copyright 2026-04-22
	 */
	public function getAllSubProPbList()
	{	
		$where = ['pb_id[!]'=>1];
		//权限 - 商品品牌
		$proBrands = \p::areas('B600');
		if(!\p::isAdmin() && $proBrands){
			$where['AND #rule_brand'] = ['pb_id'=>explode(',',$proBrands)];
		}
		$arr = $this->db->select('pro_brand',['pb_id','pb_'.LG_NAME.'(pb_name)'],$where);
		return $arr;
	}


	/**
	 * @param  String $p_id 商品id
	 * @method 根据商品id返回其对应的集团商品关联的汽车品牌列表
	 * @author hongzhang
	 * @copyright 2026-02-28
	 */
	public function getProTbList($p_id){
		$pId = $p_id;
		$link_p_id = $this->db->get('pro','p_lnk_p_id',['p_id'=>$p_id]);
		if($link_p_id != 0){
			$pId = $link_p_id;
		}
		$join = ["[>]tag_brand" => ["ptb_tb_id" => "tb_id"]];
		$list = $this->db->select('pro_tag_brand',$join,['tb_id','tb_'.LG_NAME.'(tb_name)'],['ptb_p_id'=>$pId]);
		return $list;
	}
	
	/**
	 * @method 获取有关联产品的事业部
	 * @author zhengweihua 
	 * @copyright 2025-06-19
	 */
	public function getPlcComList()
	{	
		$where = ['ORDER'=>['com_seq'=>'ASC'],'GROUP'=>'com_id'];
		//权限 - 商品品牌
		$company = \p::company('B700');
		if(!\p::isAdmin() && $company){
			$where['AND #rule_brand'] = ['plc_com_id'=>explode(',',$company)];
		}
		$arr = $this->db->select('pro_link_company',['[><]pro'=>['plc_p_id'=>'p_id'],'[><]company'=>['plc_com_id'=>'com_id']],['com_id','com_'.LG_NAME.'(com_name)'],$where);
		// dd($this->db->last());
		return $arr;
	}

	/**
	 * @method 事业部商品
	 * @author zhengweihua 
	 * @copyright 2025-06-18
	 */
	/**
	 * @method 事业部商品
	 * @author zhengweihua 
	 * @copyright 2025-06-18
	 */
	public function compProList($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? '': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];
		$this->joinWhere = [];
		$refiled = [
			'cat_name'=>'cat.'.cateName(),
			'pb_name'=>'pb.pb_'.LG_NAME,
			'p_name'=>'p.p_'.LG_NAME,
			'p_model_name'=>'p.p_model_'.LG_NAME,
			'p_des_name'=>'p.p_des_'.LG_NAME,
			'cat_name_cn'=>'cat.cn_name',
			'cat_name_en'=>'cat.en_name',
			'pcat_name'=>'pcat.'.cateName(),
			'oe_oe'=>'oe.oe_oe_format',
			'p_oe'=>'p_oe_format',
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro_link_company(plc)';
		$join = [
			"[><]pro(p)"=>['plc.plc_p_id'=>'p_id'],
			"[><]pro_cate(cat)" => ["p.p_cate" => "id"],
			"[><]pro_cate(pcat)" => ["cat.parent_id" => "id"],
			"[><]pro_brand(pb)" => ["p.p_pb_id" => "pb_id"],
			"[>]pro_ext(ext)" => ["p.p_id" => "pe_p_id"],
			"[><]pro_factory(fac)" => ["p.p_pf_id" => "pf_id"],
			"[>]oe_item(oe)" => ["p.p_oe_id" => "oe_id"],
			"[>]pro_factory(fac2)"=>["plc.plc_p_pf_id"=>"pf_id"],
			"[>]company(com)"=>["plc.plc_com_id"=>"com_id"],
		];
		$fields = ['fac2.pf_name(p_pf_name)','plc.*','pcat.'.cateName().'(pcat_name)','cat.is_engine', 'cat.'.cateName().'(cat_name)', 'cat.cn_name(cat_name_cn)','cat.en_name(cat_name_en)', 'pb_'.LG_NAME.'(pb_name)','p.*', 'p.p_des_'.LG_NAME.'(p_des_name)','p.p_model_'.LG_NAME.'(p_model_name)','p.p_'.LG_NAME.'(p_name)','ext.*','fac.pf_name','oe.oe_id','oe_'.LG_NAME.'(oe_name)','oe_oe'];
		$this->set('carmodel', new carmodel());
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
		
			if($field == 'tags')
			{
				$res = $this->get('carmodel')->medooAnyLink($field, 'p_id', $op, $data, ['tl_type'=>'pro']);
				$data = $res['data'];
				$op = $res['op'];
			}else if($field == 'p_oe_format'){
				$data = formatNum($data);
			}elseif($field == 'pn_number'){			
				$likeConditions = sprintf("pn_formart LIKE '%s%%'", $data);
				
				$data = raw(sprintf("EXISTS (SELECT 1 
					FROM pro_numidx 
					WHERE (pn_p_id = p.p_id) 
						AND (%s)
					LIMIT 1)
				", $likeConditions));

				$op = 'RAW_'.$field;
					
			}else if($field == 'p_cc'){
				$op = 'RAW_'.$field;
				// 使用参数绑定方式避免SQL注入
				$escapedData = $this->db->quote('%' . $data . '%');

				$data = raw(" (CASE WHEN cat.is_engine=1 THEN p_cc LIKE " . $escapedData . " ELSE p_cc_xj LIKE " . $escapedData . " END)");
			}elseif($field == 'p_engine'){
				$op = 'RAW_'.$field;
				// 使用参数绑定方式避免SQL注入
				$escapedData = $this->db->quote('%' . $data . '%');
				$data = raw(" (CASE WHEN cat.is_engine=1 THEN p_engine LIKE " . $escapedData . " ELSE p_engine_xj LIKE " . $escapedData . " END)");
			}elseif ($field == 'plc_com_name') {
				$field = 'com.com_'.LG_NAME;
				$dataArr = explode(' ',$data);
				$data = count($dataArr)>1?$dataArr[1]:$dataArr[0];
			}
        });
	    $formatToOrigin = [];
		$pidToNumsMap = [];
		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$tnums = [];
					foreach($val as $tk=>$tv){
						$searchNums = reSearchNum($tv);
						$tnums = array_merge($tnums, $searchNums);

						foreach ($searchNums as $searchNum) {
                            if (!isset($formatToOrigin[$searchNum])) {
                                $formatToOrigin[$searchNum] = $tv;
                            }
                        }
					}
					$tnums = array_unique($tnums);

					//2026-04-30 多个查询号码对应一个商品：列出所有对应的号码
					//查询号码对应的商品
					$numWhere['pn_formart'.($rules['numlike']? '[~]': '')] = $tnums;
					$matchedRows = $this->db->select('pro_numidx', [
						'pn_p_id',
						'pn_number'
					], $numWhere);
					if (empty($matchedRows)) {
						break;
					}

					$matchedPids = [];
					foreach ($matchedRows as $mRow) {
						$pid = $mRow['pn_p_id'];
						$num = $mRow['pn_number'];
						if (!isset($pidToNumsMap[$pid])) {
							$pidToNumsMap[$pid] = [];
							$matchedPids[] = $pid;
						}
						// 避免重复号码
						if (!in_array($num, $pidToNumsMap[$pid])) {
							$pidToNumsMap[$pid][$formatToOrigin[$num]] = $formatToOrigin[$num];
						}
					}
					if($matchedPids){
						$where['p_id'] = array_unique($matchedPids);

					}else{
						$where['p_id'] = -1;

					}
				break;

			}
		}

		if($params['com_id'])
		{
			$where['plc.plc_com_id'] = $params['com_id'];
		}
		if($params['p_id'])
		{
			$where['plc.plc_p_id'] = $params['p_id'];
		}

		//权限 - 事业部
		$company = \p::company('B700');
		if(!\p::isAdmin() && $company){
			$where['AND #rule_brand'] = ['plc.plc_com_id'=>explode(',',$company)];
		}

		$where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($page>0 && $pagesize>0){
			$pages = $this->paging($table,$join,'*',$where,$page,$pagesize);
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}

		

		$arr = $this->db->select($table,$join,$fields,$where);

		if($arr)
		{	
			//查汽车品牌
			$pb = [];
			$tb = [];
			foreach ($arr as $val) 
			{
				if($val['p_pb_id']==1){
					$pb[] = $val['p_id'];
				}else{
					$tb[] = $val['p_comnum_format'];
				}
			}
			if($tb){
				$tbArr = $this->db->select('pro',['p_id','p_comnum_format'],['p_comnum_format'=>$tb,'p_pb_id'=>1]);
				$tbArr = array_column($tbArr,'p_id','p_comnum_format');
				
				$pb = array_merge($pb,$tbArr?array_keys($tbArr):[]);
			} 
			if($pb)
			{
				$pbArr = $this->db->select('pro_tag_brand',['[><]tag_brand'=>['ptb_tb_id'=>'tb_id']],['ptb_p_id','tb_name'=>raw("GROUP_CONCAT(tb_".LG_NAME." ORDER BY CONVERT(tb_".LG_NAME." USING gbk))")],['GROUP'=>['ptb_p_id']]);
				$pbArr = array_column($pbArr,'tb_name','ptb_p_id');
			}
			$collArr = $this->db->select('object', ['o_parent_id', 'o_id', LG_NAME], ['o_parent_id'=>1]);
			$collArr = array_column($collArr, LG_NAME, 'o_id');
			$kdstatusArr = [0=>'禁用',1=>'正常'];
			$packStatusArr = [1=>'内包',2=>'外包'];
			$weightArr = ['01'=>'克','02'=>'千克'];
			$pdstatusArr = [];
			foreach(explode(',',\mvc::$cfg['PROSTATUSITEMS']) as $val){
				$tempArr = explode(':',trim($val));
				$pdstatusArr[$tempArr[0]] = $tempArr[1];
			}
			
			$comArr = $this->db->select('company',['com_id','com_'.LG_NAME.'(com_name)']);
			$comArr = array_column($comArr,'com_name','com_id');
			foreach ($arr as $key => &$val) 
			{	
				if(!$val['is_engine']){
					$val['p_engine'] = $val['p_engine_xj'];
					$val['p_cc'] = $val['p_cc_xj'];
					$val['p_engine_xj'] = '';
					$val['p_cc_xj'] = '';
				}
				$val['captions'] = [
					'plc_packaging_status'=>$packStatusArr[$val['plc_packaging_status']]??'',
					'plc_weight_unit'=>$weightArr[$val['plc_weight_unit']]??'',
					'plc_p_state_main'=>$pdstatusArr[$val['plc_p_state_main']]??'',
					'plc_gd_kingdee_status'=>$kdstatusArr[$val['plc_gd_kingdee_status']]??'',
					'p_tb_id'=>$val['p_pb_id']==1?$pbArr[$val['p_id']]:$pbArr[$tbArr[$val['p_comnum_format']]],
					'p_item_type'=>$collArr[$val['p_item_type']]??'',
					'plc_com_name'=>$comArr[$val['plc_com_id']]??'',
					'plc_p_main_pn_id'=>$val['p_pf_name'].':'.$val['plc_p_oe']??'',
					'p_oe'=>$val['p_pf_name'].':'.$val['plc_p_oe']??'',
					'pn_number'=>$pidToNumsMap[$val['p_id']]?implode("\r\n",$pidToNumsMap[$val['p_id']]):'',
				

				];
			}
			unset($val);
		}
		
		
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}
	/**
	 * @method 关联事业部信息详情
	 * @author zhengweihua 
	 * @copyright 2025-06-21
	 */
	public function compLinkDetail($id)
	{
		$join= [
			'[>]pro_factory(fac1)' => ['plc.plc_p_pf_id'=>'pf_id'],
			'[>]company' => ['plc.plc_com_id'=>'com_id'],
			'[>]pro(p)' => ['plc.plc_p_id'=>'p_id'],
			'[>]oe_item(oi)' => ['p.p_oe_id'=>'oe_id'],
			"[>]pro_factory(fac2)" => ["oi.oe_pf_id" => "pf_id"],
		];
		$fileds = ['plc.*','fac1.pf_name(pro_pf_name)','fac2.pf_name(oe_pf_name)','p_id','p_lnk_p_id','p_innum','p_comnum','oe_id','oe_oe','com_'.LG_NAME.'(com_name)'];
		$data = $this->db->get('pro_link_company(plc)',$join,$fileds,['plc_id'=>$id]);
		$kdstatusArr = [0=>'禁用',1=>'正常'];
		$data['captions'] = [
			'plc_gd_kingdee_status'=>$kdstatusArr[$data['plc_gd_kingdee_status']]??'',
		];
		return $data;
	}

	/**
	 * @param  int $p_id
	 * @method 通过p_id获取引用p_id,
	 * @author zhengweihua 
	 * @copyright 2025-06-21
	 * @return int 返回引用P_id,如果是FGIO返回自己
	 */
	public function getQuoteIdbyPid($p_id)
	{
		$pro = $this->db->get('pro',['p_id','p_lnk_p_id','p_pb_id','p_comnum_format'],['p_id'=>$p_id]);
		if($pro)
		{
			if($pro['p_pb_id'] == 1){
				return $p_id;
			}elseif ($pro['p_lnk_p_id']>0) {
				return $pro['p_lnk_p_id'];
			}
			//通过p_comnum查引用的p_Id
			$new_p_id = $this->db->get('pro','p_id',['p_comnum_format'=>$pro['p_comnum_format'], 'p_pb_id'=>1]);
			if($new_p_id){
				return $new_p_id;
			}
		}
		return $p_id;
	}

	/**
	 * @param  数组 $allProData
	 * @method yield 批量处理数据
	 * @author zhengweihua 
	 * @copyright 2025-06-23
	 */
	function processBatchData($allProData){
		foreach ($allProData as $pitem) {
			yield $pitem;
		}
	}

	/**
	 * @param  string|Array $ids
	 * @method 零件同步到FGIO
	 * @author zhengweihua 
	 * @copyright 2025-08-16
	 */
	public function synFgioByOe($ids)
	{
		if(!$ids) exitJson(-1,'参数错误');
		if(!is_array($ids)){
			$ids = explode(',',$ids);
		}
		$existsIds = $this->db->select('oe_item','oe_id',['oe_id'=>$ids]);
		foreach ($existsIds as $id) {
			$this->synProByOe($id, ['base', 'params','nums'],true);
		}
		return ['msg'=>'同步完成'];
	}

	/**
	 * @param  [type] $oe_id
	 * @method 通过产品p_oe_id获取产品的关联关系
	 * @author zhengweihua 
	 * @copyright 2025-08-26
	 */
	public function getProPairData($oe_id)
	{
		$sql = sprintf("SELECT oe_link.*,pro.*,p_".LG_NAME." as p_name,pb_".LG_NAME." as pb_name,pf_name,files.* 
		FROM oe_link 
		JOIN pro ON ol_oe_id2 = p_oe_id
		LEFT JOIN pro_factory ON p_pf_id = pf_id
		LEFT JOIN pro_brand ON p_pb_id = pb_id
		LEFT JOIN files ON p_pic = fileid 
		WHERE ol_type IN ('pair','father','son') AND ol_oe_id1 = %d",$oe_id);
		$pairArr = $this->db->query($sql)->fetchAll();
		
		$arr = [];
		if($pairArr)
		{
			$collocation = new collocation();
			foreach ($pairArr as &$val) {
				
				$val['p_item_type_name'] = $collocation->getRowByKey($val['p_item_type'])[cateName()];
				$val['smallImg'] = '';
				$val['bigImg'] = '';
				if($val['filepath']){
					$val['bigImg'] = $val['filepath'].'/'.$val['filebasename'].'big.'.$val['fileextname'];
					$val['smallImg'] = $val['filepath'].'/'.$val['filebasename'].'small.'.$val['fileextname'];
				}
				$arr[$val['ol_type']][] = $val;
			}
			unset($val);
			if($arr['pair']){
				$allPos = $this->allPos;
				$pairTypeIdArr = array_filter(array_column($arr['pair'],'ol_pair_type'));
				if($pairTypeIdArr){
					$pairTypeArr = $this->db->select('object', ['cn_name','o_id'],['o_id'=>$pairTypeIdArr]);
					$pairTypeArr = array_column($pairTypeArr,'cn_name','o_id');
				}
				//获取位置信息
				$pidArr = array_column($arr['pair'],'p_id');
				$field = ['p_id','p_pos1','p_pos2','p_pos3','p_pos4','p_pos5','cat_pos1','cat_pos2','cat_pos3','cat_pos4','cat_pos5'];
				$posArr = $this->db->select('pro_cate',['[><]pro'=>['id'=>'p_cate']],$field,['p_id'=>$pidArr]);
				foreach ($posArr as $poskey => $posval) {
					foreach ($allPos as $pos => $val) {
						if($posval['cat_'.$pos] && $posval['p_'.$pos]) {
							$pos1 = array_intersect(explode('/',$posval['p_'.$pos]),explode(',',$posval['cat_'.$pos]));
							if($pos1) $paramArr2[$posval['p_id']][$val['name']] = ['name'=>$val['name'],'unikey'=>$val['name'],'value'=>implode('/',$pos1)];
						}
					}
				}
				foreach ($arr['pair'] as $key => &$val) { 
					$val['ol_pair_type_name'] = $pairTypeArr[$val['ol_pair_type']]??'';
					$val['pos'] = $paramArr2[$val['p_id']]??[];
				}	
				unset($val);

			}
		}
		return [$arr['pair'],$arr['father'],$arr['son']];
	}

	/**
	 * @method 移除发动机字段的重复项目
	 * @author zhengweihua 
	 * @copyright 2025-09-25
	 */
	public function removeEngineDuplicates()
	{	
		
		$result = [
			'pro_count' => 0,
			'oe_count'=>0,
			'pro_updated' => 0,
			'oe_updated' => 0,
		];
		$this->db->Begin();
		$proRecords = $this->db->select('pro', ['p_id', 'p_engine'],['p_engine[~]'=>',']);

		foreach ($proRecords as $record) 
		{
            $p_id = $record['p_id'];
            $engineStr = $record['p_engine'];
            
            // 去除重复项
			$engines = explode(',', $engineStr);
			$cleanedEngines = array_unique(array_map('trim', $engines));
			$newEngineStr = implode(',', $cleanedEngines);
			
			// 如果有变化则更新
			if ($engineStr !== $newEngineStr) {

				$this->db->update('pro', ['p_engine' => $newEngineStr], ['p_id' => $p_id]);
				$result['pro_updated']++;
			}
        }
		
		 // 处理oe_item表中的oe_engine字段
		$oeRecords = $this->db->select('oe_item', ['oe_id', 'oe_engine'],['oe_engine[~]'=>',']);
        
		foreach ($oeRecords as $record) 
		{
			$oe_id = $record['oe_id'];
			$engineStr = $record['oe_engine'];
		
			// 去除重复项
			$engines = explode(',', $engineStr);
			$cleanedEngines = array_unique(array_map('trim', $engines));
			$newEngineStr = implode(',', $cleanedEngines);
			
			// 如果有变化则更新
			if ($engineStr !== $newEngineStr) {
	
				$this->db->update('oe_item', ['oe_engine' => $newEngineStr], ['oe_id' => $oe_id]);
				$result['oe_updated']++;
			}	 
		}

		$this->db->End();
		return $result;
	}

	/**
	 * @method 检查商品是否为FGIO品牌,返回是FGIO的商品数组
	 * @author zhengweihua 
	 * @copyright 2025-10-20
	 */
	public function checkIsFgioBrand($p_id)
	{	
		if(!is_array($p_id)) $p_id =  explode(',',$p_id);
		if(is_array($p_id)){
			$pid = $this->db->select('pro',['p_id','p_comnum','p_innum'],['p_id'=>$p_id,'p_pb_id'=>1]);
			return $pid;
		}
	}
	/**
	 * @param  int $p_id 根据商品id获取指定分类的零件
	 * @method
	 * @author zhengweihua 
	 * @copyright 2025-10-20
	 */
	public function getOeItemByPid($paramArr)
	{	
		$params['num'] = empty($params['num'])? $paramArr['query']: $paramArr['num'];
		$where = ['on_formart[=~]'=>formatNum($params['num'])];
		if($paramArr['p_id']){
			$p_cate = $this->db->get('pro','p_cate',['p_id'=>$paramArr['p_id']]);
			$where['oe_cate_id'] = $p_cate;
		}
	
		$where['LIMIT'] = empty($params['limit'])? 20: (int) $params['limit'];
		$where['GROUP'] = 'on_formart';
		$where['ORDER'] = 'on_formart';
		$join = ["[><]oe_item(oe)" => ["num.on_oe_id" => "oe_id"]];
		$rows = $this->db->select('oe_numidx(num)', $join, ['on_number','on_oe_id'], $where);
		$data = [];
        foreach($rows as $k=>$v){
            $data[$k]=['key'=>$v['on_oe_id'], 'value'=>$v['on_number']];
        }
        return $data;
	}

	/**
	 * @param  Array $paramArr
	 * @method 变更商品关联零件
	 * @author zhengweihua 
	 * @copyright 2025-10-21
	 */
	public function changeProOe($paramArr)
	{
		if($paramArr['p_id'] && $paramArr['oe_id']){
			$pitem = $this->db->get('pro',['p_oe_id','p_id','p_cate'],['p_id'=>$paramArr['p_id'],'p_pb_id'=>1]);
			if(!$pitem){
				return ['msg'=>'商品不存在','code'=>-1];
			}
			if($pitem['p_oe_id'] == $paramArr['oe_id']){
				return ['msg'=>'无需变更','code'=>0];
			}
			$oeExists = $this->db->get('oe_item',['oe_id','oe_cate_id'],['oe_id'=>$paramArr['oe_id']]);
			if(!$oeExists){
				return ['msg'=>'零件不存在','code'=>-1];
			}
			if($oeExists['oe_cate_id'] != $pitem['p_cate']){
				return ['msg'=>'零件与商品分类不匹配','code'=>-1];
			}
			$this->db->Begin();
			//变更FGIO商品的关联零件
			$this->db->update('pro',['p_oe_id'=>$paramArr['oe_id']],['p_id'=>$paramArr['p_id']]);

			//变更FGIO所属其他品牌商品的关联零件
			$this->db->update('pro',['p_oe_id'=>$paramArr['oe_id']],['p_lnk_p_id'=>$paramArr['p_id'],'p_pb_id[!]'=>1]);
			//同步零件数据
			$p_ids = $this->db->select('pro','p_id',['p_lnk_p_id'=>$paramArr['p_id']]);
			$p_ids = array_merge($p_ids,[$paramArr['p_id']]);
			$this->synProByOe($paramArr['oe_id'],[],true,['syncChassis'=>true],$p_ids);
			$this->db->End();
		
			return ['msg'=>'操作成功','code'=>0];
		}
		return ['msg'=>'参数错误','code'=>-1];
	}

	/**
     * @param  int $p_id
     * @method 获取商品北美车型xml文件导出命名相关数据
     * @author hongzhang
     * @copyright 2026-05-06
     */
	public function getXMLProInfo($p_id)
	{
		$proData = $this->db->select('pro',['[>]pro_factory'=>['p_pf_id'=>'pf_id']],['pf_name','p_oe_format','p_'.LG_NAME.'(pro_name)'],['p_id'=>$p_id]);
		return $proData;
	}

	/**
	 * @method 获取所有事业部列表 
	 * @author hongzhang
	 * @copyright 2026-02-28
	 */
	public function getCompanyList(){
		//权限 - 事业部
		$company = \p::company('B700');
		if(!\p::isAdmin() && $company){
			$where['AND #rule_brand'] = ['com_id'=>explode(',',$company)];
		}
		$list = $this->db->select('company',['com_id','com_'.LG_NAME.'(com_name)']);
		return $list;
	}

		/**
	 * @method 品牌物料添加事业部
	 * @author hongzhang
	 * @copyright 2026-03-02
	 */
	public function addCompanyToPro($p_id,$com_ids){
		//判断是否存在事业部数据
		$ext = $this->db->get('pro_link_company',['plc_id'],['plc_p_id'=>$p_id,'plc_com_id'=>$com_ids]);
		if($ext){
			return exitJson('添加了已存在的事业部数据');
		}
		//获取品牌物料信息
		$proInfo = $this->db->get('pro(p)',
		[
			'[>]pro_numidx(pn)' => [
				'p.p_id' => 'pn_p_id',
				'AND' => 'pn_ismain = 1'
			]
		],['p.*','pn.pn_id(p_main_pn_id)'],['p_id'=>$p_id]);
		if(!$proInfo){
			return exitJson('不存在的品牌物料');
		}
		$newPlcInfo = [];
		$opuser = getOpuser();
		$datatime = getNowTime();
		foreach($com_ids as $com_id){
			$newPlcInfo[] = [
				'plc_p_id'=>$p_id,
				'plc_com_id'=>$com_id,
				'plc_p_main_pn_id'=>$proInfo['p_main_pn_id'],
				'plc_p_pf_id'=>$proInfo['p_pf_id'],
				'plc_p_oe'=>$proInfo['p_oe'],
				'plc_p_oe_format'=>$proInfo['p_oe_format'],
				'plc_p_state_main'=>$proInfo['p_state_main'],
				'plc_p_cn_name'=>$proInfo['p_cn_name'],
				'plc_p_en_name'=>$proInfo['p_en_name'],
				'plc_p_py_name'=>$proInfo['p_py_name'],
				'plc_p_sp_name'=>$proInfo['p_sp_name'],
				'plc_p_al_name'=>$proInfo['p_al_name'],
				'plc_p_model_cn_name'=>$proInfo['p_model_cn_name'],
				'plc_p_model_en_name'=>$proInfo['p_model_en_name'],
				'plc_p_model_py_name'=>$proInfo['p_model_py_name'],
				'plc_p_model_sp_name'=>$proInfo['p_model_sp_name'],
				'plc_p_model_al_name'=>$proInfo['p_model_al_name'],
				'plc_p_chassis'=>$proInfo['p_chassis'],
				'plc_p_model_year'=>$proInfo['p_model_year'],
				'plc_p_engine'=>$proInfo['p_engine'],
				'plc_p_cc'=>$proInfo['p_cc'],
				'plc_opuser'=>$opuser,
				'plc_create_time'=>$datatime,
				'plc_update_time'=>$datatime,
			];
		}
		//添加
		$this->db->insert('pro_link_company',$newPlcInfo);
		$logRows = $this->db->select('pro_link_company', ['plc_id', 'plc_p_id'], ['plc_p_id'=>$p_id,'plc_com_id'=>$com_ids]);
		$logArr = [];
		if($logRows){
			foreach($logRows as $item){
				$logArr[] = ['p_id'=>$item['plc_p_id'],'plc_id'=>$item['plc_id']];
			}
		}
		//添加同步日志
		$this->addProComLinkSynLog($logArr,'add','text');
		return ['msg'=>'操作成功','code'=>0];
	}
	/**
	 * @method 添加事业部商品同步日志
	 * @param  $plcArr [['p_id'=>商品ID,'plc_id'=>事业部商品关联ID],...] 
	 * @param  $act string  增删改 add|set|del 
	 * @param  $type string 文本信息|文件信息 text|file 
	 */
	public function addProComLinkSynLog($plcArr, $act, $type)
	{
		$opuser = getOpuser();
		$datetime = getNowTime();
		$addArr = [];
		foreach($plcArr as $plc){
			$p_id = $plc['p_id'] ?? 0;
			$plc_id = $plc['plc_id'] ?? 0;
			if(!$p_id || !$plc_id) continue;
			$addArr[] = [
				'psy_mod'=>'procom',
				'psy_p_id'=>$p_id,
				'psy_plc_id'=>$plc_id,
				'psy_act'=>$act,
				'psy_type'=>$type,
				'psy_opuser'=>$opuser,
				'psy_create_time'=>$datetime,
			];
		}
		if($addArr) $this->db->insert('pro_synlog',$addArr);
		return [];
	}
}
