feat: 完成多个功能修改和bug修复

1. 修改uploadOnLineResource以支持任何网络URL
2. 修复登录状态过期问题,添加/common/uploadOnLineResource到Sa-Token白名单
3. 拆分effect相关字段:subtitlePosition拆分为subtitlePositionX/Y,duration拆分为durationStart/End
4. 修复/callbackWithAmount在fileUrl未提供时不报错
5. 为Effect、EffectTemplate、DigitalHuman、SubtitleItem、SubtitleStyle控制器添加自定义update方法
6. 修复MyBatisPlusMetaObjectHandler自动填充异常问题

详细修改:
- FileServiceImpl.java: 修改uploadOnLineResource使用HttpURLConnection支持任意网络URL
- LoginHelper.java: 修复getLoginUserSafely()处理所有异常
- MyBatisPlusMetaObjectHandler.java: 修复updateFill方法安全获取userId
- BillingServiceImpl.java: 处理fileUrl为空的情况
- 各控制器:添加自定义update方法,不使用框架Api.UPDATE
- 各ServiceImpl:更新相关实现逻辑以支持新字段拆分
- application-dev.yml:添加uploadOnLineResource到白名单
This commit is contained in:
wangzhiwei 2026-01-06 16:09:17 +08:00
parent a7d65ca240
commit 60b3e7e1a3
17 changed files with 208 additions and 47 deletions

View File

@ -5,8 +5,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import top.continew.starter.extension.crud.model.entity.BaseDO; import top.continew.starter.extension.crud.model.entity.BaseDO;
import java.time.LocalDateTime;
/** /**
* 数字人-文案实体类 * 数字人-文案实体类
* *

View File

@ -39,19 +39,18 @@ public class DigitalHumanReq extends BaseReq {
*/ */
private String generatedVideoUrl; private String generatedVideoUrl;
// /**
// /** // * 字幕项列表冗余存储用于快速回显
// * 字幕项列表冗余存储用于快速回显 // */
// */ // private String subtitle;
// private String subtitle; //
// // /**
// /** // * 字幕样式配置冗余或快照
// * 字幕样式配置冗余或快照 // */
// */ // private String subtitleStyle;
// private String subtitleStyle; //
// // /**
// /** // * 特效列表冗余存储
// * 特效列表冗余存储 // */
// */ // private String effects;
// private String effects;
} }

View File

@ -49,20 +49,20 @@ public class DigitalHumanResp extends BaseResp {
*/ */
private String generatedVideoUrl; private String generatedVideoUrl;
// /** // /**
// * 字幕项列表冗余存储用于快速回显 // * 字幕项列表冗余存储用于快速回显
// */ // */
// private String subtitle; // private String subtitle;
// //
// /** // /**
// * 字幕样式配置冗余或快照 // * 字幕样式配置冗余或快照
// */ // */
// private String subtitleStyle; // private String subtitleStyle;
// //
// /** // /**
// * 特效列表冗余存储 // * 特效列表冗余存储
// */ // */
// private String effects; // private String effects;
/** /**
* 创建时间 * 创建时间

View File

@ -17,4 +17,6 @@ import top.continew.starter.extension.crud.service.BaseService;
public interface EffectService extends BaseService<EffectResp, EffectDetailResp, EffectQuery, EffectReq> { public interface EffectService extends BaseService<EffectResp, EffectDetailResp, EffectQuery, EffectReq> {
PageResp<EffectResp> pageList(EffectQuery query, EffectPageQuery pageQuery); PageResp<EffectResp> pageList(EffectQuery query, EffectPageQuery pageQuery);
// 可根据需要添加额外的业务方法 // 可根据需要添加额外的业务方法
void update(EffectReq req, Long id);
} }

View File

@ -532,6 +532,11 @@ public class BillingServiceImpl implements BillingService {
private void addTaskRecordHistory(TaskRecordHistoryDO taskRecord, TaskCallbackReq req) { private void addTaskRecordHistory(TaskRecordHistoryDO taskRecord, TaskCallbackReq req) {
String fileStr = req.getFileUrl(); String fileStr = req.getFileUrl();
// 检查fileUrl是否为空为空则直接插入记录
if (StrUtil.isEmpty(fileStr)) {
taskRecordHistoryMapper.insert(taskRecord);
return;
}
//先下载文件 //先下载文件
List<String> fileUrls = Arrays.asList(fileStr.split(",")); List<String> fileUrls = Arrays.asList(fileStr.split(","));
if (!fileUrls.isEmpty()) { if (!fileUrls.isEmpty()) {

View File

@ -41,7 +41,6 @@ public class CopyrightServiceImpl extends BaseServiceImpl<CopyrightMapper, Copyr
// 默认格局createTime 倒叙排列 // 默认格局createTime 倒叙排列
wrapper.orderByDesc(Copyright::getCreateTime); wrapper.orderByDesc(Copyright::getCreateTime);
Page<Copyright> page = new Page<>(pageQuery.getPage(), pageQuery.getSize()); Page<Copyright> page = new Page<>(pageQuery.getPage(), pageQuery.getSize());
Page<Copyright> result = copyrightMapper.selectPage(page, wrapper); Page<Copyright> result = copyrightMapper.selectPage(page, wrapper);

View File

@ -1,10 +1,8 @@
package top.continew.admin.business.service.impl; package top.continew.admin.business.service.impl;
import cn.crane4j.core.util.CollectionUtils; import cn.crane4j.core.util.CollectionUtils;
import cn.dev33.satoken.stp.StpUtil;
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 jodd.util.CollectionUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -19,7 +17,6 @@ import top.continew.admin.business.model.req.DigitalHumanReq;
import top.continew.admin.business.model.resp.DigitalHumanDetailResp; import top.continew.admin.business.model.resp.DigitalHumanDetailResp;
import top.continew.admin.business.model.resp.DigitalHumanResp; import top.continew.admin.business.model.resp.DigitalHumanResp;
import top.continew.admin.business.service.DigitalHumanService; import top.continew.admin.business.service.DigitalHumanService;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.starter.extension.crud.model.resp.PageResp; import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.impl.BaseServiceImpl; import top.continew.starter.extension.crud.service.impl.BaseServiceImpl;
@ -111,14 +108,26 @@ public class DigitalHumanServiceImpl extends BaseServiceImpl<DigitalHumanMapper,
digitalHumanMapper.deleteBatchIds(ids); digitalHumanMapper.deleteBatchIds(ids);
} }
@Override
public void update(DigitalHumanReq req, Long id) {
DigitalHuman digitalHuman = new DigitalHuman();
BeanUtils.copyProperties(req, digitalHuman);
digitalHuman.setId(id);
digitalHuman.setUpdateTime(java.time.LocalDateTime.now());
digitalHumanMapper.updateById(digitalHuman);
}
private DigitalHumanResp convertToResp(DigitalHuman digitalHuman) { private DigitalHumanResp convertToResp(DigitalHuman digitalHuman) {
DigitalHumanResp resp = new DigitalHumanResp(); DigitalHumanResp resp = new DigitalHumanResp();
BeanUtils.copyProperties(digitalHuman, resp); BeanUtils.copyProperties(digitalHuman, resp);
// 处理关联数据 // 处理关联数据
List<SubtitleStyle> subtitleStyles = subtitleStyleMapper.selectList(new LambdaQueryWrapper<SubtitleStyle>().eq(SubtitleStyle::getDigitalHumanId, digitalHuman.getId())); List<SubtitleStyle> subtitleStyles = subtitleStyleMapper.selectList(new LambdaQueryWrapper<SubtitleStyle>()
resp.setSubtitleStyle(CollectionUtils.isNotEmpty(subtitleStyles)? subtitleStyles.get(0) : null); .eq(SubtitleStyle::getDigitalHumanId, digitalHuman.getId()));
resp.setEffects(effectMapper.selectList(new LambdaQueryWrapper<Effect>().eq(Effect::getDigitalHumanId, digitalHuman.getId()))); resp.setSubtitleStyle(CollectionUtils.isNotEmpty(subtitleStyles) ? subtitleStyles.get(0) : null);
resp.setSubtitles(subtitleItemMapper.selectList(new LambdaQueryWrapper<SubtitleItem>().eq(SubtitleItem::getDigitalHumanId, digitalHuman.getId()))); resp.setEffects(effectMapper.selectList(new LambdaQueryWrapper<Effect>()
.eq(Effect::getDigitalHumanId, digitalHuman.getId())));
resp.setSubtitles(subtitleItemMapper.selectList(new LambdaQueryWrapper<SubtitleItem>()
.eq(SubtitleItem::getDigitalHumanId, digitalHuman.getId())));
return resp; return resp;
} }
} }

View File

@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.continew.admin.business.mapper.EffectMapper; import top.continew.admin.business.mapper.EffectMapper;
import top.continew.admin.business.model.entity.DigitalHuman;
import top.continew.admin.business.model.entity.Effect; import top.continew.admin.business.model.entity.Effect;
import top.continew.admin.business.model.query.EffectPageQuery; import top.continew.admin.business.model.query.EffectPageQuery;
import top.continew.admin.business.model.query.EffectQuery; import top.continew.admin.business.model.query.EffectQuery;
@ -71,4 +70,13 @@ public class EffectServiceImpl extends BaseServiceImpl<EffectMapper, Effect, Eff
BeanUtils.copyProperties(effect, resp); BeanUtils.copyProperties(effect, resp);
return resp; return resp;
} }
@Override
public void update(EffectReq req, Long id) {
Effect effect = new Effect();
BeanUtils.copyProperties(req, effect);
effect.setId(id);
effect.setUpdateTime(java.time.LocalDateTime.now());
effectMapper.updateById(effect);
}
} }

View File

@ -87,6 +87,15 @@ public class EffectTemplateServiceImpl extends BaseServiceImpl<EffectTemplateMap
return effectTemplate.getId(); return effectTemplate.getId();
} }
@Override
public void update(EffectTemplateReq req, Long id) {
EffectTemplate effectTemplate = new EffectTemplate();
BeanUtils.copyProperties(req, effectTemplate);
effectTemplate.setId(id);
effectTemplate.setUpdateTime(java.time.LocalDateTime.now());
effectTemplateMapper.updateById(effectTemplate);
}
private EffectTemplateResp convertToResp(EffectTemplate effectTemplate) { private EffectTemplateResp convertToResp(EffectTemplate effectTemplate) {
EffectTemplateResp resp = new EffectTemplateResp(); EffectTemplateResp resp = new EffectTemplateResp();
BeanUtils.copyProperties(effectTemplate, resp); BeanUtils.copyProperties(effectTemplate, resp);

View File

@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.continew.admin.business.mapper.SubtitleItemMapper; import top.continew.admin.business.mapper.SubtitleItemMapper;
import top.continew.admin.business.model.entity.EffectTemplate;
import top.continew.admin.business.model.entity.SubtitleItem; import top.continew.admin.business.model.entity.SubtitleItem;
import top.continew.admin.business.model.query.SubtitleItemPageQuery; import top.continew.admin.business.model.query.SubtitleItemPageQuery;
import top.continew.admin.business.model.query.SubtitleItemQuery; import top.continew.admin.business.model.query.SubtitleItemQuery;
@ -66,6 +65,15 @@ public class SubtitleItemServiceImpl extends BaseServiceImpl<SubtitleItemMapper,
return subtitleItem.getId(); return subtitleItem.getId();
} }
@Override
public void update(SubtitleItemReq req, Long id) {
SubtitleItem subtitleItem = new SubtitleItem();
BeanUtils.copyProperties(req, subtitleItem);
subtitleItem.setId(id);
subtitleItem.setUpdateTime(java.time.LocalDateTime.now());
subtitleItemMapper.updateById(subtitleItem);
}
private SubtitleItemResp convertToResp(SubtitleItem subtitleItem) { private SubtitleItemResp convertToResp(SubtitleItem subtitleItem) {
SubtitleItemResp resp = new SubtitleItemResp(); SubtitleItemResp resp = new SubtitleItemResp();
BeanUtils.copyProperties(subtitleItem, resp); BeanUtils.copyProperties(subtitleItem, resp);

View File

@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.continew.admin.business.mapper.SubtitleStyleMapper; import top.continew.admin.business.mapper.SubtitleStyleMapper;
import top.continew.admin.business.model.entity.SubtitleItem;
import top.continew.admin.business.model.entity.SubtitleStyle; import top.continew.admin.business.model.entity.SubtitleStyle;
import top.continew.admin.business.model.query.SubtitleStylePageQuery; import top.continew.admin.business.model.query.SubtitleStylePageQuery;
import top.continew.admin.business.model.query.SubtitleStyleQuery; import top.continew.admin.business.model.query.SubtitleStyleQuery;
@ -66,6 +65,15 @@ public class SubtitleStyleServiceImpl extends BaseServiceImpl<SubtitleStyleMappe
return subtitleStyle.getId(); return subtitleStyle.getId();
} }
@Override
public void update(SubtitleStyleReq req, Long id) {
SubtitleStyle subtitleStyle = new SubtitleStyle();
BeanUtils.copyProperties(req, subtitleStyle);
subtitleStyle.setId(id);
subtitleStyle.setUpdateTime(java.time.LocalDateTime.now());
subtitleStyleMapper.updateById(subtitleStyle);
}
private SubtitleStyleResp convertToResp(SubtitleStyle subtitleStyle) { private SubtitleStyleResp convertToResp(SubtitleStyle subtitleStyle) {
SubtitleStyleResp resp = new SubtitleStyleResp(); SubtitleStyleResp resp = new SubtitleStyleResp();
BeanUtils.copyProperties(subtitleStyle, resp); BeanUtils.copyProperties(subtitleStyle, resp);

View File

@ -74,7 +74,7 @@ public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler {
return; return;
} }
Long updateUser = LoginHelper.getUserId(); Long updateUser = ExceptionUtils.exToNull(LoginHelper::getUserId);
LocalDateTime updateTime = LocalDateTime.now(); LocalDateTime updateTime = LocalDateTime.now();
if (metaObject.getOriginalObject() instanceof BaseDO baseDO) { if (metaObject.getOriginalObject() instanceof BaseDO baseDO) {
// 继承了 BaseDO 的类填充修改信息 // 继承了 BaseDO 的类填充修改信息

View File

@ -32,9 +32,17 @@ import java.util.stream.Collectors;
@Tag(name = "数字人任务管理 API") @Tag(name = "数字人任务管理 API")
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@CrudRequestMapping(value = "/business/digitalHuman", api = {Api.GET, Api.UPDATE, Api.LIST}) @CrudRequestMapping(value = "/business/digitalHuman", api = {Api.GET, Api.LIST})
public class DigitalHumanController extends BaseController<DigitalHumanService, DigitalHumanResp, DigitalHumanDetailResp, DigitalHumanQuery, DigitalHumanReq> { public class DigitalHumanController extends BaseController<DigitalHumanService, DigitalHumanResp, DigitalHumanDetailResp, DigitalHumanQuery, DigitalHumanReq> {
@Log
@Operation(summary = "更新数字人任务", description = "更新数字人任务信息")
@PutMapping("/{id}")
public Boolean updateDigitalHuman(@RequestBody DigitalHumanReq req, @PathVariable Long id) {
baseService.update(req, id);
return true;
}
@Log @Log
@Operation(summary = "查询数字人任务", description = "查询数字人任务列表") @Operation(summary = "查询数字人任务", description = "查询数字人任务列表")
@ResponseBody @ResponseBody

View File

@ -32,9 +32,17 @@ import java.util.stream.Collectors;
@Tag(name = "数字人-特效管理 API") @Tag(name = "数字人-特效管理 API")
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@CrudRequestMapping(value = "/business/effect", api = {Api.GET, Api.UPDATE, Api.LIST}) @CrudRequestMapping(value = "/business/effect", api = {Api.GET, Api.LIST})
public class EffectController extends BaseController<EffectService, EffectResp, EffectDetailResp, EffectQuery, EffectReq> { public class EffectController extends BaseController<EffectService, EffectResp, EffectDetailResp, EffectQuery, EffectReq> {
@Log
@Operation(summary = "更新特效", description = "更新特效信息")
@PutMapping("/{id}")
public Boolean updateEffect(@RequestBody EffectReq req, @PathVariable Long id) {
baseService.update(req, id);
return true;
}
@Log @Log
@Operation(summary = "查询特效", description = "查询特效列表") @Operation(summary = "查询特效", description = "查询特效列表")
@ResponseBody @ResponseBody

View File

@ -32,9 +32,17 @@ import java.util.stream.Collectors;
@Tag(name = "数字人-特效模板管理 API") @Tag(name = "数字人-特效模板管理 API")
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@CrudRequestMapping(value = "/business/effectTemplate", api = {Api.GET, Api.UPDATE, Api.LIST}) @CrudRequestMapping(value = "/business/effectTemplate", api = {Api.GET, Api.LIST})
public class EffectTemplateController extends BaseController<EffectTemplateService, EffectTemplateResp, EffectTemplateDetailResp, EffectTemplateQuery, EffectTemplateReq> { public class EffectTemplateController extends BaseController<EffectTemplateService, EffectTemplateResp, EffectTemplateDetailResp, EffectTemplateQuery, EffectTemplateReq> {
@Log
@Operation(summary = "更新特效模板", description = "更新特效模板信息")
@PutMapping("/{id}")
public Boolean updateEffectTemplate(@RequestBody EffectTemplateReq req, @PathVariable Long id) {
baseService.update(req, id);
return true;
}
@Log @Log
@ResponseBody @ResponseBody
@Operation(summary = "新增特效模板", description = "新增特效模板") @Operation(summary = "新增特效模板", description = "新增特效模板")

View File

@ -32,9 +32,17 @@ import java.util.stream.Collectors;
@Tag(name = "数字人-字幕项管理 API") @Tag(name = "数字人-字幕项管理 API")
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@CrudRequestMapping(value = "/business/subtitleItem", api = {Api.GET, Api.UPDATE, Api.LIST}) @CrudRequestMapping(value = "/business/subtitleItem", api = {Api.GET, Api.LIST})
public class SubtitleItemController extends BaseController<SubtitleItemService, SubtitleItemResp, SubtitleItemDetailResp, SubtitleItemQuery, SubtitleItemReq> { public class SubtitleItemController extends BaseController<SubtitleItemService, SubtitleItemResp, SubtitleItemDetailResp, SubtitleItemQuery, SubtitleItemReq> {
@Log
@Operation(summary = "更新字幕项", description = "更新字幕项信息")
@PutMapping("/{id}")
public Boolean updateSubtitleItem(@RequestBody SubtitleItemReq req, @PathVariable Long id) {
baseService.update(req, id);
return true;
}
@Log @Log
@Operation(summary = "查询字幕项", description = "查询字幕项列表") @Operation(summary = "查询字幕项", description = "查询字幕项列表")
@ResponseBody @ResponseBody

View File

@ -0,0 +1,84 @@
package top.continew.admin.controller.business;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.continew.admin.business.model.query.SubtitleStylePageQuery;
import top.continew.admin.business.model.query.SubtitleStyleQuery;
import top.continew.admin.business.model.req.BatchReq;
import top.continew.admin.business.model.req.SubtitleStyleReq;
import top.continew.admin.business.model.resp.SubtitleStyleDetailResp;
import top.continew.admin.business.model.resp.SubtitleStyleResp;
import top.continew.admin.business.service.SubtitleStyleService;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.controller.BaseController;
import top.continew.starter.extension.crud.enums.Api;
import top.continew.starter.extension.crud.model.query.SortQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.log.core.annotation.Log;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 数字人-字幕样式管理 API
*
* @author 王志维
* @since 2025/12/29
*/
@Tag(name = "数字人-字幕样式管理 API")
@RestController
@RequiredArgsConstructor
@CrudRequestMapping(value = "/business/subtitleStyle", api = {Api.GET, Api.LIST})
public class SubtitleStyleController extends BaseController<SubtitleStyleService, SubtitleStyleResp, SubtitleStyleDetailResp, SubtitleStyleQuery, SubtitleStyleReq> {
@Log
@Operation(summary = "更新字幕样式", description = "更新字幕样式信息")
@PutMapping("/{id}")
public Boolean updateSubtitleStyle(@RequestBody SubtitleStyleReq req, @PathVariable Long id) {
baseService.update(req, id);
return true;
}
@Log
@Operation(summary = "查询字幕样式", description = "查询字幕样式列表")
@ResponseBody
@GetMapping({"/list"})
public List<SubtitleStyleResp> list(SubtitleStyleQuery query, SortQuery sortQuery) {
return baseService.list(query, sortQuery);
}
@Log
@ResponseBody
@Operation(summary = "新增字幕样式", description = "新增字幕样式")
@PostMapping()
public Long addSubtitleStyle(@RequestBody SubtitleStyleReq req) {
return baseService.add(req);
}
@Log
@Operation(summary = "分页查询字幕样式", description = "分页查询字幕样式列表")
@ResponseBody
@GetMapping({"/page"})
public PageResp<SubtitleStyleResp> page(SubtitleStyleQuery query, SubtitleStylePageQuery pageQuery) {
return baseService.pageList(query, pageQuery);
}
@Log
@Operation(summary = "批量删除字幕样式", description = "根据字幕样式ID列表批量删除字幕样式")
@PostMapping("/batchDelete")
public void deleteBatch(@Validated @RequestBody BatchReq req) {
baseService.delete(req.getIds());
}
@Log
@Operation(summary = "批量删除字幕样式(通过路径参数)", description = "根据路径中的ID列表批量删除字幕样式ID以逗号分隔")
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") String ids) {
List<Long> idList = Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList());
baseService.delete(idList);
}
}