param('page', 1, 'intval'); $limit = $request->param('limit', 15, 'intval'); $type = $request->param('type', ''); $category_id = $request->param('category_id', 0, 'intval'); $keyword = $request->param('keyword', ''); $model_list = Post::with(['categorys.category', 'tags.tag']) ->order('id desc'); if (!empty($type)) { $model_list = $model_list->where('type', $type); } if (!empty($category_id)) { $model_list = $model_list->where('category_id', $category_id); } if (!empty($keyword)) { $model_list = $model_list->where('title', 'like', "%{$keyword}%"); } $list = $model_list->paginate([ 'page' => $page, 'list_rows' => $limit, ]); return json_message([ 'list' => $list->items(), 'total' => $list->total(), 'page' => $page, ]); } /** * 文章详情 */ public function read(Request $request) { $id = $request->param('id', 0, 'intval'); if ($id <= 0) { return json_message('参数错误'); } $post = Post::with(['categorys.category', 'tags.tag'])->find($id); if (empty($post)) { return json_message('文章不存在'); } return json_message(['post' => $post]); } /** * 创建文章 */ public function save(Request $request) { if ($request->can_write_own != 1) { return json_message('无权操作', 403); } $post_data = $request->post(); if (empty($post_data['title'])) { return json_message('标题必填'); } $categorys = []; $tags = []; if (isset($post_data['categorys'])) { $categorys = $post_data['categorys']; unset($post_data['categorys']); } if (isset($post_data['tags'])) { $tags = $post_data['tags']; unset($post_data['tags']); } // 禁止客户端设置的时间字段 unset($post_data['create_time'], $post_data['update_time']); $post_data['uid'] = uniqid(); $post_data['source'] = 'api'; $post_data['create_time'] = time(); $post_data['update_time'] = time(); if (!isset($post_data['type'])) { $post_data['type'] = '1'; } if (!isset($post_data['status'])) { $post_data['status'] = 0; } if (!isset($post_data['content_type'])) { $post_data['content_type'] = 'html'; } // 校验 publish_time 格式(必须是 Y-m-d H:i:s) if (isset($post_data['publish_time']) && !empty($post_data['publish_time'])) { if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $post_data['publish_time'])) { return json_message('publish_time 格式错误,应为 Y-m-d H:i:s,如 2024-01-15 14:30:00'); } } // content_type 白名单校验 $allowed_content_types = ['html', 'markdown']; if (!in_array($post_data['content_type'], $allowed_content_types)) { return json_message('无效的content_type', 500); } // Markdown→HTML 自动转换(启用表格扩展) if ($post_data['content_type'] === 'markdown' && !empty($post_data['content'])) { $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new TableExtension()); $converter = new MarkdownConverter($environment); $post_data['content_html'] = $converter->convert($post_data['content'])->getContent(); } // 提供字段默认值,避免数据库严格模式报错 $default_fields = [ 'jump_to_btn_title' => '', 'jump_to_url' => '', 'jump_to_url_status' => 0, 'poster' => '', 'desc' => '', 'author_name' => '', 'hits' => 0, 'is_top' => 0, 'sort' => 0, 'files' => '', 'pictures' => '', 'tpl_name' => '', ]; foreach ($default_fields as $field => $default) { if (!isset($post_data[$field])) { $post_data[$field] = $default; } } $model_post = Post::create($post_data); foreach ($categorys as $category) { PostCategory::create([ 'post_id' => $model_post->id, 'category_id' => $category, ]); } foreach ($tags as $tag) { PostTag::create([ 'post_id' => $model_post->id, 'tag_id' => $tag, ]); } return json_message(['id' => $model_post->id, 'uid' => $model_post->uid], 0, '创建成功'); } /** * 编辑文章 */ public function update(Request $request) { $id = $request->param('id', 0, 'intval'); if ($id <= 0) { return json_message('参数错误'); } $model_post = Post::find($id); if (empty($model_post)) { return json_message('文章不存在'); } $source = $model_post->getData('source'); if ($source === 'api') { if ($request->can_write_own != 1) { return json_message('无权操作', 403); } } else { if ($request->can_write_other != 1) { return json_message('无权操作', 403); } } $post_data = $request->post(); unset($post_data['id']); // 禁止客户端设置的时间字段 unset($post_data['create_time'], $post_data['update_time']); // 校验 publish_time 格式(必须是 Y-m-d H:i:s) if (isset($post_data['publish_time']) && !empty($post_data['publish_time'])) { if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $post_data['publish_time'])) { return json_message('publish_time 格式错误,应为 Y-m-d H:i:s,如 2024-01-15 14:30:00'); } } // categorys diff update if (isset($post_data['categorys'])) { $categorys = $post_data['categorys']; unset($post_data['categorys']); $old_category_list = PostCategory::where('post_id', $id)->select(); $old_category_ids = array_column($old_category_list->toArray(), 'category_id'); // old has, new doesn't -> delete foreach ($old_category_list as $model_category) { if (!in_array($model_category->category_id, $categorys)) { $model_category->delete(); } } // new has, old doesn't -> create foreach ($categorys as $category) { if (!in_array($category, $old_category_ids)) { PostCategory::create([ 'post_id' => $id, 'category_id' => $category, ]); } } } // tags diff update if (isset($post_data['tags'])) { $tags = $post_data['tags']; unset($post_data['tags']); $old_tag_list = PostTag::where('post_id', $id)->select(); $old_tag_ids = array_column($old_tag_list->toArray(), 'tag_id'); foreach ($old_tag_list as $model_tag) { if (!in_array($model_tag->tag_id, $tags)) { $model_tag->delete(); } } foreach ($tags as $tag) { if (!in_array($tag, $old_tag_ids)) { PostTag::create([ 'post_id' => $id, 'tag_id' => $tag, ]); } } } // Markdown→HTML 自动转换(启用表格扩展) if (isset($post_data['content_type']) && $post_data['content_type'] === 'markdown' && !empty($post_data['content'])) { $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new TableExtension()); $converter = new MarkdownConverter($environment); $post_data['content_html'] = $converter->convert($post_data['content'])->getContent(); } $model_post->save($post_data); return json_message([], 0, '更新成功'); } /** * 删除文章 */ public function delete(Request $request) { $id = $request->param('id', 0, 'intval'); if ($id <= 0) { return json_message('参数错误'); } $model_post = Post::find($id); if (empty($model_post)) { return json_message('文章不存在'); } $source = $model_post->getData('source'); if ($source === 'api') { if ($request->can_delete < 1) { return json_message('无权删除', 403); } } else { if ($request->can_delete != 2) { return json_message('无权删除', 403); } } $model_post->delete(); PostCategory::where('post_id', $id)->delete(); PostTag::where('post_id', $id)->delete(); return json_message([], 0, '删除成功'); } }