/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.springblade.modules.discuss.service.impl; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; import org.springblade.common.constant.CommonConstant; import org.springblade.common.utils.SpringUtils; import org.springblade.core.redis.cache.BladeRedis; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.SpringUtil; import org.springblade.modules.discuss.entity.PublicDiscussEntity; import org.springblade.modules.discuss.entity.TopicsEntity; import org.springblade.modules.discuss.entity.UserTopicsEntity; import org.springblade.modules.discuss.excel.UserTopicsExcel; import org.springblade.modules.discuss.excel.holdExcel; import org.springblade.modules.discuss.mapper.UserTopicsMapper; import org.springblade.modules.discuss.service.IPublicDiscussService; import org.springblade.modules.discuss.service.ITopicsService; import org.springblade.modules.discuss.service.IUserTopicsService; import org.springblade.modules.discuss.vo.TopicsVO; import org.springblade.modules.discuss.vo.UserTopicsVO; import org.springblade.modules.district.entity.DistrictEntity; import org.springblade.modules.district.service.IDistrictService; import org.springblade.modules.house.entity.HouseholdEntity; import org.springblade.modules.house.excel.HouseHoldExcel; import org.springblade.modules.house.service.IHouseholdService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * 用户议题报表 服务实现类 * * @author BladeX * @since 2023-11-22 */ @Service public class UserTopicsServiceImpl extends ServiceImpl implements IUserTopicsService { @Resource private ITopicsService topicsService; public static final String SMS_VALIDATE_PHONE = "sms:validate:code:"; @Autowired private BladeRedis redisTemplate; @Override public IPage selectUserTopicsPage(IPage page, UserTopicsVO userTopics) { if (StringUtils.isNotBlank(userTopics.getDistrictId())) { List longs = Arrays.asList(userTopics.getDistrictId().split(",")); IDistrictService bean = SpringUtils.getBean(IDistrictService.class); List list = bean.list(Wrappers.lambdaQuery().in(DistrictEntity::getId, longs)); List collect = list.stream().map(item -> item.getAoiCode() ).collect(Collectors.toList()); if (collect != null) { userTopics.setAoiCodeList(collect); } } IHouseholdService householdService = SpringUtils.getBean(IHouseholdService.class); HouseholdEntity householdEntity = householdService.getOne(Wrappers.lambdaQuery() .eq(HouseholdEntity::getHouseCode, userTopics.getHouseCode()) .eq(HouseholdEntity::getAssociatedUserId, AuthUtil.getUserId()) .eq(HouseholdEntity::getIsDeleted, 0) .last("limit 1")); if (householdEntity != null) { userTopics.setHouseholdId(householdEntity.getId()); } List userTopicsVOS = baseMapper.selectUserTopicsPage(page, userTopics); return page.setRecords(userTopicsVOS); } @Override @Transactional(rollbackFor = Exception.class) public String batchSave(TopicsVO topics) throws Exception { List topicsList = topics.getChildren(); if (topicsList == null || topicsList.isEmpty()) { return "你未选选项内容"; } IPublicDiscussService bean = SpringUtil.getBean(IPublicDiscussService.class); PublicDiscussEntity discussEntity = bean.getOne(Wrappers.lambdaQuery().eq(PublicDiscussEntity::getArticleId, topicsList.get(0).getArticleId())); // 判断是否在开始和结束时间内 if (discussEntity.getStartTime().getTime() > System.currentTimeMillis() || discussEntity.getEndTime().getTime() < System.currentTimeMillis()) { return "目前不在投票时间内,投票时间:"+ DateUtil.formatDateTime(discussEntity.getStartTime()) +" 至 "+DateUtil.formatDateTime(discussEntity.getEndTime()); } if (StringUtils.isNotBlank(topics.getPhone())) { if (StringUtils.isBlank(topics.getCode())) { return "验证码不能为空!"; } Object validateCode = redisTemplate.get(SMS_VALIDATE_PHONE + topics.getPhone()); if (validateCode == null) { return "验证码已过期"; } if (!validateCode.toString().equals(topics.getCode())) { return "验证码错误"; } //删除验证码 redisTemplate.del(SMS_VALIDATE_PHONE + topics.getPhone()); } // 判断是否一户一票 还是一人一票 IHouseholdService householdService = SpringUtils.getBean(IHouseholdService.class); HouseholdEntity householdEntity = householdService.getOne(Wrappers.lambdaQuery() .eq(HouseholdEntity::getHouseCode, topicsList.get(0).getHouseCode()) .eq(HouseholdEntity::getAssociatedUserId, AuthUtil.getUserId()) .eq(HouseholdEntity::getIsDeleted, 0) .last("limit 1")); // 一户一票 if (discussEntity.getVoteRestrictions().equals(CommonConstant.NUMBER_ONE)) { long count = count(Wrappers.lambdaQuery() .eq(UserTopicsEntity::getHouseCode, topicsList.get(0).getHouseCode()) .eq(UserTopicsEntity::getArticleId, topicsList.get(0).getArticleId())); if (count > 0) { return "您的房屋已投票,不能重复投票!"; } } else { // long count = count(Wrappers.lambdaQuery() .eq(UserTopicsEntity::getHouseholdId, householdEntity.getId()) .eq(UserTopicsEntity::getArticleId, topicsList.get(0).getArticleId())); if (count > 0) { return "您已投票,不能重复投票!"; } } for (TopicsVO topic : topicsList) { if (topic.getMandatoryFlag().equals(2)) { if (topic.getOptionNumberMin() > 1) { JSONArray objects1 = JSON.parseArray(topic.getSelected()); if (objects1.size() < topic.getOptionNumberMin()) { return topic.getDiscussContent() + ":议题最少需要选择" + topic.getOptionNumberMin() + "项"; } } if (topic.getOptionNumber() > 1) { JSONArray objects1 = JSON.parseArray(topic.getSelected()); if (objects1.size() > topic.getOptionNumber()) { return topic.getDiscussContent() + ":议题最多需要选择" + topic.getOptionNumber() + "项"; } } } } Boolean userTopics = getaBoolean(topicsList, householdEntity); if (userTopics) return "200"; return "操作失败!"; } @Nullable private Boolean getaBoolean(List topics, HouseholdEntity householdEntity) { List objects = new ArrayList<>(); Boolean result = false; for (TopicsVO topic : topics) { UserTopicsEntity userTopicsEntity = new UserTopicsEntity(); userTopicsEntity.setHouseholdId(householdEntity.getId()); userTopicsEntity.setSelected(topic.getSelected()); userTopicsEntity.setTopicsId(topic.getId()); userTopicsEntity.setPublicDiscussId(topic.getPublicDiscussId()); objects.add(userTopicsEntity); // 单选 if (topic.getOptionRange().equals(0)) { if (StringUtils.isBlank(topic.getSelected())) { break; } UserTopicsEntity userTopics = new UserTopicsEntity(); userTopics.setSelected(topic.getSelected()); userTopics.setHouseholdId(householdEntity.getId()); userTopics.setPublicDiscussId(topic.getPublicDiscussId()); userTopics.setTopicsId(Integer.valueOf(topic.getSelected())); userTopics.setArticleId(topic.getArticleId()); userTopics.setHouseCode(topic.getHouseCode()); userTopics.setSignaturePath(topic.getSignaturePath()); UpdateWrapper objectUpdateWrapper = new UpdateWrapper<>(); objectUpdateWrapper.setSql("number = number + 1"); objectUpdateWrapper.eq("id", topic.getSelected()); topicsService.update(null, objectUpdateWrapper); result = save(userTopics); } else { // 多选 if (StringUtils.isBlank(topic.getSelected())) { break; } JSONArray objects1 = JSON.parseArray(topic.getSelected()); List objectsTwo = new ArrayList<>(); for (Object o : objects1) { UserTopicsEntity userTopics = new UserTopicsEntity(); userTopics.setSelected(topic.getSelected()); userTopics.setHouseholdId(householdEntity.getId()); userTopics.setPublicDiscussId(topic.getPublicDiscussId()); userTopics.setArticleId(topic.getArticleId()); userTopics.setHouseCode(topic.getHouseCode()); userTopics.setTopicsId((Integer) o); userTopics.setSignaturePath(topic.getSignaturePath()); objectsTwo.add(userTopics); UpdateWrapper objectUpdateWrapper = new UpdateWrapper<>(); objectUpdateWrapper.setSql("number = number + 1"); objectUpdateWrapper.eq("id", o); topicsService.update(null, objectUpdateWrapper); } result = saveBatch(objectsTwo); } } return result; } @Override public Integer getCount(Integer id) { List list = list(Wrappers.lambdaQuery() .eq(UserTopicsEntity::getPublicDiscussId, id) .groupBy(UserTopicsEntity::getHouseholdId)); return list.size(); } @Override public List exportUser(UserTopicsVO userTopics) { if (StringUtils.isNotBlank(userTopics.getDistrictId())) { List longs = Arrays.asList(userTopics.getDistrictId().split(",")); IDistrictService bean = SpringUtils.getBean(IDistrictService.class); List list = bean.list(Wrappers.lambdaQuery().in(DistrictEntity::getId, longs)); List collect = list.stream().map(item -> item.getAoiCode() ).collect(Collectors.toList()); if (collect != null) { userTopics.setAoiCodeList(collect); } } List userTopicsExcels = baseMapper.exportUser(userTopics); return userTopicsExcels; } @Override public Boolean saveUserTopicsEntity(UserTopicsEntity userTopics) { IHouseholdService householdService = SpringUtils.getBean(IHouseholdService.class); HouseholdEntity householdEntity = householdService.getOne(Wrappers.lambdaQuery() .eq(HouseholdEntity::getHouseCode, userTopics.getHouseCode()) .eq(HouseholdEntity::getAssociatedUserId, AuthUtil.getUserId()) .eq(HouseholdEntity::getIsDeleted, 0) .last("limit 1")); if (householdEntity != null) { userTopics.setHouseholdId(householdEntity.getId()); } return save(userTopics); } /** * 处理Excel文件的生成,将用户主题数据写入Excel并输出到流中。 * * @param out 输出流,用于保存生成的Excel文件。 * @param userTopics 用户主题数据,包含提案和投票记录信息。 */ @Override public void handleExcel(OutputStream out, UserTopicsVO userTopics) { // 初始化Excel写入器 ExcelWriter excelWriter = EasyExcel.write(out) .build(); // 设置内容自动换行的样式 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); contentWriteCellStyle.setWrapped(true); // 处理并写入提案数据 List proposal = getProposal(userTopics); ExcelWriterSheetBuilder userExcelSheet = new ExcelWriterSheetBuilder(); userExcelSheet.registerWriteHandler(new HorizontalCellStyleStrategy(null, contentWriteCellStyle)); userExcelSheet.sheetName("小区投票人员"); userExcelSheet.sheetNo(0); userExcelSheet.head(holdExcel.class); excelWriter.write(proposal, userExcelSheet.build()); // 处理并写入投票记录数据 List publicopinion = getPublicopinion(userTopics); ExcelWriterSheetBuilder classExcelSheet = new ExcelWriterSheetBuilder(); classExcelSheet.registerWriteHandler(new HorizontalCellStyleStrategy(null, contentWriteCellStyle)); classExcelSheet.sheetName("投票记录"); classExcelSheet.sheetNo(1); classExcelSheet.head(UserTopicsExcel.class); excelWriter.write(publicopinion, classExcelSheet.build()); // 完成Excel写入并释放资源 excelWriter.finish(); } /** * 获取首页的房屋记录 * * @param userTopics 包含用户话题信息的对象,其中可能含有区域ID等关键信息 * @return 返回一个包含房屋记录信息的列表 */ private List getProposal(UserTopicsVO userTopics) { List resultList = new ArrayList<>(); try { // 检查区域ID字符串是否有效 List strings = validateAndParseDistrictId(userTopics.getDistrictId()); // 获取区域服务和话题服务的实例 IDistrictService districtService = SpringUtils.getBean(IDistrictService.class); ITopicsService topicsService = SpringUtils.getBean(ITopicsService.class); // 处理区域ID并查询对应的区域实体列表 List aoiCodeList = processDistrictIds(districtService, strings); // 设置AOI代码列表到用户话题对象中 userTopics.setAoiCodeList(aoiCodeList); // 查询并处理房屋列表信息 List householdList = processHouseholdList(topicsService, userTopics); resultList.addAll(householdList); } catch (Exception e) { // 适当的异常处理逻辑 // 例如:记录日志、返回错误信息等 e.printStackTrace(); } return resultList; } /** * 验证并解析区域ID字符串。 * * @param districtIdStr 区域ID的字符串表示。不能为空或空白字符串。 * @return 返回一个JSONArray对象,包含解析后的区域ID。 * @throws IllegalArgumentException 如果区域ID字符串为空或空白字符串,抛出此异常。 */ private List validateAndParseDistrictId(String districtIdStr) throws IllegalArgumentException { // 验证区域ID字符串是否为空 if (StringUtils.isBlank(districtIdStr)) { throw new IllegalArgumentException("区域ID不能为空"); } // 解析区域ID字符串为JSONArray对象 return Arrays.asList(districtIdStr.split(",")); } private List processDistrictIds(IDistrictService districtService, List districtIds) { List collect1 = districtIds.stream().map(item -> (String) item).collect(Collectors.toList()); List list3 = districtService.list(Wrappers.lambdaQuery().in(DistrictEntity::getId, collect1)); return list3.stream().map(item -> item.getAoiCode()).collect(Collectors.toList()); } private List processHouseholdList(ITopicsService topicsService, UserTopicsVO userTopics) { List householdList = baseMapper.getHouseholdList(userTopics); householdList.forEach(item -> processItem(topicsService, item)); return householdList; } private void processItem(ITopicsService topicsService, holdExcel item) { if (StringUtils.isBlank(item.getOptionContent())) { item.setVoteFlag("否"); } else { List longs = Func.toLongList(item.getOptionContent()); for (Long aLong : longs) { TopicsEntity topics = topicsService.getById(aLong); setManagementRegulationsOrRulesOfProcedure(item, topics); } item.setVoteFlag("是"); } } private void setManagementRegulationsOrRulesOfProcedure(holdExcel item, TopicsEntity topics) { if (StringUtils.isNotBlank(topics.getDiscussContent())) { if (topics.getDiscussContent().equals("管理公约")) { item.setManagementRegulations(topics.getOptionContent()); } else if (topics.getDiscussContent().equals("议事规则")) { item.setRulesOfProcedure(topics.getOptionContent()); } } } /** * 获取公开意见信息 * * @param userTopics 用户话题VO对象,封装了用户话题的查询条件 * @return 返回用户话题的Excel格式列表,包含所有符合条件的意见信息 */ private List getPublicopinion(UserTopicsVO userTopics) { // 初始化返回列表 List list = new ArrayList<>(); // 通过基础mapper查询结果,并将结果添加到列表中 List userTopicsExcels = baseMapper.getresultTwo(userTopics); list.addAll(userTopicsExcels); return list; } }