From 39bb93cc2fa7e1c5e78fbc2b9f05e7a51023b2cf Mon Sep 17 00:00:00 2001 From: ikmkj Date: Mon, 26 Jan 2026 21:42:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(models):=20=E6=B7=BB=E5=8A=A0=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E7=B1=BB=E6=96=87=E6=A1=A3=E6=B3=A8=E9=87=8A=E5=B9=B6?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0MarkdownFileVO=E6=89=A9=E5=B1=95=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为Grouping、Image、MarkdownFile、RegistrationCode、SystemSetting、User等模型类添加详细的PHP文档注释 - 为各个模型类添加公共属性定义,包括分组、图片、笔记、注册码、系统设置和用户相关字段 - 实现MarkdownFileVO视图对象类,扩展MarkdownFile模型以支持分组名称查询 - 在MarkdownController中使用MarkdownFileVO替代原模型获取包含分组名称的数据 - 添加TrashItemVo视图对象用于回收站项目的展示 - 添加UpdatePasswordBo业务对象用于密码更新请求处理 - 为RegistrationCode模型添加按ID和代码查询的方法及详细验证功能 - 为SystemSetting模型添加带描述的设置获取和设置方法 --- biji-php/src/BO/UpdatePasswordBo.php | 92 ++++++++++ .../src/Controllers/MarkdownController.php | 6 +- biji-php/src/Models/Grouping.php | 20 +++ biji-php/src/Models/Image.php | 24 +++ biji-php/src/Models/ImageCleanup.php | 4 + biji-php/src/Models/MarkdownFile.php | 30 ++++ biji-php/src/Models/MarkdownFileVO.php | 159 ++++++++++++++++++ biji-php/src/Models/RegistrationCode.php | 59 +++++++ biji-php/src/Models/SystemSetting.php | 30 ++++ biji-php/src/Models/Trash.php | 4 + biji-php/src/Models/TrashItemVo.php | 83 +++++++++ biji-php/src/Models/User.php | 24 +++ 12 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 biji-php/src/BO/UpdatePasswordBo.php create mode 100644 biji-php/src/Models/MarkdownFileVO.php create mode 100644 biji-php/src/Models/TrashItemVo.php diff --git a/biji-php/src/BO/UpdatePasswordBo.php b/biji-php/src/BO/UpdatePasswordBo.php new file mode 100644 index 0000000..f79b821 --- /dev/null +++ b/biji-php/src/BO/UpdatePasswordBo.php @@ -0,0 +1,92 @@ +oldPassword = $oldPassword; + $this->newPassword = $newPassword; + } + + /** + * 验证密码更新对象的有效性 + * @return array 返回验证结果 ['valid' => bool, 'errors' => array] + */ + public function validate() + { + $errors = []; + + if (empty($this->oldPassword)) { + $errors[] = '旧密码不能为空'; + } + + if (empty($this->newPassword)) { + $errors[] = '新密码不能为空'; + } + + if (!empty($this->oldPassword) && !empty($this->newPassword)) { + if ($this->oldPassword === $this->newPassword) { + $errors[] = '新密码不能与旧密码相同'; + } + + if (strlen($this->newPassword) < 6) { + $errors[] = '新密码长度不能少于6个字符'; + } + + if (strlen($this->newPassword) > 32) { + $errors[] = '新密码长度不能超过32个字符'; + } + } + + return [ + 'valid' => empty($errors), + 'errors' => $errors + ]; + } + + /** + * 将对象转换为数组 + * @return array + */ + public function toArray() + { + return [ + 'oldPassword' => $this->oldPassword, + 'newPassword' => $this->newPassword, + ]; + } + + /** + * 从数组创建对象 + * @param array $data + * @return UpdatePasswordBo + */ + public static function fromArray($data) + { + return new self( + $data['oldPassword'] ?? '', + $data['newPassword'] ?? '' + ); + } +} diff --git a/biji-php/src/Controllers/MarkdownController.php b/biji-php/src/Controllers/MarkdownController.php index 979b703..78f9762 100644 --- a/biji-php/src/Controllers/MarkdownController.php +++ b/biji-php/src/Controllers/MarkdownController.php @@ -5,6 +5,7 @@ namespace App\Controllers; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use App\Models\MarkdownFile; +use App\Models\MarkdownFileVO; use App\Utils\Response as ApiResponse; class MarkdownController @@ -98,8 +99,9 @@ class MarkdownController public function getRecent(Request $request, Response $response) { - $model = new MarkdownFile(); - $files = $model->getRecent(12); + // 使用 MarkdownFileVO 获取包含分组名称的数据 + $voModel = new MarkdownFileVO(); + $files = $voModel->getRecentWithGrouping(12); $response->getBody()->write(ApiResponse::json(ApiResponse::success($files))); return $response->withHeader('Content-Type', 'application/json; charset=utf-8'); diff --git a/biji-php/src/Models/Grouping.php b/biji-php/src/Models/Grouping.php index 80ab530..c4bebe1 100644 --- a/biji-php/src/Models/Grouping.php +++ b/biji-php/src/Models/Grouping.php @@ -5,10 +5,30 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * Grouping - 分组模型 + * + * 数据库表: grouping + * 主要字段: + * - id (Long) - 分组ID,雪花算法生成 + * - parentId (Long) - 上级分组ID(支持分组嵌套) + * - grouping (String) - 分组名称 + * - is_deleted (Integer) - 逻辑删除标志(0-未删除,1-已删除) + * - deleted_at (DateTime) - 删除时间 + * - deleted_by (Long) - 删除人ID + */ class Grouping { private $db; + // 分组属性 + public $id; + public $parentId; + public $grouping; + public $isDeleted; + public $deletedAt; + public $deletedBy; + public function __construct() { $this->db = Database::getInstance()->getConnection(); diff --git a/biji-php/src/Models/Image.php b/biji-php/src/Models/Image.php index ca7679f..5fb620c 100644 --- a/biji-php/src/Models/Image.php +++ b/biji-php/src/Models/Image.php @@ -5,10 +5,34 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * Image - 图片模型 + * + * 数据库表: image + * 主要字段: + * - id (Long) - 图片ID,自增主键 + * - markdown_id (Long) - 关联的Markdown文件ID + * - original_name (String) - 原始文件名 + * - stored_name (String) - 系统生成的唯一文件名 + * - url (String) - 图片访问URL + * - size (Long) - 图片大小(字节) + * - content_type (String) - MIME类型(如image/jpeg) + * - created_at (DateTime) - 上传时间 + */ class Image { private $db; + // 图片属性 + public $id; + public $markdownId; + public $originalName; + public $storedName; + public $url; + public $size; + public $contentType; + public $createdAt; + public function __construct() { $this->db = Database::getInstance()->getConnection(); diff --git a/biji-php/src/Models/ImageCleanup.php b/biji-php/src/Models/ImageCleanup.php index e232d61..a7a2873 100644 --- a/biji-php/src/Models/ImageCleanup.php +++ b/biji-php/src/Models/ImageCleanup.php @@ -4,6 +4,10 @@ namespace App\Models; use App\Utils\Database; +/** + * ImageCleanup - 图片清理模型 + * 用于清理冗余图片和维护数据库与文件系统的一致性 + */ class ImageCleanup { private $db; diff --git a/biji-php/src/Models/MarkdownFile.php b/biji-php/src/Models/MarkdownFile.php index 056b819..9b9e912 100644 --- a/biji-php/src/Models/MarkdownFile.php +++ b/biji-php/src/Models/MarkdownFile.php @@ -5,10 +5,40 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * MarkdownFile - 笔记文件模型 + * + * 数据库表: markdown_file + * 主要字段: + * - id (Long) - 笔记ID,自增主键 + * - grouping_id (Long) - 所属分组ID + * - title (String) - 笔记标题 + * - file_name (String) - 文件名(带.md后缀) + * - content (String) - Markdown内容 + * - created_at (DateTime) - 创建时间 + * - updated_at (DateTime) - 更新时间 + * - is_deleted (Integer) - 逻辑删除标志 + * - deleted_at (DateTime) - 删除时间 + * - deleted_by (Long) - 删除人ID + * - is_private (Integer) - 是否私密(0-公开,1-私密) + */ class MarkdownFile { private $db; + // 笔记属性 + public $id; + public $groupingId; + public $title; + public $fileName; + public $content; + public $createdAt; + public $updatedAt; + public $isDeleted; + public $deletedAt; + public $deletedBy; + public $isPrivate; + public function __construct() { $this->db = Database::getInstance()->getConnection(); diff --git a/biji-php/src/Models/MarkdownFileVO.php b/biji-php/src/Models/MarkdownFileVO.php new file mode 100644 index 0000000..80d877e --- /dev/null +++ b/biji-php/src/Models/MarkdownFileVO.php @@ -0,0 +1,159 @@ +db = Database::getInstance()->getConnection(); + } + + /** + * 获取笔记详情,包含分组名称 + * @param $id 笔记ID + * @param bool $includeDeleted 是否包含已删除的笔记 + * @return array|false + */ + public function findByIdWithGrouping($id, $includeDeleted = false) + { + $sql = "SELECT + mf.id, + mf.title, + mf.file_name as fileName, + mf.content, + mf.grouping_id as groupingId, + mf.created_at as createdAt, + mf.updated_at as updatedAt, + mf.is_deleted as isDeleted, + mf.deleted_at as deletedAt, + mf.deleted_by as deletedBy, + mf.is_private as isPrivate, + g.grouping as groupingName + FROM markdown_file mf + LEFT JOIN `grouping` g ON mf.grouping_id = g.id + WHERE mf.id = ?"; + + if (!$includeDeleted) { + $sql .= " AND mf.is_deleted = 0"; + } + + $stmt = $this->db->prepare($sql); + $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + /** + * 获取所有笔记,包含分组名称 + * @return array + */ + public function getAllWithGrouping() + { + $stmt = $this->db->prepare( + "SELECT + mf.id, + mf.title, + mf.file_name as fileName, + mf.created_at as createdAt, + mf.updated_at as updatedAt, + mf.is_private as isPrivate, + mf.grouping_id as groupingId, + g.grouping as groupingName + FROM markdown_file mf + LEFT JOIN `grouping` g ON mf.grouping_id = g.id + WHERE mf.is_deleted = 0 + ORDER BY mf.updated_at DESC" + ); + $stmt->execute(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * 按分组ID获取笔记,包含分组名称 + * @param $groupingId 分组ID + * @return array + */ + public function getByGroupingIdWithGrouping($groupingId) + { + $stmt = $this->db->prepare( + "SELECT + mf.id, + mf.title, + mf.file_name as fileName, + mf.created_at as createdAt, + mf.updated_at as updatedAt, + mf.is_private as isPrivate, + mf.grouping_id as groupingId, + g.grouping as groupingName + FROM markdown_file mf + LEFT JOIN `grouping` g ON mf.grouping_id = g.id + WHERE mf.grouping_id = ? AND mf.is_deleted = 0 + ORDER BY mf.updated_at DESC" + ); + $stmt->execute([$groupingId]); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * 搜索笔记,包含分组名称 + * @param $keyword 搜索关键词 + * @return array + */ + public function searchByTitleWithGrouping($keyword) + { + $stmt = $this->db->prepare( + "SELECT + mf.id, + mf.title, + mf.file_name as fileName, + mf.created_at as createdAt, + mf.updated_at as updatedAt, + mf.is_private as isPrivate, + mf.grouping_id as groupingId, + g.grouping as groupingName + FROM markdown_file mf + LEFT JOIN `grouping` g ON mf.grouping_id = g.id + WHERE mf.title LIKE ? AND mf.is_deleted = 0 + ORDER BY mf.updated_at DESC" + ); + $stmt->execute(['%' . $keyword . '%']); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * 获取最近的笔记,包含分组名称 + * @param int $limit 限制数量 + * @return array + */ + public function getRecentWithGrouping($limit = 12) + { + $stmt = $this->db->prepare( + "SELECT + mf.id, + mf.title, + mf.file_name as fileName, + mf.created_at as createdAt, + mf.updated_at as updatedAt, + mf.is_private as isPrivate, + mf.grouping_id as groupingId, + g.grouping as groupingName + FROM markdown_file mf + LEFT JOIN `grouping` g ON mf.grouping_id = g.id + WHERE mf.is_deleted = 0 + ORDER BY mf.updated_at DESC + LIMIT ?" + ); + $stmt->execute([$limit]); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/biji-php/src/Models/RegistrationCode.php b/biji-php/src/Models/RegistrationCode.php index 9b84ee1..ead3c86 100644 --- a/biji-php/src/Models/RegistrationCode.php +++ b/biji-php/src/Models/RegistrationCode.php @@ -5,10 +5,28 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * RegistrationCode - 注册码模型 + * + * 数据库表: registration_codes + * 主要字段: + * - id (Long) - 主键ID,自增 + * - code (String) - 注册码 + * - expiry_time (DateTime) - 过期时间 + * - created_by (String) - 创建者 + * - created_at (DateTime) - 创建时间 + */ class RegistrationCode { private $db; + // 注册码属性 + public $id; + public $code; + public $expiryTime; + public $createdBy; + public $createdAt; + public function __construct() { $this->db = Database::getInstance()->getConnection(); @@ -27,6 +45,38 @@ class RegistrationCode return $code; } + public function generateCodeWithId($createdBy) + { + $code = bin2hex(random_bytes(16)); + $expiryTime = date('Y-m-d H:i:s', strtotime('+7 days')); + + $stmt = $this->db->prepare( + "INSERT INTO registration_codes (code, expiry_time, created_by, created_at) VALUES (?, ?, ?, NOW())" + ); + $stmt->execute([$code, $expiryTime, $createdBy]); + + // 返回包含 id 的完整记录 + return $this->getCodeByCode($code); + } + + public function getCodeByCode($code) + { + $stmt = $this->db->prepare( + "SELECT id, code, expiry_time, created_by, created_at FROM registration_codes WHERE code = ?" + ); + $stmt->execute([$code]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function getCodeById($id) + { + $stmt = $this->db->prepare( + "SELECT id, code, expiry_time, created_by, created_at FROM registration_codes WHERE id = ?" + ); + $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + public function validateCode($code) { $stmt = $this->db->prepare( @@ -35,4 +85,13 @@ class RegistrationCode $stmt->execute([$code]); return $stmt->fetch() !== false; } + + public function validateCodeWithDetails($code) + { + $stmt = $this->db->prepare( + "SELECT id, code, expiry_time, created_by, created_at FROM registration_codes WHERE code = ? AND expiry_time > NOW()" + ); + $stmt->execute([$code]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } } diff --git a/biji-php/src/Models/SystemSetting.php b/biji-php/src/Models/SystemSetting.php index 137cd43..220dc92 100644 --- a/biji-php/src/Models/SystemSetting.php +++ b/biji-php/src/Models/SystemSetting.php @@ -5,10 +5,24 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * SystemSetting - 系统设置模型 + * + * 数据库表: system_settings + * 主要字段: + * - setting_key (String) - 设置键(主键) + * - setting_value (String) - 设置值 + * - description (String) - 设置描述 + */ class SystemSetting { private $db; + // 系统设置属性 + public $settingKey; + public $settingValue; + public $description; + public function __construct() { $this->db = Database::getInstance()->getConnection(); @@ -31,6 +45,22 @@ class SystemSetting return $stmt->execute([$key, $value, $value]); } + public function getSettingWithDescription($key) + { + $stmt = $this->db->prepare("SELECT setting_value, description FROM system_settings WHERE setting_key = ?"); + $stmt->execute([$key]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function setSettingWithDescription($key, $value, $description = null) + { + $stmt = $this->db->prepare( + "INSERT INTO system_settings (setting_key, setting_value, description) VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE setting_value = ?, description = ?" + ); + return $stmt->execute([$key, $value, $description, $value, $description]); + } + public function isRegistrationEnabled() { $value = $this->getSetting('registration_enabled'); diff --git a/biji-php/src/Models/Trash.php b/biji-php/src/Models/Trash.php index 6520a38..a027ed9 100644 --- a/biji-php/src/Models/Trash.php +++ b/biji-php/src/Models/Trash.php @@ -4,6 +4,10 @@ namespace App\Models; use App\Utils\Database; +/** + * Trash - 回收站模型 + * 用于管理已删除的笔记和分组 + */ class Trash { private $db; diff --git a/biji-php/src/Models/TrashItemVo.php b/biji-php/src/Models/TrashItemVo.php new file mode 100644 index 0000000..bab1943 --- /dev/null +++ b/biji-php/src/Models/TrashItemVo.php @@ -0,0 +1,83 @@ +id = $id; + $this->title = $title; + $this->type = $type; + $this->deletedAt = $deletedAt; + $this->deletedBy = $deletedBy; + } + + /** + * 将对象转换为数组 + * @return array + */ + public function toArray() + { + return [ + 'id' => $this->id, + 'title' => $this->title, + 'type' => $this->type, + 'deletedAt' => $this->deletedAt, + 'deletedBy' => $this->deletedBy, + ]; + } + + /** + * 从数组创建对象 + * @param array $data + * @return TrashItemVo + */ + public static function fromArray($data) + { + return new self( + $data['id'] ?? '', + $data['title'] ?? '', + $data['type'] ?? '', + $data['deletedAt'] ?? '', + $data['deletedBy'] ?? '' + ); + } +} diff --git a/biji-php/src/Models/User.php b/biji-php/src/Models/User.php index 82e9834..71dc054 100644 --- a/biji-php/src/Models/User.php +++ b/biji-php/src/Models/User.php @@ -5,10 +5,34 @@ namespace App\Models; use App\Utils\Database; use PDO; +/** + * User - 用户模型 + * + * 数据库表: user + * 主要字段: + * - id (Long) - 用户ID,自增主键 + * - username (String) - 用户名 + * - password (String) - 密码(加密存储) + * - email (String) - 邮箱 + * - created_at (DateTime) - 创建时间 + * - updated_at (DateTime) - 更新时间 + * - token (String) - 用户token + * - token_enddata (DateTime) - token过期时间 + */ class User { private $db; + // 用户属性 + public $id; + public $username; + public $password; + public $email; + public $createdAt; + public $updatedAt; + public $token; + public $tokenEnddata; + public function __construct() { $this->db = Database::getInstance()->getConnection();