Commit 8e273c31a0340e29fbce77e8384b53e0bec40350

Authored by 房远帅
1 parent 76ca9d26

楚江ERP:客户资信-导出+审核过程中修改资信

Too many changes to show.

To preserve performance only 8 of 10 files are displayed.

... ... @@ -34,6 +34,7 @@
34 34 <maven.compiler.target>8</maven.compiler.target>
35 35 <xingyun.version>1.0.0-SNAPSHOT</xingyun.version>
36 36 <jugg.version>4.0.6</jugg.version>
  37 + <freemarker.version>2.3.32</freemarker.version>
37 38 </properties>
38 39
39 40 <dependencyManagement>
... ...
... ... @@ -27,5 +27,25 @@
27 27 <artifactId>pinyin4j</artifactId>
28 28 <version>2.5.1</version>
29 29 </dependency>
  30 + <!-- FreeMarker -->
  31 + <dependency>
  32 + <groupId>org.freemarker</groupId>
  33 + <artifactId>freemarker</artifactId>
  34 + <version>${freemarker.version}</version>
  35 + </dependency>
  36 + <!-- commons-io (可选,用于文件操作) -->
  37 + <dependency>
  38 + <groupId>commons-io</groupId>
  39 + <artifactId>commons-io</artifactId>
  40 + <version>2.11.0</version>
  41 + </dependency>
  42 +
  43 + <!-- Lombok(可选) -->
  44 + <dependency>
  45 + <groupId>org.projectlombok</groupId>
  46 + <artifactId>lombok</artifactId>
  47 + <version>1.18.30</version>
  48 + <scope>provided</scope>
  49 + </dependency>
30 50 </dependencies>
31 51 </project>
... ...
1 1 package com.lframework.xingyun.sc.bo.customer.credit;
2 2
3 3 import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.annotation.JsonIgnore;
4 5 import com.lframework.starter.web.core.dto.BaseDto;
5 6 import com.lframework.xingyun.sc.entity.CorePersonnel;
6 7 import com.lframework.xingyun.sc.entity.CustomerCredit;
... ... @@ -407,6 +408,13 @@ public class GetCustomerCreditBo extends BaseBo<CustomerCredit> implements BaseD
407 408 private List<CorePersonnel> corePersonnelList;
408 409
409 410 /**
  411 + * 核心人员
  412 + */
  413 + @ApiModelProperty("核心人员")
  414 + @JsonIgnore
  415 + private List<GetCorePersonnelBo> getCorePersonnelBoList;
  416 +
  417 + /**
410 418 * 创建时间
411 419 */
412 420 @ApiModelProperty("创建时间")
... ...
1 1 package com.lframework.xingyun.sc.controller.customer;
2 2
3 3 import com.lframework.starter.common.utils.StringUtil;
4   -import com.lframework.starter.mq.core.utils.ExportTaskUtil;
5 4 import com.lframework.starter.web.core.annotations.security.HasPermission;
6 5 import com.lframework.starter.web.core.controller.DefaultBaseController;
7 6 import com.lframework.starter.web.core.utils.ExcelUtil;
... ... @@ -16,9 +15,8 @@ import com.lframework.starter.web.core.utils.PageResultUtil;
16 15 import com.lframework.starter.web.core.components.resp.PageResult;
17 16 import com.lframework.starter.web.core.components.resp.InvokeResult;
18 17 import javax.annotation.Resource;
  18 +import javax.servlet.http.HttpServletResponse;
19 19 import javax.validation.constraints.NotBlank;
20   -import com.lframework.xingyun.sc.enums.ExportType;
21   -import com.lframework.xingyun.sc.excel.customerCredit.CustomerCreditExportTaskWorker;
22 20 import com.lframework.xingyun.sc.excel.customerCredit.CustomerCreditImportListener;
23 21 import com.lframework.xingyun.sc.excel.customerCredit.CustomerCreditImportModel;
24 22 import com.lframework.xingyun.sc.service.customer.CorePersonnelService;
... ... @@ -27,6 +25,7 @@ import com.lframework.xingyun.sc.vo.customer.credit.CreateCustomerCreditVo;
27 25 import com.lframework.xingyun.sc.vo.customer.credit.QueryCorePersonnelVo;
28 26 import com.lframework.xingyun.sc.vo.customer.credit.QueryCustomerCreditVo;
29 27 import com.lframework.xingyun.sc.vo.customer.credit.UpdateCustomerCreditVo;
  28 +import freemarker.template.TemplateException;
30 29 import io.swagger.annotations.ApiImplicitParam;
31 30 import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
32 31 import com.lframework.starter.common.exceptions.impl.DefaultClientException;
... ... @@ -40,6 +39,11 @@ import org.springframework.web.multipart.MultipartFile;
40 39
41 40 import javax.validation.Valid;
42 41 import javax.validation.constraints.NotNull;
  42 +import java.io.IOException;
  43 +import java.net.URLEncoder;
  44 +import java.nio.file.Files;
  45 +import java.nio.file.Path;
  46 +import java.nio.file.Paths;
43 47 import java.util.List;
44 48 import java.util.stream.Collectors;
45 49
... ... @@ -232,10 +236,24 @@ public class CustomerCreditController extends DefaultBaseController {
232 236 @ApiOperation("导出")
233 237 @HasPermission({"customer-dev-manage:customer-dev-plan:export"})
234 238 @PostMapping("/export")
235   - public InvokeResult<Void> export(@Valid QueryCustomerCreditVo vo) {
236   - vo.setExportType(ExportType.CUSTOMER_CREDIT.getCode());
237   - ExportTaskUtil.exportTask("客户资信信息", CustomerCreditExportTaskWorker.class, vo);
238   - return InvokeResultBuilder.success();
  239 + public void export(@NotBlank(message = "ID不能为空") String id, HttpServletResponse response) {
  240 + try {
  241 + String fileName = customerCreditService.export(id);
  242 + Path filePath = Paths.get("/web/service/erp/xingyun/export/templates", fileName);
  243 +
  244 + if (Files.exists(filePath)) {
  245 + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
  246 + response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
  247 +
  248 + Files.copy(filePath, response.getOutputStream());
  249 + } else {
  250 + response.sendError(404, "文件未找到");
  251 + }
  252 + } catch (IOException e) {
  253 + e.printStackTrace();
  254 + } catch (TemplateException e) {
  255 + e.printStackTrace();
  256 + }
239 257 }
240 258
241 259
... ...
... ... @@ -118,4 +118,76 @@ public class CorePersonnel extends BaseEntity implements BaseDto {
118 118 @TableField(fill = FieldFill.INSERT_UPDATE)
119 119 private LocalDateTime updateTime;
120 120
  121 +
  122 + public String getName() {
  123 + return name;
  124 + }
  125 +
  126 + public void setName(String name) {
  127 + this.name = name;
  128 + }
  129 +
  130 + public String getSex() {
  131 + return sex;
  132 + }
  133 +
  134 + public void setSex(String sex) {
  135 + this.sex = sex;
  136 + }
  137 +
  138 + public String getNativePlace() {
  139 + return nativePlace;
  140 + }
  141 +
  142 + public void setNativePlace(String nativePlace) {
  143 + this.nativePlace = nativePlace;
  144 + }
  145 +
  146 + public String getAge() {
  147 + return age;
  148 + }
  149 +
  150 + public void setAge(String age) {
  151 + this.age = age;
  152 + }
  153 +
  154 + public String getPosition() {
  155 + return position;
  156 + }
  157 +
  158 + public void setPosition(String position) {
  159 + this.position = position;
  160 + }
  161 +
  162 + public String getMobile() {
  163 + return mobile;
  164 + }
  165 +
  166 + public void setMobile(String mobile) {
  167 + this.mobile = mobile;
  168 + }
  169 +
  170 + public String getPhone() {
  171 + return phone;
  172 + }
  173 +
  174 + public void setPhone(String phone) {
  175 + this.phone = phone;
  176 + }
  177 +
  178 + public String getEmail() {
  179 + return email;
  180 + }
  181 +
  182 + public void setEmail(String email) {
  183 + this.email = email;
  184 + }
  185 +
  186 + public String getAddress() {
  187 + return address;
  188 + }
  189 +
  190 + public void setAddress(String address) {
  191 + this.address = address;
  192 + }
121 193 }
... ...
... ... @@ -16,6 +16,7 @@ import com.lframework.starter.web.inner.entity.SysUser;
16 16 import com.lframework.starter.web.inner.service.system.SysDeptService;
17 17 import com.lframework.starter.web.inner.service.system.SysUserService;
18 18 import com.lframework.starter.web.inner.vo.system.user.QuerySysUserVo;
  19 +import com.lframework.xingyun.sc.bo.customer.credit.GetCorePersonnelBo;
19 20 import com.lframework.xingyun.sc.bo.customer.credit.GetCustomerCreditBo;
20 21 import com.lframework.xingyun.sc.entity.CorePersonnel;
21 22 import com.lframework.xingyun.sc.entity.CustomerCredit;
... ... @@ -47,12 +48,15 @@ import org.springframework.cache.annotation.Cacheable;
47 48 import org.springframework.stereotype.Service;
48 49 import org.springframework.transaction.annotation.Transactional;
49 50 import net.sourceforge.pinyin4j.PinyinHelper;
50   -
51 51 import javax.annotation.Resource;
  52 +import java.lang.reflect.InvocationTargetException;
  53 +import java.lang.reflect.Method;
  54 +import java.lang.reflect.Modifier;
52 55 import java.nio.charset.StandardCharsets;
53 56 import java.nio.file.Files;
54 57 import java.nio.file.Path;
55 58 import java.nio.file.Paths;
  59 +import java.time.format.DateTimeFormatter;
56 60 import java.util.*;
57 61 import java.util.stream.Collectors;
58 62 import java.util.stream.IntStream;
... ... @@ -877,6 +881,25 @@ public class CustomerCreditServiceImpl extends BaseMpServiceImpl<CustomerCreditM
877 881 flowInstanceWrapperService.startInstance(BPM_FLAG, data.getId(), BPM_FLAG, vo);
878 882 }
879 883
  884 + @OpLog(type = OtherOpLogType.class, name = "修改客户资信,ID:{}", params = {"#id"})
  885 + @Transactional(rollbackFor = Exception.class)
  886 + @Override
  887 + public void updateByMap(Map<String, Object> map) {
  888 + // 创建 ObjectMapper 实例
  889 + ObjectMapper objectMapper = new ObjectMapper();
  890 + try {
  891 + // 方法1:先将 Map 序列化为 JSON 字符串,再反序列化为目标对象
  892 + String json = objectMapper.writeValueAsString(map);
  893 + UpdateCustomerCreditVo updateCustomerCreditVo = objectMapper.readValue(json, UpdateCustomerCreditVo.class);
  894 + // 使用转换后的对象
  895 + System.out.println(updateCustomerCreditVo);
  896 + updateNoFlowInstance(updateCustomerCreditVo);
  897 +
  898 + } catch (JsonProcessingException e) {
  899 + e.printStackTrace();
  900 + }
  901 + }
  902 +
880 903 @OpLog(type = OtherOpLogType.class, name = "修改客户资信表不走审核,ID:{}", params = {"#id"})
881 904 @Transactional(rollbackFor = Exception.class)
882 905 @Override
... ... @@ -1149,6 +1172,172 @@ public class CustomerCreditServiceImpl extends BaseMpServiceImpl<CustomerCreditM
1149 1172 throw new IllegalArgumentException("人员不存在");
1150 1173 }
1151 1174 }
  1175 +
  1176 + /**
  1177 + * 导出
  1178 + */
  1179 + @Override
  1180 + public String export(String id) throws IOException, TemplateException {
  1181 + // 1. 创建 FreeMarker 配置
  1182 + Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
  1183 +
  1184 + // 2.从 classpath 加载 templates 目录(推荐)
  1185 + cfg.setClassLoaderForTemplateLoading(
  1186 + Thread.currentThread().getContextClassLoader(),
  1187 + "templates" // 对应 src/main/resources/templates/
  1188 + );
  1189 +
  1190 + // 3. 设置编码
  1191 + cfg.setDefaultEncoding("UTF-8");
  1192 +
  1193 + // 4. 设置异常处理器
  1194 + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
  1195 +
  1196 + // 5.加载模板(会自动从 classpath:/templates/CustomerCredit.xml 加载)
  1197 + Template template = cfg.getTemplate("CustomerCredit.xml");
  1198 +
  1199 + // 3. 构建数据模型
  1200 +// Map<String, Object> model = new HashMap<>();
  1201 + CustomerCredit credit = getBaseMapper().findById(id);
  1202 + // 处理关联数据
  1203 + GetCustomerCreditBo data = new GetCustomerCreditBo(credit);
  1204 + //获取核心人员信息
  1205 + QueryCorePersonnelVo vo = new QueryCorePersonnelVo();
  1206 + vo.setCreditId(credit.getId());
  1207 + List<CorePersonnel> corePersonnel = corePersonnelService.query(vo);
  1208 + //调查人
  1209 + if (StringUtil.isNotEmpty(credit.getInvestigator())) {
  1210 + SysUser sysUser = sysUserService.findById(credit.getInvestigator());
  1211 + if (sysUser != null) {
  1212 + data.setInvestigatorName(sysUser.getName());
  1213 + }
  1214 + }
  1215 + //主管审核
  1216 + if (StringUtil.isNotEmpty(credit.getSupervisorReview())) {
  1217 + SysUser sysUser = sysUserService.findById(credit.getSupervisorReview());
  1218 + if (sysUser != null) {
  1219 + data.setSupervisorReviewName(sysUser.getName());
  1220 + }
  1221 + }
  1222 +// ObjectMapper mapper = new ObjectMapper();
  1223 +// Map<String, Object> dataModel = mapper.convertValue(data, new TypeReference<Map<String, Object>>() {});
  1224 + Map<String, Object> dataModel = new HashMap<>();
  1225 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  1226 + if (data.getRegisterDate() != null) {
  1227 + String registerDateStr = data.getRegisterDate().format(formatter);
  1228 + dataModel.put("registerDate", registerDateStr);
  1229 + }
  1230 + if (data.getRegistrationTime() != null) {
  1231 + String registrationTimeStr = data.getRegistrationTime().format(formatter);
  1232 + dataModel.put("registrationTime", registrationTimeStr);
  1233 + }
  1234 + if (StringUtil.isNotEmpty(data.getEnterpriseType())) {
  1235 + String enterpriseType;
  1236 + if ("DISTRIBUTOR".equals(data.getEnterpriseType())) {
  1237 + enterpriseType = "经销商";
  1238 + } else {
  1239 + enterpriseType = "终端";
  1240 + }
  1241 + dataModel.put("enterpriseType", enterpriseType);
  1242 + }
  1243 + if (CollectionUtils.isNotEmpty(corePersonnel)) {
  1244 + List<GetCorePersonnelBo> getCorePersonnelBoList = new ArrayList<>();
  1245 + for (CorePersonnel corePersonnel1 : corePersonnel) {
  1246 + // 关键:过滤 null 元素
  1247 + if (corePersonnel1 == null) {
  1248 + continue; // 跳过 null 值
  1249 + }
  1250 + GetCorePersonnelBo corePersonnelBo = new GetCorePersonnelBo();
  1251 + corePersonnelBo.setName(corePersonnel1.getName());
  1252 + corePersonnelBo.setSex(corePersonnel1.getSex());
  1253 + corePersonnelBo.setNativePlace(corePersonnel1.getNativePlace());
  1254 + corePersonnelBo.setAge(corePersonnel1.getAge());
  1255 + corePersonnelBo.setPosition(corePersonnel1.getPosition());
  1256 + corePersonnelBo.setMobile(corePersonnel1.getMobile());
  1257 + corePersonnelBo.setPhone(corePersonnel1.getPhone());
  1258 + corePersonnelBo.setEmail(corePersonnel1.getEmail());
  1259 + corePersonnelBo.setAddress(corePersonnel1.getAddress());
  1260 + getCorePersonnelBoList.add(corePersonnelBo);
  1261 + }
  1262 + GetCorePersonnelBo corePersonnelBo = getCorePersonnelBoList.get(0);
  1263 + Method getNameMethod = null;
  1264 + try {
  1265 + getNameMethod = corePersonnelBo.getClass().getMethod("getName");
  1266 + System.out.println("✅ getName() 方法存在,修饰符: " + Modifier.toString(getNameMethod.getModifiers()));
  1267 + System.out.println("✅ getName() 返回值: " + getNameMethod.invoke(corePersonnelBo));
  1268 + } catch (NoSuchMethodException e) {
  1269 + e.printStackTrace();
  1270 + } catch (IllegalAccessException e) {
  1271 + e.printStackTrace();
  1272 + } catch (InvocationTargetException e) {
  1273 + e.printStackTrace();
  1274 + }
  1275 + dataModel.put("getCorePersonnelBoList", getCorePersonnelBoList);
  1276 + System.out.println("Test getName: " + getCorePersonnelBoList.get(0).getName());
  1277 + }
  1278 + System.out.println("2===" + dataModel.get("getCorePersonnelBoList"));
  1279 +
  1280 + // 4. 处理模板 → 生成XML字符串
  1281 + StringWriter stringWriter = new StringWriter();
  1282 + template.process(dataModel, stringWriter);
  1283 + String processedXml = stringWriter.toString();
  1284 + // 1. 定义服务器导出目录
  1285 + String exportDir = "/web/service/erp/xingyun/export/templates";
  1286 + Path dirPath = Paths.get(exportDir);
  1287 + // 2. 创建目录(如果不存在)
  1288 + if (!Files.exists(dirPath)) {
  1289 + Files.createDirectories(dirPath);
  1290 + }
  1291 + // 3. 生成唯一文件名
  1292 + String fileName = "资信报告_" + System.currentTimeMillis() + ".docx";
  1293 + String outputPath = dirPath.resolve(fileName).toString();
  1294 +
  1295 + // 5. 重新打包为 .docx
  1296 + rebuildDocx("templates/customerCredit.docx", processedXml, outputPath);
  1297 + return fileName;
  1298 + }
  1299 +
  1300 + public void rebuildDocx(String templatePathInClasspath, String processedXml, String outputPath) throws IOException {
  1301 + // 1. 确保输出目录存在
  1302 + Path output = Paths.get(outputPath);
  1303 + Files.createDirectories(output.getParent());
  1304 +
  1305 + // 2. 从 classpath 加载模板
  1306 + try (InputStream templateIs = getClass().getClassLoader().getResourceAsStream(templatePathInClasspath)) {
  1307 + if (templateIs == null) {
  1308 + throw new FileNotFoundException("模板文件未找到,请检查路径: " + templatePathInClasspath);
  1309 + }
  1310 +
  1311 + // 3. 创建输出文件流
  1312 + try (FileOutputStream fos = new FileOutputStream(outputPath);
  1313 + ZipOutputStream zos = new ZipOutputStream(fos)) {
  1314 +
  1315 + try (ZipInputStream zis = new ZipInputStream(templateIs)) {
  1316 + ZipEntry entry;
  1317 + byte[] buffer = new byte[8192];
  1318 +
  1319 + while ((entry = zis.getNextEntry()) != null) {
  1320 + String entryName = entry.getName();
  1321 + zos.putNextEntry(new ZipEntry(entryName));
  1322 +
  1323 + if ("word/document.xml".equals(entryName)) {
  1324 + // 替换为处理后的 XML
  1325 + zos.write(processedXml.getBytes(StandardCharsets.UTF_8));
  1326 + } else {
  1327 + // 其他内容原样复制
  1328 + int len;
  1329 + while ((len = zis.read(buffer)) > 0) {
  1330 + zos.write(buffer, 0, len);
  1331 + }
  1332 + }
  1333 + zos.closeEntry();
  1334 + }
  1335 + }
  1336 + }
  1337 + }
  1338 +
  1339 + System.out.println("文件已生成: " + outputPath);
  1340 + }
1152 1341 /**
1153 1342 * 从“XXX办事处”格式的名称中提取前缀拼音首字母,例如:
1154 1343 * “东莞办事处” → “东莞” → DG
... ...
  1 +package com.lframework.xingyun.sc.impl.customer;
  2 +
  3 +import com.fasterxml.jackson.core.JsonProcessingException;
  4 +import com.fasterxml.jackson.databind.ObjectMapper;
  5 +import com.lframework.starter.bpm.service.FlowTaskService;
  6 +import com.lframework.starter.web.core.annotations.oplog.OpLog;
  7 +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  8 +import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
  9 +import com.lframework.xingyun.sc.vo.customer.credit.*;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.transaction.annotation.Transactional;
  12 +
  13 +import javax.annotation.Resource;
  14 +import java.util.*;
  15 +
  16 +@Service
  17 +public class FlowTaskServiceImpl implements FlowTaskService {
  18 +
  19 + @Resource
  20 + private CustomerCreditService customerCreditService;
  21 +
  22 +
  23 + @OpLog(type = OtherOpLogType.class, name = "修改客户资信,ID:{}", params = {"#id"})
  24 + @Transactional(rollbackFor = Exception.class)
  25 + @Override
  26 + public void updateByMap(Map<String, Object> map) {
  27 + // 创建 ObjectMapper 实例
  28 + ObjectMapper objectMapper = new ObjectMapper();
  29 + try {
  30 + // 方法1:先将 Map 序列化为 JSON 字符串,再反序列化为目标对象
  31 + String json = objectMapper.writeValueAsString(map);
  32 + UpdateCustomerCreditVo updateCustomerCreditVo = objectMapper.readValue(json, UpdateCustomerCreditVo.class);
  33 + // 使用转换后的对象
  34 + System.out.println(updateCustomerCreditVo);
  35 + customerCreditService.updateNoFlowInstance(updateCustomerCreditVo);
  36 +
  37 + } catch (JsonProcessingException e) {
  38 + e.printStackTrace();
  39 + }
  40 + }
  41 +}
... ...
... ... @@ -11,6 +11,7 @@ import freemarker.template.TemplateException;
11 11
12 12 import java.io.IOException;
13 13 import java.util.List;
  14 +import java.util.Map;
14 15
15 16 /**
16 17 * 客户资信表 Service
... ... @@ -53,6 +54,13 @@ public interface CustomerCreditService extends BaseMpService<CustomerCredit> {
53 54 /**
54 55 * 修改不走审核流
55 56 *
  57 + * @param map
  58 + */
  59 + void updateByMap(Map<String, Object> map);
  60 +
  61 + /**
  62 + * 修改不走审核流
  63 + *
56 64 * @param vo
57 65 */
58 66 void updateNoFlowInstance(UpdateCustomerCreditVo vo);
... ... @@ -96,4 +104,9 @@ public interface CustomerCreditService extends BaseMpService<CustomerCredit> {
96 104 */
97 105 SysUser getDeptUser();
98 106
  107 + /**
  108 + * 导出
  109 + */
  110 + String export(String id) throws IOException, TemplateException;
  111 +
99 112 }
... ...