You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
668 lines
25 KiB
668 lines
25 KiB
package com.wok.supportbot.controller;
|
|
|
|
import com.wok.supportbot.entity.CategoryNode;
|
|
import com.wok.supportbot.entity.KnowledgeCategory;
|
|
import com.wok.supportbot.entity.KnowledgeDocument;
|
|
import com.wok.supportbot.entity.SearchResult;
|
|
import com.wok.supportbot.service.DocumentService;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* 知识库文档管理控制器
|
|
* 提供文档上传、查询、管理、分类、搜索等完整功能
|
|
*/
|
|
@RestController
|
|
public class DocumentController {
|
|
|
|
@Autowired
|
|
private DocumentService documentService;
|
|
|
|
// ==================== 上传校验常量 ====================
|
|
|
|
/** 允许上传的文件类型白名单 */
|
|
private static final Set<String> ALLOWED_EXTENSIONS = Set.of(
|
|
"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx",
|
|
"txt", "md", "json", "csv", "html", "xml", "rtf"
|
|
);
|
|
|
|
/** 文件大小上限(50MB,与 application.yml 中 multipart 配置一致) */
|
|
private static final long MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
|
|
/**
|
|
* 校验上传文件
|
|
* @param file 上传的文件
|
|
*/
|
|
private void validateUploadFile(MultipartFile file) {
|
|
if (file.getSize() > MAX_FILE_SIZE) {
|
|
throw new IllegalArgumentException("文件大小超过限制(最大 50MB)");
|
|
}
|
|
String extension = getFileExtension(file.getOriginalFilename());
|
|
if (extension != null && !ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
|
|
throw new IllegalArgumentException("不支持的文件类型: " + extension);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取文件扩展名
|
|
*/
|
|
private String getFileExtension(String filename) {
|
|
if (filename == null || !filename.contains(".")) {
|
|
return null;
|
|
}
|
|
return filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
|
|
}
|
|
|
|
// ==================== 文档上传 ====================
|
|
|
|
/**
|
|
* 上传普通文件(支持多种格式),用 Tika 解析
|
|
*
|
|
* @param file 文件
|
|
* @param title 文档标题(可选,默认使用文件名)
|
|
* @param categoryId 分类ID(可选)
|
|
* @param tags 标签(可选)
|
|
* @return 上传结果
|
|
*/
|
|
@PostMapping("/upload/file")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadFile(
|
|
@RequestParam("file") MultipartFile file,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
validateUploadFile(file);
|
|
KnowledgeDocument doc = documentService.uploadFile(file, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "文件上传并向量化成功",
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传字符串内容
|
|
*
|
|
* @param content 内容
|
|
* @param title 标题
|
|
* @param categoryId 分类ID(可选)
|
|
* @param tags 标签(可选)
|
|
* @return 上传结果
|
|
*/
|
|
@PostMapping("/upload/string")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadString(
|
|
@RequestBody String content,
|
|
@RequestParam String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
KnowledgeDocument doc = documentService.uploadString(content, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "文本内容上传并向量化成功",
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传 Markdown 文件
|
|
*/
|
|
@PostMapping("/upload/markdown")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadMarkdown(
|
|
@RequestParam("file") MultipartFile file,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
validateUploadFile(file);
|
|
KnowledgeDocument doc = documentService.uploadMarkdown(file, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "Markdown文件上传并向量化成功",
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传 JSON 文件(基本方式)
|
|
*/
|
|
@PostMapping("/upload/json/basic")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadJsonBasic(
|
|
@RequestParam("file") MultipartFile file,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
validateUploadFile(file);
|
|
KnowledgeDocument doc = documentService.uploadJsonBasic(file, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "JSON文件(基本方式)上传并向量化成功",
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传 JSON 文件(按字段提取)
|
|
*/
|
|
@PostMapping("/upload/json/fields")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadJsonWithFields(
|
|
@RequestParam("file") MultipartFile file,
|
|
@RequestParam("fields") List<String> fields,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
validateUploadFile(file);
|
|
KnowledgeDocument doc = documentService.uploadJsonFields(file, fields, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "JSON文件(按字段)上传并向量化成功",
|
|
"data", doc,
|
|
"extractedFields", fields
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传 JSON 文件(按指针拆分)
|
|
*/
|
|
@PostMapping("/upload/json/pointer")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> uploadJsonWithPointer(
|
|
@RequestParam("file") MultipartFile file,
|
|
@RequestParam("pointer") String pointer,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
validateUploadFile(file);
|
|
KnowledgeDocument doc = documentService.uploadJsonPointer(file, pointer, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "JSON文件(按指针)上传并向量化成功",
|
|
"data", doc,
|
|
"pointer", pointer
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "上传失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
// ==================== 文档管理 ====================
|
|
|
|
/**
|
|
* 查询文档列表(分页 + 过滤)
|
|
*
|
|
* @param page 页码(默认1)
|
|
* @param size 每页大小(默认10)
|
|
* @param categoryId 分类ID过滤(可选)
|
|
* @param status 状态过滤(PROCESSING/READY/FAILED,可选)
|
|
* @return 分页文档列表
|
|
*/
|
|
@GetMapping("/document/list")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> listDocuments(
|
|
@RequestParam(defaultValue = "1") int page,
|
|
@RequestParam(defaultValue = "10") int size,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) String status) {
|
|
try {
|
|
Map<String, Object> result = documentService.listDocuments(page, size, categoryId, status);
|
|
Map<String, Object> data = new HashMap<>();
|
|
data.put("success", true);
|
|
data.put("data", result.get("records"));
|
|
data.put("total", result.get("total"));
|
|
data.put("page", result.get("page"));
|
|
data.put("size", result.get("size"));
|
|
data.put("pages", result.get("pages"));
|
|
return ResponseEntity.ok(data);
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "查询失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取文档详情
|
|
*/
|
|
@GetMapping("/document/{id}")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> getDocumentDetail(@PathVariable Long id) {
|
|
try {
|
|
KnowledgeDocument doc = documentService.getDocumentDetail(id);
|
|
if (doc == null) {
|
|
return ResponseEntity.status(404).body(Map.of(
|
|
"success", false,
|
|
"message", "文档不存在"
|
|
));
|
|
}
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "查询失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取文档的所有分块
|
|
*/
|
|
@GetMapping("/document/{id}/chunks")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> getDocumentChunks(@PathVariable Long id) {
|
|
try {
|
|
List<Map<String, Object>> chunks = documentService.getDocumentChunks(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", chunks,
|
|
"total", chunks.size()
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "查询失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除文档(逻辑删除 + 级联删除向量)
|
|
*/
|
|
@DeleteMapping("/document/{id}")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> deleteDocument(@PathVariable Long id) {
|
|
try {
|
|
int vectorCount = documentService.deleteDocument(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "删除成功",
|
|
"deletedVectors", vectorCount
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "删除失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 批量删除文档
|
|
*/
|
|
@PostMapping("/document/batch/delete")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> batchDeleteDocuments(@RequestBody Map<String, Object> body) {
|
|
try {
|
|
List<Long> ids = extractIds(body);
|
|
if (ids.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", "请提供要删除的文档ID列表"
|
|
));
|
|
}
|
|
Map<String, Object> result = documentService.batchDeleteDocuments(ids);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", String.format("批量删除完成:成功 %d 个,失败 %d 个",
|
|
result.get("successCount"), result.get("failCount")),
|
|
"data", result
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "批量删除失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 批量重新处理文档
|
|
*/
|
|
@PostMapping("/document/batch/reprocess")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> batchReprocessDocuments(@RequestBody Map<String, Object> body) {
|
|
try {
|
|
List<Long> ids = extractIds(body);
|
|
if (ids.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", "请提供要重新处理的文档ID列表"
|
|
));
|
|
}
|
|
Map<String, Object> result = documentService.batchReprocessDocuments(ids);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", String.format("批量重新处理完成:成功 %d 个,失败 %d 个",
|
|
result.get("successCount"), result.get("failCount")),
|
|
"data", result
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "批量重新处理失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 从请求体中提取 ID 列表(兼容字符串和数字类型的 ID)
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
private List<Long> extractIds(Map<String, Object> body) {
|
|
List<?> rawIds = (List<?>) body.get("ids");
|
|
if (rawIds == null || rawIds.isEmpty()) {
|
|
return List.of();
|
|
}
|
|
return rawIds.stream().map(id -> {
|
|
if (id instanceof Number) {
|
|
return ((Number) id).longValue();
|
|
} else if (id instanceof String) {
|
|
return Long.parseLong((String) id);
|
|
} else {
|
|
throw new IllegalArgumentException("无效的ID格式: " + id);
|
|
}
|
|
}).toList();
|
|
}
|
|
|
|
/**
|
|
* 更新文档元信息
|
|
*/
|
|
@PutMapping("/document/{id}")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> updateDocument(
|
|
@PathVariable Long id,
|
|
@RequestParam(required = false) String title,
|
|
@RequestParam(required = false) Long categoryId,
|
|
@RequestParam(required = false) List<String> tags) {
|
|
try {
|
|
documentService.updateDocumentMetadata(id, title, categoryId, tags);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "更新成功"
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "更新失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 重新处理文档(重新分块 + 向量化)
|
|
*/
|
|
@PutMapping("/document/{id}/reprocess")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> reprocessDocument(@PathVariable Long id) {
|
|
try {
|
|
KnowledgeDocument doc = documentService.reprocessDocument(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "重新处理成功",
|
|
"data", doc
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "重新处理失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
// ==================== 语义搜索 ====================
|
|
|
|
/**
|
|
* 语义搜索
|
|
*
|
|
* @param body 搜索参数
|
|
* @return 搜索结果
|
|
*/
|
|
@PostMapping("/document/search")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> searchDocuments(@RequestBody Map<String, Object> body) {
|
|
try {
|
|
String query = (String) body.get("query");
|
|
int topK = body.get("topK") != null ? ((Number) body.get("topK")).intValue() : 5;
|
|
double similarityThreshold = body.get("similarityThreshold") != null
|
|
? ((Number) body.get("similarityThreshold")).doubleValue() : 0.5;
|
|
Long categoryId = body.get("categoryId") != null ? ((Number) body.get("categoryId")).longValue() : null;
|
|
List<Long> categoryIds = parseCategoryIds(body.get("categoryIds"));
|
|
if (categoryIds.isEmpty() && categoryId != null) {
|
|
categoryIds = List.of(categoryId);
|
|
}
|
|
String searchMode = (String) body.get("searchMode");
|
|
|
|
List<SearchResult> results;
|
|
if (searchMode != null && !searchMode.isEmpty()) {
|
|
results = documentService.searchDocuments(query, topK, similarityThreshold, categoryIds, searchMode);
|
|
} else {
|
|
results = documentService.searchDocuments(query, topK, similarityThreshold, categoryIds);
|
|
}
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", results,
|
|
"total", results.size()
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "搜索失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
private List<Long> parseCategoryIds(Object rawCategoryIds) {
|
|
if (rawCategoryIds == null) {
|
|
return List.of();
|
|
}
|
|
if (rawCategoryIds instanceof List<?> list) {
|
|
return list.stream()
|
|
.filter(Objects::nonNull)
|
|
.map(item -> item instanceof Number number ? number.longValue() : Long.parseLong(item.toString()))
|
|
.filter(id -> id > 0)
|
|
.distinct()
|
|
.toList();
|
|
}
|
|
String text = rawCategoryIds.toString();
|
|
if (text.isBlank()) {
|
|
return List.of();
|
|
}
|
|
return Arrays.stream(text.split(","))
|
|
.map(String::trim)
|
|
.filter(item -> !item.isEmpty())
|
|
.map(Long::parseLong)
|
|
.filter(id -> id > 0)
|
|
.distinct()
|
|
.toList();
|
|
}
|
|
|
|
// ==================== 统计 ====================
|
|
|
|
/**
|
|
* 知识库统计面板
|
|
*/
|
|
@GetMapping("/document/stats")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> getStats() {
|
|
try {
|
|
Map<String, Object> stats = documentService.getStats();
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", stats
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "查询统计失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
// ==================== 分类管理 ====================
|
|
|
|
/**
|
|
* 获取分类树
|
|
*/
|
|
@GetMapping("/category/tree")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> getCategoryTree() {
|
|
try {
|
|
List<CategoryNode> tree = documentService.getCategoryTree();
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", tree
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "获取分类树失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取分类列表
|
|
*/
|
|
@GetMapping("/category/list")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> listCategories() {
|
|
try {
|
|
List<KnowledgeCategory> list = documentService.listCategories();
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"data", list
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "获取分类列表失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建分类
|
|
*/
|
|
@PostMapping("/category")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> createCategory(@RequestBody Map<String, Object> body) {
|
|
try {
|
|
String name = (String) body.get("name");
|
|
String description = (String) body.get("description");
|
|
Long parentId = body.get("parentId") != null ? ((Number) body.get("parentId")).longValue() : null;
|
|
Integer sortOrder = body.get("sortOrder") != null ? ((Number) body.get("sortOrder")).intValue() : null;
|
|
|
|
KnowledgeCategory category = documentService.createCategory(name, description, parentId, sortOrder);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "分类创建成功",
|
|
"data", category
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "创建分类失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新分类
|
|
*/
|
|
@PutMapping("/category/{id}")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> updateCategory(
|
|
@PathVariable Long id,
|
|
@RequestBody Map<String, Object> body) {
|
|
try {
|
|
String name = (String) body.get("name");
|
|
String description = (String) body.get("description");
|
|
Integer sortOrder = body.get("sortOrder") != null ? ((Number) body.get("sortOrder")).intValue() : null;
|
|
|
|
documentService.updateCategory(id, name, description, sortOrder);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "分类更新成功"
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "更新分类失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除分类
|
|
*/
|
|
@DeleteMapping("/category/{id}")
|
|
@PreAuthorize("hasAnyRole('admin','kb_operator')")
|
|
public ResponseEntity<Map<String, Object>> deleteCategory(@PathVariable Long id) {
|
|
try {
|
|
documentService.deleteCategory(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "分类删除成功"
|
|
));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "删除分类失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
}
|