Browse Source

vben代码自动生成文件

dev
zhouhaibin 3 months ago
parent
commit
9deefe0bb4
  1. 42
      ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java
  2. 59
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/api/index.ts.vm
  3. 57
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/api/model.ts.vm
  4. 144
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/data.ts.vm
  5. 115
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/index_vben.vue.vm
  6. 111
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/index_vben_tree.vue.vm
  7. 68
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/modal.vue.vm
  8. 86
      ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/modal_tree.vue.vm

42
ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java

@ -134,6 +134,20 @@ public class VelocityUtils {
} else if (GenConstants.TPL_TREE.equals(tplCategory)) {
templates.add("vm/vue/index-tree.vue.vm");
}
/**
* 添加vben
*/
templates.add("vm/vben/api/index.ts.vm");
templates.add("vm/vben/api/model.ts.vm");
templates.add("vm/vben/views/data.ts.vm");
if (GenConstants.TPL_CRUD.equals(tplCategory)) {
templates.add("vm/vben/views/index_vben.vue.vm");
templates.add("vm/vben/views/modal.vue.vm");
} else if (GenConstants.TPL_TREE.equals(tplCategory)) {
templates.add("vm/vben/views/index_vben_tree.vue.vm");
templates.add("vm/vben/views/modal_tree.vue.vm");
}
return templates;
}
@ -186,6 +200,34 @@ public class VelocityUtils {
} else if (template.contains("index-tree.vue.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
}
String vbenPath = "vben";
String BusinessName = StringUtils.capitalize(genTable.getBusinessName());
/**
* 添加vben
*/
if (template.contains("index.ts.vm")) {
fileName = StringUtils.format("{}/api/{}/{}/index.ts", vbenPath, moduleName, businessName);
}
if (template.contains("model.ts.vm")) {
fileName = StringUtils.format("{}/api/{}/{}/model.ts", vbenPath, moduleName, businessName);
}
if (template.contains("index_vben.vue.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vbenPath, moduleName, businessName);
}
if (template.contains("index_vben_tree.vue.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vbenPath, moduleName, businessName);
}
if (template.contains("data.ts.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/{}.data.ts", vbenPath, moduleName, businessName, businessName);
}
if (template.contains("modal.vue.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/{}Modal.vue", vbenPath, moduleName, businessName, BusinessName);
}
if (template.contains("modal_tree.vue.vm")) {
fileName = StringUtils.format("{}/views/{}/{}/{}Modal.vue", vbenPath, moduleName, businessName, BusinessName);
}
return fileName;
}

59
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/api/index.ts.vm

@ -0,0 +1,59 @@
import { defHttp } from '@/utils/http/axios';
import { ID, IDS, commonExport } from '@/api/base';
import { ${BusinessName}VO, ${BusinessName}Form, ${BusinessName}Query } from './model';
/**
* 查询${functionName}列表
* @param params
* @returns
*/
export function ${businessName}List(params?: ${BusinessName}Query) {
return defHttp.get<${BusinessName}VO[]>({ url: '/${moduleName}/${businessName}/list', params });
}
#if($tplCategory != 'tree')
/**
* 导出${functionName}列表
* @param params
* @returns
*/
export function ${businessName}Export(params?: ${BusinessName}Query) {
return commonExport('/${moduleName}/${businessName}/export', params ?? {});
}
#end
/**
* 查询${functionName}详细
* @param ${pkColumn.javaField} id
* @returns
*/
export function ${businessName}Info(${pkColumn.javaField}: ID) {
return defHttp.get<${BusinessName}VO>({ url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField} });
}
/**
* 新增${functionName}
* @param data
* @returns
*/
export function ${businessName}Add(data: ${BusinessName}Form) {
return defHttp.postWithMsg<void>({ url: '/${moduleName}/${businessName}', data });
}
/**
* 更新${functionName}
* @param data
* @returns
*/
export function ${businessName}Update(data: ${BusinessName}Form) {
return defHttp.putWithMsg<void>({ url: '/${moduleName}/${businessName}', data });
}
/**
* 删除${functionName}
* @param ${pkColumn.javaField} id
* @returns
*/
export function ${businessName}Remove(${pkColumn.javaField}: ID | IDS) {
return defHttp.deleteWithMsg<void>({ url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField} },);
}

57
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/api/model.ts.vm

@ -0,0 +1,57 @@
import { BaseEntity, PageQuery } from '@/api/base';
export interface ${BusinessName}VO {
#foreach ($column in $columns)
#if($column.list)
/**
* $column.columnComment
*/
$column.javaField:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) string | number;
#elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number;
#elseif($column.javaType == 'Boolean') boolean;
#else string;
#end
#end
#end
#if ($table.tree)
/**
* 子对象
*/
children: ${BusinessName}VO[];
#end
}
export interface ${BusinessName}Form extends BaseEntity {
#foreach ($column in $columns)
#if($column.insert || $column.edit)
/**
* $column.columnComment
*/
$column.javaField?:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) string | number;
#elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number;
#elseif($column.javaType == 'Boolean') boolean;
#else string;
#end
#end
#end
}
export interface ${BusinessName}Query #if(!${treeCode})extends PageQuery #end{
#foreach ($column in $columns)
#if($column.query)
/**
* $column.columnComment
*/
$column.javaField?:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) string | number;
#elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number;
#elseif($column.javaType == 'Boolean') boolean;
#else string;
#end
#end
#end
/**
* 日期范围参数
*/
params?: any;
}

144
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/data.ts.vm

@ -0,0 +1,144 @@
import { BasicColumn } from '@/components/Table';
import { FormSchema } from '@/components/Form';
#if(${dicts} != '')
import { getDictOptions } from '@/utils/dict';
import { useRender } from '@/hooks/component/useRender';
#end
export const formSchemas: FormSchema[] = [
#foreach($column in $columns)
#if($column.query)
#if($column.dictType)
#set($dictType=$column.dictType)
#else
#set($dictType="")
#end
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.htmlType == "input")
#set($component="Input")
#elseif($column.htmlType == "textarea")
#set($component="InputTextArea")
#elseif($column.htmlType == "select")
#set($component="Select")
#elseif($column.htmlType == "radio")
#set($component="RadioButtonGroup")
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
#set($component="DatePicker")
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($component="RangePicker")
#else
#set($component="Input")
#end
{
label: '${comment}',
field: '${column.javaField}',
component: '${component}',
#if($dictType != "")
componentProps: {
options: getDictOptions('$dictType')
},
#elseif($component == "DatePicker" || $component == "RangePicker")
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
#end
},
#end
#end
];
#if(${dicts} != '')
const { renderDict } = useRender();
#end
export const columns: BasicColumn[] = [
#foreach($column in $columns)
#if($column.list)
#if($column.dictType)
#set($dictType=$column.dictType)
#else
#set($dictType="")
#end
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
{
title: '${comment}',
dataIndex: '${column.javaField}',
#if($dictType != "")
customRender: ({ value }) => renderDict(value, '$dictType'),
#end
},
#end
#end
];
export const modalSchemas: FormSchema[] = [
#foreach($column in $columns)
#if($column.edit)
#if($column.dictType)
#set($dictType=$column.dictType)
#else
#set($dictType="")
#end
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.htmlType == "input")
#set($component="Input")
#elseif($column.htmlType == "textarea")
#set($component="InputTextArea")
#elseif($column.htmlType == "select")
#set($component="Select")
#elseif($column.htmlType == "radio")
#set($component="RadioButtonGroup")
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
#set($component="DatePicker")
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($component="RangePicker")
#else
#set($component="Input")
#end
#if($column.required)
#set($required='true')
#else
#set($required='false')
#end
{
label: '${comment}',
field: '${column.javaField}',
required: ${required},
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
component: 'TreeSelect',
#else
component: '${component}',
#end
#if($dictType != "")
componentProps: {
options: getDictOptions('$dictType')
},
#elseif($component == "DatePicker" || $component == "RangePicker")
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
#end
#if(${column.pk})
show: false,
#end
},
#end
#end
];

115
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/index_vben.vue.vm

@ -0,0 +1,115 @@
<template>
<PageWrapper dense>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button
@click="downloadExcel(${businessName}Export, '${functionName}数据', getForm().getFieldsValue())"
v-auth="'${permissionPrefix}:export'"
>导出</a-button
>
<a-button
type="primary"
danger
@click="multipleRemove(${businessName}Remove)"
:disabled="!selected"
v-auth="'${permissionPrefix}:remove'"
>删除</a-button
>
<a-button
type="primary"
@click="handleAdd"
v-auth="'${permissionPrefix}:add'"
>新增</a-button
>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
stopButtonPropagation
:actions="[
{
label: '修改',
icon: IconEnum.EDIT,
type: 'primary',
ghost: true,
auth: '${permissionPrefix}:edit',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
icon: IconEnum.DELETE,
type: 'primary',
danger: true,
ghost: true,
auth: '${permissionPrefix}:remove',
popConfirm: {
placement: 'left',
title: '是否删除${functionName}[' + record.${pkColumn.javaField} + ']?',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</template>
</BasicTable>
<${BusinessName}Modal @register="registerModal" @reload="reload" />
</PageWrapper>
</template>
<script setup lang="ts">
import { PageWrapper } from '@/components/Page';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { ${businessName}List, ${businessName}Export, ${businessName}Remove } from '@/api/${moduleName}/${businessName}';
import { downloadExcel } from '@/utils/file/download';
import { useModal } from '@/components/Modal';
import ${BusinessName}Modal from './${BusinessName}Modal.vue';
import { formSchemas, columns } from './${businessName}.data';
import { IconEnum } from '@/enums/appEnum';
defineOptions({ name: '${BusinessName}' });
const [registerTable, { reload, multipleRemove, selected, getForm }] = useTable({
rowSelection: {
type: 'checkbox',
},
title: '${functionName}列表',
api: ${businessName}List,
showIndexColumn: false,
rowKey: '${pkColumn.javaField}',
useSearchForm: true,
formConfig: {
schemas: formSchemas,
baseColProps: {
xs: 24,
sm: 24,
md: 24,
lg: 6,
},
},
columns: columns,
actionColumn: {
width: 200,
title: '操作',
key: 'action',
fixed: 'right',
},
});
const [registerModal, { openModal }] = useModal();
function handleEdit(record: Recordable) {
openModal(true, { record, update: true });
}
function handleAdd() {
openModal(true, { update: false });
}
async function handleDelete(record: Recordable) {
await ${businessName}Remove([record.${pkColumn.javaField}]);
await reload();
}
</script>
<style scoped></style>

111
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/index_vben_tree.vue.vm

@ -0,0 +1,111 @@
<template>
<PageWrapper dense>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button @click="expandAll">展开</a-button
>
<a-button @click="collapseAll">折叠</a-button
>
<a-button
type="primary"
@click="handleAdd"
v-auth="'${permissionPrefix}:add'"
>新增</a-button
>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
stopButtonPropagation
:actions="[
{
label: '修改',
icon: IconEnum.EDIT,
type: 'primary',
ghost: true,
auth: '${permissionPrefix}:edit',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
icon: IconEnum.DELETE,
type: 'primary',
danger: true,
ghost: true,
auth: '${permissionPrefix}:remove',
popConfirm: {
placement: 'left',
title: '是否删除${functionName}[' + record.${pkColumn.javaField} + ']?',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</template>
</BasicTable>
<${BusinessName}Modal @register="registerModal" @reload="reload" />
</PageWrapper>
</template>
<script setup lang="ts">
import { PageWrapper } from '@/components/Page';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { ${businessName}List, ${businessName}Remove } from '@/api/${moduleName}/${businessName}';
import type { ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/model';
import { useModal } from '@/components/Modal';
import ${BusinessName}Modal from './${BusinessName}Modal.vue';
import { formSchemas, columns } from './${businessName}.data';
import { listToTree, removeEmptyChildren } from '@/utils/helper/treeHelper';
import { IconEnum } from '@/enums/appEnum';
defineOptions({ name: '${BusinessName}' });
const [registerTable, { reload, expandAll, collapseAll }] = useTable({
api: ${businessName}List,
title: '${functionName}列表',
showIndexColumn: false,
isTreeTable: true,
pagination: false,
rowKey: '$treeCode}',
afterFetch(data: ${BusinessName}VO[]) {
const ret = listToTree(data, { id: '${treeCode}', pid: '${treeParentCode}' });
removeEmptyChildren(ret);
return ret;
},
useSearchForm: true,
formConfig: {
schemas: formSchemas,
baseColProps: {
xs: 24,
sm: 24,
md: 24,
lg: 6,
},
},
columns: columns,
actionColumn: {
width: 200,
title: '操作',
key: 'action',
fixed: 'right',
},
});
const [registerModal, { openModal }] = useModal();
function handleEdit(record: Recordable) {
openModal(true, { record, update: true });
}
function handleAdd() {
openModal(true, { update: false });
}
async function handleDelete(record: Recordable) {
await ${businessName}Remove(record.${pkColumn.javaField});
await reload();
}
</script>
<style scoped></style>

68
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/modal.vue.vm

@ -0,0 +1,68 @@
<template>
<BasicModal
v-bind="$attrs"
:title="title"
@register="registerInnerModal"
@ok="handleSubmit"
@cancel="resetForm"
>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script setup lang="ts">
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { computed, ref, unref } from 'vue';
import { ${businessName}Info, ${businessName}Add, ${businessName}Update } from '@/api/${moduleName}/${businessName}';
import { modalSchemas } from './${businessName}.data';
defineOptions({ name: '${BusinessName}Modal' });
const emit = defineEmits(['register', 'reload']);
const isUpdate = ref<boolean>(false);
const title = computed<string>(() => {
return isUpdate.value ? '编辑${functionName}' : '新增${functionName}';
});
const [registerInnerModal, { modalLoading, closeModal }] = useModalInner(
async (data: { record?: Recordable; update: boolean }) => {
modalLoading(true);
const { record, update } = data;
isUpdate.value = update;
if (update && record) {
const ret = await ${businessName}Info(record.${pkColumn.javaField});
await setFieldsValue(ret);
}
modalLoading(false);
},
);
const [registerForm, { setFieldsValue, resetForm, validate }] = useForm({
labelWidth: 100,
showActionButtonGroup: false,
baseColProps: { span: 24 },
schemas: modalSchemas,
});
async function handleSubmit() {
try {
modalLoading(true);
const data = await validate();
if (unref(isUpdate)) {
await ${businessName}Update(data);
} else {
await ${businessName}Add(data);
}
emit('reload');
closeModal();
await resetForm();
} catch (e) {
} finally {
modalLoading(false);
}
}
</script>
<style scoped></style>

86
ruoyi-modules/ruoyi-generator/src/main/resources/vm/vben/views/modal_tree.vue.vm

@ -0,0 +1,86 @@
<template>
<BasicModal
v-bind="$attrs"
:title="title"
@register="registerInnerModal"
@ok="handleSubmit"
@cancel="resetForm"
>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script setup lang="ts">
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { computed, ref, unref } from 'vue';
import { ${businessName}Info, ${businessName}Add, ${businessName}Update, ${businessName}List } from '@/api/${moduleName}/${businessName}';
import { modalSchemas } from './${businessName}.data';
import { listToTree } from '@/utils/helper/treeHelper';
defineOptions({ name: '${BusinessName}Modal' });
const emit = defineEmits(['register', 'reload']);
const isUpdate = ref<boolean>(false);
const title = computed<string>(() => {
return isUpdate.value ? '编辑${functionName}' : '新增${functionName}';
});
const [registerInnerModal, { modalLoading, closeModal }] = useModalInner(
async (data: { record?: Recordable; update: boolean }) => {
modalLoading(true);
const { record, update } = data;
isUpdate.value = update;
if (update && record) {
const ret = await ${businessName}Info(record.${pkColumn.javaField});
await setFieldsValue(ret);
}
// 下拉框初始化
await init${BusinessName}Select();
modalLoading(false);
},
);
async function init${BusinessName}Select() {
// 需要动态更新TreeSelect组件 这里允许为空
const listData = await ${businessName}List();
const treeData = listToTree(listData, { id: '${treeCode}', pid: '${treeParentCode}' });
await updateSchema({
field: '${treeParentCode}',
componentProps: {
treeData,
treeLine: { showLeafIcon: false },
fieldNames: { label: '${businessName}Name', value: '${businessName}Id' },
treeDefaultExpandAll: true,
},
});
}
const [registerForm, { setFieldsValue, resetForm, validate, updateSchema }] = useForm({
labelWidth: 100,
showActionButtonGroup: false,
baseColProps: { span: 24 },
schemas: modalSchemas,
});
async function handleSubmit() {
try {
modalLoading(true);
const data = await validate();
if (unref(isUpdate)) {
await ${businessName}Update(data);
} else {
await ${businessName}Add(data);
}
emit('reload');
closeModal();
await resetForm();
} catch (e) {
} finally {
modalLoading(false);
}
}
</script>
<style scoped></style>
Loading…
Cancel
Save