Commit 1e784b08 by Ren Ping

fix:处理初始化工程师容量定时任务

1 parent 8905fedb
...@@ -2,6 +2,7 @@ package com.dituhui.pea.dispatch.constraint; ...@@ -2,6 +2,7 @@ package com.dituhui.pea.dispatch.constraint;
import java.util.List; import java.util.List;
import cn.hutool.core.util.StrUtil;
import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore; import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore;
import org.optaplanner.core.api.score.stream.Constraint; import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory; import org.optaplanner.core.api.score.stream.ConstraintFactory;
...@@ -13,97 +14,95 @@ import com.dituhui.pea.dispatch.pojo.Technician; ...@@ -13,97 +14,95 @@ import com.dituhui.pea.dispatch.pojo.Technician;
public class DispatchConstraintProvider implements ConstraintProvider { public class DispatchConstraintProvider implements ConstraintProvider {
@Override @Override
public Constraint[] defineConstraints(ConstraintFactory factory) { public Constraint[] defineConstraints(ConstraintFactory factory) {
return new Constraint[] { return new Constraint[]{
// 硬约束 // 硬约束
// 运行时长提升效果 // 运行时长提升效果
// 5s/60s: 技能权重4-技能匹配问题0个,时间窗问题14个 // 5s/60s: 技能权重4-技能匹配问题0个,时间窗问题14个
// 10s/300s: 技能权重4-技能匹配问题0个,时间窗问题9个 // 10s/300s: 技能权重4-技能匹配问题0个,时间窗问题9个
customerTimeWindowsMatch(factory), customerTimeWindowsMatch(factory),
technicianTimeWindowsMatch(factory), technicianTimeWindowsMatch(factory),
technicianCapacityMatch(factory), technicianCapacityMatch(factory),
skillMatch(factory), skillMatch(factory),
dispatchedMatch(factory), dispatchedMatch(factory),
// 软约束 // 软约束
technicianBalanceSoft(factory), technicianBalanceSoft(factory),
totalDistance(factory), totalDistance(factory),
preferredTotalDistance(factory) preferredTotalDistance(factory)
}; };
} }
// ************************************************************************ // ************************************************************************
// Hard constraints // Hard constraints
// ************************************************************************ // ************************************************************************
// 1,技术员到达时间跟时间窗吻合customerTimeWindowsMatch // 1,技术员到达时间跟时间窗吻合customerTimeWindowsMatch
// 2,技术员时间窗吻合technicianTimeWindowsMatch // 2,技术员时间窗吻合technicianTimeWindowsMatch
// 3,技术员技能跟订单相匹配skillMatch // 3,技术员技能跟订单相匹配skillMatch
public Constraint greaterThanZero(ConstraintFactory factory) { public Constraint greaterThanZero(ConstraintFactory factory) {
return factory.forEach(Technician.class).filter(technician -> technician.getCustomerList().size() == 0) return factory.forEach(Technician.class).filter(technician -> technician.getCustomerList().size() == 0)
.penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1).asConstraint("每个技术员至少分配一个单子"); .penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1).asConstraint("每个技术员至少分配一个单子");
} }
protected Constraint customerTimeWindowsMatch(ConstraintFactory factory) { protected Constraint customerTimeWindowsMatch(ConstraintFactory factory) {
return factory.forEach(Customer.class).filter( return factory.forEach(Customer.class).filter(
customer -> customer.getTechnician() != null && customer.getArrivalTime() > customer.getEndTime()) customer -> customer.getTechnician() != null && customer.getArrivalTime() > customer.getEndTime())
.penalizeLong(HardSoftLongScore.ONE_HARD, .penalizeLong(HardSoftLongScore.ONE_HARD,
// 迟到每2小时扣一分 // 迟到每2小时扣一分
customer -> (long) Math.ceil((customer.getArrivalTime() - customer.getEndTime()) / 120F)) customer -> (long) Math.ceil((customer.getArrivalTime() - customer.getEndTime()) / 120F))
.asConstraint(ConstraintNameEnum.customerTimeWindowsMatch.name()); .asConstraint(ConstraintNameEnum.customerTimeWindowsMatch.name());
} }
protected Constraint technicianTimeWindowsMatch(ConstraintFactory factory) { protected Constraint technicianTimeWindowsMatch(ConstraintFactory factory) {
return factory.forEach(Technician.class).filter( return factory.forEach(Technician.class).filter(
technician -> { technician -> {
boolean ret = false; boolean ret = false;
// 单子的服务时间都在时间窗口内 // 单子的服务时间都在时间窗口内
int[][] timeWindows = technician.getTimeWindows(); int[][] timeWindows = technician.getTimeWindows();
List<Customer> customers = technician.getCustomerList(); List<Customer> customers = technician.getCustomerList();
if (null != timeWindows && timeWindows.length > 0 && null != customers && customers.size() > 0) { if (null != timeWindows && timeWindows.length > 0 && null != customers && customers.size() > 0) {
for (Customer customer : customers) { for (Customer customer : customers) {
Integer arrivalTime = customer.getArrivalTime(); Integer arrivalTime = customer.getArrivalTime();
if (arrivalTime != null && arrivalTime > 0) { if (arrivalTime != null && arrivalTime > 0) {
boolean in = false; boolean in = false;
for (int[] window : timeWindows) { for (int[] window : timeWindows) {
if (window[0] <= arrivalTime && window[1] >= arrivalTime) { if (window[0] <= arrivalTime && window[1] >= arrivalTime) {
in = true; in = true;
break; break;
} }
} }
if (!in) { if (!in) {
// 到达时间在日历窗口外,惩罚得分 // 到达时间在日历窗口外,惩罚得分
ret = true; ret = true;
} }
} }
} }
} }
return ret; return ret;
}).penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1) }).penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1)
.asConstraint(ConstraintNameEnum.technicianTimeWindowsMatch.name()); .asConstraint(ConstraintNameEnum.technicianTimeWindowsMatch.name());
} }
protected Constraint technicianCapacityMatch(ConstraintFactory factory) { protected Constraint technicianCapacityMatch(ConstraintFactory factory) {
return factory.forEach(Technician.class).filter( return factory.forEach(Technician.class).filter(
// MaxCount ==0 表示不起作用 // MaxCount ==0 表示不起作用
technician -> technician.getMaxCount() > 0 && technician.getCustomerSize() > technician.getMaxCount()) technician -> technician.getMaxCount() > 0 && technician.getCustomerSize() > technician.getMaxCount())
.penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1) .penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1)
.asConstraint(ConstraintNameEnum.technicianCapacityMatch.name()); .asConstraint(ConstraintNameEnum.technicianCapacityMatch.name());
} }
protected Constraint dispatchedMatch(ConstraintFactory factory) { protected Constraint dispatchedMatch(ConstraintFactory factory) {
return factory.forEach(Customer.class).filter(customer -> return factory.forEach(Customer.class).filter(customer ->
// 已分配 // 已分配
(customer.getDispatchedTechnicianCode() != null && ((customer.getTechnician() == null) (customer.getDispatchedTechnicianCode() != null
|| (!StringUtils.equals(customer.getDispatchedTechnicianCode(), customer.getTechnician().getCode())))) && (customer.getTechnician() == null || !StringUtils.equals(customer.getDispatchedTechnicianCode(), customer.getTechnician().getCode())))
|| || (customer.getExclusiveTechnicianCode() != null
// 已排除 && (customer.getTechnician() == null || StrUtil.contains("," + customer.getExclusiveTechnicianCode() + ",", "," + customer.getTechnician().getCode() + ","))))
(customer.getExclusiveTechnicianCode() != null && ((customer.getTechnician() == null) || (StringUtils .penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 50)
.equals(customer.getExclusiveTechnicianCode(), customer.getTechnician().getCode()))))) .asConstraint(ConstraintNameEnum.dispatchedMatch.name());
.penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 50) }
.asConstraint(ConstraintNameEnum.dispatchedMatch.name());
}
// protected Constraint customerTimeWindowsMatch1(ConstraintFactory factory) { // protected Constraint customerTimeWindowsMatch1(ConstraintFactory factory) {
// return factory.forEach(Customer.class).filter( // return factory.forEach(Customer.class).filter(
...@@ -118,17 +117,17 @@ public class DispatchConstraintProvider implements ConstraintProvider { ...@@ -118,17 +117,17 @@ public class DispatchConstraintProvider implements ConstraintProvider {
// .penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 1).asConstraint("技术员到达时间跟时间窗吻合2"); // .penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 1).asConstraint("技术员到达时间跟时间窗吻合2");
// } // }
protected Constraint skillMatch(ConstraintFactory factory) { protected Constraint skillMatch(ConstraintFactory factory) {
return factory.forEach(Customer.class) return factory.forEach(Customer.class)
.filter(customer -> customer.getTechnician() != null .filter(customer -> customer.getTechnician() != null
&& !customer.getTechnician().getSkills().contains(customer.getRequiredSkill())) && !customer.getTechnician().getSkills().contains(customer.getRequiredSkill()))
.penalizeLong(HardSoftLongScore.ONE_HARD, .penalizeLong(HardSoftLongScore.ONE_HARD,
// 技能匹配跟时间窗匹配存在很明显的跷跷板效应,权重小于3就会存在技能匹配问题 // 技能匹配跟时间窗匹配存在很明显的跷跷板效应,权重小于3就会存在技能匹配问题
// 3-技能匹配问题1个,时间窗问题8个 // 3-技能匹配问题1个,时间窗问题8个
// 4-技能匹配问题0个,时间窗问题14个 // 4-技能匹配问题0个,时间窗问题14个
customer -> 4) customer -> 4)
.asConstraint(ConstraintNameEnum.skillMatch.name()); .asConstraint(ConstraintNameEnum.skillMatch.name());
} }
// protected Constraint technicianBalance(ConstraintFactory factory) { // protected Constraint technicianBalance(ConstraintFactory factory) {
// // 会导致剩余单子集中? // // 会导致剩余单子集中?
...@@ -144,30 +143,30 @@ public class DispatchConstraintProvider implements ConstraintProvider { ...@@ -144,30 +143,30 @@ public class DispatchConstraintProvider implements ConstraintProvider {
// .penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1).asConstraint("订单均分2"); // .penalizeLong(HardSoftLongScore.ONE_HARD, technician -> 1).asConstraint("订单均分2");
// } // }
// ************************************************************************ // ************************************************************************
// Soft constraints // Soft constraints
// ************************************************************************ // ************************************************************************
// 1, 总路程最小 totalDistance // 1, 总路程最小 totalDistance
// 2, 技术员中心点偏好 preferredTotalDistance // 2, 技术员中心点偏好 preferredTotalDistance
// 3, 订单数量均衡 technicianBalanceSoft // 3, 订单数量均衡 technicianBalanceSoft
protected Constraint totalDistance(ConstraintFactory factory) { protected Constraint totalDistance(ConstraintFactory factory) {
return factory.forEach(Technician.class) return factory.forEach(Technician.class)
.penalizeLong(HardSoftLongScore.ONE_SOFT, Technician::getTotalDistanceMeters) .penalizeLong(HardSoftLongScore.ONE_SOFT, Technician::getTotalDistanceMeters)
.asConstraint(ConstraintNameEnum.totalDistance.name()); .asConstraint(ConstraintNameEnum.totalDistance.name());
} }
protected Constraint preferredTotalDistance(ConstraintFactory factory) { protected Constraint preferredTotalDistance(ConstraintFactory factory) {
return factory.forEach(Technician.class) return factory.forEach(Technician.class)
.penalizeLong(HardSoftLongScore.ONE_SOFT, Technician::getPreferredTotalDistanceMeters) .penalizeLong(HardSoftLongScore.ONE_SOFT, Technician::getPreferredTotalDistanceMeters)
.asConstraint(ConstraintNameEnum.preferredTotalDistance.name()); .asConstraint(ConstraintNameEnum.preferredTotalDistance.name());
} }
protected Constraint technicianBalanceSoft(ConstraintFactory factory) { protected Constraint technicianBalanceSoft(ConstraintFactory factory) {
return factory.forEachUniquePair(Technician.class).penalizeLong(HardSoftLongScore.ONE_SOFT, return factory.forEachUniquePair(Technician.class).penalizeLong(HardSoftLongScore.ONE_SOFT,
// 权重需要调节,差距一个相当于多一公里 FIXME 这里应该是时长均衡,不是订单量均衡 // 权重需要调节,差距一个相当于多一公里 FIXME 这里应该是时长均衡,不是订单量均衡
(a, b) -> Math.abs(a.getCustomerSize() - b.getCustomerSize()) * 4000) (a, b) -> Math.abs(a.getCustomerSize() - b.getCustomerSize()) * 4000)
.asConstraint(ConstraintNameEnum.technicianBalanceSoft.name()); .asConstraint(ConstraintNameEnum.technicianBalanceSoft.name());
} }
} }
...@@ -197,4 +197,25 @@ public class OrderInfo implements Serializable { ...@@ -197,4 +197,25 @@ public class OrderInfo implements Serializable {
@Column(name = "update_time") @Column(name = "update_time")
private LocalDateTime updateTime; private LocalDateTime updateTime;
/**
* 是否重物搬运(双人上门) 0:否 1:是 默认0
*/
@Column(name = "is_multiple")
private Integer isMultiple = 0;
/**
* 是否指定某个工程师/是否排除某个工程师 0:否 1:指定 2:排除 默认0
*/
@Column(name = "is_appoint_engineer")
private Integer isAppointEngineer = 0;
/**
* 指定某个工程师/排除某个工程师 codes 多个,分割
*/
@Column(name = "appoint_engineer_codes")
private String appointEngineerCodes;
} }
package com.dituhui.pea.dispatch.quartz.engineerCapacity; package com.dituhui.pea.dispatch.quartz.engineerCapacity;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.dispatch.common.DateUtil; import com.dituhui.pea.dispatch.common.DateUtil;
import com.dituhui.pea.dispatch.common.DateUtils; import com.dituhui.pea.dispatch.common.DateUtils;
import com.dituhui.pea.dispatch.common.OccupyInfoDetail; import com.dituhui.pea.dispatch.common.OccupyInfoDetail;
...@@ -189,7 +190,7 @@ public class InitEngineerCapacityScheduler { ...@@ -189,7 +190,7 @@ public class InitEngineerCapacityScheduler {
// 初始化一个工程师、一天的容量 // 初始化一个工程师、一天的容量
CapacityEngineerStatEntity statEntity = capacityEngineerStatDao.getByWorkdayAndEngineerCode(date, engineerCode); CapacityEngineerStatEntity statEntity = capacityEngineerStatDao.getByWorkdayAndEngineerCode(date, engineerCode);
if (statEntity != null && !rewriteForce) { if (statEntity != null && !rewriteForce) {
log.error("技术员容量信息记录已存在, 直接返回"); log.error("技术员容量信息记录(engineer: {}, date:{})已存在, 直接返回", engineerCode, date);
return; return;
} }
log.info("日期[{}] 技术员[{}] 有日历记录需要特别处理 ===", date, engineerCode); log.info("日期[{}] 技术员[{}] 有日历记录需要特别处理 ===", date, engineerCode);
...@@ -212,10 +213,11 @@ public class InitEngineerCapacityScheduler { ...@@ -212,10 +213,11 @@ public class InitEngineerCapacityScheduler {
} }
public void initOneEngineerByDays(String bdate, String edate, String branchId) { public void initOneEngineerByDays(String bdate, String edate, String branchId) {
LocalDate currentDate = DateUtils.localDateFromStr(bdate);
LocalDate endDate = DateUtils.localDateFromStr(edate);
List<String> allEngineerCodes = engineerInfoDao.getAllByBranchId(branchId).stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList()); List<String> allEngineerCodes = engineerInfoDao.getAllByBranchId(branchId).stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList());
for(String engineerCode: allEngineerCodes){ log.warn(">>> 分部工程师容量初始化开始,branchId: {},工程师数量:{}", branchId, allEngineerCodes.size());
for (String engineerCode : allEngineerCodes) {
LocalDate currentDate = DateUtils.localDateFromStr(bdate);
LocalDate endDate = DateUtils.localDateFromStr(edate);
while (!currentDate.isAfter(endDate)) { while (!currentDate.isAfter(endDate)) {
initOneEngineer(DateUtils.formatDate(currentDate), engineerCode); initOneEngineer(DateUtils.formatDate(currentDate), engineerCode);
currentDate = currentDate.plusDays(1); currentDate = currentDate.plusDays(1);
......
...@@ -84,7 +84,7 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -84,7 +84,7 @@ public class SchedulerServiceImpl implements SchedulerService {
return; return;
} }
OrgGroup orgGroup=orgGroupRepository.findByGroupId(orgTeamEntity.getGroupId()).get(); OrgGroup orgGroup = orgGroupRepository.findByGroupId(orgTeamEntity.getGroupId()).get();
if (ObjectUtil.equals(2, orgGroup.getCategory())) { if (ObjectUtil.equals(2, orgGroup.getCategory())) {
log.error(">>> teamId:{} 来自网点,不自动派工", teamId); log.error(">>> teamId:{} 来自网点,不自动派工", teamId);
...@@ -97,6 +97,7 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -97,6 +97,7 @@ public class SchedulerServiceImpl implements SchedulerService {
} }
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
String today = DateUtil.format(now, "yyyy-MM-dd");
String nowTime = DateUtil.format(now, "HH:mm"); String nowTime = DateUtil.format(now, "HH:mm");
String nowTimePlus30 = DateUtil.format(now.plusMinutes(30), "HH:mm"); String nowTimePlus30 = DateUtil.format(now.plusMinutes(30), "HH:mm");
...@@ -109,10 +110,13 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -109,10 +110,13 @@ public class SchedulerServiceImpl implements SchedulerService {
String groupId = orgTeamEntity.getGroupId(); String groupId = orgTeamEntity.getGroupId();
log.info("dispatchRun group:{}, team:{} done", groupId, teamId); log.info("dispatchRun group:{}, team:{} done", groupId, teamId);
for (int i = 1; i <= nextDaysLimit; i++) { for (int i = 1; i <= nextDaysLimit; i++) {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE); String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
Optional<DispatchBatch> optional = dispatchBatchRepository.findByTeamIdAndBatchDate(teamId, currDay); Optional<DispatchBatch> optional = dispatchBatchRepository.findByTeamIdAndBatchDate(teamId, currDay);
if (optional.isPresent() && Objects.nonNull(optional.get().getCutoffedTime())) { if (optional.isPresent()
&& Objects.nonNull(optional.get().getCutoffedTime())
&& today.equals(DateUtil.format(optional.get().getCutoffedTime(), "yyyy-MM-dd"))) {
//自动任务截止 //自动任务截止
log.error(">>> teamId:{}, day:{} 自动任务已截止", teamId, currDay); log.error(">>> teamId:{}, day:{} 自动任务已截止", teamId, currDay);
continue; continue;
......
package com.dituhui.pea.dispatch.service.impl; package com.dituhui.pea.dispatch.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.dituhui.pea.dispatch.common.GeoDistanceCalculator; import com.dituhui.pea.dispatch.common.GeoDistanceCalculator;
import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider; import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider;
import com.dituhui.pea.dispatch.dao.DispatchEngineerRepository; import com.dituhui.pea.dispatch.dao.*;
import com.dituhui.pea.dispatch.dao.DispatchOrderRepository;
import com.dituhui.pea.dispatch.dao.OrgGroupRepository;
import com.dituhui.pea.dispatch.dao.OrgTeamDao;
import com.dituhui.pea.dispatch.entity.DispatchOrder; import com.dituhui.pea.dispatch.entity.DispatchOrder;
import com.dituhui.pea.dispatch.entity.OrderInfo;
import com.dituhui.pea.dispatch.entity.OrgGroup; import com.dituhui.pea.dispatch.entity.OrgGroup;
import com.dituhui.pea.dispatch.entity.OrgTeamEntity; import com.dituhui.pea.dispatch.entity.OrgTeamEntity;
import com.dituhui.pea.dispatch.pojo.*; import com.dituhui.pea.dispatch.pojo.*;
...@@ -59,6 +58,9 @@ public class SolveServiceImpl implements SolveService { ...@@ -59,6 +58,9 @@ public class SolveServiceImpl implements SolveService {
DispatchOrderRepository dispatchOrderRepo; DispatchOrderRepository dispatchOrderRepo;
@Autowired @Autowired
private OrderInfoRepository orderInfoRepository;
@Autowired
OrgGroupRepository groupRepository; OrgGroupRepository groupRepository;
...@@ -252,6 +254,17 @@ public class SolveServiceImpl implements SolveService { ...@@ -252,6 +254,17 @@ public class SolveServiceImpl implements SolveService {
} }
Customer customer = new Customer(order.getId(), order.getOrderId(), order.getDt(), location, start, end, order.getSkills(), order.getTakeTime()); Customer customer = new Customer(order.getId(), order.getOrderId(), order.getDt(), location, start, end, order.getSkills(), order.getTakeTime());
OrderInfo orderInfo = orderInfoRepository.findByOrderId(order.getOrderId()).get(0);
if ((StrUtil.equals("MANUAL", orderInfo.getAppointmentMethod())
&& StrUtil.equals("CONFIRM", orderInfo.getAppointmentStatus()))
|| ObjectUtil.equal(1, orderInfo.getIsAppointEngineer())) {
customer.setDispatchedTechnicianCode(orderInfo.getEngineerCode());
}
if (ObjectUtil.equal(2, orderInfo.getIsAppointEngineer())) {
customer.setExclusiveTechnicianCode(Objects.nonNull(orderInfo.getAppointEngineerCodes()) ?
orderInfo.getAppointEngineerCodes().trim() : null);
}
customerList.add(customer); customerList.add(customer);
}); });
......
...@@ -3,7 +3,7 @@ server: ...@@ -3,7 +3,7 @@ server:
dispatch: dispatch:
cron: cron:
expr: 0 14 8-22 * * ? expr: 0 55 8-22 * * ?
next-day-limit: 2 next-day-limit: 2
# expr: 0 */10 8-18 * * ? # expr: 0 */10 8-18 * * ?
...@@ -11,9 +11,9 @@ scheduler: ...@@ -11,9 +11,9 @@ scheduler:
init-engineer-capacity: init-engineer-capacity:
# 每天22点1次 # 每天22点1次
#cron-expr: 0 0 22 * * ? #cron-expr: 0 0 22 * * ?
cron-expr: 0 29 * * * ? cron-expr: 0 51 * * * ?
day-offset-begin: 0 day-offset-begin: 0
day-offset-end: 14 day-offset-end: 20
rewrite-force: true rewrite-force: true
calc-engineer-capacity: calc-engineer-capacity:
...@@ -49,12 +49,12 @@ spring: ...@@ -49,12 +49,12 @@ spring:
enabled: false enabled: false
datasource: datasource:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai # url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai
username: root # username: root
password: 123456 # password: 123456
# url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai
# username: boxi username: boxi
# password: boxi_dev_0725 password: boxi_dev_0725
type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource
jpa: jpa:
......
...@@ -73,6 +73,24 @@ ...@@ -73,6 +73,24 @@
<onMatch>ACCEPT</onMatch> <onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch> <onMismatch>DENY</onMismatch>
</filter> </filter>
</appender>
<!-- 异常文件输出设置,将异常堆栈另外保存一份到单独的文件中,方便查找 -->
<appender name="FILE_WARN"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_FILE}/warn/${spring.application.name:-}.warn.log</File>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_FILE}/warn/${spring.application.name:-}.warn-%d{yyyy-MM-dd}-%i.zip
</FileNamePattern>
<maxFileSize>${LOG_MAXFILESIZE}</maxFileSize>
<maxHistory>${LOG_FILEMAXDAY}</maxHistory>
<totalSizeCap>500MB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印警告日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印警告日志 -->
<level>WARN</level> <level>WARN</level>
<onMatch>ACCEPT</onMatch> <onMatch>ACCEPT</onMatch>
...@@ -118,6 +136,7 @@ ...@@ -118,6 +136,7 @@
<appender-ref ref="console"/> <appender-ref ref="console"/>
<appender-ref ref="FileAppender"/> <appender-ref ref="FileAppender"/>
<appender-ref ref="FILE_ERROR"/> <appender-ref ref="FILE_ERROR"/>
<appender-ref ref="FILE_WARN"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!