22 changed files with 913 additions and 339 deletions
@ -1,141 +0,0 @@ |
|||||||
|
|
||||||
package apelet.tenantadmin.tenant.controller; |
|
||||||
|
|
||||||
import apelet.common.core.annotation.MyRequestBody; |
|
||||||
import apelet.common.core.exception.MyRuntimeException; |
|
||||||
import apelet.common.core.object.ObjectValue; |
|
||||||
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
|
||||||
import cn.hutool.core.io.IoUtil; |
|
||||||
import org.apache.poi.xwpf.usermodel.*; |
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.core.io.ClassPathResource; |
|
||||||
import org.springframework.web.bind.annotation.*; |
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse; |
|
||||||
import java.io.*; |
|
||||||
import java.net.URLEncoder; |
|
||||||
import java.nio.charset.StandardCharsets; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.regex.Matcher; |
|
||||||
import java.util.regex.Pattern; |
|
||||||
|
|
||||||
@RestController |
|
||||||
@RequestMapping("/api/template") |
|
||||||
public class DocxTemplateController { |
|
||||||
|
|
||||||
|
|
||||||
@Autowired |
|
||||||
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
|
||||||
|
|
||||||
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(.+?)\\}"); |
|
||||||
|
|
||||||
/** |
|
||||||
* 替换字符串中 ${key},JDK8兼容 |
|
||||||
*/ |
|
||||||
private String replaceContent(String text, Map<String, Object> dataMap) { |
|
||||||
if (text == null) return ""; |
|
||||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
|
||||||
StringBuffer sb = new StringBuffer(); |
|
||||||
while (matcher.find()) { |
|
||||||
String key = matcher.group(1).trim(); |
|
||||||
Object val = dataMap.get(key); |
|
||||||
String realVal = val == null ? "" : val.toString(); |
|
||||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(realVal)); |
|
||||||
} |
|
||||||
matcher.appendTail(sb); |
|
||||||
return sb.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
@GetMapping("/downloadDocx") |
|
||||||
public void downloadDocx(@RequestParam("id") String quotationId, HttpServletResponse response) { |
|
||||||
XWPFDocument document = null; |
|
||||||
InputStream templateIs = null; |
|
||||||
OutputStream out = null; |
|
||||||
try { |
|
||||||
// 1. 查数据
|
|
||||||
ObjectValue objectValue = ormGenDataSourceUtil.queryOne("quotation", quotationId); |
|
||||||
Map<String, Object> hashMap = new HashMap<>(); |
|
||||||
hashMap.put("name", objectValue.getString("name")); |
|
||||||
hashMap.put("number", objectValue.getString("number")); |
|
||||||
hashMap.put("create_time", objectValue.getString("create_time")); |
|
||||||
hashMap.put("qty", objectValue.getObjectValue("qty")); |
|
||||||
ObjectValue managerperson = objectValue.getObjectValue("managerperson"); |
|
||||||
if(managerperson != null){ |
|
||||||
managerperson = ormGenDataSourceUtil.queryOne(managerperson.getTableName(), managerperson.getString("id")); |
|
||||||
hashMap.put("managerperson",1); |
|
||||||
} |
|
||||||
// 2. 读模板
|
|
||||||
File file = new File("D:\\work\\xykj-project\\xhgl\\zz-resource\\quotation_template.docx"); |
|
||||||
templateIs = new FileInputStream(file); |
|
||||||
document = new XWPFDocument(templateIs); |
|
||||||
// 3. 替换占位符
|
|
||||||
replaceParagraph(document, hashMap); |
|
||||||
replaceTable(document, hashMap); |
|
||||||
// 4. 设置响应头 —— 关键!
|
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
|
||||||
response.setCharacterEncoding("UTF-8"); |
|
||||||
String fileName = URLEncoder.encode("报价单.docx", StandardCharsets.UTF_8.name()) |
|
||||||
.replaceAll("\\+", "%20"); |
|
||||||
// 兼容各浏览器的文件名写法
|
|
||||||
response.setHeader("Content-Disposition", |
|
||||||
"attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName); |
|
||||||
response.setHeader("Pragma", "no-cache"); |
|
||||||
response.setHeader("Cache-Control", "no-cache"); |
|
||||||
response.setDateHeader("Expires", 0); |
|
||||||
// 5. 写出
|
|
||||||
out = response.getOutputStream(); |
|
||||||
document.write(out); |
|
||||||
out.flush(); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
throw new MyRuntimeException("导出失败: " + e.getMessage()); |
|
||||||
} finally { |
|
||||||
IoUtil.close(document); |
|
||||||
IoUtil.close(templateIs); |
|
||||||
IoUtil.close(out); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void replaceParagraph(XWPFDocument document, Map<String, Object> dataMap) { |
|
||||||
for (XWPFParagraph paragraph : document.getParagraphs()) { |
|
||||||
String text = paragraph.getText(); |
|
||||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
|
||||||
if (!matcher.find()) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
//清空原有run
|
|
||||||
for (XWPFRun run : paragraph.getRuns()) { |
|
||||||
run.setText("", 0); |
|
||||||
} |
|
||||||
String newText = replaceContent(text, dataMap); |
|
||||||
paragraph.createRun().setText(newText); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void replaceTable(XWPFDocument document, Map<String, Object> dataMap) { |
|
||||||
for (XWPFTable table : document.getTables()) { |
|
||||||
for (XWPFTableRow row : table.getRows()) { |
|
||||||
for (XWPFTableCell cell : row.getTableCells()) { |
|
||||||
for (XWPFParagraph paragraph : cell.getParagraphs()) { |
|
||||||
String text = paragraph.getText(); |
|
||||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
|
||||||
if (!matcher.find()) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
for (XWPFRun run : paragraph.getRuns()) { |
|
||||||
run.setText("", 0); |
|
||||||
} |
|
||||||
String newText = replaceContent(text, dataMap); |
|
||||||
paragraph.createRun().setText(newText); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,353 @@ |
|||||||
|
package apelet.tenantadmin.upms.controller; |
||||||
|
|
||||||
|
import apelet.common.core.exception.MyRuntimeException; |
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.core.object.ResponseResult; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.online.service.OnlineDictService; |
||||||
|
import apelet.common.orm.impl.Filter; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
import cn.hutool.core.date.DateUtil; |
||||||
|
import cn.hutool.core.io.IoUtil; |
||||||
|
import cn.hutool.poi.excel.ExcelReader; |
||||||
|
import cn.hutool.poi.excel.ExcelUtil; |
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.alibaba.fastjson.JSONArray; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; |
||||||
|
import org.apache.poi.xwpf.usermodel.*; |
||||||
|
import org.docx4j.Docx4J; |
||||||
|
import org.docx4j.fonts.IdentityPlusMapper; |
||||||
|
import org.docx4j.fonts.PhysicalFonts; |
||||||
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.*; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.*; |
||||||
|
import java.net.HttpURLConnection; |
||||||
|
import java.net.URL; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.nio.file.Files; |
||||||
|
import java.util.*; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
@RestController |
||||||
|
@RequestMapping("/api/template") |
||||||
|
public class DocxTemplateController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
@Autowired |
||||||
|
private OnlineDictService onlineDictService; |
||||||
|
|
||||||
|
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("#\\{(.+?)\\}"); |
||||||
|
|
||||||
|
private String replaceContent(String text, Map<String, Object> dataMap) { |
||||||
|
if (text == null) return ""; |
||||||
|
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||||
|
StringBuffer sb = new StringBuffer(); |
||||||
|
while (matcher.find()) { |
||||||
|
String key = matcher.group(1).trim(); |
||||||
|
if ("personimage".equals(key)) { |
||||||
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(matcher.group(0))); |
||||||
|
continue; |
||||||
|
} |
||||||
|
Object val = dataMap.get(key); |
||||||
|
String realVal = val == null ? "" : val.toString(); |
||||||
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(realVal)); |
||||||
|
} |
||||||
|
matcher.appendTail(sb); |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/downloadDocx") |
||||||
|
public void downloadDocx(@RequestParam("id") String quotationId, @RequestParam("userId") String userId, HttpServletResponse response) { |
||||||
|
XWPFDocument document = null; |
||||||
|
InputStream templateIs = null; |
||||||
|
OutputStream out = null; |
||||||
|
ByteArrayOutputStream pdfOut = null; |
||||||
|
try { |
||||||
|
// 1. 查数据
|
||||||
|
ObjectValue objectValue = ormGenDataSourceUtil.queryOne("quotation", quotationId); |
||||||
|
ObjectValue user = ormGenDataSourceUtil.queryOne("xy_sys_user", userId); |
||||||
|
Map<String, String> dictMap = onlineDictService.getDictMap(2052225870772310016L); |
||||||
|
Map<String, Object> hashMap = new HashMap<>(); |
||||||
|
hashMap.put("name", objectValue.getString("name")); |
||||||
|
hashMap.put("type", dictMap.get(String.valueOf(objectValue.get("type", "")))); |
||||||
|
hashMap.put("number", objectValue.getString("number")); |
||||||
|
hashMap.put("create_time", objectValue.getString("create_time").substring(0, 10)); |
||||||
|
hashMap.put("qty", objectValue.getString("qty")); |
||||||
|
|
||||||
|
String signatureImage = user.getString("signature_image"); |
||||||
|
String imageUrl = getUrl(signatureImage); |
||||||
|
byte[] imageBytes = null; |
||||||
|
if (StringUtils.isNotEmpty(imageUrl)) { |
||||||
|
imageBytes = downloadImage(imageUrl); |
||||||
|
} |
||||||
|
ObjectValue managerperson = objectValue.getObjectValue("managerperson"); |
||||||
|
if (managerperson != null) { |
||||||
|
managerperson = ormGenDataSourceUtil.queryOne(managerperson.getTableName(), managerperson.getString("id")); |
||||||
|
hashMap.put("managerperson", managerperson.getString("show_name")); |
||||||
|
} |
||||||
|
// 2. 读模板
|
||||||
|
String savePath = System.getProperty("user.dir") + "\\zz-resource\\"; |
||||||
|
File file = new File(savePath + "quotation_template.docx"); |
||||||
|
templateIs = Files.newInputStream(file.toPath()); |
||||||
|
document = new XWPFDocument(templateIs); |
||||||
|
// 3. 替换文本占位符
|
||||||
|
replaceParagraph(document, hashMap); |
||||||
|
replaceTable(document, hashMap); |
||||||
|
// 4. 替换图片占位符
|
||||||
|
replaceImageInParagraphs(document, "personimage", imageBytes, 100, 100); |
||||||
|
replaceImageInTables(document, "personimage", imageBytes, 100, 100); |
||||||
|
// 5. 将填充后的 DOCX 转为 PDF(使用 docx4j)
|
||||||
|
ByteArrayOutputStream docxOut = new ByteArrayOutputStream(); |
||||||
|
document.write(docxOut); |
||||||
|
byte[] docxBytes = docxOut.toByteArray(); |
||||||
|
docxOut.close(); |
||||||
|
|
||||||
|
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new ByteArrayInputStream(docxBytes)); |
||||||
|
PhysicalFonts.discoverPhysicalFonts(); |
||||||
|
wordMLPackage.setFontMapper(new IdentityPlusMapper()); |
||||||
|
pdfOut = new ByteArrayOutputStream(); |
||||||
|
Docx4J.toPDF(wordMLPackage, pdfOut); |
||||||
|
byte[] pdfBytes = pdfOut.toByteArray(); |
||||||
|
|
||||||
|
// 6. 设置响应头
|
||||||
|
response.setContentType("application/pdf"); |
||||||
|
response.setCharacterEncoding("UTF-8"); |
||||||
|
String fileName = URLEncoder.encode("报价单.pdf", StandardCharsets.UTF_8.name()) |
||||||
|
.replaceAll("\\+", "%20"); |
||||||
|
response.setHeader("Content-Disposition", |
||||||
|
"attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName); |
||||||
|
response.setHeader("Pragma", "no-cache"); |
||||||
|
response.setHeader("Cache-Control", "no-cache"); |
||||||
|
response.setDateHeader("Expires", 0); |
||||||
|
// 7. 写出 PDF
|
||||||
|
out = response.getOutputStream(); |
||||||
|
out.write(pdfBytes); |
||||||
|
out.flush(); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
throw new MyRuntimeException("导出失败: " + e.getMessage()); |
||||||
|
} finally { |
||||||
|
IoUtil.close(pdfOut); |
||||||
|
IoUtil.close(document); |
||||||
|
IoUtil.close(templateIs); |
||||||
|
IoUtil.close(out); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
String getUrl(String signatureImage) { |
||||||
|
if (StringUtils.isEmpty(signatureImage)) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
JSONArray jsonArray = JSON.parseArray(signatureImage); |
||||||
|
if (jsonArray.isEmpty()) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
JSONObject jsonObject = jsonArray.getJSONObject(0); |
||||||
|
String baseUrl = jsonObject.getString("baseUrl"); |
||||||
|
String uploadPath = jsonObject.getString("uploadPath"); |
||||||
|
String filename = jsonObject.getString("filename"); |
||||||
|
|
||||||
|
return baseUrl + "/" + uploadPath + "/" + filename; |
||||||
|
} |
||||||
|
|
||||||
|
private void replaceParagraph(XWPFDocument document, Map<String, Object> dataMap) { |
||||||
|
for (XWPFParagraph paragraph : document.getParagraphs()) { |
||||||
|
String text = paragraph.getText(); |
||||||
|
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||||
|
if (!matcher.find()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
for (XWPFRun run : paragraph.getRuns()) { |
||||||
|
run.setText("", 0); |
||||||
|
} |
||||||
|
String newText = replaceContent(text, dataMap); |
||||||
|
paragraph.createRun().setText(newText); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void replaceTable(XWPFDocument document, Map<String, Object> dataMap) { |
||||||
|
for (XWPFTable table : document.getTables()) { |
||||||
|
for (XWPFTableRow row : table.getRows()) { |
||||||
|
for (XWPFTableCell cell : row.getTableCells()) { |
||||||
|
for (XWPFParagraph paragraph : cell.getParagraphs()) { |
||||||
|
String text = paragraph.getText(); |
||||||
|
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||||
|
if (!matcher.find()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
for (XWPFRun run : paragraph.getRuns()) { |
||||||
|
run.setText("", 0); |
||||||
|
} |
||||||
|
String newText = replaceContent(text, dataMap); |
||||||
|
paragraph.createRun().setText(newText); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private byte[] downloadImage(String imageUrl) throws IOException { |
||||||
|
URL url = new URL(imageUrl); |
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
||||||
|
conn.setRequestMethod("GET"); |
||||||
|
conn.setConnectTimeout(5000); |
||||||
|
conn.setReadTimeout(10000); |
||||||
|
InputStream is = conn.getInputStream(); |
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||||
|
byte[] buffer = new byte[4096]; |
||||||
|
int len; |
||||||
|
while ((len = is.read(buffer)) != -1) { |
||||||
|
baos.write(buffer, 0, len); |
||||||
|
} |
||||||
|
IoUtil.close(is); |
||||||
|
return baos.toByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void replaceImageInParagraphs(XWPFDocument document, String placeholderKey, byte[] imageBytes, int width, int height) throws IOException, InvalidFormatException { |
||||||
|
String placeholder = "#{" + placeholderKey + "}"; |
||||||
|
for (XWPFParagraph paragraph : document.getParagraphs()) { |
||||||
|
String text = paragraph.getText(); |
||||||
|
if (text != null && text.contains(placeholder)) { |
||||||
|
List<XWPFRun> runs = paragraph.getRuns(); |
||||||
|
for (int i = runs.size() - 1; i >= 0; i--) { |
||||||
|
XWPFRun run = runs.get(i); |
||||||
|
String runText = run.getText(0); |
||||||
|
if (runText != null && runText.contains(placeholder)) { |
||||||
|
run.setText("", 0); |
||||||
|
if (imageBytes != null) { |
||||||
|
run.addPicture(new ByteArrayInputStream(imageBytes), XWPFDocument.PICTURE_TYPE_PNG, placeholderKey + ".png", |
||||||
|
width * 9525, height * 9525); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void replaceImageInTables(XWPFDocument document, String placeholderKey, byte[] imageBytes, int width, int height) throws IOException, InvalidFormatException { |
||||||
|
String placeholder = "#{" + placeholderKey + "}"; |
||||||
|
for (XWPFTable table : document.getTables()) { |
||||||
|
for (XWPFTableRow row : table.getRows()) { |
||||||
|
for (XWPFTableCell cell : row.getTableCells()) { |
||||||
|
for (XWPFParagraph paragraph : cell.getParagraphs()) { |
||||||
|
String text = paragraph.getText(); |
||||||
|
if (text != null && text.contains(placeholder)) { |
||||||
|
List<XWPFRun> runs = paragraph.getRuns(); |
||||||
|
for (int i = runs.size() - 1; i >= 0; i--) { |
||||||
|
XWPFRun run = runs.get(i); |
||||||
|
String runText = run.getText(0); |
||||||
|
if (runText != null && runText.contains(placeholder)) { |
||||||
|
run.setText("", 0); |
||||||
|
if (imageBytes != null) { |
||||||
|
run.addPicture(new ByteArrayInputStream(imageBytes), XWPFDocument.PICTURE_TYPE_PNG, placeholderKey + ".png", |
||||||
|
width * 9525, height * 9525); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static final Map<String, String> HEADER_MAP = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
HEADER_MAP.put("名称", "name"); |
||||||
|
HEADER_MAP.put("性别", "gender"); |
||||||
|
HEADER_MAP.put("手机号码", "phone"); |
||||||
|
HEADER_MAP.put("出生年月", "birth_date"); |
||||||
|
HEADER_MAP.put("学历", "education"); |
||||||
|
HEADER_MAP.put("民族", "nation"); |
||||||
|
HEADER_MAP.put("政治面貌", "political_status"); |
||||||
|
HEADER_MAP.put("身份证号码", "id_card"); |
||||||
|
HEADER_MAP.put("毕业院校", "graduate_school"); |
||||||
|
HEADER_MAP.put("所属专业", "major"); |
||||||
|
HEADER_MAP.put("常住地", "permanent_address"); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("/expertImport") |
||||||
|
public ResponseResult<?> expertImport(@RequestParam("file") MultipartFile file) { |
||||||
|
List<Map<String, Object>> dataList = new ArrayList<>(); |
||||||
|
try (InputStream is = file.getInputStream()) { |
||||||
|
ExcelReader reader = ExcelUtil.getReader(is); |
||||||
|
// 第一行作为表头,key 为表头名称,自动兼容 xls/xlsx
|
||||||
|
List<Map<String, Object>> rawList = reader.readAll(); |
||||||
|
//学历
|
||||||
|
Map<String, String> educationDictMap = onlineDictService.getDictMap(2054094099727781888L); |
||||||
|
educationDictMap = educationDictMap.entrySet().stream() |
||||||
|
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); |
||||||
|
//政治面貌
|
||||||
|
Map<String, String> politicalDictMap = onlineDictService.getDictMap(2054098587905691648L); |
||||||
|
politicalDictMap = politicalDictMap.entrySet().stream() |
||||||
|
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); |
||||||
|
for (Map<String, Object> row : rawList) { |
||||||
|
Map<String, Object> dataMap = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
for (Map.Entry<String, Object> entry : row.entrySet()) { |
||||||
|
String header = entry.getKey() == null ? "" : entry.getKey().trim(); |
||||||
|
// 中文表头转英文,映射中没有的表头保留原值
|
||||||
|
String key = HEADER_MAP.getOrDefault(header, header); |
||||||
|
Object value = entry.getValue(); |
||||||
|
dataMap.put(key, value); |
||||||
|
if (key.equals("gender")) { |
||||||
|
dataMap.put("gender", value.equals("男") ? "1" : "0"); |
||||||
|
} |
||||||
|
if (key.equals("education")) { |
||||||
|
dataMap.put("education", educationDictMap.get(value.toString())); |
||||||
|
} |
||||||
|
if (key.equals("political_status")) { |
||||||
|
dataMap.put("political_status", politicalDictMap.get(value.toString())); |
||||||
|
} |
||||||
|
if ("birth_date".equals(key)) { |
||||||
|
if (value instanceof Date) { |
||||||
|
value = DateUtil.formatDateTime((Date) value); |
||||||
|
} else if (value instanceof String && StringUtils.isNotBlank((String) value)) { |
||||||
|
value = DateUtil.formatDateTime(DateUtil.parse((String) value)); |
||||||
|
} |
||||||
|
dataMap.put(key, value); |
||||||
|
} |
||||||
|
} |
||||||
|
dataMap.put("billstatus", "A"); |
||||||
|
dataMap.put("apply_time", DateUtil.formatDateTime(new Date())); |
||||||
|
dataList.add(dataMap); |
||||||
|
} |
||||||
|
ObjectCollection expertManage = ormGenDataSourceUtil.query("expert_manage", new Filter(), new Selector()); |
||||||
|
dataList.forEach(dataMap -> { |
||||||
|
long count = expertManage.stream().filter(f -> f.get("id_card").equals(dataMap.get("id_card"))).count(); |
||||||
|
if (count > 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
ObjectValue value = new ObjectValue("expert_manage"); |
||||||
|
value.setValues(dataMap); |
||||||
|
try { |
||||||
|
ormGenDataSourceUtil.addNew("expert_manage", value); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
} catch (IOException e) { |
||||||
|
throw new MyRuntimeException("文件解析失败: " + e.getMessage()); |
||||||
|
} |
||||||
|
return ResponseResult.success("导入成功"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,121 @@ |
|||||||
|
package apelet.tenantadmin.upms.service; |
||||||
|
|
||||||
|
import cn.hutool.http.HttpRequest; |
||||||
|
import cn.hutool.http.HttpResponse; |
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.redisson.api.RBucket; |
||||||
|
import org.redisson.api.RedissonClient; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Service |
||||||
|
public class SupersetSsoService { |
||||||
|
|
||||||
|
@Value("${superset.baseUrl}") |
||||||
|
private String supersetBaseUrl; |
||||||
|
|
||||||
|
@Value("${superset.username}") |
||||||
|
private String supersetUsername; |
||||||
|
|
||||||
|
@Value("${superset.password}") |
||||||
|
private String supersetPassword; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private RedissonClient redissonClient; |
||||||
|
|
||||||
|
private static final String SUPERSET_TOKEN_CACHE_KEY = "superset:access_token"; |
||||||
|
private static final int TOKEN_CACHE_SECONDS = 3500; |
||||||
|
|
||||||
|
public String getAccessToken() { |
||||||
|
RBucket<String> cached = redissonClient.getBucket(SUPERSET_TOKEN_CACHE_KEY); |
||||||
|
if (cached.isExists()) { |
||||||
|
return cached.get(); |
||||||
|
} |
||||||
|
String url = supersetBaseUrl + "/api/v1/security/login"; |
||||||
|
JSONObject payload = new JSONObject(); |
||||||
|
payload.put("username", supersetUsername); |
||||||
|
payload.put("password", supersetPassword); |
||||||
|
payload.put("provider", "db"); |
||||||
|
payload.put("refresh", true); |
||||||
|
|
||||||
|
HttpResponse response = HttpRequest.post(url) |
||||||
|
.header("Content-Type", "application/json") |
||||||
|
.body(payload.toJSONString()) |
||||||
|
.timeout(10000) |
||||||
|
.execute(); |
||||||
|
|
||||||
|
if (!response.isOk()) { |
||||||
|
log.error("Superset login failed, status={}, body={}", response.getStatus(), response.body()); |
||||||
|
throw new RuntimeException("Superset认证失败: " + response.body()); |
||||||
|
} |
||||||
|
|
||||||
|
JSONObject result = JSON.parseObject(response.body()); |
||||||
|
String accessToken = result.getString("access_token"); |
||||||
|
|
||||||
|
cached.set(accessToken, TOKEN_CACHE_SECONDS, TimeUnit.SECONDS); |
||||||
|
log.info("Superset access token refreshed successfully."); |
||||||
|
return accessToken; |
||||||
|
} |
||||||
|
|
||||||
|
public String getGuestToken(String dashboardId, String username, String firstName, String lastName, |
||||||
|
List<Map<String, String>> rlsRules) { |
||||||
|
String accessToken = getAccessToken(); |
||||||
|
|
||||||
|
String url = supersetBaseUrl + "/api/v1/security/guest_token/"; |
||||||
|
|
||||||
|
JSONObject user = new JSONObject(); |
||||||
|
user.put("username", username); |
||||||
|
user.put("first_name", firstName); |
||||||
|
user.put("last_name", lastName); |
||||||
|
|
||||||
|
List<Map<String, Object>> resources = new ArrayList<>(); |
||||||
|
Map<String, Object> resource = new HashMap<>(); |
||||||
|
resource.put("type", "dashboard"); |
||||||
|
resource.put("id", dashboardId); |
||||||
|
resources.add(resource); |
||||||
|
|
||||||
|
JSONObject payload = new JSONObject(); |
||||||
|
payload.put("user", user); |
||||||
|
payload.put("resources", resources); |
||||||
|
if (rlsRules != null && !rlsRules.isEmpty()) { |
||||||
|
payload.put("rls", rlsRules); |
||||||
|
} else { |
||||||
|
payload.put("rls", new ArrayList<>()); |
||||||
|
} |
||||||
|
|
||||||
|
HttpResponse response = HttpRequest.post(url) |
||||||
|
.header("Content-Type", "application/json") |
||||||
|
.header("Authorization", "Bearer " + accessToken) |
||||||
|
.body(payload.toJSONString()) |
||||||
|
.timeout(10000) |
||||||
|
.execute(); |
||||||
|
|
||||||
|
if (!response.isOk()) { |
||||||
|
log.error("Superset get guest token failed, status={}, body={}", response.getStatus(), response.body()); |
||||||
|
redissonClient.getBucket(SUPERSET_TOKEN_CACHE_KEY).delete(); |
||||||
|
throw new RuntimeException("获取Superset Guest Token失败: " + response.body()); |
||||||
|
} |
||||||
|
|
||||||
|
JSONObject result = JSON.parseObject(response.body()); |
||||||
|
return result.getString("token"); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildDashboardUrl(String dashboardId) { |
||||||
|
String accessToken = getAccessToken(); |
||||||
|
return supersetBaseUrl + "superset/dashboard/" + dashboardId + "/?token=" + accessToken; |
||||||
|
} |
||||||
|
|
||||||
|
public String buildEmbeddedDashboardUrl(String dashboardId, String guestToken) { |
||||||
|
return supersetBaseUrl + "superset/embed/dashboard/" + dashboardId + "/?guest_token=" + guestToken; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
package apelet.association.plugin.active; |
||||||
|
|
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.core.util.ApplicationContextHolder; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.online.plugin.EndOperationTransactionArgs; |
||||||
|
import apelet.common.online.plugin.OperationServicePlugIn; |
||||||
|
import apelet.common.orm.impl.Filter; |
||||||
|
import apelet.common.orm.impl.FilterItem; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
|
||||||
|
public class ActivityInvitationSavePlugin extends OperationServicePlugIn { |
||||||
|
|
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
public ActivityInvitationSavePlugin() { |
||||||
|
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void endOperationTransaction(EndOperationTransactionArgs e) { |
||||||
|
ObjectValue objectValue = e.getModel(); |
||||||
|
ObjectCollection collection = objectValue.getObjectCollection("visitor_invitation"); |
||||||
|
if(collection == null){ |
||||||
|
return; |
||||||
|
} |
||||||
|
Filter filter = new Filter(); |
||||||
|
filter.add(new FilterItem("parent_id", FilterItem.equals, objectValue.get("id"))); |
||||||
|
ObjectCollection visitorInvitationHis = ormGenDataSourceUtil.query("visitor_invitation_his", filter, new Selector()); |
||||||
|
|
||||||
|
for (ObjectValue value : collection) { |
||||||
|
long count = visitorInvitationHis.stream().filter(f -> f.get("name").equals(value.get("name")) && |
||||||
|
f.get("unit_name").equals(value.get("unit_name"))).count(); |
||||||
|
if(count == 0){ |
||||||
|
continue; |
||||||
|
} |
||||||
|
ObjectValue invitationHis = new ObjectValue("visitor_invitation_his"); |
||||||
|
invitationHis.setValues(value.getValues()); |
||||||
|
invitationHis.remove("id"); |
||||||
|
try { |
||||||
|
ormGenDataSourceUtil.addNew(invitationHis.getTableName(), invitationHis); |
||||||
|
} catch (Exception ex) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
package apelet.association.plugin.member; |
||||||
|
|
||||||
|
import apelet.common.core.exception.MyRuntimeException; |
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.core.util.ApplicationContextHolder; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.online.abstractplugin.ExecutePluginParent; |
||||||
|
import apelet.common.online.abstractplugin.ListPlugin; |
||||||
|
import apelet.common.online.dto.OnlineEventPluginExecuteDto; |
||||||
|
import apelet.common.online.model.constant.AttributeEnum; |
||||||
|
import apelet.common.orm.impl.Filter; |
||||||
|
import apelet.common.orm.impl.FilterItem; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
|
||||||
|
import java.sql.Date; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
|
||||||
|
public class MembershipBenefitsUpdatePlugin extends ListPlugin { |
||||||
|
|
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
public MembershipBenefitsUpdatePlugin() { |
||||||
|
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void formCreated(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
ObjectValue value = ormGenDataSourceUtil.queryOne(objectValue.getTableName(), objectValue.getString("id")); |
||||||
|
ObjectCollection collection = value.getObjectCollection("equity_services"); |
||||||
|
ObjectCollection equityServices = objectValue.getObjectCollection("equity_services"); |
||||||
|
for (ObjectValue equityService : equityServices) { |
||||||
|
Optional<ObjectValue> first = collection.stream().filter(f -> f.getString("id").equals(equityService.getString("id"))).findFirst(); |
||||||
|
ObjectValue value1 = first.get(); |
||||||
|
this.setWidgetAttributeByEntry("table1782205467614", "member", |
||||||
|
AttributeEnum.VALUE_CHANGE, value1.getInt("member"), equityService.getString("rowkey")); |
||||||
|
this.setWidgetAttributeByEntry("table1782205467614", "director", |
||||||
|
AttributeEnum.VALUE_CHANGE, value1.getInt("director"), equityService.getString("rowkey")); |
||||||
|
this.setWidgetAttributeByEntry("table1782205467614", "executive_director", |
||||||
|
AttributeEnum.VALUE_CHANGE, value1.getInt("executive_director"), equityService.getString("rowkey")); |
||||||
|
this.setWidgetAttributeByEntry("table1782205467614", "vice_president", |
||||||
|
AttributeEnum.VALUE_CHANGE, value1.getInt("vice_president"), equityService.getString("rowkey")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
Loading…
Reference in new issue