更新本地js

This commit is contained in:
2025-11-20 00:50:59 +08:00
parent 1b771fca15
commit 304d88541a
7 changed files with 199 additions and 94 deletions

View File

@@ -82,7 +82,7 @@ public class BizFiles implements Serializable {
* 是否删除0-未删除1-已删除)
*/
@TableField("is_deleted")
private Byte isDeleted;
private Integer isDeleted;
/**
* 文件版本号(用于版本控制)

View File

@@ -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";
}

View 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);
}
}

View 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;
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 => {
// // 处理上传失败
// });
}
// 模拟上传进度