'test'] * @var null */ protected $simple = []; /** * 精准查询,精确字段,格式['language_id'=> 1] * @var null */ protected $focus = []; /** * 排序字段。格式 ['sort'=>'desc'] * @var null */ protected $order = []; /** * 筛选字段,用于提交给前端需要显示哪些数据库字段数据, * @var null */ protected $field = []; /** * 模型 * @var null */ protected $model = null; /** * 验证器 * @var null */ protected $validate = null; /** * 七牛云 * @var null */ protected $qn = null; /** * 分页页码 * @var integer */ protected $page = 0; /** * 分页数量 * @var integer */ protected $size = 0; /** * 接口监控数据 * @var string[] */ protected $apiLog = [ 'items' => '', 'forum' => '',/*模块-中文*/ 'forum_code'=> '',/*模块日志编码*/ 'refer' => '',/*引用接口页*/ 'source' => '',/*数据来源标识*/ 'source_code'=> '',/*接口地址*/ 'source_name'=> '',/*接口调用地址*/ 'state' => '',/*结果状态*/ 'date_time' => '',/*生成时间*/ 'start_time'=> '',/*开始时间*/ 'end_time' => '',/*结束时间*/ 'elapsed_time'=>'',/*耗时*/ 'ip' => '',/*访客IP*/ 'country' => '',/*国家*/ 'city' => '',/*城市*/ 'area' => '',/*地区*/ 'system' => '',/*设备系统*/ 'version' => '',/*系统版本*/ 'brower' => '',/*浏览器*/ 'models' => '',/*设备型号*/ 'beginCode' => '',/*传值参数*/ 'reurnCode' => '',/*返回结果*/ ]; /** * 初始化方法 */ public function initialize() { //初始化用户信息 $this->adminInfo = $this->request->admin_user_info; $config = [ 'iss' => Env::get('jwt_config.iss'), 'exp' => Env::get('jwt_config.exp') ]; $this->jwt = new Jwt($config); $this->platformId = 1; $this->qn = new QiniuUploader(); // if ($this->request->param('page') != '') { $this->page = $this->request->param('page/d',1); } if ($this->request->param('size') != '') { $this->size = $this->request->param('size/d',10); } //请求来源页 $this->apiLog['items'] = Env::get('platform_name','官网'); $this->apiLog['refer'] = $this->request->server('HTTP_REFERER'); $this->apiLog['source'] = $this->request->server('HTTP_REFERER'); $this->apiLog['source_code'] = $this->request->domain().$this->request->server('REQUEST_URI'); $this->apiLog['source_name'] = $this->request->server('REQUEST_URI'); //获取应用启动时间 $this->apiLog['start_time'] = $this->app->getBeginTime(); //获取访问设备,系统版本,浏览器,设备型号 $userAgent = $this->request->server('HTTP_USER_AGENT'); AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE); $dd = new DeviceDetector($userAgent); $dd->parse(); if ($dd->isBot()) { $this->apiLog['brower'] = '未知'; $this->apiLog['system'] = '未知'; $this->apiLog['version'] = '未知'; $this->apiLog['models'] = '爬虫'; } else { $clientInfo = $dd->getClient(); $osInfo = $dd->getOs(); $device = $dd->getDeviceName(); $brand = $dd->getBrandName(); $model = $dd->getModel(); $this->apiLog['brower'] = !empty($clientInfo) ? $clientInfo['name'].' '.$clientInfo['version'] : '未知'; $this->apiLog['system'] = !empty($osInfo) ? $osInfo['name'].' '.$osInfo['version'] : '未知'; $this->apiLog['version'] = $osInfo['version']??''; $this->apiLog['models'] = $device . " " . $brand . " ". $model; } //解析IP地址,得到国家,城市,地址, $visitIp = get_client_ip(); $this->apiLog['ip'] = $visitIp; if (!filter_var($visitIp,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_NULL_ON_FAILURE)) { $this->apiLog['country'] = '本地'; $this->apiLog['city'] = '本地'; $this->apiLog['area'] = '本地'; } else { $reader = new Reader(public_path() . '/GeoLite2-City.mmdb'); $record = $reader->city($visitIp); $this->apiLog['country'] = $record->country->names['zh-CN']; $this->apiLog['city'] = $record->city->name; $this->apiLog['area'] = $record->city->name; } } /** * 全局接口返回 * @param int $status 状态码 * @param string $message 消息提示 * @param array $data 返回的数据内容 */ public function msg(int $status,string $message,array $data = []):\think\response\Json { $route = strtolower($this->request->pathinfo()); $pathInfo = explode('/',$route); $this->apiLog['state'] = $status; $this->apiLog['forum'] = $pathInfo[1]??''; $this->apiLog['forum_code'] = $status == 200 ? 0 : 1; $this->apiLog['date_time'] = date('Y-m-d H:i:s',time()); $this->apiLog['end_time'] = microtime(true); $this->apiLog['elapsed_time'] = round((float)($this->apiLog['end_time'] - $this->apiLog['start_time']),6); $this->apiLog['end_time'] = date('Y-m-d H:i:s',time()); $this->apiLog['start_time'] = date('Y-m-d H:i:s',(int)$this->app->getBeginTime()); $this->apiLog['beginCode'] = json_encode($this->request->param()); $this->apiLog['reurnCode'] = $status == 200 ? 'SUCCESS' : 'ERROR'; //返回信息前,写入kafka log日志 if (!Env::get('APP_DEBUG')) { // $this->sendLogsToKafkaProduce($this->apiLog,'api_logs',Env::get('database.database'),'api'); $this->asyncApiLog($this->apiLog,'api_logs','api'); } header("Content-Type: application/json; charset=UTF-8"); $result = [ 'status' => $status, 'message' => $message, 'data' => $data ]; return json($result); } /** * PHP发送Json对象数据 * * @param string $url 请求url * @param string $jsonStr 发送的json字符串 * @param string $Bearer * @return array */ public function curlJson(string $url, string $jsonStr,string $Bearer = ''):array { $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($jsonStr), 'Bearer:' . $Bearer ) ); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return array('status' => $httpCode, 'data' => $response); } /** * 全局验证器验证方法 * * @param string $functionName 当前控制器需要验证的方法名 * @param array $inputData 当前控制器需要验证的数据 */ public function commonValidate(string $functionName,array $inputData):bool { //验证器验证 return $this->validate->scene($functionName)->check($inputData); } /** * 列表 */ public function index():\think\Response\Json { $inputData = $this->request->param(); $inputData['platform_id'] = $this->platformId; if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->getIndexList($this->page,$this->size,$this->field, $this->simple, $this->focus,$this->order); return $this->msg(200,'获取列表成功',$result); } /** * 详情 */ public function read():\think\Response\Json { $inputData = $this->request->param(['id']); if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } $inputData['platform_id'] = $this->platformId; if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->getInfo($inputData); if ($result) { $result['language_id'] = $result['site_id']; return $this->msg(200,'获取列表成功',$result); } else { return $this->msg(200,'获取列表成功',[]); } } /** * 新增 */ public function create():\think\Response\Json { $inputData = $this->request->param(); $inputData['platform_id'] = $this->platformId; //语言包 if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } if (isset($inputData['site_id']) || !empty($inputData['site_id']) || $inputData['site_id'] != 0) { $this->focus['site_id'] = $inputData['site_id']; } else { return $this->msg(504,'语言包/所属站点参数,不正确,请检查!'); } if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->addData($inputData); if ($result) { return $this->msg(200,'新增成功'); } else { return $this->msg(504,'新增失败'); } } /** * 修改 */ public function update():\think\Response\Json { $inputData = $this->request->param(); if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } $inputData['platform_id'] = $this->platformId; if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->editData($inputData); if ($result) { return $this->msg(200,'更改成功'); } else { return $this->msg(504,'更改失败'); } } /** * 图片,ICON上传 */ public function upload():\think\Response\Json { $files = $this->request->file(); if (!$files) { return $this->msg(-1, "请选择上传的文件"); } $field = array_keys($files)[0]; $data = []; //兼容多图上传 if (is_array($files) && count($files) > 1 ) { //不同字段文件名上传 image img ico //上传到七牛 foreach ($files as $key => $fileSimple) { if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { return $this->msg(-1, $this->validate->getError()); } $result[$key] = $this->qn->uploadFile($key); } foreach ($result as $key => $item) { $data[] = [ 'cdn' => Env::get('QINIU.cdn'), 'origin_name' => $files[$key]->getOriginalName(), 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], 'md5' => md5_file($files[$key]->getPathname()), 'url' => $item['remote_url'], 'relative_path' => $item['filename'] ]; } } elseif (is_array($files[$field]) && count($files[$field]) > 1) { //同一名称的数组文件上传.image[0] image[1] foreach ($files as $key => $fileSimple) { if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { return $this->msg(-1, $this->validate->getError()); } } //上传到七牛 $result = $this->qn->uploadFile($field, true, count($files[$field])); foreach ($result as $key => $item) { $data[] = [ 'cdn' => Env::get('QINIU.cdn'), 'origin_name' => $files[$field][$key]->getOriginalName(), 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], 'md5' => md5_file($files[$field][$key]->getPathname()), 'url' => $item['remote_url'], 'relative_path' => $item['filename'] ]; } } else { if (!$this->commonValidate(__FUNCTION__,[$field=>$files])) { return $this->msg(-1,$this->validate->getError()); } //上传到七牛 $result = $this->qn->uploadFile($field); $data = [ 'cdn' => Env::get('QINIU.cdn'), 'origin_name' => $files[$field]->getOriginalName(), 'filename' => explode('/',$result['filename'])[count(explode('/',$result['filename']))-1], 'md5' => md5_file($files[$field]->getPathname()), 'url' => $result['remote_url'], 'relative_path' => $result['filename'] ]; } return $this->msg(200, '上传成功', $data); } /** * 删除 */ public function del():\think\Response\Json { $inputData = $this->request->param(['id']); $inputData['platform_id'] = $this->platformId; if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->delData($inputData); if ($result) { return $this->msg(200,"删除成功"); } else { return $this->msg(504,"删除失败"); } } /** * 列表树 */ public function tree():\think\Response\Json { $inputData = $this->request->param(); if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } $inputData['platform_id'] = $this->platformId; if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $list = $this->model->getAllList($inputData); $tree = list_to_tree($list); return $this->msg(200, '获取列表成功', $tree); } /** * 排序 */ public function sort():\think\Response\Json { $inputData = $this->request->param(['id','sort']); if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } $inputData['platform_id'] = $this->platformId; if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->editData($inputData); if ($result) { return $this->msg(200,"排序成功"); } else { return $this->msg(504,"排序失败"); } } /** * 启用禁用 */ public function changeStatus():\think\Response\Json { $inputData = $this->request->param(['id','status']); if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } if (!$this->commonValidate(__FUNCTION__,$inputData)) { return $this->msg(-1,$this->validate->getError()); } $result = $this->model->changeStatus($inputData); if ($result) { return $this->msg(200,"操作成功"); } else { return $this->msg(504,"操作失败"); } } /** * 批量新增 */ public function batchCreate():\think\Response\Json { $inputData = $this->request->param(); if (count($inputData['data']) > 0) { foreach ($inputData['data'] as &$item) { if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } if (!$this->commonValidate(__FUNCTION__,$item)) { return $this->msg(-1,$this->validate->getError()); } $item['platform_id'] = $this->platformId; } } $result = $this->model->saveAll($inputData['data']); if ($result) { return $this->msg(200,'新增成功'); } else { return $this->msg(504,'新增失败'); } } /** * 批量更新 */ public function batchUpdate():\think\Response\Json { $inputData = $this->request->param(); if (count($inputData['data']) > 0) { foreach ($inputData['data'] as &$item) { if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; unset($inputData['language_id']); } if (!$this->commonValidate(__FUNCTION__,$item)) { return $this->msg(-1,$this->validate->getError()); } $item['platform_id'] = $this->platformId; } } $result = $this->model->batchEditData($inputData['data']); if ($result) { return $this->msg(200,'更新成功'); } else { return $this->msg(504,'更新失败'); } } /** * 百度富文本上传 * @throws \Exception */ public function ueditorUpload():\think\Response\Json { header("Access-Control-Allow-Origin:*"); header("Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE,OPTIONS"); header("Access-Control-Allow-Headers:Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With,x_requested_with,x-token"); $action = $this->request->param(); $config = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents(root_path()."extend/utils/ueditor_config.json")), true); //替换前台图片后缀 $config['imageUrlPrefix'] = Env::get('QINIU.cdn'); $config['scrawlUrlPrefix'] = Env::get('QINIU.cdn'); $config['snapscreenUrlPrefix'] = Env::get('QINIU.cdn'); $config['catcherUrlPrefix'] = Env::get('QINIU.cdn'); $config['videoUrlPrefix'] = Env::get('QINIU.cdn'); $config['fileUrlPrefix'] = Env::get('QINIU.cdn'); $config['imageManagerUrlPrefix'] = Env::get('QINIU.cdn'); $config['fileManagerUrlPrefix'] = Env::get('QINIU.cdn'); $action['action'] ?? $action['action'] = 'config'; switch ($action['action']) { case 'uploadimage': $fieldName = $config['imageFieldName']; $config = [ "pathFormat" => $config['imagePathFormat'], "maxSize" => $config['imageMaxSize'], "allowFiles" => $config['imageAllowFiles'] ]; break; case 'uploadscrawl': $fieldName = $config['scrawlFieldName']; $config = [ "pathFormat" => $config['scrawlPathFormat'], "maxSize" => $config['scrawlMaxSize'], "allowFiles" => $config['scrawlAllowFiles'], "oriName" => "scrawl.png" ]; break; case 'uploadvideo': $fieldName = $config['videoFieldName']; $config = [ "pathFormat" => $config['videoPathFormat'], "maxSize" => $config['videoMaxSize'], "allowFiles" => $config['videoAllowFiles'] ]; break; case 'uploadfile': $fieldName = $config['fileFieldName']; $config = [ "pathFormat" => $config['filePathFormat'], "maxSize" => $config['fileMaxSize'], "allowFiles" => $config['fileAllowFiles'] ]; break; case 'config': default: echo isset($action['callback']) ? $action['callback'].'('.json_encode($config).')': '('.json_encode($config).')';die; } $up = new UEUploader($fieldName, $config); $resultData = $up->getFileInfo(); if ($resultData['state'] == 'SUCCESS') { //本地文件上传七牛云 $qn = new QiniuUploader(); $res = $qn->uploadLocalFile(public_path().$resultData['url'],$resultData['url']); $data = [ "state" => "SUCCESS", "title" => $resultData["title"], "original" => $resultData["original"], "type" => $resultData["type"], "size" => $resultData["size"], 'cdn' => Env::get('QINIU.cdn'), 'filename' => explode('/',$res['filename'])[count(explode('/',$res['filename']))-1], // 'url' => $res['remote_url'], 'url' => $res['filename'], 'relative_path' => $res['filename'] ]; echo json_encode($data);die; } else { echo "上传失败";die; } } /** * 静态cdn域名 */ public function getCDNUrl():\think\Response\Json { $data = [ 'domain' => Env::get('QINIU.cdn','') ]; return $this->msg(200,'获取成功',$data); } /** * Excel导入 */ public function import():\think\Response\Json { $file = $this->request->file('file'); if (!$file) { return $this->msg(-1,'没有上传文件'); } // if ($this->commonValidate(__FUNCTION__,['file'=>$file])) { // return json($this->message(true)); // } $filename = Filesystem::disk('public')->putFile('', $file, 'unique_id'); $filePath = public_path().'storage/' . $filename; if (!is_file($filePath)) { return $this->msg(-1,'没找到数据'); } //实例化reader $ext = pathinfo($filePath, PATHINFO_EXTENSION); if (!in_array($ext, ['csv', 'xls', 'xlsx'])) { return $this->msg(-1,'文件格式不对'); } if ($ext === 'csv') { $file = fopen($filePath, 'r'); $filePath = tempnam(sys_get_temp_dir(), 'import_csv'); $fp = fopen($filePath, "w"); $n = 0; while ($line = fgets($file)) { $line = rtrim($line, "\n\r\0"); $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']); if ($encoding != 'utf-8') { $line = mb_convert_encoding($line, 'utf-8', $encoding); } if ($n == 0 || preg_match('/^".*"$/', $line)) { fwrite($fp, $line . "\n"); } else { fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n"); } $n++; } fclose($file) || fclose($fp); $reader = new Csv(); } elseif ($ext === 'xls') { $reader = new Xls(); } else { $reader = new Xlsx(); } //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name $table = $this->model->getTable(); $database = Env::get('database.database'); $fieldArr = []; $list = Db::query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); foreach ($list as $v) { if ($this->importHeadType == 'comment') { $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; } else { $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_NAME']; } } //加载文件 $insert = []; try { if (!$PHPExcel = $reader->load($filePath)) { return $this->msg(-1,'没找到数据'); } $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表 $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号 $allRow = $currentSheet->getHighestRow(); //取得一共有多少行 $maxColumnNumber = Coordinate::columnIndexFromString($allColumn); $fields = []; for ($currentRow = 1; $currentRow <= 1; $currentRow++) { for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); $fields[] = $val; } } for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) { $values = []; for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); $values[] = is_null($val) ? '' : $val; } $row = []; $temp = array_combine($fields, $values); foreach ($temp as $k => $v) { if (isset($fieldArr[$k]) && $k !== '') { $row[$fieldArr[$k]] = $v; } } if ($row) { $insert[] = $row; } } //需要关联查询的字段,进行关联相询翻译 } catch (\Exception $exception) { return $this->msg(-1,$exception->getMessage()); } //批量新增 try { $count = 0; $failCount = 0; // foreach ($insert as $item) { // if ($this->commonValidate(__FUNCTION__,$item)) { // $failCount++; // continue; // } $res = $this->model->save($insert[0]); // $count++; // } if (count($insert) > $count) { return $this->msg(-1,'总共【'.count($insert).'】,成功导入【'.$count.'】条记录,还有【'.(count($insert) - $count).'】条记录未导入成功'); } else { return $this->msg(200,'总共【'.count($insert).'】,成功导入【'.$count.'】条记录,有【'.(count($insert) - $count).'】条记录未导入成功'); } } catch (PDOException $exception) { $this->msg = $exception->getMessage(); if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $this->msg, $matches)) { $this->msg = "导入失败,包含【{$matches[1]}】的记录已存在"; return $this->msg(-1,"导入失败,包含【{$matches[1]}】的记录已存在"); } return $this->msg(-1,$exception->getMessage()); } catch (\Exception $e) { return $this->msg(-1,$e->getMessage()); } } /** * Excel导出, * @param array $data * @param int $count * @param string $fileName * @param array $options * @return \think\Response\Json */ protected function excelExport(array $data = [], int $count = 10 ,string $fileName = '', array $options = []):\think\Response\Json { try { if (empty($data)) { return $this->msg(-1,'没有选择需要导出的数据'); } set_time_limit(0); $objSpreadsheet = new Spreadsheet(); //设置全局字体,大小 $styleArray = [ 'font' => [ 'bold' => false, 'color' => ['rgb'=>'000000'], 'size' => 14, 'name' => 'Verdana' ] ]; $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray); /* 设置默认文字居左,上下居中 */ $styleArray = [ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_LEFT, 'vertical' => Alignment::VERTICAL_CENTER, ], ]; $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray); /* 设置Excel Sheet */ $activeSheet = $objSpreadsheet->setActiveSheetIndex(0); /* 打印设置 */ if (isset($options['print']) && $options['print']) { /* 设置打印为A4效果 */ $activeSheet->getPageSetup()->setPaperSize(PageSetup:: PAPERSIZE_A4); /* 设置打印时边距 */ $pValue = 1 / 2.54; $activeSheet->getPageMargins()->setTop($pValue / 2); $activeSheet->getPageMargins()->setBottom($pValue * 2); $activeSheet->getPageMargins()->setLeft($pValue / 2); $activeSheet->getPageMargins()->setRight($pValue / 2); } $row = 2; $col = 0; /* 行数据处理 */ foreach ($data as $sKey => $sItem) { /* 默认文本格式 */ $pDataType = DataType::TYPE_STRING; /* 设置单元格格式 */ if (isset($options['format']) && !empty($options['format'])) { $colRow = Coordinate::coordinateFromString($sKey); /* 存在该列格式并且有特殊格式 */ if (isset($options['format'][$colRow[0]]) && NumberFormat::FORMAT_GENERAL != $options['format'][$colRow[0]]) { $activeSheet->getStyle($sKey)->getNumberFormat() ->setFormatCode($options['format'][$colRow[0]]); if (false !== strpos($options['format'][$colRow[0]], '0.00') && is_numeric(str_replace(['¥', ','], '', $sItem))) { /* 数字格式转换为数字单元格 */ $pDataType = DataType::TYPE_NUMERIC; $sItem = str_replace(['¥', ','], '', $sItem); } } elseif (is_int($sItem)) { $pDataType = DataType::TYPE_NUMERIC; } } if ($col < count($options['alignCenter'])) { if (strlen($sItem) <= 255) { $activeSheet->getColumnDimension($options['alignCenter'][$col])->setWidth(100); } else { $activeSheet->getColumnDimension($options['alignCenter'][$col])->setAutoSize(true); } } $activeSheet->getRowDimension($row)->setRowHeight(30); $activeSheet->setCellValueExplicit($sKey, $sItem, $pDataType); $row++; $col++; /* 存在:形式的合并行列,列入A1:B2,则对应合并 */ if (false !== strstr($sKey, ":")) { $options['mergeCells'][$sKey] = $sKey; } if (is_image(public_path().$sItem) && file_exists(public_path().$sItem)) { $activeSheet->setCellValueExplicit($sKey, '', $pDataType); $drawing = new Drawing(); $drawing->setName('Logo'); $drawing->setDescription('Logo'); $drawing->setPath(Env::get('root_path').'public'.$sItem); $drawing->setResizeProportional(false); $drawing->setHeight(60); $drawing->setCoordinates($sKey); $drawing->setOffsetX(12); $drawing->setOffsetY(12); $drawing->getShadow()->setVisible(true); // $drawing->getShadow()->setDirection(45); $drawing->setWorksheet($objSpreadsheet->getActiveSheet()); } } unset($data); /* 设置锁定行 */ if (isset($options['freezePane']) && !empty($options['freezePane'])) { $activeSheet->freezePane($options['freezePane']); unset($options['freezePane']); } /* 设置宽度 */ if (isset($options['setWidth']) && !empty($options['setWidth'])) { foreach ($options['setWidth'] as $swKey => $swItem) { $activeSheet->getColumnDimension($swKey)->setWidth($swItem); } unset($options['setWidth']); } else { $end = $count + 64 > 80 ? 80 : $count + 64; foreach(range(chr(65),chr($end)) as $columnID) { $activeSheet->getColumnDimension($columnID)->setAutoSize(true); } } /* 设置背景色 */ if (isset($options['setARGB']) && !empty($options['setARGB'])) { foreach ($options['setARGB'] as $sItem) { $activeSheet->getStyle($sItem) ->getFill()->setFillType(Fill::FILL_SOLID) ->getStartColor()->setARGB(Color::COLOR_YELLOW); } unset($options['setARGB']); } /* 设置公式 */ if (isset($options['formula']) && !empty($options['formula'])) { foreach ($options['formula'] as $fKey => $fItem) { $activeSheet->setCellValue($fKey, $fItem); } unset($options['formula']); } /* 合并行列处理 */ if (isset($options['mergeCells']) && !empty($options['mergeCells'])) { $activeSheet->setMergeCells($options['mergeCells']); unset($options['mergeCells']); } /* 设置居中 */ if (isset($options['alignCenter']) && !empty($options['alignCenter'])) { $styleArray = [ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_LEFT, 'vertical' => Alignment::VERTICAL_CENTER, ], ]; foreach ($options['alignCenter'] as $acItem) { $activeSheet->getStyle($acItem)->applyFromArray($styleArray); } unset($options['alignCenter']); } /* 设置加粗 */ if (isset($options['bold']) && !empty($options['bold'])) { foreach ($options['bold'] as $bItem) { $activeSheet->getStyle($bItem)->getFont()->setBold(true); } unset($options['bold']); } /* 设置单元格边框,整个表格设置即可,必须在数据填充后才可以获取到最大行列 */ if (isset($options['setBorder']) && $options['setBorder']) { $border = [ 'borders' => [ 'allBorders' => [ 'borderStyle' => Border::BORDER_THIN, // 设置border样式 'color' => ['argb' => 'FF000000'], // 设置border颜色 ], ], ]; $setBorder = 'A1:' . $activeSheet->getHighestColumn() . $activeSheet->getHighestRow(); $activeSheet->getStyle($setBorder)->applyFromArray($border); unset($options['setBorder']); } $fileName = !empty($fileName) ? $fileName : (date('YmdHis') . '.xlsx'); if (!isset($options['savePath'])) { /* 直接导出Excel,无需保存到本地,输出07Excel文件 */ header('Content-Type: application/vnd.ms-excel,application/x-rar-compressed,application/vnd.openxmlformats-officedocument.wordprocessingml.document; Charset=UTF-8'); header('Access-Control-Expose-Headers: Content-Disposition'); // header( // "Content-Disposition:attachment;filename=" . iconv( // "utf-8", "GB2312//TRANSLIT", $fileName // ) // ); header("Content-Disposition:attachment;filename=" . $fileName); header('Cache-Control: max-age=0');//禁止缓存 header("Content-Transfer-Encoding:binary"); $savePath = 'php://output'; } else { $savePath = $options['savePath']; } ob_clean(); ob_start(); $objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx'); $objWriter->save($savePath); /* 释放内存 */ $objSpreadsheet->disconnectWorksheets(); unset($objSpreadsheet); ob_end_flush(); exit; } catch (\Exception $e) { return $this->msg(-1,$e->getMessage()); } } /** * 表格导出数据前置方法 */ public function export():\think\Response\Json { $ids = $this->request->param(); if ($this->commonValidate(__FUNCTION__,$ids)) { return $this->msg(-1,''); } $data = $this->model->getExportData($ids); //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name $this->importHeadType = 'name'; $table = $this->model->getTable(); $database = Env::get('database.database'); //字段名与注释的数组, $fieldArr = []; $list = Db::query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); foreach ($list as $v) { if ($this->importHeadType == 'comment') { $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; } else { $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_COMMENT']; } } $newData = [];/*表格数据*/ $newHeader = [];/*表格表头*/ $cols = []; /*分别占用表格哪几列*/ if (array_key_exists(0,$data)) { $header = array_keys($data[0]); foreach ($header as $k => $v) { if ($k <= 25) { $newHeader[chr($k+65).'1'] = $fieldArr[$v]?:$v; $cols[$k] = chr($k+65); } else { $newHeader[chr(65).chr($k-26+65).'1'] = $fieldArr[$v]?:$v; $cols[$k] = chr(65).chr($k-26+65); } } } foreach ($data as $k => $v) { $index = 0; foreach ($v as $v1) { if ($index <= 25) { $header = chr($index+65); $header .= $k+2; $newData[$header] = $v1;/*获取表头*/ } else { $header = chr(65).chr($index-26+65); $header .= $k+2; $newData[$header] = $v1;/*获取表头*/ } $index++; } } $newData = array_merge($newHeader,$newData); $options = [ 'print' =>false, 'freezePane'=>'A2', // 'setWidth'=>['A'=>40,'B'=>30,'C'=>20,'D'=>25,'E'=>20,'F'=>15,'G'=>10,'H'=>10], 'setBorder'=>true, 'alignCenter'=>$cols, 'bold'=>array_keys($newHeader), ]; return $this->excelExport($newData,count($newHeader),'export-excel-'.time().'.xlsx',$options); } /** * 异步提交 * @param array $apiLog 日志提交的数据 * @param string $logType 日志类型 api_logs * @param string $type 请求类型 api add queue * @return string */ public function asyncApiLog(array $apiLog, string $logType, string $type):string { // 异步执行 // Async::exec(LogToKafka::class, 'sendLogsToKafkaProduce', $apiLog,$logType,'user',$type); // Async::execUseCustomQueue(self::class, 'test','async_exec_method_custom', 'exec'); // 异步延迟执行 延迟20秒 Async::delay(20, LogToKafka::class, 'sendLogsToKafkaProduce', $apiLog,$logType,Env::get('database.database'),$type); // Async::delayUseCustomQueue(20, LogToKafka::class, 'sendLogsToKafkaProduce','async_exec_method_custom', $apiLog,$logType,Env::get('database.database'),$type); return ''; } /** * 写入日志调试信息 * @param array $data * @param string $string * @return void */ public function dLog(array $data,string $string = 'debug') : void { \think\facade\Log::record($string . " = ".json_encode($data)); } }