<?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\sample\sampleDate;
class pro extends \model
{
    public $table = 'pro';
    public $key = 'p_id';

    public $cate;
    public $factory;
    public $paramset;
    public $param;
    public $paramStrenvalKeyValues = []; //参数翻译
    public $paramType;
    public $tags;
	public $formatRowCache = [];
	public $codeFields = [];
	public $defaultFieldName= [];
	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 = ['pc_state_main'=>'主状态','pc_state_remark'=>"主状态备注",'pc_item_type'=>"物料类型",'pc_cn_name'=>'产品中文名','pc_en_name'=>'产品英文名','pc_py_name'=>'产品俄文名',
			'pc_cn_model'=>'车型中文名','pc_en_model'=>'车型英文名','pc_py_model'=>'车型俄文名','pc_auto_assign'=>'是否自动分配','pc_unit'=>'基本单位','pc_en_guige'=>'规格英文',
			'pc_py_guige'=>'规格俄文','pc_chassis'=>'底盘','pc_model_year_range'=>'车型年限','pc_engine'=>'发动机','pc_cc'=>'排量','pc_inter_develop'=>'内部研发',
			'pc_develop_no'=>'开发号','pc_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'=>'备选采购跟单员','pc_purc_warn'=>"采购提醒","pn_main_formart"=>'主OE'
		];
		$this->defaultFieldName = [
			'pro_bom_assemble'=>['p_id'=>['pba_p_id'],'pba_name'=>'名称','pba_count'=>'数量'],

			'pro_bom_pack'=>['p_id'=>['pbp_p_id'],'pbp_name'=>'名称','pbp_count'=>'数量'],

			'pro_source_link'=>['p_id'=>['psl_p_id'],'psl_code'=>'国标码','psl_from'=>'来源','psl_from_id'=>'来源ID'],

			'pro_supplier'=>['p_id'=>['psu_p_id'],'psu_sup_id'=> '供应商ID','psu_gczbq' =>'工厂质保期','psu_gckz'=>'是否工厂刻字','psu_zjm' => '助记码',
				'psu_zjm_bx' => '助记码(备选)','psu_jhjq'=> '计划交期(天)','psu_kpmc1' =>'开票名称1','psu_kpmc2' => '开票名称2',
				'psu_gdhyd' => '固定货源地','psu_hsbm' => 'HS编码','psu_ktsl'=> '可退税率','psu_bgdw'=> '报关单位','psu_tz' => '图纸'],
			
			'pro_exchange'=>[
				'p_id'=>['pe_p_id1','pe_p_id2'],'pe_param1'=>'属性1','pe_param2'=>'属性2','pe_remark'=>'备注','pe_frometo'=>'通用方向'
			],
			'pro_pair'=>[
				'p_id'=>['pp_p_id1','pp_p_id2'],'pp_pos'=>'安装位置1','pp_pos2'=>'安装位置2','pp_remark'=>'备注','pp_group'=>'组号'
			],

			'pro_fatherson'=>[
				'p_id'=>['pf_father_pid','pf_son_pid']
			],
		];
	}

	/**
     * 获取集团中性号[待完善]
     * @param int $cat_id 品类ID
     * @return string
     */
	function buildComNum($cat_id){
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$len = strlen($chars);
		$num = sprintf('C%03d', $cat_id);
		for ($i = 0; $i < 6; $i++) {
			$num .= $chars[rand(0, $len - 1)];
		}
		return $num;
    }
	

	/**
     * 获取SKU品牌的新物料编码 [待完善]
     * @param int $pb_id SKU品牌ID
     * @param int $cat_id 品类ID
     * @param int $lnk_p_id 关联菲尔科技产品ID
     * @return string
     */
	function buildBrandInnum($pb_id, $cat_id, $lnk_p_id = 0)
	{
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$len = strlen($chars);
		$num = sprintf('I%02d%03d', $pb_id, $cat_id);
		for ($i = 0; $i < 4; $i++) {
			$num .= $chars[rand(0, $len - 1)];
		}
		return $num;
	}


	function getDb(){
	    return $this->db;
	}
	
	function list($rules, $where='',$page=0,$pagesize=0,$sidx='',$sord='asc',$orderby=''){
        $table = $this->table.'(p)';
        $this->fields = ['p.*'];
        $this->join = [];
		$this->joinWhere = [];
		$this->group = [];
		$whereRegi = 0;
		$othWhere = [];
        $where = $this->filter2medoo($where,function(&$field,&$op,&$data)use(&$rules,&$whereRegi,&$othWhere){
            $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.name';
                    break;
			    case 'ms_name':
                    $op = '~';
                    $field = 'ms.name';
                    break;
			    case 'mm_name':
                    $op = '~';
                    $field = '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;	
				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->fields[] = 'pf.'.LG_NAME.' (pf_alias)';
					/*$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['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.name(mk_name)';
				$this->fields[] = 'ms.name(ms_name)';
				$this->fields[] = '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.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.name';
				        if($v=='ms_name') $v = 'ms.name';
				        if($v=='mm_name') $v = '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 车型查询
			    
			//参数
			$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_pc_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['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_merge JOIN pro mpro ON pch_p_id_to = mpro.`p_id` where pch_p_id_from = p.p_id limit 1)");
				$this->fields['mergeto'] = raw("(select mpro.`p_comnum` from p_code JOIN pro mpro ON pc_merge_p_id = mpro.`p_id` where pc_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';'ps_qty';
    			$this->join['[><]p_code(pc)'] = ["p.p_id" => "pc_p_id"];
    		}
		
			
			//查非
			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)];
        }
        
        //权限 - 区域
        $areas = \p::areas('1100');
        if(!\p::isAdmin() && $areas){
			if(!isset($this->joinWhere['pma_ma_id'])){
    			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(',',$areas);
			}
       }
        
        //权限 - 版本
        $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_moreline':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_cate WHERE id = p.p_cate AND is_moreline=1 LIMIT 1)");
                    break;
                case 'null_father':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_fatherson WHERE pf_son_pid = p.p_id LIMIT 1)");
                    break;
                case 'null_son':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_fatherson WHERE pf_father_pid = p.p_id LIMIT 1)");
                    break;
                case 'null_exchange':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_exchange WHERE pe_p_id1 = p.p_id OR pe_p_id2 = p.p_id LIMIT 1)");
                    break;
                case 'null_pair':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pair WHERE pp_p_id1 = p.p_id OR pp_p_id2 = p.p_id LIMIT 1)");
                    break;
                case 'null_oe':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_pf_id = 1 AND pn_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_oe_ok':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_pf_id = 1 AND pn_p_id = p.p_id and ckresult2 = %d LIMIT 1)",NUMIDX_CKRESULT2_OK);
                    break;
                case 'null_oe_wait':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_pf_id = 1 AND pn_p_id = p.p_id and ckresult2 = %d LIMIT 1)",NUMIDX_CKRESULT2_WAIT);
                    break;
                case 'null_barcode':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_barcode<>'' AND pn_pf_id = 2 AND pn_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_barcodeg':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_barcode<>'' AND pn_pf_id = 4 AND pn_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_barcodeenertek':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_numidx WHERE pn_barcode<>'' AND pn_pf_id = 6 AND pn_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_param':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_param_val WHERE ppv_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_ktype':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_model_link,m_model_source WHERE mms_mm_id=pml_mm_id AND mms_source=%d AND pml_p_id = p.p_id LIMIT 1)",OBJECT_KTYPE);
                    break;
                case 'null_cnmodel':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_model_cn_link WHERE pml_p_id = p.p_id LIMIT 1)");
                    break;
                case 'null_merge':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_merge WHERE pch_p_id_from = p.p_id OR pch_p_id_to = p.p_id LIMIT 1)");
                    break;
                case 'null_vio':
                     $tsql = ($value) ? "p.p_vio>0" : "p.p_vio=0";
                    break;
                case 'null_order':
                     $tsql = ($value) ? "p.p_sales_qty>0" : "p.p_sales_qty=0";
                    break;
                /*case 'null_pack':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE pack<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_miniqty_sales':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE miniqty_sales>0 AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_miniqty_packing':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE miniqty_packing>0 AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_miniqty_trays':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE miniqty_trays>0 AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_nilongsize':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE nilongsize<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_zhihesize':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE zhihesize<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_waixiangsize':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE waixiangsize<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_zhixiangsize':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE zhixiangsize<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;
                case 'null_danzhong':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack WHERE danzhong<>'' AND pp_id = p.p_id LIMIT 1)");
                    break;*/
				case 'null_pack':
                    $tsql = $op.sprintf("(SELECT 1 FROM pro_pack_area WHERE area<>'' AND pp_p_id = p.p_id LIMIT 1)");
                    break;
				default:
					//包装查空
					/*
					if(stripos($name, 'null_pack_') === 0){
						$filed = substr($name, 10);
						$tsql = $op.sprintf("(SELECT 1 FROM pro_pack_area WHERE %s != '0' and %s is not null and %s != '' AND pp_p_id = p.p_id LIMIT 1)", $filed, $filed, $filed);
					}*/
				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 ppic_type in('init_add','init_back','init_replay') AND ppic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'init_del':
	            //删除
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE ppic_type='init_del' AND ppic_p_id=p.p_id limit 1))";
                break;
            case 'init_back':
	            //退回+重拍
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic WHERE ppic_type in ('init_back','init_replay') AND ppic_p_id=p.p_id limit 1))";
                break;
            case 'init_check':
	            //原始图审核 只要有一张没有审就显示
			    $tsql = "(
			        exists (SELECT 1 FROM pro_pic WHERE ppic_type='init_add' AND ppic_state=0 AND ppic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'designer':
	            //设计师, 已审核但没有精修图,并且没有不入精修图标识
	            $this->join['[>]pro_pic(picI)'] = ['p.p_id'=>'ppic_p_id'];
	            $this->joinWhere['picI.ppic_type'] = 'init';
	            $this->joinWhere['picI.ppic_state'] = 1;
	            $this->joinWhere['picI.ppic_isnotbeaut'] = 0;
	            //如果不存在精修图有同名的
			    $tsql = "not exists (SELECT 1 FROM pro_pic WHERE ppic_type in ('beautify_add','beautify') AND ppic_p_id=p.p_id AND ppic_filebase = picI.ppic_filebase limit 1)";
			    if($rules['checkOption']=='1'){
    			    $this->joinWhere['picI.desexport_time[!]'] = null; //已导出
			    }else if($rules['checkOption']=='-1'){
    			    $this->joinWhere['picI.desexport_time'] = null; //未导出
			    }else if($rules['checkOption']=='2'){
    			    $this->joinWhere['picI.ppic_isusa'] = 1; //北美
			    }else if($rules['checkOption']=='3'){
    			    $this->joinWhere['picI.ppic_isusa'] = 1; //北美
    			    $this->joinWhere['picI.desexport_time'] = null; //未导出
			    }
			    $this->group['GROUP'] = 'p.p_id';
                break;
            case 'init':
	            //原始图
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE ppic_type='init' AND ppic_p_id=p.p_id limit 1))";
                break;
            case 'beautify_add':
	            //上传精修图, 已审核但没有精修图
	            $this->join['[>]pro_pic(picI)'] = ['p.p_id'=>'ppic_p_id'];
				$this->joinWhere['OR #picI.ppic_type'] = [
					'AND #picI.ppic_type_1'=>[
						'picI.ppic_type'=>'init',
						'ppic_state'=>1
					],
					'AND #picI.ppic_type_2'=>[
						'picI.ppic_type'=>'beautify_back'
					],
				];
	            //$this->joinWhere['picI.ppic_type'] = 'init';
	            //$this->joinWhere['picI.ppic_state'] = 1;
	            $this->joinWhere['picI.ppic_isnotbeaut'] = 0;
	            //如果不存在精修图有同名并审核的
			    $tsql = "(
					not exists (SELECT 1 FROM pro_pic WHERE ppic_type in ('beautify') AND ppic_p_id=p.p_id AND ppic_filebase = picI.ppic_filebase limit 1)
					OR
			        exists (SELECT 1 FROM pro_pic WHERE ppic_type in('beautify_add','beautify_back','beautify_replay') AND ppic_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 ppic_type in('beautify_add') and ppic_state=0 AND ppic_p_id=p.p_id limit 1)
			    )";
                break;
            case 'beautify_back':
	            //精修图 退回
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE ppic_type in('beautify_back','beautify_replay') AND ppic_p_id=p.p_id limit 1))";
                break;
            case 'beautify':
	            //精修图
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE ppic_type='beautify' AND ppic_p_id=p.p_id limit 1))";
                break;
                
            case 'catalog_gsp':
            case 'catalog_g':
			    $this->joinWhere['p_pic[>]'] = 0;
			    break;
            case 'tecdoc':
			    $this->joinWhere['p_pic[>]'] = 0;
				$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",4));
                break;
            case 'usa':
			    $tsql = "(exists (SELECT 1 FROM pro_pic WHERE ppic_type in ('beautify','beautify_replay') AND ppic_isusa=1 AND ppic_p_id=p.p_id limit 1))";
                break;
        }
	    if($tsql!=''){ 
	        $this->joinWhere['RAW #image'] = raw($tsql);
	    }
	   
	    if($rules['propictype']=='notcattle'){
	        $this->join['[>]pro_state'] = ["p.p_id" => "ps_p_id"];
	        $this->fields['ps_notcattle_state'] = raw("IFNULL(ps_notcattle_state,0)");
	    }
	    
	    if($rules['propictype']=='init'){
	        $this->join['[>]pro_pic'] = [
	            "p.p_id" => "ppic_p_id",
	            "RAWppic_type" => "@pro_pic.ppic_type = 'beautify'",
	            'pro_pic.ppic_filebase'=>'ppic_innum',
	         ];
	        $this->fields[] = "pro_pic.update_time(main_update_time)";
		    //$this->fields[] ="@(select update_time from pro_pic where ppic_type='beautify' and ppic_p_id = p.p_id and ppic_filebase=ppic_innum limit 1) as main_update_time";
	    }
	    
	    if($rules['propictype']=='beautify'){
	        $this->join['[>]pro_state'] = ["p.p_id" => "ps_p_id"];
	        $this->fields['ps_beautify_state'] = raw("IFNULL(ps_beautify_state,0)");
	        
	        $this->join['[>]pro_pic'] = [
	            "p.p_id" => "ppic_p_id",
	            "RAWppic_type" => "@pro_pic.ppic_type = 'beautify'",
	            'pro_pic.ppic_filebase'=>'ppic_innum',
	         ];
	        $this->fields[] = "pro_pic.update_time(main_update_time)";
		    //$this->fields[] ="@(select update_time from pro_pic where ppic_type='beautify' and ppic_p_id = p.p_id and ppic_filebase=ppic_innum limit 1) as main_update_time";
	    }
	    
	    if($rules['propictype']=='tecdoc'){
	        $this->join['[>]pro_state'] = ["p.p_id" => "ps_p_id"];
	        $this->fields['ps_tecdoc_state'] = raw("IFNULL(ps_tecdoc_state,0)");
	    }
	    
	    if($rules['propictype']=='usa'){
	        $this->join['[>]pro_state'] = ["p.p_id" => "ps_p_id"];
	        $this->fields['ps_usa_state'] = raw("IFNULL(ps_usa_state,0)");
	    }
	    
	    if( ($rules['propictype']=='init' || $rules['propictype']=='beautify') &&
	        !empty($rules['main_update_time_begin']) && !empty($rules['main_update_time_end'])){
	        //$tsql = 
	        //$this->joinWhere['RAW #main_update_time_begin_end'] = raw($tsql);
	        //$this->joinWhere['HAVING']['main_update_time[>=] #1'] = $rules['main_update_time_begin'];
	        //$this->joinWhere['HAVING']['main_update_time[<=] #2'] = $rules['main_update_time_end'];
	        $this->joinWhere['pro_pic.update_time[>=] #1'] = $rules['main_update_time_begin'];
	        $this->joinWhere['pro_pic.update_time[<=] #2'] = $rules['main_update_time_end'];
	        
	    }

	    //图片列过滤
	    if(isset($rules['imageCount'])){
	        list($count,$has) = $rules['imageCount'];
	        $count = $count + 1;
	        $usaWhere = '';
	        if($rules['propictype']=='usa'){
	            $usaWhere = ' OR ppic_isusa=1';
	        }
	        if($has){
	            $sql = sprintf(" EXISTS (SELECT COUNT(1) total FROM pro_pic  WHERE ppic_p_id = p.p_id AND (ppic_type='%s'%s) HAVING total=%d)",$rules['propictype'],$usaWhere,$count);
	        }else{
	            $sql = sprintf(" EXISTS (SELECT COUNT(1) total FROM pro_pic  WHERE ppic_p_id = p.p_id AND (ppic_type='%s'%s) HAVING total<%d)",$rules['propictype'],$usaWhere,$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']]);
		}

        //产品线与品名
        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);
		}
        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 int
     * @return bool
     */
    public function hasUsa($pid){
        if($this->db->has('p_code',['pc_p_id'=>$pid,'pc_rule_1'=>1])){
            return true;
        }
        if($this->db->has('pro_numidx',['pn_p_id'=>$pid,'pn_ma_id'=>2])){
            return true;
        }
        return false;
    }

    /**
     * 修正要保存的数据
     * @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('p_code','pc_id',['pc_innum_format'=>formatNum($innum), 'pc_pb_id'=>1]);
	}

	//获取物料编码的产品ID
    public function getPidByNumber($innum)
    {
		return $this->db->get('p_code','pc_id',['pc_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 int $cateId 品名ID
     * @param int $start min seq
     * @param int $end max seq
     * @return bool
     */
	function getSeqByCate($p_cate,$start,$end){
		$where = [
			'pc_cate' => $p_cate,
			'pc_seq[<>]'=>[$start,$end]
		];
        $max = $this->db->max('p_code','pc_seq',$where);
		if(empty($max)) 
			$max = $start*1;
		else
			$max = $max * 1 + 1;
		return $max;
    }

    /**
     * 添加一条记录
     * @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('产品不存在');

		$list = $this->getCodeList(['pc_p_id'=>$pid]);
		$oldArr =  $list['rows'][0];

		$oldArr['pn_main_formart'] = $this->getProMainOe($pid);

		$this->db->Begin();

		$codeArr = [];
		$extArr = [];
		$pnumArr = [];
		$paramArr = [];
		foreach($data as $field=>$val){
			if(stripos($field, 'pc_') === 0){
				$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['opuser'] = $opuser;
			$codeArr['update_time'] = $datetime;

			$this->db->update('p_code', $codeArr, ['pc_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_mainoe'=>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_mainoe'] = 1;
				$this->db->insert('pro_numidx',$tempnum);
			}else{
				
				$this->db->update('pro_numidx',['pn_mainoe'=>1],['pn_id'=>$pn_id]);

				
			}
		}
		//日志
		$changeArr = [];
		//获取新的
		$list = $this->getCodeList(['pc_p_id'=>$pid]);
		$newArr =  $list['rows'][0];
		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->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  $innum  int  [必填] 样品ID
	  * @author soul
	  */
	public function setProductBySample($innum)
	{
		errorLog($innum,'setProductBySample');
		//确认产品状态
		$proArr = $this->db->get('pro', '*', ['p_innum_format'=>formatNum($innum)]);
		if(empty($proArr)) return [];
		$p_id = $proArr['p_id'];

		//内部编码找样品ID
		$samArr = $this->db->select('sample', '*', ['s_innum'=>$innum]);
		if(empty($samArr)) return [];
		$sidArr = array_column($samArr, 's_id');

		//交叉号转待进入
		$addTempNumArr = [];
		foreach($samArr as $v)
		{
			if(!empty($v['s_arri_number']))
			{
				$addTempNumArr[] = [
					'pnt_p_id'=>$p_id,
					'pnt_sample'=>$v['s_id'],
					'pnt_sign_type'=>$v['s_sign_type'],
					'pnt_pf_id'=>$v['s_arri_brand'],
					'pnt_number'=>$v['s_arri_number'],
					'pnt_src'=>10337
				];
			}

			$addTempNumArr[] = [
				'pnt_p_id'=>$p_id,
				'pnt_sample'=>$v['s_id'],
				'pnt_sign_type'=>$v['s_sign_type'],
				'pnt_pf_id'=>$v['s_apply_brand'],
				'pnt_number'=>$v['s_apply_number'],
			];
		}
		
		$carmodel = new carmodel();

		$rows =  $this->db->select('sample_model_txt', ['smt_s_id', 'sm_makes'=>raw("group_concat(sm_make)")], ['smt_s_id'=>$sidArr, 'smt_s_id[>]'=>0, 'GROUP'=>'smt_s_id']);
		$oemakeArr = array_column($rows, 'sm_makes', 'smt_s_id');
		
		$join = [
			"[><]sample(sam)" => ["sn.sn_s_id" => "s_id"],
		];
		$rows = $this->db->select('sample_numidx(sn)', $join, '*', ['sn_s_id'=>$sidArr]);
		foreach($rows as $sm)
		{
			$oe_mak_id = '';
			if(!empty($sm['sn_oe_make']))
				$oe_mak_id = $carmodel->getMakeIdByName($sm['sn_oe_make']);
			else if(!empty($oemakeArr[$sm['s_id']]))
				$oe_mak_id = $oemakeArr[$sm['s_id']];

			$addTempNumArr[] = [
				'pnt_p_id'=>$p_id,
				'pnt_sample'=>$sm['s_id'],
				'pnt_sign_type'=>$sm['s_sign_type'],
				'pnt_pf_id'=>$sm['sn_pro_factory'],
				'pnt_number'=>$sm['sn_number'],
				'pnt_src'=>$sm['sn_src'],
				'pnt_mk_id'=>$oe_mak_id,
			];
		}
		$this->db->Begin();
		$opuser = getOpuser();
		$datetime = getNowTime();
		$numidx = new numidx();
		
		//2022/10/24 提交数据本身重复事务无法去重
		$uniTempNumArr = [];
		foreach($addTempNumArr as $add)
		{
			$add['pnt_formart'] = formatNum($add['pnt_number']);
			if(empty($add['pnt_pf_id']) || empty($add['pnt_formart'])) continue;
			$uniTempNumArr[$add['pnt_pf_id'].'@'.$add['pnt_formart']] = $add;
		}
		
		foreach($uniTempNumArr as $add)
		{
			$add['pnt_innum'] = $proArr['p_innum'];
			$add['pnt_outnum'] = $proArr['p_comnum'];
			$add['opuser'] = $opuser;
			$add['create_time'] = $datetime;
			$add['update_time'] = $datetime;
			$exists = $numidx->checkExistTemp($add);
			if(empty($exists))
				$this->db->insert('pro_numidx_temp', $add);	
		}
	

		//车型转待进入
		$join = [
			"[><]sample(sam)" => ["sml.sml_s_id" => "s_id"],
			"[><]m_model(mm)" => ["sml.sml_mm_id" => "mm_id"],
		];
		$rows = $this->db->select('sample_model_link(sml)', $join, ['sml.*', 'sam.*'], ['sml_s_id'=>$sidArr]);
		$promodel = new promodel();
		foreach($rows as $sm)
		{
			$add = [
				'pmlt_p_id'=>$p_id,
				'pmlt_mm_id'=>$sm['sml_mm_id'],
				'pmlt_cate'=>$sm['s_cate'],
				'pmlt_sample'=>$sm['s_id'],
				'pmlt_innum'=>$proArr['p_innum'],
				'pmlt_outnum'=>$proArr['p_comnum'],
				'pmlt_pos0'=>$sm['sml_pos0'],
				'pmlt_pos1'=>$sm['sml_pos1'],
				'pmlt_pos2'=>$sm['sml_pos2'],
				'pmlt_pos3'=>$sm['sml_pos3'],
				'pmlt_pos4'=>$sm['sml_pos4'],
				'pmlt_pos5'=>$sm['sml_pos5'],
				'pmlt_pos6'=>$sm['sml_pos6'],
				'pmlt_node1'=>$sm['sml_node1'],
				'opuser'=>$opuser,
				'create_time'=>$datetime,
				'update_time'=>$datetime,
			];
			$exists = $promodel->checkExistTemp($add);
			if(empty($exists))
				$this->db->insert('pro_model_link_temp', $add);
		}

		//样品库
		$set = [
			's_state_main'=>'Y1',
			's_stop'=>1,
			's_p_id'=>$p_id,
			's_innum'=>$proArr['p_innum'],
			's_outnum'=>$proArr['p_comnum'],
			's_topro_opuser'=>$opuser,
			's_topro_time'=>$datetime
		];
		$this->db->update('sample', $set, ['s_id' =>$sidArr, 's_p_id'=>0]);
		$this->db->end();
		return $sidArr;
	}


	/**
	  * @method 样品数据追加到产品
	  * @param  $innum  int  [必填] 样品ID
	  * @author soul
	  */
	public function setProductBySampleOnlyToPro($innum)
	{
	    errorLog('内部编码:' . $innum,'setProductBySampleOnlyToPro');
		//确认产品状态
		$proArr = $this->db->get('pro', '*', ['p_innum_format'=>formatNum($innum)]);
		if(empty($proArr)) return [];
		$p_id = $proArr['p_id'];

		//内部编码找样品ID
		$samArr = $this->db->select('sample', '*', ['s_innum'=>$innum]);
		if(empty($samArr)) return [];
		$sidArr = array_column($samArr, 's_id');

		//交叉号转待进入
		$addTempNumArr = [];
		foreach($samArr as $v)
		{
			if(!empty($v['s_arri_number']))
			{
				$addTempNumArr[] = [
					'pnt_p_id'=>$p_id,
					'pnt_sample'=>$v['s_id'],
					'pnt_sign_type'=>$v['s_sign_type'],
					'pnt_pf_id'=>$v['s_arri_brand'],
					'pnt_number'=>$v['s_arri_number'],
					'pnt_src'=>10337
				];
			}

			$addTempNumArr[] = [
				'pnt_p_id'=>$p_id,
				'pnt_sample'=>$v['s_id'],
				'pnt_sign_type'=>$v['s_sign_type'],
				'pnt_pf_id'=>$v['s_apply_brand'],
				'pnt_number'=>$v['s_apply_number'],
			];
		}
		
		$carmodel = new carmodel();

		$rows =  $this->db->select('sample_model_txt', ['smt_s_id', 'sm_makes'=>raw("group_concat(sm_make)")], ['smt_s_id'=>$sidArr, 'smt_s_id[>]'=>0, 'GROUP'=>'smt_s_id']);
		$oemakeArr = array_column($rows, 'sm_makes', 'smt_s_id');
		
		$join = [
			"[><]sample(sam)" => ["sn.sn_s_id" => "s_id"],
		];
		$rows = $this->db->select('sample_numidx(sn)', $join, '*', ['sn_s_id'=>$sidArr]);
		foreach($rows as $sm)
		{
			$oe_mak_id = '';
			if(!empty($sm['sn_oe_make']))
				$oe_mak_id = $carmodel->getMakeIdByName($sm['sn_oe_make']);
			else if(!empty($oemakeArr[$sm['s_id']]))
				$oe_mak_id = $oemakeArr[$sm['s_id']];

			$addTempNumArr[] = [
				'pnt_p_id'=>$p_id,
				'pnt_sample'=>$sm['s_id'],
				'pnt_sign_type'=>$sm['s_sign_type'],
				'pnt_pf_id'=>$sm['sn_pro_factory'],
				'pnt_number'=>$sm['sn_number'],
				'pnt_src'=>$sm['sn_src'],
				'pnt_mk_id'=>$oe_mak_id,
			];
		}
	    errorLog('Begin','setProductBySampleOnlyToPro');

		$opuser = getOpuser();
		$datetime = getNowTime();
		$numidx = new numidx();

		//2022/10/24 提交数据本身重复事务无法去重
		$uniTempNumArr = [];
		foreach($addTempNumArr as $add)
		{
			$add['pnt_formart'] = formatNum($add['pnt_number']);
			if(empty($add['pnt_pf_id']) || empty($add['pnt_formart'])) continue;
			$uniTempNumArr[$add['pnt_pf_id'].'@'.$add['pnt_formart']] = $add;
		}
		
		foreach($uniTempNumArr as $add)
		{
			$add['pnt_innum'] = $proArr['p_innum'];
			$add['pnt_outnum'] = $proArr['p_comnum'];
			$add['opuser'] = $opuser;
			$add['create_time'] = $datetime;
			$add['update_time'] = $datetime;
			$exists = $numidx->checkExistTemp($add);
			if(empty($exists)){
				$addArr['pro_numidx_temp'][] = $add;
			}
		}
	    errorLog(["insert pro_numidx_temp"],'setProductBySampleOnlyToPro');

		//车型转待进入
		$join = [
			"[><]sample(sam)" => ["sml.sml_s_id" => "s_id"],
			"[><]m_model(mm)" => ["sml.sml_mm_id" => "mm_id"],
		];
		$rows = $this->db->select('sample_model_link(sml)', $join, ['sml.*', 'sam.*'], ['sml_s_id'=>$sidArr]);
		$promodel = new promodel();
		foreach($rows as $sm)
		{
			$add = [
				'pmlt_p_id'=>$p_id,
				'pmlt_mm_id'=>$sm['sml_mm_id'],
				'pmlt_cate'=>$sm['s_cate'],
				'pmlt_sample'=>$sm['s_id'],
				'pmlt_innum'=>$proArr['p_innum'],
				'pmlt_outnum'=>$proArr['p_comnum'],
				'pmlt_pos0'=>$sm['sml_pos0'],
				'pmlt_pos1'=>$sm['sml_pos1'],
				'pmlt_pos2'=>$sm['sml_pos2'],
				'pmlt_pos3'=>$sm['sml_pos3'],
				'pmlt_pos4'=>$sm['sml_pos4'],
				'pmlt_pos5'=>$sm['sml_pos5'],
				'pmlt_pos6'=>$sm['sml_pos6'],
				'pmlt_node1'=>$sm['sml_node1'],
				'opuser'=>$opuser,
				'create_time'=>$datetime,
				'update_time'=>$datetime,
			];
			$exists = $promodel->checkExistTemp($add);
			if(empty($exists)){
				$addArr['pro_model_link_temp'][] = $add;
			}
		}
	    errorLog(["insert pro_model_link_temp"],'setProductBySampleOnlyToPro');
		//$this->db->Begin();
		foreach($addArr as $table=>$dvs)
		{
			foreach($dvs as $add){
				$this->db->insert($table, $add);
			}
		}
		//$this->db->end();
	    errorLog([$addArr, "END"],'setProductBySampleOnlyToPro');
		return $sidArr;
	}



	/**
	  * @method 通过编码创建产品
	  * @param  $pc_id  int  [必填] 
	  * @author soul
	  */
	public function addProductByCode($pc_id, $act = '')
	{
		$pcArr = $this->db->get('p_code', '*', ['pc_id'=>$pc_id]);
		if(empty($pcArr)) exitJson('记录不存在');
		if(empty($pcArr['pc_innum'])) exitJson('物料编码不能为空');
		if(empty($pcArr['pc_comnum'])) exitJson('集团中性号不能为空');
		if(empty($pcArr['pc_state_main'])) exitJson('主状态不能为空');
		if(!empty($pcArr['ck3'])) exitJson('记录已审，请勿重复操作');

		if(!\p::catesCheck2('B100', $pcArr['pc_cate'])) exitJson('无此品名权限');

		//查询内部编码是否存在
		$chk = $this->db->get('pro', ['p_id'], ['p_innum'=>$pcArr['pc_innum']]);
		if(!empty($chk)) exitJson('物料编码已被使用');

		$opuser = getOpuser();
		$datetime = getNowTime();
		$p_id = $pcArr['pc_id'];
		$addPro = [
			'p_id'=>$p_id,
			'p_cate'=>$pcArr['pc_cate'],
			'p_lnk_p_id'=>$pcArr['pc_lnk_p_id'],
			'p_mk_id'=>$pcArr['pc_mk_id'],
			'p_pb_id'=>$pcArr['pc_pb_id'],
			'p_innum'=>$pcArr['pc_innum'],
			'p_innum_format'=>$pcArr['pc_innum_format'],
			'p_comnum'=>$pcArr['pc_comnum'],
			'p_comnum_format'=>$pcArr['pc_comnum_format'],
			'p_state_main'=>$pcArr['pc_state_main'],
			'p_opuser'=>$opuser,
			'p_create_time'=>$datetime,
			'p_update_time'=>$datetime,
		];
		$this->db->Begin();

		//基本库
		$this->db->insert('pro', $addPro);
		
		$addNumArr = [];
		
		//主OE
		$addNumArr[] = [
			'pn_is_sys'=>0,
			'pn_pf_id'=>1,
			'pn_mainoe'=>1,
			'pn_number'=>$pcArr['pc_oe'],
			'pn_formart'=>$pcArr['pc_oe_format'],
			'pn_mk_id'=>$pcArr['pc_mk_id'],
		];
		$addNumArr[] = [
			'pn_is_sys'=>1,
			'pn_pf_id'=>3,
			'pn_number'=>$pcArr['pc_innum'],
			'pn_formart'=>$pcArr['pc_innum_format']
		];
		$addNumArr[] = [
			'pn_is_sys'=>1,
			'pn_pf_id'=>2,
			'pn_number'=>$pcArr['pc_comnum'],
			'pn_formart'=>$pcArr['pc_comnum_format']
		];
		
		//菲尔科技追加 OE库数据
		if($pcArr['pc_pb_id'] == 1 && !empty($pcArr['pc_oe_id'])){
			//参数
			$baseInfo = $this->db->get('oe_item', ['oe_para'], ['oe_id'=>$pcArr['pc_oe_id']]);
			if(!empty($baseInfo['oe_para'])){
				$pvals = json_decode($baseInfo['oe_para'], true);
				$paras = $this->formatParaFromTcd($pcArr['pc_cate'], $pvals, $p_id);
				if($paras) $this->param->setParam($paras, $p_id);
			}
			
			//号码
			$rows = $this->db->select('oe_numidx', '*', ['on_oe_id'=>$pcArr['pc_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_mk_id'=>$v['on_mk_id']
				];
			}

			//国际车型
			$rows = $this->db->select('oe_model_link', '*', ['oml_oe_id'=>$pcArr['pc_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'],
						'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'=>$pcArr['pc_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'],
						'opuser'=>$opuser,
						'create_time'=>$datetime,
						'update_time'=>$datetime
					];
					$this->db->insert('pro_model_cn_link', $add);
				}
			}
		}
		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;
				$add['ckuser2'] = $opuser;
				$add['ckresult2'] = 1024;
				$add['cktime2'] = $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', $uniwhere);
				if(empty($exists)){
					$this->db->insert('pro_numidx', $add);
				}
			}
		}
		
		$set = [
			'ck3'=>1,
			'pc_p_id'=>$p_id,
			'opuser'=>$opuser,
			'update_time'=>$datetime,
		];
		
		if($act != 'init' || empty($pcArr['cktime3'])){
			$set['ckuser3'] = $opuser;
			$set['cktime3'] = $datetime;
		}
		if(empty($pcArr['pc_fno_date'])) $set['pc_fno_date'] = $datetime;
				$this->db->update('p_code', $set, ['pc_id' => $pc_id]);

		$this->db->End();
		return ['p_id'=>$p_id, 'p_comnum'=>$pcArr['pc_comnum']];
	}


	/**
	  * @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)));
		//参数字段
		$cateIdArr = array_unique(array_column($itemArr, 'p_cate'));

		$where = ['ptpa_pc_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)
		{
			if(!empty($v['p_pic']))
			{
				$v['main_pic'] = \mvc::$cfg['path']['files'].'/pro/catalog_gsp/'.($v['p_id'] % 100).'/'.$v['p_id'].'big.jpg';
				$v['g_pic'] = \mvc::$cfg['path']['files'].'/pro/catalog_g/'.($v['p_id'] % 100).'/'.$v['p_id'].'big.jpg';
			}

			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', 'ckresult2'], $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'));
			}
			$v['ckresult2']  = !empty($collArr[$v['ckresult2']])? $collArr[$v['ckresult2']]: '';
			$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)', 'pf_is_sys(seq)'],
				'order'=>['pf_is_sys', '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'=>'p_code',
				'key'=>'pc_id',
				'fileds'=>['pc_innum(name)','pc_id(id)'],
				'order'=>['pc_id'],
				'where'=>['pc_pb_id'=>1]
			]
		];
		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);
		}
	}


	/*通过编码找pc_id*/
    public function getPcId($value)
	{
		$where = ['pc_comnum'=>$value];
		return $this->db->get('p_code',"pc_id",$where);
    }




	/**
	  * @method 编码库  
	  * @author soul
	  */
	public function getCodeList($params, $rules = [])
	{
		$filters = $params['filters'];
		$page = $params['page'];
		$pagesize = $params['rows'];
		$sidx = empty($params['sidx'])? 'pc_id': $params['sidx'];
		$sord = empty($params['sord'])? 'asc': $params['sord'];
		$orderby = $params['orderby'];

		$refiled = [
			'cat_name'=>'cat.'.cateName(),
			'pb_name'=>'pb.pb_'.LG_NAME,
			'cat_name_cn'=>'cat.cn_name',
			'cat_name_en'=>'cat.en_name',
			'pcat_name'=>'pcat.'.cateName(),
			'opuser'=>'cod.opuser',
			'create_time'=>'cod.update_time',
			'update_time'=>'cod.update_time',
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'p_code(cod)';
		$join = [
			"[><]pro_cate(cat)" => ["cod.pc_cate" => "id"],
			"[><]pro_brand(pb)" => ["cod.pc_pb_id" => "pb_id"],
			"[><]pro_cate(pcat)" => ["cat.parent_id" => "id"],
			"[>]pro(pro)" => ["cod.pc_p_id" => "p_id"],
			"[>]pro_ext(ext)" => ["pro.p_id" => "pe_p_id"],
			"[>]m_make(mk)" => ["cod.pc_mk_id" => "mk_id"],
		];
	
		$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, 'pc_id', $op, $data, ['tl_type'=>'pro']);
				$data = $res['data'];
				$op = $res['op'];
			}
        });
		
		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$where["AND #num"] = [
						"OR" => [
							'pc_comnum'.($rules['numlike']? '[~]': '') => $val,
							'pc_innum'.($rules['numlike']? '[~]': '') => $val
						]
					];
				break;
			}
		}

		if(!empty($params['keys'])) $where['pc_id'] = explode(',', $params['keys']);
		if(!empty($params['pc_id'])) $where['pc_id'] = $params['pc_id'];
		if(!empty($params['pc_p_id'])) $where['pc_p_id'] = $params['pc_p_id'];
		
		if(isset($params['ck3'])) $where['ck3'] = $params['ck3'];
		if(empty($where['ORDER']))$where['ORDER'] = ['cktime3'=>'DESC', 'pc_id'=>'ASC'];
		$check = new \model\check();
		$ruleWhere = $check->getPowerWhere('p_code', 'B100');
		$where = array_merge($where, $ruleWhere);

        $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)', 'pcat.'.cateName().'(pcat_name)', 'cat.'.cateName().'(cat_name)', 'cat.cn_name(cat_name_cn)','cat.en_name(cat_name_en)', 'p_id', 'pc_innum', 'pc_comnum', 'mk_'.LG_NAME.'(mk_name)', 'pb_'.LG_NAME.'(pb_name)','cod.*', 'ext.*'];
        $arr = $this->db->select($table,$join,$fields,$where);
		if(!empty($arr))
		{
			$carmodel = new carmodel();
			$tags = new tags();
			$collocation = new collocation();
			$collArr = $collocation->getCollItems('pro');
			$verArr = $tags->getTypeValTags('pro', array_column($arr, 'pc_id'));
			$verArr = array_column($verArr, 'tags', 'tl_value_id');
			$codeOpts = $this->getAllCodeOpts();
			foreach($arr as &$v)
			{
				$pe_category = [];
				if(!empty($v['pe_category'])){
					foreach(explode(',', $v['pe_category']) as $t){
						$pe_category[] = $collArr[$t];
					}
				}
				$v['pc_para'] = empty($v['pc_para'])? []:json_decode($v['pc_para'], true);
				$v['tags'] = empty($verArr[$v['pc_id']]) ? '': implode(',', array_column($verArr[$v['pc_id']], 't_id'));
				$v['captions'] = [
					'pc_mk_id'=>$v['mk_name'],
					'pc_item_type'=>!empty($collArr[$v['pc_item_type']])? $collArr[$v['pc_item_type']]: '',
					'pc_unit'=>!empty($collArr[$v['pc_unit']])? $collArr[$v['pc_unit']]: '',
					'pc_fuel'=>!empty($collArr[$v['pc_fuel']])? $collArr[$v['pc_fuel']]: '',
					'pc_progroup'=>!empty($collArr[$v['pc_progroup']])? $collArr[$v['pc_progroup']]: '',
					'pc_state_main'=>\mvc::$cfg['PROSTATUS'][$v['pc_state_main']]? \mvc::$cfg['PROSTATUS'][$v['pc_state_main']]: '',
					'tags'=> empty($verArr[$v['pc_id']]) ? '': implode(',', array_column($verArr[$v['pc_id']], LG_NAME)),
					'pc_rule_1'=>empty($codeOpts['ext'][$v['pc_rule_1']]) ? '': $codeOpts['ext'][$v['pc_rule_1']]['name'],
					'pc_rule_a'=>empty($codeOpts['a'][$v['pc_rule_a']]) ? '': $codeOpts['a'][$v['pc_rule_a']]['name'],
					'pc_rule_b'=>empty($codeOpts['b'][$v['pc_rule_b']]) ? '': $codeOpts['b'][$v['pc_rule_b']]['name'],
					'pc_rule_c'=>empty($codeOpts['c'][$v['pc_rule_c']]) ? '': $codeOpts['c'][$v['pc_rule_c']]['name'],
					'pe_category'=>implode(',', $pe_category)
				];
			}
		}
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	/**
	  * @method 编辑编码库
	  * @param  $pc_id  int  [必填] pc_id
	  * @param  $setArr  array  [必填] ['pc_state_main'=>'',....]
	  * @author soul
	  */
	public function setCodeCell($pc_id, $setArr)
	{
		$result = '';
		//$canSetFiled = ['pc_cate', 'pc_state_main', 'pc_state_sub', 'pc_comnum', 'pc_rule_1', 'pc_rule_a', 'pc_rule_b', 'pc_rule_c', 'pc_usa_make', 'pc_state_remark', 'tags', 'pc_remark', 'pc_sales_qty', 'pc_vio', 'pc_release_time', 'pc_release_vers','nosale_cn'];
		
		if(!empty($pc_id) && !empty($setArr))
		{
			$list = $this->getCodeList(['pc_id'=>$pc_id]);
			$old = $list['rows'][0];
			if(empty($old)) exitJson('记录不存在');

			if(!\p::catesEdit('B100', $old['pc_cate'])) exitJson('无此品名权限');

			$setProArr = [];
			
			foreach($setArr as $filed=>$val)
			{
				//审核后部分字段不允许修改
				//if(!in_array($filed, $canSetFiled) || (!empty($old['ck3']) && in_array($filed, ['pc_comnum', 'pc_rule_1', 'pc_rule_a', 'pc_rule_b', 'pc_rule_c']))
				if((!empty($old['ck3']) && in_array($filed, ['pc_comnum', 'pc_rule_1', 'pc_rule_a', 'pc_rule_b', 'pc_rule_c']))
				){
					unset($setArr[$filed]);
				}
			}
			if(isset($setArr['pc_comnum']) && $setArr['pc_comnum']){
				if($this->db->has('p_code',['pc_id[!]'=>$pc_id,'pc_comnum'=>$setArr['pc_comnum']])){
					exitJson(lg('自动编码').': '.$setArr['pc_comnum'].lg('已经被使用'));
				}
			}
			$tmpsetArr  = $setArr;
			$this->db->Begin();
			if(isset($setArr['tags']))
			{
				$tags = new tags();
				$tagsLinkArr = [['t_id'=>$val, 'value_id'=>$pc_id]];
				$tags->changeTagsLink('pro', 'replace', $tagsLinkArr);
				unset($setArr['tags']);
			}
			if(!empty($setArr))
			{
				$opuser = getOpuser();
				$datetime = getNowTime();
				$setArr['opuser'] = $opuser;
				$setArr['update_time'] = $datetime;
				$this->db->update('p_code', $setArr, ['pc_id'=>$pc_id]);
			}
			//产品日志
			$changeArr =[];
			//获取新的
			$list = $this->getCodeList(['pc_id'=>$pc_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'=>$pc_id,
					'cl_change'=>json_encode(['code'=>$changeArr], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
				$this->db->insert('change_log',$logdata);
			}

			$this->db->End();
		}
		return $result;
	}
	
	/**
	  * @method 变更品名
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @param  cat_id  int  [必填] 品名ID
	  * @author soul
	  */
	public function setCodeCate($ids, $cat_id)
	{
		$pcodeArr = $this->db->select('p_code',['[><]pro_cate'=>['pc_cate'=>'id']],['pc_id','pc_cate',LG_NAME], ['pc_id'=>explode(',', $ids), 'pc_cate[!]'=>$cat_id]);
		$pidArr = array_column($pcodeArr,'pc_id');

		$pcodeArr = array_column($pcodeArr,null,'pc_id');
		
		if(!empty($pidArr))
		{
			$this->db->Begin();
			$opuser = getOpuser();
			$datetime = getNowTime();
			$setArr = [
				'opuser'=>$opuser,
				'update_time'=>$datetime,
				'pc_cate'=>$cat_id,
			];
			$this->db->update('p_code', $setArr, ['pc_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'=>'pc_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->db->End();
		}
		return[];
	}

	/**
	  * @method 变更国内未下单
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @param  val  int  [必填] 0|1
	  * @author soul
	  */
	public function setCnNosale($ids, $val)
	{
		$val = $val? 1: 0;
		$pidArr = $this->db->select('p_code', 'pc_id', ['pc_id'=>explode(',', $ids), 'nosale_cn[!]'=>$val]);
		if(!empty($pidArr))
		{
			$opuser = getOpuser();
			$datetime = getNowTime();
			$setArr = [
				'opuser'=>$opuser,
				'update_time'=>$datetime,
				'nosale_cn'=>$val,
			];
			$this->db->update('p_code', $setArr, ['pc_id'=>$pidArr]);
		}
		return[];
	}

	/**
	  * @method 变更主状态
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @author soul
	  */
	public function changeStateMain($idArr, $dataArr)
	{
		$this->db->Begin();
		if(!empty($idArr) && !empty($dataArr['pc_state_main']) && !empty($dataArr['pc_state_remark']))
		{
			$setArr = [
				'pc_state_main'=>$dataArr['pc_state_main'],
				'pc_state_remark'=>$dataArr['pc_state_remark'],
			];
			foreach($idArr as $pc_id)
			{
				$this->setCodeCell($pc_id, $setArr);
			}
		}
		$this->db->End();
		return [];
	}


	/**
	  * @method 删除编码库  已审或者来自样品的不允许
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @author soul
	  */
	public function delCode($idArr)
	{
		if(!empty($idArr))
		{
			//物理删除
			$arr = $this->db->select('p_code', '*', ['pc_id'=>$idArr]);
			$this->db->Begin();
			$this->db->delete('p_code', ['pc_id'=>$idArr]);
			//删除记录
			foreach ($arr as $item) 
			{
				$log = [
					'cl_type'=>'pro',
					'cl_act'=>'del',
					'cl_dataid'=>$item['pc_id'],
					'cl_change'=>json_encode(['code'=>[$item]], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
				$this->db->insert('change_log', $log);
			}

			$this->db->delete('pro', ['p_id'=>$idArr]);
			$this->db->delete('pro_bom_assemble', ['pba_p_id'=>$idArr]);
			$this->db->delete('pro_bom_pack', ['pbp_p_id'=>$idArr]);
			$this->db->delete('pro_ext', ['pe_p_id'=>$idArr]);
			$this->db->delete('pro_model_cn_link', ['pml_p_id'=>$idArr]);
			$this->db->delete('pro_model_link', ['pml_p_id'=>$idArr]);
			$this->db->delete('pro_model_link', ['pml_p_id'=>$idArr]);
			$this->db->delete('pro_numidx', ['pn_p_id'=>$idArr]);
			$this->db->delete('pro_pack', ['pp_p_id'=>$idArr]);
			$this->db->delete('pro_pack_ext', ['ppe_p_id'=>$idArr]);
			$this->db->delete('pro_param_val', ['ppv_p_id'=>$idArr]);
			$this->db->delete('pro_source_link', ['psl_p_id'=>$idArr]);
			$this->db->delete('pro_supplier', ['psu_p_id'=>$idArr]);
			$this->db->delete('pro_fatherson', ['OR'=>['pf_father_pid'=>$idArr,'pf_son_pid'=>$idArr]]);
			$this->db->delete('pro_exchange', ['OR'=>['pe_p_id1'=>$idArr,'pe_p_id2'=>$idArr]]);
			$this->db->delete('pro_pair', ['OR'=>['pp_p_id1'=>$idArr,'pp_p_id2'=>$idArr]]);
			
			$this->db->End();

			/*$where = [
				'pc_id'=>$idArr,
				"AND" =>[
					"OR"=>[
						'ck3'=>1,
						//'pc_s_id[>=]'=>1,
					]
				]
			];
			$row = $this->db->get('p_code', 'pc_id', $where);
			if(!empty($row)) exitJson('已审记录禁止删除');

			$arr = $this->db->select('p_code', ['*'],['ck3'=>0,'pc_id'=>$idArr]);
			$this->db->Begin();

			$this->db->delete('p_code', ['ck3'=>0, 'pc_id'=>$idArr]);
			//删除记录
			foreach ($arr as $item) 
			{
				$log = [
					'cl_type'=>'pro',
					'cl_act'=>'del',
					'cl_dataid'=>$item['pc_id'],
					'cl_change'=>json_encode(['code'=>$item], JSON_UNESCAPED_UNICODE),
					'cl_opuser'=>getOpuser(),
					'cl_create_time'=>getNowTime(),
				];
				$this->db->insert('change_log', $log);
			}
			$this->db->End();*/
		}
		return [];
	}
	

	/**
	  * @method 生成编码
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @author soul
	  */
	public function buildCode($idArr, $auto = 1, $pcr_id = 0)
	{
		if(!empty($idArr))
		{
			$row = $this->db->get('p_code', 'pc_id', ['pc_id'=>$idArr,'ck3'=>1]);
			if(!empty($row)) exitJson('已审记录禁止操作');

			$codeRule = new \model\pro\codeRule();
			$this->db->Begin();
			foreach($idArr as $pc_id)
			{
				$pcArr = $this->db->get('p_code', '*', ['pc_id'=>$pc_id]);
				$pcCate = $pcArr['pc_cate'];
				if(empty($pcArr)) exitJson('记录不存在');
				if(empty($pcArr['pc_innum'])) exitJson('内部编码不存在');
				if(!empty($pcArr['pc_samseq']))
				{
					if($auto)
					{
						$codeArr = $codeRule->createCode($pcArr['pc_samseq'], $pcArr['pc_innum']);
					}
					else
					{
						$codeArr = $codeRule->createCode($pcArr['pc_samseq'], $pcArr['pc_innum'], $pcr_id);
					}
				}
				else
				{
					$ruleArr = [
						's_cate'=>$pcArr['pc_cate'],
						's_procode_ext'=>$pcArr['pc_rule_1'],
						's_procode_a'=>$pcArr['pc_rule_a'],
						's_procode_b'=>$pcArr['pc_rule_b'],
						's_procode_c'=>$pcArr['pc_rule_c'],
						's_usa_make'=>$pcArr['pc_usa_make'],
					];
					if($auto)
					{
						$codeArr = $codeRule->createCodeByValues($ruleArr, $pcArr['pc_innum']);
					}
					else
					{
					    $ruleCate = $this->db->get('pro_code_rule', 'pcr_cate', ['pcr_id' => $pcr_id]);
						if($pcCate!=$ruleCate){
							exitJson($pcArr['pc_innum'].' '.lg('生成失败,所选型号品名与规则品名不一至'));
						}
						$codeArr = $codeRule->createCodeByValues($ruleArr, $pcArr['pc_innum'], $pcr_id);
					}
				}
				if($codeArr['code']==1)
				{
					if(!empty($pcArr['pc_s_id']))
					{
						$set = [
							's_stop'=>1,
							's_innum'=>$pcArr['pc_innum'],
							's_auto_nums'=>json_encode($codeArr['data']),
							'update_time'=>$datetime
						];
						$this->db->update('sample', $set, ['s_id' => $pcArr['pc_s_id']]);
					}

					$opuser = getOpuser();
					$datetime = getNowTime();
					$set = [
						's_stop'=>1,
						's_auto_nums'=>json_encode($codeArr['data']),
						'update_time'=>$datetime
					];
					$this->db->update('sample', $set, ['s_id' => $s_id]);
					
					$setPc = [
						'opuser'=>$opuser,
						'update_time'=>$datetime
					];
					$newArr = [];
					//{"OUTNUM":{"areaId":0,"areaName":"","brandId":2,"brandName":"OUTNUM","num":"NCV50025","seq":0},"NTK":[{"areaId":0,"areaName":"","brandId":"5","brandName":"NTK","num":"NCV50025"}]}
					foreach($codeArr['data'] as $fname=>$tarr)
					{
						if($fname == 'OUTNUM')
						{
							$setPc['pc_comnum'] = $tarr['num'];
							$setPc['pc_seq'] = $tarr['seq'];
							$setPc['pc_seq_group'] = $tarr['seq_group'];
							$tarr = [$tarr];
						}
					}
					$this->db->update('p_code', $setPc, ['pc_id' => $pc_id]);
				}else{
					exitJson($codeArr['msg']);
				}
			}
			$this->db->End();
		}
		return [];
	}


	public function autoBuildCode($idArr,$auto=false)
	{
		if(!empty($idArr))
		{
			$rows = $this->db->select('p_code', '*', ['pc_id'=>$idArr,'ck3'=>0]);
			$codeRule = new \model\pro\codeRule();
			//$this->db->Begin();
			foreach($rows as $pcArr)
			{
				$pc_id = $pcArr['pc_id'];
				if(!empty($pcArr['pc_samseq']))
				{
					if($auto)
					{
						$codeArr = $codeRule->createCode($pcArr['pc_samseq'], $pcArr['pc_innum'],'',$pcArr['pc_comnum'],$pcArr['pc_seq']);
					}
					else
					{
						$codeArr = $codeRule->createCode($pcArr['pc_samseq'], $pcArr['pc_innum'], $pcr_id,$pcArr['pc_comnum'],$pcArr['pc_seq']);
					}
				}
				else
				{
					$ruleArr = [
						's_cate'=>$pcArr['pc_cate'],
						's_procode_ext'=>$pcArr['pc_rule_1'],
						's_procode_a'=>$pcArr['pc_rule_a'],
						's_procode_b'=>$pcArr['pc_rule_b'],
						's_procode_c'=>$pcArr['pc_rule_c'],
						's_usa_make'=>$pcArr['pc_usa_make'],
					];
					if($auto)
					{
						$codeArr = $codeRule->createCodeByValues($ruleArr, $pcArr['pc_innum'],'',$pcArr['pc_comnum'],$pcArr['pc_seq']);
					}
					else
					{
						$codeArr = $codeRule->createCodeByValues($ruleArr, $pcArr['pc_innum'], $pcr_id,$pcArr['pc_comnum'], $pcArr['pc_seq']);
					}
				}
				if($codeArr['code']==1)
				{
					$opuser = getOpuser();
					$datetime = getNowTime();
					$set = [
						's_stop'=>1,
						's_auto_nums'=>json_encode($codeArr['data']),
						'update_time'=>$datetime
					];
					$this->db->update('sample', $set, ['s_id' => $s_id]);
					
					$setPc = [
						'opuser'=>$opuser,
						'update_time'=>$datetime
					];
					$newArr = [];
					$outnum = '';
					//{"OUTNUM":{"areaId":0,"areaName":"","brandId":2,"brandName":"OUTNUM","num":"NCV50025","seq":0},"NTK":[{"areaId":0,"areaName":"","brandId":"5","brandName":"NTK","num":"NCV50025"}]}
					foreach($codeArr['data'] as $fname=>$tarr)
					{
						if($fname == 'OUTNUM')
						{
							$outnum = $tarr['num'];
							$setPc['pc_comnum'] = $tarr['num'];
							$setPc['pc_seq'] = $tarr['seq'];
							$setPc['pc_seq_group'] = $tarr['seq_group'];
							$tarr = [$tarr];
						}
					}
					if(!empty($pcArr['pc_s_id']))
					{
						$set = [
							's_stop'=>1,
							's_innum'=>$pcArr['pc_innum'],
							//'s_outnum'=>$outnum,
							's_p_id'=>$pcArr['pc_id'],
							's_auto_nums'=>json_encode($codeArr['data']),
							'update_time'=>$datetime
						];
						$this->db->update('sample', $set, ['s_id' => $pcArr['pc_s_id']]);
					}
					$this->db->update('p_code', $setPc, ['pc_id' => $pc_id]);
				}
			}
			//$this->db->End();
		}
		return [];
	}

	
	/**
	  * @method 审核编码
	  * @param  ids  string  [必填] pc_id  多个逗号分隔
	  * @author soul
	  */
	public function checkCode($idArr)
	{
		if(!empty($idArr))
		{
			$this->db->Begin();
			foreach($idArr as $pc_id)
			{
				$this->addProductByCode($pc_id);
			}
			$this->db->End();
		}
		return[];
	}

	

	//所有编码规则的枚举值
	public function getAllCodeOpts()
	{
		$tableArr = [
			'ext'=>'pro_code_ext',
			'a'=>'pro_code_a',
			'b'=>'pro_code_b',
			'c'=>'pro_code_c',
		];
		$arr = [];
		foreach($tableArr as $k=>$table)
		{
			 $rows = $this->db->select($table, '*');
			 $arr[$k] = array_column($rows, null, 'id');
		}
		return $arr;
	}


	public function addMerge($p_id_from, $p_id_to)
	{
		$proArr = $this->db->select('p_code', ['pc_p_id', 'pc_comnum', 'pc_cate', 'pc_merge_p_id'], ['pc_p_id'=>[$p_id_from, $p_id_to]]);
		if(count($proArr) != 2) exitJson(lg('请选择两个产品进行合并'));
		$proArr = array_column($proArr, null, 'pc_p_id');
		if($proArr[$p_id_from]['pc_cate'] != $proArr[$p_id_to]['pc_cate']) exitJson(lg('不同品类禁止合并'));
		if(!empty($proArr[$p_id_to]['pc_merge_p_id'])) exitJson(lg($proArr[$p_id_to]['pc_comnum'].'不能再次成为合并后集团中性号'));
		
		$check = new check();
		$proCateRule = $check->checkProRuleCate([$p_id_from], 'B600', 'add');
		if(in_array($p_id_from, $proCateRule['no']))  exitJson(lg('无此品名权限'));
		
		$opuser = getOpuser();
		$datetime = getNowTime();
		$addArr = [
			'pch_status'=>0,
			'pch_p_id_from'=>$p_id_from,
			'pch_p_id_to'=>$p_id_to,
			'create_time'=>$datetime,
			'update_time'=>$datetime,
			'opuser'=>$opuser
		];
		$check = new check();
		$exist = $check->checkExist('pro_merge', $addArr);
		if(!empty($exist)) exitJson('记录已存在');
		$this->db->insert('pro_merge', $addArr);
		$pch_id = $this->db->id();
		return ['id'=>$pch_id];
	}


	public function getMergeList($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 = [
			'p_innumf'=>'prof.p_innum',
			'p_comnumf'=>'prof.p_comnum',
			'p_innumt'=>'prot.p_innum',
			'p_comnumt'=>'prot.p_comnum',
			'cat_namef'=>'catf.'.cateName(),
			'pcat_namef'=>'pcatf.'.LG_NAME
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro_merge(pch)';
		$join = [
			"[>]pro(prof)" => ["pch.pch_p_id_from" => "p_id"],
			"[><]pro_cate(catf)" => ["prof.p_cate" => "id"],
			"[><]pro_cate(pcatf)" => ["catf.parent_id" => "id"],
			"[>]pro(prot)" => ["pch.pch_p_id_to" => "p_id"]
			
		];
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
        });

		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$where["AND #num"] = [
						"OR" => [
							'prof.p_comnum'.($rules['numlike']? '[~]': '') => $val,
							'prof.p_innum'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_comnum'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_innum'.($rules['numlike']? '[~]': '') => $val
						]
					];
				break;
			}
		}
		if(!empty($params['keys'])) $where['pch_id'] = explode(',', $params['keys']);
		if(!empty($params['pch_id'])) $where['pch_id'] = $params['pch_id'];
		if(isset($params['ck3'])) $where['ck3'] = $params['ck3'];
		if(!empty($params['p_id']))
		{
			$where["AND #pro"] = [
				"OR" => [
					'pch_p_id_from'=>$params['p_id'],
					'pch_p_id_to'=>$params['p_id'],
				]
			];
		}

		$check = new \model\check();
		$ruleWhere = $check->getPowerWhere('pro_merge', 'B600');
		$where = array_merge($where, $ruleWhere);

        $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 = ['pcatf.'.LG_NAME.'(pcat_namef)', 'catf.'.cateName().'(cat_namef)', 'prof.p_innum(p_innumf)', 'prof.p_comnum(p_comnumf)', 'prot.p_innum(p_innumt)', 'prot.p_comnum(p_comnumt)', 'pch.*'];
        $arr = $this->db->select($table,$join,$fields,$where);
        //dd($this->db->last());
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

    //qg临时屏蔽2022-07-22 原函数 getMergeEndList($params, $rules = [])
	public function getMergeEndList($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 = [
			'p_innumf'=>'prof.p_innum',
			'p_comnumf'=>'prof.p_comnum',
			'p_innumt'=>'prot.p_innum',
			'p_comnumt'=>'prot.p_comnum',
			'cat_namef'=>'catf.'.cateName(),
			'pcat_namef'=>'pcatf.'.LG_NAME
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro_merge(pch)';
		$join = [
			"[><]p_code(pcrof)" => ["pch.pch_p_id_from" => "pc_p_id"],
			"[><]pro(prof)" => ["pch.pch_p_id_from" => "p_id"],
			"[><]pro_cate(catf)" => ["prof.p_cate" => "id"],
			"[><]pro_cate(pcatf)" => ["catf.parent_id" => "id"],
			"[><]pro(prot)" => ["pcrof.pc_merge_p_id" => "p_id"] 
		];
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
        });

		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$where["AND #num"] = [
						"OR" => [
							'prof.p_comnum_format'.($rules['numlike']? '[~]': '') => $val,
							'prof.p_innum_format'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_comnum_format'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_innum_format'.($rules['numlike']? '[~]': '') => $val
						]
					];
				break;
			}
		}
		$where['pch.ck3'] = 1;
		$where['pch.pch_isback'] = 0;
		
		$check = new \model\check();
		$ruleWhere = $check->getPowerWhere('pro_merge', '1B00');
		$where = array_merge($where, $ruleWhere);

        $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 = ['pcatf.'.LG_NAME.'(pcat_namef)', 'catf.'.cateName().'(cat_namef)', 'prof.p_innum(p_innumf)', 'prof.p_comnum(p_comnumf)', 'prot.p_innum(p_innumt)', 'prot.p_comnum(p_comnumt)', 'pch.*','pc_merge_p_id','pc_merge_time'];
        $arr = $this->db->select($table,$join,$fields,$where);
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}
    //qg临时处理   soul 9400114合并异常 恢复原代码
	public function getMergeEndList_20220915($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 = [
			'p_innumf'=>'prof.p_innum',
			'p_comnumf'=>'prof.p_comnum',
			'p_innumt'=>'prot.p_innum',
			'p_comnumt'=>'prot.p_comnum',
			'cat_namef'=>'catf.'.cateName(),
			'pcat_namef'=>'pcatf.'.LG_NAME
		];
		$this->set('refiled', $refiled);
		$sidx =  strtr($sidx, $refiled);

		$table = 'pro_merge(pch)';
		$join = [
			"[><]p_code(pcrof)" => ["pch.pch_p_id_from" => "pc_p_id"],
			"[><]pro(prof)" => ["pch.pch_p_id_from" => "p_id"],
			"[><]pro_cate(catf)" => ["prof.p_cate" => "id"],
			"[><]pro_cate(pcatf)" => ["catf.parent_id" => "id"],
			//qg临时屏蔽2022-07-22
			//"[><]pro(prot)" => ["pcrof.pc_merge_p_id" => "p_id"] 
			"[>]pro(prot)" => ["pch.pch_p_id_to" => "p_id"]
		];
        $where = $this->filter2medoo($filters,function(&$field,&$op,&$data){
			$field = strtr( $field, $this->get('refiled'));
        });

		foreach($rules as $filed=>$val)
		{
			if(empty($val)) continue;
			switch($filed)
			{
				case 'numbers':
					$where["AND #num"] = [
						"OR" => [
							'prof.p_comnum_format'.($rules['numlike']? '[~]': '') => $val,
							'prof.p_innum_format'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_comnum_format'.($rules['numlike']? '[~]': '') => $val,
							'prot.p_innum_format'.($rules['numlike']? '[~]': '') => $val
						]
					];
				break;
			}
		}
		$where['pch.ck3'] = 1;
		$where['pch.pch_isback'] = 0;
		
		$check = new \model\check();
		$ruleWhere = $check->getPowerWhere('pro_merge', '1B00');
		$where = array_merge($where, $ruleWhere);

        $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];
		}
		//qg临时屏蔽2022-07-22
		/*
		$fields = ['pcatf.'.LG_NAME.'(pcat_namef)', 'catf.'.cateName().'(cat_namef)', 'prof.p_innum(p_innumf)', 'prof.p_comnum(p_comnumf)', 'prot.p_innum(p_innumt)', 'prot.p_comnum(p_comnumt)', 'pch.*','pc_merge_p_id','pc_merge_time'];
		*/
		$fields = ['pcatf.'.LG_NAME.'(pcat_namef)', 'catf.'.cateName().'(cat_namef)', 'prof.p_innum(p_innumf)', 'prof.p_comnum(p_comnumf)', 'prot.p_innum(p_innumt)', 'prot.p_comnum(p_comnumt)', 'pch.*','pch.update_time(pc_merge_time)'];
		//end qg
		
        $arr = $this->db->select($table,$join,$fields,$where);
        //dd($this->db->last());
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $arr
		];
		return $data;
	}

	public function delMerge($idArr)
	{
		if(!empty($idArr))
		{
			$where = [
				'pch_id'=>$idArr,
				'ck3'=>1,
				'pch_isback'=>0,
			];
			$row = $this->db->get('pro_merge', 'pch_id', $where);
			if(!empty($row)) exitJson('已审记录禁止删除');
			$delwhere = [
				'OR'=>[
					'ck3'=>0,
					'pch_isback'=>1,
				],
				'pch_id'=>$idArr
			];
			$this->db->delete('pro_merge', $delwhere);
		}
		return [];
	}

	//审核合并
	public function checkMerge($idArr, $params = [])
	{
		if(!empty($idArr))
		{
			$opuser = getOpuser();
			$datetime = getNowTime();
			$numidx = new \model\pro\numidx();
			$promodel = new \model\pro\promodel();
			$check = new check();
			$this->db->Begin();
			$pchArr = $this->db->select('pro_merge', '*', ['ck3'=>0, 'pch_id'=>$idArr]);
			
			foreach($pchArr as $pch)
			{
				$join = [
					"[><]p_code(pc)" => ["p.p_id" => "pc_p_id"],	
				];
				$proArr = $this->db->select('pro(p)', $join, '*', ['p_id'=>[$pch['pch_p_id_from'], $pch['pch_p_id_to']]]);
				$proArr = array_column($proArr, null, 'p_id');
				if(count($proArr) != 2) exitJson(lg('集团中性号不存在'));
				$fromPro = $proArr[$pch['pch_p_id_from']];
				$toPro = $proArr[$pch['pch_p_id_to']];

				if($fromPro['p_cate'] != $toPro['p_cate']) exitJson(lg('不同品类禁止合并'));

				if(!empty($toPro['pc_merge_p_id'])) exitJson(lg($toPro['pc_comnum'].'不能再次成为合并后集团中性号'));
				
				//交叉号
				$setMergeArr = [
					'pch_from'=>$fromPro,
					'pch_numidx_to'=>[],
					'pch_model_to'=>[],
					'pch_modelcn_to'=>[],
					'ck3'=>1,
					'pch_status'=>1,
					'ckuser3'=>$opuser,
					'opuser'=>$opuser,
					'update_time'=>$datetime,
					'cktime3'=>$datetime
				];
				if(!empty($params['remark'])) $setMergeArr['remark'] = $params['remark'];

				$rows = $this->db->select('pro_numidx', '*', ['pn_is_sys'=>0, 'pn_p_id'=>$fromPro['p_id']]);
				foreach($rows as $org)
				{
					$set = $org;
					unset($set['pn_id']);
					$set['pn_p_id'] = $toPro['p_id'];
					if(empty($org['pn_merge_remark'])) $set['pn_merge_remark'] = $fromPro['p_comnum'];
					$exists = $numidx->checkExist($set, $org['pn_id']);
					if(!empty($exists)) exitJson($exists['msg']);
					$this->db->insert('pro_numidx', $set);
					$set['pn_id'] = $this->db->id();
					//数据版本
					$tres = $this->db->select('tags_link', '*', ['tl_type'=>'number', 'tl_value_id'=>$org['pn_id']]);
					if(!empty($tres))
					{
						foreach($tres as $tv)
						{
							$tv['tl_value_id'] = $set['pn_id'];
							$this->db->insert('tags_link', $tv);
						}
					}
					$setMergeArr['pch_numidx_to'][] = ['set'=>$set, 'fromid'=>$org['pn_id'], 'newid'=>$set['pn_id']];
				}
				
				$rows = $this->db->select('pro_model_link', '*', ['pml_p_id'=>$fromPro['p_id']]);
				foreach($rows as $org)
				{
					$set = $org;
					unset($set['pml_id']);
					$set['pml_p_id'] = $toPro['p_id'];
					if(empty($org['pml_merge_remark'])) $set['pml_merge_remark'] = $fromPro['p_comnum'];
					$exists = $promodel->checkExist($set, $org['pml_id']);
					if(!empty($exists)) exitJson($exists['msg']);
					$this->db->insert('pro_model_link', $set);
					$set['pml_id'] = $this->db->id();
					
					//其他关联表
					$links = $this->db->select('pro_model_area_link', '*', ['pma_pml_id'=>$org['pml_id']]);
					foreach($links as $tl)
					{
						$tl['pma_pml_id'] = $set['pml_id'];
						$this->db->insert('pro_model_area_link', $tl);
					}
					$setMergeArr['pch_model_to'][] = ['set'=>$set, 'fromid'=>$org['pml_id'], 'newid'=>$set['pml_id']];
				}

				$rows = $this->db->select('pro_model_cn_link', '*', ['pml_p_id'=>$fromPro['p_id']]);
				foreach($rows as $org)
				{
					$set = $org;
					unset($set['pml_id']);
					$set['pml_p_id'] = $toPro['p_id'];
					if(empty($org['pml_merge_remark'])) $set['pml_merge_remark'] = $fromPro['p_comnum'];
					$exists = $check->checkExist('pro_model_cn_link', $set, $org['pml_id']);
					if(!empty($exists)) continue;
					$this->db->insert('pro_model_cn_link', $set);
					$set['pml_id'] = $this->db->id();
					$setMergeArr['pch_modelcn_to'][] = ['set'=>$set, 'fromid'=>$org['pml_id'], 'newid'=>$set['pml_id']];
				}
				
				//合并链条相关的产品历史
				$lnkpid = $this->getMergeLink($fromPro['p_id']);
				$setPcArr = [
					'pc_state_main'=>'Y5',
					'pc_state_remark'=>'合并为'.$toPro['p_comnum'],
					'pc_remark'=>'合并为'.$toPro['p_comnum'],
					'pc_merge_p_id'=>$toPro['p_id'],
					'pc_merge_time'=>$datetime,
					'opuser'=>$opuser,
					'update_time'=>$datetime,
				];
				$lnkpid[] = $fromPro['p_id'];
				if(!empty($lnkpid))
				{
					$olf = array_keys($setPcArr);
					$olf[] = 'pc_p_id';
					$rows = $this->db->select('p_code', $olf, ['pc_p_id'=>$lnkpid]);
					$setMergeArr['pch_from']['linklast'] = $rows;
				}
				$this->db->update('p_code', $setPcArr, ['pc_p_id'=>$lnkpid]);
				
				foreach($setMergeArr as $fk=>$fv)
				{
					if(is_array($fv))
						$setMergeArr[$fk] = json_encode($fv);
				}
				$this->db->update('pro_merge', $setMergeArr, ['pch_id'=>$pch['pch_id']]);
			}
			$this->db->End();
		}
		return [];
	}

	//合并恢复
	public function rollbackMerge($pch_id, $params = [])
	{
		$opuser = getOpuser();
		$datetime = getNowTime();
		$pch = $this->db->get('pro_merge', '*', ['pch_isback'=>0, 'pch_status'=>1, 'ck3'=>1, 'pch_id'=>$pch_id]);
		if(!empty($pch))
		{
			$numidx = new \model\pro\numidx();
			$promodel = new \model\pro\promodel();

			$this->db->Begin();
			$pch['pch_from'] = json_decode($pch['pch_from'], true);
			$pch['pch_numidx_to'] = json_decode($pch['pch_numidx_to'], true);
			$pch['pch_model_to'] = json_decode($pch['pch_model_to'], true);
			$pch['pch_modelcn_to'] = json_decode($pch['pch_modelcn_to'], true);

			//不参与比较的字段
			$uncomfiled = ['pn_id', 'pn_p_id', 'warn', 'update_time', 'opuser','pn_merge_remark'];
			foreach($pch['pch_numidx_to'] as $mrow)
			{
				$comrows = $this->db->select('pro_numidx', '*', ['pn_id'=>[$mrow['fromid'], $mrow['newid']]]);
				$md5Arr = [];
				foreach($comrows as $k=>$row)
				{
					foreach($uncomfiled as $filed)
					{
						unset($row[$filed]);
					}
					$md5Arr[] = md5(json_encode($row));
				}
				
				if(count($md5Arr) == 2 && $md5Arr[0] == $md5Arr[1])
				{
					$this->db->delete('pro_numidx', ['pn_id'=>$mrow['newid']]);
					//数据版本
					$this->db->delete('tags_link', ['tl_type'=>'number', 'tl_value_id'=>$mrow['newid']]);
					//$numidx->delNumidx($mrow['newid'], '合并数据恢复');
				}
			}

			//不参与比较的字段
			$uncomfiled = ['pml_id', 'pml_p_id', 'warn', 'update_time', 'opuser','pml_merge_remark'];
			foreach($pch['pch_model_to'] as $mrow)
			{
				$comrows = $this->db->select('pro_model_link', '*', ['pml_id'=>[$mrow['fromid'], $mrow['newid']]]);
				$md5Arr = [];
				foreach($comrows as $k=>$row)
				{
					foreach($uncomfiled as $filed)
					{
						unset($row[$filed]);
					}
					$row['area'] = $this->db->select('pro_model_area_link', ['pma_ma_id', 'pma_catalog_notes'], ['pma_pml_id'=>$row['pml_id'], 'ORDER'=>'pma_ma_id']);
					$md5Arr[] = md5(json_encode($row));
				}
				if(count($md5Arr) == 2 && $md5Arr[0] == $md5Arr[1])
				{
					$this->db->delete('pro_model_link', ['pml_id'=>$mrow['newid']]);
					$this->db->delete('pro_model_area_link', ['pma_pml_id'=>$mrow['newid']]);
					//$promodel->delProModel($row['newid'], '合并数据恢复', 'del');
				}
			}


			//不参与比较的字段
			$uncomfiled = ['pml_id', 'pml_p_id', 'update_time', 'opuser','pml_merge_remark'];
			foreach($pch['pch_modelcn_to'] as $mrow)
			{
				$comrows = $this->db->select('pro_model_cn_link', '*', ['pml_id'=>[$mrow['fromid'], $mrow['newid']]]);
				$md5Arr = [];
				foreach($comrows as $k=>$row)
				{
					foreach($uncomfiled as $filed)
					{
						unset($row[$filed]);
					}
					$md5Arr[] = md5(json_encode($row));
				}
				if(count($md5Arr) == 2 && $md5Arr[0] == $md5Arr[1])
				{
					$this->db->delete('pro_model_cn_link', ['pml_id'=>$mrow['newid']]);
				}
			}
			
			//恢复相关联数据
			if(is_array($pch['pch_from']) && !empty($pch['pch_from']['linklast']))
			{
				foreach($pch['pch_from']['linklast'] as $row)
				{
					$row['opuser'] = $opuser;
					$row['update_time'] = $datetime;
					$this->db->update('p_code', $row, ['pc_p_id'=>$row['pc_p_id']]);
				}
			}
			
			$set = [
				'pch_isback'=>1,
				'opuser'=>$opuser,
				'update_time'=>$datetime,
				'back_time'=>$datetime,
			];
			if(!empty($params['remark'])) $set['remark'] = $params['remark'];
			$this->db->update('pro_merge', $set, ['pch_id'=>$pch['pch_id']]);
			$this->db->End();
		}
		return [];
	}

	//获取产品ID对应的合并链条  $type all || merge
	public function getMergeLink($pid, &$linkPid = [])
	{
		$rows = $this->db->select('pro_merge', 'pch_p_id_from', ['pch_status'=>1, 'pch_isback'=>0,'pch_p_id_to'=>$pid]);
		if(!empty($rows))
		{
			$linkPid = array_merge($linkPid, $rows);
			$this->getMergeLink($rows, $linkPid);
		}
		return array_unique($linkPid);
	}

	public function getMergeHistory($pid, &$pchids = [])
	{
		if(!is_array($pid)) $pid = [$pid];
		$where = ['pch_status'=>1, 'pch_isback'=>0, 'pch_p_id_from'=>$pid];
		if(!empty($pchids))
		{
			$where['pch_id[!]'] = $pchids;
		}  
		
		$rows = $this->db->select('pro_merge', ['pch_id', 'pch_p_id_from', 'pch_p_id_to'], $where);
		if(!empty($rows))
		{
			$tpids = [];
			foreach($rows as $v)
			{
				if(!in_array($v['pch_p_id_from'], $pid)) $tpids[] = $v['pch_p_id_from'];
				if(!in_array($v['pch_p_id_to'], $pid)) $tpids[] = $v['pch_p_id_to'];
				$pchids[] = $v['pch_id'];
			}
			if(!empty($tpids))
			{
				$this->getMergeHistory($tpids, $pchids);
			}
		}
		return array_unique($pchids);
	}


	public function getMergeFrom($pid, &$pch = [])
	{
		if(!is_array($pid)) $pid = [$pid];
		$where = ['pch_status'=>1, 'pch_isback'=>0, 'pch_p_id_to'=>$pid];
		if(!empty($pch))
		{
			$where['pch_id[!]'] = array_column($pch, 'pch_id');
		}  
		$join = [
			"[><]pro(p)" => ["pm.pch_p_id_from" => "p_id"],
		];
		$rows = $this->db->select('pro_merge(pm)', $join, ['pch_id', 'p_comnum', 'pch_p_id_from', 'cktime3'], $where);
		if(!empty($rows))
		{
			$tpids = [];
			foreach($rows as $v)
			{
				if(!in_array($v['pch_p_id_from'], $pid)) $tpids[] = $v['pch_p_id_from'];
				$pch[] = $v;
			}
			if(!empty($tpids))
			{
				$this->getMergeFrom($tpids, $pch);
			}
		}
		return array_unique($pch);
	}


	//型号通用汇总（通用，父子，通用手工）
	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];
	}

	/**
	 * @param  [int] $p_id 产品ID
	 * @method 获取指定产品投诉总数
	 * @author zhengweihua 
	 * @copyright 2022-06-17
	 */
	public function getTousuNum($p_id)
	{
		return [];
		//投诉记录
		$tousuCount =$this->db->select('pro_tousu',['sam_count'=>raw('count(*)')],['pt_p_id'=>$p_id]);
		$tousu_num = empty($tousuCount[0]['sam_count'])?0:$tousuCount[0]['sam_count'];
		return $tousu_num;
	}

	/**
	 * @param  [string] $cnTxt 中文内容
	 * @method 获取BOM英文内容
	 */
	public function getBomEnTxt($cnTxt)
	{
		return $this->db->get('bom_kv','en',['cn'=>$cnTxt]);
	}
	
	/**
	 * @method 通过产品ID获取样品ID
	 * @param  [int] $pid 产品ID
	 */
	public function getSampleId($pid)
	{
		return $this->db->get('p_code','pc_s_id',['pc_p_id'=>$pid]);
	}

	/**
	 * @method BOM 翻译信息
	 */
	public function getBomKv()
	{
		return $this->db->select('bom_kv','*');
	}

	/**
	 * @method 取库存
	 */
	public function getStock($outnum)
	{
		$result = $this->db->get('pro_stock','ps_qty',['ps_outnum'=>$outnum]);
        return $result ? $result : '';
	}

	/**
	 * edit ceil 值修改
	 * @return array
	 */
	function getMasAttaqtyByPid($key){
		return $this->db->get('pro_masattaqty','*',['pa_p_id'=>$key]);;
	}

	function setMasAttaqty($key,$field,$value){
        $result = 200;
        if($result== 200) {
			$this->db->replace('pro_masattaqty',['pa_p_id'=>$key,$field=>$value],['pa_p_id']);
		}
		return $result;
	}


	//审核OE库到产品库需要的信息
	function getBuildProByOeInfo($oe_id){
		$arr = $this->db->get('oe_item', ['oe_id', 'oe_oe', 'oe_cate_id', 'oe_mk_id', 'oe_auto_assign'], ['oe_id'=>$oe_id]);
		//已存在的产品
		$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['comnum'] = $this->buildComNum($arr['oe_cate_id']);
		$arr['pbrands'] = $this->db->select('pro_brand', ['pb_id', 'pb_'.LG_NAME.'(pb_name)']);
		if($arr['oe_auto_assign'] == 'Y'){
			foreach($arr['pbrands'] as &$bv){
				$bv['innum'] = $this->buildBrandInnum($bv['pb_id'], $arr['oe_cate_id']);
			}
		}
		return $arr;
	}
	
	//OE审核到产品库
	function buildProByOe($oe_id, $dataArr)
	{
		$oeInfo = $this->db->get('oe_item', '*', ['oe_id'=>$oe_id]);
		if(empty($oeInfo)) exitJson('记录不存在');

		//检测中性号和物料编码的唯一性
		$comnum = $dataArr['comnum'];
		$comnum_format = formatNum($dataArr['comnum']);
		if(empty($comnum_format)) exitJson('集团中性号必填');
		$pbrand = [];
		foreach($dataArr['pbrand'] as $pb_id=>$innum){
			$format = formatNum($innum);
			if($format){
				$exists = $this->db->get('p_code', 'pc_id', ['pc_innum_format'=>$format]);
				if($exists) exitJson('物料编码：'.$innum.'已被使用');
				$pbrand[$pb_id] = ['pc_pb_id'=>$pb_id, 'pc_innum'=>$innum, 'pc_innum_format'=>$format];
			}
		}
		if(empty($pbrand[1])) exitJson('菲尔科技的物料编码必填');
		ksort($pbrand);

		$this->db->Begin();
		$p_lnk_p_id = 0;
		$pids = [];
		$opuser = getOpuser();
		$datetime = getNowTime();
		foreach($pbrand as $pbk=>$pbv){
			$add = [
				'pc_oe_id'=>$oe_id,
				'pc_lnk_p_id'=>$p_lnk_p_id,
				'pc_pb_id'=>$pbv['pc_pb_id'],
				'pc_mk_id'=>$oeInfo['oe_mk_id'],
				'pc_oe'=>$oeInfo['oe_oe'],
				'pc_oe_format'=>$oeInfo['oe_oe_format'],
				'pc_cate'=>$oeInfo['oe_cate_id'],
				'pc_item_type'=>$oeInfo['oe_item_type'],
				'pc_comnum'=>$comnum,
				'pc_comnum_format'=>$comnum_format,
				'pc_innum'=>$pbv['pc_innum'],
				'pc_innum_format'=>$pbv['pc_innum_format'],
				'pc_cn_name'=>$oeInfo['oe_cn_name'],
				'pc_en_name'=>$oeInfo['oe_en_name'],
				'pc_py_name'=>$oeInfo['oe_py_name'],
				'pc_unit'=>$oeInfo['oe_unit'],
				'pc_auto_assign'=>$oeInfo['oe_auto_assign'],
				'pc_cn_model'=>$oeInfo['oe_cn_model'],
				'pc_en_model'=>$oeInfo['oe_en_model'],
				'pc_py_model'=>$oeInfo['oe_py_model'],
				'pc_en_guige'=>$oeInfo['oe_en_guige'],
				'pc_py_guige'=>$oeInfo['oe_py_guige'],
				'pc_chassis'=>$oeInfo['oe_chassis'],
				'pc_model_year_range'=>$oeInfo['oe_model_year_range'],
				'pc_engine'=>$oeInfo['oe_engine'],
				'pc_cc'=>$oeInfo['oe_cc'],
				'pc_fuel'=>$oeInfo['oe_fuel'],
				'pc_purc_warn'=>$oeInfo['oe_purc_warn'],
				'pc_progroup'=>$oeInfo['oe_progroup'],
				'pc_develop_no'=>$oeInfo['oe_develop_no'],
				'pc_inter_develop'=>$oeInfo['oe_inter_develop'],
				'pc_para'=>$oeInfo['oe_para'],
				'opuser'=>$opuser,
				'create_time'=>$datetime,
				'update_time'=>$datetime
			];
			$this->db->insert('p_code', $add);
			$p_id = $this->db->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->addProductByCode($p_id);
			$pids[] = $p_id;
			if(!$p_lnk_p_id && $add['pc_pb_id'] == 1)
				$p_lnk_p_id = $p_id;
		}
		$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();
		return $pids;
	}

	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()
	{
		return $this->db->select('pro_brand',['pro_brand.*', 'pb_'.LG_NAME.'(pb_name)']);
	}

	function getProRelOe($pid)
	{		
		if(!$pid) return [];
		$arr = [$pid];	
		$res = $this->db->get('pro','p_lnk_p_id',['p_id'=>$pid]);
		if($res){
			$arr[] = $res;
		}
		$result = $this->db->select('pro_numidx',['pn_formart(key)','pn_number(value)'],['pn_pf_id'=>1,'pn_p_id'=>$arr,'GROUP'=>'pn_formart']);
		return $result;
	}

	function getProMainOe($pid)
	{
		$result = $this->db->get('pro_numidx','pn_formart',['pn_mainoe'=>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->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']]['p_id'];
	
		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_pc_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 = [];
		foreach($pvals as $pv){
			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;
	}

	//检测引用状态后决定是否删除
	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',['[><]p_code'=>['pb_id'=>'pc_pb_id']],'pb_id',['pc_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',['[><]p_code'=>['pf_id'=>'pc_pf_id']],'pf_id',['pc_pf_id'=>$ids]);
				break;
		}
		
		if(!empty($arr)) 
			return exitJson('402', '已有产品引用该选项，不可删除');

		if($where){
			$this->db->Begin();
			$this->db->delete($elename,$where);
			$this->db->End();
		}	
	
		return [];
	}
}