lzq 2025-12-07 14:26:23 +08:00
parent 4d11980eed
commit 5920c3b8e4
13 changed files with 161 additions and 100 deletions

View File

@ -1,14 +1,9 @@
package com.njzscloud.common.gen;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.njzscloud.common.core.tuple.Tuple3;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.core.utils.Mime;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.gen.support.Generator;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.mvc.util.ServletUtil;
@ -17,10 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -63,56 +55,22 @@ public class TplController {
}
@PostMapping("/download")
public void download(@RequestParam("tplNames") String[] tplNames,
public void download(@RequestParam("lang") String lang,
@RequestParam("tableName") String tableName,
@RequestBody(required = false) Map<String, Object> data,
HttpServletResponse response) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
String[] paths = new String[tplNames.length];
InputStream[] ins = new InputStream[tplNames.length];
for (int i = 0; i < tplNames.length; i++) {
String tplName = tplNames[i];
Tuple3<String, String, String> res = Generator.generate(tplName, tableName, data);
String res0 = res.get_0();
String res1 = res.get_1();
String res2 = res.get_2();
StringBuilder pathBuilder = new StringBuilder();
if (StrUtil.isNotBlank(res0)) {
pathBuilder.append(res0);
if (!res0.endsWith("/")) pathBuilder.append("/");
}
if (StrUtil.isNotBlank(res1)) pathBuilder.append(res1);
else pathBuilder.append(IdUtil.fastSimpleUUID()).append(".txt");
paths[i] = pathBuilder.toString();
ins[i] = new ByteArrayInputStream(res2.getBytes());
}
ZipUtil.zip(out, paths, ins);
ByteArrayOutputStream out = tplService.download(lang, tableName, data);
ServletUtil.download(response, out.toByteArray(), Mime.ZIP, DateTime.now() + ".zip");
}
@PostMapping("/preview")
public R<?> preview(@RequestParam("tplNames") String[] tplNames,
public R<?> preview(@RequestParam("lang") String lang,
@RequestParam("tableName") String tableName,
@RequestBody(required = false) Map<String, Object> data) {
Map<String, Map<String, String>> map = new HashMap<>();
for (String tplName : tplNames) {
Tuple3<String, String, String> res = Generator.generate(tplName, tableName, data);
String res0 = res.get_0();
String res1 = res.get_1();
String res2 = res.get_2();
StringBuilder pathBuilder = new StringBuilder();
if (StrUtil.isNotBlank(res0)) {
pathBuilder.append(res0);
if (!res0.endsWith("/")) pathBuilder.append("/");
}
if (StrUtil.isNotBlank(res1)) pathBuilder.append(res1);
else pathBuilder.append(IdUtil.fastSimpleUUID()).append(".txt");
map.put(tplName, MapUtil.<String, String>builder()
.put("path", pathBuilder.toString())
.put("content", res2)
.build());
}
Map<String, Map<String, String>> map = tplService.preview(lang, tableName, data);
return R.success(map);
}
@ -120,18 +78,24 @@ public class TplController {
/**
*
*/
@GetMapping("/list_table")
public R<List<Map<String, Object>>> listTable(@RequestParam(value = "tableName", required = false) String tableName) {
return R.success(tplService.listTable(tableName));
@GetMapping("/table/paging")
public R<PageResult<Map<String, Object>>> tablePaging(PageParam pageParam,
@RequestParam(value = "tableSchema", required = false) String tableSchema,
@RequestParam(value = "tableName", required = false) String tableName
) {
return R.success(tplService.tablePaging(pageParam, tableSchema, tableName));
}
/**
*
*/
@GetMapping("/list")
public R<?> listAll() {
return R.success(tplService.list());
@GetMapping("/list_all")
public R<?> listAll(@RequestParam("lang") String lang) {
return R.success(tplService
.list(Wrappers.lambdaQuery(TplEntity.class)
.eq(TplEntity::getLang, lang)
.orderByAsc(TplEntity::getTplName)));
}

View File

@ -1,7 +1,14 @@
package com.njzscloud.common.gen;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.Map;
/**
*
@ -9,4 +16,8 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TplMapper extends BaseMapper<TplEntity> {
@Select("SELECT TABLE_SCHEMA tableSchema, TABLE_NAME tableName, TABLE_COMMENT tableComment\n" +
"FROM information_schema.TABLES\n" +
"${ew.customSqlSegment}")
IPage<Map<String, Object>> tablePaging(Page<Object> page, @Param("ew") QueryWrapper<Object> ew);
}

View File

@ -2,11 +2,17 @@ package com.njzscloud.common.gen;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.tuple.Tuple2;
import com.njzscloud.common.core.tuple.Tuple3;
import com.njzscloud.common.gen.support.DbMetaData;
import com.njzscloud.common.gen.support.Generator;
import com.njzscloud.common.gen.support.TemplateEngine;
import com.njzscloud.common.gen.support.Tpl;
import com.njzscloud.common.mp.support.PageParam;
@ -16,6 +22,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
@ -104,7 +113,74 @@ public class TplService extends ServiceImpl<TplMapper, TplEntity> implements ISe
private final DbMetaData dbMetaData;
public List<Map<String, Object>> listTable(String tableName) {
return dbMetaData.getTables(tableName);
public PageResult<Map<String, Object>> tablePaging(PageParam pageParam, String tableSchema, String tableName) {
pageParam.setOrders("TABLE_NAME");
if (StrUtil.isBlank(tableSchema)) {
tableSchema = dbMetaData.getDatabaseName();
}
Assert.notBlank(tableSchema, () -> Exceptions.exception("数据库名称获取失败"));
return PageResult.of(baseMapper.tablePaging(pageParam.toPage(), Wrappers.query()
.eq("TABLE_SCHEMA", tableSchema)
.like(StrUtil.isNotBlank(tableName), "TABLE_NAME", tableName)
));
}
public Map<String, Map<String, String>> preview(String lang, String tableName, Map<String, Object> data) {
Map<String, Map<String, String>> map = MapUtil.newHashMap();
List<String> tplNames = this.list(Wrappers.lambdaQuery(TplEntity.class)
.eq(TplEntity::getLang, lang))
.stream()
.map(TplEntity::getTplName)
.toList();
for (String tplName : tplNames) {
Tuple2<String, String> res = generate(tplName, tableName, data);
map.put(tplName, MapUtil.<String, String>builder()
.put("path", res.get_0())
.put("content", res.get_1())
.build());
}
return map;
}
public ByteArrayOutputStream download(String lang, String tableName, Map<String, Object> data) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
List<String> tplNames = this.list(Wrappers.lambdaQuery(TplEntity.class)
.eq(TplEntity::getLang, lang))
.stream()
.map(TplEntity::getTplName)
.toList();
if (tplNames.isEmpty()) {
return out;
}
int size = tplNames.size();
String[] paths = new String[size];
InputStream[] ins = new InputStream[size];
for (int i = 0; i < size; i++) {
String tplName = tplNames.get(i);
Tuple2<String, String> res = generate(tplName, tableName, data);
paths[i] = res.get_0();
ins[i] = new ByteArrayInputStream(res.get_1().getBytes());
}
ZipUtil.zip(out, paths, ins);
return out;
}
private Tuple2<String, String> generate(String tplName, String tableName, Map<String, Object> data) {
Tuple3<String, String, String> res = Generator.generate(tplName, tableName, data);
String res0 = res.get_0();
String res1 = res.get_1();
String res2 = res.get_2();
StringBuilder pathBuilder = new StringBuilder();
if (StrUtil.isNotBlank(res0)) {
pathBuilder.append(res0.trim());
if (!res0.endsWith("/")) pathBuilder.append("/");
}
if (StrUtil.isNotBlank(res1)) pathBuilder.append(res1.trim());
else pathBuilder.append(IdUtil.fastSimpleUUID()).append(".txt");
return Tuple2.of(pathBuilder.toString(), res2);
}
}

View File

@ -19,7 +19,16 @@ import java.util.Map;
public class DbMetaData {
private final DataSource dataSource;
public List<Map<String, Object>> getMetaData(String tableName) {
public String getDatabaseName() {
try (Connection conn = dataSource.getConnection()) {
return conn.getCatalog();
} catch (Exception e) {
log.error("获取数据库名称失败", e);
return null;
}
}
public List<Map<String, Object>> getTableMetaData(String tableName) {
try (Connection connection = dataSource.getConnection()) {
return getTables(connection, tableName);
} catch (Exception e) {
@ -71,23 +80,4 @@ public class DbMetaData {
return tableInfos;
}
public List<Map<String, Object>> getTables(String tableName) {
try (Connection connection = dataSource.getConnection()) {
List<Map<String, Object>> tableInfos = new ArrayList<>();
DatabaseMetaData metaData = connection.getMetaData();
try (ResultSet tablesData = metaData.getTables(null, null, StrUtil.isNotBlank(tableName) ? tableName : "%", new String[]{"TABLE"})) {
while (tablesData.next()) {
String tableName_ = tablesData.getString("TABLE_NAME");
tableInfos.add(MapUtil.<String, Object>builder()
.put("name", tableName_)
.put("comment", tablesData.getString("REMARKS"))
.build());
}
}
return tableInfos;
} catch (Exception e) {
log.error("获取数据库元数据失败", e);
return Collections.emptyList();
}
}
}

View File

@ -26,7 +26,7 @@ public class Generator {
Assert.notBlank(tableName, () -> Exceptions.clierr("未指定表名称"));
data.put("tableName", tableName);
List<Map<String, Object>> table = dbMetaData.getMetaData(tableName);
List<Map<String, Object>> table = dbMetaData.getTableMetaData(tableName);
TplEntity tplEntity = tplService.getOne(Wrappers.<TplEntity>lambdaQuery()
.eq(TplEntity::getTplName, tplName));

View File

@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import java.util.List;
import ${basePackage}.${moduleName}.pojo.entity.${entityClass};
import ${basePackage}.${moduleName}.service.${serviceClass};

View File

@ -8,7 +8,7 @@ var serviceInstance = entityName + "Service";
var mapperClass = upperFirst(entityName) + "Mapper";
var baseUrl = isBlank(prefix) ? table.name : subAfter(table.name, prefix);
%>
package ${basePackage}.${moduleName}.entity;
package ${basePackage}.${moduleName}.pojo.entity;
import lombok.Getter;
import lombok.Setter;
@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
import com.baomidou.mybatisplus.annotation.*;
import lombok.ToString;
<%for(column in table.columns) {
var map = sqlDataTypeMap(column.dataType);
var map = javaType(column.dataType);
%>
<%if(!isBlank(map.importStatement)){%>
${map.importStatement}

View File

@ -10,7 +10,6 @@ var baseUrl = isBlank(prefix) ? table.name : subAfter(table.name, prefix);
%>
package ${basePackage}.${moduleName}.service;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -20,6 +19,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import java.util.List;
import ${basePackage}.${moduleName}.pojo.entity.${entityClass};
import ${basePackage}.${moduleName}.mapper.${mapperClass};

View File

@ -4,7 +4,7 @@ var lcc = toCamelCase(ulc);
var ucc = upperFirst(lcc);
var dc = toDashCase(lcc);
var pageVueName = ucc + "vue";
var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts";
var apiTsName = dc + "-api.ts";

View File

@ -4,7 +4,7 @@ var lcc = toCamelCase(ulc);
var ucc = upperFirst(lcc);
var dc = toDashCase(lcc);
var pageVueName = ucc + "vue";
var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts";
var apiTsName = dc + "-api.ts";

View File

@ -4,7 +4,7 @@ var lcc = toCamelCase(ulc);
var ucc = upperFirst(lcc);
var dc = toDashCase(lcc);
var pageVueName = ucc + "vue";
var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts";
var apiTsName = dc + "-api.ts";
@ -14,17 +14,20 @@ var dTsName = dc + ".d.ts";
<ElDialog v-model="showDialog"
:close-on-click-modal="false"
destroy-on-close
width="25vw">
<ElForm :model="${lcc}FormData"
class="${dc}-form"
width="fit-content"
ref="${lcc}Form"
@close="dialogCloseHandler">
<ElForm :model="formData"
:rules="rules"
class="form-panel"
label-width="auto">
<%
for(column in table.columns) {
var map = tsType(column.dataType);
%>
<ElFormItem label="${column.comment}">
<ElFormItem label="${column.comment}" prop="${toCamelCase(column.name)}">
<ElInput
v-model="${lcc}FormData.${toCamelCase(column.name)}"
v-model="formData.${toCamelCase(column.name)}"
:disabled="status === 'view'"
placeholder="${column.comment}"/>
</ElFormItem>
@ -40,21 +43,38 @@ var dTsName = dc + ".d.ts";
<script lang="ts" setup>
import ${ucc}Api from '@/pages/${moduleName}<%if(subModuleName != null){%>/${subModuleName}<%}%>/${apiTsName}'
import Strings from '@/common/utils/strings.ts'
import { ElMessage } from 'element-plus'
import FormUtil from '@/common/utils/formUtil.ts'
import {
ElMessage,
type FormInstance,
type FormRules,
} from 'element-plus'
const emits = defineEmits(['editSucc'])
const showDialog = ref(false)
const submiting = ref(false)
const status = ref<'add' | 'view' | 'modify'>('add')
const ${lcc}FormIns = useTemplateRef<FormInstance>('${lcc}Form')
const ${lcc}FormData = reactive<${ucc}Types.Search${ucc}Result>({})
const formData = ref<${ucc}Types.Search${ucc}Result>({})
const rules = reactive<FormRules<${ucc}Types.Search${ucc}Result>>({
<%
for(column in table.columns) {
%>
${toCamelCase(column.name)}: [{ required: true, message: '请填写${column.comment}', trigger: 'blur' }],
<%}%>
})
function dialogCloseHandler() {
formData.vaule = {}
}
function submitHandler() {
if (status.value === 'view') return
submiting.value = true
if (${lcc}FormData.id != null) {
${ucc}Api.modify(${lcc}FormData)
if (formData.vaule.id != null) {
FormUtil.submit(${lcc}FormIns, () => ${ucc}Api.modify(formData.vaule))
.then(() => {
ElMessage.success('修改成功')
emits('editSucc')
@ -64,7 +84,7 @@ function submitHandler() {
submiting.value = false
})
} else {
${ucc}Api.add(${lcc}FormData)
FormUtil.submit(${lcc}FormIns, () => ${ucc}Api.add(formData.vaule))
.then(() => {
ElMessage.success('添加成功')
emits('editSucc')
@ -83,18 +103,18 @@ defineExpose({
status.value = 'modify'
${ucc}Api.detail(data.id!)
.then(res => {
Object.assign(${lcc}FormData, res.data)
formData.vaule = res.data
})
} else {
status.value = 'add'
Object.assign(${lcc}FormData, {})
formData.vaule = data
}
}
})
</script>
<style lang="stylus" scoped>
.${dc}-form {
.form-panel {
padding 20px
}
</style>

View File

@ -4,7 +4,7 @@ var lcc = toCamelCase(ulc);
var ucc = upperFirst(lcc);
var dc = toDashCase(lcc);
var pageVueName = ucc + "vue";
var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts";
var apiTsName = dc + "-api.ts";

View File

@ -4,7 +4,7 @@ var lcc = toCamelCase(ulc);
var ucc = upperFirst(lcc);
var dc = toDashCase(lcc);
var pageVueName = ucc + "vue";
var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts";
var apiTsName = dc + "-api.ts";
@ -74,7 +74,6 @@ var dTsName = dc + ".d.ts";
:total="pagination.total"
@change="pageChangeHandler"/>
<${ucc}Form ref="${lcc}Form" @edit-succ="paging"/>
</Page>
</template>