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.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
@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;
}
}