From d92eebf2f60c2dc15eeccb6a67d1a9dcc12e589f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=9A=E9=A3=9E=E7=9A=84=E9=B1=BC?= <3057433102@qq.com> Date: Wed, 13 May 2026 15:55:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 239 ++++++------------ doc/software_requirements_model.md | 73 +++++- model/uml_diagrams.md | 170 ++++++++++--- .../src/context/AuthContext.jsx | 10 +- .../src/pages/MobileEditProfilePage.jsx | 11 +- .../src/main/resources/application.yml | 9 +- 6 files changed, 290 insertions(+), 222 deletions(-) diff --git a/README.md b/README.md index 91ea78f..af04e14 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
-![React](https://img.shields.io/badge/React-19.2-61DAFB) ![Vite](https://img.shields.io/badge/Vite-8.0-646CFF) ![Ant Design](https://img.shields.io/badge/Ant_Design-6.3-1677FF) ![React Router](https://img.shields.io/badge/React_Router-7.14-CA4245) ![Spring Boot](https://img.shields.io/badge/Spring_Boot-2.7.6-6DB33F) ![Java](https://img.shields.io/badge/Java-11-007396) ![MySQL](https://img.shields.io/badge/MySQL-8-4479A1) ![Redis](https://img.shields.io/badge/Redis-5.0-DC382D) ![MyBatis Plus](https://img.shields.io/badge/MyBatis_Plus-3.5.15-C6534B) ![Hutool](https://img.shields.io/badge/Hutool-5.8.38-E44D26) ![腾讯云 COS](https://img.shields.io/badge/腾讯云_COS-5.6.227-0052D9) ![Knife4j](https://img.shields.io/badge/Knife4j-4.4.0-009688) +![React](https://img.shields.io/badge/React-19.2-61DAFB) ![Vite](https://img.shields.io/badge/Vite-8.0-646CFF) ![Ant Design](https://img.shields.io/badge/Ant_Design-6.3-1677FF) ![React Router](https://img.shields.io/badge/React_Router-7.14-CA4245) ![Spring Boot](https://img.shields.io/badge/Spring_Boot-3.2.5-6DB33F) ![Java](https://img.shields.io/badge/Java-21-007396) ![MySQL](https://img.shields.io/badge/MySQL-8-4479A1) ![Redis](https://img.shields.io/badge/Redis-5.0-DC382D) ![MyBatis Plus](https://img.shields.io/badge/MyBatis_Plus-3.5.14-C6534B) ![Hutool](https://img.shields.io/badge/Hutool-5.8.38-E44D26) ![腾讯云 COS](https://img.shields.io/badge/腾讯云_COS-5.6.227-0052D9) ![Knife4j](https://img.shields.io/badge/Knife4j-4.4.0-009688) [GitHub](https://github.com/FishDuM/AI.Image.Material.Collaboration.Platform) | [Gitee](https://gitee.com/dumhfdy/AI.Image.Material.Collaboration.Platform) | [头歌](https://code.educoder.net/pfqxsyecz/AI.Image.Material.Collaboration.Platform) @@ -10,24 +10,28 @@ **FishPics** 是一个基于 React 19 + Spring Boot 的图片分享与互动社区平台,采用前后端分离架构,提供图片管理、社区互动、团队协作、AI 素材管理等核心功能。平台支持用户注册登录、图片浏览管理、帖子发布与编辑、评论互动、分类标签浏览、团队空间协作、后台审核管理等能力,社区广场采用瀑布流布局与小红书风格的帖子详情弹窗,致力于打造简洁高效、安全可靠的图片内容生态。 ---- +*** ## 项目特色 - 美观流畅的前端界面,支持 PC / 移动端自适应 +- 完整的移动端适配:独立登录/注册页、帖子创建/详情页、个人资料编辑、底部Tab导航栏 - 完整的图片生态:上传、查看、收藏、评论、点赞、关注 - 安全可靠的用户体系:登录注册、权限控制、图形验证码防护 -- 高性能架构:Session + Redis 会话管理、用户信息缓存、系统配置缓存、MyBatis-Plus 分页查询 +- 高性能架构:Session + Redis 会话管理、用户信息缓存、系统配置缓存、MyBatis-Plus 分页查询、请求去重 - 明暗主题切换,个性化用户体验 - 多空间管理:个人空间、团队空间、社区广场、图片关联空间 - 社区广场:瀑布流布局、分类标签筛选、帖子发布与编辑、小红书风格详情弹窗、图片轮播、滚动隐藏导航栏 -- 图片管理:图片上传审核、管理员批量审核、公开图片列表、图片关联空间 +- 图片管理:分级上传限制、图片上传审核、管理员批量审核、公开图片列表、图片关联空间 - 系统管理:分类标签管理(Redis 缓存)、跑马灯图片管理(Redis 缓存) - 管理员后台:用户管理、图片管理、系统管理、空间管理、团队管理、AI 管理、权限控制 +- VIP/SVIP 会员体系:分级存储配额、升级方案展示、增量包购买 - 腾讯云 COS 对象存储服务,支持海量图片存储 -- Redisson 分布式锁,支持并发安全操作 +- Redisson 分布式锁,点赞操作并发安全 +- 共享组件库:LoginModal、RegisterModal、StorageCard、UpgradePanel 等可复用组件 +- 自定义 Hooks:useIsMobile(移动端检测)、useAuthModal(认证弹窗管理) ---- +*** ## 技术栈 @@ -37,26 +41,28 @@ - **React Router v7** 路由管理与路由守卫 - **Context API** 状态管理 (AuthContext、ThemeContext) - **dayjs** 日期处理 -- **Axios** 请求封装(拦截器、统一错误处理) -- 响应式布局 / 美观 UI +- **Axios** 请求封装(拦截器、统一错误处理、请求去重机制) +- 响应式布局 / 美观 UI / 移动端适配 +- 自定义 Hooks (useIsMobile、useAuthModal) +- 共享组件库 (LoginModal、RegisterModal、StorageCard、UpgradePanel 等) - ESLint 代码规范检查 ### 后端 (FishPics-backend) -- **Spring Boot 2.7.6** -- **Java 11** +- **Spring Boot 3.2.5** +- **Java 21** - **Spring Session + Redis** 会话管理(Session 存储 userId,Redis 缓存 User 信息) -- **Redisson** 分布式锁 -- **MyBatis-Plus 3.5.15** ORM框架 + 分页插件 +- **Redisson 3.27.0** 分布式锁 +- **MyBatis-Plus 3.5.14** ORM框架 + 分页插件(mybatis-plus-spring-boot3-starter) - **MySQL 8+** 关系型数据库 - **Redis** 验证码存储、会话管理、用户信息缓存、系统配置缓存 -- **Knife4j 4.4.0** API文档生成 +- **Knife4j 4.4.0** API文档生成(OpenAPI3 Jakarta 版) - **Hutool 5.8.38** 工具库 - **Lombok** 简化代码 - **AOP** 注解式权限拦截 (AuthCheck) - **腾讯云 COS 5.6.227** 对象存储服务 ---- +*** ## 效果预览 @@ -67,7 +73,7 @@ - **API 文档**:Knife4j 自动生成的接口文档 ![API 文档](doc/picture/p3.gif) ---- +*** ## 核心功能 @@ -90,6 +96,10 @@ - 公开图片列表,支持分页获取已审核通过的图片 - 图片关联空间,支持将图片归入指定空间管理 - 图片简介,支持为图片添加文字描述 +- 图片信息编辑,支持修改图片名称和介绍 +- 分级上传限制,根据用户等级限制文件大小(普通3MB/VIP 5MB/SVIP 20MB) +- 空间存储检查,上传前检查私人空间是否充足 +- 管理员上传自动通过审核 ### 帖子管理模块 @@ -101,10 +111,13 @@ - 帖子状态管控,支持正常、禁用、待审核、逻辑删除 - 隐私控制:公开、仅自己可见 - 统计数据:点赞数、收藏数、评论数、查看数、热度值 +- 热度排序公式:likes \* 0.3 + collects \* 0.3 + comments \* 0.2 + clicks \* 0.2 - 我的帖子列表,分页获取当前用户发布的帖子 - 我的收藏列表,分页获取当前用户收藏的帖子 - 我的点赞列表,分页获取当前用户点赞的帖子 -- 图片上传支持最多 15 张,格式校验(JPEG、PNG、GIF、WebP、HEIC),单张不超过 5MB +- 图片上传支持最多 15 张,格式校验(JPEG、PNG、GIF、WebP、HEIC),单张大小限制 5MB +- 子图片关联表(picture\_child),支持图片排序 +- 帖子图片列表同步过滤,getPost时pictureUrl与pictureIds同步过滤已删除图片 ### 评论互动模块 @@ -128,18 +141,22 @@ - 个人空间,管理个人图片与帖子内容 - 团队空间,支持团队协作与共享素材 +- 团队空间详情页,支持空间信息查看/编辑、图片瀑布流浏览/搜索/批量操作/编辑 - 社区广场,瀑布流展示所有公开帖子,支持分类标签筛选、发帖、编辑、帖子详情浏览、返回顶部(向下滚动100px后显示,平滑滚动) -- 空间创建,支持管理员创建私有空间(默认 512MB)和团队空间(默认 5GB) +- 空间创建,私人空间每人限1个(普通512MB/VIP 5GB/SVIP 10GB),团队空间按等级限制数量(普通1个/VIP 5个/SVIP 10个) - 空间配置,支持空间名称、介绍、类型、级别、存储大小管理 +- 空间详情查询,支持创建者或团队成员访问 - 空间图片列表,分页查看指定空间内的图片 - 跑马灯展示,首页轮播展示跑马灯图片 - 消息通知,支持评论互动、赞和收藏、新增关注、系统通知、私信五个分类 +- VIP/SVIP会员体系,升级面板展示升级方案和增量包购买选项 +- 存储空间卡片,圆形进度条展示使用率(超过90%红色警示) ### 系统管理模块 - 分类标签管理,支持添加、删除图片分类标签(Redis 缓存加速) - 跑马灯图片管理,支持添加、删除跑马灯图片(Redis 缓存加速) -- 系统配置存储在 pic_system 表,键值对格式,支持 JSON 数组 +- 系统配置存储在 pic\_system 表,键值对格式,支持 JSON 数组 - 配置优先从 Redis 读取,未命中时查数据库并回写缓存 ### 后台管理模块 @@ -152,7 +169,7 @@ - AI 素材管理,后台管理 AI 相关素材(开发中) - 权限控制,基于 AOP 注解实现管理员权限拦截 ---- +*** ## 数据库设计 @@ -162,11 +179,12 @@ - **picture**: 图片表,记录图片信息和关联用户与空间(名称、URL、宽高、大小、状态、公开性、帖子关联、空间关联、图片简介) - **post**: 帖子表,管理帖子内容、统计数据、隐私设置和热度值(标题、内容、状态、点赞/收藏/评论/查看数、封面、热度值) - **comment**: 评论表,记录用户评论和回复关系(内容、父评论、回复目标用户、状态) +- **picture\_child**: 子图片关联表,记录帖子与图片的关联关系和排序(图片ID、帖子ID、排序序号) - **space**: 空间表,管理私有空间和团队空间(名称、介绍、类型、级别、存储大小、已用大小、团队成员) -- **pic_system**: 系统配置表,存储分类标签和跑马灯图片等系统配置(键值对格式,JSON 存储) -- **user_post_collect**: 用户帖子收藏表 -- **user_post_likes**: 用户帖子点赞表 -- **user_fans**: 用户粉丝关系表 +- **pic\_system**: 系统配置表,存储分类标签和跑马灯图片等系统配置(键值对格式,JSON 存储) +- **user\_post\_collect**: 用户帖子收藏表 +- **user\_post\_likes**: 用户帖子点赞表 +- **user\_fans**: 用户粉丝关系表 ### 索引优化 @@ -178,7 +196,7 @@ - 系统配置表:syskey 唯一索引 - 粉丝表:用户 ID 和粉丝 ID 联合索引 ---- +*** ## 项目结构 @@ -186,13 +204,25 @@ ``` src/ -├── api/ # API 请求封装 +├── api/ # API 请求封装(含请求去重机制) ├── assets/ # 前端静态资源 -├── components/ # 公共组件 (ErrorBoundary, FunnyBackground, GlobalLayout, ProtectedRoute, PostDetailModal, CreateEditPostModal) +├── components/ # 公共组件 +│ ├── shared/ # 共享组件 (LoginModal, RegisterModal, SettingsModal, FloatingActions, BulkActionBar, +│ │ # StorageCard, UpgradePanel, SpacePickerModal, ImageEditModal, PageHeader, EmptyState, +│ │ # SearchBar, ProfileHeader, PostCard, MobileBottomNav) +│ ├── ErrorBoundary, FunnyBackground, GlobalLayout, MobilePageWrapper, +│ │ ProtectedRoute, PostDetailModal, CreateEditPostModal ├── context/ # 状态管理 (AuthContext, ThemeContext) -├── pages/ # 页面组件 (HomePage, UserProfile, CommunitySquare, PrivateSpace, TeamSpace, Notifications, AdminUserList, AdminPictureManagement, SystemManagement, UserManagement, NotFound 等) +├── hooks/ # 自定义 Hooks (useIsMobile, useAuthModal) +├── pages/ # 页面组件 +│ ├── 桌面端页面: HomePage, UserProfile, CommunitySquare, PrivateSpace, TeamSpace, +│ │ TeamSpaceDetail, Notifications, AdminUserList, AdminPictureManagement, +│ │ SystemManagement, UserManagement, NotFound 等 +│ └── 移动端页面: MobileLoginPage, MobileRegisterPage, MobilePostCreatePage, +│ MobilePostDetailPage, MobileEditProfilePage, MobileEditPicturePage +├── styles/ # 全局样式 (animations.css, carousel.css, shared.css) ├── utils/ # 工具函数 (storage.js) -├── App.jsx # 路由配置 +├── App.jsx # 路由配置(含移动端独立路由) └── main.jsx # 应用入口 ``` @@ -228,13 +258,13 @@ hk.ljx.fishpicsbackend/ └── user/ # 验证码、登录、用户信息视图对象 ``` ---- +*** ## 快速启动 ### 环境要求 -- Java 11+ +- Java 21+ - Maven 3.6+ - MySQL 8+ - Redis 5.0+ @@ -263,152 +293,30 @@ npm run dev - 后端 API:`http://localhost:8080/api` - API 文档:`http://localhost:8080/api/doc.html` ---- +*** ## 技术亮点 - **前后端分离架构**,职责清晰,易于维护 -- **Session + Redis 认证**,Session 存储 userId,Redis 缓存 User JSON,仅需一次 Redis 查询获取用户,支持分布式部署 -- **LoginUser 工具类**,统一封装从 Session 获取 userId、从 Redis 获取 User 对象的逻辑 -- **图形验证码机制**,防止机器暴力破解 -- **Redis 存储验证码**,验证码过期自动清理 -- **Redis 系统配置缓存**,分类标签和跑马灯图片缓存在 Redis,减少数据库查询 +- **Session + Redis 认证**,Session 存储 userId,Redis 缓存 User JSON,支持分布式部署 - **AOP 注解式权限拦截**,基于 @AuthCheck 注解的细粒度权限控制 -- **统一异常处理**,全局错误捕获和响应 (GlobalExceptionHandler) -- **统一响应格式**,规范的 API 返回 (Response\) +- **统一响应格式**,规范的 API 返回 (Response\),全局异常处理 - **分页查询优化**,MyBatis-Plus 分页插件,大数据量处理高效 - **腾讯云 COS 对象存储**,海量图片存储 - **DTO/VO 分层设计**,数据传输与视图分离 - **隐私控制机制**,用户可自定义个人数据可见性 -- **二级评论系统**,支持回复指定用户 -- **帖子统计功能**,点赞数、收藏数、评论数、查看数、热度值实时统计 - **图片审核机制**,上传后默认待审核,管理员可批量审核通过/拒绝/标记精选 - **瀑布流布局**,Ant Design Masonry 组件实现响应式多列卡片展示 - **小红书风格弹窗**,左右分栏帖子详情/发帖弹窗,支持图片轮播与触摸滑动 -- **滚动隐藏导航栏**,向下滚动自动隐藏顶部导航栏,向上滚动恢复显示 -- **返回顶部按钮**,向下滚动100px后显示,点击平滑滚动回顶部 -- **帖子图片列表同步过滤**,getPost时pictureUrl与pictureIds同步过滤已删除图片,保证两个列表一一对应 -- **分类标签栏**,动态获取标签列表,sticky 固定在搜索栏下方 -- **跑马灯轮播**,首页跑马灯图片轮播展示 - **明暗主题切换**,ThemeContext 状态管理,支持深色/浅色模式 -- **错误边界组件**,前端异常优雅降级 -- **路由保护组件**,基于角色的路由守卫 (ProtectedRoute) -- **Context API 状态管理**,AuthContext + ThemeContext 轻量级状态管理 -- **Redisson 分布式锁**,支持并发安全操作 - ---- - -## 数据库设计详情 - -### 用户表 (user) - -| 字段 | 类型 | 说明 | -| ----------------------- | --------------- | ---------------------------------- | -| id | bigint unsigned | 主键,自增 | -| username | varchar(32) | 用户名(唯一) | -| password | varchar(128) | 密码 | -| avatar | varchar(256) | 头像 URL | -| email | varchar(64) | 邮箱 | -| phone | varchar(16) | 手机号 | -| nickname | varchar(32) | 昵称(唯一) | -| status | tinyint | 状态:1-正常,0-禁用,2-待审核 | -| is_delete | tinyint | 逻辑删除:0-未删除,1-已删除 | -| role | varchar(32) | 用户权限角色 | -| like_num | bigint | 收到的点赞数 | -| collect_num | bigint | 收藏数 | -| is_private_follows | tinyint | 关注列表隐私:0-公开,1-不公开 | -| is_private_post_collect | tinyint | 收藏帖子列表隐私:0-公开,1-不公开 | -| is_private_likes | tinyint | 点赞帖子列表隐私:0-公开,1-不公开 | -| is_private_fans | tinyint | 粉丝列表隐私:0-公开,1-不公开 | -| level | tinyint | 用户级别:0-普通,1-VIP,2-SVIP | -| size | bigint | 已用存储大小(字节) | -| create_time | datetime | 创建时间 | -| update_time | datetime | 更新时间 | - -### 图片表 (picture) - -| 字段 | 类型 | 说明 | -| ------------ | ------------ | -------------------------------------- | -| id | bigint | 主键,自增 | -| user_id | bigint | 用户 ID | -| picture_name | bigint | 图片名称 | -| url | varchar(512) | 图片地址 | -| width | varchar(32) | 宽度 | -| height | varchar(32) | 高度 | -| size | bigint | 文件大小(字节) | -| status | tinyint | 状态:1-正常,0-禁用,2-待审核(默认) | -| is_private | tinyint | 公开性:0-不公开到首页,1-公开到首页 | -| post_id | bigint | 关联帖子 ID | -| space_id | bigint | 关联空间 ID | -| introduction | varchar(256) | 图片简介 | -| create_time | datetime | 创建时间 | -| update_time | datetime | 更新时间 | - -### 帖子表 (post) - -| 字段 | 类型 | 说明 | -| ------------ | ------------ | ------------------------------ | -| id | bigint | 主键,自增 | -| user_id | bigint | 发帖用户 ID | -| title | varchar(256) | 标题 | -| content | text | 内容 | -| status | tinyint | 状态:1-正常,0-禁用,2-待审核 | -| is_delete | int | 逻辑删除:0-未删除,1-已删除 | -| likes_num | bigint | 点赞数 | -| collects_num | bigint | 收藏数 | -| comment_num | int | 评论数 | -| views_num | bigint | 查看数 | -| is_private | tinyint | 隐私:0-公开,1-仅自己可见 | -| cover | bigint | 封面图片 ID | -| hot | decimal | 热度值 | -| create_time | datetime | 创建时间 | -| update_time | datetime | 更新时间 | - -### 评论表 (comment) - -| 字段 | 类型 | 说明 | -| ----------- | -------- | -------------------------------- | -| id | bigint | 主键,自增 | -| user_id | bigint | 评论用户 ID | -| post_id | bigint | 帖子 ID | -| content | text | 评论内容 | -| parent_id | bigint | 父评论 ID(支持二级评论 / 回复) | -| to_user_id | int | 回复目标用户 ID | -| status | tinyint | 状态:1-正常,0-禁用,2-待审核 | -| create_time | datetime | 创建时间 | - -### 子图片表 (picture_child) - -| 字段 | 类型 | 说明 | -| ---------- | ------- | ------------------ | -| id | bigint | 主键,自增 | -| picture_id | bigint | 关联图片 ID | -| post_id | bigint | 关联帖子 ID | -| sort_num | int | 在帖子中的排序序号 | - -### 空间表 (space) - -| 字段 | 类型 | 说明 | -| ------------- | ------------- | -------------------------------- | -| id | bigint | 主键,自增 | -| user_id | bigint | 创建者 ID | -| name | varchar(246) | 空间名称 | -| introduction | varchar(256) | 空间介绍 | -| type | tinyint | 空间类型:0-私有空间,1-团队空间 | -| level | tinyint | 空间级别:0-普通,1-VIP,2-SVIP | -| storage_size | bigint | 空间存储大小(KB) | -| size | bigint | 已用空间大小 | -| team_users_id | varchar(1024) | 团队空间成员 ID 列表(JSON) | - -### 系统配置表 (pic_system) - -| 字段 | 类型 | 说明 | -| -------- | ------------- | --------------------------------------------- | -| id | bigint | 主键,自增 | -| syskey | varchar(256) | 配置键(唯一,如 SYS_PIC_TYPE、SYS_MARQUEES) | -| sysvalue | varchar(1024) | 配置值(JSON 格式存储) | - ---- +- **Redisson 分布式锁**,点赞操作使用分布式锁防止并发冲突 +- **移动端适配**,useIsMobile Hook + MobilePageWrapper + MobileBottomNav 完整移动端体验 +- **请求去重机制**,Axios 拦截器实现自动请求去重,通过 AbortController 防止重复请求 +- **分级上传限制**,根据用户等级(普通/VIP/SVIP)动态调整文件大小限制 +- **团队空间详情管理**,支持空间信息编辑、图片瀑布流浏览、批量操作、图片编辑 +- **VIP/SVIP 会员体系**,存储空间分级配额、团队空间数量限制、升级方案展示 + +*** ## 安全设计 @@ -424,7 +332,7 @@ npm run dev - **文件上传限制**:受限输入流(LimitedInputStream)限制文件大小 - **Redisson 分布式锁**:防止并发操作冲突 ---- +*** ## 开发规范 @@ -438,4 +346,5 @@ npm run dev - 认证:LoginUser 工具类统一封装 Session + Redis 获取用户逻辑 - 缓存:系统配置优先从 Redis 读取,未命中时查数据库并回写缓存 ---- +*** + diff --git a/doc/software_requirements_model.md b/doc/software_requirements_model.md index 6ac22de..daf27b1 100644 --- a/doc/software_requirements_model.md +++ b/doc/software_requirements_model.md @@ -14,7 +14,7 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 ### 1.2 技术栈 - **前端**: React 19 + Vite 8 + Ant Design 6 + React Router v7 + Context API + Axios + dayjs -- **后端**: Spring Boot 2.7.6 + MyBatis-Plus 3.5.15 + MySQL 8 + Redis + Redisson + Knife4j + Hutool + Lombok + 腾讯云 COS +- **后端**: Spring Boot 3.2.5 + MyBatis-Plus 3.5.14 + MySQL 8 + Redis + Redisson 3.27.0 + Knife4j 4.4.0 + Hutool 5.8.38 + Lombok + 腾讯云 COS - **认证**: HTTP Session + Cookie(Spring Session + Redis机制,依赖CORS allowCredentials) - **密码安全**: MD5 + 盐值"fish" @@ -37,10 +37,11 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 #### 2.1.1 用户认证模块 -- **用户注册** +- **注册** - 输入:用户名(6-11字符)、密码(8-20字符)、确认密码、图形验证码 - 校验:用户名唯一性、密码一致性、验证码正确性 - 默认值:昵称"小鱼籽\_+随机字符串"、角色"user" + - 注册成功后自动创建默认私人空间(512MB) - **用户登录** - 输入:用户名、密码、图形验证码 - 流程:验证码校验 → 用户查询 → 密码比对(MD5+Salt) → 将用户ID存入HTTP Session → 将用户信息缓存到Redis → 返回用户信息 @@ -81,9 +82,11 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - 功能:用户头像上传,文件大小限制5MB - 参数:file(图片文件)、id(用户ID) - **帖子图片上传** - - 接口:POST /api/picture/post - - 功能:帖子相关图片上传,文件大小限制5MB + - 接口:POST /api/picture/upload + - 功能:帖子相关图片上传,根据用户等级限制文件大小(普通3MB/VIP 5MB/SVIP 20MB) - 参数:file(图片文件) + - 检查私人空间存储是否充足,空间不足时删除已上传文件并提示 + - 管理员上传的图片自动通过审核(status=1),普通用户需审核(status=2) - 返回:PicturePostVO(图片URL、ID等信息) - **图片信息管理** - 图片名称、URL、尺寸(宽、高)、大小 @@ -139,6 +142,8 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - 接口:POST /api/post/myCollects(获取本人收藏的帖子列表) - **点赞功能** - 点赞帖子(user_post_likes表:userId、postId) + - 使用Redisson分布式锁(10秒超时)防止并发点赞 + - 乐观更新点赞数(likes_num +1/-1) - 点赞列表管理 - 接口:POST /api/post/like?id={id} - 接口:POST /api/post/myLikes(获取本人点赞的帖子列表) @@ -187,24 +192,36 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - **空间列表查询** - 接口:GET /api/space/list?type={type} - 功能:按类型获取用户的空间列表(0-私人空间,1-团队空间) + - 批量查询图片数量、创建人信息、团队成员信息(团队空间最多显示10个成员) +- **空间详情查询** + - 接口:GET /api/space/getSpace?id={id} + - 功能:获取单个空间详情 + - 权限校验:仅创建者或团队成员可访问 - **空间信息更新** - 接口:POST /api/space/update - 功能:更新空间名称和介绍 - 参数:id(空间ID)、name、introduction + - 权限校验:仅创建者或管理员可操作 - **空间图片列表** - 接口:POST /api/space/pictureList - 功能:获取指定空间下的图片列表(分页) - 参数:spaceId(空间ID)、current、pageSize + - 权限校验:仅创建者或团队成员可访问 #### 2.1.11 图片管理扩展模块 - **图片列表查询(公开)** - 接口:GET /api/picture/list?current={current}&pageSize={pageSize} - 功能:分页获取公开图片列表 +- **图片信息更新** + - 接口:PUT /api/picture/update + - 功能:更新图片名称和介绍 + - 参数:id(图片ID)、pictureName、introduction - **图片删除** - 接口:POST /api/picture/delete - - 功能:删除图片(支持批量删除) - - 参数:ids(图片ID列表) + - 功能:删除图片(支持批量删除),帖子封面图禁止删除 + - 权限校验:图片主人或管理员可操作 + - 参数:idList(图片ID列表) - **管理员图片管理** - 获取图片列表:GET /api/picture/admin/list?current={current}&pageSize={pageSize}&status={status} - 审核图片:POST /api/picture/admin/review?pictureId={pictureId}&status={status}&selected={selected} @@ -221,6 +238,13 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - **本人点赞列表** - 接口:POST /api/post/myLikes - 功能:获取当前登录用户点赞的帖子列表(分页) +- **编辑帖子时获取图片列表** + - 接口:POST /api/post/pictureList + - 功能:编辑帖子时获取空间内可选图片列表,标记已选图片的flag状态 + - 参数:spaceId、current、pageSize +- **帖子热度排序** + - 热度公式:likes * 0.3 + collects * 0.3 + comments * 0.2 + clicks * 0.2 + - 社区广场支持按热度优先排序(hotPost=true) #### 2.1.13 前端页面模块 @@ -228,6 +252,7 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - **社区广场**(CommunitySquare):社区内容展示,瀑布流布局,支持分类标签筛选、搜索、发帖、编辑、帖子详情弹窗、返回顶部按钮(向下滚动100px后显示,平滑滚动) - **私人空间**(PrivateSpace):用户个人私密内容管理 - **团队空间**(TeamSpace):团队协作内容管理 +- **团队空间详情**(TeamSpaceDetail):查看和管理团队空间,包含空间信息展示和图片瀑布流管理,支持图片搜索、批量操作、图片编辑 - **通知中心**(Notifications):用户通知消息(评论互动、赞和收藏、新增关注、系统通知、私信五个分类) - **用户资料**(UserProfile):个人资料查看与编辑 - **用户管理**(UserManagement):管理员查看和编辑用户信息 @@ -237,6 +262,12 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - **空间管理**(SpaceManagement):空间配置管理(开发中) - **AI管理**(AIManagement):AI相关功能管理(开发中) - **系统管理**(SystemManagement):帖子分类标签管理、首页跑马灯图片管理 +- **移动端登录页**(MobileLoginPage):独立的移动端登录页面,支持验证码 +- **移动端注册页**(MobileRegisterPage):独立的移动端注册页面,含确认密码 +- **移动端帖子创建页**(MobilePostCreatePage):移动端发帖页面,复用CreateEditPostModal +- **移动端帖子详情页**(MobilePostDetailPage):移动端帖子详情查看与编辑 +- **移动端编辑资料页**(MobileEditProfilePage):移动端个人资料编辑,支持头像上传 +- **移动端图片编辑页**(MobileEditPicturePage):移动端图片信息编辑 - **404页面**(NotFound):未找到页面 #### 2.1.14 前端通用组件 @@ -245,13 +276,34 @@ FishPics(FishPics Image Collaboration Platform)是一个基于前后端分 - **ProtectedRoute**:路由权限保护(支持requireAdmin属性) - **ErrorBoundary**:错误边界处理 - **FunnyBackground**:趣味背景动画(浮动emoji) -- **PostDetailModal**:帖子详情弹窗(小红书风格,左右分栏,左侧图片轮播,右侧内容与互动数据) -- **CreateEditPostModal**:帖子发布/编辑弹窗(左右分栏布局,支持多图片上传、封面选择、隐私设置) +- **PostDetailModal**:帖子详情弹窗(小红书风格,左右分栏,左侧图片轮播,右侧内容与互动数据,支持mode="page"模式用于移动端) +- **CreateEditPostModal**:帖子发布/编辑弹窗(左右分栏布局,支持多图片上传、封面选择、隐私设置,支持mode="page"模式用于移动端) +- **MobilePageWrapper**:移动端页面包裹组件,提供统一的顶部导航栏和返回按钮 +- **LoginModal**:桌面端登录弹窗(左右双栏布局,左侧二维码区+右侧登录表单) +- **RegisterModal**:桌面端注册弹窗(支持用户协议勾选) +- **SettingsModal**:设置弹窗(含社交链接) +- **FloatingActions**:浮动操作按钮组(发帖、刷新、回到顶部) +- **BulkActionBar**:批量操作底部栏(全选、取消全选、删除) +- **StorageCard**:存储空间卡片(圆形进度条展示使用率,超过90%红色警示) +- **UpgradePanel**:VIP/SVIP升级方案面板(含增量包购买选项) +- **SpacePickerModal**:空间图片选择器弹窗(从私人空间选取图片,支持去重和数量限制) +- **ImageEditModal**:图片编辑表单弹窗(编辑图片名称和介绍) +- **PageHeader**:统一页面标题头组件 +- **EmptyState**:统一空数据展示组件 +- **SearchBar**:自定义搜索栏组件(支持Enter搜索和清除) +- **ProfileHeader**:用户个人资料头组件(头像、昵称、统计数据、头像预览) +- **PostCard**:社区帖子卡片组件(瀑布流风格,显示封面、标题、用户信息、点赞收藏数) +- **MobileBottomNav**:移动端底部Tab导航栏(首页、社区、私人空间、团队空间、我的) - **AuthContext**:认证状态管理(登录、登出、用户信息) - **ThemeContext**:主题状态管理(明暗主题切换) -- **API封装**:Axios请求配置(请求/响应拦截器,统一错误处理) +- **API封装**:Axios请求配置(请求/响应拦截器,统一错误处理,请求去重机制) - **Storage工具**:本地存储管理(用户信息) +#### 2.1.15 前端自定义Hooks + +- **useIsMobile**:响应式检测Hook,监听窗口resize事件,断点768px判断移动端 +- **useAuthModal**:认证弹窗管理Hook,封装登录/注册弹窗的全部状态管理与业务逻辑(验证码获取、登录/注册提交、错误处理、表单重置) + --- ## 3. 数据模型分析 @@ -462,6 +514,7 @@ User (1) ───< (N) UserPostLikes - **基础路径**: `/api` - **请求格式**: JSON (application/json) 或 multipart/form-data(文件上传) - **认证方式**: HTTP Session(Spring Session机制,通过Cookie自动传输Session ID) +- **请求去重**: Axios拦截器实现自动请求去重,相同请求自动取消前一个(通过AbortController),支持noDedup配置跳过去重 - **响应格式**: 统一 Response 结构 { code, message, data } - code: 1-成功,其他-失败 - message: 响应信息 @@ -940,7 +993,7 @@ User (1) ───< (N) UserPostLikes ### 8.1 环境要求 -- **Java**: JDK 11+ +- **Java**: JDK 21+ - **MySQL**: 8.0+ - **Redis**: 5.0+ - **Node.js**: 18+ diff --git a/model/uml_diagrams.md b/model/uml_diagrams.md index 757d8b4..57b0559 100644 --- a/model/uml_diagrams.md +++ b/model/uml_diagrams.md @@ -494,6 +494,30 @@ +------------------------------------------+ ``` +##### PictureUpdateRequest + +``` ++------------------------------------------+ +| PictureUpdateRequest | ++------------------------------------------+ +| - id: Long (图片ID) | +| - pictureName: String (图片名称) | +| - introduction: String (图片简介) | ++------------------------------------------+ +``` + +##### GetPictureBySpaceRequest + +``` ++------------------------------------------+ +| GetPictureBySpaceRequest | ++------------------------------------------+ +| - spaceId: Long (空间ID) | +| - current: long (当前页) | +| - pageSize: long (每页大小) | ++------------------------------------------+ +``` + ##### SpacePictureList ``` @@ -731,6 +755,7 @@ | + POST /post/editPost (编辑帖子) | | + POST /post/postList (获取帖子列表) | | + POST /post/like (点赞帖子) | +| + POST /post/pictureList (编辑帖子图片列表)| | + POST /post/myPosts (我的帖子列表) | | + POST /post/myCollects (我的收藏列表) | | + POST /post/myLikes (我的点赞列表) | @@ -746,11 +771,12 @@ | - pictureService: PictureService | +------------------------------------------+ | + POST /picture/avatar (上传头像) | -| + POST /picture/post (上传帖子图片) | +| + POST /picture/upload (上传图片) | | + GET /picture/list (公开图片列表) | | + GET /picture/admin/list (管理员图片列表)| | + POST /picture/admin/review (审核图片) | | + POST /picture/delete (删除图片) | +| + PUT /picture/update (更新图片信息) | +------------------------------------------+ ``` @@ -764,6 +790,7 @@ +------------------------------------------+ | + POST /space/create (创建空间) | | + GET /space/list (获取空间列表) | +| + GET /space/getSpace (获取空间详情) | | + POST /space/update (更新空间) | | + POST /space/pictureList (空间图片列表) | +------------------------------------------+ @@ -836,12 +863,12 @@ | extends IService | +------------------------------------------+ | + uploadAvatar(file, id, request) | -| + uploadPicture4Post(file, request) | -| + setPicturePostId(imageIds, postId) | +| + uploadPicture(file, request) | | + getPictureList(current, pageSize) | | + getAdminPictureList(current, pageSize, status)| | + reviewPicture(pictureId, status, selected)| -| + deletePicture(ids) | +| + deletePicture(ids, request) | +| + updatePicture(pictureUpdateRequest) | +------------------------------------------+ ``` @@ -1120,38 +1147,43 @@ LoginUser --> UserService: 返回User对象 ``` 用户 -> 前端: 填写帖子内容并上传图片 -前端 -> 后端(PictureController): POST /picture/post (MultipartFile) -PictureController: 校验文件大小(<=5MB) -PictureController -> PictureService: uploadPicture4Post(file, request) +前端 -> 后端(PictureController): POST /picture/upload (MultipartFile) +PictureController: 校验文件非空 +PictureController -> PictureService: uploadPicture(file, request) PictureService -> LoginUser: getLoginUser(request) [获取当前用户] LoginUser -> HttpSession: getAttribute(TOKEN_KEY) HttpSession --> LoginUser: 返回userId LoginUser -> Redis: get(USER_ID:{userId}) Redis --> LoginUser: 返回UserJSON LoginUser --> PictureService: 返回User对象 +PictureService: 根据用户等级限制文件大小(普通3MB/VIP 5MB/SVIP 20MB) PictureService -> CosService: 上传文件到腾讯云COS CosService --> PictureService: 返回图片URL -PictureService -> PictureMapper: INSERT INTO picture (userId, url, width, height, size) +PictureService -> PictureService: 获取图片元信息(宽高) +PictureService -> SpaceMapper: 查询用户私人空间 +SpaceMapper -> MySQL: SELECT * FROM space WHERE user_id=? AND type=0 +MySQL --> SpaceMapper: 返回私人空间 +PictureService: 检查私人空间存储是否充足 +PictureService -> PictureMapper: INSERT INTO picture (userId, url, width, height, size, spaceId, status) + [管理员] status=1(直接通过) + [普通用户] status=2(待审核) PictureMapper -> MySQL: 插入图片记录 MySQL --> PictureMapper: 返回插入结果(含pictureId) +PictureService -> SpaceMapper: UPDATE space SET size=size+fileSize PictureService --> 前端: Response (url + pictureId) 用户 -> 前端: 提交帖子(含图片ID列表) 前端 -> 后端(PostController): POST /post/post (UploadPostRequest) PostController -> PostService: uploadPost(uploadPostRequest, request) PostService -> LoginUser: getLoginUser(request) [获取当前用户] -LoginUser -> HttpSession: getAttribute(TOKEN_KEY) -HttpSession --> LoginUser: 返回userId -LoginUser -> Redis: get(USER_ID:{userId}) -Redis --> LoginUser: 返回UserJSON LoginUser --> PostService: 返回User对象 +PostService: 校验图片(最多15张)、标题、内容、封面 +PostService -> PostService: isMyPicture(userId, imageIds) [验证图片归属] PostService -> PostMapper: INSERT INTO post (userId, title, content, cover, isPrivate) PostMapper -> MySQL: 插入帖子记录 MySQL --> PostMapper: 返回插入结果(含postId) -PostService -> PictureService: setPicturePostId(imageIds, postId) -PictureService -> PictureMapper: UPDATE picture SET post_id=? WHERE id IN (?) -PictureMapper -> MySQL: 更新图片postId -MySQL --> PictureMapper: 更新成功 +PostService -> PictureChildMapper: INSERT batch INTO picture_child (pictureId, postId, sortNum) +PostService -> PictureMapper: UPDATE picture SET post_id=? WHERE id IN (?) PostService --> 后端: Response 后端 --> 前端: 发布成功 前端 --> 用户: 显示成功并跳转 @@ -1212,14 +1244,20 @@ HttpSession --> LoginUser: 返回userId LoginUser -> Redis: get(USER_ID:{userId}) Redis --> LoginUser: 返回UserJSON LoginUser --> PostService: 返回User对象 +PostService -> Redisson: getLock(LIKE_POST + postId) [获取分布式锁] +Redisson --> PostService: 返回RLock对象 +PostService -> RLock: tryLock(10秒超时) [尝试获取锁] + [获取失败] -> PostService --> 后端: 提示操作频繁,请稍后再试 + [获取成功] -> PostService -> UserPostLikesMapper: selectOne(userId, postId) UserPostLikesMapper -> MySQL: 查询是否已点赞 MySQL --> UserPostLikesMapper: 返回查询结果 PostService -> 判断点赞状态: [未点赞] -> UserPostLikesMapper: INSERT (userId, postId) - -> PostMapper: UPDATE post SET likes_num = likes_num + 1 + -> PostMapper: UPDATE post SET likes_num = likes_num + 1 (乐观更新) [已点赞] -> UserPostLikesMapper: DELETE (userId, postId) - -> PostMapper: UPDATE post SET likes_num = likes_num - 1 + -> PostMapper: UPDATE post SET likes_num = likes_num - 1 (乐观更新) +PostService -> RLock: unlock() [释放分布式锁] MySQL --> PostService: 操作成功 PostService --> 后端: Response 后端 --> 前端: 点赞/取消成功 @@ -1416,25 +1454,27 @@ PicSystemService --> 后端: Response 前端 --> 管理员: 显示成功并刷新列表 ``` -### 3.17 管理员创建空间流程 +### 3.17 创建空间流程 ``` -管理员 -> 前端: 填写空间信息并提交 +用户 -> 前端: 填写空间信息并提交 前端 -> 后端(SpaceController): POST /space/create (CreateSpace) -后端 -> AuthInterceptor: @AuthCheck(role=ADMIN) [权限校验] +后端 -> AuthInterceptor: @AuthCheck [权限校验(私人空间需登录, 团队空间需管理员)] AuthInterceptor -> LoginUser: getLoginUser(request) LoginUser -> AuthInterceptor: 返回User对象 AuthInterceptor -> 后端: 权限通过 -SpaceController -> SpaceService: createSpace(createSpace, request) -SpaceService -> LoginUser: getLoginUser(request) -LoginUser -> SpaceService: 返回User对象 -SpaceService: 根据type设置默认存储大小 (PRIVATE:512MB / TEAM:5GB) +SpaceController -> SpaceService: createSpace(createSpace, user) +SpaceService -> 判断空间类型: + [私人空间(0)] -> SpaceService: 检查是否已有私人空间(每人限1个) + SpaceService: 根据用户等级设置存储大小(普通512MB/VIP 5GB/SVIP 10GB) + [团队空间(1)] -> SpaceService: 检查团队空间数量限制(普通1个/VIP 5个/SVIP 10个) + SpaceService: 根据用户等级设置存储大小(VIP 30GB/SVIP 50GB) SpaceService -> SpaceMapper: INSERT INTO space (name, introduction, type, userId, storageSize, level) SpaceMapper -> MySQL: 插入空间记录 MySQL --> SpaceMapper: 返回插入结果 SpaceService --> 后端: Response 后端 --> 前端: 创建成功 -前端 --> 管理员: 显示成功并刷新列表 +前端 --> 用户: 显示成功并刷新列表 ``` ### 3.18 获取公开图片列表流程 @@ -1512,7 +1552,26 @@ PictureService --> 后端: Response [仅自己可见(1)] --(用户修改为公开)--> [公开(0)] ``` -### 4.5 图片首页展示状态图 +### 4.5 用户等级状态图 + +``` +[普通用户(0)] --(购买VIP)--> [VIP(1)] +[VIP(1)] --(购买SVIP)--> [SVIP(2)] +[SVIP(2)] --(降级)--> [VIP(1)] +[VIP(1)] --(降级)--> [普通用户(0)] +[普通/VIP/SVIP] --(管理员编辑)--> [任意等级] +``` + +### 4.6 图片审核状态图 + +``` +[待审核(2)] --(管理员通过)--> [正常(1)] +[待审核(2)] --(管理员拒绝)--> [禁用(0)] +[正常(1)] --(管理员标记精选)--> [精选(selected=1)] +[管理员上传] --(自动通过)--> [正常(1)] +``` + +### 4.7 图片首页展示状态图 ``` [公开到首页(1)] --(用户修改为不公开)--> [不公开(0)] @@ -1541,6 +1600,7 @@ PictureService --> 后端: Response - **CommunitySquare.jsx**: 社区广场 (帖子瀑布流展示,滚动100px后显示返回顶部按钮) - **PrivateSpace.jsx**: 个人空间 - **TeamSpace.jsx**: 团队空间 +- **TeamSpaceDetail.jsx**: 团队空间详情(空间信息展示、图片瀑布流管理、批量操作、图片编辑) - **Notifications.jsx**: 通知消息 - **UserProfile.jsx**: 用户资料 - **UserManagement.jsx**: 用户管理 @@ -1551,17 +1611,53 @@ PictureService --> 后端: Response - **SpaceManagement.jsx**: 空间管理(开发中) - **AIManagement.jsx**: AI管理(开发中) - **NotFound.jsx**: 404页面 +- **MobileLoginPage.jsx**: 移动端独立登录页 +- **MobileRegisterPage.jsx**: 移动端独立注册页 +- **MobilePostCreatePage.jsx**: 移动端帖子创建页(复用CreateEditPostModal) +- **MobilePostDetailPage.jsx**: 移动端帖子详情页(复用PostDetailModal) +- **MobileEditProfilePage.jsx**: 移动端编辑资料页(含头像上传) +- **MobileEditPicturePage.jsx**: 移动端图片编辑页 #### 通用组件 - **GlobalLayout.jsx**: 全局布局组件 +- **MobilePageWrapper.jsx**: 移动端页面包裹组件(统一顶部导航栏和返回按钮) - **ProtectedRoute.jsx**: 路由保护组件 - **ErrorBoundary.jsx**: 错误边界组件 - **FunnyBackground.jsx**: 趣味背景动画 -- **PostDetailModal.jsx**: 帖子详情弹窗 -- **CreateEditPostModal.jsx**: 帖子发布/编辑弹窗 -- **api/index.js**: API请求封装 (Axios配置、拦截器、所有接口方法) +- **PostDetailModal.jsx**: 帖子详情弹窗(支持mode="modal"/"page"双模式) +- **CreateEditPostModal.jsx**: 帖子发布/编辑弹窗(支持mode="modal"/"page"双模式) + +#### 共享组件 (components/shared/) + +- **LoginModal.jsx**: 桌面端登录弹窗(左右双栏布局) +- **RegisterModal.jsx**: 桌面端注册弹窗 +- **SettingsModal.jsx**: 设置弹窗(含社交链接) +- **FloatingActions.jsx**: 浮动操作按钮组(发帖、刷新、回到顶部) +- **BulkActionBar.jsx**: 批量操作底部栏 +- **StorageCard.jsx**: 存储空间卡片(圆形进度条) +- **UpgradePanel.jsx**: VIP/SVIP升级方案面板 +- **SpacePickerModal.jsx**: 空间图片选择器弹窗 +- **ImageEditModal.jsx**: 图片编辑表单弹窗 +- **PageHeader.jsx**: 统一页面标题头 +- **EmptyState.jsx**: 统一空数据展示 +- **SearchBar.jsx**: 自定义搜索栏 +- **ProfileHeader.jsx**: 用户个人资料头 +- **PostCard.jsx**: 社区帖子卡片 +- **MobileBottomNav.jsx**: 移动端底部Tab导航栏 + +#### 自定义Hooks (hooks/) + +- **useIsMobile.js**: 响应式移动端检测Hook(断点768px) +- **useAuthModal.js**: 认证弹窗管理Hook(封装登录/注册弹窗状态与逻辑) + +#### 工具与配置 + +- **api/index.js**: API请求封装 (Axios配置、拦截器、请求去重、所有接口方法) - **utils/storage.js**: localStorage操作工具 +- **styles/animations.css**: 动画样式 +- **styles/carousel.css**: 轮播样式 +- **styles/shared.css**: 共享样式 ### 5.2 后端组件 (FishPics-backend) @@ -1580,18 +1676,18 @@ PictureService --> 后端: Response #### Controller 层 -- **UserController**: 用户相关接口 (11个接口) -- **PostController**: 帖子相关接口 (5个接口) -- **PictureController**: 图片相关接口 (6个接口) -- **SpaceController**: 空间相关接口 (4个接口) +- **UserController**: 用户相关接口 (12个接口) +- **PostController**: 帖子相关接口 (9个接口) +- **PictureController**: 图片相关接口 (7个接口) +- **SpaceController**: 空间相关接口 (5个接口) - **SystemController**: 系统相关接口 (6个接口) #### Service 层 - **UserService/Impl**: 用户业务逻辑 (11个方法) -- **PostService/Impl**: 帖子业务逻辑 (9个方法,含myPosts/myCollects/myLikes) -- **PictureService/Impl**: 图片业务逻辑 (7个方法,含list/admin/review/delete) -- **SpaceService/Impl**: 空间业务逻辑 (5个方法) +- **PostService/Impl**: 帖子业务逻辑 (11个方法,含myPosts/myCollects/myLikes/pictureList/likePost) +- **PictureService/Impl**: 图片业务逻辑 (8个方法,含upload/review/delete/update) +- **SpaceService/Impl**: 空间业务逻辑 (6个方法,含create/list/getSpace/update/pictureList) - **PicSystemService/Impl**: 系统配置业务逻辑 (6个方法,标签+跑马灯) - **CommentService/Impl**: 评论业务逻辑 - **UserPostCollectService/Impl**: 帖子收藏业务 diff --git a/src/FishPic-frontend/src/context/AuthContext.jsx b/src/FishPic-frontend/src/context/AuthContext.jsx index 67b39c9..bc62180 100644 --- a/src/FishPic-frontend/src/context/AuthContext.jsx +++ b/src/FishPic-frontend/src/context/AuthContext.jsx @@ -49,8 +49,16 @@ export function AuthProvider({ children }) { setIsAuthenticated(false) } + const updateUserInfo = (updater) => { + setUserInfo(prev => { + const next = typeof updater === 'function' ? updater(prev) : updater + if (next) saveUserInfo(next) + return next + }) + } + return ( - + {children} ) diff --git a/src/FishPic-frontend/src/pages/MobileEditProfilePage.jsx b/src/FishPic-frontend/src/pages/MobileEditProfilePage.jsx index 281d4e5..7054fc7 100644 --- a/src/FishPic-frontend/src/pages/MobileEditProfilePage.jsx +++ b/src/FishPic-frontend/src/pages/MobileEditProfilePage.jsx @@ -11,7 +11,7 @@ export default function MobileEditProfilePage() { const navigate = useNavigate() const { message } = App.useApp() const [form] = Form.useForm() - const { setUserInfo } = useContext(AuthContext) + const { updateUserInfo } = useContext(AuthContext) const [loading, setLoading] = useState(false) const [userData, setUserData] = useState(null) const [avatarLoading, setAvatarLoading] = useState(false) @@ -45,11 +45,14 @@ export default function MobileEditProfilePage() { } setAvatarLoading(true) try { - const res = await uploadAvatar(file) + const formData = new FormData() + formData.append('file', file) + formData.append('id', userData.id) + const res = await uploadAvatar(formData) const newAvatar = res?.data?.data?.avatar || res?.data?.avatar if (newAvatar) { setUserData(prev => ({ ...prev, avatar: newAvatar })) - setUserInfo(prev => ({ ...prev, avatar: newAvatar })) + updateUserInfo(prev => ({ ...prev, avatar: newAvatar })) message.success('头像更新成功') } } catch { @@ -68,7 +71,7 @@ export default function MobileEditProfilePage() { email: values.email, phone: values.phone, }) - setUserInfo(prev => ({ + updateUserInfo(prev => ({ ...prev, nickname: values.nickname, email: values.email, diff --git a/src/FishPics-backend/src/main/resources/application.yml b/src/FishPics-backend/src/main/resources/application.yml index 3837055..e24d669 100644 --- a/src/FishPics-backend/src/main/resources/application.yml +++ b/src/FishPics-backend/src/main/resources/application.yml @@ -19,14 +19,14 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/FishPics - username: root - password: 123456 + username: # 数据库账号 + password: # 数据库密码 data: redis: - host: 192.168.163.101 + host: # redis 地址 database: 0 port: 6379 - profiles: + profiles: # 使用本地环境配置文件 active: local knife4j: enable: true @@ -50,7 +50,6 @@ knife4j: # bucket: # public: true # 开发true 生产false # url: # 阿里云图片 url 前缀 - logging: level: root: info