diff --git a/.cursor/rules/backend.mdc b/.cursor/rules/backend.mdc
index 49cdf5cdab..8ba3f5006a 100644
--- a/.cursor/rules/backend.mdc
+++ b/.cursor/rules/backend.mdc
@@ -20,12 +20,121 @@ globs: **/*.java, **/*.xml, **/*.yaml, **/*.yml
- **VO 层**: 视图对象,用于前后端交互
- **DO 层**: 数据对象,对应数据库表
+## 目录结构规范
+
+### 模块目录结构
+
+业务模块的标准目录结构如下:
+
+```
+yudao-module-{模块名}/
+└── src/main/java/cn/iocoder/yudao/module/{模块名}/
+ ├── controller/ # Controller 层
+ │ └── {Xxx}Controller.java
+ ├── service/ # Service 层
+ │ ├── {Xxx}Service.java # Service 接口
+ │ ├── {Xxx}ServiceImpl.java # Service 实现类
+ │ └── {Xxx}Util.java # Service 工具类(可选)
+ ├── mapper/ # Mapper 层
+ │ └── {Xxx}Mapper.java
+ ├── dataobject/ # DO 对象(可选)
+ │ └── {Xxx}DO.java
+ ├── vo/ # VO 对象
+ │ ├── {Xxx}SaveReqVO.java
+ │ ├── {Xxx}PageReqVO.java
+ │ ├── {Xxx}UpdateReqVO.java
+ │ └── {Xxx}RespVO.java
+ ├── enums/ # 枚举类(可选)
+ │ └── {Xxx}Enum.java
+ └── mq/ # 消息队列(可选)
+ └── consumer/
+ └── {Xxx}Consumer.java
+```
+
+### 目录结构说明
+
+- **mapper/**: Mapper 接口,继承 `BaseMapperX`
+- **dataobject/**: DO 对象(可选),继承 `BaseDO` 或 `TenantBaseDO`
+- 如果模块没有 DO 对象,可以省略 `dataobject/` 包
+
+### 包命名规范
+
+#### Controller 包
+- Controller 类名:`{Xxx}Controller` 或 `App{Xxx}Controller`
+- 直接放在 `controller/` 包下
+
+#### Service 包
+- Service 接口:`{Xxx}Service.java`
+- Service 实现:`{Xxx}ServiceImpl.java`
+- Service 工具类:`{Xxx}Util.java` 或 `{Xxx}Helper.java`
+
+#### Mapper 包
+- Mapper 接口:`mapper/{Xxx}Mapper.java`
+- Mapper 接口继承 `BaseMapperX`
+
+#### DO 包
+- DO 对象:`dataobject/{Xxx}DO.java`(可选)
+- DO 类名:`{Xxx}DO.java`
+- 继承 `BaseDO` 或 `TenantBaseDO`
+
+#### VO 包
+- Request VO: `{Xxx}SaveReqVO`、`{Xxx}PageReqVO`、`{Xxx}UpdateReqVO`
+- Response VO: `{Xxx}RespVO`
+- App VO: `App{Xxx}ReqVO`、`App{Xxx}RespVO`
+- 直接放在 `vo/` 包下
+
+### 目录结构示例
+
+#### 示例 1:简单模块(tikhup)
+```
+tikhup/
+├── controller/
+│ └── TikHupController.java
+├── service/
+│ ├── TikHupService.java
+│ ├── TikHupServiceImpl.java
+│ └── TikFileTransCharacters.java
+├── mapper/
+│ ├── TikPromptMapper.java
+│ └── TikTokenMapper.java
+└── vo/
+ ├── TikPromptVO.java
+ └── TikTokenVO.java
+```
+
+#### 示例 2:完整模块(file)
+```
+file/
+├── controller/
+│ ├── AppTikUserFileController.java
+│ ├── AppTikFileGroupController.java
+│ └── AppTikTestController.java
+├── service/
+│ ├── TikUserFileService.java
+│ ├── TikUserFileServiceImpl.java
+│ ├── TikFileGroupService.java
+│ └── TikFileGroupServiceImpl.java
+├── mapper/
+│ ├── TikUserFileMapper.java
+│ └── TikFileGroupMapper.java
+├── vo/
+│ ├── AppTikUserFilePageReqVO.java
+│ ├── AppTikUserFileRespVO.java
+│ └── AppTikFileGroupCreateReqVO.java
+└── enums/
+ └── TikFileCategoryEnum.java
+```
+
+### 目录结构原则
+
+1. **统一性**:同一模块内保持结构一致
+2. **简洁性**:使用 `mapper/` 和 `dataobject/` 包,结构清晰
+3. **可选性**:没有 DO 对象时可以省略 `dataobject/` 包
+4. **可扩展性**:预留扩展空间,便于后续功能扩展
+
## Controller 层规范
-### 包结构
-- `controller.admin.*`: 管理后台接口
-- `controller.app.*`: 用户端接口(C 端)
-- App Controller 和 VO 必须添加 `App` 前缀
+
### 注解使用
- 使用 `@RestController` 而非 `@Controller`
@@ -260,7 +369,7 @@ public UserPromptDO getUserPrompt(Long id) {
### 路径前缀
- 管理后台:`/admin-api`
-- 用户端:`/app-api`
+- 用户端:`/api`
- Controller 路径:`/模块/资源`,如 `/ai/user-prompt`
### HTTP 方法
diff --git a/frontend/app/web-gold/src/api/material.js b/frontend/app/web-gold/src/api/material.js
index d99ec401cb..ce58eedc38 100644
--- a/frontend/app/web-gold/src/api/material.js
+++ b/frontend/app/web-gold/src/api/material.js
@@ -39,10 +39,9 @@ export const MaterialService = {
const formData = new FormData()
formData.append('file', file)
formData.append('fileCategory', fileCategory)
+ // 大文件上传需要更长的超时时间(30分钟)
return http.post(`${BASE_URL}/upload`, formData, {
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
+ timeout: 30 * 60 * 1000 // 30分钟
})
},
diff --git a/frontend/app/web-gold/src/components/material/MaterialUploadModal.vue b/frontend/app/web-gold/src/components/material/MaterialUploadModal.vue
index ca46bae2c9..ee14966859 100644
--- a/frontend/app/web-gold/src/components/material/MaterialUploadModal.vue
+++ b/frontend/app/web-gold/src/components/material/MaterialUploadModal.vue
@@ -25,7 +25,7 @@
点击或拖拽文件到此处上传
- 支持多文件上传,单个文件不超过 500MB
+ 支持多文件上传,单个文件不超过 100MB
支持格式:视频(MP4、MOV、AVI等)、图片(JPG、PNG、GIF等)、音频(MP3、WAV等)
@@ -63,7 +63,7 @@
{{ uploading ? '上传中...' : `上传 (${fileList.length})` }}
@@ -94,16 +94,16 @@ const emit = defineEmits(['update:visible', 'confirm', 'cancel'])
// 数据
const fileList = ref([])
-const fileCategory = ref('video') // 文件分类,默认为视频集
+// 文件分类使用默认值,不再在UI中显示
+const DEFAULT_FILE_CATEGORY = 'video'
// 支持的文件类型
const acceptTypes = 'video/*,image/*,audio/*,.mp4,.mov,.avi,.mkv,.jpg,.jpeg,.png,.gif,.webp,.mp3,.wav,.aac'
-// 监听 visible 变化,重置文件列表和分类
+// 监听 visible 变化,重置文件列表
watch(() => props.visible, (newVal) => {
if (!newVal) {
fileList.value = []
- fileCategory.value = 'video' // 重置为默认分类
}
})
@@ -134,9 +134,9 @@ const formatFileSize = (bytes) => {
// 上传前处理
const handleBeforeUpload = (file) => {
- // 检查文件大小(500MB)
- if (file.size > 500 * 1024 * 1024) {
- message.warning(`文件 ${file.name} 超过 500MB,已跳过`)
+ // 检查文件大小(100MB)
+ if (file.size > 100 * 1024 * 1024) {
+ message.warning(`文件 ${file.name} 超过 100MB,已跳过`)
return false
}
@@ -214,12 +214,8 @@ const handleConfirm = () => {
return
}
- if (!fileCategory.value) {
- message.warning('请选择文件分类')
- return
- }
-
- emit('confirm', files, fileCategory.value)
+ // 使用默认分类
+ emit('confirm', files, DEFAULT_FILE_CATEGORY)
}
// 处理 visible 变化
@@ -239,16 +235,6 @@ const handleCancel = () => {
padding: 8px 0;
}
-.upload-category-select {
- margin-bottom: 24px;
-}
-
-.upload-label {
- margin-bottom: 8px;
- font-weight: 500;
- color: var(--color-text);
-}
-
.upload-area {
margin-bottom: 24px;
}
diff --git a/frontend/app/web-gold/src/views/material/MaterialList.vue b/frontend/app/web-gold/src/views/material/MaterialList.vue
index b8928e3150..8ea8602772 100644
--- a/frontend/app/web-gold/src/views/material/MaterialList.vue
+++ b/frontend/app/web-gold/src/views/material/MaterialList.vue
@@ -148,7 +148,6 @@ const uploading = ref(false)
// 筛选条件
const filters = reactive({
- fileCategory: undefined,
fileName: '',
createTime: undefined
})
@@ -204,11 +203,6 @@ const handleConfirmUpload = async (files, fileCategory) => {
return
}
- if (!fileCategory) {
- message.warning('请选择文件分类')
- return
- }
-
uploading.value = true
let successCount = 0
let failCount = 0
@@ -289,7 +283,6 @@ const handleFilterChange = () => {
}
const handleResetFilters = () => {
- filters.fileCategory = undefined
filters.fileName = ''
filters.createTime = undefined
pagination.pageNo = 1
diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml
index f599ba39e9..98315b3424 100644
--- a/yudao-server/src/main/resources/application.yaml
+++ b/yudao-server/src/main/resources/application.yaml
@@ -12,8 +12,8 @@ spring:
servlet:
# 文件上传相关配置项
multipart:
- max-file-size: 16MB # 单个文件大小
- max-request-size: 32MB # 设置总上传的文件大小
+ max-file-size: 100MB # 单个文件大小
+ max-request-size: 200MB # 设置总上传的文件大小(支持多文件上传)
# Jackson 配置项
jackson:
@@ -348,4 +348,4 @@ yudao:
message-bus:
type: redis # 消息总线的类型
-debug: false
\ No newline at end of file
+debug: false