Commit 0c8f92fa959e08f34d4a721245891fef5c38ec20

Authored by YunaiV
1 parent 937c51f4

基本完成代码生成器

ruoyi-ui/src/api/tool/testDemo.js
... ... @@ -22,7 +22,7 @@ export function updateTestDemo(data) {
22 22 // 删除字典类型
23 23 export function deleteTestDemo(id) {
24 24 return request({
25   - url: '/tool/test-demo/delelte?id=' + id,
  25 + url: '/tool/test-demo/delete?id=' + id,
26 26 method: 'delete'
27 27 })
28 28 }
... ... @@ -50,6 +50,6 @@ export function exportTestDemoExcel(query) {
50 50 url: '/tool/test-demo/export-excel',
51 51 method: 'get',
52 52 params: query,
53   - reponseBody: 'blob'
  53 + responseType: 'blob'
54 54 })
55 55 }
... ...
ruoyi-ui/src/utils/ruoyi.js
... ... @@ -93,7 +93,7 @@ export function addBeginAndEndTime(params, dateRange, propName) {
93 93 params['begin' + propName] = dateRange[0] + ' 00:00:00';
94 94 }
95 95 if (dateRange[1]) {
96   - params['end' + propName] = dateRange[0] + ' 23:59:59';
  96 + params['end' + propName] = dateRange[1] + ' 23:59:59';
97 97 }
98 98 return params;
99 99 }
... ...
ruoyi-ui/src/views/system/menu/index.vue
... ... @@ -160,14 +160,10 @@
160 160 </el-form-item>
161 161 </el-col>
162 162 <el-col :span="12">
163   - <el-form-item v-if="form.type != '3'" label="菜单状态">
  163 + <el-form-item label="菜单状态">
164 164 <el-radio-group v-model="form.status">
165   - <el-radio
166   - v-for="dict in statusDictDatas"
167   - :key="parseInt(dict.value)"
168   - :label="dict.label"
169   - :value="parseInt(dict.value)"
170   - >{{dict.label}}</el-radio>
  165 + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
  166 + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
171 167 </el-radio-group>
172 168 </el-form-item>
173 169 </el-col>
... ...
ruoyi-ui/src/views/tool/gen/editTable.vue
... ... @@ -129,6 +129,7 @@
129 129 import { getCodegenDetail, updateCodegen } from "@/api/tool/codegen";
130 130 import { listAllSimple as listAllSimpleDictType } from "@/api/system/dict/type";
131 131 import { listMenu as getMenuTreeselect } from "@/api/system/menu";
  132 +import { listSimpleMenus } from "@/api/system/menu";
132 133 import basicInfoForm from "./basicInfoForm";
133 134 import genInfoForm from "./genInfoForm";
134 135 import Sortable from 'sortablejs'
... ... @@ -170,8 +171,9 @@ export default {
170 171 this.dictOptions = response.data;
171 172 });
172 173 /** 查询菜单下拉列表 */
173   - getMenuTreeselect().then(response => {
174   - this.menus = this.handleTree(response.data, "menuId");
  174 + listSimpleMenus().then(response => {
  175 + this.menus = [];
  176 + this.menus.push(...this.handleTree(response.data, "id"));
175 177 });
176 178 }
177 179 },
... ...
ruoyi-ui/src/views/tool/gen/genInfoForm.vue
... ... @@ -51,17 +51,17 @@
51 51 </el-form-item>
52 52 </el-col>
53 53  
54   - <el-col :span="12">
55   - <el-form-item prop="businessPackage">
56   - <span slot="label">
57   - 业务包
58   - <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">
59   - <i class="el-icon-question"></i>
60   - </el-tooltip>
61   - </span>
62   - <el-input v-model="info.businessPackage" />
63   - </el-form-item>
64   - </el-col>
  54 +<!-- <el-col :span="12">-->
  55 +<!-- <el-form-item prop="businessPackage">-->
  56 +<!-- <span slot="label">-->
  57 +<!-- 业务包-->
  58 +<!-- <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">-->
  59 +<!-- <i class="el-icon-question"></i>-->
  60 +<!-- </el-tooltip>-->
  61 +<!-- </span>-->
  62 +<!-- <el-input v-model="info.businessPackage" />-->
  63 +<!-- </el-form-item>-->
  64 +<!-- </el-col>-->
65 65  
66 66 <el-col :span="12">
67 67 <el-form-item prop="className">
... ... @@ -95,14 +95,8 @@
95 95 <i class="el-icon-question"></i>
96 96 </el-tooltip>
97 97 </span>
98   - <treeselect
99   - :append-to-body="true"
100   - v-model="info.parentMenuId"
101   - :options="menus"
102   - :normalizer="normalizer"
103   - :show-count="true"
104   - placeholder="请选择系统菜单"
105   - />
  98 + <treeselect :append-to-body="true" v-model="info.parentMenuId" :options="menus"
  99 + :normalizer="normalizer" :show-count="true" placeholder="请选择系统菜单" />
106 100 </el-form-item>
107 101 </el-col>
108 102  
... ... @@ -289,8 +283,8 @@ export default {
289 283 delete node.children;
290 284 }
291 285 return {
292   - id: node.menuId,
293   - label: node.menuName,
  286 + id: node.id,
  287 + label: node.name,
294 288 children: node.children
295 289 };
296 290 },
... ...
ruoyi-ui/src/views/tool/testDemo/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="名字" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入名字" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="状态" prop="status">
  10 + <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
  11 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
  12 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  13 + </el-select>
  14 + </el-form-item>
  15 + <el-form-item label="类型" prop="type">
  16 + <el-select v-model="queryParams.type" placeholder="请选择类型" clearable size="small">
  17 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)"
  18 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  19 + </el-select>
  20 + </el-form-item>
  21 + <el-form-item label="分类" prop="category">
  22 + <el-select v-model="queryParams.category" placeholder="请选择分类" clearable size="small">
  23 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INF_REDIS_TIMEOUT_TYPE)"
  24 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  25 + </el-select>
  26 + </el-form-item>
  27 + <el-form-item label="备注" prop="remark">
  28 + <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable size="small" @keyup.enter.native="handleQuery"/>
  29 + </el-form-item>
  30 + <el-form-item label="创建时间">
  31 + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  32 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  33 + </el-form-item>
  34 + <el-form-item label="是否删除" prop="deleted">
  35 + <el-select v-model="queryParams.deleted" placeholder="请选择是否删除" clearable size="small">
  36 + <el-option label="请选择字典生成" value="" />
  37 + </el-select>
  38 + </el-form-item>
  39 + <el-form-item>
  40 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  41 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  42 + </el-form-item>
  43 + </el-form>
  44 +
  45 + <!-- 操作工具栏 -->
  46 + <el-row :gutter="10" class="mb8">
  47 + <el-col :span="1.5">
  48 + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
  49 + v-hasPermi="['tool:test-demo:create']">新增</el-button>
  50 + </el-col>
  51 + <el-col :span="1.5">
  52 + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
  53 + v-hasPermi="['tool:test-demo:export']">导出</el-button>
  54 + </el-col>
  55 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  56 + </el-row>
  57 +
  58 + <!-- 列表 -->
  59 + <el-table v-loading="loading" :data="list">
  60 + <el-table-column label="编号" align="center" prop="id" />
  61 + <el-table-column label="名字" align="center" prop="name" />
  62 + <el-table-column label="状态" align="center" prop="status">
  63 + <template slot-scope="scope">
  64 + <span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
  65 + </template>
  66 + </el-table-column>>
  67 + <el-table-column label="类型" align="center" prop="type">
  68 + <template slot-scope="scope">
  69 + <span>{{ getDictDataLabel(DICT_TYPE.SYS_OPERATE_TYPE, scope.row.type) }}</span>
  70 + </template>
  71 + </el-table-column>>
  72 + <el-table-column label="分类" align="center" prop="category">
  73 + <template slot-scope="scope">
  74 + <span>{{ getDictDataLabel(DICT_TYPE.INF_REDIS_TIMEOUT_TYPE, scope.row.category) }}</span>
  75 + </template>
  76 + </el-table-column>>
  77 + <el-table-column label="备注" align="center" prop="remark" />
  78 + <el-table-column label="创建时间" align="center" prop="createTime" width="180">
  79 + <template slot-scope="scope">
  80 + <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
  81 + </template>
  82 + </el-table-column>
  83 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  84 + <template slot-scope="scope">
  85 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
  86 + v-hasPermi="['tool:test-demo:update']">修改</el-button>
  87 + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
  88 + v-hasPermi="['tool:test-demo:delete']">删除</el-button>
  89 + </template>
  90 + </el-table-column>
  91 + </el-table>
  92 + <!-- 分页组件 -->
  93 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  94 + @pagination="getList"/>
  95 +
  96 + <!-- 对话框(添加 / 修改) -->
  97 + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  98 + <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  99 + <el-form-item label="名字" prop="name">
  100 + <el-input v-model="form.name" placeholder="请输入名字" />
  101 + </el-form-item>
  102 + <el-form-item label="状态">
  103 + <el-radio-group v-model="form.status">
  104 + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
  105 + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
  106 + </el-radio-group>
  107 + </el-form-item>
  108 + <el-form-item label="类型" prop="type">
  109 + <el-select v-model="form.type" placeholder="请选择类型">
  110 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)"
  111 + :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" />
  112 + </el-select>
  113 + </el-form-item>
  114 + <el-form-item label="分类">
  115 + <el-radio-group v-model="form.category">
  116 + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.INF_REDIS_TIMEOUT_TYPE)"
  117 + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
  118 + </el-radio-group>
  119 + </el-form-item>
  120 + <el-form-item label="备注" prop="remark">
  121 + <el-input v-model="form.remark" placeholder="请输入备注" />
  122 + </el-form-item>
  123 + </el-form>
  124 + <div slot="footer" class="dialog-footer">
  125 + <el-button type="primary" @click="submitForm">确 定</el-button>
  126 + <el-button @click="cancel">取 消</el-button>
  127 + </div>
  128 + </el-dialog>
  129 + </div>
  130 +</template>
  131 +
  132 +<script>
  133 +import { createTestDemo, updateTestDemo, deleteTestDemo, getTestDemo, getTestDemoPage, exportTestDemoExcel } from "@/api/tool/testDemo";
  134 +
  135 +export default {
  136 + name: "TestDemo",
  137 + components: {
  138 + },
  139 + data() {
  140 + return {
  141 + // 遮罩层
  142 + loading: true,
  143 + // 显示搜索条件
  144 + showSearch: true,
  145 + // 总条数
  146 + total: 0,
  147 + // 测试示例列表
  148 + list: [],
  149 + // 弹出层标题
  150 + title: "",
  151 + // 是否显示弹出层
  152 + open: false,
  153 + dateRangeCreateTime: [],
  154 + // 查询参数
  155 + queryParams: {
  156 + pageNo: 1,
  157 + pageSize: 10,
  158 + name: null,
  159 + status: null,
  160 + type: null,
  161 + category: null,
  162 + remark: null,
  163 + deleted: null,
  164 + },
  165 + // 表单参数
  166 + form: {},
  167 + // 表单校验
  168 + rules: {
  169 + name: [{ required: true, message: "名字不能为空", trigger: "blur" }],
  170 + status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
  171 + type: [{ required: true, message: "类型不能为空", trigger: "change" }],
  172 + category: [{ required: true, message: "分类不能为空", trigger: "blur" }],
  173 + }
  174 + };
  175 + },
  176 + created() {
  177 + this.getList();
  178 + },
  179 + methods: {
  180 + /** 查询列表 */
  181 + getList() {
  182 + this.loading = true;
  183 + let params = {...this.queryParams};
  184 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  185 + // 执行查询
  186 + getTestDemoPage(params).then(response => {
  187 + this.list = response.data.list;
  188 + this.total = response.data.total;
  189 + this.loading = false;
  190 + });
  191 + },
  192 + // 取消按钮
  193 + cancel() {
  194 + this.open = false;
  195 + this.reset();
  196 + },
  197 + // 表单重置
  198 + reset() {
  199 + this.form = {
  200 + id: undefined,
  201 + name: undefined,
  202 + status: undefined,
  203 + type: undefined,
  204 + category: undefined,
  205 + remark: undefined,
  206 + createBy: undefined,
  207 + createTime: undefined,
  208 + updateBy: undefined,
  209 + updateTime: undefined,
  210 + deleted: undefined,
  211 + };
  212 + this.resetForm("form");
  213 + },
  214 + /** 搜索按钮操作 */
  215 + handleQuery() {
  216 + this.queryParams.pageNo = 1;
  217 + this.getList();
  218 + },
  219 + /** 重置按钮操作 */
  220 + resetQuery() {
  221 + this.dateRangeCreateTime = [];
  222 + this.resetForm("queryForm");
  223 + this.handleQuery();
  224 + },
  225 + /** 新增按钮操作 */
  226 + handleAdd() {
  227 + this.reset();
  228 + this.open = true;
  229 + this.title = "添加测试示例";
  230 + },
  231 + /** 修改按钮操作 */
  232 + handleUpdate(row) {
  233 + this.reset();
  234 + const id = row.id;
  235 + getTestDemo(id).then(response => {
  236 + this.form = response.data;
  237 + this.open = true;
  238 + this.title = "修改测试示例";
  239 + });
  240 + },
  241 + /** 提交按钮 */
  242 + submitForm() {
  243 + this.$refs["form"].validate(valid => {
  244 + if (!valid) {
  245 + return;
  246 + }
  247 + // 修改的提交
  248 + if (this.form.id != null) {
  249 + updateTestDemo(this.form).then(response => {
  250 + this.msgSuccess("修改成功");
  251 + this.open = false;
  252 + this.getList();
  253 + });
  254 + return;
  255 + }
  256 + // 添加的提交
  257 + createTestDemo(this.form).then(response => {
  258 + this.msgSuccess("新增成功");
  259 + this.open = false;
  260 + this.getList();
  261 + });
  262 + });
  263 + },
  264 + /** 删除按钮操作 */
  265 + handleDelete(row) {
  266 + const id = row.id;
  267 + this.$confirm('是否确认删除测试示例编号为"' + id + '"的数据项?', "警告", {
  268 + confirmButtonText: "确定",
  269 + cancelButtonText: "取消",
  270 + type: "warning"
  271 + }).then(function() {
  272 + return deleteTestDemo(id);
  273 + }).then(() => {
  274 + this.getList();
  275 + this.msgSuccess("删除成功");
  276 + })
  277 + },
  278 + /** 导出按钮操作 */
  279 + handleExport() {
  280 + let params = {...this.queryParams};
  281 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  282 + this.$confirm('是否确认导出所有测试示例数据项?', "警告", {
  283 + confirmButtonText: "确定",
  284 + cancelButtonText: "取消",
  285 + type: "warning"
  286 + }).then(function() {
  287 + return exportTestDemoExcel(params);
  288 + }).then(response => {
  289 + this.downloadExcel(response, '测试示例.xls');
  290 + })
  291 + }
  292 + }
  293 +};
  294 +</script>
... ...
src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java
... ... @@ -44,14 +44,19 @@ public class DictConvert implements Converter&lt;Object&gt; {
44 44  
45 45 @Override
46 46 public CellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,
47   - GlobalConfiguration globalConfiguration) {
  47 + GlobalConfiguration globalConfiguration) {
  48 + // 空时,返回空
  49 + if (object == null) {
  50 + return new CellData<>("");
  51 + }
  52 +
48 53 // 使用字典格式化
49 54 SysDictTypeEnum type = getType(contentProperty);
50 55 String value = String.valueOf(object);
51 56 SysDictDataDO dictData = DictUtils.getDictDataFromCache(type.getValue(), value);
52 57 if (dictData == null) {
53 58 log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
54   - return null;
  59 + return new CellData<>("");
55 60 }
56 61 // 生成 Excel 小表格
57 62 return new CellData<>(dictData.getLabel());
... ...
src/main/java/cn/iocoder/dashboard/framework/excel/core/package-info.java deleted
1   -package cn.iocoder.dashboard.framework.excel.core;
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/menu/SysMenuBaseVO.java
... ... @@ -42,11 +42,12 @@ public class SysMenuBaseVO {
42 42 @ApiModelProperty(value = "菜单图标", example = "/menu/list", notes = "仅菜单类型为菜单或者目录时,才需要传")
43 43 private String icon;
44 44  
45   - /**
46   - * 组件路径
47   - */
48 45 @ApiModelProperty(value = "组件路径", example = "system/post/index", notes = "仅菜单类型为菜单时,才需要传")
49 46 @Size(max = 200, message = "组件路径不能超过255个字符")
50 47 private String component;
51 48  
  49 + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举")
  50 + @NotNull(message = "状态不能为空")
  51 + private Integer status;
  52 +
52 53 }
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java
... ... @@ -51,7 +51,6 @@ public class ToolCodegenController {
51 51 @ApiImplicitParam(name = "tableName", required = true, example = "yudao", dataTypeClass = String.class),
52 52 @ApiImplicitParam(name = "tableComment", required = true, example = "芋道", dataTypeClass = String.class)
53 53 })
54   -// @PreAuthorize("@ss.hasPermi('tool:gen:list')") TODO 权限
55 54 public CommonResult<List<ToolSchemaTableRespVO>> getSchemaTableList(
56 55 @RequestParam(value = "tableName", required = false) String tableName,
57 56 @RequestParam(value = "tableComment", required = false) String tableComment) {
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTableBaseVO.java
... ... @@ -31,10 +31,6 @@ public class ToolCodegenTableBaseVO {
31 31 @NotNull(message = "业务名不能为空")
32 32 private String businessName;
33 33  
34   - @ApiModelProperty(value = "业务包", required = true, example = "codegen")
35   - @NotNull(message = "业务包不能为空")
36   - private String businessPackage;
37   -
38 34 @ApiModelProperty(value = "类名称", required = true, example = "ToolCodegenTable")
39 35 @NotNull(message = "类名称不能为空")
40 36 private String className;
... ... @@ -51,4 +47,7 @@ public class ToolCodegenTableBaseVO {
51 47 @NotNull(message = "模板类型不能为空")
52 48 private Integer templateType;
53 49  
  50 + @ApiModelProperty(value = "父菜单编号", example = "1024")
  51 + private Long parentMenuId;
  52 +
54 53 }
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.tool.controller.test;
3 3 import cn.iocoder.dashboard.common.pojo.CommonResult;
4 4 import cn.iocoder.dashboard.common.pojo.PageResult;
5 5 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
  6 +import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
6 7 import cn.iocoder.dashboard.modules.tool.controller.test.vo.*;
7 8 import cn.iocoder.dashboard.modules.tool.convert.test.ToolTestDemoConvert;
8 9 import cn.iocoder.dashboard.modules.tool.dal.dataobject.test.ToolTestDemoDO;
... ... @@ -10,6 +11,7 @@ import cn.iocoder.dashboard.modules.tool.service.test.ToolTestDemoService;
10 11 import io.swagger.annotations.Api;
11 12 import io.swagger.annotations.ApiImplicitParam;
12 13 import io.swagger.annotations.ApiOperation;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
13 15 import org.springframework.validation.annotation.Validated;
14 16 import org.springframework.web.bind.annotation.*;
15 17  
... ... @@ -21,8 +23,9 @@ import java.util.Collection;
21 23 import java.util.List;
22 24  
23 25 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
  26 +import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
24 27  
25   -@Api(tags = "字典类型")
  28 +@Api(tags = "测试示例")
26 29 @RestController
27 30 @RequestMapping("/tool/test-demo")
28 31 @Validated
... ... @@ -31,58 +34,66 @@ public class ToolTestDemoController {
31 34 @Resource
32 35 private ToolTestDemoService testDemoService;
33 36  
34   - @ApiOperation("创建字典类型")
35 37 @PostMapping("/create")
36   - public CommonResult<Long> createTestDemo(@Valid ToolTestDemoCreateReqVO createReqVO) {
  38 + @ApiOperation("创建测试示例")
  39 + @PreAuthorize("@ss.hasPermission('tool:test-demo:create')")
  40 + public CommonResult<Long> createTestDemo(@Valid @RequestBody ToolTestDemoCreateReqVO createReqVO) {
37 41 return success(testDemoService.createTestDemo(createReqVO));
38 42 }
39 43  
40   - @ApiOperation("更新字典类型")
41 44 @PutMapping("/update")
42   - public CommonResult<Boolean> updateTestDemo(@Valid ToolTestDemoUpdateReqVO updateReqVO) {
  45 + @ApiOperation("更新测试示例")
  46 + @PreAuthorize("@ss.hasPermission('tool:test-demo:update')")
  47 + public CommonResult<Boolean> updateTestDemo(@Valid @RequestBody ToolTestDemoUpdateReqVO updateReqVO) {
43 48 testDemoService.updateTestDemo(updateReqVO);
44 49 return success(true);
45 50 }
46 51  
47   - @ApiOperation("删除字典类型")
48 52 @DeleteMapping("/delete")
  53 + @ApiOperation("删除测试示例")
49 54 @ApiImplicitParam(name = "id", value = "编号", required = true)
  55 + @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')")
50 56 public CommonResult<Boolean> deleteTestDemo(@RequestParam("id") Long id) {
51 57 testDemoService.deleteTestDemo(id);
52 58 return success(true);
53 59 }
54 60  
55 61 @GetMapping("/get")
56   - @ApiOperation("获得字典类型")
  62 + @ApiOperation("获得测试示例")
57 63 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  64 + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")
58 65 public CommonResult<ToolTestDemoRespVO> getTestDemo(@RequestParam("id") Long id) {
59 66 ToolTestDemoDO testDemo = testDemoService.getTestDemo(id);
60 67 return success(ToolTestDemoConvert.INSTANCE.convert(testDemo));
61 68 }
62 69  
63 70 @GetMapping("/list")
64   - @ApiOperation("获得字典类型列表")
  71 + @ApiOperation("获得测试示例列表")
65 72 @ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class)
  73 + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")
66 74 public CommonResult<List<ToolTestDemoRespVO>> getTestDemoList(@RequestParam("ids") Collection<Long> ids) {
67 75 List<ToolTestDemoDO> list = testDemoService.getTestDemoList(ids);
68 76 return success(ToolTestDemoConvert.INSTANCE.convertList(list));
69 77 }
70 78  
71   - @ApiOperation("获得字典类型分页")
72 79 @GetMapping("/page")
  80 + @ApiOperation("获得测试示例分页")
  81 + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")
73 82 public CommonResult<PageResult<ToolTestDemoRespVO>> getTestDemoPage(@Valid ToolTestDemoPageReqVO pageVO) {
74 83 PageResult<ToolTestDemoDO> pageResult = testDemoService.getTestDemoPage(pageVO);
75 84 return success(ToolTestDemoConvert.INSTANCE.convertPage(pageResult));
76 85 }
77 86  
78 87 @GetMapping("/export-excel")
79   - @ApiOperation("导出字典类型 Excel")
  88 + @ApiOperation("导出测试示例 Excel")
  89 + @PreAuthorize("@ss.hasPermission('tool:test-demo:export')")
  90 + @OperateLog(type = EXPORT)
80 91 public void exportTestDemoExcel(@Valid ToolTestDemoExportReqVO exportReqVO,
81 92 HttpServletResponse response) throws IOException {
82 93 List<ToolTestDemoDO> list = testDemoService.getTestDemoList(exportReqVO);
83 94 // 导出 Excel
84 95 List<ToolTestDemoExcelVO> datas = ToolTestDemoConvert.INSTANCE.convertList02(list);
85   - ExcelUtils.write(response, "字典类型.xls", "数据", ToolTestDemoExcelVO.class, datas);
  96 + ExcelUtils.write(response, "测试示例.xls", "数据", ToolTestDemoExcelVO.class, datas);
86 97 }
87 98  
88 99 }
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java
1 1 package cn.iocoder.dashboard.modules.tool.controller.test.vo;
2 2  
3 3 import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
4 5 import com.alibaba.excel.annotation.ExcelProperty;
5 6 import lombok.Data;
6 7  
... ... @@ -9,7 +10,7 @@ import java.util.Date;
9 10 import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.*;
10 11  
11 12 /**
12   - * 字典类型 Excel VO
  13 + * 测试示例 Excel VO
13 14 *
14 15 * @author 芋艿
15 16 */
... ... @@ -22,15 +23,15 @@ public class ToolTestDemoExcelVO {
22 23 @ExcelProperty("名字")
23 24 private String name;
24 25  
25   - @ExcelProperty("状态")
  26 + @ExcelProperty(value = "状态", converter = DictConvert.class)
26 27 @DictFormat(SYS_COMMON_STATUS)
27 28 private Integer status;
28 29  
29   - @ExcelProperty("类型")
  30 + @ExcelProperty(value = "类型", converter = DictConvert.class)
30 31 @DictFormat(SYS_OPERATE_TYPE)
31 32 private Integer type;
32 33  
33   - @ExcelProperty("分类")
  34 + @ExcelProperty(value = "分类", converter = DictConvert.class)
34 35 @DictFormat(INF_REDIS_TIMEOUT_TYPE)
35 36 private Integer category;
36 37  
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/codegen/ToolCodegenTableDO.java
... ... @@ -54,14 +54,6 @@ public class ToolCodegenTableDO extends BaseDO {
54 54 */
55 55 private String businessName;
56 56 /**
57   - * 业务包,自定义二级目录
58   - *
59   - * 例如说,我们希望将 dictType 和 dictData 归类成 dict 业务
60   - *
61   - * 如果不需要的情况下,businessName 和 businessPackage 是等价的
62   - */
63   - private String businessPackage;
64   - /**
65 57 * 类名称(首字母大写)
66 58 *
67 59 * 例如说,SysUser、SysMenu、SysDictData 等等
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenBuilder.java
... ... @@ -128,7 +128,6 @@ public class ToolCodegenBuilder {
128 128 '_', false))); // 第一个 _ 前缀的前面,作为 module 名字
129 129 table.setBusinessName(toCamelCase(subAfter(table.getTableName(),
130 130 '_', false))); // 第一步,第一个 _ 前缀的后面,作为 module 名字; 第二步,可能存在多个 _ 的情况,转换成驼峰
131   - table.setBusinessPackage(table.getBusinessPackage());
132 131 table.setClassName(upperFirst(toCamelCase(table.getTableName()))); // 驼峰 + 首字母大写
133 132 table.setClassComment(subBefore(table.getTableComment(), // 去除结尾的表,作为类描述
134 133 '表', true));
... ...
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java
... ... @@ -11,6 +11,7 @@ import cn.iocoder.dashboard.common.pojo.PageParam;
11 11 import cn.iocoder.dashboard.common.pojo.PageResult;
12 12 import cn.iocoder.dashboard.framework.codegen.config.CodegenProperties;
13 13 import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
  14 +import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
14 15 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
15 16 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
16 17 import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum;
... ... @@ -27,11 +28,9 @@ import org.springframework.stereotype.Component;
27 28  
28 29 import javax.annotation.PostConstruct;
29 30 import javax.annotation.Resource;
30   -import java.util.HashMap;
31   -import java.util.LinkedHashMap;
32   -import java.util.List;
33   -import java.util.Map;
  31 +import java.util.*;
34 32  
  33 +import static cn.hutool.core.map.MapUtil.getStr;
35 34 import static cn.hutool.core.text.CharSequenceUtil.*;
36 35  
37 36 /**
... ... @@ -82,7 +81,7 @@ public class ToolCodegenEngine {
82 81 javaFilePath("service/${table.businessName}/impl/${table.className}ServiceImpl"))
83 82 // Vue
84 83 .put(vueTemplatePath("views/index.vue"),
85   - vueFilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
  84 + vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
86 85 .put(vueTemplatePath("api/api.js"),
87 86 vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
88 87 // SQL
... ... @@ -131,6 +130,7 @@ public class ToolCodegenEngine {
131 130 globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
132 131 globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
133 132 globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
  133 + globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
134 134 globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
135 135 globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
136 136 }
... ... @@ -167,13 +167,18 @@ public class ToolCodegenEngine {
167 167 }
168 168  
169 169 private String formatFilePath(String filePath, Map<String, Object> bindingMap) {
170   - filePath = StrUtil.replace(filePath, "${basePackage}", ((String) bindingMap.get("basePackage")).replaceAll("\\.", "/"));
  170 + filePath = StrUtil.replace(filePath, "${basePackage}",
  171 + getStr(bindingMap, "basePackage").replaceAll("\\.", "/"));
  172 + filePath = StrUtil.replace(filePath, "${simpleModuleName_upperFirst}",
  173 + getStr(bindingMap, "simpleModuleName_upperFirst"));
  174 + filePath = StrUtil.replace(filePath, "${classNameVar}",
  175 + getStr(bindingMap, "classNameVar"));
  176 +
  177 + // table 包含的字段
171 178 ToolCodegenTableDO table = (ToolCodegenTableDO) bindingMap.get("table");
172   - filePath = StrUtil.replace(filePath, "${simpleModuleName_upperFirst}", (String) bindingMap.get("simpleModuleName_upperFirst"));
173 179 filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName());
174 180 filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName());
175 181 filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName());
176   - filePath = StrUtil.replace(filePath, "${classNameVar}", (String) bindingMap.get("classNameVar"));
177 182 return filePath;
178 183 }
179 184  
... ...
src/main/resources/codegen/java/controller/controller.vm
... ... @@ -39,15 +39,15 @@ public class ${table.className}Controller {
39 39  
40 40 @PostMapping("/create")
41 41 @ApiOperation("创建${table.classComment}")
42   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:create')")
43   - public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid ${table.className}CreateReqVO createReqVO) {
  42 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
  43 + public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${table.className}CreateReqVO createReqVO) {
44 44 return success(${classNameVar}Service.create${simpleClassName}(createReqVO));
45 45 }
46 46  
47 47 @PutMapping("/update")
48 48 @ApiOperation("更新${table.classComment}")
49   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:update')")
50   - public CommonResult<Boolean> update${simpleClassName}(@Valid ${table.className}UpdateReqVO updateReqVO) {
  49 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
  50 + public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${table.className}UpdateReqVO updateReqVO) {
51 51 ${classNameVar}Service.update${simpleClassName}(updateReqVO);
52 52 return success(true);
53 53 }
... ... @@ -55,7 +55,7 @@ public class ${table.className}Controller {
55 55 @DeleteMapping("/delete")
56 56 @ApiOperation("删除${table.classComment}")
57 57 @ApiImplicitParam(name = "id", value = "编号", required = true)
58   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:delete')")
  58 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
59 59 public CommonResult<Boolean> delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
60 60 ${classNameVar}Service.delete${simpleClassName}(id);
61 61 return success(true);
... ... @@ -64,7 +64,7 @@ public class ${table.className}Controller {
64 64 @GetMapping("/get")
65 65 @ApiOperation("获得${table.classComment}")
66 66 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = ${primaryColumn.javaType}.class)
67   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
  67 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
68 68 public CommonResult<${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
69 69 ${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
70 70 return success(${table.className}Convert.INSTANCE.convert(${classNameVar}));
... ... @@ -73,7 +73,7 @@ public class ${table.className}Controller {
73 73 @GetMapping("/list")
74 74 @ApiOperation("获得${table.classComment}列表")
75 75 @ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class)
76   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
  76 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
77 77 public CommonResult<List<${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
78 78 List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
79 79 return success(${table.className}Convert.INSTANCE.convertList(list));
... ... @@ -81,7 +81,7 @@ public class ${table.className}Controller {
81 81  
82 82 @GetMapping("/page")
83 83 @ApiOperation("获得${table.classComment}分页")
84   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
  84 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
85 85 public CommonResult<PageResult<${table.className}RespVO>> get${simpleClassName}Page(@Valid ${table.className}PageReqVO pageVO) {
86 86 PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageVO);
87 87 return success(${table.className}Convert.INSTANCE.convertPage(pageResult));
... ... @@ -89,7 +89,7 @@ public class ${table.className}Controller {
89 89  
90 90 @GetMapping("/export-excel")
91 91 @ApiOperation("导出${table.classComment} Excel")
92   - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
  92 + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")
93 93 @OperateLog(type = EXPORT)
94 94 public void export${simpleClassName}Excel(@Valid ${table.className}ExportReqVO exportReqVO,
95 95 HttpServletResponse response) throws IOException {
... ...
src/main/resources/codegen/java/controller/vo/excelVO.vm
... ... @@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
8 8 #foreach ($column in $columns)
9 9 #if ("$!column.dictType" != "")## 有设置数据字典
10 10 import ${DictFormatClassName};
  11 +import ${DictConvertClassName};
11 12  
12 13 import static ${SysDictTypeEnumClassName}.*;
13 14 #break
... ... @@ -24,9 +25,11 @@ public class ${table.className}ExcelVO {
24 25  
25 26 #foreach ($column in $columns)
26 27 #if (${column.listOperationResult})##返回字段
27   - @ExcelProperty("${column.columnComment}")
28 28 #if ("$!column.dictType" != "")##处理枚举值
  29 + @ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)
29 30 @DictFormat(${column.dictType.toUpperCase()})
  31 + #else
  32 + @ExcelProperty("${column.columnComment}")
30 33 #end
31 34 private ${column.javaType} ${column.javaField};
32 35  
... ...
src/main/resources/codegen/sql/sql.vm
... ... @@ -4,8 +4,8 @@ INSERT INTO `sys_menu`(
4 4 `path`, `icon`, `component`, `status`
5 5 )
6 6 VALUES (
7   - '${table.tableComment}管理', '${permissionPrefix}:query', 2, 0, ${table.parentMenuId},
8   - '${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 1
  7 + '${table.classComment}管理', '${permissionPrefix}:query', 2, 0, ${table.parentMenuId},
  8 + '${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 1
9 9 );
10 10  
11 11 -- 按钮父菜单ID
... ... @@ -15,12 +15,13 @@ SELECT @parentId := LAST_INSERT_ID();
15 15 #set ($functionNames = ['创建', '更新', '删除', '导出'])
16 16 #set ($functionOps = ['create', 'update', 'delete', 'export'])
17 17 #foreach ($functionName in $functionNames)
  18 +#set ($index = $foreach.count - 1)
18 19 INSERT INTO `sys_menu`(
19 20 `name`, `permission`, `menu_type`, `sort`, `parent_id`,
20 21 `path`, `icon`, `component`, `status`
21 22 )
22 23 VALUES (
23   - '${table.tableComment}${functionName}', '${permissionPrefix}:${functionOps[$velocityCount]}', 3, 0, @parentId,
  24 + '${table.tableComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
24 25 '', '', '', 1
25 26 );
26 27 #end
... ...
src/main/resources/codegen/vue/api/api.js.vm
... ... @@ -23,7 +23,7 @@ export function update${simpleClassName}(data) {
23 23 // 删除${table.classComment}
24 24 export function delete${simpleClassName}(id) {
25 25 return request({
26   - url: '${baseURL}/delelte?id=' + id,
  26 + url: '${baseURL}/delete?id=' + id,
27 27 method: 'delete'
28 28 })
29 29 }
... ... @@ -51,6 +51,6 @@ export function export${simpleClassName}Excel(query) {
51 51 url: '${baseURL}/export-excel',
52 52 method: 'get',
53 53 params: query,
54   - reponseBody: 'blob'
  54 + responseType: 'blob'
55 55 })
56 56 }
... ...
src/main/resources/codegen/vue/views/index.vue.vm
... ... @@ -18,14 +18,14 @@
18 18 <el-select v-model="queryParams.${javaField}" placeholder="请选择${comment}" clearable size="small">
19 19 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
20 20 <el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
21   - :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"/>
  21 + :key="dict.value" :label="dict.label" :value="dict.value"/>
22 22 #else## 未设置 dictType 数据字典的情况
23 23 <el-option label="请选择字典生成" value="" />
24 24 #end
25 25 </el-select>
26 26 </el-form-item>
27 27 #elseif($column.htmlType == "datetime")
28   - #if ($column.queryType != "BETWEEN")## 非范围
  28 + #if ($column.listOperationCondition != "BETWEEN")## 非范围
29 29 <el-form-item label="${comment}" prop="${javaField}">
30 30 <el-date-picker clearable size="small" v-model="queryParams.${javaField}" type="date" value-format="yyyy-MM-dd" placeholder="选择${comment}" />
31 31 </el-form-item>
... ... @@ -74,7 +74,7 @@
74 74 #elseif("" != $column.dictType)## 数据字典
75 75 <el-table-column label="${comment}" align="center" prop="${javaField}">
76 76 <template slot-scope="scope">
77   - <span>{{ getDictDataLabel(DICT_TYPE.$dictType.toUpperCase(), scope.row.javaField) }}</span>
  77 + <span>{{ getDictDataLabel(DICT_TYPE.$dictType.toUpperCase(), scope.row.${column.javaField}) }}</span>
78 78 </template>
79 79 </el-table-column>>
80 80 #else
... ... @@ -253,11 +253,12 @@ export default {
253 253 /** 查询列表 */
254 254 getList() {
255 255 this.loading = true;
  256 + // 处理查询参数
256 257 let params = {...this.queryParams};
257 258 #foreach ($column in $columns)
258 259 #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
259 260 #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
260   - this.addBeginAndEndTime(params, this.dateRange${AttrName}, ${column.javaField});
  261 + this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}');
261 262 #end
262 263 #end
263 264 // 执行查询
... ... @@ -279,7 +280,7 @@ export default {
279 280 #if($column.htmlType == "checkbox")
280 281 $column.javaField: [],
281 282 #else
282   - $column.javaField: null,
  283 + $column.javaField: undefined,
283 284 #end
284 285 #end
285 286 };
... ... @@ -325,7 +326,7 @@ export default {
325 326 /** 提交按钮 */
326 327 submitForm() {
327 328 this.#[[$]]#refs["form"].validate(valid => {
328   - if (valid) {
  329 + if (!valid) {
329 330 return;
330 331 }
331 332 #foreach ($column in $columns)
... ... @@ -366,19 +367,23 @@ export default {
366 367 },
367 368 /** 导出按钮操作 */
368 369 handleExport() {
  370 + // 处理查询参数
  371 + let params = {...this.queryParams};
  372 + params.pageNo = undefined;
  373 + params.pageSize = undefined;
  374 + #foreach ($column in $columns)
  375 + #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
  376 + #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
  377 + this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}');
  378 + #end
  379 + #end
  380 + // 执行导出
369 381 this.$confirm('是否确认导出所有${table.classComment}数据项?', "警告", {
370 382 confirmButtonText: "确定",
371 383 cancelButtonText: "取消",
372 384 type: "warning"
373 385 }).then(function() {
374   - let params = {...this.queryParams};
375   - #foreach ($column in $columns)
376   - #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
377   - #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
378   - this.addBeginAndEndTime(params, this.dateRange${AttrName}, ${column.javaField});
379   - #end
380   - #end
381   - return export${simpleClassName}(params);
  386 + return export${simpleClassName}Excel(params);
382 387 }).then(response => {
383 388 this.downloadExcel(response, '${table.classComment}.xls');
384 389 })
... ...