Commit 12a21868 by HlQ

[add]

1.添加点位设计功能
2.添加请求日志功能
3.微信 openid 绑定使用 Spring Event
4.添加机器人推送功能
5.发货管理添加批量导入功能
1 parent d0b75b48
Showing 50 changed files with 1784 additions and 117 deletions
......@@ -13,22 +13,34 @@
<artifactId>Vion-DevOps</artifactId>
<version>1</version>
<properties>
<pg.version>42.6.0</pg.version>
<sqlserver.version>12.2.0.jre8</sqlserver.version>
<lombok.version>1.18.30</lombok.version>
<hutool.version>5.8.25</hutool.version>
<mapstruct-plus.version>1.3.5</mapstruct-plus.version>
<mp.version>3.5.5</mp.version>
<mp-join.version>1.4.7.2</mp-join.version>
<wx-mp.version>4.6.0</wx-mp.version>
<sa-token.verion>1.37.0</sa-token.verion>
<myexcel.version>4.3.3</myexcel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
<version>${pg.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.2.0.jre8</version>
<version>${sqlserver.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
......@@ -37,33 +49,37 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.24</version>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.3.5</version>
<version>${mapstruct-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version>
<version>${mp.version}</version>
</dependency>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId>
<version>1.4.7.2</version>
<version>${mp-join.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.5.0</version>
<version>${wx-mp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -72,22 +88,17 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.37.0</version>
<version>${sa-token.verion}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>1.37.0</version>
<version>${sa-token.verion}</version>
</dependency>
<dependency>
<groupId>com.github.liaochong</groupId>
<artifactId>myexcel</artifactId>
<version>4.3.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>4.2.0</version>
<version>${myexcel.version}</version>
</dependency>
</dependencies>
......
package vion.advice;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author HlQ
* @date 2024/1/17
*/
@Component
@RequiredArgsConstructor
@Aspect
@Slf4j
public class LogAspect {
private final ObjectMapper objectMapper;
@Pointcut("execution(* vion.controller.*.*(..))")
public void logPointcut() {
}
@Before("logPointcut()")
public void doBefore(JoinPoint joinPoint) throws JsonProcessingException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjUtil.isNull(attributes)) {
return;
}
HttpServletRequest request = attributes.getRequest();
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
String requestId = (String) request.getAttribute("requestId");
MDC.put("requestId", requestId);
log.info("Request URL:{}, Method:{}, IP:{}, Arguments:{}",
request.getRequestURI(),
request.getMethod(),
ServletUtil.getClientIP(request),
objectMapper.writeValueAsString(request.getParameterMap())
);
}
@AfterReturning(pointcut = "logPointcut()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) throws JsonProcessingException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjUtil.isNull(attributes)) {
return;
}
HttpServletRequest request = attributes.getRequest();
// Calculate response time
long startTime = (Long) request.getAttribute("startTime");
long responseTime = System.currentTimeMillis() - startTime;
String resStr = objectMapper.writeValueAsString(result);
if (resStr.length() > 1000) {
resStr = resStr.substring(0, 1000);
}
log.info("Response time: {} ms. Return value: {}",
responseTime,
resStr);
MDC.remove("requestId");
}
}
......@@ -20,7 +20,7 @@ public class UserNameConverter implements CustomWriteConverter<Long, String> {
@Override
public String convert(Long originalData, CustomWriteContext customWriteContext) {
return Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:" + originalData)))
return Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:id:" + originalData)))
.map(User::getUsername)
.orElse("未知");
}
......
......@@ -9,6 +9,8 @@ import vion.dto.DeliveryRecordDTO;
import vion.service.IDeliveryRecordService;
import vion.vo.DeliveryRecordVO;
import java.util.List;
/**
* 发货记录管理
*/
......@@ -38,6 +40,12 @@ public class DeliveryRecordController {
return deliveryRecordService.save(dto);
}
@PostMapping("/deliveryRecord/batch")
@SaCheckPermission(value = "deliveryRecord:save", orRole = "admin")
public String save(@RequestBody List<DeliveryRecordDTO> dto) {
return deliveryRecordService.saveBatch(dto);
}
@PostMapping("/deliveryRecord/{id}")
@SaCheckPermission(value = "deliveryRecord:edit", orRole = "admin")
public String updateById(@PathVariable Long id, DeliveryRecordDTO dto) {
......
package vion.controller;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -35,6 +36,11 @@ public class FileController {
@GetMapping("/files")
public Page<FileInfo> getFiles(FileInfoDTO data) {
return fileService.lambdaQuery(converter.convert(data, new FileInfo()))
.eq(ObjUtil.isNotNull(data.getStoreId()), FileInfo::getStoreId, data.getStoreId())
.eq(ObjUtil.isNotNull(data.getSourceId()), FileInfo::getSourceId, data.getSourceId())
.eq(ObjUtil.isNotNull(data.getContractId()), FileInfo::getContractId, data.getContractId())
.eq(ObjUtil.isNotNull(data.getSourceType()), FileInfo::getSourceType, data.getSourceType())
.in(CollUtil.isNotEmpty(data.getSourceTypeList()), FileInfo::getSourceType, data.getSourceTypeList())
.page(Page.of(data.getPageNum(), data.getPageSize()));
}
......@@ -50,21 +56,36 @@ public class FileController {
}
@PostMapping("/upLoadFile")
public String uploadFile(Long storeId, Long sourceId, FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) {
public String uploadFile(FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) {
try {
//上传url地址
String filename = infile.getOriginalFilename() + "_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
// String path = fileurl + FileUtil.FILE_SEPARATOR + storeId + FileUtil.FILE_SEPARATOR + sourceId + FileUtil.FILE_SEPARATOR + filename;
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
// todo 路径未确定
String path = fileUrl + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
infile.transferTo(file);
String sha256 = SecureUtil.sha256(file).toUpperCase();
String extName = FileUtil.extName(file);
FileInfo tempFileInfo = new FileInfo();
tempFileInfo.setStoreId(fileInfo.getStoreId());
tempFileInfo.setSourceId(fileInfo.getSourceId());
tempFileInfo.setSourceType(fileInfo.getSourceType());
tempFileInfo.setName(filename);
tempFileInfo.setUrl(path);
tempFileInfo.setType(FileUtil.extName(file));
tempFileInfo.setSha256(SecureUtil.sha256(file).toUpperCase());
tempFileInfo.setUploader(fileInfo.getUploader());
if (fileService.save(tempFileInfo)) {
return path;
} else {
return "文件保存失败";
}
} catch (IOException e) {
log.error("上传文件失败", e);
}
return "success";
return "文件保存成功";
}
@PostMapping("/uploadFile1")
......
package vion.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.liaochong.myexcel.core.DefaultExcelBuilder;
import com.github.liaochong.myexcel.core.watermark.Watermark;
import com.github.liaochong.myexcel.utils.AttachmentExportUtil;
import com.github.liaochong.myexcel.utils.WatermarkUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.*;
import vion.dto.PointInfoDTO;
import vion.model.RejectInfo;
import vion.service.IPointInfoService;
import vion.third.WechatMod;
import vion.vo.PointInfoVO;
import vion.vo.UserVO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.Date;
import java.util.List;
/**
* 点位管理
*
* @author HlQ
* @date 2024/1/8
*/
@RestController
@RequestMapping("/api/point")
@RequiredArgsConstructor
@Slf4j
public class PointDesignController {
private final IPointInfoService pointInfoService;
private final WechatMod wechatMod;
@PostMapping("/frontSubmit")
public Object frontSubmit(PointInfoDTO dto) {
return pointInfoService.frontSubmit(dto);
}
@PostMapping
@SaCheckPermission(value = "point:save", orRole = "admin")
public Object save(PointInfoDTO dto) {
return pointInfoService.save(dto);
}
@PostMapping("/{id}")
@SaCheckPermission(value = "point:edit", orRole = "admin")
public String updById(@PathVariable Long id, PointInfoDTO dto) {
return pointInfoService.upd(id, null, dto);
}
@PostMapping("/upd/{uuid}")
public String updById(@PathVariable String uuid, PointInfoDTO dto) {
return pointInfoService.upd(null, uuid, dto);
}
@GetMapping
@SaCheckPermission(value = "point:list", orRole = "admin")
public Page<PointInfoVO> list(PointInfoDTO dto) {
return pointInfoService.list(dto);
}
@GetMapping("/{id}")
@SaCheckPermission(value = "point:query", orRole = "admin")
public PointInfoVO getPointById(@PathVariable Long id) {
return pointInfoService.getPointByDetail(id, null);
}
@GetMapping("/get/{uuid}")
public PointInfoVO getPointByUuid(@PathVariable String uuid) {
return pointInfoService.getPointByDetail(null, uuid);
}
@DeleteMapping("/{id}")
@SaCheckPermission(value = "point:remove", orRole = "admin")
public String delById(@PathVariable Long id) {
return pointInfoService.delById(id);
}
@PostMapping("/client/reject")
public String clientReject(@RequestBody RejectInfo dto) {
return pointInfoService.reject(dto, "client");
}
@PostMapping("/reject")
@SaCheckPermission(value = "point:reject", orRole = "admin")
public String reject(@RequestBody RejectInfo dto) {
return pointInfoService.reject(dto, null);
}
@GetMapping("/reject/{pointId}")
@SaCheckPermission(value = "point:reject:list", orRole = "admin")
public Page<RejectInfo> rejectInfoList(@PathVariable Long pointId, RejectInfo dto) {
return pointInfoService.rejectInfoList(pointId, dto);
}
@GetMapping("/reject/uuid/{uuid}")
public Page<RejectInfo> rejectInfoPage(@PathVariable String uuid, RejectInfo dto) {
return pointInfoService.rejectInfoList(uuid, dto);
}
@GetMapping("/desgin/push")
@SaCheckPermission(value = "point:design:push", orRole = "admin")
public Object designPush(Long pointId, String pushType) {
return pointInfoService.designPush(pointId, null, pushType);
}
@GetMapping("/export")
@SaCheckPermission(value = "point:export", orRole = "admin")
public void pointExport(PointInfoDTO dto, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
dto.setPageSize(9999);
Page<PointInfoVO> voPage = pointInfoService.list(dto);
voPage.getRecords().forEach(v -> v.setPointUrl("https://yunwei.vionyun.com:8443/wap/setup-device?uuid=" + v.getUuid()));
try (DefaultExcelBuilder<PointInfoVO> pointInfoVODefaultExcelBuilder = DefaultExcelBuilder.of(PointInfoVO.class)) {
Workbook workbook = pointInfoVODefaultExcelBuilder.build(voPage.getRecords());
// 水印添加指定字体,并在服务器上安装 SimSun 字体,解决中文字体变成方块的问题
Watermark watermark = new Watermark();
watermark.setText(user.getUsername() + "-" + user.getPhone());
watermark.setFont(new Font("SimSun", Font.PLAIN, 16));
WatermarkUtil.addWatermark(workbook, watermark);
AttachmentExportUtil.export(workbook, StrUtil.format("点位设计列表_{}", DateUtil.formatDateTime(new Date())), response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@PostMapping("/install/submit/{uuid}")
public String installSubmit(@PathVariable String uuid, @RequestBody List<String> deviceList) {
return pointInfoService.installSubmit(uuid, deviceList);
}
@GetMapping("/getBindQRCode")
public String getBindQRCode(String uuid) {
return wechatMod.genBindOpenidQRCode(uuid);
}
@GetMapping("/getBindOpenid")
public Object genBindOpenidQRCode(String uuid, String code) {
return pointInfoService.bindOpenid(uuid, code);
}
}
......@@ -82,7 +82,7 @@ public class TaskController {
@GetMapping("/task/export")
@SaCheckPermission(value = "task:export", orRole = "admin")
public void defaultBuild(TaskDTO data, HttpServletResponse response) {
public void taskExport(TaskDTO data, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
data.setPageSize(9999);
Page<TaskVO> voPage = taskService.getTaskList(data);
......
......@@ -6,15 +6,11 @@ import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import vion.third.WechatMod;
import vion.dto.TaskTempDTO;
import vion.model.TaskTemp;
import vion.service.ITaskTempService;
import vion.vo.TaskTempVO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 预工单
*/
......@@ -25,7 +21,6 @@ import java.io.IOException;
public class TaskTempController {
private final ITaskTempService taskTempService;
private final WechatMod wechatMod;
private final Converter converter;
@GetMapping("/taskTemps")
......@@ -46,17 +41,6 @@ public class TaskTempController {
return taskTempService.saveOrUpdTaskTemp(data);
}
@GetMapping("/taskTemp/wechatCallback")
public Object wechatCallback(String code, HttpServletResponse res) throws IOException {
Object obj = wechatMod.wechatCallback(code);
if (obj instanceof String) {
res.sendRedirect("https://yunwei.vionyun.com/wap/?openid=" + obj);
} else {
return obj;
}
return "success";
}
@PostMapping("/taskTemp/{id}")
@SaCheckPermission(value = "taskTemp:edit", orRole = "admin")
public String upd(@PathVariable(name = "id") Long id, TaskTempDTO data) {
......
......@@ -4,24 +4,24 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import vion.dto.DingDTO;
import vion.dto.UserDTO;
import vion.model.RUserRole;
import vion.model.Role;
import vion.model.TaskTemp;
import vion.model.User;
import vion.service.IRUserRoleService;
import vion.service.IRoleService;
import vion.service.ITaskTempService;
import vion.service.IUserService;
import vion.third.DingMod;
import vion.third.WechatMod;
......@@ -29,7 +29,9 @@ import vion.vo.RoleVO;
import vion.vo.UserVO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
......@@ -40,7 +42,6 @@ import java.util.stream.Collectors;
public class UserController {
private final IUserService userService;
private final ITaskTempService taskTempService;
private final IRUserRoleService userRoleService;
private final IRoleService roleService;
private final Converter converter;
......@@ -106,14 +107,36 @@ public class UserController {
return "注销成功";
}
@GetMapping("/wechat/callback")
public Object wechatCallback(String code, Long taskTempId) {
Object obj = wechatMod.wechatCallback(code);
if (obj instanceof String) {
return taskTempService.lambdaUpdate().set(TaskTemp::getOpenid, obj).eq(TaskTemp::getId, taskTempId).update(new TaskTemp()) ? new ModelAndView("weChatNeedAttention") : new ModelAndView("weChatError");
/**
* 用于微信公众号自定义菜单里填写的回调地址
*
* @param code 授权码
* @param active 前端标识,根据此标识跳转到不同的页面
* @param res
* @return java.lang.Object
*/
@GetMapping("/wechatCallback")
public Object wechatCallback(String code, Integer active, HttpServletResponse res) throws IOException {
Object obj = wechatMod.getOpenid(code);
if (obj instanceof Map) {
Map<String, String> map = (Map<String, String>) obj;
res.sendRedirect(StrUtil.format("https://yunwei.vionyun.com/wap?openid={}&nickname={}&active={}", map.get("openid"), URLUtil.encode(map.get("nickname")), active));
} else {
return obj;
}
return "success";
}
@GetMapping("/getQRCode")
public String getCallbackQRCode(Long id, Integer flag) {
Assert.notNull(id, "id 不能为空");
Assert.notNull(flag, "flag 不能为空");
return wechatMod.genCallbackQRCode(id, flag);
}
@GetMapping("/getFollowingOpenid")
public Object getOpenid(Long id, Integer flag, String code) {
return wechatMod.getFollowingOpenid(id, flag, code);
}
}
......@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
import vion.model.Contract;
import vion.model.ContractPayment;
import vion.model.Dictionary;
import vion.model.Payment;
import vion.service.*;
import java.math.BigDecimal;
......@@ -35,6 +36,7 @@ public class ContractRunner {
private final IDictionaryService dictionaryService;
private final IContractPaymentService contractPaymentService;
private final IStoreService storeService;
private final IPaymentService paymentService;
private final RedisTemplate redisTemplate;
@Scheduled(cron = "0 0 * * * *")
......@@ -122,8 +124,8 @@ public class ContractRunner {
});
contractService.saveOrUpdateBatch(insOrUpdContractList, 500);
List<ContractPayment> paymentList = contractPaymentService.list();
Map<Long, Map<Integer, Long>> contractId2PaymentMap = paymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.toMap(ContractPayment::getPaymentType, ContractPayment::getId)));
List<ContractPayment> existContractPaymentList = contractPaymentService.list();
Map<Long, Map<Integer, Long>> contractId2PaymentMap = existContractPaymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.toMap(ContractPayment::getPaymentType, ContractPayment::getId)));
// 合同付款比例
List<ContractPayment> contractPaymentList = new ArrayList<>();
......@@ -203,12 +205,15 @@ public class ContractRunner {
}
contractPaymentService.saveOrUpdateBatch(contractPaymentList);
List<Payment> paymentList = paymentService.list();
Map<String, BigDecimal> no2PaymentMap = paymentList.stream().collect(Collectors.groupingBy(Payment::getContractNo, Collectors.reducing(BigDecimal.ZERO, Payment::getPaymentAmount, BigDecimal::add)));
insOrUpdContractList.forEach(c -> {
String contractNo = c.getContractNo();
Contract exist = contractService.lambdaQuery().eq(Contract::getContractNo, contractNo).one();
Contract updDto = new Contract();
updDto.setId(exist.getId());
updDto.setPaidAmount(exist.getPaidAmount());
updDto.setPaidAmount(no2PaymentMap.getOrDefault(contractNo, BigDecimal.ZERO));
contractPaymentService.calMoney(exist, updDto);
contractService.updateById(updDto);
});
......
......@@ -18,13 +18,27 @@ public class DeliveryRecordDTO extends BaseDTO {
*/
private String contractNo;
/**
* 合同id
*/
private Long contractId;
/**
* 收货人
*/
private String consignee;
/**
* 收货地址
*/
private String address;
/**
* 收货电话
*/
private String phone;
/**
* 合同名称
*/
private String contractName;
......@@ -48,6 +62,21 @@ public class DeliveryRecordDTO extends BaseDTO {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date signDate;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 发货清单
*/
private String shippingRemark;
private String remark;
private MultipartFile[] files;
......
......@@ -3,6 +3,8 @@ package vion.dto;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class FileInfoDTO extends BaseDTO {
......@@ -13,6 +15,7 @@ public class FileInfoDTO extends BaseDTO {
private String type;
/** 文件来源(1项目、2工单预处理,3工单操作,4巡检) */
private Integer sourceType;
private List<Integer> sourceTypeList;
/** 文件来源id */
private Long sourceId;
/** 合同id */
......
package vion.dto;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
/**
* @author HlQ
* @date 2024/1/8
*/
@Getter
@Setter
public class PointInfoDTO extends BaseDTO {
private Long id;
/**
* 集团id
*/
private Long accountId;
/**
* 项目名称(用户填写的)
*/
private String projectName;
/**
* 联系人
*/
private String contact;
/**
* 手机号码
*/
private String phone;
/**
* 点位数量
*/
private Integer pointNum;
/**
* 发货状态
*/
private Integer shippingStatus;
/**
* 收货地址
*/
private String shippingAddress;
/**
* 收货联系人
*/
private String receivingContact;
/**
* 收货联系电话
*/
private String receivingPhone;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 状态
*/
private Integer status;
/**
* 合同编号
*/
private String contractNo;
/**
* 合同id
*/
private Long contractId;
/**
* 是否施工 0:不施工 1:施工
*/
private Integer isConstruct;
/**
* 施工地址
*/
private String constructAddress;
/**
* 施工联系人
*/
private String constructContact;
/**
* 施工联系电话
*/
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
private Integer invoiceType;
/**
* 发票抬头
*/
private String invoiceHeader;
/**
* 税号
*/
private String taxIdNum;
/**
* 单位地址
*/
private String invoiceAddress;
/**
* 单位电话
*/
private String invoicePhone;
/**
* 开户银行
*/
private String accountBank;
/**
* 银行卡号
*/
private String bankNumber;
/**
* 邮箱地址
*/
private String email;
/**
* 发票邮寄地址
*/
private String invoiceRecAddress;
/**
* 发票联系人
*/
private String invoiceContact;
/**
* 发票联系电话
*/
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
private String invoiceTrackingNumber;
/**
* 备注
*/
private String remake;
/**
* uuid
*/
private String uuid;
/**
* 施工方
*/
private String constructionSide;
/**
* 文件来源
*/
private Integer sourceType;
private MultipartFile[] files;
/** 客户上传合同文件 */
private MultipartFile contractFile;
/** 上传的合同范本 */
private MultipartFile contractTemplateFile;
/* 终版合同 */
private MultipartFile finalContractFile;
}
\ No newline at end of file
package vion.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
/**
* @author HlQ
* @date 2024/1/16
*/
@Getter
@Setter
@Builder
public class WxDTO {
/**
* 微信openid
*/
private String openid;
/**
* 微信昵称
*/
private String nickname;
/**
* 单子的id
*/
private Long id;
/**
* flag 1:故障保修 2:点位设计
*/
private Integer flag;
}
package vion.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import vion.dto.WxDTO;
/**
* @author HlQ
* @date 2024/1/16
*/
@Getter
public class WxDTOEvent extends ApplicationEvent {
private final WxDTO wxDTO;
public WxDTOEvent(Object source, WxDTO dto) {
super(source);
this.wxDTO = dto;
}
}
package vion.event.listener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import vion.dto.WxDTO;
import vion.event.WxDTOEvent;
import vion.model.RPointWx;
import vion.model.TaskTemp;
import vion.service.IRPointWxService;
import vion.service.ITaskTempService;
/**
* @author HlQ
* @date 2024/1/16
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class WxDTOEventListener implements ApplicationListener<WxDTOEvent> {
private final ITaskTempService taskTempService;
private final IRPointWxService pointWxService;
@Override
public void onApplicationEvent(WxDTOEvent event) {
WxDTO wxDTO = event.getWxDTO();
Integer flag = wxDTO.getFlag();
String openid = wxDTO.getOpenid();
Long id = wxDTO.getId();
String nickname = wxDTO.getNickname();
if (flag == 1) {
updateTaskTemp(openid, id);
} else if (flag == 2) {
updatePointInfo(openid, nickname, id);
}
}
private void updateTaskTemp(String openid, Long id) {
taskTempService.lambdaUpdate()
.set(TaskTemp::getOpenid, openid)
.eq(TaskTemp::getId, id)
.update(new TaskTemp());
log.info("故障保修单子[id:{}]绑定openid成功!", id);
}
private void updatePointInfo(String openid, String nickname, Long id) {
RPointWx pointWx = new RPointWx();
pointWx.setPointId(id);
pointWx.setOpenid(openid);
pointWx.setWxName(nickname);
pointWxService.save(pointWx);
log.info("点位设计单子[id:{}]绑定openid成功!", id);
}
}
......@@ -18,9 +18,15 @@ public class InterceptorConfig implements WebMvcConfigurer {
StpUtil.renewTimeout(3600L);
}))
.addPathPatterns("/api/**")
.excludePathPatterns("/api/dictionarys")
.excludePathPatterns("/api/upLoadFile", "/api/ding/callback/**", "/api/wechat/**", "/error")
.excludePathPatterns("/api/order/sign/*")
.excludePathPatterns("/api/form/sign/*")
.excludePathPatterns("/api/taskTemp", "/api/taskTemp/wechatCallback");
.excludePathPatterns("/api/wechatCallback")
.excludePathPatterns("/api/taskTemp")
.excludePathPatterns("/api/point/frontSubmit")
.excludePathPatterns("/api/getQRCode", "/api/getFollowingOpenid", "/api/verifyScan")
.excludePathPatterns("/api/point/getBindQRCode", "/api/point/getBindOpenid")
.excludePathPatterns("/api/point/upd/{uuid}", "/api/point/get/{uuid}", "/api/point/install/submit/{uuid}", "/api/point/client/reject", "/api/point/reject/uuid/{uuid}");
}
}
package vion.interceptor;
import cn.hutool.core.util.IdUtil;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
public class RequestIdFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletRequest.setAttribute("requestId", IdUtil.fastSimpleUUID());
chain.doFilter(request, response);
}
}
\ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.PointInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface PointInfoMapper extends MPJBaseMapper<PointInfo> {
}
\ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RPointDevice;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface RPointDeviceMapper extends MPJBaseMapper<RPointDevice> {
}
\ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RPointWx;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface RPointWxMapper extends MPJBaseMapper<RPointWx> {
}
\ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RejectInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface RejectInfoMapper extends MPJBaseMapper<RejectInfo> {
}
\ No newline at end of file
......@@ -34,6 +34,18 @@ public class DeliveryRecord {
@TableField(value = "contract_id")
private Long contractId;
/** 收货人 */
@TableField(value = "consignee")
private String consignee;
/** 收货地址 */
@TableField(value = "address")
private String address;
/** 收货电话 */
@TableField(value = "phone")
private String phone;
/**
* 发货日期
*/
......@@ -47,6 +59,24 @@ public class DeliveryRecord {
private Date signDate;
/**
* 快递公司
*/
@TableField(value = "courier_company")
private String courierCompany;
/**
* 快递单号
*/
@TableField(value = "tracking_number")
private String trackingNumber;
/**
* 发货清单
*/
@TableField(value = "shipping_remark")
private String shippingRemark;
/**
* 备注
*/
private String remark;
......
......@@ -26,9 +26,10 @@ public class FileInfo {
private String type;
/**
* 文件来源
* <br>1项目、2工单预处理,3工单操作,4巡检,5合同,6发货记录</br>
* <br>1项目、2工单预处理,3工单操作,4巡检,5合同,6发货记录</br>
* <br>7签订,8到货,9系统初验,10项目终验,11质保,12第一笔维保款,13第二笔维保款,14第三笔维保款</br>
* <br>15结算差异</br>
* <br>16客户提交的门店图纸,17点位设计图,18合同范本,19客户上传的合同,20安装上线,与总部邮件截图</br>
*/
private Integer sourceType;
/** 文件来源id */
......
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import lombok.Data;
import vion.dto.PointInfoDTO;
import vion.vo.PointInfoVO;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/8
*/
@Data
@TableName(value = "tbl_point_info")
@AutoMappers({
@AutoMapper(target = PointInfoVO.class),
@AutoMapper(target = PointInfoDTO.class),
})
public class PointInfo {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 集团id
*/
@TableField(value = "account_id")
private Long accountId;
/**
* 项目名称(用户填写的)
*/
@TableField(value = "project_name")
private String projectName;
/**
* 联系人
*/
@TableField(value = "contact", condition = SqlCondition.LIKE)
private String contact;
/**
* 手机号码
*/
@TableField(value = "phone", condition = SqlCondition.LIKE)
private String phone;
/**
* 点位数量
*/
@TableField(value = "point_num")
private Integer pointNum;
/**
* 发货状态
*/
@TableField(value = "shipping_status")
private Integer shippingStatus;
/**
* 收货地址
*/
@TableField(value = "shipping_address")
private String shippingAddress;
/**
* 收货联系人
*/
@TableField(value = "receiving_contact")
private String receivingContact;
/**
* 收货联系电话
*/
@TableField(value = "receiving_phone")
private String receivingPhone;
/**
* 快递公司
*/
@TableField(value = "courier_company")
private String courierCompany;
/**
* 快递单号
*/
@TableField(value = "tracking_number")
private String trackingNumber;
/**
* 状态
*/
@TableField(value = "\"status\"")
private Integer status;
/**
* 合同编号
*/
@TableField(value = "contract_no")
private String contractNo;
/**
* 是否施工 0:不施工 1:施工
*/
@TableField(value = "is_construct")
private Integer isConstruct;
/**
* 施工地址
*/
@TableField(value = "construct_address")
private String constructAddress;
/**
* 施工联系人
*/
@TableField(value = "construct_contact")
private String constructContact;
/**
* 施工联系电话
*/
@TableField(value = "construct_phone")
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
@TableField(value = "is_invoice")
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
@TableField(value = "invoice_type")
private Integer invoiceType;
/**
* 发票抬头
*/
@TableField(value = "invoice_header")
private String invoiceHeader;
/**
* 税号
*/
@TableField(value = "tax_id_num")
private String taxIdNum;
/**
* 单位地址
*/
@TableField(value = "invoice_address")
private String invoiceAddress;
/**
* 单位电话
*/
@TableField(value = "invoice_phone")
private String invoicePhone;
/**
* 开户银行
*/
@TableField(value = "account_bank")
private String accountBank;
/**
* 银行卡号
*/
@TableField(value = "bank_number")
private String bankNumber;
/**
* 邮箱地址
*/
@TableField(value = "email")
private String email;
/**
* 发票邮寄地址
*/
@TableField(value = "invoice_rec_address")
private String invoiceRecAddress;
/**
* 发票联系人
*/
@TableField(value = "invoice_contact")
private String invoiceContact;
/**
* 发票联系电话
*/
@TableField(value = "invoice_rec_phone")
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
@TableField(value = "invoice_courier_company")
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
@TableField(value = "invoice_tracking_number")
private String invoiceTrackingNumber;
/**
* 备注
*/
@TableField(value = "remake")
private String remake;
/**
* 施工方
*/
@TableField(value = "construction_side")
private String constructionSide;
/**
* uuid
*/
@TableField(value = "uuid")
private String uuid;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
\ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/12
*/
@Data
@TableName(value = "r_point_device")
public class RPointDevice {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位记录id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 设备序列号
*/
@TableField(value = "device_no")
private String deviceNo;
@TableField(value = "create_time")
private Date createTime;
@TableField(value = "update_time")
private Date updateTime;
}
\ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/12
*/
@Data
@TableName(value = "r_point_wx")
public class RPointWx {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位记录id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 微信昵称
*/
@TableField(value = "wx_name")
private String wxName;
/**
* 微信openid
*/
@TableField(value = "openid")
private String openid;
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}
\ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import vion.dto.BaseDTO;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/8
*/
@Data
@TableName(value = "tbl_reject_info")
public class RejectInfo extends BaseDTO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位信息id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 驳回类型
*/
@TableField(value = "\"type\"")
private Integer type;
/**
* 内容
*/
@TableField(value = "content")
private String content;
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}
\ No newline at end of file
......@@ -6,6 +6,8 @@ import vion.dto.DeliveryRecordDTO;
import vion.model.DeliveryRecord;
import vion.vo.DeliveryRecordVO;
import java.util.List;
/**
* @author HlQ
* @date 2023/12/5
......@@ -16,5 +18,7 @@ public interface IDeliveryRecordService extends MPJBaseService<DeliveryRecord> {
String save(DeliveryRecordDTO dto);
String saveBatch(List<DeliveryRecordDTO> dto);
String updateById(DeliveryRecordDTO dto);
}
package vion.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import vion.dto.PointInfoDTO;
import vion.model.PointInfo;
import vion.model.RejectInfo;
import vion.vo.PointInfoVO;
import java.util.List;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface IPointInfoService extends MPJBaseService<PointInfo> {
Object frontSubmit(PointInfoDTO dto);
Object save(PointInfoDTO dto);
String upd(Long id, String uuid, PointInfoDTO dto);
Page<PointInfoVO> list(PointInfoDTO dto);
PointInfoVO getPointByDetail(Long id, String uuid);
String delById(Long id);
String reject(RejectInfo dto, String userStr);
Page<RejectInfo> rejectInfoList(Long pointId, RejectInfo dto);
Page<RejectInfo> rejectInfoList(String uuid, RejectInfo dto);
Object designPush(Long pointId, PointInfo pointInfo, String pushType);
String installSubmit(String uuid, List<String> deviceList);
Object bindOpenid(String uuid, String code);
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RPointDevice;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface IRPointDeviceService extends MPJBaseService<RPointDevice> {
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RPointWx;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface IRPointWxService extends MPJBaseService<RPointWx> {
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RejectInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface IRejectInfoService extends MPJBaseService<RejectInfo> {
}
......@@ -4,24 +4,25 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import vion.dto.ContractDTO;
import vion.dto.DeliveryRecordDTO;
import vion.mapper.DeliveryRecordMapper;
import vion.model.Contract;
import vion.model.DeliveryRecord;
import vion.model.FileInfo;
import vion.service.IContractService;
import vion.service.IDeliveryRecordService;
import vion.service.IFileService;
import vion.model.*;
import vion.service.*;
import vion.third.DingMod;
import vion.vo.DeliveryRecordVO;
import vion.vo.UserVO;
......@@ -29,6 +30,8 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author HlQ
......@@ -40,6 +43,10 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
private final IFileService fileService;
private final IContractService contractService;
private final IRContractUserService contractUserService;
private final IPointInfoService pointInfoService;
private final DingMod dingMod;
private final RedisTemplate redisTemplate;
private final Converter converter;
@Value("${fileUrl:}")
......@@ -55,16 +62,23 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
.like(StrUtil.isNotBlank(dto.getContractName()), Contract::getName, dto.getContractName())
.like(StrUtil.isNotBlank(dto.getCustomerName()), Contract::getCustomerName, dto.getCustomerName())
.orderByDesc(DeliveryRecord::getCreateTime);
return this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), DeliveryRecordVO.class, wrapper);
Page<DeliveryRecordVO> voPage = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), DeliveryRecordVO.class, wrapper);
Opt.ofEmptyAble(voPage.getRecords())
.map(recs -> recs.stream().map(DeliveryRecordVO::getId).collect(Collectors.toList()))
.map(ids -> {
List<FileInfo> fileInfos = fileService.lambdaQuery().in(FileInfo::getSourceId, ids).eq(FileInfo::getSourceType, 6).list();
return fileInfos.stream().collect(Collectors.groupingBy(FileInfo::getSourceId));
})
.filter(MapUtil::isNotEmpty)
.ifPresent(map -> voPage.getRecords().forEach(rec -> rec.setFileList(map.get(rec.getId()))));
return voPage;
}
@Override
public String save(DeliveryRecordDTO dto) {
DeliveryRecord record = converter.convert(dto, DeliveryRecord.class);
if (this.save(record)) {
ContractDTO contractDTO = new ContractDTO();
contractDTO.setStatus(2);
contractService.updateById(null, dto.getContractNo(), contractDTO);
updStatusAndPushMsg(record);
Opt.ofNullable(dto.getFiles())
.ifPresent(fileList -> {
......@@ -74,7 +88,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);;
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + dto.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
try {
......@@ -103,6 +117,66 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
}
@Override
public String saveBatch(List<DeliveryRecordDTO> dto) {
List<DeliveryRecord> records = converter.convert(dto, DeliveryRecord.class);
if (this.saveBatch(records)) {
records.forEach(record -> updStatusAndPushMsg(record));
return "新增成功";
} else {
return "新增失败";
}
}
private void updStatusAndPushMsg(DeliveryRecord record) {
ContractDTO contractDTO = new ContractDTO();
contractDTO.setStatus(2);
Contract existContract = contractService.lambdaQuery().eq(Contract::getContractNo, record.getContractNo()).one();
if (existContract.getStatus() < 2) {
contractService.updateById(null, record.getContractNo(), contractDTO);
}
// 更新点位信息的发货状态
pointInfoService.lambdaUpdate().set(PointInfo::getShippingStatus, 1)
.set(PointInfo::getCourierCompany, record.getCourierCompany())
.set(PointInfo::getTrackingNumber, record.getTrackingNumber())
.set(PointInfo::getStatus, 9)
.eq(PointInfo::getContractNo, record.getContractNo()).update(new PointInfo());
Opt.ofNullable(pointInfoService.lambdaQuery().eq(PointInfo::getContractNo, record.getContractNo()).one())
.ifPresent(p -> pointInfoService.designPush(null, p, "发货"));
List<String> useridList = contractUserService.listObjs(Wrappers.<RContractUser>lambdaQuery().select(RContractUser::getUserId).eq(RContractUser::getContractId, existContract.getId()), Object::toString);
Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:name:" + existContract.getSaleName())))
.map(User::getUserid)
.ifPresent(useridList::add);
dingMod.sendMessage(buildMsg(useridList.stream().distinct().collect(Collectors.joining(",")), record, existContract));
}
JSONObject buildMsg(String userid, DeliveryRecord rec, Contract contract) {
JSONObject jsonObj = new JSONObject();
jsonObj.set("agent_id", 2358374016L);
jsonObj.set("userid_list", userid);
JSONObject msg = new JSONObject();
JSONObject content = new JSONObject();
content.set("title", "设备发货提醒");
String markdown = StrUtil.format("#### 发货通知" +
" \n #### 合同名称:{}" +
" \n #### 合同编号:{}" +
" \n #### 快递公司:{}" +
" \n #### 快递单号:{}" +
" \n #### 收件人:{}" +
" \n #### 发货日期:{}" +
" \n #### 发送时间:{}",
contract.getName(), contract.getContractNo(), rec.getCourierCompany(), rec.getTrackingNumber(), rec.getConsignee(), DateUtil.formatDate(rec.getShipDate()), DateUtil.now());
content.set("text", markdown);
msg.set("msgtype", "markdown");
msg.set("markdown", content);
jsonObj.set("msg", msg);
return jsonObj;
}
@Override
public String updateById(DeliveryRecordDTO dto) {
DeliveryRecord record = converter.convert(dto, DeliveryRecord.class);
if (this.updateById(record)) {
......@@ -115,7 +189,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);;
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + deliveryRecord.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
try {
......
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RPointDeviceMapper;
import vion.model.RPointDevice;
import vion.service.IRPointDeviceService;
/**
* @author HlQ
* @date 2024/1/12
*/
@Service
public class RPointDeviceServiceImpl extends MPJBaseServiceImpl<RPointDeviceMapper, RPointDevice> implements IRPointDeviceService {
}
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RPointWxMapper;
import vion.model.RPointWx;
import vion.service.IRPointWxService;
/**
* @author HlQ
* @date 2024/1/12
*/
@Service
public class RPointWxServiceImpl extends MPJBaseServiceImpl<RPointWxMapper, RPointWx> implements IRPointWxService {
}
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RejectInfoMapper;
import vion.model.RejectInfo;
import vion.service.IRejectInfoService;
/**
* @author HlQ
* @date 2024/1/8
*/
@Service
public class RejectInfoServiceImpl extends MPJBaseServiceImpl<RejectInfoMapper, RejectInfo> implements IRejectInfoService {
}
......@@ -132,7 +132,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);;
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + statusDTO.getStoreId() + FileUtil.FILE_SEPARATOR + statusDTO.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
try {
......
......@@ -5,12 +5,10 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.*;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
......@@ -134,7 +132,10 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
}
// 可能直接提工单,而不是预工单确认之后生成的工单
if (data.getTaskTempId() != null) {
if (ObjUtil.isNotNull(data.getTaskTempId())) {
Task existTask = this.lambdaQuery().eq(Task::getTaskTempId, data.getTaskTempId()).one();
Assert.isNull(existTask, "工单已创建,无需再次确认");
taskTempService.lambdaUpdate()
.set(TaskTemp::getStatus, 3)
.set(TaskTemp::getOperator, data.getActiveUser())
......@@ -221,11 +222,12 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
.put(4, "挂起")
.build();
List<WxMpTemplateData> wxMpTemplateDataList = ListUtil.of(
new WxMpTemplateData("character_string1", existTask.getUuid()),
new WxMpTemplateData("thing7", DesensitizedUtil.chineseName(user.getUsername())),
new WxMpTemplateData("time4", DateUtil.formatDateTime(new Date())),
new WxMpTemplateData("const3", statusMap.get(existTask.getStatus())));
String sentMsg = wechatMod.sendMsg("ueJlVya7uOfYhFlIv28pC0kiHPe1b6Q-gkWsYKkoRWo", openid, wxMpTemplateDataList, null);
new WxMpTemplateData("character_string21", existTask.getUuid()),
new WxMpTemplateData("thing12", DesensitizedUtil.chineseName(user.getUsername())),
new WxMpTemplateData("time11", DateUtil.formatDateTime(new Date())),
new WxMpTemplateData("thing20", existTask.getFaultDescription().length() > 20 ? StrUtil.sub(existTask.getFaultDescription(), 0, 17) + "..." : existTask.getFaultDescription()),
new WxMpTemplateData("phrase25", statusMap.get(existTask.getStatus())));
String sentMsg = wechatMod.sendMsg("H3zWJysLWrcxrUlrgqPnjDV7LyWLaml_Ap9WsLuQDCs", openid, wxMpTemplateDataList, null);
});
}
......@@ -235,7 +237,7 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);;
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + data.getStoreId() + FileUtil.FILE_SEPARATOR + task.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
try {
......
......@@ -3,6 +3,7 @@ package vion.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONArray;
......@@ -26,7 +27,6 @@ import vion.service.IFileService;
import vion.service.ITaskTempService;
import vion.service.IUserService;
import vion.third.DingMod;
import vion.third.WechatMod;
import vion.vo.TaskTempVO;
import java.io.File;
......@@ -43,7 +43,6 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
private final IFileService fileService;
private final IUserService userService;
private final DingMod dingMod;
private final WechatMod wechatMod;
private final Converter converter;
@Value("${fileUrl:}")
......@@ -88,7 +87,7 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);;
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + 0 + FileUtil.FILE_SEPARATOR + taskTemp.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
try {
......@@ -114,11 +113,9 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
String userids = userList.stream().map(User::getUserid).collect(Collectors.joining(","));
dingMod.sendMessage(buildMsg(userids, taskTemp));
if (StrUtil.isNotBlank(data.getOpenid())) {
return "工单提交成功!";
} else {
return wechatMod.genQRCodeUrl(taskTemp.getId());
}
return MapUtil.<String, Long>builder()
.put("id", taskTemp.getId())
.build();
}
JSONObject buildMsg(String userid, TaskTemp taskTemp) {
......
......@@ -148,7 +148,8 @@ public class DingMod {
}
userService.saveOrUpdate(user, Wrappers.<User>lambdaUpdate().eq(User::getUserid, userid));
User one = userService.lambdaQuery().eq(User::getUserid, userid).one();
redisTemplate.opsForValue().set("dingtalk:user:" + one.getId(), user);
redisTemplate.opsForValue().set("dingtalk:user:id:" + one.getId(), user);
redisTemplate.opsForValue().set("dingtalk:user:name:" + one.getUsername(), user);
}
}
});
......@@ -190,7 +191,9 @@ public class DingMod {
*/
public String sendMessage(JSONObject msg) {
String token = getToken();
return HttpUtil.post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=" + token, msg.toString());
String res = HttpUtil.post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=" + token, msg.toString());
log.info("钉钉工作通知消息推送:{}", res);
return res;
}
/**
......@@ -329,4 +332,10 @@ public class DingMod {
}
return "";
}
public String robotPush(String access_token, String body) {
String res = HttpUtil.post("https://oapi.dingtalk.com/robot/send?access_token=" + access_token, body);
log.info("钉钉机器人消息推送:{}", res);
return res;
}
}
package vion.third;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -8,10 +10,14 @@ import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import vion.dto.WxDTO;
import vion.event.WxDTOEvent;
import java.util.List;
......@@ -25,18 +31,24 @@ import java.util.List;
public class WechatMod {
private final WxMpService wxMpService;
private final ApplicationEventPublisher publisher;
/**
* 微信扫码获取用户 openid
* 用于微信公众号内提交单子。
* 用户已关注公众号,直接获取 openid 即可。
*
* @param code 授权码
* @return java.lang.Object
*/
public Object wechatCallback(String code) {
public Object getOpenid(String code) {
try {
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
return wxMpUser.getOpenid();
WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
String openid = userInfo.getOpenid();
String nickname = userInfo.getNickname();
return MapUtil.<String, String>builder()
.put("nickname", nickname)
.put("openid", openid).build();
} catch (WxErrorException e) {
log.error("调用微信接口异常!", e);
}
......@@ -44,14 +56,55 @@ public class WechatMod {
}
/**
* 生成微信网页授权链接
* 生成微信网页授权链接用于 pc 端故障保修、点位设计等页面,绑定openid
*
* @param taskTempId 预工单 id
* @param id 生成单子的 id
* @param flag 1:故障保修 2:点位设计
* @return java.lang.String
*/
public String genQRCodeUrl(Long taskTempId) {
String url = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/wechat/callback?taskTempId={}", taskTempId);
return wxMpService.getOAuth2Service().buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
public String genCallbackQRCode(Long id, Integer flag) {
String redirectUri = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/getFollowingOpenid?id={}&flag={}", id, flag);
return wxMpService.getOAuth2Service().buildAuthorizationUrl(redirectUri, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
}
/**
* 用户提交单子,需要判断用户是否关注公众号。
* 关注公众号的用户,直接获取 openid,返回前端,前端提交工单(或其他单子)时带上 openid。
* 未关注公众号的用户,直接返回一个页面,提示用户关注公众号。
*
* @param code 授权码
* @return java.lang.Object
*/
public Object getFollowingOpenid(Long id, Integer flag, String code) {
try {
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
String openid = userInfo.getOpenid();
WxMpUser wxMpUser = wxMpService.getUserService().userInfo(openid);
if (!wxMpUser.getSubscribe()) {
return new ModelAndView("weChatNeedAttention");
}
String nickname = userInfo.getNickname();
WxDTO wxDTO = WxDTO.builder().nickname(nickname).openid(openid).id(id).flag(flag).build();
WxDTOEvent wxDTOEvent = new WxDTOEvent(this, wxDTO);
publisher.publishEvent(wxDTOEvent);
return new ModelAndView("weChatSuccess");
} catch (WxErrorException e) {
log.error("调用微信接口异常!", e);
}
return new ModelAndView("weChatError");
}
/**
* 点位设计详情页获取绑定微信二维码
*
* @param uuid 点位记录 uuid
* @return java.lang.String
*/
public String genBindOpenidQRCode(String uuid) {
String redirectUri = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/point/getBindOpenid?uuid={}&rid={}", uuid, IdUtil.fastSimpleUUID());
return wxMpService.getOAuth2Service().buildAuthorizationUrl(redirectUri, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
}
public String sendMsg(String templateId, String openId, List<WxMpTemplateData> wxMpTemplateDataList, String url) {
......
......@@ -24,6 +24,20 @@ public class DeliveryRecordVO {
*/
private Long contractId;
/**
* 收货人
*/
private String consignee;
/**
* 收货地址
*/
private String address;
/**
* 收货电话
*/
private String phone;
/**
* 客户名称
......@@ -43,6 +57,21 @@ public class DeliveryRecordVO {
private Date signDate;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 发货清单
*/
private String shippingRemark;
/**
* 备注
*/
private String remark;
......
package vion.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.liaochong.myexcel.core.annotation.ExcelColumn;
import com.github.liaochong.myexcel.core.annotation.ExcelModel;
import com.github.liaochong.myexcel.core.constant.LinkType;
import lombok.Getter;
import lombok.Setter;
import vion.model.FileInfo;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author HlQ
* @date 2024/1/8
*/
@Getter
@Setter
@ExcelModel(sheetName = "点位设计", includeAllField = false)
public class PointInfoVO {
private Long id;
/**
* 集团id
*/
private Long accountId;
private String accountName;
/**
* 项目名称(用户填写的)
*/
@ExcelColumn(order = 0, title = "门店名称")
private String projectName;
/**
* 联系人
*/
@ExcelColumn(order = 1, title = "联系人")
private String contact;
/**
* 手机号码
*/
@ExcelColumn(order = 2, title = "联系电话")
private String phone;
/**
* 点位数量
*/
@ExcelColumn(order = 3, title = "点位数量")
private Integer pointNum;
/**
* 点位设计图url
*/
@ExcelColumn(order = 4, title = "点位设计图", linkType = LinkType.URL)
private String pointUrl;
/**
* 发货状态
*/
private Integer shippingStatus;
/**
* 收货地址
*/
private String shippingAddress;
/**
* 收货联系人
*/
private String receivingContact;
/**
* 收货联系电话
*/
private String receivingPhone;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 状态
*/
private Integer status;
/**
* 合同编号
*/
private String contractNo;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 是否施工 0:不施工 1:施工
*/
private Integer isConstruct;
/**
* 施工地址
*/
private String constructAddress;
/**
* 施工联系人
*/
private String constructContact;
/**
* 施工联系电话
*/
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
private Integer invoiceType;
/**
* 发票抬头
*/
private String invoiceHeader;
/**
* 税号
*/
private String taxIdNum;
/**
* 单位地址
*/
private String invoiceAddress;
/**
* 单位电话
*/
private String invoicePhone;
/**
* 开户银行
*/
private String accountBank;
/**
* 银行卡号
*/
private String bankNumber;
/**
* 邮箱地址
*/
private String email;
/**
* 发票邮寄地址
*/
private String invoiceRecAddress;
/**
* 发票联系人
*/
private String invoiceContact;
/**
* 发票联系电话
*/
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
private String invoiceTrackingNumber;
/**
* 图纸数量
*/
private Long drawingCnt;
/**
* 点位设计图的数量
*/
private Long designCnt;
/**
* 合同相关的数量
*/
private Long contractCnt;
/**
* 回执单的数量
*/
private Long receiptCnt;
/**
* 备注
*/
private String remake;
/**
* 施工方
*/
private String constructionSide;
/**
* uuid
*/
private String uuid;
private List<String> wxNameList;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
/**
* 客户上传的图纸文件
*/
private List<FileInfo> drawingFiles;
/**
* 点位设计图文件
*/
private List<FileInfo> designFiles;
/**
* 合同范本文件
*/
private List<FileInfo> contractTemplateFiles;
/**
* 终版合同
*/
private List<FileInfo> finalContractFiles;
/**
* 合同文件
*/
private List<FileInfo> contractFiles;
/**
* 回执单文件
*/
private List<FileInfo> receiptFiles;
}
\ No newline at end of file
debug=false
################################## DATABASE ########################################
#spring.datasource.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order
#spring.datasource.username=vion
#spring.datasource.password=jkou72j32m4K5d8k
#spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.dynamic.primary=master
spring.datasource.dynamic.strict=false
spring.datasource.dynamic.datasource.master.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order
spring.datasource.dynamic.datasource.master.username=vion
spring.datasource.dynamic.datasource.master.password=jkou72j32m4K5d8k
spring.datasource.dynamic.datasource.master.driver-class-name=org.postgresql.Driver
spring.datasource.dynamic.datasource.slave_1.url=jdbc:postgresql://47.102.107.41:5432/f_serv
spring.datasource.dynamic.datasource.slave_1.username=postgres
spring.datasource.dynamic.datasource.slave_1.password=zxl123456
spring.datasource.dynamic.datasource.slave_1.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order
spring.datasource.username=vion
spring.datasource.password=jkou72j32m4K5d8k
spring.datasource.driver-class-name=org.postgresql.Driver
spring.redis.host=r-2zejlb88mng3q50aw7pd.redis.rds.aliyuncs.com
spring.redis.password=RtOTnx2V
spring.redis.port=6379
spring.redis.database=8
wx.mp.config-storage.type=RedisTemplate
wx.mp.config-storage.key-prefix=wa
wx.mp.config-storage.redis.host=r-2zejlb88mng3q50aw7pd.redis.rds.aliyuncs.com
wx.mp.config-storage.redis.password==RtOTnx2V
wx.mp.config-storage.redis.port=6379
wx.mp.config-storage.redis.database=8
server.port=8011
fileUrl=D:/pic
#fileurl=/nas-data/work-order
......
......@@ -9,7 +9,7 @@
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="logs"/>
<property name="pattern" value="[%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS})] %highlight([%-5level]) [%thread] %green(%logger{50} [%L]) - %msg%n"/>
<property name="pattern" value="[%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS})] %cyan(%X{requestId}) %highlight([%-5level]) [%thread] %green(%logger{50} [%L]) - %msg%n"/>
<property name="datapattern" value="%msg%n"/>
<!--输出到控制台-->
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xml; charset=utf-8" />
</head>
<title>绑定成功</title>
<style>
.center{
line-height: 200px;
height: 100%;
text-align: center;
}
.center p {
line-height: 1.5;
display: inline-block;
vertical-align: middle;
font-size: 6rem;
}
</style>
<body>
<div class="center">
<p>绑定成功</p>
</div>
</body>
</html>
\ No newline at end of file
......@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/xml; charset=utf-8" />
</head>
<title>绑定成功</title>
<title>扫码成功</title>
<style>
.center{
line-height: 200px;
......@@ -19,7 +19,7 @@
</style>
<body>
<div class="center">
<p>绑定成功</p>
<p>扫码成功</p>
</div>
</body>
</html>
\ 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!