package com.xy.service; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xy.annotation.Lock; import com.xy.collections.list.JArrayList; import com.xy.collections.list.JList; import com.xy.collections.map.JHashMap; import com.xy.collections.map.JMap; import com.xy.config.DeviceThreadPoolConfig; import com.xy.device.EnumDeviceQrCode; import com.xy.device.EnumDeviceType; import com.xy.dto.DeviceCreateIdsDto; import com.xy.dto.DeviceQualityDto; import com.xy.dto.MercDeviceQrConfigDto; import com.xy.dto.SysWorkUser.ListDto; import com.xy.dto.SysWorkUser.SysWorkVo; import com.xy.dto.be.MercDto; import com.xy.entity.DeviceCreateIds; import com.xy.entity.DeviceInfo; import com.xy.mapper.DeviceCreateIdsMapper; import com.xy.service.be.MercService; import com.xy.utils.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import static com.xy.utils.Beans.copy; import static com.xy.utils.PlusBeans.toIPage; import static com.xy.utils.PlusBeans.toPageBean; /** *

* 设备-机器ID号生成 服务实现类 *

* * @author lijin * @since 2022-12-29 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) @Api(tags = "设备-机器ID号生成") public class DeviceCreateIdsServiceImpl extends ServiceImpl implements DeviceCreateIdsService { private final SysWorkUserService sysWorkUserService; private final MercDeviceQrConfigService mercDeviceQrConfigService; private final MercService mercService; private final DeviceInfoServiceImpl deviceInfoService; @SneakyThrows @PostMapping("save") @ApiOperation("添加") @Lock("device-create-ids-save") public R> save(@RequestBody @Validated DeviceCreateIdsDto.Save save) { LocalDate localDate = LocalDate.now(); String year = String.valueOf(localDate.getYear()); String month = String.valueOf(localDate.getMonthValue()); String yearMonth = year.substring(2) + (month.length() == 1 ? "0" + month : month); String property = LambdaUtils.getProperty(DeviceCreateIds::getDeviceId); QueryWrapper queryWrapper = new QueryWrapper() .select(String.format("max(%s) as %s", StringTools.humpToLine(property), property)) .eq(StringTools.humpToLine(LambdaUtils.getProperty(DeviceCreateIds::getIsCustom)), false); DeviceCreateIds deviceCreateIds = getOne(queryWrapper); JMap deviceCreateIdss = new JHashMap<>(save.getNum()); Long loginId = AuthorizeUtils.getLoginId(Long.class); for (int i = 0; i < save.getNum(); i++) { String tail = null; if (deviceCreateIds != null) { String substring = String.valueOf(deviceCreateIds.getDeviceId()).substring(0, 4); if (substring.equals(yearMonth)) { tail = String.valueOf(deviceCreateIds.getDeviceId() + (i + 1)).substring(4); } } if (tail == null) { tail = String.valueOf((i + 1)); int i0 = 6 - tail.length(); for (int i1 = 0; i1 < i0; i1++) { tail = 0 + tail; } } Long deviceId = Long.valueOf(yearMonth + tail); DeviceCreateIds deviceCreateIdsInfo = copy(DeviceCreateIds.class, save) .setDeviceId(deviceId) .setCreateUserId(loginId) .setCreateTime(LocalDateTime.now()); deviceCreateIdss.put(deviceId, deviceCreateIdsInfo); } //去重复 weight(deviceCreateIdss, save.getNum()); //添加 JList value = deviceCreateIdss.toList().value(); JList> partition = value.partition(20); ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, partition.size()); partition.forEach(createIds -> execute.execute(() -> saveBatch(createIds))); execute.end(); return R.ok(value); } @PostMapping("saveCustom") @ApiOperation("添加自定义机器号") @Lock("device-create-ids-save") public R saveCustom(@RequestBody @Validated DeviceCreateIdsDto.SaveCustom saveCustom) { DeviceCreateIds deviceCreateIds = getById(saveCustom.getDeviceId()); if (deviceCreateIds != null) { return R.fail("机器号已存在"); } DeviceCreateIds deviceCreateIdsInfo = copy(DeviceCreateIds.class, saveCustom) .setCreateUserId(AuthorizeUtils.getLoginId(Long.class)) .setIsCustom(true) .setCreateTime(LocalDateTime.now()); save(deviceCreateIdsInfo); return R.ok(); } @PostMapping("page") @ApiOperation("分页查询") public R> page(@RequestBody DeviceCreateIdsDto.Page page) { PageBean pageBean = page.getPage(); LambdaQueryWrapper lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceCreateIds.class) .ge(DeviceCreateIds::getCreateTime, page.getBeginCreateTime()) .le(DeviceCreateIds::getCreateTime, page.getEndCreateTime()) .ge(DeviceCreateIds::getBindTime, page.getBeginBindTime()) .le(DeviceCreateIds::getBindTime, page.getEndBindTime()) .build() .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceCreateIds::getCreateTime, DeviceCreateIds::getDeviceId); IPage iPage = page(toIPage(pageBean), lambdaQueryWrapper); PageBean voPageBean = toPageBean(PlusBeans.copy(DeviceCreateIdsDto.Vo.class, iPage)); List records = voPageBean.getRecords(); JList createUserIds = new JArrayList<>(records).getProperty(DeviceCreateIdsDto.Vo::getCreateUserId); //查询创建人 JMap sysWorkVoJMap; List sysWorkVos = sysWorkUserService.list(new ListDto().setId(createUserIds)).getData(); if (Emptys.check(sysWorkVos)) { sysWorkVoJMap = new JArrayList<>(sysWorkVos).toMap(SysWorkVo::getId).cover(); } else { sysWorkVoJMap = new JHashMap<>(); } //查询绑定商户 JMap mercsJMaps; JList mercIds = new JArrayList<>(records).filter().isNotNull(DeviceCreateIdsDto.Vo::getDeviceQrMercId).gt(DeviceCreateIdsDto.Vo::getDeviceQrMercId, 0).list().getProperty(DeviceCreateIdsDto.Vo::getDeviceQrMercId); if (Emptys.check(mercIds)) { List mercs = mercService.list(new MercDto.SelectList().setMercIds(mercIds)).getData(); mercsJMaps = new JArrayList<>(mercs).toMap(MercDto.Vo::getId).cover(); } else { mercsJMaps = new JHashMap<>(); } records.forEach(vo -> { if (Emptys.check(sysWorkVoJMap)) { if (Emptys.check(vo.getCreateUserId())) { SysWorkVo sysWorkVo = sysWorkVoJMap.get(vo.getCreateUserId()); if (sysWorkVo != null) { vo.setCreateUserName(sysWorkVo.getAccount()); } } } if (Emptys.check(mercsJMaps)) { if (Emptys.check(vo.getDeviceQrMercId())) { MercDto.Vo mercVo = mercsJMaps.get(vo.getDeviceQrMercId()); if (mercVo != null) { vo.setDeviceQrMercName(mercVo.getName()); } } } }); return R.ok(voPageBean); } @Override @ApiOperation("修改") public R update(DeviceCreateIdsDto.Update update) { DeviceCreateIds deviceCreateIds = copy(DeviceCreateIds.class, update); updateById(deviceCreateIds); return R.ok(); } @Override @ApiOperation("批量修改") public R updateBatch(DeviceCreateIdsDto.UpdateBatch updateBatch) { List deviceIds = updateBatch.getDeviceIds(); List deviceCreateIdss = new ArrayList<>(deviceIds.size()); deviceIds.forEach(deviceId -> { DeviceCreateIds deviceCreateIds = copy(DeviceCreateIds.class, updateBatch).setDeviceId(deviceId); deviceCreateIdss.add(deviceCreateIds); }); updateBatchById(deviceCreateIdss); return R.ok(); } @PostMapping("getQrCode") @ApiOperation("获取二维码") public R> getQrCode(@RequestBody @Validated DeviceQualityDto.Qrcode qrcode) { //默认二维码 String qrUrl = SysDictUtils.getValue(EnumDeviceQrCode.Code.CODE.getCode(), EnumDeviceQrCode.URL.getCode(), String.class); //查询商户特有二维码地址 DeviceInfo deviceInfo = deviceInfoService.getById(qrcode.getDeviceId()); if (Emptys.check(deviceInfo.getMercId())) { MercDeviceQrConfigDto.Vo mercDeviceQrConfig = mercDeviceQrConfigService.getQrUrl(new MercDeviceQrConfigDto.GetQrUrl().setMercId(deviceInfo.getMercId())).getData(); if (Emptys.check(mercDeviceQrConfig)) { qrUrl = mercDeviceQrConfig.getQrUrl() + "?deviceId="; } } //验证是否是双门柜 int deviceType = SysDictUtils.getValue(EnumDeviceType.Code.CODE.getCode(), EnumDeviceType.N_2.getCode(), Integer.class); String deviceId = qrcode.getDeviceId().toString(); JList deviceIds = new JArrayList() .set(qrUrl + deviceId); JList deviceIdInfos = new JArrayList() .set(deviceId); DeviceCreateIds deviceCreateIds = getById(qrcode.getDeviceId()); if (deviceCreateIds.getDeviceType() == deviceType) { deviceIds.clear(); deviceIdInfos.clear(); for (int i = 0; i < 2; i++) { deviceIds.add(String.format("%s%s&door=%d", qrUrl, deviceId, i)); deviceIdInfos.add(String.format("%s-%d", deviceId, i)); } } List base64s = QRCodeUtils.create(deviceIds, 400, 400, "back1.png", deviceIdInfos).base64(); return R.ok(base64s); } @PostMapping("exportQrCode") @ApiOperation("导出二维码") public void exportQrCode(@RequestBody @Validated DeviceCreateIdsDto.ExportQrCode exportQrCode) { String url = SysDictUtils.getValue(EnumDeviceQrCode.Code.CODE.getCode(), EnumDeviceQrCode.URL.getCode(), String.class); int deviceType = SysDictUtils.getValue(EnumDeviceType.Code.CODE.getCode(), EnumDeviceType.N_2.getCode(), Integer.class); LocalDateTime now = LocalDateTime.now(); JList deviceIds = new JArrayList<>(); List deviceIdInfos = new ArrayList<>(); List updateDeviceCreateIds = new ArrayList<>(); JList deviceCreateIdss = new JArrayList<>(listByIds(exportQrCode.getDeviceIds())); List deviceInfos = deviceInfoService.listByIds(exportQrCode.getDeviceIds()); JMap deviceInfoJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover(); //循环 deviceCreateIdss.forEach(deviceCreateIds -> { String qrUrl = url; //查询商户特有二维码地址 DeviceInfo deviceInfo = deviceInfoJMaps.get(deviceCreateIds.getDeviceId()); if (Emptys.check(deviceInfo.getMercId())) { MercDeviceQrConfigDto.Vo mercDeviceQrConfig = mercDeviceQrConfigService.getQrUrl(new MercDeviceQrConfigDto.GetQrUrl().setMercId(deviceInfo.getMercId())).getData(); if (Emptys.check(mercDeviceQrConfig)) { qrUrl = mercDeviceQrConfig.getQrUrl() + "?deviceId="; } } //验证是否是双门柜 if (deviceCreateIds.getDeviceType() == deviceType) { for (int i = 0; i < 2; i++) { deviceIds.add(String.format("%s%s&door=%d", qrUrl, deviceCreateIds.getDeviceId(), i)); deviceIdInfos.add(String.format("%s-%d", deviceCreateIds.getDeviceId(), i)); } } else { deviceIds.add(qrUrl + deviceCreateIds.getDeviceId()); deviceIdInfos.add(String.valueOf(deviceCreateIds.getDeviceId())); } updateDeviceCreateIds.add(deviceCreateIds.setLastExportQrCodeTime(now)); }); updateBatchById(updateDeviceCreateIds); QRCodeUtils.create(deviceIds, 400, 400, "back1.png", deviceIdInfos).download(deviceIdInfos); } @SneakyThrows @ApiOperation("下载自定义设备id模板") @PostMapping("downloadIdTemplet") public void downloadIdTemplet(HttpServletResponse response) { InputStream inputStream = IoUtils.inputStream("id_templet.xlsx").get(); response.setHeader("Content-Disposition", "attachment; filename=" + "id_templet.xlsx"); response.setContentType("application/xlsx"); byte[] buffer = new byte[1024]; int bytesRead; OutputStream outputStream = response.getOutputStream(); while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } inputStream.close(); outputStream.close(); } @ApiOperation("批量添加自定义机器号") @PostMapping("uploadSaveCustom") public R uploadSaveCustom(@RequestParam("file") MultipartFile file) { ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, 1) .execute(() -> { try { EasyExcel.read(file.getInputStream(), UploadSaveCustom.class, new UploadSaveCustomListener(AuthorizeUtils.getLoginId(Long.class), this)).sheet().doRead(); } catch (IOException e) { log.error("", e); } }); return R.ok(); } private void weight(JMap deviceCreateIdss, int num) { List list = list(new LambdaQueryWrapper().in(DeviceCreateIds::getDeviceId, deviceCreateIdss.toList().key())); if (Emptys.check(list)) { list.forEach(deviceCreateIdsInfo -> { //添加 DeviceCreateIds deviceCreateIdsOld = deviceCreateIdss.get(deviceCreateIdsInfo.getDeviceId()); Long deviceId = deviceCreateIdsOld.getDeviceId() + num; deviceCreateIdss.put(deviceId, copy(DeviceCreateIds.class, deviceCreateIdsOld).setDeviceId(deviceId)); //删除 deviceCreateIdss.remove(deviceCreateIdsInfo.getDeviceId()); }); weight(deviceCreateIdss, num); } } @Slf4j @RequiredArgsConstructor public static class UploadSaveCustomListener implements ReadListener { private final Long loginId; private final DeviceCreateIdsServiceImpl deviceCreateIdsService; private JMap deviceIds = new JHashMap<>(); /** * 这个每一条数据解析都会来调用 * * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(UploadSaveCustom data, AnalysisContext context) { String deviceType = data.getDeviceType(); if (deviceType == null) { return; } Integer deviceTypeValue = deviceType.equals("动态视觉柜(单门)") ? 1 : deviceType.equals("动态视觉柜(双门)") ? 2 : deviceType.equals("重力柜(单门)") ? 3 : deviceType.equals("重力柜(双门)") ? 4 : deviceType.equals("支付宝视动态觉柜") ? 5 : null; if (deviceTypeValue == null) { return; } if (!Emptys.check(data.getDevicePc())) { return; } data.setDeviceTypeValue(deviceTypeValue); deviceIds.put(data.getDeviceId(), data); } /** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { List list = deviceCreateIdsService.list(new LambdaQueryWrapper().in(DeviceCreateIds::getDeviceId, deviceIds.toList().key())); if (Emptys.check(list)) { list.forEach(deviceCreateIds -> { deviceIds.remove(deviceCreateIds.getDeviceId()); log.info("重复的设备号:{}", deviceCreateIds.getDeviceId()); }); } if (Emptys.check(deviceIds)) { LocalDateTime now = LocalDateTime.now(); List saves = new ArrayList<>(deviceIds.size()); deviceIds.forEach((deviceId, uploadSaveCustom) -> { DeviceCreateIds deviceCreateIdsInfo = new DeviceCreateIds() .setDeviceId(deviceId) .setDeviceType(uploadSaveCustom.getDeviceTypeValue()) .setCreatePc(uploadSaveCustom.getDevicePc()) .setCreateUserId(loginId) .setIsCustom(true) .setCreateTime(now); saves.add(deviceCreateIdsInfo); }); deviceCreateIdsService.saveBatch(saves); log.info("批量添加自定义机器号完成,共{}条", saves.size()); } } } @Data public static class UploadSaveCustom { /** * 设备id */ private Long deviceId; /** * 设备类型 */ private String deviceType; /** * 批次号 */ private String devicePc; /** * 设备类型值 */ private Integer deviceTypeValue; } }