commit 51e2791a4982e0c68a71f0988fb5dfd9b51c2df5
Author: superlishunqin <852326703@qq.com>
Date: Thu Sep 25 05:52:22 2025 +0800
农产品直销平台完整项目
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5a28c95
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,204 @@
+# Java编译文件
+*.class
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+# Gradle
+.gradle
+/build/
+gradle-app.setting
+!gradle-wrapper.jar
+!gradle-wrapper.properties
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+# Spring Boot
+spring-boot-starter-parent/
+
+# Node.js和Vue
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+dist/
+dist-ssr/
+*.local
+.npmrc
+
+# Vue相关
+.vuepress/dist
+.nuxt
+.nitro
+
+# Python虚拟环境
+venv/
+env/
+ENV/
+.venv/
+.env/
+.python-version
+pyenv.cfg
+
+# Python编译文件
+__pycache__/
+*.py[cod]
+*$py.class
+*.so
+*.egg
+*.egg-info/
+dist/
+build/
+.eggs/
+
+# Python工具
+.pytest_cache/
+.coverage
+.tox/
+.nox/
+htmlcov/
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IDE相关文件
+.idea/
+.vscode/
+*.swp
+*.swo
+*~
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+*.sublime-project
+.spyderproject
+.spyproject
+
+# 系统相关文件
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+.fseventsd
+.TemporaryItems
+.DocumentRevisions-V100
+
+# 日志文件
+logs/
+*.log
+log/
+*.log.*
+*.out
+
+# 缓存文件
+.cache/
+.temp/
+.tmp/
+*.cache
+.eslintcache
+.stylelintcache
+
+# 环境配置文件(包含敏感信息)
+.env
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# 敏感配置文件(重要:包含密钥信息)
+**/application-*.yml
+!**/application.yml
+!**/application-prod.yml.template
+!**/application-dev.yml.template
+*.key
+*.pem
+*.p12
+*.keystore
+*.jks
+
+# 数据库文件
+*.db
+*.sqlite
+*.sqlite3
+
+# 测试覆盖率报告
+coverage/
+*.lcov
+.nyc_output
+
+# 依赖分析文件
+.pnp
+.pnp.js
+
+# 运行时数据
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# 可选的npm缓存目录
+.npm
+
+# 可选的eslint缓存
+.eslintcache
+
+# 可选的stylelint缓存
+.stylelintcache
+
+# TypeScript缓存
+*.tsbuildinfo
+
+# 备份文件
+*.bak
+*.backup
+*.old
+
+# 压缩文件
+*.7z
+*.dmg
+*.gz
+*.iso
+*.tar
+
+# 项目特定文件
+export_code.sh
+temp_*
+*.txt.backup*
+*.yml.backup*
+*.yml.bak*
+SunnyFarm_源代码.txt
+
+# Docker相关
+.dockerignore
+docker-compose.override.yml
+
+# 其他
+.vite-inspect/
+.vite/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..29b31b3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,351 @@
+# 🌱 农产品直销平台 (SunnyFarm)
+
+一个基于 Spring Boot + Vue.js + MySQL 的现代化农产品电商平台,支持多角色管理(用户、商家、管理员),提供完整的电商功能包括商品管理、订单处理、支付集成、库存管理等。
+
+## 📋 目录
+
+- [功能特性](#功能特性)
+- [技术栈](#技术栈)
+- [环境要求](#环境要求)
+- [快速开始](#快速开始)
+- [配置说明](#配置说明)
+- [部署指南](#部署指南)
+- [API文档](#api文档)
+- [贡献指南](#贡献指南)
+
+## ✨ 功能特性
+
+### 🛒 核心电商功能
+- **商品管理**: 分类管理、商品发布、图片上传、库存管理
+- **购物车**: 添加商品、数量调整、批量操作
+- **订单系统**: 创建订单、支付集成、状态跟踪、物流管理
+- **用户系统**: 注册登录、个人中心、收货地址管理
+- **评价系统**: 商品评价、商家回复、评分统计
+
+### 👥 多角色支持
+- **普通用户**: 浏览商品、下单购买、管理订单
+- **商家**: 商品管理、订单处理、销售统计、客服聊天
+- **平台管理员**: 用户管理、商家审核、系统配置、数据统计
+
+### 🔧 技术亮点
+- **支付集成**: 支付宝沙箱支付,支持异步回调
+- **文件存储**: 腾讯云COS + CDN加速
+- **缓存优化**: Redis缓存用户会话和购物车数据
+- **邮件服务**: 注册验证码、订单通知
+- **实时聊天**: 用户与商家在线客服
+- **响应式设计**: 支持PC端和移动端访问
+
+## 🛠 技术栈
+
+### 后端技术
+- **框架**: Spring Boot 2.7.14
+- **安全**: Spring Security + JWT认证
+- **数据库**: MySQL 8.0 + MyBatis Plus
+- **缓存**: Redis
+- **文件存储**: 腾讯云COS
+- **支付**: 支付宝开放平台
+- **邮件**: Spring Boot Mail
+
+### 前端技术
+- **框架**: Vue 3 + Vite
+- **UI组件**: Element Plus
+- **状态管理**: Pinia
+- **路由**: Vue Router 4
+- **图表**: ECharts
+- **HTTP客户端**: Axios
+
+### 运维部署
+- **容器化**: Docker + Docker Compose
+- **云服务**: 支持各类云平台部署
+- **反向代理**: Nginx
+- **进程管理**: PM2(可选)
+
+## 📋 环境要求
+
+### 开发环境
+- **Java**: JDK 8 或以上
+- **Node.js**: 16.0 或以上
+- **Maven**: 3.6 或以上
+- **MySQL**: 8.0 或以上
+- **Redis**: 6.0 或以上
+
+### 生产环境
+- **服务器**: Linux (推荐 Ubuntu 20.04+)
+- **内存**: 建议 2GB 以上
+- **存储**: 建议 20GB 以上
+- **网络**: 需要公网IP或域名(用于支付回调)
+
+## 🚀 快速开始
+
+### 1. 克隆项目
+
+```bash
+git clone https://git.sq0715.com/qin/SunnyFarm.git
+cd SunnyFarm
+```
+
+### 2. 配置文件设置
+
+#### 后端配置
+
+复制配置模板并填入你的配置信息:
+
+```bash
+# 开发环境配置
+cp backend/src/main/resources/application-dev.yml.example backend/src/main/resources/application-dev.yml
+
+# 生产环境配置
+cp backend/src/main/resources/application-prod.yml.example backend/src/main/resources/application-prod.yml
+```
+
+### 3. 数据库初始化
+
+```bash
+# 创建数据库
+mysql -u root -p -e "CREATE DATABASE sunnyfarm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
+
+# 导入数据库结构和初始数据
+mysql -u your_username -p sunnyfarm < sql/sunnyfarm.sql
+mysql -u your_username -p sunnyfarm < sql/init_inventory.sql
+```
+
+### 4. 启动后端服务
+
+```bash
+cd backend
+mvn clean install
+mvn spring-boot:run
+```
+
+服务启动后访问: http://localhost:8080/api/init/status
+
+### 5. 启动前端服务
+
+```bash
+cd frontend
+npm install
+npm run dev
+```
+
+前端启动后访问: http://localhost:3000
+
+## ⚙️ 配置说明
+
+### 数据库配置
+```yaml
+spring:
+ datasource:
+ url: jdbc:mysql://your-mysql-host:3306/sunnyfarm
+ username: your-db-username
+ password: your-db-password
+```
+
+### Redis配置
+```yaml
+spring:
+ redis:
+ host: your-redis-host
+ port: 6379
+ password: your-redis-password
+```
+
+### 邮件服务配置 (QQ邮箱示例)
+```yaml
+spring:
+ mail:
+ host: smtp.qq.com
+ port: 465
+ username: your-email@qq.com
+ password: your-email-auth-code # QQ邮箱授权码
+```
+
+### 腾讯云COS配置
+```yaml
+tencent:
+ cos:
+ secret-id: your-tencent-cos-secret-id
+ secret-key: your-tencent-cos-secret-key
+ region: ap-guangzhou
+ bucket: your-bucket-name
+```
+
+### 支付宝配置
+```yaml
+alipay:
+ app-id: your-alipay-app-id
+ app-private-key: your-alipay-app-private-key
+ alipay-public-key: your-alipay-public-key
+ notify-url: http://your-domain:8080/api/payment/alipay/notify
+ return-url: http://your-domain:3000/orders?payment=success
+```
+
+**重要**: 支付宝回调地址必须是公网可访问的地址,不能使用localhost
+
+### JWT配置
+```yaml
+jwt:
+ secret: your-jwt-secret-key
+ expiration: 86400000 # 24小时,单位毫秒
+```
+
+## 🐳 Docker部署
+
+### 使用Docker Compose部署
+
+```bash
+# 构建并启动服务
+docker-compose up -d
+
+# 查看服务状态
+docker-compose ps
+
+# 查看日志
+docker-compose logs -f
+```
+
+### 手动Docker部署
+
+```bash
+# 构建后端镜像
+cd backend
+docker build -t sunnyfarm-backend .
+
+# 构建前端镜像
+cd ../frontend
+docker build -t sunnyfarm-frontend .
+
+# 启动服务
+docker run -d -p 8080:8080 --name sunnyfarm-backend sunnyfarm-backend
+docker run -d -p 3000:3000 --name sunnyfarm-frontend sunnyfarm-frontend
+```
+
+## 🌍 生产环境部署
+
+### 1. 服务器准备
+
+```bash
+# 安装基础软件
+sudo apt update && sudo apt install -y git docker.io docker-compose nginx
+
+# 启动Docker服务
+sudo systemctl start docker
+sudo systemctl enable docker
+```
+
+### 2. 克隆项目并配置
+
+```bash
+git clone https://git.sq0715.com/qin/SunnyFarm.git
+cd SunnyFarm
+
+# 配置生产环境文件
+cp backend/src/main/resources/application-prod.yml.example backend/src/main/resources/application-prod.yml
+# 编辑配置文件,填入生产环境配置信息
+vim backend/src/main/resources/application-prod.yml
+```
+
+### 3. 部署启动
+
+```bash
+# 构建并启动
+docker-compose up -d
+
+# 检查服务状态
+docker-compose ps
+curl http://your-server-ip:8080/api/init/status
+```
+
+## 📚 API文档
+
+### 认证接口
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| POST | `/api/user/login` | 用户登录 |
+| POST | `/api/user/register` | 用户注册 |
+| POST | `/api/merchant/login` | 商家登录 |
+| POST | `/api/admin/login` | 管理员登录 |
+
+### 商品接口
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| GET | `/api/product/list` | 商品列表 |
+| GET | `/api/product/{id}` | 商品详情 |
+| POST | `/api/product/create` | 创建商品(商家) |
+| PUT | `/api/product/{id}` | 更新商品(商家) |
+
+### 订单接口
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| POST | `/api/order/create` | 创建订单 |
+| GET | `/api/order/list` | 订单列表 |
+| GET | `/api/order/{id}` | 订单详情 |
+| POST | `/api/order/{id}/pay` | 订单支付 |
+
+## 🎯 默认账号
+
+### 管理员账号
+- 用户名: `admin`
+- 密码: `admin123`
+
+### 测试商家账号
+- 用户名: `merchant`
+- 密码: `merchant123`
+
+### 测试用户账号
+- 用户名: `user`
+- 密码: `user123`
+
+## 📝 开发说明
+
+### 项目结构
+
+```
+SunnyFarm/
+├── backend/ # 后端Spring Boot项目
+│ ├── src/main/java/ # Java源码
+│ ├── src/main/resources/ # 配置文件
+│ └── pom.xml # Maven配置
+├── frontend/ # 前端Vue项目
+│ ├── src/ # Vue源码
+│ ├── public/ # 静态资源
+│ └── package.json # NPM配置
+├── sql/ # 数据库脚本
+├── docker-compose.yml # Docker编排
+└── README.md # 项目文档
+```
+
+### 开发规范
+
+- 代码格式化: 使用项目配置的格式化规则
+- 提交规范: 使用语义化提交信息
+- 分支管理: 使用Git Flow工作流
+- 代码审查: 重要功能需要代码审查
+
+## 🤝 贡献指南
+
+1. Fork本项目
+2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
+3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
+4. 推送分支 (`git push origin feature/AmazingFeature`)
+5. 创建Pull Request
+
+## 📄 许可证
+
+本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
+
+## 📞 联系方式
+
+- 项目地址: https://git.sq0715.com/qin/SunnyFarm
+- 问题反馈: 请在GitHub Issues中提交
+- 邮箱联系: 852326703@qq.com
+
+## 🙏 致谢
+
+感谢所有为本项目做出贡献的开发者们!
+
+---
+
+**注意**: 本项目仅供学习和研究使用,请勿用于商业用途。使用前请确保遵守相关法律法规。
\ No newline at end of file
diff --git a/backend/README.md b/backend/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/backend/pom.xml b/backend/pom.xml
new file mode 100644
index 0000000..37ebbe0
--- /dev/null
+++ b/backend/pom.xml
@@ -0,0 +1,133 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.14
+
+
+ com.sunnyfarm
+ sunny-farm
+ 0.0.1-SNAPSHOT
+ sunny-farm
+ Agricultural Product Direct Sales Platform
+
+ 8
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.3
+
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.33
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+
+
+ com.qcloud
+ cos_api
+ 5.6.155
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ 4.38.10.ALL
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
diff --git a/backend/pom.xml.backup2 b/backend/pom.xml.backup2
new file mode 100644
index 0000000..f61c109
--- /dev/null
+++ b/backend/pom.xml.backup2
@@ -0,0 +1,206 @@
+
+
+ 4.0.0
+
+ com.sunnyfarm
+ sunny-farm
+ 1.0.0
+ jar
+
+ SunnyFarm
+ 农产品直销平台
+
+
+
+ 17
+ 17
+ 17
+
+ 2.7.14
+ 3.5.3
+ 8.0.33
+ 2.7.14
+ 0.11.5
+ 5.6.89
+ 4.35.79.ALL
+ 5.8.20
+ 2.0.31
+ 1.18.32
+ UTF-8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring.boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis.plus.version}
+
+
+
+ com.mysql
+ mysql-connector-j
+ ${mysql.version}
+
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ ${jwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ ${jwt.version}
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ ${jwt.version}
+ runtime
+
+
+
+
+ com.qcloud
+ cos_api
+ ${cos.version}
+
+
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ ${alipay.version}
+
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ ${fastjson.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 3.11.0
+
+
+ ${java.version}
+ ${java.version}
+ UTF-8
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+ 0.2.0
+
+
+
+
+
+
+
diff --git a/backend/pom.xml.backup3 b/backend/pom.xml.backup3
new file mode 100644
index 0000000..43fc33c
--- /dev/null
+++ b/backend/pom.xml.backup3
@@ -0,0 +1,122 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.14
+
+
+ com.sunnyfarm
+ sunny-farm
+ 0.0.1-SNAPSHOT
+ sunny-farm
+ Agricultural Product Direct Sales Platform
+
+ 8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.3
+
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.33
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+
+
+ com.qcloud
+ cos_api
+ 5.6.155
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
diff --git a/backend/src/main/java/com/sunnyfarm/SunnyFarmApplication.java b/backend/src/main/java/com/sunnyfarm/SunnyFarmApplication.java
new file mode 100644
index 0000000..84a46cf
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/SunnyFarmApplication.java
@@ -0,0 +1,12 @@
+package com.sunnyfarm;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+
+@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
+public class SunnyFarmApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SunnyFarmApplication.class, args);
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/common/PageResult.java b/backend/src/main/java/com/sunnyfarm/common/PageResult.java
new file mode 100644
index 0000000..a5f1244
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/common/PageResult.java
@@ -0,0 +1,22 @@
+package com.sunnyfarm.common;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageResult {
+ private Long total;
+ private Long pages;
+ private Long current;
+ private Long size;
+ private List records;
+
+ public static PageResult of(Long total, Long pages, Long current, Long size, List records) {
+ return new PageResult<>(total, pages, current, size, records);
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/common/Result.java b/backend/src/main/java/com/sunnyfarm/common/Result.java
new file mode 100644
index 0000000..6b68a60
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/common/Result.java
@@ -0,0 +1,42 @@
+package com.sunnyfarm.common;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Result {
+ private Integer code;
+ private String message;
+ private T data;
+
+ public static Result success() {
+ return new Result<>(200, "操作成功", null);
+ }
+
+ public static Result success(T data) {
+ return new Result<>(200, "操作成功", data);
+ }
+
+ public static Result success(String message, T data) {
+ return new Result<>(200, message, data);
+ }
+
+ public static Result error() {
+ return new Result<>(500, "操作失败", null);
+ }
+
+ public static Result error(String message) {
+ return new Result<>(500, message, null);
+ }
+
+ public static Result error(Integer code, String message) {
+ return new Result<>(code, message, null);
+ }
+
+ public static Result error(String message, T data) {
+ return new Result<>(500, message, data);
+ }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/sunnyfarm/config/AlipayConfig.java b/backend/src/main/java/com/sunnyfarm/config/AlipayConfig.java
new file mode 100644
index 0000000..952d2ab
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/AlipayConfig.java
@@ -0,0 +1,28 @@
+package com.sunnyfarm.config;
+
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.sunnyfarm.config.properties.AlipayProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AlipayConfig {
+
+ @Autowired
+ private AlipayProperties alipayProperties;
+
+ @Bean
+ public AlipayClient alipayClient() {
+ return new DefaultAlipayClient(
+ alipayProperties.getServerUrl(),
+ alipayProperties.getAppId(),
+ alipayProperties.getAppPrivateKey(),
+ alipayProperties.getFormat(),
+ alipayProperties.getCharset(),
+ alipayProperties.getAlipayPublicKey(),
+ alipayProperties.getSignType()
+ );
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/AsyncConfig.java b/backend/src/main/java/com/sunnyfarm/config/AsyncConfig.java
new file mode 100644
index 0000000..78ca784
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/AsyncConfig.java
@@ -0,0 +1,9 @@
+package com.sunnyfarm.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/CosConfig.java b/backend/src/main/java/com/sunnyfarm/config/CosConfig.java
new file mode 100644
index 0000000..20694de
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/CosConfig.java
@@ -0,0 +1,33 @@
+package com.sunnyfarm.config;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.region.Region;
+import com.sunnyfarm.config.properties.CosProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CosConfig {
+
+ @Autowired
+ private CosProperties cosProperties;
+
+ @Bean
+ public COSClient cosClient() {
+ // 初始化用户身份信息(secretId, secretKey)
+ COSCredentials cred = new BasicCOSCredentials(
+ cosProperties.getSecretId(),
+ cosProperties.getSecretKey()
+ );
+
+ // 设置bucket的区域
+ ClientConfig clientConfig = new ClientConfig(new Region(cosProperties.getRegion()));
+
+ // 生成cos客户端
+ return new COSClient(cred, clientConfig);
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/MybatisPlusConfig.java b/backend/src/main/java/com/sunnyfarm/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..d21927d
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/MybatisPlusConfig.java
@@ -0,0 +1,21 @@
+package com.sunnyfarm.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@MapperScan("com.sunnyfarm.mapper")
+public class MybatisPlusConfig {
+
+ @Bean
+ public MybatisPlusInterceptor mybatisPlusInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ // 分页插件
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/PasswordConfig.java b/backend/src/main/java/com/sunnyfarm/config/PasswordConfig.java
new file mode 100644
index 0000000..e9de3b8
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/PasswordConfig.java
@@ -0,0 +1,15 @@
+package com.sunnyfarm.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+public class PasswordConfig {
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/WebConfig.java b/backend/src/main/java/com/sunnyfarm/config/WebConfig.java
new file mode 100644
index 0000000..d4f7ae3
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/WebConfig.java
@@ -0,0 +1,93 @@
+package com.sunnyfarm.config;
+
+import com.sunnyfarm.interceptor.JwtAuthInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.Arrays;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private JwtAuthInterceptor jwtAuthInterceptor;
+
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedOriginPatterns("*")
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+ .allowedHeaders("*")
+ .allowCredentials(true)
+ .maxAge(3600);
+ }
+
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration configuration = new CorsConfiguration();
+ configuration.setAllowedOriginPatterns(Arrays.asList("*"));
+ configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
+ configuration.setAllowedHeaders(Arrays.asList("*"));
+ configuration.setAllowCredentials(true);
+ configuration.setMaxAge(3600L);
+
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", configuration);
+ return source;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(jwtAuthInterceptor)
+ .addPathPatterns("/**")
+ .excludePathPatterns(
+ // 用户认证相关
+ "/api/user/login",
+ "/api/user/register",
+ "/api/user/send-code",
+ "/api/user/send-email-code", // 新增:邮箱验证码接口
+ "/api/user/verify-code",
+ // 商家认证相关
+ "/api/merchant/register",
+ "/api/merchant/login",
+ // 管理员认证相关
+ "/api/admin/login",
+ // 公开接口 - 商品分类
+ "/api/category/**",
+ // 公开接口 - 商品相关(用户端公共访问)
+ "/api/product/list",
+ "/api/product/*/detail",
+ "/api/product/hot",
+ "/api/product/search",
+ // 初始化和测试接口
+ "/api/init/**",
+ // 公共接口 - 公告相关
+ "/api/announcements/published",
+ "/api/announcements/latest",
+ "/api/announcements/*/detail",
+ "/api/test/**",
+ // 支付回调(无需认证)
+ "/api/payment/alipay/notify",
+ "/api/payment/alipay/return",
+ // 系统相关
+ "/error",
+ "/favicon.ico",
+ // 静态资源
+ "/**/*.css",
+ "/**/*.js",
+ "/**/*.png",
+ "/**/*.jpg",
+ "/**/*.jpeg",
+ "/**/*.gif",
+ "/**/*.ico",
+ "/**/*.html"
+ );
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/properties/AlipayProperties.java b/backend/src/main/java/com/sunnyfarm/config/properties/AlipayProperties.java
new file mode 100644
index 0000000..6c73d99
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/properties/AlipayProperties.java
@@ -0,0 +1,37 @@
+package com.sunnyfarm.config.properties;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+public class AlipayProperties {
+
+ @Value("${alipay.app-id}")
+ private String appId;
+
+ @Value("${alipay.app-private-key}")
+ private String appPrivateKey;
+
+ @Value("${alipay.alipay-public-key}")
+ private String alipayPublicKey;
+
+ @Value("${alipay.server-url}")
+ private String serverUrl;
+
+ @Value("${alipay.format}")
+ private String format;
+
+ @Value("${alipay.charset}")
+ private String charset;
+
+ @Value("${alipay.sign-type}")
+ private String signType;
+
+ @Value("${alipay.notify-url}")
+ private String notifyUrl;
+
+ @Value("${alipay.return-url}")
+ private String returnUrl;
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/properties/CosProperties.java b/backend/src/main/java/com/sunnyfarm/config/properties/CosProperties.java
new file mode 100644
index 0000000..e08ba80
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/properties/CosProperties.java
@@ -0,0 +1,25 @@
+package com.sunnyfarm.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "tencent.cos")
+public class CosProperties {
+ private String region;
+ private String bucket;
+ private String secretId;
+ private String secretKey;
+ private String baseUrl;
+ private String cdnUrl;
+ private Boolean cdnEnabled = false;
+
+ /**
+ * 获取实际使用的URL(CDN优先)
+ */
+ public String getActualUrl() {
+ return (cdnEnabled != null && cdnEnabled && cdnUrl != null) ? cdnUrl : baseUrl;
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/config/properties/EmailProperties.java b/backend/src/main/java/com/sunnyfarm/config/properties/EmailProperties.java
new file mode 100644
index 0000000..0979003
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/config/properties/EmailProperties.java
@@ -0,0 +1,14 @@
+package com.sunnyfarm.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "system.email")
+public class EmailProperties {
+ private boolean enabled = true;
+ private String from;
+ private String fromName;
+}
diff --git a/backend/src/main/java/com/sunnyfarm/controller/AddressController.java b/backend/src/main/java/com/sunnyfarm/controller/AddressController.java
new file mode 100644
index 0000000..0fcaa8b
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/controller/AddressController.java
@@ -0,0 +1,129 @@
+package com.sunnyfarm.controller;
+
+import com.sunnyfarm.common.Result;
+import com.sunnyfarm.entity.Address;
+import com.sunnyfarm.service.AddressService;
+import com.sunnyfarm.util.UserContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/address")
+@CrossOrigin
+public class AddressController {
+
+ @Autowired
+ private AddressService addressService;
+
+ /**
+ * 获取用户地址列表
+ */
+ @GetMapping("/list")
+ public Result> getAddressList() {
+ Long userId = UserContext.getCurrentUserId();
+ List addresses = addressService.getUserAddresses(userId);
+ return Result.success(addresses);
+ }
+
+ /**
+ * 获取用户默认地址
+ */
+ @GetMapping("/default")
+ public Result getDefaultAddress() {
+ Long userId = UserContext.getCurrentUserId();
+ Address address = addressService.getUserDefaultAddress(userId);
+ return Result.success(address);
+ }
+
+ /**
+ * 获取地址详情
+ */
+ @GetMapping("/{id}")
+ public Result getAddressDetail(@PathVariable Long id) {
+ Address address = addressService.getById(id);
+ if (address != null) {
+ return Result.success(address);
+ } else {
+ return Result.error("地址不存在");
+ }
+ }
+
+ /**
+ * 创建地址
+ */
+ @PostMapping("/create")
+ public Result createAddress(@RequestBody Address address) {
+ try {
+ Long userId = UserContext.getCurrentUserId();
+ address.setUserId(userId);
+
+ Address createdAddress = addressService.createAddress(address);
+ return Result.success("地址创建成功", createdAddress);
+ } catch (Exception e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 更新地址
+ */
+ @PutMapping("/{id}")
+ public Result updateAddress(@PathVariable Long id, @RequestBody Address address) {
+ try {
+ Long userId = UserContext.getCurrentUserId();
+ address.setUserId(userId);
+
+ Address updatedAddress = addressService.updateAddress(id, address);
+ return Result.success("地址更新成功", updatedAddress);
+ } catch (Exception e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 删除地址
+ */
+ @DeleteMapping("/{id}")
+ public Result deleteAddress(@PathVariable Long id) {
+ try {
+ boolean success = addressService.deleteAddress(id);
+ if (success) {
+ return Result.success("地址删除成功");
+ } else {
+ return Result.error("地址删除失败");
+ }
+ } catch (Exception e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 设置默认地址
+ */
+ @PutMapping("/{id}/default")
+ public Result setDefaultAddress(@PathVariable Long id) {
+ try {
+ Long userId = UserContext.getCurrentUserId();
+ boolean success = addressService.setDefaultAddress(userId, id);
+ if (success) {
+ return Result.success("默认地址设置成功");
+ } else {
+ return Result.error("默认地址设置失败");
+ }
+ } catch (Exception e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 获取用户地址数量
+ */
+ @GetMapping("/count")
+ public Result getAddressCount() {
+ Long userId = UserContext.getCurrentUserId();
+ Long count = addressService.getUserAddressCount(userId);
+ return Result.success(count);
+ }
+}
diff --git a/backend/src/main/java/com/sunnyfarm/controller/AdminController.java b/backend/src/main/java/com/sunnyfarm/controller/AdminController.java
new file mode 100644
index 0000000..44c61aa
--- /dev/null
+++ b/backend/src/main/java/com/sunnyfarm/controller/AdminController.java
@@ -0,0 +1,631 @@
+package com.sunnyfarm.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.sunnyfarm.common.PageResult;
+import com.sunnyfarm.common.Result;
+import com.sunnyfarm.dto.AdminLoginRequest;
+import com.sunnyfarm.dto.AdminUpdateRequest;
+import com.sunnyfarm.dto.AdminPasswordRequest;
+import com.sunnyfarm.entity.*;
+import com.sunnyfarm.service.*;
+import com.sunnyfarm.util.JwtUtil;
+import com.sunnyfarm.util.UserContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/admin")
+@CrossOrigin
+public class AdminController {
+
+ @Autowired
+ private AdminService adminService;
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private MerchantService merchantService;
+
+ @Autowired
+ private ProductService productService;
+
+ @Autowired
+ private OrderService orderService;
+
+ @Autowired
+ private StatisticsService statisticsService;
+
+ @Autowired
+ private SystemLogService systemLogService;
+
+ @Autowired
+ private SystemConfigService systemConfigService;
+
+ @Autowired
+ private AnnouncementService announcementService;
+
+ @Autowired
+ private JwtUtil jwtUtil;
+
+ /**
+ * 管理员登录
+ */
+ @PostMapping("/login")
+ public Result