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; package com.njzscloud.common.gen;
import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.njzscloud.common.core.utils.Mime; import com.njzscloud.common.core.utils.Mime;
import com.njzscloud.common.core.utils.R; 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.PageParam;
import com.njzscloud.common.mp.support.PageResult; import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.mvc.util.ServletUtil; import com.njzscloud.common.mvc.util.ServletUtil;
@ -17,10 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -63,56 +55,22 @@ public class TplController {
} }
@PostMapping("/download") @PostMapping("/download")
public void download(@RequestParam("tplNames") String[] tplNames, public void download(@RequestParam("lang") String lang,
@RequestParam("tableName") String tableName, @RequestParam("tableName") String tableName,
@RequestBody(required = false) Map<String, Object> data, @RequestBody(required = false) Map<String, Object> data,
HttpServletResponse response) { 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"); ServletUtil.download(response, out.toByteArray(), Mime.ZIP, DateTime.now() + ".zip");
} }
@PostMapping("/preview") @PostMapping("/preview")
public R<?> preview(@RequestParam("tplNames") String[] tplNames, public R<?> preview(@RequestParam("lang") String lang,
@RequestParam("tableName") String tableName, @RequestParam("tableName") String tableName,
@RequestBody(required = false) Map<String, Object> data) { @RequestBody(required = false) Map<String, Object> data) {
Map<String, Map<String, String>> map = new HashMap<>();
for (String tplName : tplNames) { Map<String, Map<String, String>> map = tplService.preview(lang, tableName, 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);
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());
}
return R.success(map); return R.success(map);
} }
@ -120,18 +78,24 @@ public class TplController {
/** /**
* *
*/ */
@GetMapping("/list_table") @GetMapping("/table/paging")
public R<List<Map<String, Object>>> listTable(@RequestParam(value = "tableName", required = false) String tableName) { public R<PageResult<Map<String, Object>>> tablePaging(PageParam pageParam,
return R.success(tplService.listTable(tableName)); @RequestParam(value = "tableSchema", required = false) String tableSchema,
@RequestParam(value = "tableName", required = false) String tableName
) {
return R.success(tplService.tablePaging(pageParam, tableSchema, tableName));
} }
/** /**
* *
*/ */
@GetMapping("/list") @GetMapping("/list_all")
public R<?> listAll() { public R<?> listAll(@RequestParam("lang") String lang) {
return R.success(tplService.list()); 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; 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.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.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 @Mapper
public interface TplMapper extends BaseMapper<TplEntity> { 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.lang.Assert;
import cn.hutool.core.map.MapUtil; 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.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions; 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.DbMetaData;
import com.njzscloud.common.gen.support.Generator;
import com.njzscloud.common.gen.support.TemplateEngine; import com.njzscloud.common.gen.support.TemplateEngine;
import com.njzscloud.common.gen.support.Tpl; import com.njzscloud.common.gen.support.Tpl;
import com.njzscloud.common.mp.support.PageParam; import com.njzscloud.common.mp.support.PageParam;
@ -16,6 +22,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; 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.List;
import java.util.Map; import java.util.Map;
@ -104,7 +113,74 @@ public class TplService extends ServiceImpl<TplMapper, TplEntity> implements ISe
private final DbMetaData dbMetaData; private final DbMetaData dbMetaData;
public List<Map<String, Object>> listTable(String tableName) { public PageResult<Map<String, Object>> tablePaging(PageParam pageParam, String tableSchema, String tableName) {
return dbMetaData.getTables(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 { public class DbMetaData {
private final DataSource dataSource; 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()) { try (Connection connection = dataSource.getConnection()) {
return getTables(connection, tableName); return getTables(connection, tableName);
} catch (Exception e) { } catch (Exception e) {
@ -71,23 +80,4 @@ public class DbMetaData {
return tableInfos; 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("未指定表名称")); Assert.notBlank(tableName, () -> Exceptions.clierr("未指定表名称"));
data.put("tableName", tableName); 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() TplEntity tplEntity = tplService.getOne(Wrappers.<TplEntity>lambdaQuery()
.eq(TplEntity::getTplName, tplName)); .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.core.utils.R;
import com.njzscloud.common.mp.support.PageParam; import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult; import com.njzscloud.common.mp.support.PageResult;
import java.util.List;
import ${basePackage}.${moduleName}.pojo.entity.${entityClass}; import ${basePackage}.${moduleName}.pojo.entity.${entityClass};
import ${basePackage}.${moduleName}.service.${serviceClass}; import ${basePackage}.${moduleName}.service.${serviceClass};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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