diff --git a/app/admin/controller/v1/Article.php b/app/admin/controller/v1/Article.php index dd5c99b3..c2e3ddb4 100644 --- a/app/admin/controller/v1/Article.php +++ b/app/admin/controller/v1/Article.php @@ -5,6 +5,8 @@ namespace app\admin\controller\v1; use app\admin\model\v1\ArticleModel; use app\admin\validate\v1\ArticleValidate; +use PhpOffice\PhpSpreadsheet\IOFactory; +use PhpOffice\PhpSpreadsheet\Spreadsheet; class Article { @@ -163,4 +165,103 @@ class Article } return success('操作成功'); } + + // 文章导出 + public function export() + { + $schema = [ + 'id' => 'ID', + 'category_name' => '分类名称', + 'title' => '标题', + 'author' => '作者', + 'source' => '来源', + 'image' => '封面图片', + 'link' => '外链', + 'desc' => '描述', + 'content' => '内容详情', + 'recommend' => '是否推荐', + 'sort' => '排序值', + 'view_count' => '浏览量', + 'praise_count' => '点赞数', + 'seo_title' => 'seo标题', + 'seo_keywords' => 'seo关键词', + 'seo_desc' => 'seo描述', + 'enabled' => '是否启用', + 'release_time' => '发布时间', + 'created_at' => '添加时间', + 'updated_at' => '最后更新时间' + ]; + + // 获取导出数据 + $data = $this->getExportArticleData(); + + // 获取Spreadsheet对象 + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + // 写入表头 + $title = array_values($schema); + $title_col = 'A'; + foreach ($title as $value) { + // 单元格内容写入 + $sheet->setCellValue($title_col . '1', $value); + $title_col++; + } + + // 写入数据 + $row = 2; + $keys = array_keys($schema); + foreach ($data as $item) { + $data_col = 'A'; + foreach ($keys as $key) { + $sheet->setCellValue($data_col . $row, $item[$key]); + $data_col++; + } + $row++; + } + + flush(); + ob_flush(); + $filename = date('YmdHms'); + header('Access-Control-Expose-Headers: Content-Disposition'); + header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; Charset=UTF-8'); + header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"'); + header('Cache-Control: max-age=0'); + $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); + $writer->save('php://output'); + exit; + } + + // 获取文章导出数据 + private function getExportArticleData() + { + $server = request()->server(); + $image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . config('filesystem.disks.public.url') . '/'; + $param = request()->param(['title', 'category_id', 'created_at']); + $data = ArticleModel::field([ + '*', + 'CONCAT("' . $image_host . '", `image`)' => 'image', + 'CASE WHEN recommend = 1 THEN "是" ELSE "否" END' => 'recommend', + 'CASE WHEN enabled = 1 THEN "是" ELSE "否" END' => 'enabled', + ]) + ->with('category', function($query) { + return $query->field(['id', 'name']); + }) + ->language(request()->lang_id) + ->categoryNullable($param['category_id']??null) + ->withSearch(['title', 'created_at'], [ + 'title' => $param['title']??'', + 'created_at' => !empty($param['created_at'])?explode(',', $param['created_at']):'' + ]) + ->order('sort', 'desc') + ->select() + ->hidden([ + 'language_id', + 'category_id', + 'category', + ]) + ->bindAttr('category', ['category_name' => 'name']); + + return $data->toArray(); + } } diff --git a/app/admin/model/v1/ArticleModel.php b/app/admin/model/v1/ArticleModel.php index 0c18dbe2..88115493 100644 --- a/app/admin/model/v1/ArticleModel.php +++ b/app/admin/model/v1/ArticleModel.php @@ -49,6 +49,9 @@ class ArticleModel extends ArticleBaseModel // 语言查询 public function scopeLanguage($query, $value) { + if (is_null($value)) { + return; + } $query->where('language_id', '=', $value); } @@ -57,4 +60,11 @@ class ArticleModel extends ArticleBaseModel { $query->where('category_id', '=', $value); } + public function scopeCategoryNullable($query, $value) + { + if (is_null($value)) { + return; + } + $query->where('category_id', '=', $value); + } } diff --git a/app/admin/route/v1.php b/app/admin/route/v1.php index 058a08d3..824f6509 100644 --- a/app/admin/route/v1.php +++ b/app/admin/route/v1.php @@ -49,6 +49,9 @@ Route::group('v1', function () { // 文章删除 Route::delete('delete/:id', 'Article/delete'); + // 文章导出 + Route::get('export', 'Article/export'); + // 文章分类 Route::get('categorys', 'ArticleCategory/list'); diff --git a/app/common/model/ArticleBaseModel.php b/app/common/model/ArticleBaseModel.php index 3a74df33..33334118 100644 --- a/app/common/model/ArticleBaseModel.php +++ b/app/common/model/ArticleBaseModel.php @@ -36,6 +36,7 @@ class ArticleBaseModel extends Model 'seo_title' => 'string', 'seo_keywords' => 'string', 'seo_desc' => 'string', + 'enabled' => 'int', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', diff --git a/composer.json b/composer.json index fb98f826..51f53e19 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,8 @@ "thans/tp-jwt-auth": "^2.2", "topthink/think-throttle": "^2.0", "intervention/image": "^3.10", - "topthink/think-cors": "^1.0" + "topthink/think-cors": "^1.0", + "phpoffice/phpspreadsheet": "^3.8" }, "require-dev": { "symfony/var-dumper": ">=4.2",