This commit is contained in:
Jerry Yan 2025-01-22 14:23:00 +08:00
parent f670fb2f91
commit 38c4b553bc
17 changed files with 178 additions and 131 deletions

View File

@ -119,6 +119,11 @@ public class OrderBiz {
isBuy = sourceRepository.getUserIsBuy(userId, goodsType, goodsId);
break;
}
} else {
OrderEntity orderEntity = orderRepository.getUserBuyItem(userId, goodsType, goodsId);
if (orderEntity != null) {
respVO.setOrderId(orderEntity.getId());
}
}
// 还是没买
respVO.setBuy(isBuy);

View File

@ -9,8 +9,10 @@ import com.ycwl.basic.model.mobile.goods.GoodsReqQuery;
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppScenicService;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.utils.ApiResponse;
@ -33,6 +35,8 @@ public class AppScenicController {
@Autowired
private AppScenicService appScenicService;
@Autowired
private ScenicRepository scenicRepository;
@ApiOperation("分页查询景区列表")
@PostMapping("/page")
@ -46,6 +50,13 @@ public class AppScenicController {
return appScenicService.getDetails(id);
}
@GetMapping("/{id}/config")
@IgnoreToken
public ApiResponse<ScenicConfigEntity> getConfig(@PathVariable Long id){
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(id);
return ApiResponse.success(scenicConfig);
}
@ApiOperation("查询景区设备总数和拍到用户的机位数量")
@GetMapping("/{scenicId}/deviceCount/")
public ApiResponse<ScenicDeviceCountVO> deviceCountByScenicId(@PathVariable Long scenicId){

View File

@ -25,6 +25,7 @@ import com.ycwl.basic.model.viid.req.RegisterReq;
import com.ycwl.basic.model.viid.req.UnRegisterReq;
import com.ycwl.basic.model.viid.resp.SystemTimeResp;
import com.ycwl.basic.model.viid.resp.VIIDBaseResp;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -61,6 +62,8 @@ public class ViidController {
private static final String serverId = "00000000000000000001";
@Autowired
private SourceMapper sourceMapper;
@Autowired
private DeviceRepository deviceRepository;
// region 注册注销基础接口
/**
@ -75,7 +78,7 @@ public class ViidController {
DeviceIdObject deviceIdObject = req.getRegisterObject();
log.info("注册的设备信息:{}", deviceIdObject);
// 保存设备注册时间
DeviceEntity device = deviceMapper.getByDeviceNo(deviceIdObject.getDeviceId());
DeviceEntity device = deviceRepository.getDeviceByDeviceNo(deviceIdObject.getDeviceId());
if (device == null) {
device = new DeviceEntity();
device.setName("未配置设备");
@ -86,6 +89,7 @@ public class ViidController {
device.setIpAddr(IpUtils.getIpAddr(request));
if (device.getId() != null) {
deviceMapper.updateEntity(device);
deviceRepository.clearDeviceCache(device.getId());
} else {
device.setId(SnowFlakeUtil.getLongId());
deviceMapper.addEntity(device);
@ -109,7 +113,7 @@ public class ViidController {
// log.info("对方发送的心跳的信息:{}", keepaliveObject);
String deviceId = keepaliveObject.getDeviceId();
DeviceEntity device = deviceMapper.getByDeviceNo(deviceId);
DeviceEntity device = deviceRepository.getDeviceByDeviceNo(deviceId);
// 判断设备状态
if (device == null) {
@ -123,9 +127,7 @@ public class ViidController {
device.setId(SnowFlakeUtil.getLongId());
deviceMapper.addEntity(device);
} else {
device.setOnline(1);
device.setKeepaliveAt(new Date());
deviceMapper.updateEntity(device);
deviceRepository.updateOnlineStatus(device.getId(), IpUtils.getIpAddr(request), 1, new Date());
}
// log.info("已经解析过的心跳信息:{}", keepaliveObject);
@ -141,19 +143,17 @@ public class ViidController {
* @return 返回
*/
@RequestMapping(value = "/System/UnRegister", method = RequestMethod.POST)
public VIIDBaseResp unRegister(@RequestBody UnRegisterReq req) {
public VIIDBaseResp unRegister(@RequestBody UnRegisterReq req, HttpServletRequest request) {
// 获取设备id
DeviceIdObject unRegisterObject = req.getUnRegisterObject();
String deviceId = unRegisterObject.getDeviceId();
log.info("获取的注销的请求参数:{}", unRegisterObject);
// 首先查询该设备是否存在
DeviceEntity device = deviceMapper.getByDeviceNo(deviceId);
DeviceEntity device = deviceRepository.getDeviceByDeviceNo(deviceId);
// 判断
if (device != null) {
device.setOnline(0);
device.setKeepaliveAt(new Date());
int update = deviceMapper.updateEntity(device);
deviceRepository.updateOnlineStatus(device.getId(), IpUtils.getIpAddr(request), 0, new Date());
}
return new VIIDBaseResp(
new ResponseStatusObject(deviceId, "/VIID/System/UnRegister", "0", "注销成功", sdfTime.format(new Date()))
@ -201,7 +201,7 @@ public class ViidController {
SubImageList subImageList = face.getSubImageList();
// 判断人脸对象中的列表是否为空
String deviceID = face.getDeviceID();
DeviceEntity device = deviceMapper.getByDeviceNo(deviceID);
DeviceEntity device = deviceRepository.getDeviceByDeviceNo(deviceID);
if (device == null) {
continue;
}

View File

@ -9,6 +9,7 @@ import com.ycwl.basic.model.pc.device.resp.DeviceRespVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
@ -40,4 +41,8 @@ public interface DeviceMapper {
int updateEntity(DeviceEntity device);
int addEntity(DeviceEntity device);
int updateOnlineStatus(Long id, String ipAddr, int online, Date keepaliveAt);
DeviceEntity getByDeviceNo2(String deviceNo);
}

View File

@ -49,4 +49,6 @@ public interface TaskMapper {
TaskEntity getFaceAutomaticTask(Long faceId);
TaskEntity get(Long taskId);
List<TaskEntity> listEntity(TaskReqQuery taskReqQuery);
}

View File

@ -51,11 +51,9 @@ public class ScenicConfigEntity {
* 视频保存时间
*/
private Integer videoStoreDay;
/**
* 最大行程时长
*/
private Integer maxJourneyHour;
private Integer allFree;
private Integer disableSourceVideo;
private Integer disableSourceImage;
private Integer templateNewVideoType;
private Integer antiScreenRecordType;
}

View File

@ -13,4 +13,5 @@ public class TemplateConfigEntity {
private Integer isDefault;
private Date createDate;
private Integer minimalPlaceholderFill;
private Integer automaticPlaceholderFill;
}

View File

@ -9,6 +9,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@Component
public class DeviceRepository {
@Autowired
@ -35,8 +38,13 @@ public class DeviceRepository {
return JSONObject.parseObject(redisTemplate.opsForValue().get(String.format(DEVICE_CACHE_KEY, deviceNo)), DeviceEntity.class);
}
DeviceEntity device = deviceMapper.getByDeviceNo(deviceNo);
if (null == device) {
device = deviceMapper.getByDeviceNo2(deviceNo);
}
if (null != device) {
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceNo), JSONObject.toJSONString(device));
} else {
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceNo), "null", 60 * 60L, TimeUnit.SECONDS);
}
return device;
}
@ -66,4 +74,28 @@ public class DeviceRepository {
redisTemplate.delete(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId));
return true;
}
public void updateOnlineStatus(String deviceNo, int online, Date keepaliveAt) {
DeviceEntity device = getDeviceByDeviceNo(deviceNo);
if (null == device) {
return;
}
updateOnlineStatus(device.getId(), null, online, keepaliveAt);
}
public void updateOnlineStatus(Long deviceId, String ipAddr, int online, Date keepaliveAt) {
DeviceEntity device = getDevice(deviceId);
if (null == device) {
return;
}
device.setOnline(online);
device.setKeepaliveAt(keepaliveAt);
deviceMapper.updateOnlineStatus(deviceId, ipAddr, online, keepaliveAt);
updateDeviceCache(device);
}
private void updateDeviceCache(DeviceEntity device) {
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getId()), JSONObject.toJSONString(device));
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getNo()), JSONObject.toJSONString(device));
}
}

View File

@ -72,10 +72,19 @@ public class OrderRepository {
redisTemplate.opsForValue().set(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId), "0", 60, TimeUnit.SECONDS);
return false;
}
if (Integer.valueOf(1).equals(orderEntity.getStatus())) {
redisTemplate.opsForValue().set(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId), "1");
return true;
} else {
redisTemplate.opsForValue().set(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId), "0", 60, TimeUnit.SECONDS);
return false;
}
}
}
public OrderEntity getUserBuyItem(Long userId, int goodsType, Long goodsId) {
return orderMapper.getUserBuyItem(userId, goodsType, goodsId);
}
public boolean checkUserBuyFaceSourceImage(Long userId, Long faceId) {
return checkUserBuyItem(userId, 2, faceId);

View File

@ -101,12 +101,11 @@ public class DeviceServiceImpl implements DeviceService {
}
if (reqVo.getDevices() != null && !reqVo.getDevices().isEmpty()) {
for (WvpSyncReqVo.DeviceItem deviceItem : reqVo.getDevices()) {
DeviceEntity device = deviceMapper.getByDeviceNo(deviceItem.getDeviceNo());
DeviceEntity device = deviceRepository.getDeviceByDeviceNo(deviceItem.getDeviceNo());
if (device != null) {
device.setOnline(deviceItem.getOnline());
device.setKeepaliveAt(deviceItem.getKeepaliveAt());
deviceMapper.updateEntity(device);
deviceRepository.clearDeviceCache(device.getId());
deviceRepository.updateOnlineStatus(device.getId(), null, 1, deviceItem.getKeepaliveAt());
}
}
}

View File

@ -10,7 +10,6 @@ import java.util.Date;
public interface TaskService {
TaskSyncRespVo handleSyncTask(TaskReqVo req);
boolean createRenderTask(Long scenicId, Long templateId, Long faceId);
TemplateRespVO workerGetTemplate(Long templateId, WorkerAuthReqVo req);

View File

@ -15,6 +15,7 @@ import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.mapper.TaskMapper;
import com.ycwl.basic.mapper.TemplateMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.order.PriceObj;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
@ -43,7 +44,9 @@ import com.ycwl.basic.notify.adapters.INotifyAdapter;
import com.ycwl.basic.notify.entity.NotifyContent;
import com.ycwl.basic.notify.enums.NotifyType;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.OrderRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.VideoRepository;
import com.ycwl.basic.repository.VideoTaskRepository;
import com.ycwl.basic.service.task.TaskService;
import com.ycwl.basic.storage.StorageFactory;
@ -104,6 +107,10 @@ public class TaskTaskServiceImpl implements TaskService {
private TemplateBiz templateBiz;
@Autowired
private FaceRepository faceRepository;
@Autowired
private VideoRepository videoRepository;
@Autowired
private OrderRepository orderRepository;
private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
String accessKey = req.getAccessKey();
@ -170,34 +177,6 @@ public class TaskTaskServiceImpl implements TaskService {
return resp;
}
@Override
public boolean createRenderTask(Long scenicId, Long templateId, Long faceId) {
boolean canGenerate = templateBiz.determineTemplateCanGenerate(templateId, faceId);
if (!canGenerate) {
return false;
}
FaceEntity face = faceRepository.getFace(faceId);
if (face == null) {
return false;
}
List<SourceEntity> sourceEntityList = sourceMapper.listVideoByScenicFaceRelation(scenicId, faceId);
Map<String, List<SourceEntity>> sourcesMap = sourceEntityList.stream()
.collect(Collectors.groupingBy(item -> item.getDeviceId().toString()));
sourcesMap.forEach((key, value) -> {
// 每个value只保留第一个
value.removeIf(item -> !value.get(0).equals(item));
});
TaskEntity taskEntity = new TaskEntity();
taskEntity.setId(SnowFlakeUtil.getLongId());
taskEntity.setFaceId(faceId);
taskEntity.setTemplateId(templateId);
taskEntity.setScenicId(scenicId);
taskEntity.setTaskParams(JSON.toJSONString(sourcesMap));
taskEntity.setStatus(0);
taskMapper.add(taskEntity);
return true;
}
@Override
public TemplateRespVO workerGetTemplate(@NonNull Long templateId, @NonNull WorkerAuthReqVo req) {
if (templateId == null) {
@ -346,13 +325,34 @@ public class TaskTaskServiceImpl implements TaskService {
memberVideoEntity.setIsBuy(0);
if (list.isEmpty()) {
log.info("创建任务! faceId:{},templateId:{},taskParams:{}", faceId, templateId, sourcesMap);
TaskEntity taskEntity = new TaskEntity();
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
TaskEntity taskEntity = null;
if (Integer.valueOf(0).equals(scenicConfig.getTemplateNewVideoType())) {
log.info("景区{}启用templateNewVideoType全新视频原位替换", face.getScenicId());
taskReqQuery.setTemplateId(templateId);
List<TaskEntity> templateTaskList = taskMapper.listEntity(taskReqQuery);
if (!templateTaskList.isEmpty()) {
taskEntity = templateTaskList.get(0);
log.info("已有旧生成的视频:{}", taskEntity);
MemberVideoEntity taskVideoRelation = videoMapper.queryRelationByMemberTask(face.getMemberId(), taskEntity.getId());
if (taskVideoRelation != null) {
log.info("已有旧关联记录的视频:{}", taskVideoRelation);
memberVideoEntity.setIsBuy(taskVideoRelation.getIsBuy());
memberVideoEntity.setOrderId(taskVideoRelation.getOrderId());
}
taskMapper.deleteById(taskEntity.getId());
}
}
if (taskEntity == null) {
taskEntity = new TaskEntity();
taskEntity.setId(SnowFlakeUtil.getLongId());
taskEntity.setScenicId(face.getScenicId());
taskEntity.setFaceId(faceId);
taskEntity.setTemplateId(templateId);
taskEntity.setStatus(0);
taskEntity.setAutomatic(automatic);
}
taskEntity.setWorkerId(null);
taskEntity.setStatus(0);
taskEntity.setTaskParams(JSON.toJSONString(sourcesMap));
taskMapper.add(taskEntity);
memberVideoEntity.setTaskId(taskEntity.getId());
@ -361,8 +361,12 @@ public class TaskTaskServiceImpl implements TaskService {
memberVideoEntity.setTaskId(list.get(0).getId());
VideoEntity video = videoMapper.findByTaskId(list.get(0).getId());
if (video != null) {
PriceObj priceObj = orderBiz.queryPrice(list.get(0).getScenicId(), 0, video.getId());
if (priceObj.isFree()) {
IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), list.get(0).getScenicId(), 0, video.getId());
if (isBuy.isBuy()) {
memberVideoEntity.setIsBuy(1);
memberVideoEntity.setOrderId(isBuy.getOrderId());
}
if (isBuy.isFree()) {
memberVideoEntity.setIsBuy(1);
}
memberVideoEntity.setVideoId(video.getId());
@ -427,10 +431,31 @@ public class TaskTaskServiceImpl implements TaskService {
videoMapper.add(video);
}
int isBuy = 0;
PriceObj priceObj = orderBiz.queryPrice(task.getScenicId(), 0, video.getId());
FaceEntity face = faceRepository.getFace(task.getFaceId());
if (face != null) {
IsBuyRespVO priceObj = orderBiz.isBuy(face.getMemberId(), task.getScenicId(), 0, video.getId());
if (priceObj.isBuy()) {
isBuy = 1;
}
if (priceObj.isFree()) {
isBuy = 1;
}
if (isBuy != 1) {
// 判断景区新生成免费送逻辑
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId());
if (Integer.valueOf(2).equals(scenicConfig.getTemplateNewVideoType())) {
log.info("景区{}启用templateNewVideoType全新视频不需要重新购买", task.getScenicId());
// 全新视频不需要重新购买旧视频在我的里面查看
List<MemberVideoEntity> entityList = videoMapper.listRelationByFaceAndTemplate(face.getMemberId(), face.getId(), task.getTemplateId());
Optional<MemberVideoEntity> buy = entityList.stream().filter(item -> Integer.valueOf(1).equals(item.getIsBuy())).findAny();
if (buy.isPresent()) {
log.info("人脸{},模板{},已经被购买过,{}", face.getId(), task.getTemplateId(), buy.get());
// 买过
isBuy = 1;
}
}
}
}
videoMapper.updateRelationWhenTaskSuccess(taskId, video.getId(), isBuy);
new Thread(() -> {
sendVideoGeneratedServiceNotification(taskId);

View File

@ -64,75 +64,6 @@ public class DynamicTaskGenerator {
@Autowired
private FaceRepository faceRepository;
@Scheduled(cron = "0 0 * * * ?")
public void dynamicTask() {
List<ScenicRespVO> scenicList = scenicMapper.list(new ScenicReqQuery());
for (ScenicRespVO scenic : scenicList) {
log.info("定时任务执行,当前景区:{}", scenic.getName());
ScenicConfigEntity scenicConfig = scenicMapper.getConfig(scenic.getId());
if (scenicConfig == null || Integer.valueOf(2).equals(scenicConfig.getBookRoutine())) {
log.info("当前景区{},未启用提前预约流程", scenic.getName());
continue;
}
log.info("当前景区{},启用了提前预约流程", scenic.getName());
TemplateReqQuery templateQuery = new TemplateReqQuery();
templateQuery.setScenicId(scenic.getId());
List<TemplateRespVO> templateList = templateMapper.list(templateQuery);
for (TemplateRespVO template : templateList) {
log.info("当前景区{},启用了提前预约流程,模板:{}", scenic.getName(), template.getName());
if (template.getStatus() == 0) {
log.info("当前模板{}未启用,跳过", template.getName());
continue;
}
TemplateConfigEntity templateConfig = templateMapper.getConfig(template.getId());
if (templateConfig == null) {
log.info("当前模板{}未配置,跳过", template.getName());
continue;
}
if (templateConfig.getIsDefault() == 0) {
if (scenicConfig.getBookRoutine() == 1) {
log.info("当前模板{}未启用默认,且景区启用预约流程,跳过", template.getName());
continue;
}
}
// 查找人脸样本
List<FaceRespVO> list = faceMapper.listByScenicIdAndNotFinished(scenic.getId());
for (FaceRespVO face : list) {
log.info("当前模板{}启用默认,人脸样本:{}", template.getName(), face.getFaceUrl());
if (((new Date()).getTime() - face.getCreateAt().getTime()) > scenicConfig.getMaxJourneyHour() * 3600 * 1000) {
log.info("当前人脸样本{}已超过最大游玩{}小时,自动检测人脸", face.getFaceUrl(), scenicConfig.getMaxJourneyHour());
List<String> oldMatchedSampleListIds = new ArrayList<>();
if (face.getMatchSampleIds() != null) {
oldMatchedSampleListIds = Arrays.asList(face.getMatchSampleIds().split(","));
}
SearchFaceRespVo searchFace = faceService.searchFace(face.getId());
if (oldMatchedSampleListIds.size() == searchFace.getSampleListIds().size()) {
boolean isEqual = true;
for (Long sampleId : searchFace.getSampleListIds()) {
if (!oldMatchedSampleListIds.contains(sampleId.toString())) {
isEqual = false;
break;
}
}
if (isEqual) {
log.info("当前人脸样本{}已超过最大游玩{}小时,但人脸检测结果与上次相同,跳过", face.getFaceUrl(), scenicConfig.getMaxJourneyHour());
continue;
}
}
if (templateBiz.determineTemplateCanGenerate(template.getId(), face.getId())) {
log.info("当前人脸样本{}已超过最小占位素材,自动创建任务", face.getFaceUrl());
taskService.createRenderTask(scenic.getId(), template.getId(), face.getId());
faceMapper.finishedJourney(face.getId());
} else {
log.info("当前人脸样本{}未超过最小占位素材,未达到自动生成条件", face.getFaceUrl());
}
}
}
}
}
}
@Data
@AllArgsConstructor
public static class Task implements Delayed {

View File

@ -48,6 +48,14 @@
update_at = now()
where id = #{id}
</update>
<update id="updateOnlineStatus">
update device
set online = #{online},
<if test="ipAddr != null">ip_addr = #{ipAddr},</if>
keepalive_at = #{keepaliveAt},
update_at = now()
where id = #{id}
</update>
<delete id="deleteById">
delete from device where id = #{id}
</delete>
@ -114,4 +122,10 @@
from device
where status = 1
</select>
<select id="getByDeviceNo2" resultType="com.ycwl.basic.model.pc.device.entity.DeviceEntity">
select *
from device
where no_2 = #{deviceNo}
limit 1
</select>
</mapper>

View File

@ -86,7 +86,8 @@
book_routine=#{bookRoutine},
sample_store_day=#{sampleStoreDay},
video_store_day=#{videoStoreDay},
max_journey_hour=#{maxJourneyHour},
template_new_video_type=#{templateNewVideoType},
anti_screen_record_type=#{antiScreenRecordType},
disable_source_video=#{disableSourceVideo},
disable_source_image=#{disableSourceImage}
</set>

View File

@ -109,4 +109,18 @@
from task
where id = #{id}
</select>
<select id="listEntity" resultType="com.ycwl.basic.model.pc.task.entity.TaskEntity">
select *
from task
<where>
<if test="workerId!= null">and worker_id = #{workerId} </if>
<if test="memberId!= null">and member_id = #{memberId} </if>
<if test="faceId!= null">and face_id = #{faceId} </if>
<if test="templateId!= null">and template_id = #{templateId} </if>
<if test="scenicId!= null">and scenic_id = #{scenicId} </if>
<if test="status!= null">and `status` = #{status} </if>
<if test="startTime!= null">and create_time &gt;= #{startTime} </if>
<if test="endTime!= null">and create_time &lt;= #{endTime} </if>
</where>
</select>
</mapper>

View File

@ -44,7 +44,8 @@
update template_config
<set>
<if test="isDefault!= null">is_default = #{isDefault}, </if>
<if test="minimalPlaceholderFill!= null">minimal_placeholder_fill = #{minimalPlaceholderFill}, </if>
minimal_placeholder_fill = #{minimalPlaceholderFill},
automatic_placeholder_fill = #{automaticPlaceholderFill}
</set>
where id = #{id}
</update>