diff --git a/ruoyi-ui/CONTENT_MODULE_README.md b/ruoyi-ui/CONTENT_MODULE_README.md
new file mode 100644
index 0000000..7d41d5e
--- /dev/null
+++ b/ruoyi-ui/CONTENT_MODULE_README.md
@@ -0,0 +1,168 @@
+# 内容管理模块
+
+## 功能概述
+
+内容管理模块包含以下三个子模块:
+- **分类管理**:管理内容分类,支持分类名称和分类图片
+- **标签管理**:管理内容标签,支持标签名称
+- **Banner管理**:管理轮播图,支持名称、排序、跳转链接和图片
+
+## 文件结构
+
+```
+src/
+├── api/content/
+│ ├── category.js # 分类管理API
+│ ├── tag.js # 标签管理API
+│ └── banner.js # Banner管理API
+└── views/content/
+ ├── category/
+ │ └── index.vue # 分类管理页面
+ ├── tag/
+ │ └── index.vue # 标签管理页面
+ └── banner/
+ └── index.vue # Banner管理页面
+```
+
+## 后端接口
+
+### 分类管理接口
+- 列表查询:`GET /back/category/list`
+- 新增分类:`POST /back/category` (FormData格式)
+- 修改分类:`PUT /back/category` (FormData格式)
+- 删除分类:`DELETE /back/category/{id}`
+
+### 标签管理接口
+- 列表查询:`GET /back/tag/list`
+- 新增标签:`POST /back/tag`
+- 修改标签:`PUT /back/tag`
+- 删除标签:`DELETE /back/tag/{id}`
+
+### Banner管理接口
+- 列表查询:`GET /back/banner/list`
+- 新增Banner:`POST /back/banner/add` (FormData格式)
+- 修改Banner:`PUT /back/banner` (FormData格式)
+- 删除Banner:`DELETE /back/banner/{id}`
+
+## 图片处理说明
+
+### 图片上传方式
+- **不再预先上传**:图片不会先上传到服务器
+- **直接提交**:图片作为二进制文件直接随表单提交到后端
+- **本地预览**:使用 `URL.createObjectURL()` 创建本地预览
+- **FormData格式**:使用 `multipart/form-data` 格式提交
+
+### 图片显示方式
+- **字段映射**:
+ - 分类管理:使用 `backImg` 字段
+ - Banner管理:使用 `imageUrl` 字段
+- **URL拼接**:后端返回图片路径,前端拼接完整URL
+- **工具方法**:使用 `src/utils/image.js` 中的 `getImageUrl()` 方法
+
+### 请求格式示例
+```javascript
+// 分类新增请求
+const formData = new FormData()
+formData.append('name', '分类名称')
+formData.append('file', fileObject) // 文件对象
+
+// Banner新增请求
+const formData = new FormData()
+formData.append('name', 'Banner名称')
+formData.append('sort', '1')
+formData.append('jumpUrl', 'https://example.com')
+formData.append('file', fileObject) // 文件对象
+```
+
+### 图片URL处理示例
+```javascript
+// 后端返回数据
+{
+ "id": 1,
+ "name": "分类名称",
+ "backImg": "/upload/category/image.jpg" // 图片路径
+}
+
+// 前端显示
+const fullUrl = getImageUrl(backImg)
+// 结果: "http://60.205.107.210:8080/upload/category/image.jpg"
+```
+
+## 安装步骤
+
+### 1. 执行菜单SQL
+在数据库中执行 `content_menu.sql` 文件,创建菜单和权限配置。
+
+### 2. 重启前端服务
+```bash
+npm run dev
+```
+
+### 3. 分配权限
+登录系统后,在角色管理中为相应角色分配内容管理模块的权限。
+
+## 功能特性
+
+### 分类管理
+- ✅ 分类列表展示(支持分页)
+- ✅ 分类搜索(按名称)
+- ✅ 新增分类(支持图片上传)
+- ✅ 编辑分类
+- ✅ 删除分类
+- ✅ 图片预览
+
+### 标签管理
+- ✅ 标签列表展示(支持分页)
+- ✅ 标签搜索(按名称)
+- ✅ 新增标签
+- ✅ 编辑标签
+- ✅ 删除标签
+
+### Banner管理
+- ✅ Banner列表展示(支持分页)
+- ✅ Banner搜索(按名称)
+- ✅ 新增Banner(支持图片上传)
+- ✅ 编辑Banner
+- ✅ 删除Banner
+- ✅ 图片预览
+- ✅ 排序功能
+
+## 注意事项
+
+1. **图片上传**:分类和Banner模块支持图片上传,图片直接作为二进制流传给后端。
+
+2. **FormData格式**:分类和Banner的新增/修改接口使用FormData格式,标签管理使用JSON格式。
+
+3. **权限控制**:所有操作都有相应的权限控制,需要在角色管理中分配权限。
+
+4. **分页支持**:所有列表都支持分页查询。
+
+5. **文件大小限制**:图片大小限制为2MB,支持JPG/PNG/GIF格式。
+
+## 常见问题
+
+### Q: 图片上传失败怎么办?
+A: 检查以下几点:
+- 图片格式是否为JPG/PNG/GIF
+- 图片大小是否超过2MB
+- 网络连接是否正常
+- 后端接口是否正常接收FormData格式
+
+### Q: 菜单不显示怎么办?
+A: 检查以下几点:
+- 是否执行了菜单SQL
+- 当前用户角色是否有相应权限
+- 是否刷新了页面
+
+### Q: 接口调用失败怎么办?
+A: 检查以下几点:
+- 后端服务是否正常运行
+- 接口地址是否正确
+- 网络连接是否正常
+- 请求参数格式是否正确
+
+### Q: 图片预览不显示怎么办?
+A: 检查以下几点:
+- 文件是否成功选择
+- 浏览器是否支持 `URL.createObjectURL()`
+- 图片格式是否正确
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/content/banner.js b/ruoyi-ui/src/api/content/banner.js
new file mode 100644
index 0000000..e01a472
--- /dev/null
+++ b/ruoyi-ui/src/api/content/banner.js
@@ -0,0 +1,73 @@
+import request from '@/utils/request'
+
+// 查询Banner列表
+export function listBanner(query) {
+ return request({
+ url: '/back/banner/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询Banner详细
+export function getBanner(id) {
+ return request({
+ url: '/back/banner/' + id,
+ method: 'get'
+ })
+}
+
+// 新增Banner
+export function addBanner(data) {
+ const formData = new FormData()
+ formData.append('name', data.name)
+ formData.append('sort', data.sort)
+ formData.append('jumpUrl', data.jumpUrl || '')
+ if (data.file) {
+ formData.append('file', data.file)
+ }
+ return request({
+ url: '/back/banner/add',
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+}
+
+// 修改Banner
+export function updateBanner(data) {
+ const formData = new FormData()
+ formData.append('id', data.id)
+ formData.append('name', data.name)
+ formData.append('sort', data.sort)
+ formData.append('jumpUrl', data.jumpUrl || '')
+
+ // 如果有新图片文件,上传新图片
+ if (data.file) {
+ formData.append('file', data.file)
+ }
+
+ // 传递图片路径(原图片或新图片的路径)
+ if (data.bannerAddr) {
+ formData.append('bannerAddr', data.bannerAddr)
+ }
+
+ return request({
+ url: '/back/banner/update',
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+}
+
+// 删除Banner
+export function delBanner(id) {
+ return request({
+ url: '/back/banner/' + id,
+ method: 'delete'
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/content/category.js b/ruoyi-ui/src/api/content/category.js
new file mode 100644
index 0000000..27c65a7
--- /dev/null
+++ b/ruoyi-ui/src/api/content/category.js
@@ -0,0 +1,69 @@
+import request from '@/utils/request'
+
+// 查询分类列表
+export function listCategory(query) {
+ return request({
+ url: '/back/category/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询分类详细
+export function getCategory(id) {
+ return request({
+ url: '/back/category/' + id,
+ method: 'get'
+ })
+}
+
+// 新增分类
+export function addCategory(data) {
+ const formData = new FormData()
+ formData.append('name', data.name)
+ if (data.file) {
+ formData.append('file', data.file)
+ }
+ return request({
+ url: '/back/category',
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+}
+
+// 修改分类
+export function updateCategory(data) {
+ const formData = new FormData()
+ formData.append('id', data.id)
+ formData.append('name', data.name)
+
+ // 如果有新图片文件,上传新图片
+ if (data.file) {
+ formData.append('file', data.file)
+ }
+
+ // 传递图片路径(原图片或新图片的路径)
+ if (data.backImg) {
+ formData.append('backImg', data.backImg)
+ }
+
+ return request({
+ url: '/back/category/update',
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+}
+
+// 删除分类
+export function delCategory(id) {
+ return request({
+ url: '/back/category/' + id,
+ method: 'delete'
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/content/tag.js b/ruoyi-ui/src/api/content/tag.js
new file mode 100644
index 0000000..ed23476
--- /dev/null
+++ b/ruoyi-ui/src/api/content/tag.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询标签列表
+export function listTag(query) {
+ return request({
+ url: '/back/tag/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询标签详细
+export function getTag(id) {
+ return request({
+ url: '/back/tag/' + id,
+ method: 'get'
+ })
+}
+
+// 新增标签
+export function addTag(data) {
+ return request({
+ url: '/back/tag',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改标签
+export function updateTag(data) {
+ return request({
+ url: '/back/tag',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除标签
+export function delTag(id) {
+ return request({
+ url: '/back/tag/' + id,
+ method: 'delete'
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/utils/image.js b/ruoyi-ui/src/utils/image.js
new file mode 100644
index 0000000..74a37bb
--- /dev/null
+++ b/ruoyi-ui/src/utils/image.js
@@ -0,0 +1,34 @@
+/**
+ * 图片工具类
+ */
+
+/**
+ * 获取图片完整URL
+ * @param {string} imagePath 图片路径
+ * @returns {string} 完整的图片URL
+ */
+export function getImageUrl(imagePath) {
+ if (!imagePath) {
+ return '';
+ }
+
+ // 如果已经是完整URL,直接返回
+ if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
+ return imagePath;
+ }
+
+ // 使用项目的API前缀配置
+ const baseApi = process.env.VUE_APP_BASE_API || '/dev-api';
+ return baseApi + imagePath;
+}
+
+/**
+ * 获取图片完整URL(带默认图片)
+ * @param {string} imagePath 图片路径
+ * @param {string} defaultImage 默认图片路径
+ * @returns {string} 完整的图片URL
+ */
+export function getImageUrlWithDefault(imagePath, defaultImage = '') {
+ const url = getImageUrl(imagePath);
+ return url || defaultImage;
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/content/banner/index.vue b/ruoyi-ui/src/views/content/banner/index.vue
new file mode 100644
index 0000000..a20d197
--- /dev/null
+++ b/ruoyi-ui/src/views/content/banner/index.vue
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}
+
+
+
+
+ 修改
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/content/category/index.vue b/ruoyi-ui/src/views/content/category/index.vue
new file mode 100644
index 0000000..2a95cf1
--- /dev/null
+++ b/ruoyi-ui/src/views/content/category/index.vue
@@ -0,0 +1,320 @@
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}
+
+
+
+
+ 修改
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/content/tag/index.vue b/ruoyi-ui/src/views/content/tag/index.vue
new file mode 100644
index 0000000..4d762e2
--- /dev/null
+++ b/ruoyi-ui/src/views/content/tag/index.vue
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}
+
+
+
+
+ 修改
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index 40e140d..cdec3f1 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
-const baseUrl = 'http://localhost:8080' // 后端接口
+const baseUrl = 'http://60.205.107.210:8080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口