alias('links') ->field([ 'links.id', 'links.product_id', 'product.name', 'product.brand_id' => 'spu', 'links.platform_id', 'links.link', 'product.is_show' ]) ->join('product', 'product.id=links.product_id') ->where(function ($query) { $query->where('product.is_show', '=', 0) ->where('links.country_code', '=', $this->country_code); if (request()->has('skeyword')) { $query->where(function ($q) { $keyword = request()->get('skeyword'); $q->where('product.brand_id', 'like', '%' . $keyword . '%') ->whereOr('product.name', 'like', '%' . $keyword . '%'); }); } }) ->order('links.id', 'sort') ->group('links.product_id') ->paginate(10); $data = []; foreach ($list as $val) { if (empty($data[$val['spu']])) { $val['rowspan'] = 1; $data[$val['spu']] = $val; } } if (!$list->isEmpty()) { $others = Db::name('product_purchase_links')->alias('links') ->field([ 'links.id', 'product.name', 'product.brand_id' => 'spu', 'links.platform_id', 'links.link', 'product.is_show' ]) ->join('product', 'product.id=links.product_id') ->where('links.country_code', '=', $this->country_code) ->where('links.id', 'not in', array_column($list->items(), 'id')) ->where('links.product_id', 'in', array_column($list->items(), 'product_id')) ->select(); foreach ($others as $val) { if (!empty($data[$val['spu']]) && $data[$val['spu']]['id'] != $val['id']) { if (empty($data[$val['spu']]['children'])) { $data[$val['spu']]['children'] = []; } $data[$val['spu']]['children'][] = $val; $data[$val['spu']]['rowspan'] = count($data[$val['spu']]['children']) + 1; } } } $this->assign('list', $data); $this->assign('page', $list->render()); $platforms = Db::name('product_purchase_link_platforms') ->field(['id', 'platform']) ->where('id', '>', 0) ->where('country_code', '=', $this->country_code) ->select(); $this->assign('platforms', $platforms); return $this->fetch(); } /** * 更新 */ public function update() { $post = request()->post(); if (empty($post['id'])) { return $this->error('请确认操作数据'); } $id = $post['id']; unset($post['id']); // 验证链接 if (!empty($post['link'])) { $validate = new Validate([ 'link' => 'url|max:255' ], [ 'link.url' => '连接地址格式错误', 'link.max' => '连接址不能超过255个字符' ]); if (!$validate->check($post)) { return $this->error($validate->getError()); } } // 验证平台 if (!empty($post['platform_id'])) { $proid = Db::name('product_purchase_links')->where('id', '=', $id)->value('product_id'); $exists = Db::name('product_purchase_links') ->where('product_id', '=', $proid) ->where('platform_id', '=', $post['platform_id']) ->value('id'); if ($exists) { $platform = Db::name('product_purchase_link_platforms') ->where('id', '=', $post['platform_id']) ->value('platform'); return $this->error(sprintf('该型号已存在【%s】链接', $platform)); } } $ret = Db::name('product_purchase_links')->where('id', '=', $id)->update($post); if (!$ret) { return $this->error('操作失败'); } return $this->success('操作成功'); } /** * 导入 */ public function import() { ini_set('max_execution_time', '0'); $file = request()->file('file'); if ($file->getSize() > 20 * 1024 * 1024) { return $this->error('上传文件不能超过20M'); } // 创建读取器 $reader = \PHPExcel_IOFactory::createReader('Excel2007'); // 加载表格 $spreadsheet = $reader->load($file->getRealPath()); // 读取sheet $sheet = $spreadsheet->getSheet(0); $rows = $sheet->getHighestRow(); //总行数 $xlsx = []; for ($i = 2; $i <= $rows; $i++) { // $xlsx[行号] = 数据 $xlsx[$i] = [ 'spu' => $sheet->getCellByColumnAndRow(0, $i)->getValue(), 'platform' => $sheet->getCellByColumnAndRow(1, $i)->getValue(), 'link' => $sheet->getCellByColumnAndRow(2, $i)->getValue(), ]; } // 错误提示 $errors = []; // 验证成功数据 $valid_data = []; // 购买平台数据 $platforms = Db::name('product_purchase_link_platforms') ->where('id', '>', 0) ->where('country_code', '=', $this->country_code) ->column('id', 'platform'); $xlsx_chunks = array_chunk($xlsx, 500, true); // 分批次验证 spu foreach ($xlsx_chunks as $x) { $spus = array_column($x, 'spu'); $products = Db::name('product') ->where('brand_id', 'in', $spus) ->where('country_code', '=', $this->country_code) ->column('id', 'brand_id'); if (empty($products)) { $errors[] = sprintf('第%s行, 型号不存在', implode(',', array_keys($x))); continue; } $items = []; foreach ($x as $k => $v) { if (empty($products[$v['spu']])) { $errors[] = sprintf('第%s行, 型号不存在', $k); continue; } if (empty($platforms[$v['platform']])) { $errors[] = sprintf("第%s行, 平台名称错误", $k); continue; } if ( !empty($v['link']) && !\think\helper\Str::startsWith($v['link'], 'http://') && !\think\helper\Str::startsWith($v['link'], 'https://') ) { $errors[] = sprintf("第%s行, 链接地址格式错误", $k); continue; } $items[] = [ 'product_id' => $products[$v['spu']], 'platform_id' => $platforms[$v['platform']], 'link' => $v['link'], 'country_code' => $this->country_code, ]; } if (!empty($items)) { $valid_data[] = $items; } } if (!empty($valid_data)) { // 组装 SQL $sql = 'REPLACE INTO `cod_product_purchase_links`(`id`, `product_id`, `platform_id`, `link`, `country_code`) VALUES '; foreach ($valid_data as $val) { $proids = array_column($val, 'product_id'); $links = Db::name('product_purchase_links') ->field(['id', 'product_id', 'platform_id']) ->where('product_id', 'in', $proids) ->where('country_code', '=', $this->country_code) ->select(); if (!empty($links)) { $links_mapping = []; foreach ($links as $l) { $links_mapping[$l['product_id'] . "_" . $l['platform_id']] = $l['id']; } } foreach ($val as $v) { $id = null; if (!empty($links_mapping[$v['product_id'] . '_' . $v['platform_id']])) { $id = $links_mapping[$v['product_id'] . '_' . $v['platform_id']]; } $sql .= sprintf('(%d, %d, %d, "%s", "%s"),', $id, $v['product_id'], $v['platform_id'], $v['link'], $v['country_code']); } } Db::execute(\think\helper\Str::substr($sql, 0, \think\helper\Str::length($sql) - 1)); } if (!empty($errors)) { return $this->error(implode(";\n", $errors)); } return $this->success('导入成功'); } /** * 导出 */ public function export() { $data = Db::name('product_purchase_links')->alias('links') ->field([ 'product.brand_id' => 'spu', 'platforms.platform', 'links.link' ]) ->join('product_purchase_link_platforms platforms', 'platforms.id=links.platform_id') ->join('product', 'product.id=links.product_id') ->where(function ($query) { $query->where('product.is_show', '=', 0)->where('links.country_code', '=', $this->country_code); if (request()->has('skeyword')) { $query->where(function ($q) { $keyword = request()->get('skeyword'); $q->where('product.brand_id', 'like', '%' . $keyword . '%') ->whereOr('product.name', 'like', '%' . $keyword . '%'); }); } }) ->select(); $excel = new \PHPExcel(); $excel->getProperties()->setCreator("Call of Duty") ->setLastModifiedBy("Call of Duty") ->setTitle("Office 2007 XLSX Cod Document") ->setSubject("Office 2007 XLSX Cod Document") ->setDescription("Cod document for Office 2007 XLSX, generated using PHP classes.") ->setKeywords("office 2007 openxml php") ->setCategory("Cod result file"); $excel->createSheet(); $excel->getActiveSheet()->setCellValueByColumnAndRow(0, 1, '型号'); $excel->getActiveSheet()->setCellValueByColumnAndRow(1, 1, '平台'); $excel->getActiveSheet()->setCellValueByColumnAndRow(2, 1, '链接'); foreach ($data as $i => $v) { $excel->getActiveSheet()->setCellValueByColumnAndRow(0, $i + 2, $v['spu']); $excel->getActiveSheet()->setCellValueByColumnAndRow(1, $i + 2, $v['platform']); $excel->getActiveSheet()->setCellValueByColumnAndRow(2, $i + 2, $v['link']); } ob_end_clean(); $writer = \PHPExcel_IOFactory::createWriter($excel, 'Excel2007'); header("Content-Type: application/force-download"); header("Content-Type: application/octet-stream"); //文件流 header("Content-Type: application/download"); //下载文件 header('Content-Disposition: attachment;filename="' . date('YmdHis') . '-' . $this->country_code . '.xlsx"'); header("Content-Transfer-Encoding: binary"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); //上一次修改时间 header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); //不缓存页面 $writer->save('php://output'); exit; } }