后台布局

This commit is contained in:
李琦
2026-01-16 12:28:56 +08:00
parent 1eeeaf03ba
commit 7271199bef

View File

@@ -11,7 +11,7 @@
Target Server Version : 80407 (8.4.7)
File Encoding : 65001
Date: 16/01/2026 10:18:46
Date: 16/01/2026 12:21:22
*/
SET NAMES utf8mb4;
@@ -132,7 +132,7 @@ CREATE TABLE `operation_logs` (
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_user_id`(`user_id` ASC) USING BTREE,
INDEX `idx_created_at`(`created_at` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 196 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志表' ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB AUTO_INCREMENT = 280 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of operation_logs
@@ -332,6 +332,90 @@ INSERT INTO `operation_logs` VALUES (192, 1, 'lq', '::1', '/api/admin/dashboard/
INSERT INTO `operation_logs` VALUES (193, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 48, '2026-01-16 10:17:47');
INSERT INTO `operation_logs` VALUES (194, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 95, '2026-01-16 10:17:47');
INSERT INTO `operation_logs` VALUES (195, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 137, '2026-01-16 10:17:49');
INSERT INTO `operation_logs` VALUES (196, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 96, '2026-01-16 10:21:44');
INSERT INTO `operation_logs` VALUES (197, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 90, '2026-01-16 10:21:44');
INSERT INTO `operation_logs` VALUES (198, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 90, '2026-01-16 10:21:44');
INSERT INTO `operation_logs` VALUES (199, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 53, '2026-01-16 10:59:13');
INSERT INTO `operation_logs` VALUES (200, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 103, '2026-01-16 10:59:13');
INSERT INTO `operation_logs` VALUES (201, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 93, '2026-01-16 10:59:25');
INSERT INTO `operation_logs` VALUES (202, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 55, '2026-01-16 10:59:25');
INSERT INTO `operation_logs` VALUES (203, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 146, '2026-01-16 10:59:30');
INSERT INTO `operation_logs` VALUES (204, 1, 'lq', '::1', '/api/admin/posts', 'GET', '', 200, 49, '2026-01-16 10:59:31');
INSERT INTO `operation_logs` VALUES (205, 1, 'lq', '::1', '/api/admin/works', 'GET', '', 200, 237, '2026-01-16 10:59:32');
INSERT INTO `operation_logs` VALUES (206, 1, 'lq', '::1', '/api/admin/snippets', 'GET', '', 200, 47, '2026-01-16 10:59:35');
INSERT INTO `operation_logs` VALUES (207, 1, 'lq', '::1', '/api/admin/tags', 'GET', '', 200, 47, '2026-01-16 10:59:35');
INSERT INTO `operation_logs` VALUES (208, 1, 'lq', '::1', '/api/admin/about', 'GET', '', 200, 46, '2026-01-16 10:59:40');
INSERT INTO `operation_logs` VALUES (209, 1, 'lq', '::1', '/api/admin/about', 'GET', '', 200, 45, '2026-01-16 10:59:45');
INSERT INTO `operation_logs` VALUES (210, 1, 'lq', '::1', '/api/admin/about', 'GET', '', 200, 46, '2026-01-16 10:59:46');
INSERT INTO `operation_logs` VALUES (211, 1, 'lq', '::1', '/api/admin/inquiries', 'GET', '', 200, 46, '2026-01-16 11:00:05');
INSERT INTO `operation_logs` VALUES (212, 1, 'lq', '::1', '/api/admin/email-suffixes', 'GET', '', 200, 53, '2026-01-16 11:00:07');
INSERT INTO `operation_logs` VALUES (213, 1, 'lq', '::1', '/api/admin/users', 'GET', '', 200, 49, '2026-01-16 11:00:09');
INSERT INTO `operation_logs` VALUES (214, 1, 'lq', '::1', '/api/admin/roles', 'GET', '', 200, 147, '2026-01-16 11:00:10');
INSERT INTO `operation_logs` VALUES (215, 1, 'lq', '::1', '/api/admin/settings', 'GET', '', 200, 45, '2026-01-16 11:00:40');
INSERT INTO `operation_logs` VALUES (216, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 47, '2026-01-16 11:00:41');
INSERT INTO `operation_logs` VALUES (217, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 48, '2026-01-16 11:00:43');
INSERT INTO `operation_logs` VALUES (218, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 146, '2026-01-16 11:00:46');
INSERT INTO `operation_logs` VALUES (219, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 150, '2026-01-16 11:01:00');
INSERT INTO `operation_logs` VALUES (220, 1, 'lq', '::1', '/api/admin/users', 'GET', '', 200, 49, '2026-01-16 11:01:15');
INSERT INTO `operation_logs` VALUES (221, 1, 'lq', '::1', '/api/admin/roles', 'GET', '', 200, 142, '2026-01-16 11:01:15');
INSERT INTO `operation_logs` VALUES (222, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 148, '2026-01-16 11:02:00');
INSERT INTO `operation_logs` VALUES (223, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 49, '2026-01-16 11:03:05');
INSERT INTO `operation_logs` VALUES (224, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 96, '2026-01-16 11:03:05');
INSERT INTO `operation_logs` VALUES (225, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 93, '2026-01-16 11:04:41');
INSERT INTO `operation_logs` VALUES (226, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 49, '2026-01-16 11:04:41');
INSERT INTO `operation_logs` VALUES (227, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 49, '2026-01-16 11:05:25');
INSERT INTO `operation_logs` VALUES (228, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 100, '2026-01-16 11:05:25');
INSERT INTO `operation_logs` VALUES (229, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 47, '2026-01-16 11:05:38');
INSERT INTO `operation_logs` VALUES (230, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 95, '2026-01-16 11:05:38');
INSERT INTO `operation_logs` VALUES (231, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 94, '2026-01-16 11:08:30');
INSERT INTO `operation_logs` VALUES (232, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 50, '2026-01-16 11:08:30');
INSERT INTO `operation_logs` VALUES (233, 1, 'lq', '::1', '/api/admin/tags', 'GET', '', 200, 49, '2026-01-16 11:08:32');
INSERT INTO `operation_logs` VALUES (234, 1, 'lq', '::1', '/api/admin/settings', 'GET', '', 200, 46, '2026-01-16 11:08:34');
INSERT INTO `operation_logs` VALUES (235, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 45, '2026-01-16 11:08:35');
INSERT INTO `operation_logs` VALUES (236, 1, 'lq', '::1', '/api/admin/about', 'GET', '', 200, 46, '2026-01-16 11:08:37');
INSERT INTO `operation_logs` VALUES (237, 1, 'lq', '::1', '/api/admin/posts', 'GET', '', 200, 46, '2026-01-16 11:08:39');
INSERT INTO `operation_logs` VALUES (238, 1, 'lq', '::1', '/api/admin/snippets', 'GET', '', 200, 51, '2026-01-16 11:10:52');
INSERT INTO `operation_logs` VALUES (239, 1, 'lq', '::1', '/api/admin/works', 'GET', '', 200, 246, '2026-01-16 11:12:34');
INSERT INTO `operation_logs` VALUES (240, 1, 'lq', '::1', '/api/admin/posts', 'GET', '', 200, 46, '2026-01-16 11:12:39');
INSERT INTO `operation_logs` VALUES (241, 1, 'lq', '::1', '/api/admin/posts', 'GET', '', 200, 46, '2026-01-16 11:12:47');
INSERT INTO `operation_logs` VALUES (242, 1, 'lq', '::1', '/api/admin/posts', 'GET', '', 200, 44, '2026-01-16 11:12:53');
INSERT INTO `operation_logs` VALUES (243, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 46, '2026-01-16 11:13:22');
INSERT INTO `operation_logs` VALUES (244, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 92, '2026-01-16 11:13:22');
INSERT INTO `operation_logs` VALUES (245, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 94, '2026-01-16 11:13:32');
INSERT INTO `operation_logs` VALUES (246, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 55, '2026-01-16 11:13:32');
INSERT INTO `operation_logs` VALUES (247, 1, 'lq', '::1', '/api/admin/settings', 'GET', '', 200, 46, '2026-01-16 11:13:34');
INSERT INTO `operation_logs` VALUES (248, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 137, '2026-01-16 11:13:42');
INSERT INTO `operation_logs` VALUES (249, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 143, '2026-01-16 11:13:46');
INSERT INTO `operation_logs` VALUES (250, 1, 'lq', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 92, '2026-01-16 11:13:49');
INSERT INTO `operation_logs` VALUES (251, 1, 'lq', '::1', '/api/admin/operation-logs', 'GET', '', 200, 45, '2026-01-16 11:13:49');
INSERT INTO `operation_logs` VALUES (252, 1, 'lq', '::1', '/api/admin/users', 'GET', '', 200, 47, '2026-01-16 11:13:58');
INSERT INTO `operation_logs` VALUES (253, 1, 'lq', '::1', '/api/admin/users/2', 'GET', '', 200, 48, '2026-01-16 11:14:02');
INSERT INTO `operation_logs` VALUES (254, 1, 'lq', '::1', '/api/admin/users', 'GET', '', 200, 45, '2026-01-16 11:14:04');
INSERT INTO `operation_logs` VALUES (255, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 96, '2026-01-16 11:14:25');
INSERT INTO `operation_logs` VALUES (256, 5, 'cs', '::1', '/api/admin/operation-logs', 'GET', '', 200, 51, '2026-01-16 11:14:25');
INSERT INTO `operation_logs` VALUES (257, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 142, '2026-01-16 11:14:30');
INSERT INTO `operation_logs` VALUES (258, 5, 'cs', '::1', '/api/admin/works', 'GET', '', 200, 233, '2026-01-16 11:14:31');
INSERT INTO `operation_logs` VALUES (259, 5, 'cs', '::1', '/api/admin/posts', 'GET', '', 200, 45, '2026-01-16 11:14:32');
INSERT INTO `operation_logs` VALUES (260, 5, 'cs', '::1', '/api/admin/works', 'GET', '', 200, 219, '2026-01-16 11:16:01');
INSERT INTO `operation_logs` VALUES (261, 5, 'cs', '::1', '/api/admin/works', 'GET', '', 200, 221, '2026-01-16 11:16:06');
INSERT INTO `operation_logs` VALUES (262, 5, 'cs', '::1', '/api/admin/snippets', 'GET', '', 200, 48, '2026-01-16 11:16:10');
INSERT INTO `operation_logs` VALUES (263, 5, 'cs', '::1', '/api/admin/tags', 'GET', '', 200, 44, '2026-01-16 11:16:11');
INSERT INTO `operation_logs` VALUES (264, 5, 'cs', '::1', '/api/admin/posts', 'GET', '', 200, 45, '2026-01-16 11:16:12');
INSERT INTO `operation_logs` VALUES (265, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 139, '2026-01-16 11:16:13');
INSERT INTO `operation_logs` VALUES (266, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 153, '2026-01-16 11:22:15');
INSERT INTO `operation_logs` VALUES (267, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 183, '2026-01-16 11:24:06');
INSERT INTO `operation_logs` VALUES (268, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 182, '2026-01-16 11:24:10');
INSERT INTO `operation_logs` VALUES (269, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 180, '2026-01-16 11:24:11');
INSERT INTO `operation_logs` VALUES (270, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 193, '2026-01-16 11:24:12');
INSERT INTO `operation_logs` VALUES (271, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 192, '2026-01-16 11:24:14');
INSERT INTO `operation_logs` VALUES (272, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 197, '2026-01-16 11:25:30');
INSERT INTO `operation_logs` VALUES (273, 5, 'cs', '::1', '/api/admin/email-suffixes', 'GET', '', 200, 46, '2026-01-16 11:40:51');
INSERT INTO `operation_logs` VALUES (274, 5, 'cs', '::1', '/api/admin/email-suffixes', 'GET', '', 200, 47, '2026-01-16 11:48:15');
INSERT INTO `operation_logs` VALUES (275, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 189, '2026-01-16 11:57:59');
INSERT INTO `operation_logs` VALUES (276, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 190, '2026-01-16 11:59:06');
INSERT INTO `operation_logs` VALUES (277, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 190, '2026-01-16 11:59:08');
INSERT INTO `operation_logs` VALUES (278, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 189, '2026-01-16 11:59:11');
INSERT INTO `operation_logs` VALUES (279, 5, 'cs', '::1', '/api/admin/dashboard/stats', 'GET', '', 200, 196, '2026-01-16 11:59:13');
-- ----------------------------
-- Table structure for partners
@@ -455,9 +539,9 @@ CREATE TABLE `posts` (
INSERT INTO `posts` VALUES (1, 'refactor', '重构的艺术:如何优雅地处理遗留代码', '工程化', '2026-01-13', '在本文中,我们将探讨重构的核心原则和实用技巧,帮助你优雅地处理遗留代码,提高代码质量和可维护性。', '<h2>什么是代码重构?</h2><p>代码重构是在不改变代码外部行为的前提下,优化代码内部结构的过程...</p>', 4, 1, '2026-01-13 16:10:14', '2026-01-15 17:01:44');
INSERT INTO `posts` VALUES (2, 'shader', '着色器魔法:从零开始写一个噪声生成器', '图形渲染', '2026-01-13', '深入了解WebGL着色器学习如何从零开始实现一个高性能的噪声生成器为你的3D作品增添独特的视觉效果。', ' <p>GLSL (OpenGL Shading Language) 是一门让人生畏但也充满魅力的语言。它运行在 GPU 上,能够并行处理数百万个像素,创造出惊人的视觉效果。</p>\r\n <h2>什么是柏林噪声?</h2>\r\n <p>柏林噪声Perlin Noise是一种梯度噪声它比普通的随机数生成的噪声看起来更自然、更平滑。它常被用来模拟云彩、地形、火焰等自然现象。</p>\r\n <h2>Three.js 中的实现</h2>\r\n <p>在 Three.js 中,我们可以通过 <code>ShaderMaterial</code> 直接编写 GLSL 代码。</p>\r\n <pre><code><span class=\"code-comment\">// 简单的顶点着色器</span>\r\n<span class=\"code-keyword\">varying</span> <span class=\"code-keyword\">vec2</span> vUv;\r\n<span class=\"code-keyword\">void</span> <span class=\"code-func\">main</span>() {\r\n vUv = uv;\r\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n}</code></pre>\r\n <p>通过调整噪声的频率和振幅,我们可以得到各种不同的纹理效果。在我的个人网站背景中,就使用了这种技术来生成流动的极光效果。</p>\r\n ', 1, 1, '2026-01-13 16:10:14', '2026-01-15 17:01:44');
INSERT INTO `posts` VALUES (3, 'ux', '用户体验设计:从认知心理学到交互实践', '设计思维', '2026-01-13', '探索用户体验设计的核心原理,结合认知心理学知识,学习如何设计出真正符合用户需求的交互界面。', '<h2>认知心理学在UX设计中的应用</h2><p>了解用户的认知过程是设计良好用户体验的基础...</p>', 0, 1, '2026-01-13 16:10:14', '2026-01-15 17:01:44');
INSERT INTO `posts` VALUES (4, 'goravel-guide-1', 'Goravel 入门指南 (一):环境搭建与 Hello World', 'Go语言', '2026-01-15', '本文将带你了解 Go 语言领域的 Laravel —— Goravel 框架,并演示如何快速搭建环境及运行第一个 Web 服务。', '## 什么是 Goravel\n\nGoravel 是一个基于 Go 语言的 Web 开发框架,它的设计理念深受 PHP Laravel 框架的启发。如果你是一名从 PHP 转 Go 的开发者,或者你喜欢 Laravel 那种“开箱即用、优雅简洁”的开发体验,那么 Goravel 绝对是你的不二之选。\n\n它集成了丰富的功能模块包括但不限于\n- 强大的路由系统\n- ORM基于 GORM 封装)\n- 依赖注入容器\n- 队列与任务调度\n- 缓存与文件存储\n\n## 环境搭建\n\nGoravel 提供了一个名为 `knit` 的命令行工具(类似 Laravel 的 artisan可以帮助我们快速初始化项目。\n\n### 1. 安装 Knit CLI\n\n确保你已经安装了 Go (1.20+),然后运行以下命令:\n\n```bash\ngo install github.com/goravel/knit/cmd/knit@latest\n```\n\n### 2. 创建新项目\n\n使用 `knit new` 命令创建项目:\n\n```bash\nknit new my-goravel-app\ncd my-goravel-app\n```\n\n### 3. 安装依赖\n\n```bash\ngo mod tidy\n```\n\n## 目录结构\n\n打开项目你会发现它的目录结构非常清晰带有浓厚的 Laravel 风格:\n\n- **app/**: 核心业务代码Http 控制器、模型、服务提供者等)\n- **config/**: 配置文件(应用配置、数据库配置等)\n- **routes/**: 路由定义文件\n- **database/**: 数据库迁移与填充\n- **public/**: 静态资源文件\n\n## 运行 Hello World\n\nGoravel 的入口文件是根目录下的 `main.go`。在运行之前,我们先看一眼路由定义。打开 `routes/web.go`\n\n```go\npackage routes\n\nimport (\n \"github.com/goravel/framework/contracts/http\"\n \"github.com/goravel/framework/facades\"\n)\n\nfunc Web() {\n facades.Route().Get(\"/\", func(ctx http.Context) http.Response {\n return ctx.Response().Json(200, http.Json{\n \"Hello\": \"Goravel\",\n })\n })\n}\n```\n\n非常直观现在让我们启动服务\n\n```bash\ngo run .\n```\n\n默认情况下服务会运行在 `http://localhost:3000`。打开浏览器访问,你应该能看到 JSON 响应:\n\n```json\n{\n \"Hello\": \"Goravel\"\n}\n```\n\n至此你已经成功运行了你的第一个 Goravel 应用!在下一篇文章中,我们将深入探讨路由与控制器的使用。', 1209, 1, '2026-01-15 16:32:12', '2026-01-16 10:13:34');
INSERT INTO `posts` VALUES (5, 'goravel-guide-2', 'Goravel 入门指南 (二):路由与控制器', 'Go语言', '2026-01-15', '深入理解 Goravel 的 HTTP 层,学习如何定义 RESTful 路由、创建控制器以及处理 HTTP 请求与响应。', '## 路由系统\n\n在 Goravel 中,路由定义通常位于 `routes/` 目录下。`api.go` 用于定义 API 路由,`web.go` 用于定义网页路由。Goravel 使用 `facades.Route()` 来定义路由,这得益于其强大的依赖注入系统。\n\n### 基础路由\n\n```go\n// GET 请求\nfacades.Route().Get(\"/users\", func(ctx http.Context) http.Response {\n return ctx.Response().String(200, \"User List\")\n})\n\n// POST 请求\nfacades.Route().Post(\"/users\", func(ctx http.Context) http.Response {\n return ctx.Response().Success().Json(http.Json{\"id\": 1})\n})\n```\n\n### 路由参数\n\n获取 URL 中的动态参数非常简单:\n\n```go\nfacades.Route().Get(\"/users/{id}\", func(ctx http.Context) http.Response {\n id := ctx.Request().Input(\"id\")\n return ctx.Response().Success().Json(http.Json{\"user_id\": id})\n})\n```\n\n## 控制器 (Controllers)\n\n随着应用变大我们不可能把所有逻辑都写在路由闭包里。这时候就需要控制器了。\n\n### 创建控制器\n\n使用 `knit` 工具可以快速生成控制器:\n\n```bash\nknit make:controller UserController\n```\n\n这会在 `app/http/controllers` 目录下生成 `user_controller.go`。让我们修改它来添加一个 `Show` 方法:\n\n```go\npackage controllers\n\nimport (\n \"github.com/goravel/framework/contracts/http\"\n)\n\ntype UserController struct {\n // 可以在这里注入服务\n}\n\nfunc NewUserController() *UserController {\n return &UserController{}\n}\n\nfunc (r *UserController) Show(ctx http.Context) http.Response {\n id := ctx.Request().Input(\"id\")\n // 模拟数据库查询\n return ctx.Response().Success().Json(http.Json{\n \"id\": id,\n \"name\": \"Goravel User\",\n })\n}\n```\n\n### 注册控制器路由\n\n回到 `routes/api.go`,我们需要先实例化控制器,然后绑定路由:\n\n```go\nimport \"my-goravel-app/app/http/controllers\"\n\nfunc Api() {\n userController := controllers.NewUserController()\n \n // 绑定到控制器方法\n facades.Route().Get(\"/users/{id}\", userController.Show)\n}\n```\n\n## 请求与响应\n\n在控制器方法中`ctx` (http.Context) 是核心:\n\n- **获取输入**: `ctx.Request().Input(\"key\")`\n- **获取 JSON**: `ctx.Request().Bind(&user)`\n- **返回 JSON**: `ctx.Response().Json(200, data)`\n- **设置状态码**: `ctx.Response().Status(404)`\n\n通过这种方式Goravel 让 HTTP 层的处理变得异常清晰和标准化。下一章,我们将学习如何通过 ORM 操作数据库。', 899, 1, '2026-01-15 16:32:12', '2026-01-16 10:13:35');
INSERT INTO `posts` VALUES (6, 'goravel-guide-3', 'Goravel 入门指南 (三)ORM 数据库操作', 'Go语言', '2026-01-15', '掌握 Goravel 强大的 ORM 功能从数据库配置、模型定义到执行增删改查CRUD操作。', '## Goravel ORM 简介\n\nGoravel 的 ORM 基于著名的 GORM 库构建,但它进行了一层优雅的封装,使其调用方式更接近 Laravel 的 Eloquent ORM。这意味着你可以使用 Facade 模式轻松调用数据库,且支持自动迁移。\n\n## 配置数据库\n\n打开 `config/database.go` 或 `.env` 文件,配置你的 MySQL 连接信息:\n\n```env\nDB_CONNECTION=mysql\nDB_HOST=127.0.0.1\nDB_PORT=3306\nDB_DATABASE=goravel\nDB_USERNAME=root\nDB_PASSWORD=password\n```\n\n## 定义模型\n\n使用 `knit` 生成模型:\n\n```bash\nknit make:model Post\n```\n\n生成的模型文件位于 `app/models/post.go`。我们需要定义结构体字段:\n\n```go\npackage models\n\nimport (\n \"github.com/goravel/framework/database/orm\"\n)\n\ntype Post struct {\n orm.Model\n Title string `gorm:\"size:255;not null\"`\n Content string `gorm:\"type:text\"`\n UserID uint\n}\n```\n\n## 数据库迁移\n\n虽然 GORM 支持 AutoMigrate但 Goravel 推荐使用迁移文件来管理数据库变更。\n\n```bash\nknit make:migration create_posts_table\n```\n\n编辑生成的迁移文件 (`database/migrations/xxxx_create_posts_table.go`),定义表结构,然后运行:\n\n```bash\nknit migrate\n```\n\n## CRUD 操作\n\n有了模型我们就可以愉快地操作数据库了。所有操作都通过 `facades.Orm()` 入口。\n\n### 创建 (Create)\n\n```go\npost := models.Post{\n Title: \"My First Post\",\n Content: \"Content goes here...\",\n}\nerr := facades.Orm().Query().Create(&post)\n```\n\n### 查询 (Read)\n\n```go\nvar post models.Post\n// 根据主键查询\nfacades.Orm().Query().Find(&post, 1)\n\n// 条件查询\nvar posts []models.Post\nfacades.Orm().Query().Where(\"title\", \"My First Post\").Get(&posts)\n```\n\n### 更新 (Update)\n\n```go\nvar post models.Post\nfacades.Orm().Query().Find(&post, 1)\n\npost.Title = \"Updated Title\"\nfacades.Orm().Query().Save(&post)\n```\n\n### 删除 (Delete)\n\n```go\nvar post models.Post\nfacades.Orm().Query().Delete(&post, 1)\n```\n\nGoravel 的 ORM 让 Go 语言的数据库操作不再繁琐,极大地提高了开发效率。配合之前的路由和控制器知识,你现在已经具备了开发完整 RESTful API 的能力!', 1560, 1, '2026-01-15 16:32:12', '2026-01-15 17:01:44');
INSERT INTO `posts` VALUES (4, 'goravel-guide-1', 'Goravel 入门指南 (一):环境搭建与 Hello World', 'Go语言', '2026-01-15', '本文将带你了解 Go 语言领域的 Laravel —— Goravel 框架,并演示如何快速搭建环境及运行第一个 Web 服务。', '## 什么是 Goravel\n\nGoravel 是一个基于 Go 语言的 Web 开发框架,它的设计理念深受 PHP Laravel 框架的启发。如果你是一名从 PHP 转 Go 的开发者,或者你喜欢 Laravel 那种“开箱即用、优雅简洁”的开发体验,那么 Goravel 绝对是你的不二之选。\n\n它集成了丰富的功能模块包括但不限于\n- 强大的路由系统\n- ORM基于 GORM 封装)\n- 依赖注入容器\n- 队列与任务调度\n- 缓存与文件存储\n\n## 环境搭建\n\nGoravel 提供了一个名为 `knit` 的命令行工具(类似 Laravel 的 artisan可以帮助我们快速初始化项目。\n\n### 1. 安装 Knit CLI\n\n确保你已经安装了 Go (1.20+),然后运行以下命令:\n\n```bash\ngo install github.com/goravel/knit/cmd/knit@latest\n```\n\n### 2. 创建新项目\n\n使用 `knit new` 命令创建项目:\n\n```bash\nknit new my-goravel-app\ncd my-goravel-app\n```\n\n### 3. 安装依赖\n\n```bash\ngo mod tidy\n```\n\n## 目录结构\n\n打开项目你会发现它的目录结构非常清晰带有浓厚的 Laravel 风格:\n\n- **app/**: 核心业务代码Http 控制器、模型、服务提供者等)\n- **config/**: 配置文件(应用配置、数据库配置等)\n- **routes/**: 路由定义文件\n- **database/**: 数据库迁移与填充\n- **public/**: 静态资源文件\n\n## 运行 Hello World\n\nGoravel 的入口文件是根目录下的 `main.go`。在运行之前,我们先看一眼路由定义。打开 `routes/web.go`\n\n```go\npackage routes\n\nimport (\n \"github.com/goravel/framework/contracts/http\"\n \"github.com/goravel/framework/facades\"\n)\n\nfunc Web() {\n facades.Route().Get(\"/\", func(ctx http.Context) http.Response {\n return ctx.Response().Json(200, http.Json{\n \"Hello\": \"Goravel\",\n })\n })\n}\n```\n\n非常直观现在让我们启动服务\n\n```bash\ngo run .\n```\n\n默认情况下服务会运行在 `http://localhost:3000`。打开浏览器访问,你应该能看到 JSON 响应:\n\n```json\n{\n \"Hello\": \"Goravel\"\n}\n```\n\n至此你已经成功运行了你的第一个 Goravel 应用!在下一篇文章中,我们将深入探讨路由与控制器的使用。', 1210, 1, '2026-01-15 16:32:12', '2026-01-16 11:08:41');
INSERT INTO `posts` VALUES (5, 'goravel-guide-2', 'Goravel 入门指南 (二):路由与控制器', 'Go语言', '2026-01-15', '深入理解 Goravel 的 HTTP 层,学习如何定义 RESTful 路由、创建控制器以及处理 HTTP 请求与响应。', '## 路由系统\n\n在 Goravel 中,路由定义通常位于 `routes/` 目录下。`api.go` 用于定义 API 路由,`web.go` 用于定义网页路由。Goravel 使用 `facades.Route()` 来定义路由,这得益于其强大的依赖注入系统。\n\n### 基础路由\n\n```go\n// GET 请求\nfacades.Route().Get(\"/users\", func(ctx http.Context) http.Response {\n return ctx.Response().String(200, \"User List\")\n})\n\n// POST 请求\nfacades.Route().Post(\"/users\", func(ctx http.Context) http.Response {\n return ctx.Response().Success().Json(http.Json{\"id\": 1})\n})\n```\n\n### 路由参数\n\n获取 URL 中的动态参数非常简单:\n\n```go\nfacades.Route().Get(\"/users/{id}\", func(ctx http.Context) http.Response {\n id := ctx.Request().Input(\"id\")\n return ctx.Response().Success().Json(http.Json{\"user_id\": id})\n})\n```\n\n## 控制器 (Controllers)\n\n随着应用变大我们不可能把所有逻辑都写在路由闭包里。这时候就需要控制器了。\n\n### 创建控制器\n\n使用 `knit` 工具可以快速生成控制器:\n\n```bash\nknit make:controller UserController\n```\n\n这会在 `app/http/controllers` 目录下生成 `user_controller.go`。让我们修改它来添加一个 `Show` 方法:\n\n```go\npackage controllers\n\nimport (\n \"github.com/goravel/framework/contracts/http\"\n)\n\ntype UserController struct {\n // 可以在这里注入服务\n}\n\nfunc NewUserController() *UserController {\n return &UserController{}\n}\n\nfunc (r *UserController) Show(ctx http.Context) http.Response {\n id := ctx.Request().Input(\"id\")\n // 模拟数据库查询\n return ctx.Response().Success().Json(http.Json{\n \"id\": id,\n \"name\": \"Goravel User\",\n })\n}\n```\n\n### 注册控制器路由\n\n回到 `routes/api.go`,我们需要先实例化控制器,然后绑定路由:\n\n```go\nimport \"my-goravel-app/app/http/controllers\"\n\nfunc Api() {\n userController := controllers.NewUserController()\n \n // 绑定到控制器方法\n facades.Route().Get(\"/users/{id}\", userController.Show)\n}\n```\n\n## 请求与响应\n\n在控制器方法中`ctx` (http.Context) 是核心:\n\n- **获取输入**: `ctx.Request().Input(\"key\")`\n- **获取 JSON**: `ctx.Request().Bind(&user)`\n- **返回 JSON**: `ctx.Response().Json(200, data)`\n- **设置状态码**: `ctx.Response().Status(404)`\n\n通过这种方式Goravel 让 HTTP 层的处理变得异常清晰和标准化。下一章,我们将学习如何通过 ORM 操作数据库。', 900, 1, '2026-01-15 16:32:12', '2026-01-16 11:12:49');
INSERT INTO `posts` VALUES (6, 'goravel-guide-3', 'Goravel 入门指南 (三)ORM 数据库操作', 'Go语言', '2026-01-15', '掌握 Goravel 强大的 ORM 功能从数据库配置、模型定义到执行增删改查CRUD操作。', '## Goravel ORM 简介\n\nGoravel 的 ORM 基于著名的 GORM 库构建,但它进行了一层优雅的封装,使其调用方式更接近 Laravel 的 Eloquent ORM。这意味着你可以使用 Facade 模式轻松调用数据库,且支持自动迁移。\n\n## 配置数据库\n\n打开 `config/database.go` 或 `.env` 文件,配置你的 MySQL 连接信息:\n\n```env\nDB_CONNECTION=mysql\nDB_HOST=127.0.0.1\nDB_PORT=3306\nDB_DATABASE=goravel\nDB_USERNAME=root\nDB_PASSWORD=password\n```\n\n## 定义模型\n\n使用 `knit` 生成模型:\n\n```bash\nknit make:model Post\n```\n\n生成的模型文件位于 `app/models/post.go`。我们需要定义结构体字段:\n\n```go\npackage models\n\nimport (\n \"github.com/goravel/framework/database/orm\"\n)\n\ntype Post struct {\n orm.Model\n Title string `gorm:\"size:255;not null\"`\n Content string `gorm:\"type:text\"`\n UserID uint\n}\n```\n\n## 数据库迁移\n\n虽然 GORM 支持 AutoMigrate但 Goravel 推荐使用迁移文件来管理数据库变更。\n\n```bash\nknit make:migration create_posts_table\n```\n\n编辑生成的迁移文件 (`database/migrations/xxxx_create_posts_table.go`),定义表结构,然后运行:\n\n```bash\nknit migrate\n```\n\n## CRUD 操作\n\n有了模型我们就可以愉快地操作数据库了。所有操作都通过 `facades.Orm()` 入口。\n\n### 创建 (Create)\n\n```go\npost := models.Post{\n Title: \"My First Post\",\n Content: \"Content goes here...\",\n}\nerr := facades.Orm().Query().Create(&post)\n```\n\n### 查询 (Read)\n\n```go\nvar post models.Post\n// 根据主键查询\nfacades.Orm().Query().Find(&post, 1)\n\n// 条件查询\nvar posts []models.Post\nfacades.Orm().Query().Where(\"title\", \"My First Post\").Get(&posts)\n```\n\n### 更新 (Update)\n\n```go\nvar post models.Post\nfacades.Orm().Query().Find(&post, 1)\n\npost.Title = \"Updated Title\"\nfacades.Orm().Query().Save(&post)\n```\n\n### 删除 (Delete)\n\n```go\nvar post models.Post\nfacades.Orm().Query().Delete(&post, 1)\n```\n\nGoravel 的 ORM 让 Go 语言的数据库操作不再繁琐,极大地提高了开发效率。配合之前的路由和控制器知识,你现在已经具备了开发完整 RESTful API 的能力!', 1561, 1, '2026-01-15 16:32:12', '2026-01-16 11:14:59');
-- ----------------------------
-- Table structure for role_permissions
@@ -588,7 +672,7 @@ CREATE TABLE `snippets` (
-- ----------------------------
-- Records of snippets
-- ----------------------------
INSERT INTO `snippets` VALUES ('1', 'React 鼠标追踪 Hook', 'import { useState, useEffect } from \'react\';\r\n\r\nexport const useMousePosition = () => {\r\n const [pos, setPos] = useState({ x: 0, y: 0 });\r\n useEffect(() => {\r\n const update = (e) => setPos({ x: e.clientX, y: e.clientY });\r\n window.addEventListener(\'mousemove\', update);\r\n return () => window.removeEventListener(\'mousemove\', update);\r\n }, []);\r\n return pos;\r\n};', 'mouse', '这是一个鼠标追踪', 0, '2026-01-14 08:32:19', '2026-01-14 08:32:19');
INSERT INTO `snippets` VALUES ('1', 'React 鼠标追踪 Hook', 'import { useState, useEffect } from \'react\';\r\n\r\nexport const useMousePosition = () => {\r\n const [pos, setPos] = useState({ x: 0, y: 0 });\r\n useEffect(() => {\r\n const update = (e) => setPos({ x: e.clientX, y: e.clientY });\r\n window.addEventListener(\'mousemove\', update);\r\n return () => window.removeEventListener(\'mousemove\', update);\r\n }, []);\r\n return pos;\r\n};', 'mouse', '这是一个鼠标追踪', 1, '2026-01-14 08:32:19', '2026-01-16 11:10:53');
-- ----------------------------
-- Table structure for tags
@@ -651,7 +735,7 @@ CREATE TABLE `user_access_logs` (
INDEX `idx_user_id`(`user_id` ASC) USING BTREE,
INDEX `idx_article_id`(`article_id` ASC) USING BTREE,
INDEX `idx_access_time`(`access_time` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户访问记录表' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户访问记录表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user_access_logs
@@ -661,6 +745,9 @@ INSERT INTO `user_access_logs` VALUES (2, 0, '::1', 'Unknown', 4, '2026-01-16 10
INSERT INTO `user_access_logs` VALUES (3, 0, '::1', 'Unknown', 5, '2026-01-16 10:13:24');
INSERT INTO `user_access_logs` VALUES (4, 0, '::1', 'Unknown', 4, '2026-01-16 10:13:34');
INSERT INTO `user_access_logs` VALUES (5, 0, '::1', 'Unknown', 5, '2026-01-16 10:13:35');
INSERT INTO `user_access_logs` VALUES (6, 0, '::1', 'Unknown', 4, '2026-01-16 11:08:41');
INSERT INTO `user_access_logs` VALUES (7, 0, '::1', 'Unknown', 5, '2026-01-16 11:12:49');
INSERT INTO `user_access_logs` VALUES (8, 0, '::1', 'Unknown', 6, '2026-01-16 11:14:59');
-- ----------------------------
-- Table structure for users
@@ -690,8 +777,8 @@ CREATE TABLE `users` (
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES (1, 'lq', 'liqiworker@gmail.com', '$2a$10$yl.1yCZ2PSTsW14byyDQ3uekuEiqnC4VBr/TzR6OvMqFVRuiiHu5e', 1, 'admin', 1, '2026-01-13 16:10:14', '2026-01-15 13:22:46');
INSERT INTO `users` VALUES (2, 'editor', 'editor@example.com', '$2a$10$J9q3NfJ2X8H7Q5z5Q7z5Q7z5Q7z5Q7z5Q7z5Q7z5Q7z5Q7z5Q', 2, 'editor', 1, '2026-01-13 16:10:14', '2026-01-15 15:28:49');
INSERT INTO `users` VALUES (5, 'cs', 'cs@nailaoyun.cn', '$2a$10$5hmE0v3NZRTRZddfIH4kpOT0XAuWtX8Zp86zBl0RcH6RkH6jP01ku', 3, 'viewer', 1, '2026-01-15 15:28:35', '2026-01-15 15:28:35');
INSERT INTO `users` VALUES (2, 'editor', 'editor@example.com', '$2a$10$yl.1yCZ2PSTsW14byyDQ3uekuEiqnC4VBr/TzR6OvMqFVRuiiHu5e', 2, 'editor', 1, '2026-01-13 16:10:14', '2026-01-16 11:14:14');
INSERT INTO `users` VALUES (5, 'cs', 'cs@nailaoyun.cn', '$2a$10$yl.1yCZ2PSTsW14byyDQ3uekuEiqnC4VBr/TzR6OvMqFVRuiiHu5e', 3, 'viewer', 1, '2026-01-15 15:28:35', '2026-01-16 11:14:17');
-- ----------------------------
-- Table structure for work_gallery