Merge commit '343df65c698d579335d9c7c47160b79ae0c14f8a'
This commit is contained in:
@@ -1,19 +1,5 @@
|
|||||||
package com.labelsys.backend.controller;
|
package com.labelsys.backend.controller;
|
||||||
|
|
||||||
import com.labelsys.backend.annotation.RequirePosition;
|
|
||||||
import com.labelsys.backend.common.Result;
|
|
||||||
import com.labelsys.backend.context.UserContext;
|
|
||||||
import com.labelsys.backend.dto.common.PageResult;
|
|
||||||
import com.labelsys.backend.dto.request.SaveSysConfigRequest;
|
|
||||||
import com.labelsys.backend.dto.request.SysConfigPageQuery;
|
|
||||||
import com.labelsys.backend.dto.response.SysConfigResponse;
|
|
||||||
import com.labelsys.backend.enums.UserPosition;
|
|
||||||
import com.labelsys.backend.service.SysConfigService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springdoc.core.annotations.ParameterObject;
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
@@ -23,6 +9,21 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.labelsys.backend.common.Result;
|
||||||
|
import com.labelsys.backend.context.UserContext;
|
||||||
|
import com.labelsys.backend.dto.common.PageResult;
|
||||||
|
import com.labelsys.backend.dto.request.SaveSysConfigRequest;
|
||||||
|
import com.labelsys.backend.dto.request.SysConfigPageQuery;
|
||||||
|
import com.labelsys.backend.dto.request.UpdateSysConfigRequest;
|
||||||
|
import com.labelsys.backend.dto.response.SysConfigResponse;
|
||||||
|
import com.labelsys.backend.service.SysConfigService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@Tag(name = "系统配置管理")
|
@Tag(name = "系统配置管理")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/sys-configs")
|
@RequestMapping("/api/sys-configs")
|
||||||
@@ -32,21 +33,21 @@ public class SysConfigController {
|
|||||||
private final SysConfigService sysConfigService;
|
private final SysConfigService sysConfigService;
|
||||||
|
|
||||||
@Operation(summary = "创建系统配置")
|
@Operation(summary = "创建系统配置")
|
||||||
@RequirePosition(UserPosition.ADMIN)
|
// @RequirePosition(UserPosition.ADMIN)
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Result<SysConfigResponse> create(@Valid @RequestBody SaveSysConfigRequest request) {
|
public Result<SysConfigResponse> create(@Valid @RequestBody SaveSysConfigRequest request) {
|
||||||
return Result.success(sysConfigService.toResponse(sysConfigService.saveConfig(UserContext.requireUser(), request)));
|
return Result
|
||||||
|
.success(sysConfigService.toResponse(sysConfigService.saveConfig(UserContext.requireUser(), request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "更新系统配置")
|
@Operation(summary = "更新系统配置")
|
||||||
@RequirePosition(UserPosition.ADMIN)
|
// @RequirePosition(UserPosition.ADMIN)
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
public Result<SysConfigResponse> update(
|
public Result<SysConfigResponse> update(
|
||||||
@Parameter(description = "配置ID", example = "191000000000000501")
|
@Parameter(description = "配置ID", example = "191000000000000501") @PathVariable Long id,
|
||||||
@PathVariable Long id,
|
@Valid @RequestBody UpdateSysConfigRequest request) {
|
||||||
@Valid @RequestBody SaveSysConfigRequest request
|
return Result.success(
|
||||||
) {
|
sysConfigService.toResponse(sysConfigService.updateConfig(UserContext.requireUser(), id, request)));
|
||||||
return Result.success(sysConfigService.toResponse(sysConfigService.updateConfig(UserContext.requireUser(), id, request)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "分页查询系统配置")
|
@Operation(summary = "分页查询系统配置")
|
||||||
@@ -57,10 +58,8 @@ public class SysConfigController {
|
|||||||
|
|
||||||
@Operation(summary = "查询系统配置详情")
|
@Operation(summary = "查询系统配置详情")
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Result<SysConfigResponse> detail(
|
public Result<SysConfigResponse>
|
||||||
@Parameter(description = "配置ID", example = "191000000000000501")
|
detail(@Parameter(description = "配置ID", example = "191000000000000501") @PathVariable Long id) {
|
||||||
@PathVariable Long id
|
|
||||||
) {
|
|
||||||
return Result.success(sysConfigService.getConfig(UserContext.requireUser(), id));
|
return Result.success(sysConfigService.getConfig(UserContext.requireUser(), id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotBlank;
|
|||||||
public record SaveSysConfigRequest(
|
public record SaveSysConfigRequest(
|
||||||
@Schema(description = "配置类型", example = "MODEL") @NotBlank(message = "配置类型不能为空") String configType,
|
@Schema(description = "配置类型", example = "MODEL") @NotBlank(message = "配置类型不能为空") String configType,
|
||||||
@Schema(description = "配置名称", example = "qwen-plus-extract") @NotBlank(message = "配置名称不能为空") String configName,
|
@Schema(description = "配置名称", example = "qwen-plus-extract") @NotBlank(message = "配置名称不能为空") String configName,
|
||||||
@Schema(description = "配置值", example = "{\"modelName\":\"qwen-plus\",\"modelUrl\":\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\"apiKey\":\"sk-demo1234\"}") @NotBlank(message = "配置值不能为空") String configValue,
|
@Schema(description = "配置值",
|
||||||
@Schema(description = "配置状态", example = "ENABLED") @NotBlank(message = "配置状态不能为空") String status
|
example = "{\"modelName\":\"qwen-plus\",\"modelUrl\":\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\"apiKey\":\"sk-demo1234\"}") @NotBlank(
|
||||||
) {
|
message = "配置值不能为空") String configValue,
|
||||||
}
|
@Schema(description = "配置状态", example = "ENABLED") String status) {}
|
||||||
|
|||||||
@@ -3,11 +3,8 @@ package com.labelsys.backend.dto.request;
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
@Schema(description = "系统配置分页查询请求")
|
@Schema(description = "系统配置分页查询请求")
|
||||||
public record SysConfigPageQuery(
|
public record SysConfigPageQuery(@Schema(description = "配置类型", example = "MODEL") String configType,
|
||||||
@Schema(description = "配置类型", example = "MODEL") String configType,
|
|
||||||
@Schema(description = "配置名称", example = "qwen-plus-extract") String configName,
|
@Schema(description = "配置名称", example = "qwen-plus-extract") String configName,
|
||||||
@Schema(description = "配置状态", example = "ENABLED") String status,
|
@Schema(description = "配置状态", example = "ENABLED") String status,
|
||||||
@Schema(description = "页码", example = "1") Integer pageNo,
|
@Schema(description = "页码", example = "1") Integer pageNo,
|
||||||
@Schema(description = "每页数量", example = "10") Integer pageSize
|
@Schema(description = "每页数量", example = "10") Integer pageSize) {}
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.labelsys.backend.dto.request;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
@Schema(description = "更新系统配置请求")
|
||||||
|
public record UpdateSysConfigRequest(
|
||||||
|
|
||||||
|
@Schema(description = "配置类型", example = "MODEL") String configType,
|
||||||
|
@Schema(description = "配置名称", example = "qwen-plus-extract") String configName,
|
||||||
|
@Schema(description = "配置值",
|
||||||
|
example = "{\"modelName\":\"qwen-plus\",\"modelUrl\":\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\"apiKey\":\"sk-demo1234\"}") @NotBlank(
|
||||||
|
message = "配置值不能为空") String configValue,
|
||||||
|
@Schema(description = "配置状态", example = "ENABLED") String status) {}
|
||||||
@@ -23,6 +23,7 @@ public class SysConfig {
|
|||||||
private String configValue;
|
private String configValue;
|
||||||
private String status;
|
private String status;
|
||||||
private Long creatorId;
|
private Long creatorId;
|
||||||
|
private String creatorRole;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package com.labelsys.backend.service;
|
package com.labelsys.backend.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.labelsys.backend.common.ResultCode;
|
import com.labelsys.backend.common.ResultCode;
|
||||||
@@ -14,11 +18,9 @@ import com.labelsys.backend.entity.SourceResource;
|
|||||||
import com.labelsys.backend.enums.RuntimeResultStatus;
|
import com.labelsys.backend.enums.RuntimeResultStatus;
|
||||||
import com.labelsys.backend.mapper.AnnotationResultMapper;
|
import com.labelsys.backend.mapper.AnnotationResultMapper;
|
||||||
import com.labelsys.backend.mapper.SourceResourceMapper;
|
import com.labelsys.backend.mapper.SourceResourceMapper;
|
||||||
import com.labelsys.backend.service.DataPermissionService;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@@ -33,11 +35,12 @@ public class AnnotationResultService {
|
|||||||
List<String> allowedRoles = dataPermissionService.getAllowedRoles(currentUser);
|
List<String> allowedRoles = dataPermissionService.getAllowedRoles(currentUser);
|
||||||
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
|
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
|
||||||
|
|
||||||
LambdaQueryWrapper<AnnotationResult> wrapper = new LambdaQueryWrapper<AnnotationResult>()
|
LambdaQueryWrapper<AnnotationResult> wrapper =
|
||||||
.eq(AnnotationResult::getCompanyId, currentUser.companyId())
|
new LambdaQueryWrapper<AnnotationResult>().eq(AnnotationResult::getCompanyId, currentUser.companyId())
|
||||||
.eq(query.taskId() != null, AnnotationResult::getTaskId, query.taskId())
|
.eq(query.taskId() != null, AnnotationResult::getTaskId, query.taskId())
|
||||||
.eq(query.resourceId() != null, AnnotationResult::getResourceId, query.resourceId())
|
.eq(query.resourceId() != null, AnnotationResult::getResourceId, query.resourceId())
|
||||||
.eq(query.requiresManualReview() != null, AnnotationResult::getRequiresManualReview, query.requiresManualReview());
|
.eq(query.requiresManualReview() != null, AnnotationResult::getRequiresManualReview,
|
||||||
|
query.requiresManualReview());
|
||||||
|
|
||||||
if (shouldFilterByUserId) {
|
if (shouldFilterByUserId) {
|
||||||
wrapper.eq(AnnotationResult::getCreatorId, currentUser.userId());
|
wrapper.eq(AnnotationResult::getCreatorId, currentUser.userId());
|
||||||
@@ -50,19 +53,19 @@ public class AnnotationResultService {
|
|||||||
Page<AnnotationResult> page = new Page<>(query.pageNo(), query.pageSize());
|
Page<AnnotationResult> page = new Page<>(query.pageNo(), query.pageSize());
|
||||||
Page<AnnotationResult> resultPage = annotationResultMapper.selectPage(page, wrapper);
|
Page<AnnotationResult> resultPage = annotationResultMapper.selectPage(page, wrapper);
|
||||||
|
|
||||||
List<AnnotationResultResponse> records = resultPage.getRecords().stream()
|
List<AnnotationResultResponse> records = resultPage.getRecords().stream().map(this::toResponse)
|
||||||
.map(this::toResponse)
|
|
||||||
.filter(response -> query.runtimeStatus() == null || query.runtimeStatus().equals(response.runtimeStatus()))
|
.filter(response -> query.runtimeStatus() == null || query.runtimeStatus().equals(response.runtimeStatus()))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return new PageResult<>(records, resultPage.getTotal(), (int) resultPage.getCurrent(), (int) resultPage.getSize());
|
return new PageResult<>(records, resultPage.getTotal(), (int)resultPage.getCurrent(),
|
||||||
|
(int)resultPage.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnnotationResultResponse getResult(LoginUser currentUser, Long resultId) {
|
public AnnotationResultResponse getResult(LoginUser currentUser, Long resultId) {
|
||||||
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
|
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}",
|
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}", resultId,
|
||||||
resultId, currentUser.companyId(), currentUser.userId());
|
currentUser.companyId(), currentUser.userId());
|
||||||
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
|
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
|
||||||
}
|
}
|
||||||
return toResponse(result);
|
return toResponse(result);
|
||||||
@@ -71,34 +74,20 @@ public class AnnotationResultService {
|
|||||||
public AnnotationResultCompareResponse compareResult(LoginUser currentUser, Long resultId) {
|
public AnnotationResultCompareResponse compareResult(LoginUser currentUser, Long resultId) {
|
||||||
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
|
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}",
|
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}", resultId,
|
||||||
resultId, currentUser.companyId(), currentUser.userId());
|
currentUser.companyId(), currentUser.userId());
|
||||||
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
|
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
|
||||||
}
|
}
|
||||||
SourceResource resource = sourceResourceMapper.selectById(result.getResourceId());
|
SourceResource resource = sourceResourceMapper.selectById(result.getResourceId());
|
||||||
return new AnnotationResultCompareResponse(
|
return new AnnotationResultCompareResponse(result.getId(), result.getTaskId(), result.getResourceId(),
|
||||||
result.getId(),
|
result.getQaContentJson(), result.getDiffSummary(), result.getQaContentStorageMode(),
|
||||||
result.getTaskId(),
|
result.getQaContentFilePath(), resource == null ? null : resource.getFilePath());
|
||||||
result.getResourceId(),
|
|
||||||
result.getQaContentJson(),
|
|
||||||
result.getDiffSummary(),
|
|
||||||
result.getQaContentStorageMode(),
|
|
||||||
result.getQaContentFilePath(),
|
|
||||||
resource == null ? null : resource.getFilePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationResultResponse toResponse(AnnotationResult result) {
|
private AnnotationResultResponse toResponse(AnnotationResult result) {
|
||||||
return new AnnotationResultResponse(
|
return new AnnotationResultResponse(result.getId(), result.getTaskId(), result.getResourceId(),
|
||||||
result.getId(),
|
deriveStatus(result), result.getRequiresManualReview(), result.getIsDeleted(),
|
||||||
result.getTaskId(),
|
result.getQaContentStorageMode(), result.getReviewComment(), result.getReviewedAt(), result.getCreatedAt());
|
||||||
result.getResourceId(),
|
|
||||||
deriveStatus(result),
|
|
||||||
result.getRequiresManualReview(),
|
|
||||||
result.getIsDeleted(),
|
|
||||||
result.getQaContentStorageMode(),
|
|
||||||
result.getReviewComment(),
|
|
||||||
result.getReviewedAt(),
|
|
||||||
result.getCreatedAt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String deriveStatus(AnnotationResult result) {
|
private String deriveStatus(AnnotationResult result) {
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
package com.labelsys.backend.service;
|
package com.labelsys.backend.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.labelsys.backend.common.ResultCode;
|
import com.labelsys.backend.common.ResultCode;
|
||||||
@@ -12,21 +20,18 @@ import com.labelsys.backend.dto.request.PromptConfigOptionRequest;
|
|||||||
import com.labelsys.backend.dto.request.SaveSysConfigRequest;
|
import com.labelsys.backend.dto.request.SaveSysConfigRequest;
|
||||||
import com.labelsys.backend.dto.request.SysConfigPageQuery;
|
import com.labelsys.backend.dto.request.SysConfigPageQuery;
|
||||||
import com.labelsys.backend.dto.request.TaskModelConfigRequest;
|
import com.labelsys.backend.dto.request.TaskModelConfigRequest;
|
||||||
|
import com.labelsys.backend.dto.request.UpdateSysConfigRequest;
|
||||||
import com.labelsys.backend.dto.response.SysConfigResponse;
|
import com.labelsys.backend.dto.response.SysConfigResponse;
|
||||||
import com.labelsys.backend.dto.response.TaskModelConfigResponse;
|
import com.labelsys.backend.dto.response.TaskModelConfigResponse;
|
||||||
import com.labelsys.backend.dto.response.TaskPromptConfigResponse;
|
import com.labelsys.backend.dto.response.TaskPromptConfigResponse;
|
||||||
import com.labelsys.backend.entity.SysConfig;
|
import com.labelsys.backend.entity.SysConfig;
|
||||||
import com.labelsys.backend.enums.ConfigType;
|
import com.labelsys.backend.enums.ConfigType;
|
||||||
|
import com.labelsys.backend.enums.UserRole;
|
||||||
import com.labelsys.backend.mapper.SysConfigMapper;
|
import com.labelsys.backend.mapper.SysConfigMapper;
|
||||||
import com.labelsys.backend.util.IdGenerator;
|
import com.labelsys.backend.util.IdGenerator;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@@ -35,63 +40,87 @@ public class SysConfigService {
|
|||||||
|
|
||||||
private final SysConfigMapper sysConfigMapper;
|
private final SysConfigMapper sysConfigMapper;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
private final DataPermissionService dataPermissionService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public SysConfig saveConfig(LoginUser currentUser, SaveSysConfigRequest request) {
|
public SysConfig saveConfig(LoginUser currentUser, SaveSysConfigRequest request) {
|
||||||
validateConfigType(request.configType());
|
validateConfigType(request.configType());
|
||||||
SysConfig existing = sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.configName());
|
SysConfig existing =
|
||||||
|
sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.configName());
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
throw new BusinessException(ResultCode.CONFLICT, "配置名称已存在");
|
throw new BusinessException(ResultCode.CONFLICT, "配置名称已存在");
|
||||||
}
|
}
|
||||||
SysConfig config = SysConfig.builder()
|
SysConfig config = SysConfig.builder().id(IdGenerator.nextId()).companyId(currentUser.companyId())
|
||||||
.id(IdGenerator.nextId())
|
.configType(request.configType()).configName(request.configName()).configValue(request.configValue())
|
||||||
.companyId(currentUser.companyId())
|
.status(request.status()).creatorId(currentUser.userId()).creatorRole(currentUser.role().name()).build();
|
||||||
.configType(request.configType())
|
|
||||||
.configName(request.configName())
|
|
||||||
.configValue(request.configValue())
|
|
||||||
.status(request.status())
|
|
||||||
.creatorId(currentUser.userId())
|
|
||||||
.build();
|
|
||||||
sysConfigMapper.insert(config);
|
sysConfigMapper.insert(config);
|
||||||
log.info("saved sys config, companyId={}, userId={}, configName={}, configType={}",
|
log.info("saved sys config, companyId={}, userId={}, userRole={}, configName={}, configType={}",
|
||||||
currentUser.companyId(), currentUser.userId(), request.configName(), request.configType());
|
currentUser.companyId(), currentUser.userId(), currentUser.role().name(), request.configName(),
|
||||||
|
request.configType());
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public SysConfig updateConfig(LoginUser currentUser, Long configId, SaveSysConfigRequest request) {
|
public SysConfig updateConfig(LoginUser currentUser, Long configId, UpdateSysConfigRequest request) {
|
||||||
validateConfigType(request.configType());
|
validateConfigType(request.configType());
|
||||||
SysConfig existing = getConfigEntity(currentUser, configId);
|
SysConfig existing = getConfigEntity(currentUser, configId);
|
||||||
SysConfig duplicate = sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.configName());
|
// SysConfig duplicate =
|
||||||
if (duplicate != null && !duplicate.getId().equals(configId)) {
|
// sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.configName());
|
||||||
throw new BusinessException(ResultCode.CONFLICT, "配置名称已存在");
|
// if (duplicate != null && !duplicate.getId().equals(configId)) {
|
||||||
}
|
// throw new BusinessException(ResultCode.CONFLICT, "配置名称已存在");
|
||||||
existing.setConfigType(request.configType());
|
// }
|
||||||
|
if (StringUtils.hasText(request.configName())) {
|
||||||
existing.setConfigName(request.configName());
|
existing.setConfigName(request.configName());
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(request.configType())) {
|
||||||
|
existing.setConfigType(request.configType());
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(request.configValue())) {
|
||||||
existing.setConfigValue(request.configValue());
|
existing.setConfigValue(request.configValue());
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(request.status())) {
|
||||||
existing.setStatus(request.status());
|
existing.setStatus(request.status());
|
||||||
|
}
|
||||||
sysConfigMapper.updateById(existing);
|
sysConfigMapper.updateById(existing);
|
||||||
log.info("updated sys config, companyId={}, userId={}, configId={}",
|
log.info("updated sys config, companyId={}, userId={}, configId={}", currentUser.companyId(),
|
||||||
currentUser.companyId(), currentUser.userId(), configId);
|
currentUser.userId(), configId);
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SysConfigResponse getConfig(LoginUser currentUser, Long configId) {
|
public SysConfigResponse getConfig(LoginUser currentUser, Long configId) {
|
||||||
return toResponse(getConfigEntity(currentUser, configId));
|
SysConfig config = getConfigEntity(currentUser, configId);
|
||||||
|
if (!dataPermissionService.canAccessCreator(currentUser, config.getCreatorId(),
|
||||||
|
UserRole.valueOf(config.getCreatorRole()))) {
|
||||||
|
throw new BusinessException(ResultCode.FORBIDDEN, "无权访问配置");
|
||||||
|
}
|
||||||
|
return toResponse(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PageResult<SysConfigResponse> pageConfigs(LoginUser currentUser, SysConfigPageQuery query) {
|
public PageResult<SysConfigResponse> pageConfigs(LoginUser currentUser, SysConfigPageQuery query) {
|
||||||
LambdaQueryWrapper<SysConfig> wrapper = new LambdaQueryWrapper<SysConfig>()
|
List<String> allowedRoles = dataPermissionService.getAllowedRoles(currentUser);
|
||||||
.eq(SysConfig::getCompanyId, currentUser.companyId())
|
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
|
||||||
|
|
||||||
|
LambdaQueryWrapper<SysConfig> wrapper =
|
||||||
|
new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getCompanyId, currentUser.companyId())
|
||||||
.eq(StringUtils.hasText(query.configType()), SysConfig::getConfigType, query.configType())
|
.eq(StringUtils.hasText(query.configType()), SysConfig::getConfigType, query.configType())
|
||||||
.eq(StringUtils.hasText(query.status()), SysConfig::getStatus, query.status())
|
.eq(StringUtils.hasText(query.status()), SysConfig::getStatus, query.status())
|
||||||
.like(StringUtils.hasText(query.configName()), SysConfig::getConfigName, query.configName())
|
.like(StringUtils.hasText(query.configName()), SysConfig::getConfigName, query.configName());
|
||||||
.orderByDesc(SysConfig::getCreatedAt);
|
|
||||||
List<SysConfigResponse> records = sysConfigMapper.selectList(wrapper).stream()
|
if (shouldFilterByUserId) {
|
||||||
.sorted(Comparator.comparing(SysConfig::getCreatedAt, Comparator.nullsLast(Comparator.naturalOrder())).reversed())
|
wrapper.eq(SysConfig::getCreatorId, currentUser.userId());
|
||||||
.map(this::toResponse)
|
} else if (!allowedRoles.isEmpty()) {
|
||||||
.toList();
|
wrapper.in(SysConfig::getCreatorRole, allowedRoles);
|
||||||
return paginate(records, query.pageNo(), query.pageSize());
|
}
|
||||||
|
|
||||||
|
wrapper.orderByDesc(SysConfig::getCreatedAt);
|
||||||
|
|
||||||
|
Page<SysConfig> page = new Page<>(query.pageNo(), query.pageSize());
|
||||||
|
Page<SysConfig> resultPage = sysConfigMapper.selectPage(page, wrapper);
|
||||||
|
|
||||||
|
List<SysConfigResponse> records = resultPage.getRecords().stream().map(this::toResponse).toList();
|
||||||
|
|
||||||
|
return new PageResult<>(records, resultPage.getTotal(), (int)resultPage.getCurrent(),
|
||||||
|
(int)resultPage.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -113,8 +142,8 @@ public class SysConfigService {
|
|||||||
throw new BusinessException(ResultCode.BAD_REQUEST, "提示词配置不能为空");
|
throw new BusinessException(ResultCode.BAD_REQUEST, "提示词配置不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.hasText(request.selectedConfigName())) {
|
if (StringUtils.hasText(request.selectedConfigName())) {
|
||||||
SysConfig config = sysConfigMapper.findByCompanyIdAndConfigNameAndType(
|
SysConfig config = sysConfigMapper.findByCompanyIdAndConfigNameAndType(currentUser.companyId(),
|
||||||
currentUser.companyId(), request.selectedConfigName(), ConfigType.PROMPT.name());
|
request.selectedConfigName(), ConfigType.PROMPT.name());
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
throw new BusinessException(ResultCode.NOT_FOUND, "提示词配置不存在");
|
throw new BusinessException(ResultCode.NOT_FOUND, "提示词配置不存在");
|
||||||
}
|
}
|
||||||
@@ -127,12 +156,8 @@ public class SysConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TaskModelConfigResponse toResponse(ResolvedModelConfig config) {
|
public TaskModelConfigResponse toResponse(ResolvedModelConfig config) {
|
||||||
return new TaskModelConfigResponse(
|
return new TaskModelConfigResponse(config.configId(), config.configName(), config.modelName(),
|
||||||
config.configId(),
|
config.modelUrl(), maskSecret(config.apiKey()));
|
||||||
config.configName(),
|
|
||||||
config.modelName(),
|
|
||||||
config.modelUrl(),
|
|
||||||
maskSecret(config.apiKey()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskPromptConfigResponse toResponse(ResolvedPromptConfig config) {
|
public TaskPromptConfigResponse toResponse(ResolvedPromptConfig config) {
|
||||||
@@ -140,14 +165,8 @@ public class SysConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SysConfigResponse toResponse(SysConfig config) {
|
public SysConfigResponse toResponse(SysConfig config) {
|
||||||
return new SysConfigResponse(
|
return new SysConfigResponse(config.getId(), config.getConfigType(), config.getConfigName(),
|
||||||
config.getId(),
|
config.getConfigValue(), config.getStatus(), config.getCreatorId(), config.getCreatedAt(),
|
||||||
config.getConfigType(),
|
|
||||||
config.getConfigName(),
|
|
||||||
config.getConfigValue(),
|
|
||||||
config.getStatus(),
|
|
||||||
config.getCreatorId(),
|
|
||||||
config.getCreatedAt(),
|
|
||||||
config.getUpdatedAt());
|
config.getUpdatedAt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,45 +174,39 @@ public class SysConfigService {
|
|||||||
if (!StringUtils.hasText(configName)) {
|
if (!StringUtils.hasText(configName)) {
|
||||||
throw new BusinessException(ResultCode.BAD_REQUEST, "模型配置名称不能为空");
|
throw new BusinessException(ResultCode.BAD_REQUEST, "模型配置名称不能为空");
|
||||||
}
|
}
|
||||||
SysConfig config = sysConfigMapper.findByCompanyIdAndConfigNameAndType(
|
SysConfig config = sysConfigMapper.findByCompanyIdAndConfigNameAndType(currentUser.companyId(), configName,
|
||||||
currentUser.companyId(), configName, ConfigType.MODEL.name());
|
ConfigType.MODEL.name());
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
throw new BusinessException(ResultCode.NOT_FOUND, "模型配置不存在");
|
throw new BusinessException(ResultCode.NOT_FOUND, "模型配置不存在");
|
||||||
}
|
}
|
||||||
ModelConfigValue configValue = parseModelConfig(config.getConfigValue());
|
ModelConfigValue configValue = parseModelConfig(config.getConfigValue());
|
||||||
return new ResolvedModelConfig(config.getId(), config.getConfigName(),
|
return new ResolvedModelConfig(config.getId(), config.getConfigName(), configValue.modelName(),
|
||||||
configValue.modelName(), configValue.modelUrl(), configValue.apiKey());
|
configValue.modelUrl(), configValue.apiKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResolvedModelConfig resolveManualModel(LoginUser currentUser, ManualModelConfigRequest request) {
|
private ResolvedModelConfig resolveManualModel(LoginUser currentUser, ManualModelConfigRequest request) {
|
||||||
if (request == null || !StringUtils.hasText(request.modelName())
|
if (request == null || !StringUtils.hasText(request.modelName()) || !StringUtils.hasText(request.modelUrl())
|
||||||
|| !StringUtils.hasText(request.modelUrl()) || !StringUtils.hasText(request.apiKey())) {
|
|| !StringUtils.hasText(request.apiKey())) {
|
||||||
throw new BusinessException(ResultCode.BAD_REQUEST, "手动模型配置不完整");
|
throw new BusinessException(ResultCode.BAD_REQUEST, "手动模型配置不完整");
|
||||||
}
|
}
|
||||||
SysConfig existing = sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.modelName());
|
SysConfig existing = sysConfigMapper.findByCompanyIdAndConfigName(currentUser.companyId(), request.modelName());
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
String configValue = writeModelConfig(request);
|
String configValue = writeModelConfig(request);
|
||||||
SysConfig config = SysConfig.builder()
|
SysConfig config = SysConfig.builder().id(IdGenerator.nextId()).companyId(currentUser.companyId())
|
||||||
.id(IdGenerator.nextId())
|
.configType(ConfigType.MODEL.name()).configName(request.modelName()).configValue(configValue)
|
||||||
.companyId(currentUser.companyId())
|
.status("ENABLED").creatorId(currentUser.userId()).build();
|
||||||
.configType(ConfigType.MODEL.name())
|
|
||||||
.configName(request.modelName())
|
|
||||||
.configValue(configValue)
|
|
||||||
.status("ENABLED")
|
|
||||||
.creatorId(currentUser.userId())
|
|
||||||
.build();
|
|
||||||
sysConfigMapper.insert(config);
|
sysConfigMapper.insert(config);
|
||||||
log.info("auto created model config, companyId={}, userId={}, configName={}",
|
log.info("auto created model config, companyId={}, userId={}, configName={}", currentUser.companyId(),
|
||||||
currentUser.companyId(), currentUser.userId(), request.modelName());
|
currentUser.userId(), request.modelName());
|
||||||
return new ResolvedModelConfig(config.getId(), config.getConfigName(),
|
return new ResolvedModelConfig(config.getId(), config.getConfigName(), request.modelName(),
|
||||||
request.modelName(), request.modelUrl(), request.apiKey());
|
request.modelUrl(), request.apiKey());
|
||||||
}
|
}
|
||||||
if (!ConfigType.MODEL.name().equals(existing.getConfigType())) {
|
if (!ConfigType.MODEL.name().equals(existing.getConfigType())) {
|
||||||
throw new BusinessException(ResultCode.CONFLICT, "同名配置已被其他类型占用");
|
throw new BusinessException(ResultCode.CONFLICT, "同名配置已被其他类型占用");
|
||||||
}
|
}
|
||||||
ModelConfigValue configValue = parseModelConfig(existing.getConfigValue());
|
ModelConfigValue configValue = parseModelConfig(existing.getConfigValue());
|
||||||
return new ResolvedModelConfig(existing.getId(), existing.getConfigName(),
|
return new ResolvedModelConfig(existing.getId(), existing.getConfigName(), configValue.modelName(),
|
||||||
configValue.modelName(), configValue.modelUrl(), configValue.apiKey());
|
configValue.modelUrl(), configValue.apiKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysConfig getConfigEntity(LoginUser currentUser, Long configId) {
|
private SysConfig getConfigEntity(LoginUser currentUser, Long configId) {
|
||||||
@@ -220,10 +233,8 @@ public class SysConfigService {
|
|||||||
|
|
||||||
private String writeModelConfig(ManualModelConfigRequest request) {
|
private String writeModelConfig(ManualModelConfigRequest request) {
|
||||||
try {
|
try {
|
||||||
return objectMapper.writeValueAsString(Map.of(
|
return objectMapper.writeValueAsString(
|
||||||
"modelName", request.modelName(),
|
Map.of("modelName", request.modelName(), "modelUrl", request.modelUrl(), "apiKey", request.apiKey()));
|
||||||
"modelUrl", request.modelUrl(),
|
|
||||||
"apiKey", request.apiKey()));
|
|
||||||
} catch (JsonProcessingException ex) {
|
} catch (JsonProcessingException ex) {
|
||||||
throw new BusinessException(ResultCode.BAD_REQUEST, "模型配置值生成失败");
|
throw new BusinessException(ResultCode.BAD_REQUEST, "模型配置值生成失败");
|
||||||
}
|
}
|
||||||
@@ -239,20 +250,19 @@ public class SysConfigService {
|
|||||||
return "****" + secret.substring(secret.length() - 4);
|
return "****" + secret.substring(secret.length() - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> PageResult<T> paginate(List<T> records, Integer pageNo, Integer pageSize) {
|
// private <T> PageResult<T> paginate(List<T> records, Integer pageNo, Integer pageSize) {
|
||||||
int actualPageNo = pageNo == null || pageNo < 1 ? 1 : pageNo;
|
// int actualPageNo = pageNo == null || pageNo < 1 ? 1 : pageNo;
|
||||||
int actualPageSize = pageSize == null || pageSize < 1 ? 10 : pageSize;
|
// int actualPageSize = pageSize == null || pageSize < 1 ? 10 : pageSize;
|
||||||
int fromIndex = Math.min((actualPageNo - 1) * actualPageSize, records.size());
|
// int fromIndex = Math.min((actualPageNo - 1) * actualPageSize, records.size());
|
||||||
int toIndex = Math.min(fromIndex + actualPageSize, records.size());
|
// int toIndex = Math.min(fromIndex + actualPageSize, records.size());
|
||||||
return new PageResult<>(records.subList(fromIndex, toIndex), (long) records.size(), actualPageNo, actualPageSize);
|
// return new PageResult<>(records.subList(fromIndex, toIndex), (long)records.size(), actualPageNo,
|
||||||
}
|
// actualPageSize);
|
||||||
|
// }
|
||||||
|
|
||||||
private record ModelConfigValue(String modelName, String modelUrl, String apiKey) {
|
private record ModelConfigValue(String modelName, String modelUrl, String apiKey) {}
|
||||||
}
|
|
||||||
|
|
||||||
public record ResolvedModelConfig(Long configId, String configName, String modelName, String modelUrl, String apiKey) {
|
public record ResolvedModelConfig(Long configId, String configName, String modelName, String modelUrl,
|
||||||
}
|
String apiKey) {}
|
||||||
|
|
||||||
public record ResolvedPromptConfig(Long configId, String configName, String promptText) {
|
public record ResolvedPromptConfig(Long configId, String configName, String promptText) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,26 +33,26 @@ INSERT INTO sys_menu (id, company_id, menu_code, menu_name, path, visible_positi
|
|||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO sys_config (
|
INSERT INTO sys_config (
|
||||||
id, company_id, config_type, config_name, config_value, status, creator_id
|
id, company_id, config_type, config_name, config_value, status, creator_id, creator_role
|
||||||
) VALUES
|
) VALUES
|
||||||
(401, 2, 'MODEL', 'qwen-max',
|
(401, 2, 'MODEL', 'qwen-max',
|
||||||
'{"modelUrl":"https://api.example.com/extract","apiKey":"extract-api-key-demo"}', 'ENABLED', 2),
|
'{"modelUrl":"https://api.example.com/extract","apiKey":"extract-api-key-demo"}', 'ENABLED', 2, 'ENGINEER'),
|
||||||
(402, 2, 'MODEL', 'glm-4.5',
|
(402, 2, 'MODEL', 'glm-4.5',
|
||||||
'{"modelUrl":"https://api.example.com/verify","apiKey":"verify-api-key-demo"}', 'ENABLED', 2),
|
'{"modelUrl":"https://api.example.com/verify","apiKey":"verify-api-key-demo"}', 'ENABLED', 2, 'ENGINEER'),
|
||||||
(403, 2, 'PROMPT', 'extractPrompt',
|
(403, 2, 'PROMPT', 'extractPrompt',
|
||||||
'请根据输入内容提取结构化问答对。', 'ENABLED', 2),
|
'请根据输入内容提取结构化问答对。', 'ENABLED', 2,'ENGINEER'),
|
||||||
(404, 2, 'PROMPT', 'verifyPrompt',
|
(404, 2, 'PROMPT', 'verifyPrompt',
|
||||||
'请核验抽取结果是否准确,并给出修正答案。', 'ENABLED', 2),
|
'请核验抽取结果是否准确,并给出修正答案。', 'ENABLED', 2,'ENGINEER'),
|
||||||
(406, 2, 'MODEL', 'qwen-vl-max',
|
(406, 2, 'MODEL', 'qwen-vl-max',
|
||||||
'{"modelUrl":"https://api.example.com/extract-vl","apiKey":"extract-vl-api-key-demo"}', 'ENABLED', 2),
|
'{"modelUrl":"https://api.example.com/extract-vl","apiKey":"extract-vl-api-key-demo"}', 'ENABLED', 2,'ENGINEER'),
|
||||||
(407, 2, 'MODEL', 'glm-4.5v',
|
(407, 2, 'MODEL', 'glm-4.5v',
|
||||||
'{"modelUrl":"https://api.example.com/verify-vl","apiKey":"verify-vl-api-key-demo"}', 'ENABLED', 2),
|
'{"modelUrl":"https://api.example.com/verify-vl","apiKey":"verify-vl-api-key-demo"}', 'ENABLED', 2,'ENGINEER'),
|
||||||
(408, 2, 'PROMPT', 'imageExtractPrompt',
|
(408, 2, 'PROMPT', 'imageExtractPrompt',
|
||||||
'请根据输入图片内容提取结构化问答对。', 'ENABLED', 2),
|
'请根据输入图片内容提取结构化问答对。', 'ENABLED', 2,'ENGINEER'),
|
||||||
(409, 2, 'PROMPT', 'imageVerifyPrompt',
|
(409, 2, 'PROMPT', 'imageVerifyPrompt',
|
||||||
'请核验图片问答结果是否准确。', 'ENABLED', 2),
|
'请核验图片问答结果是否准确。', 'ENABLED', 2,'ENGINEER'),
|
||||||
(405, 2, 'SYSTEM', 'storageProvider',
|
(405, 2, 'SYSTEM', 'storageProvider',
|
||||||
'{"provider":"rustfs","defaultBucket":"source-data"}', 'ENABLED', 2)
|
'{"provider":"rustfs","defaultBucket":"source-data"}', 'ENABLED', 2,'ENGINEER')
|
||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO source_resource (
|
INSERT INTO source_resource (
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ CREATE TABLE IF NOT EXISTS sys_config (
|
|||||||
config_value TEXT NOT NULL,
|
config_value TEXT NOT NULL,
|
||||||
status VARCHAR(32) NOT NULL DEFAULT 'ENABLED',
|
status VARCHAR(32) NOT NULL DEFAULT 'ENABLED',
|
||||||
creator_id BIGINT NOT NULL,
|
creator_id BIGINT NOT NULL,
|
||||||
|
creator_role VARCHAR(50) NOT NULL DEFAULT 'EMPLOYEE',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
CONSTRAINT uq_sys_config_company_name UNIQUE (company_id, config_name),
|
CONSTRAINT uq_sys_config_company_name UNIQUE (company_id, config_name),
|
||||||
@@ -113,6 +114,7 @@ COMMENT ON COLUMN sys_config.config_name IS '配置名称。MODEL 类型时存
|
|||||||
COMMENT ON COLUMN sys_config.config_value IS '配置值。MODEL 类型建议保存 JSON,至少包含 modelName、modelUrl、apiKey;PROMPT 类型保存提示词文本;SYSTEM 类型预留后续扩展。';
|
COMMENT ON COLUMN sys_config.config_value IS '配置值。MODEL 类型建议保存 JSON,至少包含 modelName、modelUrl、apiKey;PROMPT 类型保存提示词文本;SYSTEM 类型预留后续扩展。';
|
||||||
COMMENT ON COLUMN sys_config.status IS '配置状态,默认 ENABLED。';
|
COMMENT ON COLUMN sys_config.status IS '配置状态,默认 ENABLED。';
|
||||||
COMMENT ON COLUMN sys_config.creator_id IS '创建人用户ID。';
|
COMMENT ON COLUMN sys_config.creator_id IS '创建人用户ID。';
|
||||||
|
COMMENT ON COLUMN sys_config.creator_role IS '创建人角色.默认 EMPLOYEE。';
|
||||||
COMMENT ON COLUMN sys_config.created_at IS '创建时间。';
|
COMMENT ON COLUMN sys_config.created_at IS '创建时间。';
|
||||||
COMMENT ON COLUMN sys_config.updated_at IS '更新时间。';
|
COMMENT ON COLUMN sys_config.updated_at IS '更新时间。';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user