<?php

/**
 * +----------------------------------------------------------------------
 * | Created By PhpStorm
 * +----------------------------------------------------------------------
 * | DATE: 2021/7/21
 * +----------------------------------------------------------------------
 * | TIME: 16:24
 * +----------------------------------------------------------------------
 * | Author: YangXing(925032253@qq.com)
 * +----------------------------------------------------------------------
 * | Class: importAction
 * +----------------------------------------------------------------------
 */

namespace admin\action\excel;


use admin\action\baseAction;
use model\excel\importLog;
use model\user\adminUser;
use phpDocumentor\GraphViz\Exception;
use servers\baseModel;
use servers\excel\read;
use servers\excel\write;

class importAction extends baseAction
{
    /**
     * @var array
     */
    private $data = [];

    private $model = null;

    /**
     * SplQueue
     * @var object
     */
    private $errorList;

    /**
     * @var null
     */
    private $wirteObject = null;

    /**
     * @var string
     */
    private $time = '';

    /**
     * @var array
     */
    private $objectTableList = [];

    /**
     * 文件名称
     * @var string
     */
    private $fileName = '';

    /**
     * Excel 配置数组
     * @var array
     */
    private $excelConfig = [];

    /**
     * Excel 当前行
     * @var int
     */
    private $count = 0;

    /**
     * Excel 第一行数据,并不一定是表头
     * @var array
     */
    private $firstLine = [];

    /**
     * 表名
     * @var string
     */
    private $table = '';

    /**
     * @var array
     */
    private $gspFactory = null;

    private $proCate = null;

    private $allFactory = null;

    private $proIdNumber = [];

    private $firstHeader = [];

    private $makeList = null;

    private $seriesList = null;

    public function getUserByList()
    {
        $req = \mvc::$req;
        $sample = new importLog();
        $rules=[];
        $data = $sample->list($rules,$req['filters'], $req['page'], $req['rows'], $req['sidx'], $req['sord'],'create_time');
        $this->successJson($data);
    }

    public function deleteRows()
    {
        if(empty(\mvc::$req['ids'])){
            $this->errorJson(1002,'参数错误');
        }
        $sample = new importLog();
        if($sample->delete(\mvc::$req['ids'])){
            $this->successJson();
        }
        $this->errorJson(1002,'参数错误');
    }

    /**
     * 获取db基类
     * @return baseModel
     */
    private function db()
    {
       if(is_null($this->model)){
           $this->model = new baseModel();
       }
       return $this->model;
    }

    private function getListByMdoelId($data)
    {
        if(empty($this->modelList)){
            $modelList = $this->db()
                                    ->table('`m_model(c)')->field(['c.mm_id','a.name(make_name)', 'b.name(series_name)', 'c.name(name)', 'c.mm_year_from', 'c.mm_month_from', 'c.mm_year_to', 'c.mm_month_to'])
                                    ->join(['[><]m_make(a)' => ['c.mm_mk_id' => 'mk_id'], '[><]m_series(b)' => ['c.mm_ms_id' => 'ms_id']])
                                    ->getAll();
            foreach ($modelList as $value)
            {
                $id = $value['mm_id'];
                unset($value['mm_id']);
                $this->modelList[$id] = md5(implode(',',array_values($value)));
            }
            unset($modelList,$value);
            $this->modelList = array_flip($this->modelList);
        }
        $md5 = md5(implode(',',array_values($data)));
        if(isset($this->modelList[$md5])){
            return $this->modelList[$md5];
        }else{
            return 0;
        }
    }

    public function index()
    {
        $imgUrl = \mvc::$cfg['path']['static'] . '/images/' . 'model.png';
        $list = [
//            [
//                'image_url' => $imgUrl,
//                'title' => '大车型导入',
//                'excel_example_type' => 'make',
//                'table' => 'm_make',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '小车型导入',
//                'excel_example_type' => 'series',
//                'table' => 'm_series',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '明细车型导入',
//                'excel_example_type' => 'model',
//                'table' => 'm_model',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '产品导入',
//                'excel_example_type' => 'pro',
//                'table' => 'pro',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '号码厂商导入',
//                'excel_example_type' => 'factory',
//                'table' => 'pro_factory',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '产品车型关系导入',
//                'excel_example_type' => 'modelLinkTmp',
//                'table' => 'pro_model_link_tmp',
//                'remark' => '备注',
//            ],
//            [
//                'image_url' => $imgUrl,
//                'title' => '号码导入',
//                'excel_example_type' => 'numidxTmp',
//                'table' => 'pro_numidx_tmp',
//                'remark' => '备注',
//            ],
            [
//                'image_url' => $imgUrl,
                'title' => 'CCU导入',
                'excel_example_type' => 'ccu',
                'table' => 'sample_ccu',
                'remark' => '',
            ],
        ];
        $this->successJson($list);
    }


    public function example($type)
    {
        $method = 'get' . ucwords($type) . 'Header';
        $filed = $this->$method();

        foreach ($filed as $key => $value)
        {
            if (isset($value['is_header']) && $value['is_header'] == false)
            {
                unset($filed[$key]);
            }
        }
        $filed = array_keys($filed);
        if($type == 'pro')
        {
            $list = $this->db()->table('pro_factory')->field('pf_name')->where(['pf_is_gsp' => 1])->getAll();
            foreach ($list as $factory)
            {
                array_push($list,$factory.lg('条码'));
            }
            $filed = array_merge($list,$filed);
        }elseif($type == 'customer'){
            $filed = ['客户代码','名称'];
            dd($filed);
        }
        $excel = new \servers\excel\write($type . '.xlsx');
        $filePath = $excel->setHeader($filed)->setBold('A1')->output();
        header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        header('Content-Disposition: attachment;filename="' . $type . '.xlsx' . '"');
        header('Content-Length: ' . filesize($filePath));
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate');
        header('Cache-Control: max-age=0');
        header('Pragma: public');
        ob_clean();
        flush();
        if (copy($filePath, 'php://output') === false) {
            // Throw exception
        }
    }

    /**
     * @return array
     * @throws \Exception
     */
    private function getGspFactory()
    {
        if(is_null($this->gspFactory)){
            $this->gspFactory = $this->db()->table('pro_factory')->field(['pf_id','pf_name'])->where(['pf_is_gsp' => 1])->getAll();
            if(empty($this->gspFactory)){
                throw new \Exception(lg('没有一个FREAY品牌号码,需要添加一个FREAY品牌号码'));
            }
            $this->gspFactory = array_column($this->gspFactory,'pf_name','pf_id');
        }
        return $this->gspFactory;
    }

    //获取小车型excel 头
    private function getSeriesHeader()
    {
        return [
            lg('大车型名称') => array('field' => 'ms_mk_id', 'length' => 50, 'must' => true),
            lg('小车型名称') => array('field' => 'name', 'length' => 255, 'must' => true),
            lg('小车型别名') => array('field' => 'alias', 'length' => 255)
        ];
    }

    //获取车型品牌excel头
    private function getMakeHeader()
    {
        return [
            lg('大车型名称') => [
                'field' => 'name',
                'must' => true,
                'length' => 50,
                'unique' => true
            ]
        ];
    }

    //号码导入
    private function getNumidxTmpHeader()
    {
        $this->allFactory = $this->db()->table('pro_factory')->field(['pf_name','pf_id'])->getAll();
        $header = [];
        foreach ($this->allFactory as $pfName)
        {
            $header[$pfName['pf_name']] = [
                'field' => $pfName['pf_name'],
                'length' => 50
            ];
        }
        return $header;
    }

    //CCU导入配置
    private function getCcuHeader()
    {
        return array(
            lg('CCU编码') => array('field' => 'sccu_code', 'length' => 20, 'must' => true, 'unique' => true),
            lg('OE') => array('field' => 'sccu_oe', 'length' => 20),
            lg('车型') => array('field' => 'sccu_model', 'length' => 255),
        );
    }

    //产品导入配置
    private function getProHeader()
    {
        return array(
            lg('小类') => array(
                'field' => 'p_pc_id',
                'length' => 255,
                'cate' => true
            ),
            lg('标签') => array('field' => 'tag', 'object_id' => 100),
            lg('包装') => array('field' => 'p_pack', 'length' => 200),
            lg('描述1') => array('field' => 'p_remark1', 'length' => 255),
            lg('描述2') => array('field' => 'p_remark2', 'length' => 255),
            lg('描述3') => array('field' => 'p_remark3', 'length' => 255),
            lg('状态') => array('field' => 'p_state', 'array' => ['上架' => 1, '下架' => 0, '开发中' => -1]),
        );
    }

    //号码厂商
    private function getFactoryHeader()
    {
        return [
            lg('品牌名') => ['field' => 'pf_name', 'length' => 100, 'must' => true, 'unique' => true],
            lg('标签') => ['field' => 'tag', 'object_id' => 100]
        ];
    }

    //产品与车型关系
    private function getModelLinkTmpHeader()
    {
        $this->getGspFactory();
        //查询号码时，把已有的号码做一个缓存,查不到再去数据库中查询，减少数据库的查询次数
        return [
            lg('号码').'|'.implode('|',$this->gspFactory) => ['field' => 'pmlt_p_id', 'length' => 50],
            lg('大车型') => ['field' => 'make_name'],
            lg('小车型') => ['field' => 'series_name'],
            lg('车款') => ['field' => 'name', 'is_field'],
            lg('起始年') => ['field' => 'mm_year_from'],
            lg('起始月') => ['field' => 'mm_month_from'],
            lg('结束年') => ['field' => 'mm_year_to'],
            lg('结束月') => ['field' => 'mm_month_to'],
            lg('安装位置0变速箱 transmission)') => ['field' => 'pmlt_pos0', 'length' => 50],
            lg('安装位置1前后 Position FR/RR)') => ['field' => 'pmlt_pos1', 'length' => 50],
            lg('安装位置2左右 Position L/R)') => ['field' => 'pmlt_pos2', 'length' => 50],
            lg('安装位置3WS外/GS内/中 Position I/O/C)') => ['field' => 'pmlt_pos3', 'length' => 50],
            lg('安装位置4上中下 Position  U/L/C)') => ['field' => 'pmlt_pos4', 'length' => 50],
            lg('安装位置5综合 complex)') => ['field' => 'pmlt_pos5', 'length' => 50],
            lg('其他车型备注(和安装位置一组)') => ['field' => 'pmlt_node1', 'length' => 255],
            lg('目录备注') => ['field' => 'pmlt_catalog_notes', 'length' => 255],
            lg('预留备注') => ['field' => 'pmlt_node2', 'length' => 255],
            lg('预留备注') => ['field' => 'pmlt_node3', 'length' => 255],
            lg('引用品牌') => ['field' => 'pmlt_quote_brand', 'length' => 50],
            lg('引用号码') => ['field' => 'pmlt_quote_number', 'length' => 60],
            lg('车型引用时间') => ['field' => 'pmlt_quote_time'],
        ];

    }

    //获取车型excel头
    private function getModelHeader()
    {
        return array(
            lg('gsp车型代码') => array('field' => 'mm_gsp_model_code', 'length' => 50),
            lg('大车型') => array('field' => 'mm_mk_id', 'must' => true),
            lg('小车型') => array('field' => 'mm_ms_id', 'must' => true, 'unique' => true),
            lg('数据源') => array('field' => 'mm_source', 'length' => 50),
            lg('关联ID') => array('field' => 'mm_link_id', 'length' => 50),
            lg('车型类别') => array('field' => 'mm_segment', 'length' => 100),
            lg('保有量') => array('field' => 'mm_vio'),
            lg('车系') => array('field' => 'mm_region_s', 'length' => 100),
            lg('国家') => array('field' => 'mm_region_c', 'length' => 100),
            lg('可销售区域') => array('field' => 'mm_apply_to'),
            lg('发布平台') => array('field' => 'tag', 'object_id' => 100),
            lg('年开始') => array('field' => 'mm_year_from', 'min' => 1900, 'max' => 3000, 'must' => true, 'unique' => true),
            lg('月开始') => array('field' => 'mm_month_from', 'min' => 1, 'max' => 12, 'must' => true, 'unique' => true),
            lg('年结束') => array('field' => 'mm_year_to', 'min' => 1900, 'max' => 3000),
            lg('月结束') => array('field' => 'mm_month_to', 'min' => 1, 'max' => 12),
            lg('款式') => array('field' => 'name', 'length' => '255', 'must' => true, 'unique' => true),
            lg('燃油方式') => array('field' => 'mm_fuel', 'object_id' => 17),
            lg('排量') => array('field' => 'mm_disp', 'length' => 50),
            lg('底盘号') => array('field' => 'mm_chassis', 'length' => 50),
            lg('发动机号') => array('field' => 'mm_engine', 'length' => 50),
            lg('增压方式') => array('field' => 'mm_turbo', 'object_id' => 15),
            lg('功率') => array('field' => 'mm_kw', 'length' => 50),
            lg('马力') => array('field' => 'mm_hp', 'length' => 50),
            lg('发动机汽缸排列方式') => array('field' => 'mm_cylinders', 'object_id' => 18),
            lg('阀门数') => array('field' => 'mm_values', 'length' => 50),
            lg('驱动方式') => array('field' => 'mm_drive_type', 'object_id' => 16),
            lg('车身') => array('field' => 'mm_body', 'length' => 50),
            lg('门数') => array('field' => 'mm_doors', 'length' => 50),
            lg('生产平台') => array('field' => 'mm_platform', 'length' => 50),
        );
    }

    private function getCustomerHeader()
    {
        return array(
            lg('客户编码') => array('field' => 'ct_code', 'length' => 100),
            lg('客户名称') => array('field' => 'ct_name', 'length' => 100),
        );
    }

    public function __call($name, $arguments)
    {
        $this->successJson(['name' => $name, 'arguments' => $arguments]);
    }

    /**
     * @param $id
     */
    private function setObjectTableList()
    {
        $id = array_column($this->excelConfig,'object_id');
        if(!empty($id)){
            $temp = $this->model->table('object')->field([LG_NAME, 'o_id'])->where(['o_parent_id' => $id])->getAll();
            $this->objectTableList = array_column($temp, 'o_id', LG_NAME);
        }else{
            $this->objectTableList = [];
        }

    }

    //大车型导入
    private function make($fileName)
    {
        //初始化
        $this->init($fileName);
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {
                    if(!isset($temp['name']) || empty($temp['name'])){
                        $this->writeExcelRow($value,0,'大车型名称不可为空');
                        return false;
                    }
                    if ($this->db()->table($this->table)->where(['name' => $temp['name']])->has()) {
                        //错误
                        $this->writeExcelRow($value,0,'品牌'.$temp['name'].'已经存在');
                        return false;
                    } else {
                        //成功
                        $this->writeExcelRow($value,1);
                    }
                    $temp = $this->setFiledDate($temp);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    private function getMakeIdByName($name)
    {
        if(is_null($this->makeList)){
            $this->makeList = $this->db()->table('m_make')->field(['mk_id','name'])->getAll();
            if(!empty($this->makeList)){
                $this->makeList = array_column($this->makeList,'mk_id','name');
            }else{
                $this->makeList = [];
            }
        }
        return isset($this->makeList[$name]) ? $this->makeList[$name] : 0;
    }

    /**
     * @param $mkId
     * @param $name
     * @return false|mixed
     */
    private function getSeriesIdByName($mkId,$name)
    {
        $index = md5($mkId.$name);
        if(isset($this->seriesList[$index])){
            return $this->seriesList[$index];
        }else{
           $this->seriesList[$index] = $this->db()->table('m_series')->field('ms_id')->where([
                'OR' => [
                        'name' => $name,
                        'alias' => $name
                ],
                'AND' => ['ms_mk_id' => $mkId]
            ])->gets();
           return $this->seriesList[$index];
        }
    }

    //小车型导入
    private function series($fileName)
    {
        //初始化
        $this->init($fileName);
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {

                    if(empty($temp['ms_mk_id'])){
                        $this->writeExcelRow($value,0,'大车型不可为空');
                        return false;
                    }
                    $makeId = $this->getMakeIdByName($temp['ms_mk_id']);
                    if($makeId <= 0){
                        $this->writeExcelRow($value,0,'大车型不存在');
                        return false;
                    }
                    $temp['ms_mk_id'] = $makeId;
                    if ($this->db()->table($this->table)->where(['ms_mk_id' => $makeId,'name' => $temp['name']])->has()) {
                        //错误
                        $this->writeExcelRow($value,0,'该小车型已经存在');
                        return false;
                    } else {
                        //成功
                        $this->writeExcelRow($value,1);
                    }
                    $temp = $this->setFiledDate($temp);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    //车型导入
    private function model($fileName)
    {
        //初始化

        $this->init($fileName);
        $this->setObjectTableList();
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 500, function ($data, $firstLine, $number) {
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {

                    //大车型
                    if(empty($temp['mm_mk_id'])){
                        $this->writeExcelRow($value,0,'大车型不可为空');
                        return false;
                    }
                    $mkId = $this->getMakeIdByName($temp['mm_mk_id']);

                    if($mkId <= 0){
                        $this->writeExcelRow($value,0,'大车型不存在');
                        return false;
                    }
                    $temp['mm_mk_id'] = $mkId;

                    //小车型
                    $msId = $this->getSeriesIdByName($mkId,$temp['mm_ms_id']);
                    if($msId <= 0){
                        $this->writeExcelRow($value,0,'小车型不存在');
                        return false;
                    }
                    $temp['mm_ms_id'] = $msId;
                    if ($this->db()->table($this->table)->where([
                        'mm_mk_id' => $mkId,
                        'mm_ms_id' => $msId,
                        'name' => $temp['name'],
                        'mm_year_from' => $temp['mm_year_from'],
                        'mm_month_from' => $temp['mm_month_from'],
                        'mm_year_to' => $temp['mm_year_to'],
                        'mm_month_to' => $temp['mm_month_to'],
                    ])->has()) {
                        //错误
                        $this->writeExcelRow($value,0,'该车型已经存在');
                        return false;
                    } else {
                        //成功
                        $this->writeExcelRow($value,1);
                    }
                    $temp = $this->setFiledDate($temp);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    /**
     * 初始化
     * @param $fileName
     */
    private function init($fileName)
    {
        $method = 'get' . ucfirst(\mvc::$req['s_id']) . 'Header';
        $this->excelConfig = $this->$method();
        $this->wirteObject = (new write($this->generateFileName()));
        $this->time = date('Y-m-d H:i:s');
        $this->before([
            'generate_file' => $this->generateFileName(),
            'original_file' => str_replace($this->sysDir(), '', $fileName),
        ]);
        $this->table = \mvc::$req['table'];
    }

    /**
     * ccu导入
     * @param $fileName
     */
    private function ccu($fileName)
    {
        //初始化
        $this->init($fileName);
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {
                    if(empty($temp['sccu_code'])){
                        $this->writeExcelRow($value,0,'CCU编码不可为空');
                        return false;
                    }
                    $temp['sccu_code_format'] = formatNum($temp['sccu_code']);
                    if ($this->db()->table('sample_ccu')->where(['sccu_code_format' => $temp['sccu_code_format']])->has()) {
                        //错误
                        $this->writeExcelRow($value,0,'CCU编码'.$temp['sccu_code'].'已经存在');
                        return false;
                    } else {
                        //成功
                        $this->writeExcelRow($value,1);
                    }
                    $temp = $this->setFiledDate($temp);

                    return $temp;
                });

                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    private function factory($fileName)
    {
        //初始化
        $this->init($fileName);
        $this->setObjectTableList();
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {
                    if ($this->db()->table($this->table)->where(['pf_name' => $temp['pf_name']])->has()) {
                        //错误
                        $this->writeExcelRow($value,0,'品牌名'.$temp['pf_name'].'已经存在');
                        return false;
                    } else {
                        //成功
                        $this->writeExcelRow($value,1);
                    }
                    $temp = $this->setFiledDate($temp);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    private function proCate($name)
    {
        if(is_null($this->proCate)){
            $this->proCate = $this->db()->table('pro_cate')->field(['id','cn_name','en_name'])->getAll();
        }

        if(empty($this->proCate)){
            return 0;
        }
        foreach ($this->proCate as $index => $item) {
            if($item['cn_name'] == $name || $item['en_name'] == $name){
                return $item['id'];
            }
        }
        return 0;
    }

    private function pro($fileName)
    {
        //初始化
        $this->init($fileName);
        $this->getGspFactory();
        foreach ($this->gspFactory as $value)
        {
            $this->excelConfig[$value] = [
                    'field' => $value,
                    'length' => 60
                ];
            $this->excelConfig[$value.lg('条码')] = [
                'field' => $value.'barcode',
                'length' => 50
            ];
        }

        $this->setObjectTableList();

        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {

                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) {

                    $tem = [];

                    foreach ($temp as $key => $val)
                    {

                        if(in_array($key,$this->gspFactory))
                        {
                            $tem[$key] = [
                                'number' => $val,
                                'barcode' => isset($temp[$key.'barcode']) ? $temp[$key.'barcode'] : '',
                            ];
                            unset($temp[$key],$temp[$key.'barcode']);

                        }
                    }

                    $temp = $this->setFiledDate($temp);
                    $proId = $this->db()->table('pro')->add($temp);
                    foreach ($tem as $index => $item){
                        $numberData[] = [
                            'pn_p_id' => $proId,
                            'pn_pf_id'  => array_search($index,$this->gspFactory), //号码厂商
                            'pn_number' => $item['number'], //号码
                            'pn_formart' => formatNum($item['number']),//格式化号码
                            'pn_barcode' => $item['barcode'],//条码
                            'create_time' => $this->time,
                            'update_time' => $this->time,
                            'opuser' => $_SESSION['userID']
                        ];
                    }
                    $this->db()->table('pro_numidx')->addAll($numberData);
                    $this->writeExcelRow($value,1);
                });
                //执行语句
                //$this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    //号码导入
    private function numidxTmp($fileName)
    {
        //初始化
        $this->init($fileName);
        $this->getGspFactory();

        $this->setObjectTableList();
        $this->allFactory = array_column($this->allFactory,'pf_id','pf_name');
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {
                $firstHeader = current($firstLine);
                if($this->count == 0){
                    foreach ($firstLine as $v)
                    {
                        if(!isset($this->allFactory[$v])){
                            throw new \Exception($v.'不在号码厂商列表中');
                        }
                    }
                }
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) use($firstHeader) {;
                    $pId = $this->db()->table('pro_numidx')->field('pn_p_id')->where([
                            'pn_formart' => formatNum($temp[$firstHeader])
                        ])->gets();
                    if((int) $pId <= 0){
                        $this->writeExcelRow($value,0, $temp[$firstHeader].'号码找不到对应的产品');
                        return false;
                    }
                    unset($temp[$firstHeader]);
                    $add = [];
                    foreach ($temp as $index => $item){
                        if(!empty($item)){
                            $add[] = [
                                'pn_p_id' => $pId,
                                'pn_pf_id' => $this->allFactory[$index],
                                'pn_number' => $item,
                                'pn_formart' => formatNum($item),
                                'pn_barcode' => '',
                                'opuser' => $_SESSION['userID'],
                                'create_time' => $this->time,
                                'update_time' => $this->time
                            ];
                        }
                    }
                    //TODO 保证重复
                    $this->db()->table('pro_numidx')->addAll($add);
                    $this->writeExcelRow($value,1);
                });
                //执行语句
                //$this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    //车型与产品关系
    private function modelLinkTmp($fileName)
    {
        //初始化
        $this->init($fileName);

        $this->setObjectTableList();
        //$this->allFactory = $this->db()->table('pro_factory')->field(['pf_name','pf_id'])->getAll();
        //$this->allFactory = array_column($this->allFactory,'pf_id','pf_name');
        $firstHeader = '';
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) use($firstHeader) {
                if(!is_array($firstHeader)){
                    $firstHeader = current($firstLine);
                    $firstHeader = str_replace(lg('号码').'|','',$firstHeader);
                    $firstHeader = explode('|',$firstHeader);
                }
                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) use($firstHeader) {
                    $mmId = $this->getListByMdoelId( [
                        'make_name' =>$temp['make_name'],
                        'series_name' => $temp['series_name'],
                        'name' => $temp['name'],
                        'mm_year_from' => $temp['mm_year_from'],
                        'mm_month_from' => $temp['mm_month_from'],
                        'mm_year_to' => $temp['mm_year_to'],
                        'mm_month_to' => $temp['mm_month_to']
                    ]);
                    if($mmId <= 0){
                        $this->writeExcelRow($value,0, '找不到该车型');
                        return false;
                    }
                    $temp['pmlt_mm_id'] = $mmId;
                    unset($temp['make_name'],$temp['series_name'],$temp['name'],$temp['mm_year_from'],$temp['mm_month_from'],$temp['mm_year_to'],$temp['mm_month_to']);

                    $num = $temp['pmlt_p_id'];

                    if(isset($this->proIdNumber[$num])){
                        $temp['pmlt_p_id'] = $this->proIdNumber[$num];
                    }else{
                        $temp['pmlt_p_id'] = $this->db()->table('pro_numidx')->field('pn_p_id')->join(['[><]pro_factory' => ['pn_pf_id' => 'pf_id']])->where(['pn_formart' => formatNum($temp['pmlt_p_id']),'pf_name' => $firstHeader])->gets();
                        $this->proIdNumber[$num] =  $temp['pmlt_p_id'];
                    }
                    if((int) $temp['pmlt_p_id'] <= 0){
                        $this->writeExcelRow($value,0, '找不到该号码的对应产品');
                        return false;
                    }
                    $temp = $this->setFiledDate($temp);
                    $this->writeExcelRow($value,1);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    private function customer($fileName)
    {
        //初始化
        $this->init($fileName);
        try {
            //读取Excel,1000个读取
            $result = new read($fileName, 1000, function ($data, $firstLine, $number) {

                $this->setExcelHeader($firstLine);
                //验证Excel,把列转换成对应数据库的字段,并以回调的形式返回每一行回调的数据(组装成可以供mysql操作的数组)
                $data = $this->verification($data, function ($temp, $value) use($firstHeader) {

                    if($this->db()->table($this->table)->where(['ct_code' => $temp['ct_code'],'ct_name' => $temp['ct_name']])->has()){
                        $this->writeExcelRow($value,0, '该客户已经存在');
                        return false;
                    }
                    $temp = $this->setFiledDate($temp);
                    $temp = $_SESSION['userID'];
                    $this->writeExcelRow($value,1);
                    return $temp;
                });
                //执行语句
                $this->implementSql($data);
            });
            //操作完数据库后执行
            $this->after();
        }catch (\Throwable $e) {
            $this->importErrorLog($e->getMessage());
        }
    }

    /**
     * 导入出错
     * @param $message
     */
    private function importErrorLog($message)
    {
        $this->db()->table('import_log')->where(['id' => $this->id])->update(['message' => $message,'is_error' => 1]);
    }

    /**
     * 写当前行的Excel
     * @param $value
     * @param $status
     * @param string $message
     */
    private function writeExcelRow($value,$status,$message = '')
    {
        if($status == 'No'){
            $this->wirteObject->setColor('A' . ($this->count + 1));
        }
        $this->wirteObject->writeRow(array_merge($value, [$status ? 'Yes' : 'No',$status ? '导入成功' : $message]), $this->count);
    }

    /**
     * 设置时间字段
     * @param $temp
     * @return mixed
     */
    private function setFiledDate($temp)
    {
        $temp['create_time'] = $this->time;
        $temp['update_time'] = $this->time;
        return $temp;
    }

    /**
     * @param $data
     * @return bool
     */
    private function implementSql($data)
    {
        if(!empty($data)){
            $this->db()->table($this->table)->addAll($data);
        }
        return true;
    }

    /**
     * 设置Excel头部
     * 设置头部样式
     * @param $firstLine
     * @return bool
     */
    private function setExcelHeader($firstLine)
    {
        if($this->count == 0)
        {
            array_push($firstLine,'Yes|No');
            array_push($firstLine,'错误原因');
            $this->wirteObject->setBold('A1')->setHeader($firstLine);
            $this->firstLine = $firstLine;
        }
        return true;
    }

    /**
     * 导入基础验证
     * @param $data
     * @param callable $callback
     * @return array
     */
    private function verification($data,Callable $callback)
    {

        foreach($data as $key => $value)
        {
            $this->count++;
            $temp = [];
            foreach ($this->firstLine as $index => $item)
            {
                if (isset($this->excelConfig[$item]))
                {
                    //判断长度
                    if (isset($this->excelConfig[$item]['length']) && mb_strlen($value[$index]) > $this->excelConfig[$item]['length'])
                    {
                        unset($data[$key]);
                        $this->writeExcelRow($value,0,$value[$index].'长度超过了限制'.$this->excelConfig[$item]['length']);
                        continue 2;
                    }

                    //自定义属性
                    if(isset($this->excelConfig[$item]['array'])){
                        if(isset($this->excelConfig[$item]['array'][$value[$index]])){
                            $temp[$this->excelConfig[$item]['field']] = $this->excelConfig[$item]['array'][$value[$index]];
                            continue;
                        }else{
                            unset($data[$key]);
                            $this->writeExcelRow($value,0,$value[$index].'属性不存在');
                            continue 2;
                        }
                    }

                    if(isset($this->excelConfig[$item]['cate'])){
                        $temp[$this->excelConfig[$item]['field']] = $this->proCate($value[$index]);
                        if($temp[$this->excelConfig[$item]['field']] <= 0){
                            unset($data[$key]);
                            $this->writeExcelRow($value,0,'小类'.$value[$index].'不存在');
                            continue 2;
                        }else{
                            continue;
                        }
                    }

                    if(isset($this->excelConfig[$item]['object_id']) && !empty($value[$index])){
                        if(isset($this->objectTableList[$value[$index]])){
                            $temp[$this->excelConfig[$item]['field']] = $this->objectTableList[$value[$index]];
                            continue;
                        }else{
                            unset($data[$key]);
                            $this->writeExcelRow($value,0,$value[$index].'属性不存在');
                            continue 2;
                        }

                    }

                    //判断必须值是否为空
                    if(isset($this->excelConfig[$item]['must']) && empty($value[$index]))
                    {
                        $this->writeExcelRow($value,0,$item.'不可为空值');
                        unset($data[$key]);
                        continue 2;
                    }
                    $temp[$this->excelConfig[$item]['field']] = $value[$index];
                }
            }
            //执行每个块的自定义逻辑
            $temp = call_user_func($callback,$temp,$value);
            if(is_array($temp)){
                $data[$key] = $temp;
            }else{
                unset($data[$key]);
            }
        }
        //不是数字连续的数组
        return array_values($data);
    }

    /**
     * 生成Excel文件名
     * @return string
     */
    private function generateFileName()
    {
       if(empty($this->fileName))
       {
           /**
            * @var \mvc::$req['s_id'] sting 文件类型
            */
           $this->fileName = \mvc::$req['s_id'].'_'.$_SESSION['userID'].'_'.date('Y_m_d_H_i_s').'.xlsx';
       }
       return $this->fileName;
    }

    /**
     * @return mixed
     */
    private function sysDir()
    {
        return \mvc::$cfg['dir']['files'];
    }

    /**
     * 导入程序开始之前
     * @param $data
     */
    private function before($data)
    {
        $data['create_time'] = $this->time;
        $data['update_time'] = $this->time;
        $data['opuser'] = $_SESSION['userID'];
        $data['is_delete'] = 0;
       $this->id =  $this->db()->table('import_log')->add($data);
    }

    //之后
    private function after()
    {
        $fileName = $this->wirteObject->output();
        $this->returnMessage($fileName);
    }

    /**
     * 上传回调接口
     * @param $fileName
     * @param $extname
     * @param $userFilename
     * @throws \Exception
     */
    public function upload($fileName,$extname,$userFilename)
    {
        $fileNames = \mvc::$cfg['dir']['files_url'].str_replace(realpath(\mvc::$cfg['dir']['files_path']),'',$fileName);
        $fileName = pathinfo($fileNames,2);
        $method = \mvc::$req['s_id'];
        $this->$method($fileName);
    }

    private function returnMessage($fileName)
    {
        $fileName = \mvc::$cfg['sitePath'].'/../files'.str_replace(\mvc::$cfg['dir']['files'],'',$fileName);
        $this->errorJson('500','<a target="_blank" href="'.addslashes($fileName).'">点击下载</a>');
    }

    /**
     * 二维数多个key去重
     * @param $data
     * @param array $key
     * @return array
     */
    public function arrayUniqueByManyKey($data,$key = [])
    {
        if(empty($key)){
            return $data;
        }

        foreach ($data as $k => &$value)
        {
            foreach ($key as $item)
            {
                $value['unique_key'] .= $value[$item];
            }
        }
        $data = array_column($data,null,'unique_key');
        foreach ($data as &$v){
            unset($v['unique_key']);
        }
        return array_values($data);
    }
}