Commit ce684107 by HlQ

[add]

1.添加富文本编辑器图片上传接口
2.添加合同导出功能
[chg]
1.微信公众号内提交点位设计,微信 openid 和昵称入库
2.合同列表查询优化
1 parent 2e88b2e6
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.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
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 org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.*;
import vion.cron.ContractRunner;
import vion.dto.ContractDTO;
......@@ -16,7 +24,12 @@ import vion.model.RContractUser;
import vion.service.IContractService;
import vion.service.IRContractStoreService;
import vion.vo.ContractVO;
import vion.vo.UserVO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
......@@ -134,4 +147,23 @@ public class ContractController {
contractRunner.contractSync();
return "成功";
}
@GetMapping("/contract/export")
@SaCheckPermission(value = "contract:export", orRole = "admin")
public void pointExport(ContractDTO dto, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
dto.setPageSize(9999);
Page<ContractVO> voPage = contractService.list(dto);
try (DefaultExcelBuilder<ContractVO> pointInfoVODefaultExcelBuilder = DefaultExcelBuilder.of(ContractVO.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);
}
}
}
......@@ -55,47 +55,51 @@ public class FileController {
}
}
@PostMapping("/upLoadFile")
public String uploadFile(FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) {
try {
//上传url地址
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);
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());
@PostMapping("/file/formFileUpload")
public String uploadFile(FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) throws IOException {
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 path = getPath(fileInfo, filename);
File file = FileUtil.touch(path);
infile.transferTo(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);
if (fileService.save(tempFileInfo)) {
return path;
} else {
return "文件保存失败";
}
return "文件保存成功";
}
@PostMapping("/uploadFile1")
private String getPath(FileInfo fileInfo, String filename) {
String path;
if ("storeLog".equals(fileInfo.getFlag())) {
path = fileUrl + FileUtil.FILE_SEPARATOR + "form" + FileUtil.FILE_SEPARATOR + "storeLog" + FileUtil.FILE_SEPARATOR + fileInfo.getStoreId() + FileUtil.FILE_SEPARATOR + fileInfo.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
} else {
path = fileUrl + FileUtil.FILE_SEPARATOR + "form" + FileUtil.FILE_SEPARATOR + fileInfo.getStoreId() + FileUtil.FILE_SEPARATOR + fileInfo.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
}
return path;
}
@PostMapping("/file/uploadFile")
public String uploadFile1(FileInfo fileInfo, @RequestParam(name = "files") MultipartFile[] files) throws IOException {
for (MultipartFile infile : files) {
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 path = FileUtil.FILE_SEPARATOR + fileInfo.getStoreId() + FileUtil.FILE_SEPARATOR + fileInfo.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
String path = fileUrl + FileUtil.FILE_SEPARATOR + fileInfo.getStoreId() + FileUtil.FILE_SEPARATOR + fileInfo.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path);
infile.transferTo(file);
......
......@@ -72,12 +72,12 @@ public class PointDesignController {
@GetMapping("/{id}")
@SaCheckPermission(value = "point:query", orRole = "admin")
public PointInfoVO getPointById(@PathVariable Long id) {
return pointInfoService.getPointByDetail(id, null);
return pointInfoService.getPointDetail(id, null);
}
@GetMapping("/get/{uuid}")
public PointInfoVO getPointByUuid(@PathVariable String uuid) {
return pointInfoService.getPointByDetail(null, uuid);
return pointInfoService.getPointDetail(null, uuid);
}
@DeleteMapping("/{id}")
......
......@@ -112,7 +112,7 @@ public class UserController {
*
* @param code 授权码
* @param active 前端标识,根据此标识跳转到不同的页面
* @param res
* @param res response
* @return java.lang.Object
*/
@GetMapping("/wechatCallback")
......
......@@ -202,4 +202,8 @@ public class PointInfoDTO extends BaseDTO {
/* 终版合同 */
private MultipartFile finalContractFile;
/** 微信 openid 和昵称 */
private String openid;
private String nickname;
}
\ No newline at end of file
......@@ -30,6 +30,7 @@ public class FileInfo {
* <br>7签订,8到货,9系统初验,10项目终验,11质保,12第一笔维保款,13第二笔维保款,14第三笔维保款</br>
* <br>15结算差异</br>
* <br>16客户提交的门店图纸,17点位设计图,18合同范本,19客户上传的合同,20安装上线,与总部邮件截图</br>
* <br>21服务单等表单富文本编辑器里传图用这个类型</br>
*/
private Integer sourceType;
/** 文件来源id */
......@@ -50,4 +51,8 @@ public class FileInfo {
private String sha256;
/** 上传人 */
private String uploader;
/** 标识:storeLog */
@TableField(exist = false)
private String flag;
}
......@@ -23,7 +23,7 @@ public interface IPointInfoService extends MPJBaseService<PointInfo> {
Page<PointInfoVO> list(PointInfoDTO dto);
PointInfoVO getPointByDetail(Long id, String uuid);
PointInfoVO getPointDetail(Long id, String uuid);
String delById(Long id);
......
......@@ -63,7 +63,7 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
@Override
public Page<ContractVO> list(ContractDTO dto) {
Result result = getResult(dto);
// fixme 关联查询,查出多条一样的记录
Page<ContractVO> contractVOList = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), ContractVO.class, result.wrapper);
if (!result.roleCodeList.contains("admin") && !result.roleCodeList.contains("xiaoshou") && !result.roleCodeList.contains("caiwu")) {
......@@ -388,7 +388,7 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
List<Long> relatedContractIdList = Opt.ofNullable(dto.getProductLine())
.map(pl -> Db.listObjs(Wrappers.lambdaQuery(Store.class).eq(Store::getProductLine, pl), Store::getId))
.map(storeIds -> contractStoreService.listObjs(Wrappers.<RContractStore>lambdaQuery().select(RContractStore::getContractId).in(RContractStore::getStoreId, storeIds), o -> Long.valueOf(o.toString())))
.orElse(ListUtil.empty());
.orElse(new ArrayList<>());
// 根据当前登录用户的角色获取用户名
UserVO userVO = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
Set<String> roleCodeList = Opt.ofEmptyAble(userVO.getRoleVOList())
......@@ -401,18 +401,19 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
}
// 查询当前销售关联的合同
List<Long> contractUserIdList = Opt.ofBlankAble(saleName)
List<Long> contractUserIdList = Opt.ofBlankAble(dto.getSaleName())
.map(name -> contractUserService.listObjs(Wrappers.<RContractUser>lambdaQuery()
.select(RContractUser::getContractId).eq(RContractUser::getUsername, name), o -> Long.valueOf(o.toString())))
.orElse(ListUtil.empty());
.orElse(new ArrayList<>());
Set<Long> mergeContractIdList = new HashSet<>(CollUtil.addAll(relatedContractIdList, contractUserIdList));
// 前端传参中的 saleName 字段已单独处理,这里置空,不参与下一步的 converter.convert
dto.setSaleName(null);
MPJLambdaWrapper<Contract> wrapper = new MPJLambdaWrapper<>(converter.convert(dto, Contract.class))
.selectAll(Contract.class)
.eq(StrUtil.isNotBlank(saleName), Contract::getSaleName, saleName)
.notIn(CollUtil.isNotEmpty(contractIdList), Contract::getId, contractIdList)
.in(CollUtil.isNotEmpty(relatedContractIdList), Contract::getId, relatedContractIdList)
.or()
.in(CollUtil.isNotEmpty(contractUserIdList), Contract::getId, contractUserIdList)
.in(CollUtil.isNotEmpty(mergeContractIdList), Contract::getId, mergeContractIdList)
.between(ArrayUtil.isAllNotNull(dto.getSignDateStart(), dto.getSignDateEnd()), Contract::getSignDate, dto.getSignDateStart(), dto.getSignDateEnd())
.orderByDesc(Contract::getEntryTime);
if (StrUtil.isNotBlank(dto.getOperator()) && ObjUtil.isNotNull(dto.getAmount())) {
......
......@@ -7,6 +7,7 @@ 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.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
......@@ -69,7 +70,22 @@ public class PointInfoServiceImpl extends MPJBaseServiceImpl<PointInfoMapper, Po
@Override
public Object frontSubmit(PointInfoDTO dto) {
return insRec(dto);
Object obj = insRec(dto);
if (obj instanceof Map) {
Map<String, Long> map = (Map<String, Long>) obj;
Opt.ofNullable(new String[]{dto.getOpenid(), dto.getNickname()})
.filter(ArrayUtil::isAllNotNull)
.ifPresent(l -> {
String openid = l[0];
String nickname = l[1];
RPointWx pointWx = new RPointWx();
pointWx.setPointId(map.get("id"));
pointWx.setOpenid(openid);
pointWx.setWxName(nickname);
pointWxService.save(pointWx);
});
}
return obj;
}
@Override
......@@ -112,7 +128,7 @@ public class PointInfoServiceImpl extends MPJBaseServiceImpl<PointInfoMapper, Po
existPoint = this.getById(id);
}
Wrapper<PointInfo> wrapper = Wrappers.<PointInfo>lambdaUpdate()
Wrapper<PointInfo> wrapper = Wrappers.<PointInfo>lambdaUpdate()
.eq(ObjUtil.isNotEmpty(id), PointInfo::getId, id)
.eq(StrUtil.isNotBlank(uuid), PointInfo::getUuid, uuid);
if (this.update(pointInfo, wrapper)) {
......@@ -230,7 +246,7 @@ public class PointInfoServiceImpl extends MPJBaseServiceImpl<PointInfoMapper, Po
if (dto.getSourceType().equals(5)) {
// 合同文件保存到合同相关目录下
// fixme 目前该合同的文件信息的 sourceId 是根据点位设计图来存的。
// fixme 假如合同管理那边查询的话,应该用合同id + sourceType 来查询吗?
// fixme 假如合同管理那边查询的话,应该用合同id + sourceType 来查询吗? 目前 dto.getContractId() 获取不到值
path = fileUrl + FileUtil.FILE_SEPARATOR + "contract" + FileUtil.FILE_SEPARATOR + dto.getContractId() + FileUtil.FILE_SEPARATOR + filename;
} else if (dto.getSourceType().equals(18)) {
path = fileUrl + FileUtil.FILE_SEPARATOR + "point" + FileUtil.FILE_SEPARATOR + id + FileUtil.FILE_SEPARATOR + "template" + FileUtil.FILE_SEPARATOR + filename;
......@@ -269,7 +285,7 @@ public class PointInfoServiceImpl extends MPJBaseServiceImpl<PointInfoMapper, Po
}
@Override
public PointInfoVO getPointByDetail(Long id, String uuid) {
public PointInfoVO getPointDetail(Long id, String uuid) {
MPJLambdaWrapper<PointInfo> wrapper = new MPJLambdaWrapper<PointInfo>()
.selectAll(PointInfo.class)
.selectCollection(RPointWx.class, PointInfoVO::getWxNameList, map -> map.result(RPointWx::getWxName))
......
......@@ -220,7 +220,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
@Override
public List<StoreVO> storeScreen() {
MPJLambdaWrapper<Store> wrapper = new MPJLambdaWrapper<Store>()
.select(Store::getName, Store::getTaskDetail, Store::getFinishDate, Store::getPercentage, Store::getStuckPoint, Store::getIsImportant)
.select(Store::getId, Store::getName, Store::getTaskDetail, Store::getFinishDate, Store::getPercentage, Store::getStuckPoint, Store::getIsImportant)
.selectCollection(User.class, StoreVO::getUserNameList, map -> map.result(User::getUsername))
.leftJoin(RStoreUser.class, on -> on.eq(RStoreUser::getStoreId, Store::getId).eq(RStoreUser::getIsMain, 1))
.leftJoin(User.class, User::getId, RStoreUser::getUserId)
......
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 lombok.Getter;
import lombok.Setter;
import vion.model.ContractLog;
......@@ -11,66 +13,78 @@ import java.util.List;
@Getter
@Setter
@ExcelModel(sheetName = "合同列表", includeAllField = false)
public class ContractVO {
private Long id;
/**
* 合同名称
*/
@ExcelColumn(order = 1, title = "合同名称")
private String name;
/**
* 合同编号
*/
@ExcelColumn(order = 0, title = "合同编号")
private String contractNo;
/**
* 合同类型:1-维保合同 2-框架合同 3-集成合同 4-供货合同 5-供货施工合同 0-其他
*/
@ExcelColumn(order = 3, title = "合同类型", mapping = "1:维保合同,2:框架合同,3:集成合同,4:供货合同,5:供货施工合同,0:其他")
private Integer type;
/**
* 合同签订日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@ExcelColumn(order = 4, title = "签订日期", format = "yyyy-MM-dd")
private Date signDate;
/**
* 合同维保开始日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@ExcelColumn(order = 5, title = "维保开始日期", format = "yyyy-MM-dd")
private Date maintainSdate;
/**
* 合同维保结束日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@ExcelColumn(order = 6, title = "维保结束日期", format = "yyyy-MM-dd")
private Date maintainEdate;
/**
* 合同进度:1-签订 2-发货 3-货到 4-安装 5-验收 6-质保
* 合同进度:1-签订 2-到货 3-系统验收(初验) 4-项目验收(终验) 5-质保 6-第一笔维保款 7-第二笔维保款 8-第三笔维保款
*/
@ExcelColumn(order = 7, title = "合同进度", mapping = "1:合同签订,2:到货,3:系统验收,4:项目验收,5:质保,6:第一笔维保款,7:第二笔维保款,8:第三笔维保款")
private Integer status;
/**
* 合同总金额
*/
@ExcelColumn(order = 9, title = "总金额")
private BigDecimal totalAmount;
/**
* 合同已收金额:人工编辑
* 合同已收金额
*/
@ExcelColumn(order = 10, title = "已收款")
private BigDecimal paidAmount;
/**
* 合同应收金额:
* 根据【合同进度】,由系统判断出应该收到的金额
*/
@ExcelColumn(order = 11, title = "应收款")
private BigDecimal receivableAmount;
/**
* 合同未收金额:total-(paid+receivable)
*/
@ExcelColumn(order = 12, title = "合同余额")
private BigDecimal outstandingAmount;
/**
......@@ -81,11 +95,13 @@ public class ContractVO {
/**
* 合同甲方名称
*/
@ExcelColumn(order = 14, title = "甲方名称")
private String customerName;
/**
* 销售人员名称
*/
@ExcelColumn(order = 8, title = "销售人")
private String saleName;
/**
......@@ -134,6 +150,7 @@ public class ContractVO {
/**
* 开票金额
*/
@ExcelColumn(order = 13, title = "已开票")
private BigDecimal invoiceAmount;
/**
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!