更新本地js
This commit is contained in:
@@ -82,7 +82,7 @@ public class BizFiles implements Serializable {
|
||||
* 是否删除(0-未删除,1-已删除)
|
||||
*/
|
||||
@TableField("is_deleted")
|
||||
private Byte isDeleted;
|
||||
private Integer isDeleted;
|
||||
|
||||
/**
|
||||
* 文件版本号(用于版本控制)
|
||||
|
||||
@@ -13,6 +13,7 @@ import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -152,8 +153,13 @@ public class viewController {
|
||||
*/
|
||||
|
||||
@GetMapping("/biz/dataDoc")
|
||||
public String getDataDox(Model model) {
|
||||
List<BizFiles> files = filesService.list();
|
||||
public String getDataDox(Model model, String folderId) {
|
||||
QueryWrapper<BizFiles> fileWrapper = new QueryWrapper<>();
|
||||
fileWrapper.eq("is_deleted", "0");
|
||||
if (StringUtils.hasText(folderId)) {
|
||||
fileWrapper.eq("folder_id", folderId);
|
||||
}
|
||||
List<BizFiles> files = filesService.list(fileWrapper);
|
||||
List<FolderTree> folderTrees = new ArrayList<>();
|
||||
QueryWrapper<BizFileFolders> parentWrapper = new QueryWrapper<>();
|
||||
parentWrapper.eq("parent_id", "0");
|
||||
@@ -164,7 +170,14 @@ public class viewController {
|
||||
List<BizFileFolders> childFolders = foldersService.list(childWrapper);
|
||||
folderTrees.add(new FolderTree(fileFolder, childFolders));
|
||||
}
|
||||
|
||||
QueryWrapper<BizFileFolders> uploadWrapper = new QueryWrapper<>();
|
||||
uploadWrapper.ne("parent_id", 0);
|
||||
List<BizFileFolders> uploadFolder = foldersService.list(uploadWrapper);
|
||||
|
||||
|
||||
model.addAttribute("files", files);
|
||||
model.addAttribute("uploadFolder", uploadFolder);
|
||||
model.addAttribute("folderTrees", folderTrees);
|
||||
return "file";
|
||||
}
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
package com.mini.capi.biz;
|
||||
|
||||
import com.mini.capi.biz.domain.BizFileFolders;
|
||||
import com.mini.capi.biz.domain.BizFiles;
|
||||
import com.mini.capi.biz.domain.BizSubTask;
|
||||
import com.mini.capi.biz.service.BizFileFoldersService;
|
||||
import com.mini.capi.biz.service.BizFilesService;
|
||||
import com.mini.capi.biz.service.BizSubTaskService;
|
||||
import com.mini.capi.model.ApiResult;
|
||||
import com.mini.capi.model.CreateFolder;
|
||||
import com.mini.capi.model.info.TodoHandleDTO;
|
||||
import com.mini.capi.utils.FileUtils;
|
||||
import com.mini.capi.utils.vId;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/biz")
|
||||
@@ -20,6 +31,14 @@ public class workController {
|
||||
@Resource
|
||||
private BizSubTaskService bizSubTaskService;
|
||||
|
||||
@Resource
|
||||
private BizFileFoldersService bizFileFoldersService;
|
||||
|
||||
@Resource
|
||||
private BizFilesService bizFilesService;
|
||||
|
||||
private static String UPLOAD_PATH = "/ogsapp/files/";
|
||||
|
||||
|
||||
/**
|
||||
* 完成待办
|
||||
@@ -45,4 +64,72 @@ public class workController {
|
||||
return ResponseEntity.status(500).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建文件夹
|
||||
*/
|
||||
@PostMapping("/CreateFolder")
|
||||
public ApiResult<?> CreateFolder(@Validated @RequestBody CreateFolder request) {
|
||||
try {
|
||||
String dirId = vId.getCid();
|
||||
BizFileFolders folders = new BizFileFolders();
|
||||
folders.setFolderId(dirId);
|
||||
folders.setFolderName(request.getName());
|
||||
folders.setParentId(request.getParentId());
|
||||
bizFileFoldersService.save(folders);
|
||||
FileUtils.checkDirExists(UPLOAD_PATH + dirId);
|
||||
return ApiResult.success();
|
||||
} catch (Exception e) {
|
||||
// 异常捕获,返回失败响应
|
||||
return ApiResult.error(101, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("uploadFiles")
|
||||
public ResponseEntity<Map<String, Object>> uploadFiles(
|
||||
@RequestParam(value = "folderId") String folderId,
|
||||
@RequestParam("files") MultipartFile[] files) {
|
||||
// 响应结果集
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
Path basePath = Paths.get(UPLOAD_PATH + folderId);
|
||||
FileUtils.checkDirExists(basePath.toString());
|
||||
// 统计成功/失败数量
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
// 遍历上传的文件
|
||||
for (MultipartFile file : files) {
|
||||
BizFiles bizFiles = new BizFiles();
|
||||
try {
|
||||
// 1. 获取原始文件名和后缀
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
|
||||
// 2. 生成唯一文件名(避免文件名冲突)
|
||||
String uniqueFileName = vId.getCid() + fileSuffix;
|
||||
// 3. 构建文件存储路径
|
||||
Path filePath = basePath.resolve(uniqueFileName);
|
||||
// 4. 保存文件到本地磁盘
|
||||
file.transferTo(filePath.toFile());
|
||||
bizFiles.setFileName(originalFilename);
|
||||
bizFiles.setFolderId(folderId);
|
||||
bizFiles.setFileSize(file.getSize());
|
||||
bizFiles.setFileType(fileSuffix);
|
||||
bizFiles.setFilePath(filePath.toString());
|
||||
bizFiles.setCreatorId(0);
|
||||
bizFiles.setIsDeleted(0);
|
||||
bizFilesService.save(bizFiles);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
System.err.print(e.getMessage());
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
// 构建响应结果
|
||||
result.put("success", true);
|
||||
result.put("message", "上传成功");
|
||||
result.put("successCount", successCount);
|
||||
result.put("failCount", failCount);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
13
src/main/java/com/mini/capi/model/CreateFolder.java
Normal file
13
src/main/java/com/mini/capi/model/CreateFolder.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.mini.capi.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class CreateFolder implements Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private String parentId;
|
||||
}
|
||||
@@ -19,7 +19,6 @@ public class LoggerUtils {
|
||||
// 单例实例
|
||||
private static volatile LoggerUtils instance;
|
||||
|
||||
// 日志文件根路径(默认:/ogsapp/logs/cApi)
|
||||
private String baseLogPath;
|
||||
|
||||
// 日期格式(文件名:yyyyMMdd,日志内容时间戳:yyyy-MM-dd HH:mm:ss.SSS)
|
||||
|
||||
@@ -24,4 +24,12 @@ public class vId {
|
||||
return tm + String.format("%015d", rand);
|
||||
}
|
||||
|
||||
|
||||
public static String getCid() {
|
||||
// 17 位时间
|
||||
String tm = LocalDateTime.now().format(DF);
|
||||
// 25 位随机数字(高位补零)
|
||||
long rand = Math.abs(RAND.nextLong()) % (long) Math.pow(3, 6);
|
||||
return tm + String.format("%04d", rand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>文档中心</title>
|
||||
<!-- Tailwind CSS v3 -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- Font Awesome -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
|
||||
<script th:src="@{/css/tailwindcss.css}"></script>
|
||||
<link th:href="@{/font-awesome/css/font-awesome.min.css}" rel="stylesheet">
|
||||
|
||||
<!-- 统一的 Tailwind 配置 -->
|
||||
<script>
|
||||
tailwind.config = {
|
||||
@@ -132,22 +132,33 @@
|
||||
<!-- 文件夹列表 -->
|
||||
<div class="flex-grow overflow-y-auto scrollbar-thin p-2">
|
||||
<div class="space-y-2">
|
||||
<!-- 文件夹组1 -->
|
||||
<div class="folder-group" th:each="folders : ${folderTrees}">
|
||||
<div class="flex items-center justify-between p-2 rounded-md hover:bg-accent-hover cursor-pointer"
|
||||
<!-- 根文件夹循环(正确遍历所有根目录) -->
|
||||
<div class="folder-group" th:each="rootFolder : ${folderTrees}">
|
||||
<!-- 父文件夹标题栏 -->
|
||||
<div class="flex items-center justify-between p-2 rounded-md hover:bg-accent-hover cursor-pointer transition-colors"
|
||||
onclick="toggleFolderGroup(this)">
|
||||
<div class="flex items-center">
|
||||
<i class="fa fa-folder-o mr-2 text-accent"></i>
|
||||
<span th:text="${folders.getFolder().getFolderName()}"></span>
|
||||
<!-- 图标动态切换(折叠/展开) -->
|
||||
<i class="fa fa-folder-o mr-2 text-accent transition-all"></i>
|
||||
<span th:text="${rootFolder.getFolder().getFolderName()}" class="font-medium"></span>
|
||||
<!-- 显示子文件夹数量 -->
|
||||
<span class="ml-2 text-xs text-gray-500"
|
||||
th:text="('(' + ${rootFolder.getChildFolders().size()} + ')')"></span>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right text-xs transition-transform duration-300"></i>
|
||||
<i class="fa fa-chevron-right text-xs transition-transform duration-300 ease-in-out"></i>
|
||||
</div>
|
||||
<div class="pl-6 mt-1 folder-content max-h-0 overflow-hidden transition-height"
|
||||
th:each="childFolders : ${folders.getChildFolders()}">
|
||||
|
||||
<!-- 子文件夹容器(修复循环层级) -->
|
||||
<div class="pl-6 mt-1 folder-content max-h-0 overflow-hidden transition-all duration-300 ease-in-out">
|
||||
<div class="space-y-1">
|
||||
<div class="p-2 rounded-md hover:bg-accent-hover cursor-pointer folder-item">
|
||||
<!-- 正确遍历当前父文件夹的子文件夹 -->
|
||||
<div class="p-2 rounded-md hover:bg-accent-hover cursor-pointer folder-item transition-colors"
|
||||
th:each="childFolder : ${rootFolder.getChildFolders()}">
|
||||
<i class="fa fa-folder-o mr-2 text-accent"></i>
|
||||
<span th:text="${childFolders.getFolderName()}"></span>
|
||||
<a th:href="@{/biz/dataDoc(folderId=${childFolder.getFolderId()})}"
|
||||
class="hover:text-accent transition-colors">
|
||||
<span th:text="${childFolder.getFolderName()}"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -238,12 +249,8 @@
|
||||
<label for="folderParent" class="block text-sm font-medium text-text-secondary mb-1">父文件夹</label>
|
||||
<select id="folderParent"
|
||||
class="w-full px-3 py-2 border border-border-color rounded-md focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent">
|
||||
<option value="">根目录</option>
|
||||
<option value="project-docs">项目文档</option>
|
||||
<option value="tech-docs">技术文档</option>
|
||||
<option value="test-docs">测试文档</option>
|
||||
<option value="meeting-notes">会议记录</option>
|
||||
<option value="training-materials">培训资料</option>
|
||||
<option th:each="folders : ${folderTrees}" th:value="${folders.getFolder().getFolderId()}"
|
||||
th:text="${folders.getFolder().getFolderName()}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
@@ -287,12 +294,8 @@
|
||||
<label for="uploadFolder" class="block text-sm font-medium text-text-secondary mb-1">上传到文件夹</label>
|
||||
<select id="uploadFolder"
|
||||
class="w-full px-3 py-2 border border-border-color rounded-md focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent">
|
||||
<option value="project-plan">项目计划</option>
|
||||
<option value="requirements">需求文档</option>
|
||||
<option value="design">设计文档</option>
|
||||
<option value="architecture">架构文档</option>
|
||||
<option value="api">API文档</option>
|
||||
<option value="database">数据库文档</option>
|
||||
<option th:each="upload : ${uploadFolder}" th:value="${upload.getFolderId()}"
|
||||
th:text="${upload.getFolderName()} "></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -463,31 +466,27 @@
|
||||
|
||||
// 这里应该是实际的API调用,现在使用模拟数据
|
||||
setTimeout(() => {
|
||||
// 模拟创建成功
|
||||
closeCreateFolderModal();
|
||||
showMessage(`文件夹 ${folderName} 创建成功`);
|
||||
|
||||
// 实际项目中,这里应该调用后端API创建文件夹
|
||||
// 例如:
|
||||
// fetch('/api/folders', {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify({
|
||||
// name: folderName,
|
||||
// parentId: folderParent
|
||||
// }),
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .then(data => {
|
||||
// closeCreateFolderModal();
|
||||
// showMessage(`文件夹 ${folderName} 创建成功`);
|
||||
// // 刷新文件夹列表
|
||||
// })
|
||||
// .catch(error => {
|
||||
// showMessage('创建文件夹失败', 'error');
|
||||
// });
|
||||
fetch('CreateFolder', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: folderName,
|
||||
parentId: folderParent
|
||||
}),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
closeCreateFolderModal();
|
||||
showMessage(`文件夹 ${folderName} 创建成功`);
|
||||
window.location.href = 'dataDoc'
|
||||
})
|
||||
.catch(error => {
|
||||
showMessage('创建文件夹失败', 'error');
|
||||
});
|
||||
}, 800);
|
||||
}
|
||||
|
||||
@@ -583,7 +582,6 @@
|
||||
showMessage('请先选择要上传的文件', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const uploadFolder = document.getElementById('uploadFolder').value;
|
||||
showMessage(`正在上传 ${uploadFiles.length} 个文件...`);
|
||||
|
||||
@@ -603,52 +601,39 @@
|
||||
uploadFiles.forEach((file, index) => {
|
||||
simulateUploadProgress(index, file, () => {
|
||||
completedFiles++;
|
||||
|
||||
// 检查是否所有文件都上传完成
|
||||
if (completedFiles === uploadFiles.length) {
|
||||
setTimeout(() => {
|
||||
// 启用上传按钮
|
||||
uploadBtn.disabled = false;
|
||||
uploadBtn.innerHTML = '开始上传';
|
||||
|
||||
// 清空上传列表
|
||||
document.getElementById('uploadFileList').innerHTML = '';
|
||||
uploadFiles = [];
|
||||
|
||||
// 关闭上传弹窗
|
||||
closeUploadFileModal();
|
||||
|
||||
// 显示成功消息
|
||||
showMessage(`${completedFiles} 个文件上传成功`);
|
||||
|
||||
// 刷新当前文件夹的文件列表
|
||||
if (currentFolder) {
|
||||
loadFiles(currentFolder);
|
||||
}
|
||||
// 实际项目中,这里应该调用后端API上传文件
|
||||
// 例如:
|
||||
const formData = new FormData();
|
||||
uploadFiles.forEach(file => {
|
||||
formData.append('files', file);
|
||||
});
|
||||
formData.append('folderId', uploadFolder);
|
||||
fetch('uploadFiles', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// 处理上传成功
|
||||
closeUploadFileModal();
|
||||
// 显示成功消息
|
||||
showMessage(`${completedFiles} 个文件上传成功`);
|
||||
window.location.href = 'dataDoc'
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理上传失败
|
||||
showMessage('上传文件失败', 'error');
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 实际项目中,这里应该调用后端API上传文件
|
||||
// 例如:
|
||||
// const formData = new FormData();
|
||||
// uploadFiles.forEach(file => {
|
||||
// formData.append('files', file);
|
||||
// });
|
||||
// formData.append('folderId', uploadFolder);
|
||||
//
|
||||
// fetch('/api/upload', {
|
||||
// method: 'POST',
|
||||
// body: formData,
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .then(data => {
|
||||
// // 处理上传成功
|
||||
// })
|
||||
// .catch(error => {
|
||||
// // 处理上传失败
|
||||
// });
|
||||
}
|
||||
|
||||
// 模拟上传进度
|
||||
|
||||
Reference in New Issue
Block a user