feat(skill): 补齐版本测试发布与工作台链路
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package com.bruce.skill.controller;
|
||||
|
||||
import com.bruce.common.domain.model.RequestResult;
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.service.ISkillVersionService;
|
||||
import com.bruce.skill.service.ISkillWorkspaceService;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import com.bruce.skill.vo.SkillWorkspaceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Skill 工作台接口,首轮对齐前端原型中的详情、草稿、测试、发布和归档能力。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/skills")
|
||||
@RequiredArgsConstructor
|
||||
public class SkillWorkspaceController {
|
||||
|
||||
private final ISkillWorkspaceService skillWorkspaceService;
|
||||
private final ISkillVersionService skillVersionService;
|
||||
|
||||
@GetMapping("/{skillCode}")
|
||||
public RequestResult<SkillWorkspaceVO> detail(@PathVariable("skillCode") String skillCode) {
|
||||
return RequestResult.success(skillWorkspaceService.getWorkspace(skillCode));
|
||||
}
|
||||
|
||||
@PostMapping("/{skillCode}/draft")
|
||||
public RequestResult<Boolean> saveDraft(@PathVariable("skillCode") String skillCode,
|
||||
@RequestBody SkillVersionSaveDTO request) {
|
||||
return RequestResult.success(skillVersionService.saveDraft(skillCode, request));
|
||||
}
|
||||
|
||||
@PostMapping("/{skillCode}/test")
|
||||
public RequestResult<SkillVersionVO> test(@PathVariable("skillCode") String skillCode,
|
||||
@RequestBody SkillVersionSaveDTO request) {
|
||||
return RequestResult.success(skillVersionService.test(skillCode, request));
|
||||
}
|
||||
|
||||
@PostMapping("/{skillCode}/publish")
|
||||
public RequestResult<Boolean> publish(@PathVariable("skillCode") String skillCode,
|
||||
@RequestBody SkillVersionSaveDTO request) {
|
||||
return RequestResult.success(skillVersionService.publish(skillCode, request));
|
||||
}
|
||||
|
||||
@PostMapping("/{skillCode}/archive")
|
||||
public RequestResult<Boolean> archive(@PathVariable("skillCode") String skillCode,
|
||||
@RequestParam("versionNo") Integer versionNo) {
|
||||
return RequestResult.success(skillVersionService.archive(skillCode, versionNo));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bruce.skill.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SkillDefinitionSaveDTO {
|
||||
private Long id;
|
||||
private String skillCode;
|
||||
private String skillName;
|
||||
private String skillType;
|
||||
private String description;
|
||||
private String status;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.bruce.skill.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SkillVersionSaveDTO {
|
||||
private Long id;
|
||||
private Long skillId;
|
||||
private Integer versionNo;
|
||||
private String promptText;
|
||||
private String codeText;
|
||||
private String configJson;
|
||||
private String variableSchemaJson;
|
||||
private String testResultJson;
|
||||
private String publishStatus;
|
||||
private String remark;
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import lombok.EqualsAndHashCode;
|
||||
@TableName("skill_definition")
|
||||
public class SkillDefinition extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String skillCode;
|
||||
|
||||
private String skillName;
|
||||
@@ -22,4 +24,6 @@ public class SkillDefinition extends BaseEntity {
|
||||
private String description;
|
||||
|
||||
private String status;
|
||||
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import lombok.EqualsAndHashCode;
|
||||
@TableName("skill_version")
|
||||
public class SkillVersion extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long skillId;
|
||||
|
||||
private Integer versionNo;
|
||||
@@ -35,4 +37,6 @@ public class SkillVersion extends BaseEntity {
|
||||
private String publishStatus;
|
||||
|
||||
private java.time.LocalDateTime publishedTime;
|
||||
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.bruce.skill.factory;
|
||||
|
||||
import com.bruce.skill.dto.SkillDefinitionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Skill 定义工厂,统一处理定义保存对象、实体和返回对象转换。
|
||||
*/
|
||||
@Component
|
||||
public class SkillDefinitionFactory {
|
||||
|
||||
public SkillDefinition toEntity(SkillDefinitionSaveDTO request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
SkillDefinition entity = new SkillDefinition();
|
||||
entity.setId(request.getId());
|
||||
entity.setSkillCode(trimToNull(request.getSkillCode()));
|
||||
entity.setSkillName(trimToNull(request.getSkillName()));
|
||||
entity.setSkillType(trimToNull(request.getSkillType()));
|
||||
entity.setDescription(trimToNull(request.getDescription()));
|
||||
entity.setStatus(trimToNull(request.getStatus()));
|
||||
entity.setRemark(trimToNull(request.getRemark()));
|
||||
return entity;
|
||||
}
|
||||
|
||||
public SkillDefinitionVO toVO(SkillDefinition entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
SkillDefinitionVO vo = new SkillDefinitionVO();
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
return vo;
|
||||
}
|
||||
|
||||
public List<SkillDefinitionVO> toVOList(List<SkillDefinition> entities) {
|
||||
return entities == null ? List.of() : entities.stream().map(this::toVO).toList();
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.bruce.skill.factory;
|
||||
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Skill 版本工厂,统一处理版本草稿、测试和发布对象转换。
|
||||
*/
|
||||
@Component
|
||||
public class SkillVersionFactory {
|
||||
|
||||
public SkillVersion toEntity(SkillVersionSaveDTO request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
SkillVersion entity = new SkillVersion();
|
||||
entity.setId(request.getId());
|
||||
entity.setSkillId(request.getSkillId());
|
||||
entity.setVersionNo(request.getVersionNo());
|
||||
entity.setPromptText(trimToNull(request.getPromptText()));
|
||||
entity.setCodeText(trimToNull(request.getCodeText()));
|
||||
entity.setConfigJson(trimToNull(request.getConfigJson()));
|
||||
entity.setVariableSchemaJson(trimToNull(request.getVariableSchemaJson()));
|
||||
entity.setTestResultJson(trimToNull(request.getTestResultJson()));
|
||||
entity.setPublishStatus(trimToNull(request.getPublishStatus()));
|
||||
entity.setRemark(trimToNull(request.getRemark()));
|
||||
return entity;
|
||||
}
|
||||
|
||||
public SkillVersionVO toVO(SkillVersion entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
SkillVersionVO vo = new SkillVersionVO();
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
return vo;
|
||||
}
|
||||
|
||||
public List<SkillVersionVO> toVOList(List<SkillVersion> entities) {
|
||||
return entities == null ? List.of() : entities.stream().map(this::toVO).toList();
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.bruce.skill.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SkillDefinitionMapper extends BaseMapper<SkillDefinition> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.bruce.skill.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SkillVersionMapper extends BaseMapper<SkillVersion> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.bruce.skill.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bruce.skill.dto.SkillDefinitionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ISkillDefinitionService extends IService<SkillDefinition> {
|
||||
|
||||
SkillDefinition getByCode(String skillCode);
|
||||
|
||||
List<SkillDefinitionVO> listDefinitions();
|
||||
|
||||
boolean saveDefinition(SkillDefinitionSaveDTO request);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.bruce.skill.service;
|
||||
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
|
||||
public interface ISkillRunner {
|
||||
|
||||
/**
|
||||
* 执行 Skill 草稿测试,首轮使用受控 mock 结果支撑工作台联调。
|
||||
*/
|
||||
String runTest(SkillDefinition definition, SkillVersion version);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.bruce.skill.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ISkillVersionService extends IService<SkillVersion> {
|
||||
|
||||
boolean saveDraft(String skillCode, SkillVersionSaveDTO request);
|
||||
|
||||
SkillVersionVO test(String skillCode, SkillVersionSaveDTO request);
|
||||
|
||||
boolean publish(String skillCode, SkillVersionSaveDTO request);
|
||||
|
||||
boolean archive(String skillCode, Integer versionNo);
|
||||
|
||||
List<SkillVersionVO> listBySkillId(Long skillId);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.bruce.skill.service;
|
||||
|
||||
import com.bruce.skill.vo.SkillWorkspaceVO;
|
||||
|
||||
public interface ISkillWorkspaceService {
|
||||
|
||||
SkillWorkspaceVO getWorkspace(String skillCode);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.bruce.skill.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bruce.skill.dto.SkillDefinitionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.factory.SkillDefinitionFactory;
|
||||
import com.bruce.skill.mapper.SkillDefinitionMapper;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SkillDefinitionServiceImpl extends ServiceImpl<SkillDefinitionMapper, SkillDefinition> implements ISkillDefinitionService {
|
||||
|
||||
private final SkillDefinitionFactory skillDefinitionFactory;
|
||||
|
||||
@Override
|
||||
public SkillDefinition getByCode(String skillCode) {
|
||||
if (!StringUtils.hasText(skillCode)) {
|
||||
throw new IllegalArgumentException("Skill编码不能为空");
|
||||
}
|
||||
SkillDefinition result = lambdaQuery()
|
||||
.eq(SkillDefinition::getSkillCode, skillCode.trim())
|
||||
.one();
|
||||
log.info("按编码查询Skill定义完成,skillCode={}, found={}", skillCode.trim(), result != null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SkillDefinitionVO> listDefinitions() {
|
||||
List<SkillDefinitionVO> result = skillDefinitionFactory.toVOList(lambdaQuery()
|
||||
.orderByAsc(SkillDefinition::getSkillCode)
|
||||
.list());
|
||||
log.info("查询Skill定义列表完成,count={}", result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveDefinition(SkillDefinitionSaveDTO request) {
|
||||
validateRequest(request);
|
||||
SkillDefinition duplicate = lambdaQuery()
|
||||
.eq(SkillDefinition::getSkillCode, request.getSkillCode().trim())
|
||||
.ne(request.getId() != null, SkillDefinition::getId, request.getId())
|
||||
.one();
|
||||
if (duplicate != null) {
|
||||
throw new IllegalArgumentException("Skill编码已存在: " + request.getSkillCode().trim());
|
||||
}
|
||||
SkillDefinition requestEntity = skillDefinitionFactory.toEntity(request);
|
||||
SkillDefinition entity = request.getId() == null ? new SkillDefinition() : getById(request.getId());
|
||||
if (request.getId() != null && entity == null) {
|
||||
throw new IllegalArgumentException("Skill定义不存在,ID: " + request.getId());
|
||||
}
|
||||
if (entity == null) {
|
||||
entity = requestEntity;
|
||||
if (!StringUtils.hasText(entity.getStatus())) {
|
||||
entity.setStatus("DRAFT");
|
||||
}
|
||||
boolean result = save(entity);
|
||||
log.info("新增Skill定义完成,skillCode={}, result={}", entity.getSkillCode(), result);
|
||||
return result;
|
||||
}
|
||||
entity.setSkillCode(requestEntity.getSkillCode());
|
||||
entity.setSkillName(requestEntity.getSkillName());
|
||||
entity.setSkillType(requestEntity.getSkillType());
|
||||
entity.setDescription(requestEntity.getDescription());
|
||||
entity.setStatus(StringUtils.hasText(requestEntity.getStatus()) ? requestEntity.getStatus() : entity.getStatus());
|
||||
entity.setRemark(requestEntity.getRemark());
|
||||
boolean result = updateById(entity);
|
||||
log.info("更新Skill定义完成,skillId={}, skillCode={}, result={}", entity.getId(), entity.getSkillCode(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void validateRequest(SkillDefinitionSaveDTO request) {
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("Skill定义保存请求不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(request.getSkillCode())) {
|
||||
throw new IllegalArgumentException("Skill编码不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(request.getSkillName())) {
|
||||
throw new IllegalArgumentException("Skill名称不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(request.getSkillType())) {
|
||||
throw new IllegalArgumentException("Skill类型不能为空");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.bruce.skill.service.impl;
|
||||
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.service.ISkillRunner;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Skill 测试执行器首轮采用 mock 执行,先保证工作台编辑、测试、保存链路打通。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SkillRunnerImpl implements ISkillRunner {
|
||||
|
||||
@Override
|
||||
public String runTest(SkillDefinition definition, SkillVersion version) {
|
||||
log.info("Skill测试执行开始,skillId={}, skillCode={}, versionNo={}",
|
||||
definition.getId(), definition.getSkillCode(), version.getVersionNo());
|
||||
String result = """
|
||||
{"quality_score":0.86,"summary":"建议补充日志留存周期引用,并明确私有化部署边界","skillCode":"%s","versionNo":%d}
|
||||
""".formatted(definition.getSkillCode(), version.getVersionNo());
|
||||
log.info("Skill测试执行结束,skillId={}, skillCode={}, versionNo={}",
|
||||
definition.getId(), definition.getSkillCode(), version.getVersionNo());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.bruce.skill.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.factory.SkillVersionFactory;
|
||||
import com.bruce.skill.mapper.SkillVersionMapper;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.service.ISkillRunner;
|
||||
import com.bruce.skill.service.ISkillVersionService;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SkillVersionServiceImpl extends ServiceImpl<SkillVersionMapper, SkillVersion> implements ISkillVersionService {
|
||||
|
||||
private final ISkillDefinitionService skillDefinitionService;
|
||||
private final ISkillRunner skillRunner;
|
||||
private final SkillVersionFactory skillVersionFactory;
|
||||
|
||||
@Override
|
||||
public boolean saveDraft(String skillCode, SkillVersionSaveDTO request) {
|
||||
SkillVersion entity = buildDraftEntity(skillCode, request, false);
|
||||
boolean result = entity.getId() == null ? save(entity) : updateById(entity);
|
||||
log.info("保存Skill草稿完成,skillId={}, versionNo={}, result={}", entity.getSkillId(), entity.getVersionNo(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillVersionVO test(String skillCode, SkillVersionSaveDTO request) {
|
||||
SkillDefinition definition = loadDefinitionByCode(skillCode);
|
||||
SkillVersion entity = buildDraftEntity(skillCode, request, false);
|
||||
entity.setTestResultJson(skillRunner.runTest(definition, entity));
|
||||
boolean result = entity.getId() == null ? save(entity) : updateById(entity);
|
||||
log.info("测试Skill草稿完成,skillId={}, versionNo={}, persistResult={}", entity.getSkillId(), entity.getVersionNo(), result);
|
||||
return skillVersionFactory.toVO(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean publish(String skillCode, SkillVersionSaveDTO request) {
|
||||
SkillVersion entity = buildDraftEntity(skillCode, request, true);
|
||||
entity.setPublishStatus("PUBLISHED");
|
||||
entity.setPublishedTime(LocalDateTime.now());
|
||||
boolean result = entity.getId() == null ? save(entity) : updateById(entity);
|
||||
|
||||
SkillDefinition definition = loadDefinitionByCode(skillCode);
|
||||
definition.setStatus("PUBLISHED");
|
||||
skillDefinitionService.updateById(definition);
|
||||
log.info("发布Skill版本完成,skillId={}, versionNo={}, result={}", entity.getSkillId(), entity.getVersionNo(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean archive(String skillCode, Integer versionNo) {
|
||||
SkillDefinition definition = loadDefinitionByCode(skillCode);
|
||||
if (versionNo == null) {
|
||||
throw new IllegalArgumentException("版本号不能为空");
|
||||
}
|
||||
SkillVersion version = findBySkillAndVersionNo(definition.getId(), versionNo);
|
||||
if (version == null) {
|
||||
throw new IllegalArgumentException("Skill版本不存在,skillCode=%s, versionNo=%d".formatted(skillCode, versionNo));
|
||||
}
|
||||
version.setPublishStatus("ARCHIVED");
|
||||
boolean result = updateById(version);
|
||||
log.info("归档Skill版本完成,skillId={}, versionNo={}, result={}", definition.getId(), versionNo, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SkillVersionVO> listBySkillId(Long skillId) {
|
||||
if (skillId == null) {
|
||||
throw new IllegalArgumentException("Skill ID不能为空");
|
||||
}
|
||||
List<SkillVersionVO> result = skillVersionFactory.toVOList(lambdaQuery()
|
||||
.eq(SkillVersion::getSkillId, skillId)
|
||||
.orderByDesc(SkillVersion::getVersionNo)
|
||||
.list());
|
||||
log.info("查询Skill版本列表完成,skillId={}, count={}", skillId, result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
public SkillDefinition loadDefinitionByCode(String skillCode) {
|
||||
SkillDefinition definition = skillDefinitionService.getByCode(skillCode);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Skill定义不存在,skillCode: " + skillCode);
|
||||
}
|
||||
return definition;
|
||||
}
|
||||
|
||||
public SkillVersion findBySkillAndVersionNo(Long skillId, Integer versionNo) {
|
||||
if (skillId == null || versionNo == null) {
|
||||
return null;
|
||||
}
|
||||
return lambdaQuery()
|
||||
.eq(SkillVersion::getSkillId, skillId)
|
||||
.eq(SkillVersion::getVersionNo, versionNo)
|
||||
.one();
|
||||
}
|
||||
|
||||
private SkillVersion buildDraftEntity(String skillCode, SkillVersionSaveDTO request, boolean publishing) {
|
||||
SkillDefinition definition = loadDefinitionByCode(skillCode);
|
||||
validateRequest(request, publishing);
|
||||
SkillVersion duplicate = findBySkillAndVersionNo(definition.getId(), request.getVersionNo());
|
||||
if (duplicate != null && request.getId() == null && publishing) {
|
||||
throw new IllegalArgumentException("Skill版本号已存在: " + request.getVersionNo());
|
||||
}
|
||||
|
||||
SkillVersion requestEntity = skillVersionFactory.toEntity(request);
|
||||
SkillVersion entity = request.getId() == null ? duplicate : getById(request.getId());
|
||||
if (request.getId() != null && entity == null) {
|
||||
throw new IllegalArgumentException("Skill版本不存在,ID: " + request.getId());
|
||||
}
|
||||
if (entity == null) {
|
||||
entity = new SkillVersion();
|
||||
}
|
||||
entity.setId(request.getId() == null ? entity.getId() : request.getId());
|
||||
entity.setSkillId(definition.getId());
|
||||
entity.setVersionNo(requestEntity.getVersionNo());
|
||||
entity.setPromptText(requestEntity.getPromptText());
|
||||
entity.setCodeText(requestEntity.getCodeText());
|
||||
entity.setConfigJson(defaultJson(requestEntity.getConfigJson()));
|
||||
entity.setVariableSchemaJson(defaultJson(requestEntity.getVariableSchemaJson()));
|
||||
entity.setTestResultJson(defaultJson(requestEntity.getTestResultJson()));
|
||||
entity.setPublishStatus(StringUtils.hasText(requestEntity.getPublishStatus()) ? requestEntity.getPublishStatus() : "DRAFT");
|
||||
entity.setRemark(requestEntity.getRemark());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void validateRequest(SkillVersionSaveDTO request, boolean publishing) {
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("Skill版本请求不能为空");
|
||||
}
|
||||
if (request.getVersionNo() == null) {
|
||||
throw new IllegalArgumentException("版本号不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(request.getPromptText())
|
||||
&& !StringUtils.hasText(request.getCodeText())
|
||||
&& !hasMeaningfulJson(request.getConfigJson())) {
|
||||
throw new IllegalArgumentException("Prompt、Code、Config 至少填写一项");
|
||||
}
|
||||
validateJson(request.getConfigJson(), "configJson");
|
||||
validateJson(request.getVariableSchemaJson(), "variableSchemaJson");
|
||||
validateJson(request.getTestResultJson(), "testResultJson");
|
||||
if (publishing && !StringUtils.hasText(request.getTestResultJson())) {
|
||||
log.info("发布Skill时未显式传测试结果,后续以当前草稿快照为准,versionNo={}", request.getVersionNo());
|
||||
}
|
||||
}
|
||||
|
||||
private void validateJson(String json, String fieldName) {
|
||||
if (!StringUtils.hasText(json)) {
|
||||
return;
|
||||
}
|
||||
String normalized = json.trim();
|
||||
boolean isObject = normalized.startsWith("{") && normalized.endsWith("}");
|
||||
boolean isArray = normalized.startsWith("[") && normalized.endsWith("]");
|
||||
if (!isObject && !isArray) {
|
||||
throw new IllegalArgumentException(fieldName + "必须是合法JSON");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasMeaningfulJson(String json) {
|
||||
return StringUtils.hasText(json) && !"{}".equals(json.trim()) && !"[]".equals(json.trim());
|
||||
}
|
||||
|
||||
private String defaultJson(String json) {
|
||||
return StringUtils.hasText(json) ? json.trim() : "{}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.bruce.skill.service.impl;
|
||||
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.service.ISkillVersionService;
|
||||
import com.bruce.skill.service.ISkillWorkspaceService;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import com.bruce.skill.vo.SkillWorkspaceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SkillWorkspaceServiceImpl implements ISkillWorkspaceService {
|
||||
|
||||
private final ISkillDefinitionService skillDefinitionService;
|
||||
private final ISkillVersionService skillVersionService;
|
||||
|
||||
@Override
|
||||
public SkillWorkspaceVO getWorkspace(String skillCode) {
|
||||
log.info("Skill工作台查询开始,skillCode={}", skillCode);
|
||||
SkillDefinition definition = skillDefinitionService.getByCode(skillCode);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Skill定义不存在,skillCode: " + skillCode);
|
||||
}
|
||||
List<SkillDefinitionVO> skills = skillDefinitionService.listDefinitions();
|
||||
List<SkillVersionVO> versions = skillVersionService.listBySkillId(definition.getId());
|
||||
|
||||
SkillWorkspaceVO workspace = new SkillWorkspaceVO();
|
||||
workspace.setSkillId(definition.getId());
|
||||
workspace.setSkillCode(definition.getSkillCode());
|
||||
workspace.setSkillName(definition.getSkillName());
|
||||
workspace.setSkillType(definition.getSkillType());
|
||||
workspace.setDescription(definition.getDescription());
|
||||
workspace.setStatus(definition.getStatus());
|
||||
workspace.setSkills(skills);
|
||||
workspace.setVersions(versions);
|
||||
|
||||
SkillVersionVO publishedVersion = versions.stream()
|
||||
.filter(item -> "PUBLISHED".equals(item.getPublishStatus()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (publishedVersion != null) {
|
||||
workspace.setPublishedVersionNo(publishedVersion.getVersionNo());
|
||||
}
|
||||
SkillVersionVO latestVersion = versions.isEmpty() ? null : versions.getFirst();
|
||||
if (latestVersion != null) {
|
||||
workspace.setLatestTestResultJson(latestVersion.getTestResultJson());
|
||||
}
|
||||
log.info("Skill工作台查询结束,skillCode={}, versionCount={}, publishedVersionNo={}",
|
||||
skillCode, versions.size(), workspace.getPublishedVersionNo());
|
||||
return workspace;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bruce.skill.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SkillDefinitionVO {
|
||||
private Long id;
|
||||
private String skillCode;
|
||||
private String skillName;
|
||||
private String skillType;
|
||||
private String description;
|
||||
private String status;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.bruce.skill.vo;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SkillVersionVO {
|
||||
private Long id;
|
||||
private Long skillId;
|
||||
private Integer versionNo;
|
||||
private String promptText;
|
||||
private String codeText;
|
||||
private String configJson;
|
||||
private String variableSchemaJson;
|
||||
private String testResultJson;
|
||||
private String publishStatus;
|
||||
private LocalDateTime publishedTime;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.bruce.skill.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SkillWorkspaceVO {
|
||||
private Long skillId;
|
||||
private String skillCode;
|
||||
private String skillName;
|
||||
private String skillType;
|
||||
private String description;
|
||||
private String status;
|
||||
private Integer publishedVersionNo;
|
||||
private String latestTestResultJson;
|
||||
private List<SkillDefinitionVO> skills;
|
||||
private List<SkillVersionVO> versions;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.bruce.skill;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bruce.common.domain.model.RequestResult;
|
||||
import com.bruce.skill.controller.SkillWorkspaceController;
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.mapper.SkillDefinitionMapper;
|
||||
import com.bruce.skill.mapper.SkillVersionMapper;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.service.ISkillVersionService;
|
||||
import com.bruce.skill.service.ISkillWorkspaceService;
|
||||
import com.bruce.skill.service.impl.SkillDefinitionServiceImpl;
|
||||
import com.bruce.skill.service.impl.SkillVersionServiceImpl;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import com.bruce.skill.vo.SkillWorkspaceVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class SkillComponentStructureTests {
|
||||
|
||||
@Test
|
||||
void skillComponentsShouldReuseMybatisPlusBaseTypes() {
|
||||
assertTrue(BaseMapper.class.isAssignableFrom(SkillDefinitionMapper.class));
|
||||
assertTrue(BaseMapper.class.isAssignableFrom(SkillVersionMapper.class));
|
||||
assertTrue(IService.class.isAssignableFrom(ISkillDefinitionService.class));
|
||||
assertTrue(IService.class.isAssignableFrom(ISkillVersionService.class));
|
||||
assertTrue(ServiceImpl.class.isAssignableFrom(SkillDefinitionServiceImpl.class));
|
||||
assertTrue(ServiceImpl.class.isAssignableFrom(SkillVersionServiceImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void skillControllerShouldExposeRequestResultMethods() throws NoSuchMethodException {
|
||||
Method detailMethod = SkillWorkspaceController.class.getMethod("detail", String.class);
|
||||
Method saveDraftMethod = SkillWorkspaceController.class.getMethod("saveDraft", String.class, SkillVersionSaveDTO.class);
|
||||
Method testMethod = SkillWorkspaceController.class.getMethod("test", String.class, SkillVersionSaveDTO.class);
|
||||
Method publishMethod = SkillWorkspaceController.class.getMethod("publish", String.class, SkillVersionSaveDTO.class);
|
||||
Method archiveMethod = SkillWorkspaceController.class.getMethod("archive", String.class, Integer.class);
|
||||
|
||||
Method definitionDetailMethod = ISkillDefinitionService.class.getMethod("getByCode", String.class);
|
||||
Method definitionListMethod = ISkillDefinitionService.class.getMethod("listDefinitions");
|
||||
Method workspaceMethod = ISkillWorkspaceService.class.getMethod("getWorkspace", String.class);
|
||||
|
||||
assertEquals(RequestResult.class, detailMethod.getReturnType());
|
||||
assertEquals(RequestResult.class, saveDraftMethod.getReturnType());
|
||||
assertEquals(RequestResult.class, testMethod.getReturnType());
|
||||
assertEquals(RequestResult.class, publishMethod.getReturnType());
|
||||
assertEquals(RequestResult.class, archiveMethod.getReturnType());
|
||||
|
||||
assertEquals(SkillDefinition.class, definitionDetailMethod.getReturnType());
|
||||
assertEquals(List.class, definitionListMethod.getReturnType());
|
||||
assertEquals(SkillWorkspaceVO.class, workspaceMethod.getReturnType());
|
||||
assertEquals(SkillDefinitionVO.class, SkillDefinitionVO.class);
|
||||
assertEquals(SkillVersion.class, SkillVersion.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.bruce.skill.factory;
|
||||
|
||||
import com.bruce.skill.dto.SkillDefinitionSaveDTO;
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class SkillFactoryTests {
|
||||
|
||||
private final SkillDefinitionFactory skillDefinitionFactory = new SkillDefinitionFactory();
|
||||
private final SkillVersionFactory skillVersionFactory = new SkillVersionFactory();
|
||||
|
||||
@Test
|
||||
void definitionFactoryShouldTrimRequestAndBuildVo() {
|
||||
SkillDefinitionSaveDTO request = new SkillDefinitionSaveDTO();
|
||||
request.setId(11L);
|
||||
request.setSkillCode(" skill-citation ");
|
||||
request.setSkillName(" 引用审校 Skill ");
|
||||
request.setSkillType(" MIXED ");
|
||||
request.setDescription(" 检查答案与引用是否一致 ");
|
||||
request.setStatus(" DRAFT ");
|
||||
request.setRemark(" 默认技能 ");
|
||||
|
||||
SkillDefinition entity = skillDefinitionFactory.toEntity(request);
|
||||
assertEquals("skill-citation", entity.getSkillCode());
|
||||
assertEquals("引用审校 Skill", entity.getSkillName());
|
||||
assertEquals("MIXED", entity.getSkillType());
|
||||
assertEquals("检查答案与引用是否一致", entity.getDescription());
|
||||
assertEquals("DRAFT", entity.getStatus());
|
||||
assertEquals("默认技能", entity.getRemark());
|
||||
|
||||
SkillDefinitionVO vo = skillDefinitionFactory.toVO(entity);
|
||||
assertEquals(11L, vo.getId());
|
||||
assertEquals("skill-citation", vo.getSkillCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionFactoryShouldPreserveJsonAndPublishStatus() {
|
||||
SkillVersionSaveDTO request = new SkillVersionSaveDTO();
|
||||
request.setSkillId(1001L);
|
||||
request.setVersionNo(4);
|
||||
request.setPromptText(" 你是回答审校器 ");
|
||||
request.setCodeText(" return input; ");
|
||||
request.setConfigJson(" {\"timeout\":3000} ");
|
||||
request.setVariableSchemaJson(" {\"type\":\"object\"} ");
|
||||
request.setPublishStatus(" DRAFT ");
|
||||
request.setRemark(" 新草稿 ");
|
||||
|
||||
SkillVersion entity = skillVersionFactory.toEntity(request);
|
||||
assertNotNull(entity);
|
||||
assertEquals("你是回答审校器", entity.getPromptText());
|
||||
assertEquals("return input;", entity.getCodeText());
|
||||
assertEquals("{\"timeout\":3000}", entity.getConfigJson());
|
||||
assertEquals("{\"type\":\"object\"}", entity.getVariableSchemaJson());
|
||||
assertEquals("DRAFT", entity.getPublishStatus());
|
||||
|
||||
SkillVersionVO vo = skillVersionFactory.toVO(entity);
|
||||
assertEquals(1001L, vo.getSkillId());
|
||||
assertEquals(4, vo.getVersionNo());
|
||||
assertEquals("DRAFT", vo.getPublishStatus());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.bruce.skill.version;
|
||||
|
||||
import com.bruce.skill.dto.SkillVersionSaveDTO;
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.entity.SkillVersion;
|
||||
import com.bruce.skill.factory.SkillVersionFactory;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.service.ISkillRunner;
|
||||
import com.bruce.skill.service.impl.SkillVersionServiceImpl;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SkillVersionServiceTests {
|
||||
|
||||
@Mock
|
||||
private ISkillDefinitionService skillDefinitionService;
|
||||
|
||||
@Mock
|
||||
private ISkillRunner skillRunner;
|
||||
|
||||
@Spy
|
||||
private SkillVersionFactory skillVersionFactory;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private SkillVersionServiceImpl skillVersionService;
|
||||
|
||||
@Test
|
||||
void saveDraftShouldRejectEmptySkillContent() {
|
||||
SkillDefinition definition = new SkillDefinition();
|
||||
definition.setId(1001L);
|
||||
definition.setSkillCode("skill-citation");
|
||||
doReturn(definition).when(skillVersionService).loadDefinitionByCode("skill-citation");
|
||||
|
||||
SkillVersionSaveDTO request = new SkillVersionSaveDTO();
|
||||
request.setVersionNo(4);
|
||||
request.setConfigJson("{}");
|
||||
request.setVariableSchemaJson("{\"type\":\"object\"}");
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> skillVersionService.saveDraft("skill-citation", request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void publishShouldPersistPublishedVersion() {
|
||||
SkillDefinition definition = new SkillDefinition();
|
||||
definition.setId(1001L);
|
||||
definition.setSkillCode("skill-citation");
|
||||
definition.setStatus("DRAFT");
|
||||
doReturn(definition).when(skillVersionService).loadDefinitionByCode("skill-citation");
|
||||
doReturn(null).when(skillVersionService).findBySkillAndVersionNo(1001L, 4);
|
||||
doAnswer(invocation -> true).when(skillVersionService).save(any(SkillVersion.class));
|
||||
|
||||
SkillVersionSaveDTO request = new SkillVersionSaveDTO();
|
||||
request.setVersionNo(4);
|
||||
request.setPromptText("你是回答审校器");
|
||||
request.setConfigJson("{\"timeout\":3000}");
|
||||
request.setVariableSchemaJson("{\"type\":\"object\"}");
|
||||
request.setTestResultJson("{\"quality_score\":0.86}");
|
||||
request.setRemark("首次发布");
|
||||
|
||||
boolean result = skillVersionService.publish("skill-citation", request);
|
||||
assertTrue(result);
|
||||
|
||||
ArgumentCaptor<SkillVersion> captor = ArgumentCaptor.forClass(SkillVersion.class);
|
||||
verify(skillVersionService).save(captor.capture());
|
||||
assertEquals("PUBLISHED", captor.getValue().getPublishStatus());
|
||||
assertEquals(1001L, captor.getValue().getSkillId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void archiveShouldUpdatePublishStatus() {
|
||||
SkillDefinition definition = new SkillDefinition();
|
||||
definition.setId(1001L);
|
||||
definition.setSkillCode("skill-citation");
|
||||
doReturn(definition).when(skillVersionService).loadDefinitionByCode("skill-citation");
|
||||
|
||||
SkillVersion version = new SkillVersion();
|
||||
version.setId(3001L);
|
||||
version.setSkillId(1001L);
|
||||
version.setVersionNo(3);
|
||||
version.setPublishStatus("PUBLISHED");
|
||||
doReturn(version).when(skillVersionService).findBySkillAndVersionNo(1001L, 3);
|
||||
doAnswer(invocation -> true).when(skillVersionService).updateById(any(SkillVersion.class));
|
||||
|
||||
boolean result = skillVersionService.archive("skill-citation", 3);
|
||||
|
||||
assertTrue(result);
|
||||
assertEquals("ARCHIVED", version.getPublishStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDraftShouldReturnTestResultAndPersistDraftSnapshot() {
|
||||
SkillDefinition definition = new SkillDefinition();
|
||||
definition.setId(1001L);
|
||||
definition.setSkillCode("skill-citation");
|
||||
doReturn(definition).when(skillVersionService).loadDefinitionByCode("skill-citation");
|
||||
doReturn(null).when(skillVersionService).findBySkillAndVersionNo(1001L, 5);
|
||||
doAnswer(invocation -> true).when(skillVersionService).save(any(SkillVersion.class));
|
||||
|
||||
SkillVersionSaveDTO request = new SkillVersionSaveDTO();
|
||||
request.setVersionNo(5);
|
||||
request.setPromptText("你是回答审校器");
|
||||
request.setConfigJson("{\"timeout\":3000}");
|
||||
request.setVariableSchemaJson("{\"type\":\"object\"}");
|
||||
doReturn("{\"quality_score\":0.86}").when(skillRunner).runTest(any(SkillDefinition.class), any(SkillVersion.class));
|
||||
|
||||
SkillVersionVO result = skillVersionService.test("skill-citation", request);
|
||||
|
||||
assertEquals("DRAFT", result.getPublishStatus());
|
||||
assertTrue(result.getTestResultJson().contains("quality_score"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.bruce.skill.workspace;
|
||||
|
||||
import com.bruce.skill.entity.SkillDefinition;
|
||||
import com.bruce.skill.service.ISkillDefinitionService;
|
||||
import com.bruce.skill.service.ISkillVersionService;
|
||||
import com.bruce.skill.service.impl.SkillWorkspaceServiceImpl;
|
||||
import com.bruce.skill.vo.SkillDefinitionVO;
|
||||
import com.bruce.skill.vo.SkillVersionVO;
|
||||
import com.bruce.skill.vo.SkillWorkspaceVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SkillWorkspaceServiceTests {
|
||||
|
||||
@Mock
|
||||
private ISkillDefinitionService skillDefinitionService;
|
||||
|
||||
@Mock
|
||||
private ISkillVersionService skillVersionService;
|
||||
|
||||
@InjectMocks
|
||||
private SkillWorkspaceServiceImpl skillWorkspaceService;
|
||||
|
||||
@Test
|
||||
void getWorkspaceShouldAggregateDefinitionAndVersions() {
|
||||
SkillDefinition definition = new SkillDefinition();
|
||||
definition.setId(1001L);
|
||||
definition.setSkillCode("skill-citation");
|
||||
definition.setSkillName("引用审校 Skill");
|
||||
definition.setSkillType("MIXED");
|
||||
definition.setStatus("PUBLISHED");
|
||||
definition.setDescription("检查答案与引用是否一致");
|
||||
|
||||
SkillDefinitionVO item = new SkillDefinitionVO();
|
||||
item.setId(1001L);
|
||||
item.setSkillCode("skill-citation");
|
||||
item.setSkillName("引用审校 Skill");
|
||||
item.setStatus("PUBLISHED");
|
||||
|
||||
SkillVersionVO version = new SkillVersionVO();
|
||||
version.setId(2001L);
|
||||
version.setSkillId(1001L);
|
||||
version.setVersionNo(4);
|
||||
version.setPublishStatus("PUBLISHED");
|
||||
version.setTestResultJson("{\"quality_score\":0.86}");
|
||||
|
||||
when(skillDefinitionService.getByCode("skill-citation")).thenReturn(definition);
|
||||
when(skillDefinitionService.listDefinitions()).thenReturn(List.of(item));
|
||||
when(skillVersionService.listBySkillId(1001L)).thenReturn(List.of(version));
|
||||
|
||||
SkillWorkspaceVO workspace = skillWorkspaceService.getWorkspace("skill-citation");
|
||||
|
||||
assertNotNull(workspace);
|
||||
assertEquals("skill-citation", workspace.getSkillCode());
|
||||
assertEquals(1, workspace.getVersions().size());
|
||||
assertEquals(Integer.valueOf(4), workspace.getPublishedVersionNo());
|
||||
assertEquals("PUBLISHED", workspace.getStatus());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user