package com.xjrsoft.module.app.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.meta.MetaUtil;
import cn.hutool.db.meta.Table;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.FormTemplateType;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.utils.DatasourceUtil;
import com.xjrsoft.config.GeneratePathConfig;
import com.xjrsoft.module.app.dto.AddAppMenuDto;
import com.xjrsoft.module.app.dto.AddFuncDesignDto;
import com.xjrsoft.module.app.dto.UpdateAppFuncDesignDto;
import com.xjrsoft.module.app.entity.AppFuncDesign;
import com.xjrsoft.module.app.entity.AppMenu;
import com.xjrsoft.module.app.mapper.AppFuncDesignMapper;
import com.xjrsoft.module.app.mapper.AppMenuMapper;
import com.xjrsoft.module.app.service.IAppFuncDesignService;
import com.xjrsoft.module.generator.dto.GeneratorAppDto;
import com.xjrsoft.module.generator.entity.GeneratorConfig;
import com.xjrsoft.module.generator.entity.OutputConfig;
import com.xjrsoft.module.generator.entity.TableConfig;
import com.xjrsoft.module.generator.service.IGeneratorService;
import com.xjrsoft.module.generator.utils.GeneratorUtil;
import com.xjrsoft.module.generator.utils.SqlUtil;
import com.xjrsoft.module.system.service.IDatabaselinkService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
*
* 服务实现类
*
*
* @author tzx
* @since 2023-07-26
*/
@Service
@AllArgsConstructor
public class AppFuncDesignServiceImpl extends MPJBaseServiceImpl implements IAppFuncDesignService {
private final AppMenuMapper appMenuMapper;
private final IGeneratorService generatorService;
private final GeneratePathConfig generatePathConfig;
private final IDatabaselinkService databaselinkService;
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean add(AddFuncDesignDto dto) {
AppFuncDesign appFuncDesign = BeanUtil.toBean(dto, AppFuncDesign.class);
//如果是自定义表单 不需要生成代码 以及 page.json
if (dto.getFormType() == FormTemplateType.CUSTOM.getCode() && dto.getIsGeneratorCode() != YesOrNoEnum.YES.getCode()) {
AppMenu appMenu = BeanUtil.toBean(dto.getMenuConfigs(), AppMenu.class);
long snowflakeNextId = IdUtil.getSnowflakeNextId();
appMenu.setUrl(appMenu.getUrl() + StringPool.QUESTION_MARK + "id=" + snowflakeNextId);
appMenuMapper.insert(appMenu);
appFuncDesign.setId(snowflakeNextId);
appFuncDesign.setAppMenuId(appMenu.getId());
save(appFuncDesign);
} else {
if(dto.getFormType() == FormTemplateType.CUSTOM.getCode()){
GeneratorConfig generatorConfig = JSONUtil.toBean(dto.getJsonContent(), GeneratorConfig.class);
generatorEndCode(generatorConfig);
}
AppMenu appMenu = BeanUtil.toBean(dto.getMenuConfigs(), AppMenu.class);
appMenu.setUrl("/pages/" + dto.getCodes().getOutputValue() + StringPool.SLASH + dto.getCodes().getClassName().toLowerCase() + StringPool.SLASH + "list");
appMenuMapper.insert(appMenu);
appFuncDesign.setAppMenuId(appMenu.getId());
save(appFuncDesign);
//保存成功之后 生成代码
modifyPageJsonFile(dto.getCodes(), dto.getMenuConfigs());
generatorService.generateAppCodes(dto.getCodes());
}
return Boolean.TRUE;
}
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean modify(UpdateAppFuncDesignDto dto) {
AppFuncDesign appFuncDesign = BeanUtil.toBean(dto, AppFuncDesign.class);
//如果是自定义表单 不需要生成代码 以及 page.json
if (dto.getFormType() == FormTemplateType.CUSTOM.getCode() && dto.getIsGeneratorCode() != YesOrNoEnum.YES.getCode()) {
AppMenu appMenu = BeanUtil.toBean(dto.getMenuConfigs(), AppMenu.class);
appMenu.setId(dto.getAppMenuId());
appMenu.setUrl(appMenu.getUrl() + StringPool.QUESTION_MARK + "id=" + appFuncDesign.getId());
appMenuMapper.updateById(appMenu);
appFuncDesign.setAppMenuId(appMenu.getId());
updateById(appFuncDesign);
} else {
if(dto.getFormType() == FormTemplateType.CUSTOM.getCode()){
GeneratorConfig generatorConfig = JSONUtil.toBean(dto.getJsonContent(), GeneratorConfig.class);
generatorEndCode(generatorConfig);
}
AppMenu appMenu = BeanUtil.toBean(dto.getMenuConfigs(), AppMenu.class);
appMenu.setId(dto.getAppMenuId());
appMenu.setUrl("/pages/" + dto.getCodes().getOutputValue() + StringPool.SLASH + dto.getCodes().getClassName().toLowerCase() + StringPool.SLASH + "list");
appMenuMapper.updateById(appMenu);
updateById(appFuncDesign);
//保存成功之后 生成代码
modifyPageJsonFile(dto.getCodes(), dto.getMenuConfigs());
generatorService.generateAppCodes(dto.getCodes());
}
return Boolean.TRUE;
}
private void modifyPageJsonFile(GeneratorAppDto dto, AddAppMenuDto menuDto) {
File tempFile = FileUtil.file(generatePathConfig.getAppPath() + StringPool.SLASH + "pages.json");
JSON jsonContent = JSONUtil.readJSON(tempFile, StandardCharsets.UTF_8);
//如果已经包含了此地址 就不再生成
if (jsonContent.getByPath("pages").toString().contains( "pages/" + dto.getOutputValue() + StringPool.SLASH + dto.getClassName().toLowerCase() + StringPool.SLASH + "list")) {
return;
}
Map listJsonMap = new HashMap<>();
listJsonMap.put("path", "pages/" + dto.getOutputValue() + StringPool.SLASH + dto.getClassName().toLowerCase() + StringPool.SLASH + "list");
Map listStyleMap = new HashMap<>();
listStyleMap.put("navigationBarTitleText", menuDto.getName());
listJsonMap.put("style", listStyleMap);
Map formJsonMap = new HashMap<>();
formJsonMap.put("path", "pages/" + dto.getOutputValue() + StringPool.SLASH + dto.getClassName().toLowerCase() + StringPool.SLASH + "form");
Map formStyleMap = new HashMap<>();
formStyleMap.put("navigationBarTitleText", "新增");
formJsonMap.put("style", formStyleMap);
JSONArray pages = JSONUtil.parseArray(jsonContent.getByPath("pages").toString());
pages.add(listJsonMap);
pages.add(formJsonMap);
jsonContent.putByPath("pages", pages);
FileUtil.writeString(jsonContent.toJSONString(4), tempFile, StandardCharsets.UTF_8);
}
/**
* 根据json 生成后端代码
* @param generatorConfig
*/
@SneakyThrows
private void generatorEndCode(GeneratorConfig generatorConfig){
Optional tableConfigOptional = generatorConfig.getTableConfigs().stream().filter(TableConfig::getIsMain).findFirst();
//主表
TableConfig mainTable;
if (tableConfigOptional.isPresent()) {
mainTable = tableConfigOptional.get();
} else {
throw new MyException("请选择主表");
}
OutputConfig outputConfig = generatorConfig.getOutputConfig();
String databaseId = generatorConfig.getDatabaseId();
if (BooleanUtils.isTrue(outputConfig.getIsDataAuth())) {
// 添加权限字段 rule_user_id
DataSource dataSource = DatasourceUtil.getDataSource(databaseId);
String[] columnNames = MetaUtil.getColumnNames(dataSource, mainTable.getTableName());
if (!ArrayUtils.contains(columnNames, GlobalConstant.AUTH_USER_ID)) {
DbType dbType = databaselinkService.getDbType(databaseId);
Db.use(dataSource).executeBatch(SqlUtil.buildAddDataAuthFieldSqls(dbType, mainTable.getTableName()));
}
}
//修改 getTableInfos 也记得修改 FromTemplateServiceImpl 的同名方法
List tableInfos = getTableInfos(generatorConfig);
createCodeFile(generatorConfig, mainTable, tableInfos);
}
/**
* 获取表结构信息
*
* @param generatorConfig
* @return
*/
private List getTableInfos(GeneratorConfig generatorConfig) {
List tableInfos = new ArrayList<>();
for (TableConfig tableConfig : generatorConfig.getTableConfigs()) {
//判断是否为默认数据源
if (StrUtil.equalsIgnoreCase(generatorConfig.getDatabaseId(), GlobalConstant.DEFAULT_DATASOURCE_KEY)) {
tableInfos.add(MetaUtil.getTableMeta(DatasourceUtil.getDatasourceMaster(), tableConfig.getTableName()));
} else {
tableInfos.add(MetaUtil.getTableMeta(DatasourceUtil.getDataSource(generatorConfig.getDatabaseId()), tableConfig.getTableName()));
}
}
return tableInfos;
}
/**
* 根据配置生成文件
*
* @param generatorConfig
* @param mainTable
* @param tableInfos
* @throws FileNotFoundException
*/
private void createCodeFile(GeneratorConfig generatorConfig, TableConfig mainTable, List tableInfos) throws FileNotFoundException {
String className = generatorConfig.getOutputConfig().getClassName();
String dirValue = generatorConfig.getOutputConfig().getOutputValue();
//---------------------------------------生成entity开始----------------------------------------------------
{
Map entityCodeMap = GeneratorUtil.getEntityCode(generatorConfig, tableInfos);
for (Map.Entry entry : entityCodeMap.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getEntityOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
//---------------------------------------生成entity结束----------------------------------------------------
//********************************************生成dto开始************************************************
{
Map dtoMap = new HashMap<>(3);
dtoMap.putAll(GeneratorUtil.getAddDtoCode(generatorConfig, tableInfos));
dtoMap.putAll(GeneratorUtil.getUpdateDtoCode(generatorConfig, tableInfos));
dtoMap.putAll(GeneratorUtil.getPageDtoCode(generatorConfig, tableInfos, mainTable));
for (Map.Entry entry : dtoMap.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getDtoOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
//********************************************生成dto结束************************************************
//###############################################生成Vo开始###############################################
{
Map voMap = new HashMap<>(2);
voMap.putAll(GeneratorUtil.getPageVoCode(generatorConfig, tableInfos, mainTable));
voMap.putAll(GeneratorUtil.getInfoVoCode(generatorConfig, tableInfos, mainTable));
for (Map.Entry entry : voMap.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getVoOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
//###############################################生成Vo结束###############################################
//---------------------------------------生成三层代码开始----------------------------------------------------
{
Map mapperCode = GeneratorUtil.getMapperCode(generatorConfig, tableInfos);
for (Map.Entry entry : mapperCode.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getMapperOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
{
Map serviceCode = GeneratorUtil.getServiceCode(generatorConfig, mainTable, tableInfos.size() > 1);
for (Map.Entry entry : serviceCode.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getServiceOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
{
Map serviceImplCode = GeneratorUtil.getServiceImplCode(generatorConfig, mainTable, tableInfos.size() > 1);
for (Map.Entry entry : serviceImplCode.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getServiceImplOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
{
Map controllerCode = GeneratorUtil.getControllerCode(generatorConfig, tableInfos, mainTable);
for (Map.Entry entry : controllerCode.entrySet()) {
GeneratorUtil.writeFile(GeneratorUtil.getControllerOutputDir(dirValue), entry.getKey() + StringPool.DOT_JAVA, entry.getValue());
}
}
//---------------------------------------生成三层代码结束----------------------------------------------------
}
}