package com.product.patch.service;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ZipUtil;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.google.common.collect.Sets;
|
import com.product.admin.service.PublicService;
|
import com.product.common.utils.StringUtils;
|
import com.product.core.config.CoreConst;
|
import com.product.core.config.Global;
|
import com.product.core.entity.DataTableEntity;
|
import com.product.core.entity.FieldSetEntity;
|
import com.product.core.exception.BaseException;
|
import com.product.core.service.support.AbstractBaseService;
|
import com.product.core.transfer.Transactional;
|
import com.product.core.util.JsonUtil;
|
import com.product.patch.config.CmnConst;
|
import com.product.patch.service.idel.IPatchImportService;
|
import com.product.tool.table.service.DataModelService;
|
import com.product.util.BaseUtil;
|
import com.sun.xml.internal.bind.v2.TODO;
|
import org.apache.poi.ss.formula.functions.T;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.nio.file.StandardCopyOption;
|
import java.util.*;
|
|
/**
|
* @Author cheng
|
* @Date 2024/10/23 10:07
|
* @Desc 补丁导出
|
*/
|
@Service
|
public class PatchImportService extends AbstractBaseService implements IPatchImportService {
|
|
@Resource
|
private PublicService publicService;
|
|
@Resource
|
private DataModelService dataModelService;
|
|
|
@Override
|
@Transactional
|
public Map<String, Object> uploadPatchFile(File patchFile) throws Exception {
|
|
Map<String, Object> result = new HashMap<>();
|
File patchDir = ZipUtil.unzip(patchFile);
|
//获取文件夹下的所有文件
|
File[] files = patchDir.listFiles();
|
//文件排序将zip排到最后
|
Arrays.sort(files, (a, v) -> {
|
if (a.getName().endsWith(".zip")) {
|
return 1;
|
} else {
|
return -1;
|
}
|
});
|
for (File file : files) {
|
if (!file.isFile()) {
|
continue;
|
}
|
String fileName = file.getName();
|
if (fileName.startsWith("face_")) {
|
//表单
|
readFaceData(file);
|
} else if (fileName.startsWith("flow_")) {
|
//流程
|
readFlowData(file);
|
} else if (fileName.startsWith("function_")) {
|
//功能
|
readFunctionData(file);
|
} else if (fileName.startsWith("structure_")) {
|
//数据表
|
readTableStructure(file);
|
} else if (fileName.startsWith("attachment") && fileName.endsWith(".zip")) {
|
//附件
|
readAttachment(file);
|
} else if (fileName.startsWith("table_data") && fileName.endsWith(".zip")) {
|
//数据
|
readTableData(file);
|
} else if (fileName.startsWith("reference") && fileName.endsWith(".zip")) {
|
//参照
|
readReference(file);
|
}
|
}
|
|
return result;
|
}
|
|
|
/**
|
* 读取参照
|
*/
|
private Integer readReference(File file) throws Exception {
|
if (!file.isFile()) {
|
return 0;
|
}
|
File unzip = ZipUtil.unzip(file);
|
//解压的文件下 有 prompt 文件 和 dict 文件 在目录下找到这两个文件
|
File dict = new File(unzip.getPath() + File.separator + "dict");
|
File prompt = new File(unzip.getPath() + File.separator + "prompt");
|
DataTableEntity dictDte = readFileData(dict, "product_sys_dict");
|
DataTableEntity promptDte = readFileData(prompt, "product_sys_prompt");
|
return addOrUpdate(dictDte) + addOrUpdate(promptDte);
|
}
|
|
private Integer addOrUpdate(DataTableEntity dte) {
|
if (DataTableEntity.isEmpty(dte)) {
|
return 0;
|
}
|
String tableName = dte.getTableName().toString();
|
//获取uuid
|
Object[] uuids = dte.getUuids();
|
DataTableEntity dte1 = getBaseDao().listTable(tableName, BaseUtil.buildQuestionMarkFilter("uuid", uuids.length, true), uuids);
|
Set<String> subTableNames = Sets.newHashSet();
|
for (int i = 0; i < dte.getRows(); i++) {
|
String uuid = dte1.getString(i, CoreConst.UUID);
|
FieldSetEntity ff = dte1.getFieldSetEntity(i);
|
if (ff.getSubData() != null) {
|
subTableNames.addAll(ff.getSubData().keySet());
|
}
|
List<FieldSetEntity> fieldSetEntity = dte1.getFieldSetEntity(uuid);
|
if (!CollectionUtil.isEmpty(fieldSetEntity)) {
|
continue;
|
}
|
|
FieldSetEntity fse = fieldSetEntity.get(0);
|
fse.setValue(CoreConst.SYSTEM_DATA_OPERATE_TYPE, CoreConst.SYSTEM_DATA_OPERATE_ADD);
|
}
|
for (String subTableName : subTableNames) {
|
FieldSetEntity info = BaseUtil.getSingleInfoByCache("所有表信息", new String[]{subTableName});
|
if (info == null) {
|
continue;
|
}
|
FieldSetEntity info1 = BaseUtil.getSingleInfoByCache("所有表关联信息", new String[]{info.getUUID()});
|
if (FieldSetEntity.isEmpty(info1)) {
|
continue;
|
}
|
getBaseDao().delete(subTableName, BaseUtil.buildQuestionMarkFilter(info1.getString("field_name"), dte1.getRows(), true), uuids);
|
}
|
getBaseDao().update(dte);
|
return dte.getRows();
|
}
|
|
/**
|
* 读取表结构数据
|
* @param file
|
* @return
|
* @throws Exception
|
*/
|
private DataTableEntity readTableStructure(File file) throws Exception {
|
DataTableEntity dte = readFileData(file, "product_sys_datamodel_table");
|
DataTableEntity old = getBaseDao().listTable("product_sys_datamodel_table", BaseUtil.buildQuestionMarkFilter("uuid", dte.getUuids().length, true), dte.getUuids(), null, null, Integer.MAX_VALUE, 1, true);
|
for (int i = 0; i < dte.getRows(); i++) {
|
FieldSetEntity fse = dte.getFieldSetEntity(i);
|
//查询出不存在的索引和字段
|
if (old != null && old.getRows() > 0) {
|
List<FieldSetEntity> oldf = old.getFieldSetEntity(fse.getString("uuid"));
|
if (CollectionUtil.isEmpty(oldf)) {
|
//记录不存在 、新表
|
continue;
|
}
|
FieldSetEntity oldFse = oldf.get(0);
|
//对比索引和字段
|
String[] table = {"product_sys_datamodel_field", "product_sys_datamodel_index"};
|
for (String t : table) {
|
DataTableEntity sub = fse.getSubDataTable(t);
|
DataTableEntity oldSub = oldFse.getSubDataTable(t);
|
if (DataTableEntity.isEmpty(oldSub)) {
|
continue;
|
}
|
// 补丁中子表为空 则全删除
|
if (DataTableEntity.isEmpty(sub)) {
|
sub = old.clones();
|
//设置为删除
|
for (int i1 = 0; i1 < sub.getRows(); i1++) {
|
sub.setFieldValue(i1, CoreConst.SYSTEM_DATA_OPERATE_TYPE, CoreConst.SYSTEM_DATA_OPERATE_DEL);
|
}
|
continue;
|
}
|
//删除当前已存在的字段但补丁中没有的
|
for (int i1 = 0; i1 < oldSub.getRows(); i1++) {
|
FieldSetEntity oldFse1 = oldSub.getFieldSetEntity(i1);
|
List<FieldSetEntity> fieldSetEntity = sub.getFieldSetEntity(oldFse1.getString("uuid"));
|
if (CollectionUtil.isEmpty(fieldSetEntity)) {
|
//不存在
|
FieldSetEntity clones = oldFse1.clones();
|
clones.setValue(CoreConst.SYSTEM_DATA_OPERATE_TYPE, CoreConst.SYSTEM_DATA_OPERATE_DEL);
|
sub.addFieldSetEntity(clones);
|
}
|
}
|
}
|
}
|
|
//调用数据建模统一操作方法
|
dataModelService.dataModelOperation(fse);
|
}
|
|
return null;
|
}
|
|
/**
|
* 读取流程配置
|
* @param file
|
* @return
|
* @throws Exception
|
*/
|
private Integer readFlowData(File file) throws Exception {
|
DataTableEntity dataTableEntity = readFileData(file, "product_sys_flow");
|
return addOrUpdate(dataTableEntity);
|
}
|
|
/**
|
* 读取功能配置
|
* @param file
|
* @return
|
* @throws Exception
|
*/
|
private int readFunctionData(File file) throws Exception {
|
DataTableEntity dte = readFileData(file, "product_sys_functions");
|
//判断是否已经存在 且 tricode 不一致
|
if (DataTableEntity.isEmpty(dte)) {
|
return 0;
|
}
|
String tableName = dte.getTableName().toString();
|
//获取uuid
|
Object[] uuids = dte.getUuids();
|
DataTableEntity dte1 = getBaseDao().listTable(tableName, BaseUtil.buildQuestionMarkFilter("uuid", uuids.length, true), uuids);
|
Set<String> subTableNames = Sets.newHashSet();
|
for (int i = 0; i < dte.getRows(); i++) {
|
String uuid = dte1.getString(i, CoreConst.UUID);
|
FieldSetEntity ff = dte1.getFieldSetEntity(i);
|
if (ff.getSubData() != null) {
|
subTableNames.addAll(ff.getSubData().keySet());
|
}
|
List<FieldSetEntity> fieldSetEntity = dte1.getFieldSetEntity(uuid);
|
if (!CollectionUtil.isEmpty(fieldSetEntity)) {
|
//判断tricode 是否一致
|
FieldSetEntity fieldSetEntity1 = fieldSetEntity.get(0);
|
String tricode = fieldSetEntity1.getString("tricode");
|
String tricode1 = dte.getString(i, "tricode");
|
if (StringUtils.isNotEmpty(tricode) && !tricode.equals(tricode1)) {
|
//不一致
|
String triCodeParent = fieldSetEntity1.getString("tricode_parent");
|
String triCodeParent1 = dte.getString(i, "tricode_parent");
|
if (StringUtils.isNotEmpty(triCodeParent) && !triCodeParent.equals(triCodeParent1)) {
|
//拿到已存在的tricode 替换
|
dte.setFieldValue(i, "tricode", tricode);
|
dte.setFieldValue(i, "tricode_parent", triCodeParent);
|
continue;
|
} else {
|
//重新生成
|
dte.setFieldValue(i, "tricode", null);
|
publicService.createdCode(dte.getFieldSetEntity(i), "product_sys_functions", "tricode", "tricode_parent");
|
}
|
continue;
|
}
|
continue;
|
}
|
for (String subTableName : subTableNames) {
|
FieldSetEntity info = BaseUtil.getSingleInfoByCache("所有表信息", new String[]{subTableName});
|
if (info == null) {
|
continue;
|
}
|
FieldSetEntity info1 = BaseUtil.getSingleInfoByCache("所有表关联信息", new String[]{info.getUUID()});
|
if (FieldSetEntity.isEmpty(info1)) {
|
continue;
|
}
|
getBaseDao().delete(subTableName, BaseUtil.buildQuestionMarkFilter(info1.getString("field_name"), dte1.getRows(), true), uuids);
|
}
|
FieldSetEntity fse = fieldSetEntity.get(0);
|
fse.setValue(CoreConst.SYSTEM_DATA_OPERATE_TYPE, CoreConst.SYSTEM_DATA_OPERATE_ADD);
|
}
|
getBaseDao().update(dte);
|
return dte.getRows();
|
}
|
|
/**
|
* 读取表单配置
|
* @param file
|
* @return
|
* @throws Exception
|
*/
|
private int readFaceData(File file) throws Exception {
|
DataTableEntity dte = readFileData(file, "product_sys_form");
|
return addOrUpdate(dte);
|
}
|
|
|
/**
|
* 数据业务表数据
|
* @param file
|
* @return
|
* @throws Exception
|
*/
|
private int readTableData(File file) throws Exception {
|
if (!file.isFile()) {
|
return 0;
|
}
|
File fileDir = ZipUtil.unzip(file);
|
int result = 0;
|
for (File file1 : fileDir.listFiles()) {
|
if (!file1.isFile()) {
|
continue;
|
}
|
String fileName = file1.getName();
|
//判断文件名是否以data_开头 中间任意字母+下划线 结尾是 _ + 16位数字
|
String regex = "^data_.*_[0-9]{14}$";
|
if (!fileName.matches(regex)) {
|
continue;
|
}
|
String tableName = fileName.substring(5, fileName.length() - 15);
|
DataTableEntity res = readFileData(file1, tableName);
|
if (DataTableEntity.isEmpty(res)) {
|
continue;
|
}
|
result += addOrUpdate(res);
|
}
|
return result;
|
}
|
|
/**
|
* 读取附件数据并保存
|
* @param file
|
* @throws Exception
|
*/
|
private void readAttachment(File file) throws Exception {
|
File unzip = ZipUtil.unzip(file);
|
//去读文件夹中的文件
|
File[] files = unzip.listFiles((v) -> v.isFile());
|
if (files.length == 0) {
|
return;
|
}
|
File attachmentFile = files[0];
|
String fileName = attachmentFile.getName();
|
JSONArray data = null;
|
if (fileName.startsWith("attachment_data")) {
|
//附件数据
|
data = readFileString(attachmentFile);
|
} else {
|
return;
|
}
|
if (data == null || data.isEmpty()) {
|
return;
|
}
|
DataTableEntity attachmentDte = toDataTable(data, "product_sys_attachments");
|
//去读附件文件
|
File attachmentDir = new File(unzip.getPath() + File.separator + "attachment");
|
|
Object[] uuids = attachmentDte.getUuids();
|
DataTableEntity dte = getBaseDao().listTable("product_sys_attachments", BaseUtil.buildQuestionMarkFilter("uuid", uuids.length, true), uuids);
|
|
|
for (int i = 0; i < attachmentDte.getRows(); i++) {
|
FieldSetEntity fse = attachmentDte.getFieldSetEntity(i);
|
|
//获取数据对应的附件
|
String attachmentTitle = fse.getString("attachment_title");
|
|
File file1 = new File(attachmentDir + File.separator + attachmentTitle);
|
if (!file1.isFile()) {
|
continue;
|
}
|
//移动到附件对应的目录
|
|
String path = fse.getString("attachment_url");
|
String dir = Global.getSystemConfig("local.dir", "./attachment/file");
|
File targetDir = new File(dir + File.separator + path);
|
if (!targetDir.exists()) {
|
targetDir.mkdirs();
|
}
|
//复制文件到直接文件夹 存在替换
|
FileUtil.copyFile(file1, targetDir, StandardCopyOption.REPLACE_EXISTING);
|
|
List<FieldSetEntity> fieldSetEntity = dte.getFieldSetEntity(fse.getUUID());
|
if (fieldSetEntity == null || fieldSetEntity.isEmpty()) {
|
//新数据
|
fse.setValue(CoreConst.SYSTEM_DATA_OPERATE_TYPE, CoreConst.SYSTEM_DATA_OPERATE_ADD);
|
}
|
}
|
getBaseDao().update(attachmentDte);
|
|
|
}
|
|
/**
|
* 读取文件中的数据并转为DataTable
|
* @param file
|
* @param tableName
|
* @return
|
* @throws Exception
|
*/
|
private DataTableEntity readFileData(File file, String tableName) throws Exception {
|
if (!file.isFile()) {
|
return null;
|
}
|
JSONArray objects = readFileString(file);
|
if (objects == null || objects.isEmpty()) {
|
return null;
|
}
|
return toDataTable(objects, tableName);
|
}
|
|
/**
|
* json数组转DataTable
|
* @param arr
|
* @param tableName
|
* @return
|
*/
|
private DataTableEntity toDataTable(JSONArray arr, String tableName) throws BaseException {
|
if (arr == null || arr.isEmpty()) {
|
return null;
|
}
|
DataTableEntity result = new DataTableEntity();
|
//遍历json数组
|
for (int i = 0; i < arr.size(); i++) {
|
FieldSetEntity fse = new FieldSetEntity(tableName);
|
JSONObject jsonObject = arr.getJSONObject(i);
|
fse.setValues((Map) jsonObject.clone());
|
//将json中装载的json对象转成DataTableEntity,遍历json中的内容
|
|
for (String key : jsonObject.keySet()) {
|
Object o = jsonObject.get(key);
|
if (o instanceof JSONArray) {
|
fse.remove(key);
|
fse.addSubDataTable(toDataTable(jsonObject.getJSONArray(key), key));
|
}
|
}
|
result.addFieldSetEntity(fse);
|
}
|
return result;
|
}
|
|
/**
|
* 读取文件中的内容
|
* @param file
|
* @return
|
*/
|
private JSONArray readFileString(File file) throws Exception {
|
if (!file.isFile()) {
|
return null;
|
}
|
try (InputStream in = new FileInputStream(file)) {
|
String str = IoUtil.read(in, "UTF-8");
|
if (StringUtils.isEmpty(str)) {
|
return null;
|
}
|
return JSONArray.parseArray(str);
|
}
|
}
|
|
private String getDateTime() {
|
return DateTime.now().toString("yyyyMMddHHmmss");
|
}
|
}
|