first commit

This commit is contained in:
ye1023
2026-04-09 15:12:08 +08:00
commit d94e9c9bc4
1980 changed files with 709719 additions and 0 deletions
@@ -0,0 +1,8 @@
DELETE FROM demo;
INSERT INTO demo (id, name, age, email,sex,birthday,content) VALUES
(1, 'Jone', 18, 'test1@baomidou.com','1','2017-12-28','很好'),
(2, 'Jack', 20, 'test2@baomidou.com','2','2018-02-28','努力型'),
(3, 'Tom', 28, 'test3@baomidou.com','1','2018-11-28','吃苦'),
(4, 'Sandy', 21, 'test4@baomidou.com','1','2018-07-28','聪明'),
(5, 'Billie', 24, 'test5@baomidou.com','2','2018-12-11','出色');
@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS demo;
CREATE TABLE demo (
id BIGINT(20) NOT NULL auto_increment COMMENT '主键ID',
name varchar(30) default NULL COMMENT '姓名',
sex varchar(2) default NULL,
age int(11) default NULL COMMENT '年龄',
birthday date default NULL COMMENT '生日',
email varchar(50) default NULL COMMENT '邮箱',
content varchar(1000) default NULL COMMENT '个人简介',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -0,0 +1,67 @@
<#if po.fieldDbType=='Blob'>
private transient java.lang.String ${po.fieldName}String;
private byte[] ${po.fieldName};
public byte[] get${po.fieldName?cap_first}(){
if(${po.fieldName}String==null){
return null;
}
try {
return ${po.fieldName}String.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public String get${po.fieldName?cap_first}String(){
if(${po.fieldName}==null || ${po.fieldName}.length==0){
return "";
}
try {
return new String(${po.fieldName},"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
<#elseif po.classType=='switch'>
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
@Excel(name = "${po.filedComment}", width = 15,replace = {"是_${switch_extend_arr1}","否_${switch_extend_arr2}"} )
@Schema(description = "${po.filedComment}")
private ${po.fieldType} ${po.fieldName};
<#elseif po.classType=='pca'>
@Excel(name = "${po.filedComment}", width = 15,exportConvert=true,importConvert = true )
@Schema(description = "${po.filedComment}")
private ${po.fieldType} ${po.fieldName};
public String convertis${po.fieldName?cap_first}() {
return SpringContextUtils.getBean(ProvinceCityArea.class).getText(${po.fieldName});
}
public void convertset${po.fieldName?cap_first}(String text) {
this.${po.fieldName} = SpringContextUtils.getBean(ProvinceCityArea.class).getCode(text);
}
<#elseif po.classType=='cat_tree'>
<#assign list_field_dictCode=', dictTable = "sys_category", dicText = "name", dicCode = "id"'>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
@Schema(description = "${po.filedComment}")
private ${po.fieldType} ${po.fieldName};
<#else>
@Schema(description = "${po.filedComment}")
<#if po.fieldDbName == 'del_flag'>
@TableLogic
</#if>
private ${po.fieldType} ${po.fieldName};
</#if>
@@ -0,0 +1,53 @@
<#if need_select_tag>
JDictSelectTag,
</#if>
<#if need_switch>
JSwitch,
</#if>
<#if need_multi>
JSelectMultiple,
</#if>
<#if need_search>
JSearchSelect,
</#if>
<#if need_popup>
JPopup,
</#if>
<#if need_popup_dict>
JPopupDict,
</#if>
<#if need_category>
JCategorySelect,
</#if>
<#if need_dept>
JSelectDept,
</#if>
<#if need_dept_user>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
JSelectUser,
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
</#if>
<#if need_select_tree>
JTreeSelect,
</#if>
<#if need_time>
TimePicker,
</#if>
<#if need_pca>
JAreaLinkage,
</#if>
<#if need_upload>
JUpload,
</#if>
<#if need_image_upload>
JImageUpload,
</#if>
<#if need_markdown>
JMarkdownEditor,
</#if>
<#if need_editor>
JEditor,
</#if>
<#if need_checkbox>
JCheckbox,
</#if>
@@ -0,0 +1,119 @@
<#include "/common/utils.ftl">
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShow =='Y' && po.fieldName != 'id' && po.fieldName !='delFlag' && isNotPidField(tableVo, po.fieldDbName)>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-col :span="${form_span}">
<a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}" id="${formEntityName}-${autoStringSuffixForModel(po)}" name="${autoStringSuffixForModel(po)}">
<#if po.classType =='date'>
<a-date-picker placeholder="请选择${po.filedComment}" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='datetime'>
<a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" showTime value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='time'>
<#assign need_time = true>
<time-picker placeholder="请选择${po.filedComment}" value-format="HH:mm:ss" v-model:value="formData.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='popup'>
<#assign need_popup = true>
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
<j-popup
placeholder="请选择${po.filedComment}"
v-model:value="formData.${po.fieldName}"
code="${po.dictTable}"
:fieldConfig="[
<#list sourceFields as fieldName>
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
</#list>
]"
:multi="${po.extendParams.popupMulti?c}"
:setFieldsValue="setFieldsValue"
<#if po.readonly=='Y'>disabled</#if><#rt> allow-clear />
<#elseif po.classType =='popup_dict'>
<#assign need_popup_dict = true>
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
<j-popup-dict
placeholder="请选择${po.filedComment}"
v-model:value="formData.${po.fieldName}"
dictCode="${po.dictTable},${po.dictText},${po.dictField}"
:multi="${po.extendParams.popupMulti?c}" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='sel_depart'>
<#assign need_dept = true>
<j-select-dept v-model:value="formData.${po.fieldName}" <#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if> <#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if> <#if po.readonly=='Y'>disabled</#if> :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='switch'>
<#assign need_switch = true>
<j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
<#elseif po.classType =='pca'>
<#assign need_pca = true>
<j-area-linkage v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" saveCode="region" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='markdown'>
<#assign need_markdown = true>
<j-markdown-editor v-model:value="formData.${autoStringSuffixForModel(po)}" id="${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></j-markdown-editor>
<#elseif po.classType =='password'>
<a-input-password v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType =='sel_user'>
<#assign need_dept_user = true>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
<j-select-user v-model:value="formData.${po.fieldName}" <#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if> <#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if> <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
<#elseif po.classType =='textarea'>
<a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" :rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='radio'>
<#assign need_select_tag = true>
<j-dict-select-tag type='radio' v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType=='list'>
<#assign need_select_tag = true>
<j-dict-select-tag v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType=='list_multi'>
<#assign need_multi = true>
<j-select-multiple type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> :triggerChange="false"/>
<#elseif po.classType=='checkbox'>
<#assign need_checkbox = true>
<j-checkbox type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType=='sel_search'>
<#assign need_search = true>
<j-search-select v-model:value="formData.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
<#elseif po.classType=='cat_tree'>
<#assign need_category = true>
<j-category-select v-model:value="formData.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}"</#if> <#if po.readonly=='Y'>disabled</#if> @change="(value) => handleFormChange('${po.fieldName}', value)" allow-clear />
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='file'>
<#assign need_upload = true>
<j-upload v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:maxCount=${po.uploadnum}</#if>></j-upload>
<#elseif po.classType=='image'>
<#assign need_image_upload = true>
<j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}<#else>:fileMax="0"</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
<#elseif po.classType=='umeditor'>
<#assign need_editor = true>
<j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if> :autoFocus="false"/>
<#elseif po.fieldDbType=='Blob'>
<a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear ></a-input>
<#elseif po.classType == 'sel_tree'>
<#assign need_select_tree = true>
<j-tree-select
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
<#elseif po.dictText?split(',')[1]??>
pidField="${po.dictText?split(',')[1]}"
<#elseif po.dictText?split(',')[3]??>
hasChildField="${po.dictText?split(',')[3]}"
</#if>
</#if>
pidValue="${po.dictField}"
<#if po.readonly=='Y'>disabled</#if>
v-model:value="formData.${po.fieldName}"
@change="(value) => handleFormChange('${po.fieldName}', value)" allow-clear >
</j-tree-select>
<#else>
<a-input v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear ></a-input>
</#if>
</a-form-item>
</a-col>
</#if>
@@ -0,0 +1,59 @@
<#if need_select_tag>
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
</#if>
<#if need_switch>
import JSwitch from '/@/components/Form/src/jeecg/components/JSwitch.vue';
</#if>
<#if need_multi>
import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
</#if>
<#if need_search>
import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
</#if>
<#if need_popup>
import JPopup from '/@/components/Form/src/jeecg/components/JPopup.vue';
</#if>
<#if need_popup_dict>
import JPopupDict from '/@/components/Form/src/jeecg/components/JPopupDict.vue';
</#if>
<#if need_category>
import JCategorySelect from '/@/components/Form/src/jeecg/components/JCategorySelect.vue';
</#if>
<#if need_dept>
import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
</#if>
<#if need_dept_user>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
import JSelectUser from '/@/components/Form/src/jeecg/components/JSelectUser.vue';
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
</#if>
<#if need_select_tree>
import JTreeSelect from '/@/components/Form/src/jeecg/components/JTreeSelect.vue';
</#if>
<#if need_time>
import { TimePicker } from 'ant-design-vue';
</#if>
<#if need_pca>
import JAreaLinkage from '/@/components/Form/src/jeecg/components/JAreaLinkage.vue';
</#if>
<#if need_upload>
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
</#if>
<#if need_image_upload>
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
</#if>
<#if need_markdown>
import JMarkdownEditor from '/@/components/Form/src/jeecg/components/JMarkdownEditor.vue';
</#if>
<#if need_editor>
import JEditor from '/@/components/Form/src/jeecg/components/JEditor.vue';
</#if>
<#if need_checkbox>
import JCheckbox from "/@/components/Form/src/jeecg/components/JCheckbox.vue";
</#if>
<#if need_range_number>
import JRangeNumber from "/@/components/Form/src/jeecg/components/JRangeNumber.vue";
</#if>
<#if is_like>
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
</#if>
@@ -0,0 +1,108 @@
<#include "/common/utils.ftl">
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isQuery=='Y' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign need_select_tag = true>
<#assign need_multi = true>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign need_select_tag = true>
<#assign need_multi = true>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :lg="6">
<#if query_field_no gt 1> </#if><a-form-item name="${autoStringSuffixForModel(po)}">
<#if query_field_no gt 1> </#if><template #label><span title="${po.filedComment}"><#if po.filedComment?default("")?trim?length gt 4>${po.filedComment?substring(0,4)}<#else>${po.filedComment}</#if></span></template>
<#if po.classType=='sel_search'>
<#if query_field_no gt 1> </#if><j-search-select placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}" allow-clear />
<#elseif po.classType=='sel_user'>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
<#if query_field_no gt 1> </#if><j-select-user placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" @change="(value)=>handleFormJoinChange('${po.fieldName}',value)" allow-clear />
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
<#elseif po.classType=='switch'>
<#if query_field_no gt 1> </#if><j-switch placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query />
<#elseif po.classType=='sel_depart'>
<#if query_field_no gt 1> </#if><j-select-dept placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" checkStrictly allow-clear />
<#elseif po.classType=='list_multi'>
<#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model:value="queryParam.${po.fieldName}" allow-clear />
<#elseif po.classType=='cat_tree'>
<#if query_field_no gt 1> </#if><j-category-select placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}" @change="(value) => handleFormChange('${po.fieldName}', value)" allow-clear />
<#elseif po.classType=='date'>
<#if query_field_no gt 1> </#if><a-date-picker valueFormat="YYYY-MM-DD" placeholder="请选择${po.filedComment}" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="queryParam.${po.fieldName}" allow-clear />
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><a-date-picker showTime valueFormat="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" allow-clear />
<#elseif po.classType=='time'>
<#if query_field_no gt 1> </#if><time-picker valueFormat="HH:mm:ss" placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" allow-clear />
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage v-model:value="queryParam.${po.fieldName}" placeholder="请选择${po.filedComment}" saveCode="region" @change="(value)=>handleFormJoinChange('${po.fieldName}',value)" allow-clear />
<#elseif po.classType=='sel_tree'>
<#if query_field_no gt 1> </#if><j-tree-select v-model:value="queryParam.${po.fieldName}" placeholder="请选择${po.filedComment}" <#if po.dictText??><#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}" <#elseif po.dictText?split(',')[1]??>pidField:"${po.dictText?split(',')[1]}", <#elseif po.dictText?split(',')[3]??>hasChildField:"${po.dictText?split(',')[3]}"</#if> </#if>pidValue="${po.dictField}" allow-clear />
<#elseif po.classType=='popup'>
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
<#if query_field_no gt 1> </#if><j-popup
<#if query_field_no gt 1> </#if>placeholder="请选择${po.filedComment}"
<#if query_field_no gt 1> </#if>v-model:value="queryParam.${po.fieldName}"
<#if query_field_no gt 1> </#if>code="${po.dictTable}"
<#if query_field_no gt 1> </#if>:fieldConfig="[
<#list sourceFields as fieldName>
<#if query_field_no gt 1> </#if>{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
</#list>
<#if query_field_no gt 1> </#if>]"
<#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}"
<#if query_field_no gt 1> </#if>:setFieldsValue="setFieldsValue" allow-clear />
<#elseif po.classType=='popup_dict'>
<#if query_field_no gt 1> </#if><j-popup-dict
<#if query_field_no gt 1> </#if>placeholder="请选择${po.filedComment}"
<#if query_field_no gt 1> </#if>v-model:value="queryParam.${po.fieldName}"
<#if query_field_no gt 1> </#if>dictCode="${po.dictTable},${po.dictText},${po.dictField}"
<#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}"
<#if query_field_no gt 1> </#if><#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}" allow-clear />
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictField}" allow-clear />
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}" allow-clear ></a-input>
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<#if query_field_no gt 1> </#if><a-input-number placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input-number>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${autoStringSuffixForModel(po)}" allow-clear ></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#elseif po.queryMode=='like'>
<#if query_field_no gt 1> </#if><a-col :lg="6">
<#if query_field_no gt 1> </#if><a-form-item name="${autoStringSuffixForModel(po)}">
<#if query_field_no gt 1> </#if><template #label><span title="${po.filedComment}"><#if po.filedComment?default("")?trim?length gt 4>${po.filedComment?substring(0,4)}<#else>${po.filedComment}</#if></span></template>
<#if query_field_no gt 1> </#if><JInput v-model:value="queryParam.${po.fieldName}"/>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :lg="6">
<#if query_field_no gt 1> </#if><a-form-item name="${autoStringSuffixForModel(po)}">
<#if query_field_no gt 1> </#if><template #label><span title="${po.filedComment}"><#if po.filedComment?default("")?trim?length gt 4>${po.filedComment?substring(0,4)}<#else>${po.filedComment}</#if></span></template>
<#if po.classType=='date'>
<#if query_field_no gt 1> </#if><a-range-picker value-format="YYYY-MM-DD" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="queryParam.${po.fieldName}" class="query-group-cust"/>
<#elseif po.classType=='time'>
<#if query_field_no gt 1> </#if><a-time-range-picker value-format="HH:mm:ss" v-model:value="queryParam.${po.fieldName}" class="query-group-cust" />
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><a-range-picker showTime value-format="YYYY-MM-DD HH:mm:ss" v-model:value="queryParam.${po.fieldName}" class="query-group-cust"/>
<#else>
<#if query_field_no gt 1> </#if><JRangeNumber v-model:value="queryParam.${po.fieldName}" class="query-group-cust"></JRangeNumber>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
@@ -0,0 +1,25 @@
<#-- 原生查询区域样式 -->
.jeecg-basic-table-form-container {
padding: 0;
.table-page-search-submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
.query-group-cust{
min-width: 100px !important;
}
.query-group-split-cust{
width: 30px;
display: inline-block;
text-align: center
}
.ant-form-item:not(.ant-form-item-with-help){
margin-bottom: 16px;
height: 32px;
}
:deep(.ant-picker),:deep(.ant-input-number){
width: 100%;
}
}
@@ -0,0 +1,13 @@
<#assign sourceFields = col.dictField?default("")?trim?split(",")/>
<#assign targetFields = col.dictText?default("")?trim?split(",")/>
type: JVxeTypes.popup,
popupCode:"${col.dictTable}",
fieldConfig: [
<#list sourceFields as fieldName>
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
</#list>
],
<#if col.readonly=='Y'>
disabled:true,
</#if>
@@ -0,0 +1,5 @@
<#-- 非原生查询区域样式 -->
:deep(.ant-picker),:deep(.ant-input-number){
width: 100%;
}
@@ -0,0 +1,17 @@
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig: [
<#list sourceFields as fieldName>
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
</#list>
],
multi:${po.extendParams.popupMulti?c}
}
},
@@ -0,0 +1,13 @@
<#list columns as po>
<#if po.isShow == 'Y'>
<#if po.fieldName != 'id'>
<#if po.defaultVal??>
<#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int">
${po.fieldName}:${po.defaultVal},
<#else>
${po.fieldName}:"${po.defaultVal}",
</#if>
</#if>
</#if>
</#if>
</#list>
@@ -0,0 +1,13 @@
<#list sub.colums as po>
<#if po.isShow == 'Y'>
<#if po.fieldName != 'id'>
<#if po.defaultVal??>
<#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int">
${po.fieldName}:${po.defaultVal},
<#else>
${po.fieldName}:"${po.defaultVal}",
</#if>
</#if>
</#if>
</#if>
</#list>
@@ -0,0 +1,11 @@
<#list columns as po>
<#if po.isShow == 'Y' && po.fieldName != 'id'>
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
<#elseif po.fieldDbType=='Blob'>
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
<#else>
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
</#if>
</#if>
</#list>
@@ -0,0 +1,11 @@
<#list columns as po>
<#if po.isShow == 'Y' && po.fieldName != 'id'>
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
<#elseif po.fieldDbType=='Blob'>
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
<#else>
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
</#if>
</#if>
</#list>
@@ -0,0 +1,11 @@
<#list sub.colums as po>
<#if po.isShow == 'Y' && po.fieldName != 'id'>
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
<#elseif po.fieldDbType=='Blob'>
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
<#else>
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
</#if>
</#if>
</#list>
@@ -0,0 +1,27 @@
-- 注意:该页面对应的前台目录为views/${entityPackagePath}文件夹下
-- 如果你想更改到其他目录,请修改sql中component字段对应的值
<#assign id = '${.now?string["yyyyMMddhhmmSSsss"]}0'>
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('${id}', NULL, '${tableVo.ftlDescription}', '/${entityPackagePath}/${entityName?uncap_first}List', '${entityPackagePath}/${entityName}List', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
-- 权限控制sql
-- 新增
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}1', '${id}', '添加${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 编辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}2', '${id}', '编辑${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}3', '${id}', '删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 批量删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}4', '${id}', '批量删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 导出excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}5', '${id}', '导出excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 导入excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}6', '${id}', '导入excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
@@ -0,0 +1,249 @@
<#---->
<#-- freemarker 的一些工具方法 -->
<#---->
<#-- 驼峰转其他字符 -->
<#-- @param str 待转换的文本 -->
<#-- @param character 要转换成的字符 -->
<#-- @param case 转换大小写(normal 不转换,lower 小写,upper 大写) -->
<#function camelToChar(str, character, case='normal')>
<#assign text=str?replace("([a-z])([A-Z]+)","$1${character}$2","r")/>
<#if case=="upper">
<#return text?upper_case>
<#elseif case=="lower">
<#return text?lower_case>
<#else>
<#return text>
</#if>
</#function>
<#--下划线转驼峰-->
<#function dashedToCamel(str)>
<#assign text=""/>
<#assign strlist = str?split("_")/>
<#list strlist as v>
<#assign text=text+v?cap_first/>
</#list>
<#return text?uncap_first>
</#function>
<#-- 驼峰转下划线 -->
<#function camelToDashed(str, case='lower')>
<#return camelToChar(str, "_", case)>
</#function>
<#---->
<#-- 驼峰转横线 -->
<#function camelToHorizontal(str, case='normal')>
<#return camelToChar(str, "-", case)>
</#function>
<#---->
<#-- 获取 v-model 属性 -->
<#function getVModel po,suffix="">
<#return "v-model=\"queryParam.${po.fieldName}${suffix}\"">
</#function>
<#-- 获取 placeholder 属性 -->
<#function getPlaceholder po,prefix,fillComment=true>
<#if fillComment>
<#return "placeholder=\"${prefix}${po.filedComment}\"">
<#else>
<#return "placeholder=\"${prefix}\"">
</#if>
</#function>
<#-- ** 判断某字段是否配置了校验 * -->
<#function poHasCheck po>
<#if (po.fieldValidType!'')?trim?length gt 0 || po.nullable == 'N'>
<#if po.fieldName != 'id'>
<#if po.nullable == 'N'
|| po.fieldValidType == '*'
|| po.fieldValidType == 'only'
|| po.fieldValidType == 'n6-16'
|| po.fieldValidType == '*6-16'
|| po.fieldValidType == 's6-18'
|| po.fieldValidType == 'url'
|| po.fieldValidType == 'e'
|| po.fieldValidType == 'm'
|| po.fieldValidType == 'p'
|| po.fieldValidType == 's'
|| po.fieldValidType == 'n'
|| po.fieldValidType == 'z'
|| po.fieldValidType == 'money'
|| po.fieldValidType != ''
>
<#return true>
</#if>
</#if>
</#if>
<#return false>
</#function>
<#-- ** 如果配置了校验就显示 validatorRules * -->
<#function autoWriteRules po>
<#if poHasCheck(po)>
<#return ", validatorRules.${po.fieldName}">
<#else>
<#return "">
</#if>
</#function>
<#-- ** 如果Blob就显示 String * -->
<#function autoStringSuffix po>
<#if po.fieldDbType=='Blob'>
<#return "'${po.fieldName}String'">
<#else>
<#return "'${po.fieldName}'">
</#if>
</#function>
<#-- ** 如果Blob就显示model方式 String * -->
<#function autoStringSuffixForModel po>
<#if po.fieldDbType=='Blob'>
<#return "${po.fieldName}String">
<#else>
<#return "${po.fieldName}">
</#if>
</#function>
<#-- ** 高级查询生成 * -->
<#function superQueryFieldList po>
<#assign superQuery_dictTable="">
<#assign superQuery_dictText="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign superQuery_dictTable="${po.dictTable}">
</#if>
<#if po.dictText?default("")?trim?length gt 1>
<#assign superQuery_dictText="${po.dictText}">
</#if>
<#if po.classType=="popup">
<#return "{type:'${po.classType}',value:'${po.fieldName}',text:'${po.filedComment}', popup:{code:'${po.dictTable}',field:'${po.dictField?split(',')[0]}',orgFields:'${po.dictField?split(',')[0]}',destFields:'${po.dictText?split(',')[0]}'}}">
<#elseif po.classType=="sel_user" || po.classType=="sel_depart" || po.classType=="datetime" || po.classType=="date" || po.classType=="pca" || po.classType=="switch">
<#return "{type:'${po.classType}',value:'${po.fieldName}',text:'${po.filedComment}'}">
<#else>
<#if po.classType=="sel_search" || po.classType=="list_multi">
<#return "{type:'${po.classType}',value:'${po.fieldName}',text:'${po.filedComment}',dictTable:\"${superQuery_dictTable}\", dictText:'${superQuery_dictText}', dictCode:'${po.dictField}'}">
<#elseif po.dictTable?? && po.dictTable!="" && po.classType!="sel_tree" && po.classType!="cat_tree" && po.classType!="link_down">
<#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}',dictCode:\"${po.dictTable},${po.dictText},${po.dictField}\"}">
<#elseif po.dictField?? && po.classType!="sel_tree" && po.classType!="cat_tree" && po.classType!="link_down">
<#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}',dictCode:'${po.dictField}'}">
<#elseif po.fieldDbType=="Text">
<#return "{type:'string',value:'${po.fieldName}',text:'${po.filedComment}'}">
<#elseif po.fieldDbType=="Blob">
<#return "{type:'byte',value:'${po.fieldName}',text:'${po.filedComment}'}">
<#elseif po.fieldDbType=="BigDecimal" || po.fieldDbType=="double">
<#return "{type:'number',value:'${po.fieldName}',text:'${po.filedComment}'}">
<#else>
<#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}">
</#if>
</#if>
</#function>
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<#-- ** 高级查询生成(Vue3 * -->
<#function superQueryFieldListForVue3(po,order)>
<#-- 字段展示/DB类型 -->
<#assign baseAttrs="view: '${po.classType}', type: 'string',">
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<#assign baseAttrs="view: 'number', type: 'number',">
</#if>
<#-- 特殊类型控件扩展字段 -->
<#assign extAttrs="">
<#assign dictCode="">
<#if po.dictTable?default('')?trim?length gt 1 && po.dictText?default('')?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#-- update-begin---author:chenrui ---date:20231228 for:fix 带条件字典存在单引号导致js编译错误---------- -->
<#assign dictCode="dictTable: \"${po.dictTable}\", dictCode: '${po.dictField}', dictText: '${po.dictText}'">
<#-- update-begin---author:chenrui ---date:20231228 for:fix 带条件字典存在单引号导致js编译错误---------- -->
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign dictCode="dictCode: '${po.dictField}'">
<#else>
<#assign dictCode="dictCode: ''">
</#if>
<#if po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='checkbox' || po.classType=='radio'>
<#assign extAttrs="${dictCode},">
<#elseif po.classType=='cat_tree'>
<#-- 分类字典树 -->
<#-- update-begin---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#assign extAttrs="pcode: '${po.dictField?default('')}',">
<#-- update-end---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#elseif po.classType=='sel_tree'>
<#-- 自定义树 -->
<#if po.dictText??>
<#-- dictText示例:id,pid,name,has_child -->
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
<#assign extAttrs="dict: '${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}'">
<#elseif po.dictText?split(',')[1]??>
<#assign extAttrs="pidField: '${po.dictText?split(',')[1]}'">
<#elseif po.dictText?split(',')[3]??>
<#assign extAttrs="hasChildField: '${po.dictText?split(',')[3]}'">
</#if>
</#if>
<#-- update-begin---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#assign extAttrs="${extAttrs}, pidValue: '${po.dictField?default('')}',">
<#-- update-end---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#elseif po.classType=='popup'>
<#-- popup -->
<#-- update-begin---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#if po.dictText?default("")?trim?length gt 1 && po.dictText?index_of(',') gt 0 && po.dictField?default("")?trim?length gt 1>
<#-- update-begin---author:chenrui ---date:20240109 for[issue/5787]增加非空判断防止代码生成时空指针异常---------- -->
<#-- 如果有多个回填字段,找到popup字段对应的来源字段 -->
<#assign orgFieldIx=po.dictText?split(',')?seq_index_of(po.fieldDbName)>
<#assign orgField=po.dictField?split(',')[orgFieldIx]>
<#else>
<#assign orgField=po.dictField?default("")>
</#if>
<#assign extAttrs="code: '${po.dictTable?default('')}', orgFields: '${orgField}', destFields: '${po.fieldName}', popupMulti: false,">
</#if>
<#return "${po.fieldName}: {title: '${po.filedComment}',order: ${order},${baseAttrs}${extAttrs}}" >
</#function>
<#-- update-end---author:chenrui ---date:20231228 for:[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<#-- vue3 获取表单modal的宽度-->
<#function getModalWidth fieldRowNum>
<#assign modal_width = 800>
<#if fieldRowNum==2>
<#assign modal_width = 896>
<#elseif fieldRowNum==3>
<#assign modal_width = 1024>
<#elseif fieldRowNum==4>
<#assign modal_width = 1280>
</#if>
<#return modal_width>
</#function>
<#-- vue3 获取表单 colspan -->
<#function getFormSpan fieldRowNum>
<#assign form_span = 24>
<#if fieldRowNum==2>
<#assign form_span = 12>
<#elseif fieldRowNum==3>
<#assign form_span = 8>
<#elseif fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#return form_span>
</#function>
<#-- vue3 native 判断字段名不是 pidField -->
<#function isNotPidField(tableVo, fieldDbName) >
<#assign flag = true>
<#if tableVo??>
<#if tableVo.extendParams??>
<#if tableVo.extendParams.pidField?default("")?trim == fieldDbName>
<#assign flag = false>
</#if>
</#if>
</#if>
<#return flag>
</#function>
<#-- vue3 native 获取范围字段 -->
<#function getRangeField(columns) >
<#assign rangeField = "">
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode=='group'>
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time' || po.classType=='date' || po.classType=='datetime'>
<#assign rangeField = rangeField + "${po.fieldName},">
</#if>
</#if>
</#if>
</#list>
<#return rangeField>
</#function>
@@ -0,0 +1,57 @@
<#include "../utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
<#if po.fieldName != 'id'>
${po.fieldName}: [
<#assign fieldValidType = po.fieldValidType!''>
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{ validator: (rule, value, callback) => validateDuplicateValue(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}', value, this.model.id, callback)},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
],
</#if>
</#if>
@@ -0,0 +1,5 @@
validatorRules: {
<#list columns as po>
<#include "core.ftl">
</#list>
},
@@ -0,0 +1,49 @@
<#assign fieldValidType = po.fieldValidType!''>
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'}<#rt>,
<#elseif fieldValidType!=''>
{ required: false}<#rt>,
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{ validator: ${po.fieldName}Duplicatevalidate }<#rt>
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'}<#rt>,
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}<#rt>,
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},<#rt>,
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}<#rt>,
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}<#rt>,
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}<#rt>,
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'}<#rt>,
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}<#rt>,
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}<#rt>,
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'}<#rt>,
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}<#rt>,
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'}<#rt>,
<#else>
<#t>
</#if>
@@ -0,0 +1,6 @@
<#include "../../utils.ftl">
<#list columns as po>
<#if po.isShow == 'Y' && poHasCheck(po)>
${po.fieldName}: [<#include "vue3CoreNative.ftl">],
</#if>
</#list>
@@ -0,0 +1,23 @@
<#include "../utils.ftl">
<#if col.isShow == 'Y' && poHasCheck(col)>
validateRules: [
<#if col.fieldName != 'id'>
<#assign subFieldValidType = col.fieldValidType!''>
<#-- 非空校验 -->
<#if col.nullable == 'N' || subFieldValidType == '*'>
{ required: true, message: '${'$'}{title}不能为空' },
<#elseif subFieldValidType!=''>
{ required: false},
</#if>
<#-- 其他情况下,只要有值就被认为是正则校验 -->
<#if subFieldValidType?length gt 0>
<#assign subMessage = '格式不正确'>
<#if subFieldValidType == 'only' >
<#assign subMessage = '不能重复'>
</#if>
{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }
<#t>
</#if>
</#if>
],
</#if>
@@ -0,0 +1,5 @@
validatorRules: {
<#list sub.colums as po>
<#include "core.ftl">
</#list>
},
@@ -0,0 +1,275 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.oConvertUtils;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
<#assign bpm_flag=false>
<#assign has_multi_query_field=false>
<#list originalColumns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
<#assign has_multi_query_field=true>
</#if>
</#list>
<#assign enhanceJavaList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.enhanceJavaList??>
<#assign enhanceJavaList = tableVo.extendParams.enhanceJavaList?filter(enhance -> enhance??)>
</#if>
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Tag(name="${tableVo.ftlDescription}")
@RestController
@RequestMapping("/${entityPackagePath}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
/**
* 分页列表查询
*
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-分页列表查询")
@Operation(summary="${tableVo.ftlDescription}-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 查询前触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeQuery()
</#if>
</#list>
</#if>
<#if has_multi_query_field>
// 自定义查询规则
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
// 自定义多选的查询规则为:LIKE_WITH_OR
<#list originalColumns as po>
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
customeRuleMap.put("${po.fieldName}", QueryRuleEnum.LIKE_WITH_OR);
</#if>
</#list>
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap(),customeRuleMap);
<#else>
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
</#if>
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 查询后触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterQuery()
</#if>
</#list>
</#if>
return Result.OK(pageList);
}
/**
* 添加
*
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-添加")
@Operation(summary="${tableVo.ftlDescription}-添加")
@RequiresPermissions("${entityPackage}:${tableName}:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 新增前的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeAdd()
</#if>
</#list>
</#if>
<#if bpm_flag>
${entityName?uncap_first}.setBpmStatus("1");
</#if>
${entityName?uncap_first}Service.save(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 新增后的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterAdd()
</#if>
</#list>
</#if>
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-编辑")
@Operation(summary="${tableVo.ftlDescription}-编辑")
@RequiresPermissions("${entityPackage}:${tableName}:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 编辑前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeEdit()
</#if>
</#list>
</#if>
${entityName?uncap_first}Service.updateById(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 编辑后,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterEdit()
</#if>
</#list>
</#if>
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-通过id删除")
@Operation(summary="${tableVo.ftlDescription}-通过id删除")
@RequiresPermissions("${entityPackage}:${tableName}:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
${entityName?uncap_first}Service.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-批量删除")
@Operation(summary="${tableVo.ftlDescription}-批量删除")
@RequiresPermissions("${entityPackage}:${tableName}:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-通过id查询")
@Operation(summary="${tableVo.ftlDescription}-通过id查询")
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
return Result.error("未找到对应数据");
}
return Result.OK(${entityName?uncap_first});
}
/**
* 导出excel
*
* @param request
* @param ${entityName?uncap_first}
*/
@RequiresPermissions("${entityPackage}:${tableName}:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='export' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导出前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeExport()
</#if>
</#list>
</#if>
return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("${entityPackage}:${tableName}:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='import' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导入前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeImport()
</#if>
</#list>
</#if>
return super.importExcel(request, response, ${entityName}.class);
}
}
@@ -0,0 +1,93 @@
<#include "/common/utils.ftl">
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@Schema(description="${tableVo.ftlDescription}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#assign excel_ignore_classType_arr=['pca','switch','cat_tree']>
<#list originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
<#elseif po.classType=='link_table'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicCode = "${po.dictField}", dicText = "${po.dictText?split(",")[0]}"'>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}") && !excel_ignore_classType_arr?seq_contains("${po.classType}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
<#if list_field_dictCode?length gt 1>
@Dict(${list_field_dictCode?substring(2)})
</#if>
<#-- <#if po.classType!='popup'>
<#if po.dictTable?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}")
<#elseif po.dictField?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}")
</#if>
</#if>-->
</#if>
<#include "/common/blob.ftl">
</#list>
}
@@ -0,0 +1,17 @@
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
</mapper>
@@ -0,0 +1,14 @@
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
}
@@ -0,0 +1,19 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
}
@@ -0,0 +1,93 @@
<template>
<view>
<!--标题和返回-->
<cu-custom :bgColor="NavBarColor" isBack :backRouterName="backRouteName">
<block slot="backText">返回</block>
<block slot="content">${tableVo.ftlDescription}</block>
</cu-custom>
<!--表单区域-->
<view>
<form>
<#list columns as po><#rt/>
<#if po.fieldName !='id'><#rt/>
<#if po.classType =='date'>
<my-date label="${po.filedComment}" fields="day" v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"></my-date>
<#elseif po.classType =='datetime'>
<my-date label="${po.filedComment}" v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"></my-date>
<#else>
<view class="cu-form-group">
<view class="flex align-center">
<view class="title"><text space="ensp">${po.filedComment}</text></view>
<input <#if "int,BigDecimal,double,"?contains(po.fieldDbType)>type="number"</#if> placeholder="请输入${po.filedComment}" v-model="model.${po.fieldName}"/>
</view>
</view>
</#if>
</#if>
</#list>
<view class="padding">
<button class="cu-btn block bg-blue margin-tb-sm lg" @click="onSubmit">
<text v-if="loading" class="cuIcon-loading2 cuIconfont-spin"></text>提交
</button>
</view>
</form>
</view>
</view>
</template>
<script>
import myDate from '@/components/my-componets/my-date.vue'
export default {
name: "${entityName}Form",
components:{ myDate },
props:{
formData:{
type:Object,
default:()=>{},
required:false
}
},
data(){
return {
CustomBar: this.CustomBar,
NavBarColor: this.NavBarColor,
loading:false,
model: {},
backRouteName:'index',
url: {
queryById: "/${entityPackagePath}/${entityName?uncap_first}/queryById",
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
},
}
},
created(){
this.initFormData();
},
methods:{
initFormData(){
if(this.formData){
let dataId = this.formData.dataId;
this.$http.get(this.url.queryById,{params:{id:dataId}}).then((res)=>{
if(res.data.success){
console.log("表单数据",res);
this.model = res.data.result;
}
})
}
},
onSubmit() {
let myForm = {...this.model};
this.loading = true;
let url = myForm.id?this.url.edit:this.url.add;
this.$http.post(url,myForm).then(res=>{
console.log("res",res)
this.loading = false
this.$Router.push({name:this.backRouteName})
}).catch(()=>{
this.loading = false
});
}
}
}
</script>
@@ -0,0 +1,44 @@
<template>
<view>
<!--标题和返回-->
<cu-custom :bgColor="NavBarColor" isBack>
<block slot="backText">返回</block>
<block slot="content">${tableVo.ftlDescription}</block>
</cu-custom>
<!--滚动加载列表-->
<mescroll-body ref="mescrollRef" bottom="88" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" @up="upCallback">
<view class="cu-list menu">
<view class="cu-item" v-for="(item,index) in list" :key="index" @click="goHome">
<view class="flex" style="width:100%">
<text class="text-lg" style="color: #000;">
{{ item.createBy}}
</text>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import Mixin from "@/common/mixin/Mixin.js";
export default {
name: '${tableVo.ftlDescription}',
mixins: [MescrollMixin,Mixin],
data() {
return {
CustomBar:this.CustomBar,
NavBarColor:this.NavBarColor,
url: "/${entityPackagePath}/${entityName?uncap_first}/list",
};
},
methods: {
goHome(){
this.$Router.push({name: "index"})
}
}
}
</script>
@@ -0,0 +1,49 @@
import { render } from '@/common/renderUtils';
//列表数据
export const columns = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderImage,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
dataIndex: '${po.fieldName}_dictText'
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
@@ -0,0 +1,560 @@
<#include "/common/utils.ftl">
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationStyle: 'custom',
navigationBarTitleText: '${tableVo.ftlDescription}',
},
}
</route>
<template>
<#assign onlyFields = []>
<PageLayout :navTitle="navTitle" :backRouteName="backRouteName">
<scroll-view class="scrollArea" scroll-y>
<view class="form-container">
<wd-form ref="form" :model="myFormData">
<wd-cell-group border>
<#list columns as po><#rt/>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<view class="{ 'mt-14px': ${po_index % 2} == 0 }">
<#if po.fieldName !='id' && po.isShow =='Y' && po.fieldName !='delFlag'><#rt/>
<#if po.classType =='image'>
<!-- 图片 -->
<wd-cell
:title="get4Label('${po.filedComment}')"
title-width="100px"
<#if po.nullable == 'N'>
:required="true"
</#if>
>
<online-image
v-model:value="myFormData[${autoStringSuffix(po)}]"
name=${autoStringSuffix(po)}
<#if po.uploadnum??>
:maxNum="${po.uploadnum}"
</#if>
/>
</wd-cell>
<#elseif po.classType =='file'>
<wd-cell
:title="get4Label('${po.filedComment}')"
title-width="100px"
<#if po.nullable == 'N'>
:required="true"
</#if>
>
<online-file-custom
v-model:value="myFormData[${autoStringSuffix(po)}]"
name=${autoStringSuffix(po)}
></online-file-custom>
</wd-cell>
<#elseif po.classType =='datetime' || po.classType =='time'>
<DateTime
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
<#if po.classType =='datetime'>
format="YYYY-MM-DD HH:mm:ss"
<#else>
format="HH:mm:ss"
</#if>
name=${autoStringSuffix(po)}
v-model="myFormData[${autoStringSuffix(po)}]"
></DateTime>
<#elseif po.classType =='date'>
<online-date
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
<#if po.extendParams?exists && po.extendParams.picker?exists>
:type="getDateExtendType('${po.extendParams.picker}')"
<#else>
type="${po.classType}"
</#if>
name=${autoStringSuffix(po)}
v-model:value="myFormData[${autoStringSuffix(po)}]"
></online-date>
<#elseif po.classType =='switch'>
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<!-- 开关 -->
<wd-cell
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
title-width="100px"
center
>
<wd-switch
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
size="18px"
v-model="myFormData[${autoStringSuffix(po)}]"
active-value="${switch_extend_arr[0]}"
inactive-value="${switch_extend_arr[1]}"
/>
</wd-cell>
<#elseif po.classType =='list' || po.classType =='sel_search'>
<online-select
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
name=${autoStringSuffix(po)}
dict="${form_field_dictCode}"
v-model="myFormData[${autoStringSuffix(po)}]"
></online-select>
<#elseif po.classType =='checkbox'>
<online-checkbox
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
name=${autoStringSuffix(po)}
dict="${form_field_dictCode}"
v-model="myFormData[${autoStringSuffix(po)}]"
></online-checkbox>
<#elseif po.classType =='radio'>
<online-radio
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
name=${autoStringSuffix(po)}
dict="${form_field_dictCode}"
v-model="myFormData[${autoStringSuffix(po)}]"
></online-radio>
<#elseif po.classType =='list_multi'>
<online-multi
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
name=${autoStringSuffix(po)}
dict="${form_field_dictCode}"
v-model="myFormData[${autoStringSuffix(po)}]"
></online-multi>
<#elseif po.classType =='textarea' || po.classType =='markdown' || po.classType =='umeditor'>
<wd-textarea
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
type="${po.classType}"
name=${autoStringSuffix(po)}
prop=${autoStringSuffix(po)}
clearable
:maxlength="300"
v-model="myFormData[${autoStringSuffix(po)}]"
></wd-textarea>
<#elseif po.classType =='password'>
<wd-input
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
show-password
name=${autoStringSuffix(po)}
prop=${autoStringSuffix(po)}
clearable
v-model="myFormData[${autoStringSuffix(po)}]"
></wd-input>
<#elseif po.classType =='pca'>
<online-pca
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
name=${autoStringSuffix(po)}
prop=${autoStringSuffix(po)}
clearable
v-model:value="myFormData[${autoStringSuffix(po)}]"
></online-pca>
<#elseif po.classType =='popup_dict'>
<PopupDict
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
v-model="myFormData[${autoStringSuffix(po)}]"
:multi="${po.extendParams.popupMulti?c}"
dictCode="${po.dictTable},${po.dictText},${po.dictField}"
></PopupDict>
<#elseif po.classType =='popup'>
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
<Popup
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
v-model="myFormData[${autoStringSuffix(po)}]"
:multi="${po.extendParams.popupMulti?c}"
code="${po.dictTable}"
:setFieldsValue="setFieldsValue"
:fieldConfig="[
<#list sourceFields as fieldName>
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
</#list>
]"
></Popup>
<#elseif po.classType =='link_table'>
<online-popup-link-record
:label="get4Label('${po.filedComment}')"
labelWidth="100px"
name=${autoStringSuffix(po)}
:formSchema="getFormSchema('${po.dictTable}','${po.dictField}','${po.dictText}')"
v-model:value="myFormData[${autoStringSuffix(po)}]"
></online-popup-link-record>
<#elseif po.classType =='sel_user'>
<select-user
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
v-model="myFormData[${autoStringSuffix(po)}]"
<#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if>
></select-user>
<#elseif po.classType =='sel_depart'>
<select-dept
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
v-model="myFormData[${autoStringSuffix(po)}]"
<#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if>
:multiple="${po.extendParams.multi?default('true')}"
></select-dept>
<#elseif po.classType =='cat_tree'>
<CategorySelect
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
v-model="myFormData[${autoStringSuffix(po)}]"
pcode="${po.dictField?default("")}"
></CategorySelect>
<#elseif po.classType =='sel_tree'>
<TreeSelect
labelWidth="100px"
:label="get4Label('${po.filedComment}')"
v-model="myFormData[${autoStringSuffix(po)}]"
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
<#elseif po.dictText?split(',')[1]??>
pidField="${po.dictText?split(',')[1]}"
<#elseif po.dictText?split(',')[3]??>
hasChildField="${po.dictText?split(',')[3]}"
</#if>
</#if>
:pidValue="`${po.dictField}`"
></TreeSelect>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<wd-input
label-width="100px"
v-model="myFormData[${autoStringSuffix(po)}]"
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
prop=${autoStringSuffix(po)}
placeholder="请选择${po.filedComment}"
inputMode="numeric"
:rules="[
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 6到16位数字 -->
<#if fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字母 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 唯一校验 -->
<#elseif fieldValidType != '' && fieldValidType == 'only'>
<#assign onlyFields = onlyFields + [autoStringSuffix(po)]>
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: /${fieldValidType}/, message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
</#if>
]"
clearable
/>
<#else>
<wd-input
label-width="100px"
v-model="myFormData[${autoStringSuffix(po)}]"
:label="get4Label('${po.filedComment}')"
name=${autoStringSuffix(po)}
prop=${autoStringSuffix(po)}
placeholder="请选择${po.filedComment}"
:rules="[
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 6到16位数字 -->
<#if fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字母 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 唯一校验 -->
<#elseif fieldValidType != '' && fieldValidType == 'only'>
<#assign onlyFields = onlyFields + [autoStringSuffix(po)]>
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: /${fieldValidType}/, message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
</#if>
]"
clearable
/>
</#if>
</#if>
</view>
</#list>
</wd-cell-group>
</wd-form>
</view>
</scroll-view>
<view class="footer">
<wd-button :disabled="loading" block :loading="loading" @click="handleSubmit">提交</wd-button>
</view>
</PageLayout>
</template>
<script lang="ts" setup>
import { onLoad } from '@dcloudio/uni-app'
import { http } from '@/utils/http'
import { useToast } from 'wot-design-uni'
import { useRouter } from '@/plugin/uni-mini-router'
import { ref, onMounted, computed,reactive } from 'vue'
import OnlineImage from '@/components/online/view/online-image.vue'
import OnlineFile from '@/components/online/view/online-file.vue'
import OnlineFileCustom from '@/components/online/view/online-file-custom.vue'
import OnlineSelect from '@/components/online/view/online-select.vue'
import OnlineTime from '@/components/online/view/online-time.vue'
import OnlineDate from '@/components/online/view/online-date.vue'
import OnlineRadio from '@/components/online/view/online-radio.vue'
import OnlineCheckbox from '@/components/online/view/online-checkbox.vue'
import OnlineMulti from '@/components/online/view/online-multi.vue'
import OnlinePopupLinkRecord from '@/components/online/view/online-popup-link-record.vue'
import OnlinePca from '@/components/online/view/online-pca.vue'
import SelectDept from '@/components/SelectDept/SelectDept.vue'
import SelectUser from '@/components/SelectUser/SelectUser.vue'
import {duplicateCheck} from "@/service/api";
defineOptions({
name: '${entityName}Form',
options: {
styleIsolation: 'shared',
},
})
const toast = useToast()
const router = useRouter()
const form = ref(null)
// 定义响应式数据
const myFormData = reactive({})
const loading = ref(false)
const navTitle = ref('新增')
const dataId = ref('')
const backRouteName = ref('${entityName}List')
// 定义 initForm 方法
const initForm = (item) => {
console.log('initForm item', item)
if(item?.dataId){
dataId.value = item.dataId;
navTitle.value = item.dataId?'编辑':'新增';
initData();
}
}
// 初始化数据
const initData = () => {
http.get("/${entityPackagePath}/${entityName?uncap_first}/queryById",{id:dataId.value}).then((res) => {
if (res.success) {
let obj = res.result
Object.assign(myFormData, { ...obj })
}else{
toast.error(res?.message || '表单加载失败!')
}
})
}
const handleSuccess = () => {
uni.$emit('refreshList');
router.back()
}
/**
* 校验唯一
* @param values
* @returns {boolean}
*/
async function fieldCheck(values: any) {
const onlyField = [
<#list onlyFields as field>
${field}<#sep>, </#sep>
</#list>
];
for (const field of onlyField) {
if (values[field]) {
// 仅校验有值的字段
const res: any = await duplicateCheck({
tableName: '${tableName}',
fieldName: field, // 使用处理后的字段名
fieldVal: values[field],
dataId: values.id,
});
if (!res.success) {
toast.warning(res.message);
return true; // 校验失败
}
}
}
return false; // 校验通过
}
// 提交表单
const handleSubmit = async () => {
// 判断字段必填和正则
if (await fieldCheck(myFormData)) {
return
}
let url = dataId.value?'/${entityPackagePath}/${entityName?uncap_first}/edit':'/${entityPackagePath}/${entityName?uncap_first}/add';
form.value
.validate()
.then(({ valid, errors }) => {
if (valid) {
loading.value = true;
http.post(url,myFormData).then((res) => {
loading.value = false;
if (res.success) {
toast.success('保存成功');
handleSuccess()
}else{
toast.error(res?.message || '表单保存失败!')
}
})
}
})
.catch((error) => {
console.log(error, 'error')
loading.value = false;
})
}
// 标题
const get4Label = computed(() => {
return (label) => {
return label && label.length > 4 ? label.substring(0, 4) : label;
}
})
// 标题
const getFormSchema = computed(() => {
return (dictTable,dictCode,dictText) => {
return {
dictCode,
dictTable,
dictText
};
}
})
/**
* 获取日期控件的扩展类型
* @param picker
* @returns {string}
*/
const getDateExtendType = (picker: string) => {
let mapField = {
month: 'year-month',
year: 'year',
quarter: 'quarter',
week: 'week',
day: 'date',
}
return picker && mapField[picker]
? mapField[picker]
: 'date'
}
//设置pop返回值
const setFieldsValue = (data) => {
Object.assign(myFormData, {...data })
}
// onLoad 生命周期钩子
onLoad((option) => {
initForm(option)
})
</script>
<style lang="scss" scoped>
.footer {
width: 100%;
padding: 10px 20px;
padding-bottom: calc(constant(safe-area-inset-bottom) + 10px);
padding-bottom: calc(env(safe-area-inset-bottom) + 10px);
}
:deep(.wd-cell__label) {
font-size: 14px;
color: #444;
}
:deep(.wd-cell__value) {
text-align: left;
}
</style>
@@ -0,0 +1,148 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationBarTitleText: '${tableVo.ftlDescription}',
navigationStyle: 'custom',
},
}
</route>
<template>
<PageLayout navTitle="${tableVo.ftlDescription}" backRouteName="index" routeMethod="pushTab">
<view class="wrap">
<z-paging
ref="paging"
:fixed="false"
v-model="dataList"
@query="queryList"
:default-page-size="15"
>
<template v-for="item in dataList" :key="item.id">
<wd-swipe-action>
<view class="list" @click="handleEdit(item)">
<template v-for="(cItem, cIndex) in columns" :key="cIndex">
<view v-if="cIndex < 3" class="box" :style="getBoxStyle">
<view class="field ellipsis">{{ cItem.title }}</view>
<view class="value cu-text-grey">{{ item[cItem.dataIndex] }}</view>
</view>
</template>
</view>
<template #right>
<view class="action">
<view class="button" @click="handleAction('del', item)">删除</view>
</view>
</template>
</wd-swipe-action>
</template>
</z-paging>
<view class="add u-iconfont u-icon-add" @click="handleAdd"></view>
</view>
</PageLayout>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { http } from '@/utils/http'
import usePageList from '@/hooks/usePageList'
import {columns} from './${entityName}Data';
defineOptions({
name: '${entityName}List',
options: {
styleIsolation: 'shared',
}
})
//分页加载配置
let { toast, router, paging, dataList, queryList } = usePageList('/${entityPackagePath}/${entityName?uncap_first}/list');
//样式
const getBoxStyle = computed(() => {
return { width: "calc(33% - 5px)" }
})
// 其他操作
const handleAction = (val, item) => {
if (val == 'del') {
http.delete("/${entityPackagePath}/${entityName?uncap_first}/delete?id="+item.id,{id:item.id}).then((res) => {
toast.success('删除成功~')
paging.value.reload()
})
}
}
// go 新增页
const handleAdd = () => {
router.push({
name: '${entityName}Form'
})
}
//go 编辑页
const handleEdit = (record) => {
router.push({
name: '${entityName}Form',
params: {dataId: record.id},
})
}
onMounted(() => {
// 监听刷新列表事件
uni.$on('refreshList', () => {
queryList(1,10)
})
})
</script>
<style lang="scss" scoped>
.wrap {
height: 100%;
}
:deep(.wd-swipe-action) {
margin-top: 10px;
background-color: #fff;
}
.list {
padding: 10px 10px;
width: 100%;
text-align: left;
display: flex;
justify-content: space-between;
.box {
width: 33%;
.field {
margin-bottom: 10px;
line-height: 20px;
}
}
}
.action {
width: 60px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.button {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
color: #fff;
&:first-child {
background-color: #fa4350;
}
}
}
.add {
height: 70upx;
width: 70upx;
text-align: center;
line-height: 70upx;
background-color: #fff;
border-radius: 50%;
position: fixed;
bottom: 80upx;
right: 30upx;
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.1);
color: #666;
}
</style>
@@ -0,0 +1,426 @@
<#include "/common/utils.ftl">
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<#assign query_field_no=0>
<#assign query_flag=false>
<#assign list_need_dict=false>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign list_need_switch=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :xl="6" :lg="7" :md="8" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='sel_search'>
<#if query_field_no gt 1> </#if><j-search-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.classType=='sel_user'>
<#if query_field_no gt 1> </#if><j-select-user-by-dep placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='switch'>
<#if query_field_no gt 1> </#if><j-switch placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query></j-switch>
<#elseif po.classType=='sel_depart'>
<#if query_field_no gt 1> </#if><j-select-depart placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='list_multi'>
<#if query_field_no gt 1> </#if><j-multi-select-tag placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='cat_tree'>
<#if query_field_no gt 1> </#if><j-category-select placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}"/>
<#elseif po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :xl="10" :lg="11" :md="12" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
<#assign list_need_dict=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
<#if po.classType=='switch'>
<#assign list_need_switch=true>
</#if>
</#list>
<#-- 结束循环 -->
<#t>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
<#if tableVo.extendParams.scroll=='1'>
:scroll="{x:true}"
</#if>
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<#if list_need_pca>
<template slot="pcaSlot" slot-scope="text">
<div>{{ getPcaText(text) }}</div>
</template>
</#if>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleDetail(record)">详情</a>
</a-menu-item>
<#if bpm_flag>
<a-menu-item v-if="record.bpmStatus === '1'">
<a @click="startProcess(record)">发起流程</a>
</a-menu-item>
</#if>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${Format.humpToShortbar(entityName)}-modal ref="modalForm" @ok="modalFormOk"></${Format.humpToShortbar(entityName)}-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
<#if bpm_flag>
import { postAction } from '@/api/manage'
</#if>
<#if list_need_category>
import { loadCategoryData } from '@/api/api'
</#if>
<#if list_need_dict>
import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
</#if>
<#if list_need_pca>
import Area from '@/components/_util/Area'
</#if>
export default {
name: '${entityName}List',
mixins:[JeecgListMixin, mixinDevice],
components: {
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
<#assign showColNum=0>
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
<#assign showColNum=showColNum+1>
{
title:'${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'htmlSlot'}
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'pcaSlot'}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : ''),
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
<#if list_need_category>
dataIndex: '${po.fieldName}',
customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : '')
<#else>
dataIndex: '${po.fieldName}',
customRender: (text, record) => (text ? record['${dashedToCamel(po.dictText)}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
<#if tableVo.extendParams.scroll=='1'>
fixed:"right",
width:147,
</#if>
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/${entityPackagePath}/${entityName?uncap_first}/list",
delete: "/${entityPackagePath}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackagePath}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackagePath}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackagePath}/${entityName?uncap_first}/importExcel",
<#if bpm_flag>startProcess: '/act/process/extActProcess/startMutilProcess'</#if>
},
<#if bpm_flag>
//代码生成后需手动设置流程编码
flowCode: 'dev_${tableName}_001',
</#if>
dictOptions:{},
<#if list_need_pca>
pcaData:'',
</#if>
superFieldList:[],
}
},
created() {
<#if list_need_pca>
this.pcaData = new Area()
</#if>
<#if list_need_switch>
<#list columns as po>
<#if po.classType=='switch'>
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
this.$set(this.dictOptions, '${po.fieldName}', [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
</#if>
</#list>
</#if>
this.getSuperFieldList();
},
computed: {
importExcelUrl: function(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
},
},
methods: {
<#if list_need_pca>
getPcaText(code){
return this.pcaData.getText(code);
},
</#if>
<#if bpm_flag>
startProcess(record){
this.$confirm({
title:'提示',
content:'确认提交流程吗?',
onOk:()=>{
let params = {
flowCode: this.flowCode,
id: record.id,
formUrl: '${entityPackagePath}/modules/${entityName}Form',
formUrlMobile: ''
}
postAction(this.url.startProcess, params).then(res=>{
if(res.success){
this.$message.success(res.message);
this.loadData();
this.onClearSelected();
}else{
this.$message.warning(res.message);
}
}).catch((e)=>{
this.$message.warning('不识别的请求!');
})
}
})
},
</#if>
initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
</#if>
</#if>
</#list>
},
getSuperFieldList(){
let fieldList=[];
<#list columns as po>
fieldList.push(${superQueryFieldList(po)})
</#list>
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,267 @@
<#--<#include "../../../../../../../common/utils.ftl">-->
<#include "/common/utils.ftl">
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<#assign form_popup = false>
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#assign form_span = 24>
<#if tableVo.fieldRowNum==2>
<#assign form_span = 12>
<#elseif tableVo.fieldRowNum==3>
<#assign form_span = 8>
<#elseif tableVo.fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y' && po.fieldName != 'id'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-col :span="${form_span}">
<a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
<#if po.classType =='date'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='datetime'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='time'>
<j-time placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-model="model.${po.fieldName}"
field="${po.fieldName}"
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>
<j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='switch'>
<j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
<#elseif po.classType =='pca'>
<j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='markdown'>
<j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
<#elseif po.classType =='password'>
<a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_user'>
<j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='textarea'>
<a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list' || po.classType=='radio'>
<j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='sel_search'>
<j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
<j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='file'>
<j-upload v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:number=${po.uploadnum}</#if>></j-upload>
<#elseif po.classType=='image'>
<j-image-upload isMultiple <#if po.uploadnum??>:number=${po.uploadnum}</#if> v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
<#elseif po.classType=='umeditor'>
<j-editor v-model="model.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.fieldDbType=='Blob'>
<a-input v-model="model.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
<#elseif po.classType == 'sel_tree'>
<j-tree-select
ref="treeSelect"
placeholder="请选择${po.filedComment}"
v-model="model.${po.fieldName}"
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
<#elseif po.dictText?split(',')[1]??>
pidField="${po.dictText?split(',')[1]}"
<#elseif po.dictText?split(',')[3]??>
hasChildField="${po.dictText?split(',')[3]}"
</#if>
</#if>
pidValue="${po.dictField}"
<#if po.readonly=='Y'>disabled</#if>>
</j-tree-select>
<#else>
<a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> ></a-input>
</#if>
</a-form-model-item>
</a-col>
</#if>
</#list>
<#if bpm_flag>
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
<a-button icon="check" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
</a-col>
</#if>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: '${entityName}Form',
components: {
},
props: {
<#if bpm_flag>
//流程表单data
formData: {
type: Object,
default: () => ({}),
required: false
},
//表单模式:true流程表单 false普通表单
formBpm: {
type: Boolean,
default: false,
required: false
},
</#if>
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
model:{
<#include "/common/init/initValue.ftl">
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
<#include "/common/validatorRulesTemplate/main.ftl">
url: {
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
queryById: "/${entityPackagePath}/${entityName?uncap_first}/queryById"
}
}
},
computed: {
formDisabled(){
<#if bpm_flag>
if(this.formBpm===true){
if(this.formData.disabled===false){
return false
}
return true
}
</#if>
return this.disabled
},
<#if bpm_flag>
showFlowSubmitButton(){
if(this.formBpm===true){
if(this.formData.disabled===false){
return true
}
}
return false
}
</#if>
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
<#if bpm_flag>
//如果是流程中表单,则需要加载流程表单data
this.showFlowData();
</#if>
},
methods: {
add () {
this.edit(this.modelDefault);
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
<#if bpm_flag>
//渲染流程表单数据
showFlowData(){
if(this.formBpm === true){
let params = {id:this.formData.dataId};
getAction(this.url.queryById,params).then((res)=>{
if(res.success){
this.edit (res.result);
}
});
}
},
</#if>
submitForm () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
<#if form_popup>
popupCallback(value,row){
this.model = Object.assign(this.model, row);
},
</#if>
<#if form_cat_tree>
handleCategoryChange(value,backObj){
this.model = Object.assign(this.model, backObj);
}
</#if>
}
}
</script>
@@ -0,0 +1,70 @@
<#--<#include "../../../../../../../common/utils.ftl">-->
<#include "/common/utils.ftl">
<#assign modal_width = 800>
<#if tableVo.fieldRowNum==2>
<#assign modal_width = 896>
<#elseif tableVo.fieldRowNum==3>
<#assign modal_width = 1024>
<#elseif tableVo.fieldRowNum==4>
<#assign modal_width = 1280>
</#if>
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<${Format.humpToShortbar(entityName)}-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></${Format.humpToShortbar(entityName)}-form>
</j-modal>
</template>
<script>
import ${entityName}Form from './${entityName}Form'
export default {
name: '${entityName}Modal',
components: {
${entityName}Form
},
data () {
return {
title:'',
width:${modal_width},
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
@@ -0,0 +1,93 @@
<#include "/common/utils.ftl">
<#assign modal_width = 800>
<#if tableVo.fieldRowNum==2>
<#assign modal_width = 896>
<#elseif tableVo.fieldRowNum==3>
<#assign modal_width = 1024>
<#elseif tableVo.fieldRowNum==4>
<#assign modal_width = 1280>
</#if>
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
destroyOnClose
:visible="visible">
<${Format.humpToShortbar(entityName)}-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></${Format.humpToShortbar(entityName)}-form>
<div class="drawer-footer">
<a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
<a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import ${entityName}Form from './${entityName}Form'
export default {
name: '${entityName}Modal',
components: {
${entityName}Form
},
data () {
return {
title:"操作",
width:${modal_width},
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
});
},
close () {
this.$emit('close');
this.visible = false;
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
handleCancel () {
this.close()
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
.drawer-footer{
position: absolute;
bottom: -8px;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>
@@ -0,0 +1,427 @@
<template>
<div>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign list_has_popup_dict=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='popup_dict'>
<#assign list_has_popup_dict=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template v-slot:bodyCell="{ column, record, index, text }">
<#list columns as po>
<#if po.classType=='umeditor' || po.classType=='pca' || po.classType=='file'>
<template v-if="column.dataIndex==='${po.fieldName}'">
<#if po.classType=='umeditor'>
<!--富文本件字段回显插槽-->
<div v-html="text"></div>
</#if>
<#if po.classType=='pca'>
<!--省市区字段回显插槽-->
{{ getAreaTextByCode(text) }}
</#if>
<#if po.classType=='file'>
<!--文件字段回显插槽-->
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</#if>
</template>
</#if>
</#list>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
<#if bpm_flag==true>
<!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" />
</#if>
</div>
</template>
<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
import {ref, reactive, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import ${entityName}Modal from './components/${entityName}Modal.vue'
import {columns, searchFormSchema, superQuerySchema} from './${entityName}.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
<#if list_need_pca>
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
</#if>
<#if list_need_category>
import { loadCategoryData } from '/@/api/common/api'
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
<#if list_has_popup_dict>
import {getPopDictByCode} from "@/utils/dict";
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
</#if>
<#if bpm_flag==true>
import { startProcess } from '/@/api/common/api';
const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
</#if>
const queryParam = reactive<any>({});
const checkedKeys = ref<Array<string | number>>([]);
const userStore = useUserStore();
const { createMessage } = useMessage();
//注册model
const [registerModal, {openModal}] = useModal();
//注册table数据
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
title: '${tableVo.ftlDescription}',
api: list,
columns,
canResize:false,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToNumber: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode=='group'>
<#-- update-begin---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time'>
<#-- update-end---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
</#if>
</#if>
</#if>
</#list>
],
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode=='group'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
actionColumn: {
width: 120,
fixed:'right'
},
beforeFetch: (params) => {
return Object.assign(params, queryParam);
},
<#if list_has_popup_dict>
afterFetch: afterFetch
</#if>
},
exportConfig: {
name:"${tableVo.ftlDescription}",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
})
const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: '${entityPackage}:${tableName}:edit'
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
<#if bpm_flag==true>
let dropDownAction = [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: '${entityPackage}:${tableName}:delete'
},
{
label: '审批进度',
onClick: handlePreviewPic.bind(null, record),
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
];
if(record.bpmStatus == '1'){
dropDownAction.push({
label: '发起流程',
popConfirm: {
title: '确认提交流程吗?',
confirm: handleProcess.bind(null, record),
placement: 'topLeft',
}
})
}
return dropDownAction;
<#else>
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
]
</#if>
}
<#if bpm_flag==true>
/**
* 提交流程
*/
async function handleProcess(record) {
let params = {
flowCode: 'dev_${tableName}_001',
id: record.id,
formUrl: '${entityPackagePath}/components/${entityName}Form',
formUrlMobile: ''
}
await startProcess(params);
handleSuccess();
}
/**
* 审批进度
*/
async function handlePreviewPic(record) {
bpmPicModal(true, {
flowCode: 'dev_${tableName}_001',
dataId: record.id,
});
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
<#if btn.buttonStyle=='link'>
function handle${btn.buttonCode?cap_first}(record){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
<#if list_need_category>
/**
* 初始化字典配置
*/
function initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
const allDictDate = userStore.getAllDictItems;
if(!allDictDate['${po.dictField?default("")}']){
userStore.setAllDictItems({...allDictDate,'${po.dictField?default("")}':res});
}
}
})
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
<#if list_has_popup_dict>
/**
* 翻译Popup字典配置
*/
async function afterFetch(records){
<#list columns as po>
<#if po.isQuery=='Y' || po.isShowList=='Y'>
<#if po.classType=='popup_dict' && list_has_popup_dict==true>
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
records.forEach((item) => {
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
});
}
</#if>
</#if>
</#list>
return records;
}
</#if>
</script>
<style lang="less" scoped>
<#include "/common/form/vue3SearchStyle.ftl">
</style>
@@ -0,0 +1,64 @@
import {defHttp} from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/${entityPackagePath}/${entityName?uncap_first}/list',
save='/${entityPackagePath}/${entityName?uncap_first}/add',
edit='/${entityPackagePath}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackagePath}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackagePath}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackagePath}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackagePath}/${entityName?uncap_first}/exportXls',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除单个
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
@@ -0,0 +1,532 @@
<#include "/common/utils.ftl">
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
text = !text ? "" : (text.length > 10 ? text.substr(0,10) : text);
<#if po.extendParams?exists && po.extendParams.picker?exists>
if(text) {
return getWeekMonthQuarterYear(text)['${po.extendParams.picker}'];
} else {
return text;
}
<#else>
return text;
</#if>
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderImage,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict' || po.classType=='link_table'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isQuery=='Y' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: ${autoStringSuffix(po)},
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
component: 'JSelectUser',
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
query:true,
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType=='list_multi'>
component: 'JSelectMultiple',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}",
</#if>
triggerChange: true
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueFormat: 'YYYY-MM-DD'
},
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true,
valueFormat: 'YYYY-MM-DD HH:mm:ss'
},
<#elseif po.classType =='time'>
component: 'TimePicker',
componentProps: {
valueFormat: 'HH:mm:ss'
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
componentProps: {
saveCode: 'region',
},
<#elseif po.classType=='popup'>
<#include "/common/form/vue3popup.ftl">
<#elseif po.classType=='popup_dict'>
component: 'JPopupDict',
componentProps: {
placeholder: '请选择${po.filedComment}',
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
multi: ${po.extendParams.popupMulti?c}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JSelectMultiple',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
},
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#else>
component: 'Input',
</#if>
//colProps: {span: 6},
},
<#elseif po.queryMode=='like'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
component: 'JInput',
},
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueType: 'Date',
},
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
valueType: 'Date',
showTime:true
},
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'JRangeNumber',
<#-- update-begin---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#elseif po.classType=='time'>
component: 'RangeTime',
<#-- update-end---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#else>
component: 'Input', //TODO 范围查询
</#if>
//colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#assign id_exists = false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.fieldDbName == 'id'>
<#assign id_exists = true>
</#if>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShow =='Y' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: ${autoStringSuffix(po)},
<#-- update-begin-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
<#if po.defaultVal??>
<#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int">
defaultValue: ${po.defaultVal},
<#else>
defaultValue: "${po.defaultVal}",
</#if>
</#if>
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
<#if po.classType =='date'>
component: 'DatePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueFormat: 'YYYY-MM-DD'
},
<#elseif po.classType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss'
},
<#elseif po.classType =='time'>
component: 'TimePicker',
componentProps: {
valueFormat: 'HH:mm:ss'
},
<#elseif po.classType =='popup'>
<#include "/common/form/vue3popup.ftl">
<#elseif po.classType=='popup_dict'>
component: 'JPopupDict',
componentProps: {
placeholder: '请选择${po.filedComment}',
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
multi: ${po.extendParams.popupMulti?c}
},
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
},
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
componentProps: {
saveCode: 'region',
},
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
component: 'JSelectUser',
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType =='textarea'>
component: 'InputTextArea',
<#elseif po.classType=='list'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#elseif po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}",
type: "radio"
},
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
<#elseif po.classType=='list_multi'>
component: 'JSelectMultiple',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#elseif po.classType=='checkbox'>
component: 'JCheckbox',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
},
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
},
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
},
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
<#else>
fileMax: 0
</#if>
},
<#elseif po.classType=='umeditor'>
component: 'JEditor',
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
},
<#elseif po.classType=='link_table'>
component: 'JLinkTableCard',
componentProps: {
valueField: '${po.dictField}',
textField: '${po.dictText}',
tableName: '${po.dictTable}',
multi: <#if (po.queryMode!"") == "multi">true<#else>false</#if>
},
<#else>
component: 'Input',
</#if>
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字母 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
<#if id_exists == false>
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false
},
</#if>
];
<#-- update-begin-author:chenrui date:2023-12-28 for:[QQYUN-7527]vue3代码生成默认带上高级查询 -->
// 高级查询数据
export const superQuerySchema = {
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
${superQueryFieldListForVue3(po,po_index)},
</#if>
</#list>
};
<#-- update-end-author:chenrui date:2023-12-28 for:[QQYUN-7527]vue3代码生成默认带上高级查询 -->
/**
* 流程表单调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,71 @@
<#include "/common/utils.ftl">
<template>
<div style="min-height: 400px">
<BasicForm @register="registerForm"></BasicForm>
<div style="width: 100%;text-align: center" v-if="!formDisabled">
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
</div>
</div>
</template>
<script lang="ts">
import {BasicForm, useForm} from '/@/components/Form/index';
import {computed, defineComponent} from 'vue';
import {defHttp} from '/@/utils/http/axios';
import { propTypes } from '/@/utils/propTypes';
import {getBpmFormSchema} from '../${entityName}.data';
import {saveOrUpdate} from '../${entityName}.api';
export default defineComponent({
name: "${entityName}Form",
components:{
BasicForm
},
props:{
formData: propTypes.object.def({}),
formBpm: propTypes.bool.def(true),
},
setup(props){
const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
labelWidth: 150,
schemas: getBpmFormSchema(props.formData),
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
});
const formDisabled = computed(()=>{
if(props.formData.disabled === false){
return false;
}
return true;
});
let formData = {};
const queryByIdUrl = '/${entityPackagePath}/${entityName?uncap_first}/queryById';
async function initFormData(){
let params = {id: props.formData.dataId};
const data = await defHttp.get({url: queryByIdUrl, params});
formData = {...data}
//设置表单的值
await setFieldsValue(formData);
//默认是禁用
await setProps({disabled: formDisabled.value})
}
async function submitForm() {
let data = getFieldsValue();
let params = Object.assign({}, formData, data);
console.log('表单数据', params)
await saveOrUpdate(params, true)
}
initFormData();
return {
registerForm,
formDisabled,
submitForm,
}
}
});
</script>
@@ -0,0 +1,104 @@
<#include "/common/utils.ftl">
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${entityName}Form" />
<#if buttonList?? && buttonList?size gt 0>
<template #insertFooter>
<#list buttonList as btn>
<#if btn.buttonStyle=='form'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</template>
</#if>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../${entityName}.data';
import {saveOrUpdate} from '../${entityName}.api';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage } = useMessage();
// Emits声明
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
const isDetail = ref(false);
//表单配置
const [registerForm, { setProps,resetFields, setFieldsValue, validate, scrollToField }] = useForm({
<#if tableVo.fieldRowNum == 1>
labelWidth: 150,
</#if>
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
isDetail.value = !!data?.showFooter;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
} finally {
setModalProps({confirmLoading: false});
}
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,569 @@
<#include "/common/utils.ftl">
<template>
<div class="p-2">
<#assign query_field_no=0>
<#assign need_category = false>
<#assign need_pca = false>
<#assign need_search = false>
<#assign need_dept_user = false>
<#assign need_switch = false>
<#assign need_dept = false>
<#assign need_multi = false>
<#assign need_popup = false>
<#assign need_popup_dict = false>
<#assign need_select_tag = false>
<#assign need_select_tree = false>
<#assign need_time = false>
<#assign bpm_flag=false>
<#assign need_markdown = false>
<#assign need_upload = false>
<#assign need_image_upload = false>
<#assign need_editor = false>
<#assign need_checkbox = false>
<#assign need_range_number = false>
<#assign is_range = false>
<#assign query_flag = false>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<#assign is_like = false>
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign need_pca=true>
</#if>
<#if po.classType=='sel_search'>
<#assign need_search = true>
</#if>
<#if po.classType=='sel_user'>
<#assign need_dept_user = true>
</#if>
<#if po.classType=='sel_depart'>
<#assign need_dept = true>
</#if>
<#if po.classType=='switch'>
<#assign need_switch = true>
</#if>
<#if po.classType=='list_multi'>
<#assign need_multi = true>
</#if>
<#if po.classType=='popup'>
<#assign need_popup = true>
</#if>
<#if po.classType=='popup_dict'>
<#assign need_popup_dict = true>
</#if>
<#if po.classType=='sel_tree'>
<#assign need_select_tree = true>
</#if>
<#if po.classType=='time'>
<#assign need_time = true>
</#if>
<#if po.queryMode=='group' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
<#assign need_range_number = true>
</#if>
<#if po.queryMode=='group'>
<#assign is_range = true>
</#if>
<#if po.queryMode=='like'>
<#assign is_like = true>
</#if>
<#include "/common/form/native/vue3NativeSearch.ftl">
</#list>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
<a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
</a>
</a-col>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
<#list columns as po>
<#if po.classType=='umeditor' || po.classType=='pca' || po.classType=='file'>
<template v-if="column.dataIndex==='${po.fieldName}'">
<#if po.classType=='umeditor'>
<!--富文本件字段回显插槽-->
<div v-html="text"></div>
</#if>
<#if po.classType=='pca'>
<!--省市区字段回显插槽-->
{{ getAreaTextByCode(text) }}
</#if>
<#if po.classType=='file'>
<!--文件字段回显插槽-->
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</#if>
</template>
</#if>
</#list>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal>
<#if bpm_flag==true>
<!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" />
</#if>
</div>
</template>
<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './${entityName}.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './${entityName}.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
import {useModal} from '/@/components/Modal';
<#include "/common/form/native/vue3NativeImport.ftl">
<#if need_category>
import { loadCategoryData } from '/@/api/common/api';
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
<#if need_pca>
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
</#if>
<#if need_popup_dict>
import {getPopDictByCode} from "@/utils/dict";
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
</#if>
<#if bpm_flag==true>
import { startProcess } from '/@/api/common/api';
const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
</#if>
<#if is_range>
import { cloneDeep } from "lodash-es";
</#if>
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
const { createMessage } = useMessage();
//注册table数据
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '${tableVo.ftlDescription}',
api: list,
columns,
canResize:false,
useSearchForm: false,
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
<#if is_range>
let rangerQuery = await setRangeQuery();
return Object.assign(params, rangerQuery);
<#else>
return Object.assign(params, queryParam);
</#if>
},
<#if need_popup_dict>
afterFetch: afterFetch
</#if>
},
exportConfig: {
name: "${tableVo.ftlDescription}",
url: getExportUrl,
<#if is_range>
params: setRangeQuery,
<#else>
params: queryParam,
</#if>
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:4,
xl:6,
xxl:4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
searchQuery();
}
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.add();
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.edit(record);
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: '${entityPackage}:${tableName}:edit'
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
<#if bpm_flag==true>
let dropDownAction = [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: '${entityPackage}:${tableName}:delete'
},
{
label: '审批进度',
onClick: handlePreviewPic.bind(null, record),
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
];
if(record.bpmStatus == '1'){
dropDownAction.push({
label: '发起流程',
popConfirm: {
title: '确认提交流程吗?',
confirm: handleProcess.bind(null, record),
placement: 'topLeft',
}
})
}
return dropDownAction;
<#else>
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
]
</#if>
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//刷新数据
reload();
}
<#if need_popup>
/**
* popup组件值改变事件
*/
function setFieldsValue(map) {
Object.keys(map).map((key) => {
queryParam[key] = map[key];
});
}
</#if>
<#if need_pca || need_dept_user>
/**
* form点击事件(以逗号分割)
* @param key
* @param value
*/
function handleFormJoinChange(key, value) {
if (typeof value != 'string') {
queryParam[key] = value.join(',');
}
}
</#if>
<#if bpm_flag==true>
/**
* 提交流程
*/
async function handleProcess(record) {
let params = {
flowCode: 'dev_${tableName}_001',
id: record.id,
formUrl: '${entityPackagePath}/components/${entityName}Form',
formUrlMobile: ''
}
await startProcess(params);
handleSuccess();
}
/**
* 审批进度
*/
async function handlePreviewPic(record) {
bpmPicModal(true, {
flowCode: 'dev_${tableName}_001',
dataId: record.id,
});
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
<#if btn.buttonStyle=='link'>
function handle${btn.buttonCode?cap_first}(record){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
<#if need_category>
/**
* form点击事件
* @param value
*/
function handleFormChange(key, value) {
queryParam[key] = value;
}
/**
* 初始化字典配置
*/
function initDictConfig() {
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
const allDictDate = userStore.getAllDictItems;
if(!allDictDate['${po.dictField?default("")}']){
userStore.setAllDictItems({...allDictDate,'${po.dictField?default("")}':res});
}
}
});
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
<#if is_range>
let rangeField = '${getRangeField(columns)}'
/**
* 设置范围查询条件
*/
async function setRangeQuery(){
let queryParamClone = cloneDeep(queryParam);
if (rangeField) {
let fieldsValue = rangeField.split(',');
fieldsValue.forEach(item => {
if (queryParamClone[item]) {
let range = queryParamClone[item];
queryParamClone[item+'_begin'] = range[0];
queryParamClone[item+'_end'] = range[1];
delete queryParamClone[item];
} else {
queryParamClone[item+'_begin'] = '';
queryParamClone[item+'_end'] = '';
}
})
}
return queryParamClone;
}
</#if>
<#if need_popup_dict>
/**
* 翻译Popup字典配置
*/
async function afterFetch(records){
<#list columns as po>
<#if po.isQuery=='Y' || po.isShowList=='Y'>
<#if po.classType=='popup_dict'>
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
records.forEach((item) => {
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
});
}
</#if>
</#if>
</#list>
return records;
}
</#if>
</script>
<style lang="less" scoped>
<#include "/common/form/native/vueNativeSearchStyle.ftl">
</style>
@@ -0,0 +1,72 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/${entityPackagePath}/${entityName?uncap_first}/list',
save='/${entityPackagePath}/${entityName?uncap_first}/add',
edit='/${entityPackagePath}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackagePath}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackagePath}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackagePath}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackagePath}/${entityName?uncap_first}/exportXls',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除单个
* @param params
* @param handleSuccess
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}
@@ -0,0 +1,90 @@
<#include "/common/utils.ftl">
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
{
title: '${po.filedComment}',
align: "center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
text = !text ? "" : (text.length > 10 ? text.substr(0,10) : text);
<#if po.extendParams?exists && po.extendParams.picker?exists>
if(text) {
return getWeekMonthQuarterYear(text)['${po.extendParams.picker}'];
} else {
return text;
}
<#else>
return text;
</#if>
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender: render.renderImage,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}');
},
<#else>
customRender: ({text, record}) => (text ? record['${po.dictText}'] : '');
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询数据
export const superQuerySchema = {
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
${superQueryFieldListForVue3(po,po_index)},
</#if>
</#list>
};
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
@@ -0,0 +1,246 @@
<#include "/common/utils.ftl">
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="${entityName}Form">
<a-row>
<#assign need_category = false>
<#assign bpm_flag=false>
<#assign need_pca = false>
<#assign need_search = false>
<#assign need_dept_user = false>
<#assign need_switch = false>
<#assign need_dept = false>
<#assign need_multi = false>
<#assign need_popup = false>
<#assign need_popup_dict = false>
<#assign need_select_tag = false>
<#assign need_select_tree = false>
<#assign need_time = false>
<#assign need_markdown = false>
<#assign need_upload = false>
<#assign need_image_upload = false>
<#assign need_editor = false>
<#assign need_checkbox = false>
<#assign hasOnlyValidate = false>
<#assign need_range_number = false>
<#assign is_like = false>
<#assign form_span = 24>
<#if tableVo.fieldRowNum==2>
<#assign form_span = 12>
<#elseif tableVo.fieldRowNum==3>
<#assign form_span = 8>
<#elseif tableVo.fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
<#assign hasOnlyValidate = true>
</#if>
<#assign formEntityName>${entityName}Form</#assign>
<#include "/common/form/native/vue3NativeForm.ftl">
</#list>
<#if bpm_flag>
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
</a-col>
</#if>
</a-row>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
<#include "/common/form/native/vue3NativeImport.ftl">
import { getValueType } from '/@/utils';
import { saveOrUpdate } from '../${entityName}.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
<#if hasOnlyValidate == true>
import { duplicateValidate } from '/@/utils/helper/validator'
</#if>
<#if bpm_flag>
import { usePermission } from '/@/hooks/web/usePermission';
const { isDisabledAuth, hasPermission, initBpmFormData } = usePermission();
</#if>
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({})},
formBpm: { type: Boolean, default: true }
});
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
<#include "/common/init/native/vue3NativeInitValue.ftl">
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//表单验证
const validatorRules = reactive({
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
// 表单禁用
const disabled = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return false;
}else{
return true;
}
}
return props.formDisabled;
});
<#if bpm_flag>
onMounted(()=>{
initBpmFormData(props.formData);
initFormData();
});
//渲染流程表单数据
const queryByIdUrl = '/${entityPackagePath}/${entityName?uncap_first}/queryById';
async function initFormData(){
if(props.formBpm === true){
let params = {id: props.formData.dataId};
const data = await defHttp.get({url: queryByIdUrl, params});
//设置表单的值
edit({...data});
}
}
// 是否显示提交按钮
const showFlowSubmitButton = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return true
}
}
return false
});
</#if>
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
*/
function edit(record) {
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if(record.hasOwnProperty(key)){
tmpData[key] = record[key]
}
})
//赋值
Object.assign(formData, tmpData);
});
}
/**
* 提交数据
*/
async function submitForm() {
try {
// 触发表单验证
await validate();
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
}
confirmLoading.value = true;
const isUpdate = ref<boolean>(false);
//时间格式化
let model = formData;
if (model.id) {
isUpdate.value = true;
}
//循环数据
for (let data in model) {
//如果该数据是数组并且是字符串类型
if (model[data] instanceof Array) {
let valueType = getValueType(formRef.value.getProps, data);
//如果是字符串类型的需要变成以逗号分割的字符串
if (valueType === 'string') {
model[data] = model[data].join(',');
}
}
}
await saveOrUpdate(model, isUpdate.value)
.then((res) => {
if (res.success) {
createMessage.success(res.message);
emit('ok');
} else {
createMessage.warning(res.message);
}
})
.finally(() => {
confirmLoading.value = false;
});
}
<#if need_popup>
/**
* popup组件值改变事件
*/
function setFieldsValue(map) {
Object.keys(map).map((key) => {
formData[key] = map[key];
});
}
</#if>
<#if need_category || need_select_tree>
/**
* 值改变事件触发
* @param key
* @param value
*/
function handleFormChange(key, value) {
formData[key] = value;
}
</#if>
<#list columns as po>
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
async function ${po.fieldName}Duplicatevalidate(_r, value) {
return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '')
}
</#if>
</#list>
defineExpose({
add,
edit,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>
@@ -0,0 +1,101 @@
<template>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
<template #footer>
<#if buttonList?? && buttonList?size gt 0>
<#list buttonList as btn>
<#if btn.buttonStyle=='form'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-button @click="handleCancel">取消</a-button>
<a-button :class="{ 'jee-hidden': disableSubmit }" type="primary" @click="handleOk">确认</a-button>
</template>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import ${entityName}Form from './${entityName}Form.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage } = useMessage();
const title = ref<string>('');
const width = ref<number>(800);
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 新增
*/
function add() {
title.value = '新增';
visible.value = true;
nextTick(() => {
registerForm.value.add();
});
}
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = disableSubmit.value ? '详情' : '编辑';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
defineExpose({
add,
edit,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>
@@ -0,0 +1,285 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.vo.LoginUser;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.vo.${entityName}Page;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service;
</#list>
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
<#assign bpm_flag=false>
<#list originalColumns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
</#list>
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Tag(name="${tableVo.ftlDescription}")
@RestController
@RequestMapping("/${entityPackagePath}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
<#list subTables as sub>
@Autowired
private I${sub.entityName}Service ${sub.entityName?uncap_first}Service;
</#list>
/**
* 分页列表查询
*
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-分页列表查询")
@Operation(summary="${tableVo.ftlDescription}-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param ${entityName?uncap_first}Page
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-添加")
@Operation(summary="${tableVo.ftlDescription}-添加")
@RequiresPermissions("${entityPackage}:${tableName}:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) {
${entityName} ${entityName?uncap_first} = new ${entityName}();
BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first});
<#if bpm_flag>
${entityName?uncap_first}.setBpmStatus("1");
</#if>
${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param ${entityName?uncap_first}Page
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-编辑")
@Operation(summary="${tableVo.ftlDescription}-编辑")
@RequiresPermissions("${entityPackage}:${tableName}:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) {
${entityName} ${entityName?uncap_first} = new ${entityName}();
BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first});
${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId());
if(${entityName?uncap_first}Entity==null) {
return Result.error("未找到对应数据");
}
${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-通过id删除")
@Operation(summary="${tableVo.ftlDescription}-通过id删除")
@RequiresPermissions("${entityPackage}:${tableName}:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
${entityName?uncap_first}Service.delMain(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-批量删除")
@Operation(summary="${tableVo.ftlDescription}-批量删除")
@RequiresPermissions("${entityPackage}:${tableName}:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-通过id查询")
@Operation(summary="${tableVo.ftlDescription}-通过id查询")
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
return Result.error("未找到对应数据");
}
return Result.OK(${entityName?uncap_first});
}
<#list subTables as sub>
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "${sub.ftlDescription}通过主表ID查询")
@Operation(summary="${sub.ftlDescription}主表ID查询")
@GetMapping(value = "/query${sub.entityName}ByMainId")
public Result<List<${sub.entityName}>> query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) {
List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id);
return Result.OK(${sub.entityName?uncap_first}List);
}
</#list>
/**
* 导出excel
*
* @param request
* @param ${entityName?uncap_first}
*/
@RequiresPermissions("${entityPackage}:${tableName}:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
// Step.1 组装查询条件查询数据
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//配置选中数据查询条件
String selections = request.getParameter("selections");
if(oConvertUtils.isNotEmpty(selections)) {
List<String> selectionList = Arrays.asList(selections.split(","));
queryWrapper.in("id",selectionList);
}
//Step.2 获取导出数据
List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper);
// Step.3 组装pageList
List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();
for (${entityName} main : ${entityName?uncap_first}List) {
${entityName}Page vo = new ${entityName}Page();
BeanUtils.copyProperties(main, vo);
<#list subTables as sub>
List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId());
vo.set${sub.entityName}List(${sub.entityName?uncap_first}List);
</#list>
pageList.add(vo);
}
// Step.4 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表");
mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class);
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}"));
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("${entityPackage}:${tableName}:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// 获取上传文件对象
MultipartFile file = entity.getValue();
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params);
for (${entityName}Page page : list) {
${entityName} po = new ${entityName}();
BeanUtils.copyProperties(page, po);
${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
}
return Result.OK("文件导入成功!数据行数:" + list.size());
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error("文件导入失败:"+e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.OK("文件导入失败!");
}
}
@@ -0,0 +1,77 @@
<#include "/common/utils.ftl">
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Schema(description="${tableVo.ftlDescription}")
@Data
@TableName("${tableName}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#list originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
<#if list_field_dictCode?length gt 1>
@Dict(${list_field_dictCode?substring(2)})
</#if>
</#if>
<#-- 大字段转换 -->
<#include "/common/blob.ftl">
</#list>
}
@@ -0,0 +1,76 @@
<#include "/common/utils.ftl">
<#list subTables as subTab>
#segment#${subTab.entityName}.java
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.util.Date;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.UnsupportedEncodingException;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Schema(description="${subTab.ftlDescription}")
@Data
@TableName("${subTab.tableName}")
public class ${subTab.entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#list subTab.originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
</#if>
<#-- 大字段转换 -->
<#include "/common/blob.ftl">
</#list>
}
</#list>
@@ -0,0 +1,17 @@
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}
@@ -0,0 +1,34 @@
<#list subTables as subTab>
#segment#${subTab.entityName}Mapper.java
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> {
/**
* 通过主表id删除子表数据
*
* @param mainId 主表id
* @return boolean
*/
public boolean deleteByMainId(@Param("mainId") String mainId);
/**
* 通过主表id查询子表数据
*
* @param mainId 主表id
* @return List<${subTab.entityName}>
*/
public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId);
}
</#list>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
</mapper>
@@ -0,0 +1,26 @@
<#list subTables as subTab>
<#assign originalForeignKeys = subTab.originalForeignKeys>
#segment#${subTab.entityName}Mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper">
<delete id="deleteByMainId" parameterType="java.lang.String">
DELETE
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</delete>
<select id="selectByMainId" parameterType="java.lang.String" resultType="${bussiPackage}.${entityPackage}.entity.${subTab.entityName}">
SELECT *
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</select>
</mapper>
</#list>
@@ -0,0 +1,54 @@
package ${bussiPackage}.${entityPackage}.service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
/**
* 添加一对多
*
* @param ${entityName?uncap_first}
<#list subTables as sub>
* @param ${sub.entityName?uncap_first}List
</#list>
*/
public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) ;
/**
* 修改一对多
*
* @param ${entityName?uncap_first}
<#list subTables as sub>
* @param ${sub.entityName?uncap_first}List
</#list>
*/
public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>);
/**
* 删除一对多
*
* @param id
*/
public void delMain (String id);
/**
* 批量删除一对多
*
* @param idList
*/
public void delBatchMain (Collection<? extends Serializable> idList);
}
@@ -0,0 +1,25 @@
<#list subTables as subTab>
#segment#I${subTab.entityName}Service.java
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> {
/**
* 通过主表id查询子表数据
*
* @param mainId 主表id
* @return List<${subTab.entityName}>
*/
public List<${subTab.entityName}> selectByMainId(String mainId);
}
</#list>
@@ -0,0 +1,105 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper;
</#list>
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.List;
import java.util.Collection;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
@Autowired
private ${entityName}Mapper ${entityName?uncap_first}Mapper;
<#list subTables as sub>
@Autowired
private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper;
</#list>
@Override
@Transactional(rollbackFor = Exception.class)
public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) {
${entityName?uncap_first}Mapper.insert(${entityName?uncap_first});
<#list subTables as sub>
if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) {
for(${sub.entityName} entity:${sub.entityName?uncap_first}List) {
<#list sub.foreignKeys as key>
//外键设置
<#if key?lower_case?index_of("${primaryKeyField}")!=-1>
entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}());
<#else>
entity.set${key?cap_first}(${entityName?uncap_first}.get${key}());
</#if>
</#list>
${sub.entityName?uncap_first}Mapper.insert(entity);
}
}
</#list>
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) {
${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first});
//1.先删除子表数据
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId());
</#list>
//2.子表数据重新插入
<#list subTables as sub>
if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) {
for(${sub.entityName} entity:${sub.entityName?uncap_first}List) {
<#list sub.foreignKeys as key>
//外键设置
<#if key?lower_case?index_of("${primaryKeyField}")!=-1>
entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}());
<#else>
entity.set${key?cap_first}(${entityName?uncap_first}.get${key}());
</#if>
</#list>
${sub.entityName?uncap_first}Mapper.insert(entity);
}
}
</#list>
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delMain(String id) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id);
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delBatchMain(Collection<? extends Serializable> idList) {
for(Serializable id:idList) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString());
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
}
}
@@ -0,0 +1,30 @@
<#list subTables as subTab>
#segment#${subTab.entityName}ServiceImpl.java
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service;
import org.springframework.stereotype.Service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service {
@Autowired
private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper;
@Override
public List<${subTab.entityName}> selectByMainId(String mainId) {
return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId);
}
}
</#list>
@@ -0,0 +1,83 @@
package ${bussiPackage}.${entityPackage}.vo;
import java.util.List;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@Schema(description="${tableVo.ftlDescription}")
public class ${entityName}Page {
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#list originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
<#if list_field_dictCode?length gt 1>
@Dict(${list_field_dictCode?substring(2)})
</#if>
</#if>
@Schema(description = "${po.filedComment}")
<#if po.fieldDbType=='Blob'>
private java.lang.String ${po.fieldName}String;
<#else>
private ${po.fieldType} ${po.fieldName};
</#if>
</#list>
<#list subTables as sub>
@ExcelCollection(name="${sub.ftlDescription}")
@Schema(description = "${sub.ftlDescription}")
private List<${sub.entityName}> ${sub.entityName?uncap_first}List;
</#list>
}
@@ -0,0 +1,397 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<#assign query_field_no=0>
<#assign query_flag=false>
<#assign list_need_dict=false>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :xl="6" :lg="7" :md="8" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='sel_search'>
<#if query_field_no gt 1> </#if><j-search-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.classType=='sel_user'>
<#if query_field_no gt 1> </#if><j-select-user-by-dep placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='sel_depart'>
<#if query_field_no gt 1> </#if><j-select-depart placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='list_multi'>
<#if query_field_no gt 1> </#if><j-multi-select-tag placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='cat_tree'>
<#if query_field_no gt 1> </#if><j-category-select placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}"/>
<#elseif po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :xl="10" :lg="11" :md="12" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
<#assign list_need_dict=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<#t>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
class="j-table-force-nowrap"
:scroll="{x:true}"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<#if list_need_pca>
<template slot="pcaSlot" slot-scope="text">
<div>{{ getPcaText(text) }}</div>
</template>
</#if>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleDetail(record)">详情</a>
</a-menu-item>
<#if bpm_flag>
<a-menu-item v-if="record.bpmStatus === '1'">
<a @click="startProcess(record)">发起流程</a>
</a-menu-item>
</#if>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${Format.humpToShortbar(entityName)}-modal ref="modalForm" @ok="modalFormOk"/>
</a-card>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
<#if list_need_category>
import { loadCategoryData } from '@/api/api'
</#if>
<#if list_need_dict>
import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
</#if>
<#if list_need_pca>
import Area from '@/components/_util/Area'
</#if>
import '@/assets/less/TableExpand.less'
<#if bpm_flag>
import { postAction } from '@/api/manage'
</#if>
export default {
name: "${entityName}List",
mixins:[JeecgListMixin],
components: {
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
<#assign showColNum=0>
<#list columns as po>
<#if po.isShowList =='Y'>
<#assign showColNum=showColNum+1>
{
title:'${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'htmlSlot'}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'pcaSlot'}
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
<#if list_need_category>
dataIndex: '${po.fieldName}',
customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : '')
<#else>
dataIndex: '${po.fieldName}',
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#if po.dictField != 'is_open'>
customRender: (text) => (!text ? "" : (text == ${po.dictField}[0] ? "是" : "否"))
<#else>
customRender: (text) => (!text ? "" : (text == "Y" ? "是" : "否"))
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' },
}
],
url: {
list: "/${entityPackagePath}/${entityName?uncap_first}/list",
delete: "/${entityPackagePath}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackagePath}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackagePath}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackagePath}/${entityName?uncap_first}/importExcel",
<#if bpm_flag>startProcess: '/act/process/extActProcess/startMutilProcess'</#if>
},
<#if bpm_flag>
flowCode: 'dev_${tableName}_001',
</#if>
dictOptions:{},
superFieldList:[],
}
},
created() {
<#if list_need_pca>
this.pcaData = new Area()
</#if>
this.getSuperFieldList();
},
computed: {
importExcelUrl: function(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
}
},
methods: {
<#if list_need_pca>
getPcaText(code){
return this.pcaData.getText(code);
},
</#if>
initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:"${po.dictField?default('')}"}).then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
</#if>
</#if>
</#list>
},
<#if bpm_flag>
startProcess(record){
this.$confirm({
title:'提示',
content:'确认提交流程吗?',
onOk:()=>{
let params = {
flowCode: this.flowCode,
id: record.id,
formUrl: '${entityPackagePath}/modules/${entityName}Form',
formUrlMobile: ''
}
postAction(this.url.startProcess, params).then(res=>{
if(res.success){
this.$message.success(res.message);
this.loadData();
this.onClearSelected();
}else{
this.$message.warning(res.message);
}
}).catch((e)=>{
this.$message.warning('不识别的请求!');
})
}
})
},
</#if>
getSuperFieldList(){
<#include "/common/utils.ftl">
let fieldList=[];
<#list columns as po>
fieldList.push(${superQueryFieldList(po)})
</#list>
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,562 @@
<#include "/common/utils.ftl">
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<!-- 主表单区域 -->
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<#assign form_popup = false>
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#assign form_span = 24>
<#if tableVo.fieldRowNum==2>
<#assign form_span = 12>
<#elseif tableVo.fieldRowNum==3>
<#assign form_span = 8>
<#elseif tableVo.fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y' && po.fieldName != 'id'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-col :span="${form_span}" >
<a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
<#if po.classType =='date'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='datetime'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='time'>
<j-time placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-model="model.${po.fieldName}"
field="${po.fieldName}"
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>
<j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='switch'>
<j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
<#elseif po.classType =='pca'>
<j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='markdown'>
<j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
<#elseif po.classType =='password'>
<a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_user'>
<j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='textarea'>
<a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list' || po.classType=='radio'>
<j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='sel_search'>
<j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
<j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='file'>
<j-upload v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:number=${po.uploadnum}</#if>></j-upload>
<#elseif po.classType=='image'>
<j-image-upload isMultiple <#if po.uploadnum??>:number=${po.uploadnum}</#if> v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
<#elseif po.classType=='umeditor'>
<j-editor v-model="model.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.fieldDbType=='Blob'>
<a-input v-model="model.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
<#elseif po.classType == 'sel_tree'>
<j-tree-select
ref="treeSelect"
placeholder="请选择${po.filedComment}"
v-model="model.${po.fieldName}"
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
<#elseif po.dictText?split(',')[1]??>
pidField="${po.dictText?split(',')[1]}"
<#elseif po.dictText?split(',')[3]??>
hasChildField="${po.dictText?split(',')[3]}"
</#if>
</#if>
pidValue="${po.dictField}"
<#if po.readonly=='Y'>disabled</#if>>
</j-tree-select>
<#else>
<a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
</#if>
</a-form-model-item>
</a-col>
</#if>
</#list>
</a-row>
</a-form-model>
</j-form-container>
<!-- 子表单区域 -->
<a-tabs v-model="activeKey" @change="handleChangeTabs">
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<${Format.humpToShortbar(sub.entityName)}-form ref="${sub.entityName?uncap_first}Form" @validateError="validateError" :disabled="formDisabled"></${Format.humpToShortbar(sub.entityName)}-form>
</a-tab-pane>
<#else>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<j-editable-table
:ref="refKeys[${sub_index}]"
:loading="${sub.entityName?uncap_first}Table.loading"
:columns="${sub.entityName?uncap_first}Table.columns"
:dataSource="${sub.entityName?uncap_first}Table.dataSource"
:maxHeight="300"
:disabled="formDisabled"
:rowNumber="true"
:rowSelection="true"
:actionButton="true"/>
</a-tab-pane>
</#if>
</#list>
</a-tabs>
<#if bpm_flag>
<a-row v-if="showFlowSubmitButton" style="text-align: center;width: 100%;margin-top: 16px;"><a-button icon="check" style="width: 126px" type="primary" @click="handleOk">提 交</a-button></a-row>
</#if>
</a-spin>
</template>
<script>
import { getAction } from '@/api/manage'
import { FormTypes,getRefPromise,VALIDATE_NO_PASSED } from '@/utils/JEditableTableUtil'
import { JEditableTableModelMixin } from '@/mixins/JEditableTableModelMixin'
import { validateDuplicateValue } from '@/utils/util'
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
import ${sub.entityName}Form from './${sub.entityName}Form.vue'
</#if>
</#list>
export default {
name: '${entityName}Form',
mixins: [JEditableTableModelMixin],
components: {
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
${sub.entityName}Form,
</#if>
</#list>
},
data() {
return {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
model:{
<#include "/common/init/initValue.ftl">
},
// 新增时子表默认添加几行空数据
addDefaultRowNum: 1,
<#include "/common/validatorRulesTemplate/main.ftl">
refKeys: [<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>],
<#assign hasOne2Many = false>
tableKeys:[<#list subTables as sub><#if sub.foreignRelationType =='0'>'${sub.entityName?uncap_first}', <#assign hasOne2Many = true></#if></#list>],
activeKey: '${subTables[0].entityName?uncap_first}',
<#list subTables as sub><#rt/>
// ${sub.ftlDescription}
${sub.entityName?uncap_first}Table: {
loading: false,
dataSource: [],
columns: [
<#if sub.foreignRelationType =='0'>
<#assign popupBackFields = "">
<#-- 循环子表的列 开始 -->
<#list sub.colums as col><#rt/>
<#if col.isShow =='Y'>
<#if col.filedComment !='外键' >
{
title: '${col.filedComment}',
key: '${autoStringSuffixForModel(col)}',
<#if col.classType =='date'>
type: FormTypes.date,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='datetime'>
type: FormTypes.datetime,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif "int,decimal,double,"?contains(col.classType)>
type: FormTypes.inputNumber,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list' || col.classType =='radio'>
type: FormTypes.select,
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list_multi' || col.classType =='checkbox'>
type: FormTypes.list_multi,
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='switch'>
type: FormTypes.checkbox,
<#if col.dictField == 'is_open'>
customValue: ['Y', 'N'],
<#else>
customValue: ${col.dictField},
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_search'>
type: FormTypes.sel_search,
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_depart'>
type: FormTypes.sel_depart,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_user'>
type: FormTypes.sel_user,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled: true,
</#if>
<#elseif col.classType =='image'>
type: FormTypes.image,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='file'>
type: FormTypes.file,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='popup'>
<#if popupBackFields?length gt 0>
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
<#else>
<#assign popupBackFields = "${col.dictText}">
</#if>
type: FormTypes.popup,
popupCode:"${col.dictTable}",
destFields:"${Format.underlineToHump(col.dictText)}",
orgFields:"${col.dictField}",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'>
type: FormTypes.inputNumber,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#else>
type: FormTypes.input,
<#if col.readonly=='Y'>
disabled:true,
</#if>
</#if>
<#if col.classType =='list_multi' || col.classType =='checkbox'>
width:"250px",
<#else>
width:"200px",
</#if>
<#if col.classType =='file'>
placeholder: '请选择文件',
<#else>
placeholder: '请输入${'$'}{title}',
</#if>
<#if col.defaultVal??>
<#if col.fieldDbType=="BigDecimal" || col.fieldDbType=="double" || col.fieldDbType=="int">
defaultValue:${col.defaultVal},
<#else>
defaultValue:"${col.defaultVal}",
</#if>
<#else>
defaultValue:'',
</#if>
<#-- 子表的校验 -->
<#assign subFieldValidType = col.fieldValidType!''>
<#-- 非空校验 -->
<#if col.nullable == 'N' || subFieldValidType == '*'>
validateRules: [{ required: true, message: '${'$'}{title}不能为空' }],
<#-- 其他情况下,只要有值就被认为是正则校验 -->
<#elseif subFieldValidType?length gt 0>
<#assign subMessage = '格式不正确'>
<#if subFieldValidType == 'only' >
<#assign subMessage = '不能重复'>
</#if>
validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }],
</#if>
},
</#if>
</#if>
</#list>
<#-- 循环子表的列 结束 -->
<#-- 处理popup的隐藏列 -->
<#if popupBackFields?length gt 0>
<#list popupBackFields?split(",") as item>
<#if item?length gt 0>
<#assign tempItemFlag = true>
<#list sub.colums as col>
<#if col.isShow =='Y' && col.fieldName == item>
<#assign tempItemFlag = false>
</#if>
</#list>
<#if tempItemFlag>
{
title: '${item}',
key: '${item}',
type:"hidden"
},
</#if>
</#if>
</#list>
</#if>
</#if>
]
},
</#list>
url: {
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
queryById: "/${entityPackagePath}/${entityName?uncap_first}/queryById",
<#list subTables as sub><#rt/>
${sub.entityName?uncap_first}: {
list: '/${entityPackagePath}/${entityName?uncap_first}/query${sub.entityName}ByMainId'
},
</#list>
}
}
},
props: {
<#if bpm_flag>
//流程表单data
formData: {
type: Object,
default: () => ({}),
required: false
},
//表单模式:false流程表单 true普通表单
formBpm: {
type: Boolean,
default: false,
required: false
},
</#if>
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
computed: {
formDisabled(){
<#if bpm_flag>
if(this.formBpm===true){
if(this.formData.disabled===false){
return false
}
return true
}
</#if>
return this.disabled
},
<#if bpm_flag>
showFlowSubmitButton(){
if(this.formBpm===true){
if(this.formData.disabled===false){
return true
}
}
return false
}
</#if>
},
created () {
<#if bpm_flag>
//如果是流程中表单,则需要加载流程表单data
this.showFlowData();
</#if>
},
methods: {
addBefore(){
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
this.$refs.${sub.entityName?uncap_first}Form.clearFormData()
<#else>
this.${sub.entityName?uncap_first}Table.dataSource=[]
</#if>
</#list>
},
getAllTable() {
<#if hasOne2Many==true>
let values = this.tableKeys.map(key => getRefPromise(this, key))
return Promise.all(values)
<#else>
return new Promise(resolve => {
resolve([]);
})
</#if>
},
/** 调用完edit()方法之后会自动调用此方法 */
editAfter() {
this.$nextTick(() => {
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
this.$refs.${sub.entityName?uncap_first}Form.initFormData(this.url.${sub.entityName?uncap_first}.list,this.model.id)
</#if>
</#list>
})
// 加载子表数据
if (this.model.id) {
let params = { id: this.model.id }
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
this.requestSubTableData(this.url.${sub.entityName?uncap_first}.list, params, this.${sub.entityName?uncap_first}Table)
</#if>
</#list>
}
},
//校验所有一对一子表表单
validateSubForm(allValues){
return new Promise((resolve,reject)=>{
Promise.all([
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
this.$refs.${sub.entityName?uncap_first}Form.validate(${sub_index}),
</#if>
</#list>
]).then(() => {
resolve(allValues)
}).catch(e => {
if (e.error === VALIDATE_NO_PASSED) {
// 如果有未通过表单验证的子表,就自动跳转到它所在的tab
this.activeKey = e.index == null ? this.activeKey : this.refKeys[e.index]
} else {
console.error(e)
}
})
})
},
/** 整理成formData */
classifyIntoFormData(allValues) {
let main = Object.assign(this.model, allValues.formValue)
return {
...main, // 展开
<#assign subManyIndex = 0>
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}List: allValues.tablesValue[${subManyIndex}].values,
<#assign subManyIndex = subManyIndex+1>
<#else>
${sub.entityName?uncap_first}List: this.$refs.${sub.entityName?uncap_first}Form.getFormData(),
</#if>
</#list>
}
},
<#if bpm_flag>
//渲染流程表单数据
showFlowData(){
if(this.formBpm === true){
let params = {id:this.formData.dataId};
getAction(this.url.queryById,params).then((res)=>{
if(res.success){
this.edit (res.result);
}
})
}
},
</#if>
validateError(msg){
this.$message.error(msg)
},
<#if form_popup>
popupCallback(value,row){
this.model = Object.assign(this.model, row);
},
</#if>
<#if form_cat_tree>
handleCategoryChange(value,backObj){
this.model = Object.assign(this.model, backObj);
}
</#if>
}
}
</script>
<style scoped>
</style>
@@ -0,0 +1,65 @@
<#include "/common/utils.ftl">
<template>
<j-modal
:title="title"
:width="1200"
:visible="visible"
:maskClosable="false"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel">
<${Format.humpToShortbar(entityName)}-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"/>
</j-modal>
</template>
<script>
import ${entityName}Form from './${entityName}Form'
export default {
name: '${entityName}Modal',
components: {
${entityName}Form
},
data() {
return {
title:'',
width:800,
visible: false,
disableSubmit: false
}
},
methods:{
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.handleOk();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
<style scoped>
</style>
@@ -0,0 +1,197 @@
<#include "/common/utils.ftl">
<#list subTables as sub>
<#if sub.foreignRelationType=='1'>
#segment#${sub.entityName}Form.vue
<template>
<j-form-container :disabled="disabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<#assign form_popup = false>
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign form_span = 24>
<#if tableVo.fieldRowNum == 2>
<#assign form_span = 12>
<#elseif tableVo.fieldRowNum==3>
<#assign form_span = 8>
<#elseif tableVo.fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#list sub.colums as po>
<#if po.isShow =='Y' && po.fieldName != 'id'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-col :span="${form_span}">
<a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
<#if po.classType =='date'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='time'>
<j-time placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-model="model.${po.fieldName}"
field="${po.fieldName}"
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='switch'>
<j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch>
<#elseif po.classType =='pca'>
<j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区"/>
<#elseif po.classType =='markdown'>
<j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
<#elseif po.classType =='password'>
<a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType =='sel_user'>
<j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='textarea'>
<a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='sel_search'>
<j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" />
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
<j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if>/>
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file'>
<j-upload v-model="model.${po.fieldName}"></j-upload>
<#elseif po.classType=='image'>
<j-image-upload isMultiple v-model="model.${po.fieldName}"></j-image-upload>
<#elseif po.classType=='umeditor'>
<j-editor v-model="model.${autoStringSuffixForModel(po)}"/>
<#elseif po.fieldDbType=='Blob'>
<a-input v-model="model.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}"></a-input>
<#else>
<a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-model-item>
</a-col>
</#if>
</#list>
</a-row>
</a-form-model>
</j-form-container>
</template>
<script>
import { getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
import { VALIDATE_NO_PASSED } from '@/utils/JEditableTableUtil'
export default {
name: '${sub.entityName}Form',
components: {
},
props:{
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
model:{
<#include "/common/init/initValueSub.ftl">
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
<#include "/common/validatorRulesTemplate/sub.ftl">
confirmLoading: false,
}
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods:{
initFormData(url,id){
this.clearFormData()
if(!id){
this.edit(this.modelDefault)
}else{
getAction(url,{id:id}).then(res=>{
if(res.success){
let records = res.result
if(records && records.length>0){
this.edit(records[0])
}
}
})
}
},
edit(record){
this.model = Object.assign({}, record)
console.log("${sub.entityName}Form-edit",this.model);
},
getFormData(){
let formdata_arr = []
this.$refs.form.validate(valid => {
if (valid) {
let isNullObj = true
Object.keys(this.model).forEach(key=>{
if(this.model[key]){
isNullObj = false
}
})
if(!isNullObj){
formdata_arr.push(this.model)
}
}else{
this.$emit("validateError","${sub.ftlDescription}表单校验未通过");
}
})
return formdata_arr;
},
validate(index){
return new Promise((resolve, reject) => {
// 验证主表表单
this.$refs.form.validate(valid => {
!valid ? reject({ error: VALIDATE_NO_PASSED ,index}) : resolve()
})
}).then(values => {
return Promise.resolve()
}).catch(error => {
return Promise.reject(error)
})
},
<#if form_popup>
popupCallback(value,row){
this.model = Object.assign(this.model, row);
},
</#if>
clearFormData(){
this.$refs.form.clearValidate()
},
<#if form_cat_tree>
handleCategoryChange(value,backObj){
this.model = Object.assign(backObj,this.model);
}
</#if>
}
}
</script>
</#if>
</#list>
@@ -0,0 +1,372 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
<#assign pidFieldName = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
</#list>
<#assign enhanceJavaList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.enhanceJavaList??>
<#assign enhanceJavaList = tableVo.extendParams.enhanceJavaList?filter(enhance -> enhance??)>
</#if>
@Tag(name="${tableVo.ftlDescription}")
@RestController
@RequestMapping("/${entityPackagePath}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service>{
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
/**
* 分页列表查询
*
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-分页列表查询")
@Operation(summary="${tableVo.ftlDescription}-分页列表查询")
@GetMapping(value = "/rootList")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 查询前触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeQuery()
</#if>
</#list>
</#if>
String hasQuery = req.getParameter("hasQuery");
if(hasQuery != null && "true".equals(hasQuery)){
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
List<${entityName}> list = ${entityName?uncap_first}Service.queryTreeListNoPage(queryWrapper);
IPage<${entityName}> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
}else{
String parentId = ${entityName?uncap_first}.get${pidFieldName?cap_first}();
if (oConvertUtils.isEmpty(parentId)) {
parentId = "0";
}
${entityName?uncap_first}.set${pidFieldName?cap_first}(null);
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
// 使用 eq 防止模糊查询
queryWrapper.eq("${Format.humpToUnderline(pidFieldName)}", parentId);
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 查询后触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterQuery()
</#if>
</#list>
</#if>
return Result.OK(pageList);
}
}
/**
* 【vue3专用】加载节点的子数据
*
* @param pid
* @return
*/
@RequestMapping(value = "/loadTreeChildren", method = RequestMethod.GET)
public Result<List<SelectTreeModel>> loadTreeChildren(@RequestParam(name = "pid") String pid) {
Result<List<SelectTreeModel>> result = new Result<>();
try {
List<SelectTreeModel> ls = ${entityName?uncap_first}Service.queryListByPid(pid);
result.setResult(ls);
result.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
result.setMessage(e.getMessage());
result.setSuccess(false);
}
return result;
}
/**
* 【vue3专用】加载一级节点/如果是同步 则所有数据
*
* @param async
* @param pcode
* @return
*/
@RequestMapping(value = "/loadTreeRoot", method = RequestMethod.GET)
public Result<List<SelectTreeModel>> loadTreeRoot(@RequestParam(name = "async") Boolean async, @RequestParam(name = "pcode") String pcode) {
Result<List<SelectTreeModel>> result = new Result<>();
try {
List<SelectTreeModel> ls = ${entityName?uncap_first}Service.queryListByCode(pcode);
if (!async) {
loadAllChildren(ls);
}
result.setResult(ls);
result.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
result.setMessage(e.getMessage());
result.setSuccess(false);
}
return result;
}
/**
* 【vue3专用】递归求子节点 同步加载用到
*
* @param ls
*/
private void loadAllChildren(List<SelectTreeModel> ls) {
for (SelectTreeModel tsm : ls) {
List<SelectTreeModel> temp = ${entityName?uncap_first}Service.queryListByPid(tsm.getKey());
if (temp != null && temp.size() > 0) {
tsm.setChildren(temp);
loadAllChildren(temp);
}
}
}
/**
* 获取子数据
* @param ${entityName?uncap_first}
* @param req
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-获取子数据")
@Operation(summary="${tableVo.ftlDescription}-获取子数据")
@GetMapping(value = "/childList")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},HttpServletRequest req) {
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
List<${entityName}> list = ${entityName?uncap_first}Service.list(queryWrapper);
IPage<${entityName}> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
}
/**
* 批量查询子节点
* @param parentIds 父ID(多个采用半角逗号分割)
* @return 返回 IPage
* @param parentIds
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-批量获取子数据")
@Operation(summary="${tableVo.ftlDescription}-批量获取子数据")
@GetMapping("/getChildListBatch")
public Result getChildListBatch(@RequestParam("parentIds") String parentIds) {
try {
QueryWrapper<${entityName}> queryWrapper = new QueryWrapper<>();
List<String> parentIdList = Arrays.asList(parentIds.split(","));
queryWrapper.in("${Format.humpToUnderline(pidFieldName)}", parentIdList);
List<${entityName}> list = ${entityName?uncap_first}Service.list(queryWrapper);
IPage<${entityName}> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("批量查询子节点失败:" + e.getMessage());
}
}
/**
* 添加
*
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-添加")
@Operation(summary="${tableVo.ftlDescription}-添加")
@RequiresPermissions("${entityPackage}:${tableName}:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 新增前的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeAdd()
</#if>
</#list>
</#if>
${entityName?uncap_first}Service.add${entityName}(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 新增后的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterAdd()
</#if>
</#list>
</#if>
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-编辑")
@Operation(summary="${tableVo.ftlDescription}-编辑")
@RequiresPermissions("${entityPackage}:${tableName}:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 编辑前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeEdit()
</#if>
</#list>
</#if>
${entityName?uncap_first}Service.update${entityName}(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 编辑后,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterEdit()
</#if>
</#list>
</#if>
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-通过id删除")
@Operation(summary="${tableVo.ftlDescription}-通过id删除")
@RequiresPermissions("${entityPackage}:${tableName}:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
${entityName?uncap_first}Service.delete${entityName}(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-批量删除")
@Operation(summary="${tableVo.ftlDescription}-批量删除")
@RequiresPermissions("${entityPackage}:${tableName}:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-通过id查询")
@Operation(summary="${tableVo.ftlDescription}-通过id查询")
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
return Result.error("未找到对应数据");
}
return Result.OK(${entityName?uncap_first});
}
/**
* 导出excel
*
* @param request
* @param ${entityName?uncap_first}
*/
@RequiresPermissions("${entityPackage}:${tableName}:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='export' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导出前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeExport()
</#if>
</#list>
</#if>
return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("${entityPackage}:${tableName}:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='import' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导入前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeImport()
</#if>
</#list>
</#if>
return super.importExcel(request, response, ${entityName}.class);
}
}
@@ -0,0 +1,91 @@
<#include "/common/utils.ftl">
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.UnsupportedEncodingException;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
@Schema(description="${tableVo.ftlDescription}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#assign excel_ignore_classType_arr=['pca','switch','cat_tree']>
<#list originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
<#elseif po.classType=='link_table'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicCode = "${po.dictField}", dicText = "${po.dictText?split(",")[0]}"'>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}") && !excel_ignore_classType_arr?seq_contains("${po.classType}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
<#-- <#if po.classType!='popup'>
<#if po.dictTable?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}")
<#elseif po.dictField?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}")
</#if>
</#if>-->
<#if list_field_dictCode?length gt 1>
@Dict(${list_field_dictCode?substring(2)})
</#if>
</#if>
<#-- 大字段转换 -->
<#include "/common/blob.ftl">
</#list>
}
@@ -0,0 +1,35 @@
package ${bussiPackage}.${entityPackage}.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.common.system.vo.SelectTreeModel;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import java.util.List;
import java.util.Map;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
/**
* 编辑节点状态
* @param id
* @param status
*/
void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status);
/**
* 【vue3专用】根据父级ID查询树节点数据
*
* @param pid
* @param query
* @return
*/
List<SelectTreeModel> queryListByPid(@Param("pid") String pid, @Param("query") Map<String, String> query);
}
@@ -0,0 +1,45 @@
<#assign hasChildrenField = "">
<#assign pidFieldName = "">
<#assign textFieldName = "">
<#assign textDbFieldName = "">
<#assign pidDbFieldName = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
<#-- begin 【vue3专用】 -->
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
<#assign pidDbFieldName = po.fieldDbName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.textField>
<#assign textFieldName = po.fieldName>
<#assign textDbFieldName = po.fieldDbName>
</#if>
<#-- end 【vue3专用】 -->
</#list>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
<update id="updateTreeNodeStatus" parameterType="java.lang.String">
update ${tableName} set ${Format.humpToUnderline(hasChildrenField)} = ${r'#'}{status} where id = ${r'#'}{id}
</update>
<!-- 【vue3专用】 -->
<select id="queryListByPid" parameterType="java.lang.Object" resultType="org.jeecg.common.system.vo.SelectTreeModel">
select
id as "key",
${textDbFieldName} as "title",
(case when ${Format.humpToUnderline(hasChildrenField)} = '1' then 0 else 1 end) as isLeaf,
${pidDbFieldName} as parentId
from ${tableName}
where ${pidDbFieldName} = ${r'#'}{pid}
<if test="query != null">
<foreach collection="query.entrySet()" item="value" index="key">
and ${r'$'}{key} = ${r'#'}{value}
</foreach>
</if>
</select>
</mapper>
@@ -0,0 +1,74 @@
package ${bussiPackage}.${entityPackage}.service;
import org.jeecg.common.system.vo.SelectTreeModel;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.exception.JeecgBootException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.List;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
/**根节点父ID的值*/
public static final String ROOT_PID_VALUE = "0";
/**树节点有子节点状态值*/
public static final String HASCHILD = "1";
/**树节点无子节点状态值*/
public static final String NOCHILD = "0";
/**
* 新增节点
*
* @param ${entityName?uncap_first}
*/
void add${entityName}(${entityName} ${entityName?uncap_first});
/**
* 修改节点
*
* @param ${entityName?uncap_first}
* @throws JeecgBootException
*/
void update${entityName}(${entityName} ${entityName?uncap_first}) throws JeecgBootException;
/**
* 删除节点
*
* @param id
* @throws JeecgBootException
*/
void delete${entityName}(String id) throws JeecgBootException;
/**
* 查询所有数据,无分页
*
* @param queryWrapper
* @return List<${entityName}>
*/
List<${entityName}> queryTreeListNoPage(QueryWrapper<${entityName}> queryWrapper);
/**
* 【vue3专用】根据父级编码加载分类字典的数据
*
* @param parentCode
* @return
*/
List<SelectTreeModel> queryListByCode(String parentCode);
/**
* 【vue3专用】根据pid查询子节点集合
*
* @param pid
* @return
*/
List<SelectTreeModel> queryListByPid(String pid);
}
@@ -0,0 +1,229 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
@Override
public void add${entityName}(${entityName} ${entityName?uncap_first}) {
//新增时设置hasChild为0
${entityName?uncap_first}.set${hasChildrenField?cap_first}(I${entityName}Service.NOCHILD);
if(oConvertUtils.isEmpty(${entityName?uncap_first}.get${pidFieldName?cap_first}())){
${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE);
}else{
//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
${entityName} parent = baseMapper.selectById(${entityName?uncap_first}.get${pidFieldName?cap_first}());
if(parent!=null && !"1".equals(parent.get${hasChildrenField?cap_first}())){
parent.set${hasChildrenField?cap_first}("1");
baseMapper.updateById(parent);
}
}
baseMapper.insert(${entityName?uncap_first});
}
@Override
public void update${entityName}(${entityName} ${entityName?uncap_first}) {
${entityName} entity = this.getById(${entityName?uncap_first}.getId());
if(entity==null) {
throw new JeecgBootException("未找到对应实体");
}
String old_pid = entity.get${pidFieldName?cap_first}();
String new_pid = ${entityName?uncap_first}.get${pidFieldName?cap_first}();
if(!old_pid.equals(new_pid)) {
updateOldParentNode(old_pid);
if(oConvertUtils.isEmpty(new_pid)){
${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE);
}
if(!I${entityName}Service.ROOT_PID_VALUE.equals(${entityName?uncap_first}.get${pidFieldName?cap_first}())) {
baseMapper.updateTreeNodeStatus(${entityName?uncap_first}.get${pidFieldName?cap_first}(), I${entityName}Service.HASCHILD);
}
}
baseMapper.updateById(${entityName?uncap_first});
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete${entityName}(String id) throws JeecgBootException {
//查询选中节点下所有子节点一并删除
id = this.queryTreeChildIds(id);
if(id.indexOf(",")>0) {
StringBuffer sb = new StringBuffer();
String[] idArr = id.split(",");
for (String idVal : idArr) {
if(idVal != null){
${entityName} ${entityName?uncap_first} = this.getById(idVal);
String pidVal = ${entityName?uncap_first}.get${pidFieldName?cap_first}();
//查询此节点上一级是否还有其他子节点
List<${entityName}> dataList = baseMapper.selectList(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pidVal).notIn("id",Arrays.asList(idArr)));
boolean flag = (dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal) && !sb.toString().contains(pidVal);
if(flag){
//如果当前节点原本有子节点 现在木有了,更新状态
sb.append(pidVal).append(",");
}
}
}
//批量删除节点
baseMapper.deleteBatchIds(Arrays.asList(idArr));
//修改已无子节点的标识
String[] pidArr = sb.toString().split(",");
for(String pid : pidArr){
this.updateOldParentNode(pid);
}
}else{
${entityName} ${entityName?uncap_first} = this.getById(id);
if(${entityName?uncap_first}==null) {
throw new JeecgBootException("未找到对应实体");
}
updateOldParentNode(${entityName?uncap_first}.get${pidFieldName?cap_first}());
baseMapper.deleteById(id);
}
}
@Override
public List<${entityName}> queryTreeListNoPage(QueryWrapper<${entityName}> queryWrapper) {
List<${entityName}> dataList = baseMapper.selectList(queryWrapper);
List<${entityName}> mapList = new ArrayList<>();
for(${entityName} data : dataList){
String pidVal = data.get${pidFieldName?cap_first}();
//递归查询子节点的根节点
if(pidVal != null && !I${entityName}Service.NOCHILD.equals(pidVal)){
${entityName} rootVal = this.getTreeRoot(pidVal);
if(rootVal != null && !mapList.contains(rootVal)){
mapList.add(rootVal);
}
}else{
if(!mapList.contains(data)){
mapList.add(data);
}
}
}
return mapList;
}
@Override
public List<SelectTreeModel> queryListByCode(String parentCode) {
String pid = ROOT_PID_VALUE;
if (oConvertUtils.isNotEmpty(parentCode)) {
LambdaQueryWrapper<${entityName}> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(${entityName}::get${pidFieldName?cap_first}, parentCode);
List<${entityName}> list = baseMapper.selectList(queryWrapper);
if (list == null || list.size() == 0) {
throw new JeecgBootException("该编码【" + parentCode + "】不存在,请核实!");
}
if (list.size() > 1) {
throw new JeecgBootException("该编码【" + parentCode + "】存在多个,请核实!");
}
pid = list.get(0).getId();
}
return baseMapper.queryListByPid(pid, null);
}
@Override
public List<SelectTreeModel> queryListByPid(String pid) {
if (oConvertUtils.isEmpty(pid)) {
pid = ROOT_PID_VALUE;
}
return baseMapper.queryListByPid(pid, null);
}
/**
* 根据所传pid查询旧的父级节点的子节点并修改相应状态值
* @param pid
*/
private void updateOldParentNode(String pid) {
if(!I${entityName}Service.ROOT_PID_VALUE.equals(pid)) {
Long count = baseMapper.selectCount(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pid));
if(count==null || count<=1) {
baseMapper.updateTreeNodeStatus(pid, I${entityName}Service.NOCHILD);
}
}
}
/**
* 递归查询节点的根节点
* @param pidVal
* @return
*/
private ${entityName} getTreeRoot(String pidVal){
${entityName} data = baseMapper.selectById(pidVal);
if(data != null && !I${entityName}Service.ROOT_PID_VALUE.equals(data.get${pidFieldName?cap_first}())){
return this.getTreeRoot(data.get${pidFieldName?cap_first}());
}else{
return data;
}
}
/**
* 根据id查询所有子节点id
* @param ids
* @return
*/
private String queryTreeChildIds(String ids) {
//获取id数组
String[] idArr = ids.split(",");
StringBuffer sb = new StringBuffer();
for (String pidVal : idArr) {
if(pidVal != null){
if(!sb.toString().contains(pidVal)){
if(sb.toString().length() > 0){
sb.append(",");
}
sb.append(pidVal);
this.getTreeChildIds(pidVal,sb);
}
}
}
return sb.toString();
}
/**
* 递归查询所有子节点
* @param pidVal
* @param sb
* @return
*/
private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){
List<${entityName}> dataList = baseMapper.selectList(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pidVal));
if(dataList != null && dataList.size()>0){
for(${entityName} tree : dataList) {
if(!sb.toString().contains(tree.getId())){
sb.append(",").append(tree.getId());
}
this.getTreeChildIds(tree.getId(),sb);
}
}
return sb;
}
}
@@ -0,0 +1,523 @@
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<#assign query_field_no=0>
<#assign query_flag=false>
<#assign list_need_dict=false>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :xl="6" :lg="7" :md="8" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='sel_search'>
<#if query_field_no gt 1> </#if><j-search-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.classType=='sel_user'>
<#if query_field_no gt 1> </#if><j-select-user-by-dep placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='switch'>
<#if query_field_no gt 1> </#if><j-switch placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query></j-switch>
<#elseif po.classType=='sel_depart'>
<#if query_field_no gt 1> </#if><j-select-depart placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='list_multi'>
<#if query_field_no gt 1> </#if><j-multi-select-tag placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model="queryParam.${po.fieldName}"/>
<#elseif po.classType=='cat_tree'>
<#if query_field_no gt 1> </#if><j-category-select placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}"/>
<#elseif po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :xl="10" :lg="11" :md="12" :sm="24">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#elseif po.classType=='datetime'>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
<#assign list_need_dict=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<#t>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<!-- 高级查询区域 -->
<j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
rowKey="id"
class="j-table-force-nowrap"
:scroll="{x:true}"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:expandedRowKeys="expandedRowKeys"
@change="handleTableChange"
@expand="handleExpand"
v-bind="tableProps">
<template slot="imgSlot" slot-scope="text,record">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="downloadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handleAddChild(record)">添加下级</a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDeleteNode(record.id)" placement="topLeft">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${entityName?uncap_first}-modal ref="modalForm" @ok="modalFormOk"></${entityName?uncap_first}-modal>
</a-card>
</template>
<script>
import { getAction, deleteAction } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
import { filterObj } from '@/utils/util';
<#if list_need_category>
import { loadCategoryData } from '@/api/api'
</#if>
<#if list_need_pca>
import Area from '@/components/_util/Area'
</#if>
export default {
name: "${entityName}List",
mixins:[JeecgListMixin],
components: {
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
<#list columns as po>
<#if po.fieldDbName==tableVo.extendParams.textField>
{
title:'${po.filedComment}',
align:"left",
dataIndex: '${po.fieldName}'
},
</#if>
</#list>
<#list columns as po>
<#if po.isShowList =='Y'>
<#if po.fieldDbName!=tableVo.extendParams.textField && po.fieldName!=pidFieldName>
{
title:'${po.filedComment}',
align:"left",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#if po.dictField != 'is_open'>
customRender: (text) => (!text ? "" : (text == ${po.dictField}[0] ? "是" : "否"))
<#else>
customRender: (text) => (!text ? "" : (text == "Y" ? "是" : "否"))
</#if>
<#elseif po.classType=='cat_tree'>
<#if list_need_category>
dataIndex: '${po.fieldName}',
customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : '')
<#else>
dataIndex: '${po.fieldName}',
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#if>
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' },
}
],
url: {
list: "/${entityPackagePath}/${entityName?uncap_first}/rootList",
childList: "/${entityPackagePath}/${entityName?uncap_first}/childList",
getChildListBatch: "/${entityPackagePath}/${entityName?uncap_first}/getChildListBatch",
delete: "/${entityPackagePath}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackagePath}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackagePath}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackagePath}/${entityName?uncap_first}/importExcel",
},
expandedRowKeys:[],
hasChildrenField:"${hasChildrenField}",
pidField:"${pidFieldName}",
dictOptions: {},
loadParent: false,
superFieldList:[],
}
},
created() {
this.getSuperFieldList();
},
computed: {
importExcelUrl(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
},
tableProps() {
let _this = this
return {
// 列表项是否可选择
rowSelection: {
selectedRowKeys: _this.selectedRowKeys,
onChange: (selectedRowKeys) => _this.selectedRowKeys = selectedRowKeys
}
}
}
},
methods: {
loadData(arg){
if(arg==1){
this.ipagination.current=1
}
this.loading = true
let params = this.getQueryParams()
params.hasQuery = 'true'
getAction(this.url.list,params).then(res=>{
if(res.success){
let result = res.result
if(Number(result.total)>0){
this.ipagination.total = Number(result.total)
this.dataSource = this.getDataByResult(res.result.records)
return this.loadDataByExpandedRows(this.dataSource)
}else{
this.ipagination.total=0
this.dataSource=[]
}
}else{
this.$message.warning(res.message)
}
}).finally(()=>{
this.loading = false
})
},
// 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
loadDataByExpandedRows(dataList) {
if (this.expandedRowKeys.length > 0) {
return getAction(this.url.getChildListBatch,{ parentIds: this.expandedRowKeys.join(',') }).then(res=>{
if (res.success && res.result.records.length>0) {
//已展开的数据批量子节点
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item[this.pidField];
if (this.expandedRowKeys.join(',').includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if(list) {
list.forEach(data => {
if (this.expandedRowKeys.includes(data.id)) {
data.children = this.getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
}
fn(dataList)
}
})
} else {
return Promise.resolve()
}
},
getQueryParams(arg) {
//获取查询条件
let sqp = {}
let param = {}
if(this.superQueryParams){
sqp['superQueryParams']=encodeURI(this.superQueryParams)
sqp['superQueryMatchType'] = this.superQueryMatchType
}
if(arg){
param = Object.assign(sqp, this.isorter ,this.filters);
}else{
param = Object.assign(sqp, this.queryParam, this.isorter ,this.filters);
}
if(JSON.stringify(this.queryParam) === "{}" || arg){
param.hasQuery = 'false'
}else{
param.hasQuery = 'true'
}
param.field = this.getQueryField();
param.pageNo = this.ipagination.current;
param.pageSize = this.ipagination.pageSize;
return filterObj(param);
},
searchReset() {
//重置
this.expandedRowKeys = []
this.queryParam = {}
this.loadData(1);
},
getDataByResult(result){
if(result){
return result.map(item=>{
//判断是否标记了带有子节点
if(item[this.hasChildrenField]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
}
},
handleExpand(expanded, record){
// 判断是否是展开状态
if (expanded) {
this.expandedRowKeys.push(record.id)
if (record.children.length>0 && record.children[0].isLoading === true) {
let params = this.getQueryParams(1);//查询条件
params[this.pidField] = record.id
params.hasQuery = 'false'
params.superQueryParams=""
getAction(this.url.childList,params).then((res)=>{
if(res.success){
if(res.result.records){
record.children = this.getDataByResult(res.result.records)
this.dataSource = [...this.dataSource]
}else{
record.children=''
record.hasChildrenField='0'
}
}else{
this.$message.warning(res.message)
}
})
}
}else{
let keyIndex = this.expandedRowKeys.indexOf(record.id)
if(keyIndex>=0){
this.expandedRowKeys.splice(keyIndex, 1);
}
}
},
handleAddChild(record){
this.loadParent = true
let obj = {}
obj[this.pidField] = record['id']
this.$refs.modalForm.add(obj);
},
handleDeleteNode(id) {
if(!this.url.delete){
this.$message.error("请设置url.delete属性!")
return
}
var that = this;
deleteAction(that.url.delete, {id: id}).then((res) => {
if (res.success) {
that.loadData(1)
} else {
that.$message.warning(res.message);
}
});
},
batchDel(){
if(this.selectedRowKeys.length<=0){
this.$message.warning('请选择一条记录!');
return false;
}else{
let ids = "";
let that = this;
that.selectedRowKeys.forEach(function(val) {
ids+=val+",";
});
that.$confirm({
title:"确认删除",
content:"是否删除选中数据?",
onOk: function(){
that.handleDeleteNode(ids)
that.onClearSelected();
}
});
}
},
getSuperFieldList(){
<#include "/common/utils.ftl">
let fieldList=[];
<#list columns as po>
fieldList.push(${superQueryFieldList(po)})
</#list>
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,246 @@
<#include "/common/utils.ftl">
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
:confirmLoading="confirmLoading"
switchFullscreen
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form-model ref="form" :model="model" :rules="validatorRules">
<#assign pidFieldName = "">
<#assign form_popup = false>
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#list columns as po>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
<j-tree-select
ref="treeSelect"
placeholder="请选择${po.filedComment}"
v-model="model.${po.fieldName}"
dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
pidField="${tableVo.extendParams.pidField}"
pidValue="0"
hasChildField="${tableVo.extendParams.hasChildren}"
<#if po.readonly=='Y'>disabled</#if>>
</j-tree-select>
<#elseif po.classType =='date'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='datetime'>
<j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='time'>
<j-time placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='switch'>
<j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if>></j-switch>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-model="model.${po.fieldName}"
field="${po.fieldName}"
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>
<j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType =='sel_user'>
<j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='textarea'>
<a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list' || po.classType=='radio'>
<j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType=='file'>
<j-upload v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:number=${po.uploadnum}</#if>></j-upload>
<#elseif po.classType=='image'>
<j-image-upload isMultiple <#if po.uploadnum??>:number=${po.uploadnum}</#if> v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
<#elseif po.classType=='sel_search'>
<j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
<j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if> <#if po.readonly=='Y'>disabled</#if>/>
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.classType =='pca'>
<j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区" <#if po.readonly=='Y'>disabled</#if> />
<#elseif po.classType=='umeditor'>
<j-editor v-model="model.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='markdown'>
<j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
<#elseif po.classType == 'sel_tree'>
<j-tree-select
ref="treeSelect"
placeholder="请选择${po.filedComment}"
v-model="model.${po.fieldName}"
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
<#elseif po.dictText?split(',')[1]??>
pidField="${po.dictText?split(',')[1]}"
<#elseif po.dictText?split(',')[3]??>
hasChildField="${po.dictText?split(',')[3]}"
</#if>
</#if>
pidValue="${po.dictField}"
<#if po.readonly=='Y'>disabled</#if>>
</j-tree-select>
<#else>
<a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
</#if>
</a-form-model-item>
</#if>
</#list>
</a-form-model>
</a-spin>
</j-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: "${entityName}Modal",
components: {
},
data () {
return {
title:"操作",
width:800,
visible: false,
model:{
<#include "/common/init/initValue.ftl">
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
<#include "/common/validatorRulesTemplate/main.ftl">
url: {
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
},
expandedRowKeys:[],
pidField:"${pidFieldName}"
}
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add (obj) {
this.modelDefault.${pidFieldName}=''
this.edit(Object.assign(this.modelDefault , obj));
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
close () {
this.$emit('close');
this.visible = false;
this.$refs.form.clearValidate()
},
handleOk () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
if(this.model.id && this.model.id === this.model[this.pidField]){
that.$message.warning("父级节点不能选择自己");
that.confirmLoading = false;
return;
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
this.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}else{
return false
}
})
},
handleCancel () {
this.close()
},
<#if form_popup>
popupCallback(value,row){
this.model = Object.assign(this.model, row);
},
</#if>
<#if form_cat_tree>
handleCategoryChange(value,backObj){
this.model = Object.assign(this.model, backObj);
},
</#if>
submitSuccess(formData,flag){
if(!formData.id){
let treeData = this.$refs.treeSelect.getCurrTreeData()
this.expandedRowKeys=[]
this.getExpandKeysByPid(formData[this.pidField],treeData,treeData)
this.$emit('ok',formData,this.expandedRowKeys.reverse());
}else{
this.$emit('ok',formData,flag);
}
},
getExpandKeysByPid(pid,arr,all){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid){
this.expandedRowKeys.push(arr[i].key)
this.getExpandKeysByPid(arr[i]['parentId'],all,all)
}else{
this.getExpandKeysByPid(pid,arr[i].children,all)
}
}
}
}
}
}
</script>
@@ -0,0 +1,548 @@
<#include "/common/utils.ftl">
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#assign bpm_flag=false>
<#assign list_has_popup_dict=false>
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<#assign list_need_pca=false>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
<#if po.classType=='popup_dict'>
<#assign list_has_popup_dict=true>
</#if>
</#list>
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleCreate" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template v-slot:bodyCell="{ column, record, index, text }">
<#list columns as po>
<#if po.classType=='umeditor' || po.classType=='pca' || po.classType=='file'>
<template v-if="column.dataIndex==='${po.fieldName}'">
<#if po.classType=='umeditor'>
<!--富文本件字段回显插槽-->
<div v-html="text"></div>
</#if>
<#if po.classType=='pca'>
<!--省市区字段回显插槽-->
{{ getAreaTextByCode(text) }}
</#if>
<#if po.classType=='file'>
<!--文件字段回显插槽-->
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</#if>
</template>
</#if>
</#list>
</template>
</BasicTable>
<!--字典弹窗-->
<${entityName}Modal @register="registerModal" @success="handleSuccess"/>
<#if bpm_flag==true>
<!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" />
</#if>
</div>
</template>
<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
//ts语法
import {ref, reactive, computed, unref, toRaw, nextTick} from 'vue';
import {BasicTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import ${entityName}Modal from './components/${entityName}Modal.vue';
import {columns, searchFormSchema, superQuerySchema} from './${entityName}.data';
import { downloadFile } from '/@/utils/common/renderUtils';
import { useMessage } from '/@/hooks/web/useMessage';
import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
<#if list_need_pca>
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
</#if>
<#if list_has_popup_dict>
import {getPopDictByCode} from "@/utils/dict";
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
</#if>
<#if bpm_flag==true>
import { startProcess } from '/@/api/common/api';
const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
</#if>
const { createMessage } = useMessage();
const queryParam = reactive<any>({});
const expandedRowKeys = ref([]);
//字典model
const [registerModal, {openModal}] = useModal();
//注册table数据
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
api: list,
title: '${tableVo.ftlDescription}',
columns,
canResize:false,
<#-- update-begin---author:chenrui ---date:20231228 for[issue/#5658] 树表复选框与展开按钮重叠问题---------- -->
isTreeTable: true,
<#-- update-end---author:chenrui ---date:20231228 for[issue/#5658] 树表复选框与展开按钮重叠问题---------- -->
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToNumber: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode=='group'>
<#-- update-begin---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time'>
<#-- update-end---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
</#if>
</#if>
</#if>
</#list>
],
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode=='group'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
actionColumn: {
width: 240,
fixed:'right'
},
beforeFetch: (params) => {
params.hasQuery = "true";
return Object.assign(params, queryParam);
},
<#if list_has_popup_dict>
afterFetch: afterFetch
</#if>
},
exportConfig: {
name:"${tableVo.ftlDescription}",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: importSuccess
},
})
const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource},{ rowSelection, selectedRowKeys }] = tableContext
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
/**
* 新增事件
*/
function handleCreate() {
openModal(true, {
isUpdate: false,
});
}
/**
* 编辑事件
*/
async function handleEdit(record) {
openModal(true, {
record,
isUpdate: true,
});
}
/**
* 详情
*/
async function handleDetail(record) {
openModal(true, {
record,
isUpdate: true,
hideFooter: true,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await delete${entityName}({id: record.id}, importSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = selectedRowKeys.value.filter(item => !item.includes('loadChild'))
await batchDelete${entityName}({id: ids}, importSuccess);
}
/**
* 导入
*/
function importSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 添加下级
*/
function handleAddSub(record) {
openModal(true, {
record,
isUpdate: false,
});
}
/**
* 成功回调
*/
async function handleSuccess({isUpdate, values, expandedArr, changeParent}) {
if (isUpdate) {
if (changeParent) {
reload();
} else {
let data = await list({ id: values.id, pageSize: 1, pageNo: 1, ${pidFieldName}: values['${pidFieldName}'] });
if (data && data.records && data.records.length > 0) {
// 编辑回调
updateTableDataRecord(values.id, data.records[0]);
}else{
updateTableDataRecord(values.id, values);
}
}
} else {
if(!values['id'] || !values['${pidFieldName}']){
//新增根节点
reload();
}else{
//新增子集
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key)
}
}
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items)&&loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',')});
if (res.success && res.result.records.length>0) {
//已展开的数据批量子节点
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item['${pidFieldName}'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if(list) {
list.forEach(data => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
};
fn(getDataSource())
}
}
}
/**
* 处理数据集
*/
function getDataByResult(result){
if(result && result.length>0){
return result.map(item=>{
//判断是否标记了带有子节点
if(item["hasChild"]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
}
}
/**
*树节点展开合并
* */
async function handleExpand(expanded, record) {
// 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
if (expanded) {
expandedRowKeys.value.push(record.id)
if (record.children.length > 0 && !!record.children[0].isLoading) {
let result = await getChildList({${pidFieldName}: record.id});
result=result.records?result.records:result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id)
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
*操作表格后处理树节点展开合并
* */
async function expandTreeNode(key) {
let record = findTableDataRecord(key)
expandedRowKeys.value.push(key);
let result = await getChildList({${pidFieldName}: key});
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
updateTableDataRecord(key, record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: '${entityPackage}:${tableName}:edit'
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, {${pidFieldName}: record.id}),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
<#if bpm_flag==true>
let dropDownAction = [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft'
},
auth: '${entityPackage}:${tableName}:delete'
},{
label: '审批进度',
onClick: handlePreviewPic.bind(null, record),
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
];
if(record.bpmStatus == '1' || !record.bpmStatus){
dropDownAction.push({
label: '发起流程',
popConfirm: {
title: '确认提交流程吗?',
confirm: handleProcess.bind(null, record),
placement: 'topLeft',
}
})
}
return dropDownAction;
<#else>
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
placement: 'topLeft'
},
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
]
</#if>
}
<#if bpm_flag==true>
/**
* 提交流程
*/
async function handleProcess(record) {
let params = {
flowCode: 'dev_${tableName}_001',
id: record.id,
formUrl: '${entityPackagePath}/components/${entityName}Form',
formUrlMobile: ''
}
await startProcess(params);
await reload();
}
/**
* 审批进度
*/
async function handlePreviewPic(record) {
bpmPicModal(true, {
flowCode: 'dev_${tableName}_001',
dataId: record.id,
});
}
</#if>
<#if list_has_popup_dict>
/**
* 翻译Popup字典配置
*/
async function afterFetch(records){
<#list columns as po>
<#if po.isQuery=='Y' || po.isShowList=='Y'>
<#if po.classType=='popup_dict' && list_has_popup_dict==true>
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
records.forEach((item) => {
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
});
}
</#if>
</#if>
</#list>
return records;
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
<#if btn.buttonStyle=='link'>
function handle${btn.buttonCode?cap_first}(record){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
</script>
<style lang="less" scoped>
<#include "/common/form/vue3SearchStyle.ftl">
</style>
@@ -0,0 +1,85 @@
import {defHttp} from "/@/utils/http/axios";
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/${entityPackagePath}/${entityName?uncap_first}/rootList',
save='/${entityPackagePath}/${entityName?uncap_first}/add',
edit='/${entityPackagePath}/${entityName?uncap_first}/edit',
delete${entityName} = '/${entityPackagePath}/${entityName?uncap_first}/delete',
importExcel = '/${entityPackagePath}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackagePath}/${entityName?uncap_first}/exportXls',
loadTreeData = '/${entityPackagePath}/${entityName?uncap_first}/loadTreeRoot',
getChildList = '/${entityPackagePath}/${entityName?uncap_first}/childList',
getChildListBatch = '/${entityPackagePath}/${entityName?uncap_first}/getChildListBatch',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
* @param params
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除
*/
export const delete${entityName} = (params,handleSuccess) => {
return defHttp.delete({url: Api.delete${entityName}, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete${entityName} = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.delete${entityName}, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdateDict = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
/**
* 查询全部树形节点数据
* @param params
*/
export const loadTreeData = (params) =>
defHttp.get({url: Api.loadTreeData,params});
/**
* 查询子节点数据
* @param params
*/
export const getChildList = (params) =>
defHttp.get({url: Api.getChildList, params});
/**
* 批量查询子节点数据
* @param params
*/
export const getChildListBatch = (params) =>
defHttp.get({url: Api.getChildListBatch, params},{isTransformResponse:false});
@@ -0,0 +1,554 @@
<#include "/common/utils.ftl">
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
{
title: '${po.filedComment}',
<#if po.fieldDbName == tableVo.extendParams.textField>
align: 'left',
<#else>
align: 'center',
</#if>
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
text = !text ? "" : (text.length > 10 ? text.substr(0,10) : text);
<#if po.extendParams?exists && po.extendParams.picker?exists>
if(text) {
return getWeekMonthQuarterYear(text)['${po.extendParams.picker}'];
} else {
return text;
}
<#else>
return text;
</#if>
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderImage,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict' || po.classType=='link_table'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isQuery=='Y' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
component: 'JSelectUser',
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType=='list_multi'>
component: 'JSelectMultiple',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}",
</#if>
triggerChange: true
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueFormat: 'YYYY-MM-DD'
},
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true,
valueFormat: 'YYYY-MM-DD HH:mm:ss'
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
componentProps: {
saveCode: 'region',
},
<#elseif po.classType=='popup'>
<#include "/common/form/vue3popup.ftl">
<#elseif po.classType=='popup_dict'>
component: 'JPopupDict',
componentProps: {
placeholder: '请选择${po.filedComment}',
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
multi: ${po.extendParams.popupMulti?c}
},
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
</#if>
<#if po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
</#if>
<#if po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
},
<#elseif po.classType=='link_table'>
component: 'JLinkTableCard',
componentProps: {
valueField: '${po.dictField}',
textField: '${po.dictText}',
tableName: '${po.dictTable}',
multi: <#if (po.queryMode!"") == "multi">true<#else>false</#if>
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JSelectMultiple',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#else>
component: 'Input',
</#if>
//colProps: {span: 6},
},
<#elseif po.queryMode=='like'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
component: 'JInput',
},
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueType: 'Date',
},
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
valueType: 'Date',
showTime:true
},
<#elseif po.classType == 'time'>
component: 'TimePicker',
componentProps:{
valueFormat: 'HH:mm:ss',
},
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'JRangeNumber',
<#-- update-begin---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#elseif po.classType=='time'>
component: 'RangeTime',
<#-- update-end---author:chenrui ---date:20240527 for[TV360X-388]时间范围查询控件---------- -->
<#else>
component: 'Input', //TODO 范围查询
</#if>
//colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#assign id_exists = false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.fieldDbName == 'id'>
<#assign id_exists = true>
</#if>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShow =='Y' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: ${autoStringSuffix(po)},
<#-- update-begin-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
<#if po.defaultVal??>
<#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int">
defaultValue: ${po.defaultVal},
<#else>
defaultValue: "${po.defaultVal}",
</#if>
</#if>
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
<#if po.fieldDbName == tableVo.extendParams.pidField>
component: 'JTreeSelect',
componentProps: {
dict: "${tableVo.tableName},${tableVo.extendParams.textField},id",
pidField: "${tableVo.extendParams.pidField}",
pidValue: "0",
hasChildField: "${tableVo.extendParams.hasChildren}",
},
<#elseif po.classType =='date'>
component: 'DatePicker',
componentProps: {
<#if po.extendParams?exists && po.extendParams.picker?exists>
picker: '${po.extendParams.picker}',
</#if>
valueFormat: 'YYYY-MM-DD'
},
<#elseif po.classType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true,
valueFormat: 'YYYY-MM-DD HH:mm:ss'
},
<#elseif po.classType =='time'>
component: 'TimePicker',
componentProps:{
valueFormat: 'HH:mm:ss',
},
<#elseif po.classType =='popup'>
<#include "/common/form/vue3popup.ftl">
<#elseif po.classType=='popup_dict'>
component: 'JPopupDict',
componentProps: {
placeholder: '请选择${po.filedComment}',
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
multi: ${po.extendParams.popupMulti?c}
},
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
},
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
componentProps: {
saveCode: 'region',
},
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
<#-- update-begin---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
component: 'JSelectUser',
<#-- update-end---author:chenrui ---date:20240102 for[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
componentProps:{
<#if po.extendParams?exists && po.extendParams.text?exists>
labelKey: '${po.extendParams.text}',
</#if>
<#if po.extendParams?exists && po.extendParams.store?exists>
rowKey: '${po.extendParams.store}',
</#if>
},
<#elseif po.classType =='textarea'>
component: 'InputTextArea',
<#elseif po.classType=='list'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#elseif po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}",
type: "radio"
},
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
<#elseif po.classType=='list_multi'>
component: 'JSelectMultiple',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#elseif po.classType=='checkbox'>
component: 'JCheckbox',
componentProps:{
dictCode:"${form_field_dictCode}"
},
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
},
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
},
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
},
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
<#else>
fileMax: 0
</#if>
},
<#elseif po.classType=='umeditor'>
component: 'JEditor',
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
</#if>
<#if po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
</#if>
<#if po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
},
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字母 -->
<#elseif fieldValidType == 's6-18'>
{ pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
<#if id_exists == false>
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false
},
</#if>
];
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询数据
export const superQuerySchema = {
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
${superQueryFieldListForVue3(po,po_index)},
</#if>
</#list>
};
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
/**
* 流程表单调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,71 @@
<#include "/common/utils.ftl">
<template>
<div style="min-height: 400px">
<BasicForm @register="registerForm"></BasicForm>
<div style="width: 100%;text-align: center" v-if="!formDisabled">
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
</div>
</div>
</template>
<script lang="ts">
import {BasicForm, useForm} from '/@/components/Form/index';
import {computed, defineComponent} from 'vue';
import {defHttp} from '/@/utils/http/axios';
import { propTypes } from '/@/utils/propTypes';
import {getBpmFormSchema} from '../${entityName}.data';
import {saveOrUpdateDict} from '../${entityName}.api';
export default defineComponent({
name: "${entityName}Form",
components:{
BasicForm
},
props:{
formData: propTypes.object.def({}),
formBpm: propTypes.bool.def(true),
},
setup(props){
const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
labelWidth: 150,
schemas: getBpmFormSchema(props.formData),
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
});
const formDisabled = computed(()=>{
if(props.formData.disabled === false){
return false;
}
return true;
});
let formData = {};
const queryByIdUrl = '/${entityPackagePath}/${entityName?uncap_first}/queryById';
async function initFormData(){
let params = {id: props.formData.dataId};
const data = await defHttp.get({url: queryByIdUrl, params});
formData = {...data}
//设置表单的值
await setFieldsValue(formData);
//默认是禁用
await setProps({disabled: formDisabled.value})
}
async function submitForm() {
let data = getFieldsValue();
let params = Object.assign({}, formData, data);
console.log('表单数据', params)
await saveOrUpdateDict(params, true)
}
initFormData();
return {
registerForm,
formDisabled,
submitForm,
}
}
});
</script>
@@ -0,0 +1,152 @@
<#include "/common/utils.ftl">
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${entityName}Form" />
<#if buttonList?? && buttonList?size gt 0>
<template #insertFooter>
<#list buttonList as btn>
<#if btn.buttonStyle=='form'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</template>
</#if>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form';
import {formSchema} from '../${entityName}.data';
import {loadTreeData, saveOrUpdateDict} from '../${entityName}.api';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage } = useMessage();
// 获取emit
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const isDetail = ref(false);
const expandedRowKeys = ref([]);
const treeData = ref([]);
// 当前编辑的数据
let model:Nullable<Recordable> = null;
//表单配置
const [registerForm, { setProps,resetFields, setFieldsValue, validate, updateSchema, scrollToField }] = useForm({
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
expandedRowKeys.value = [];
setModalProps({confirmLoading: false, minHeight: 80 ,showOkBtn: !!!data?.hideFooter});
isUpdate.value = !!data?.isUpdate;
isDetail.value = !!data?.showFooter;
if (data?.record) {
model = data.record;
//表单赋值
await setFieldsValue({
...data.record,
});
} else {
model = null;
}
//父级节点树信息
treeData.value = await loadTreeData({'async': false,'pcode':''});
// 隐藏底部时禁用整个表单
setProps({ disabled: !!data?.hideFooter })
});
//设置标题
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑'));
/**
* 根据pid获取展开的节点
* @param pid
* @param arr
*/
function getExpandKeysByPid(pid,arr){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid && unref(expandedRowKeys).indexOf(pid)<0){
expandedRowKeys.value.push(arr[i].key);
getExpandKeysByPid(arr[i]['parentId'],unref(treeData))
}else{
getExpandKeysByPid(pid,arr[i].children)
}
}
}
}
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdateDict(values, isUpdate.value);
//关闭弹窗
closeModal();
//展开的节点信息
await getExpandKeysByPid(values['${pidFieldName}'],unref(treeData))
//刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息)
emit('success', {
isUpdate: unref(isUpdate),
values: {...values},
expandedArr: unref(expandedRowKeys).reverse(),
// 是否更改了父级节点
changeParent: model != null && (model['${pidFieldName}'] != values['${pidFieldName}']),
});
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
} finally {
setModalProps({confirmLoading: false});
}
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,723 @@
<#include "/common/utils.ftl">
<template>
<div class="p-2">
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<#assign query_field_no=0>
<#assign need_category = false>
<#assign need_pca = false>
<#assign need_search = false>
<#assign need_dept_user = false>
<#assign need_switch = false>
<#assign need_dept = false>
<#assign need_multi = false>
<#assign need_popup = false>
<#assign need_popup_dict = false>
<#assign need_select_tag = false>
<#assign need_select_tree = false>
<#assign need_time = false>
<#assign bpm_flag=false>
<#assign need_markdown = false>
<#assign need_upload = false>
<#assign need_image_upload = false>
<#assign need_editor = false>
<#assign need_checkbox = false>
<#assign need_range_number = false>
<#assign is_range = false>
<#assign is_like = false>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<#assign query_flag = false>
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign need_pca=true>
</#if>
<#if po.classType=='sel_search'>
<#assign need_search = true>
</#if>
<#if po.classType=='sel_user'>
<#assign need_dept_user = true>
</#if>
<#if po.classType=='sel_depart'>
<#assign need_dept = true>
</#if>
<#if po.classType=='switch'>
<#assign need_switch = true>
</#if>
<#if po.classType=='list_multi'>
<#assign need_multi = true>
</#if>
<#if po.classType=='popup'>
<#assign need_popup = true>
</#if>
<#if po.classType=='popup_dict'>
<#assign need_popup_dict = true>
</#if>
<#if po.classType=='sel_tree'>
<#assign need_select_tree = true>
</#if>
<#if po.classType=='time'>
<#assign need_time = true>
</#if>
<#if po.queryMode=='group' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
<#assign need_range_number = true>
</#if>
<#if po.queryMode=='group'>
<#assign is_range = true>
</#if>
<#if po.queryMode=='like'>
<#assign is_like = true>
</#if>
<#include "/common/form/native/vue3NativeSearch.ftl">
</#list>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
<a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
</a>
</a-col>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'"
>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<!--字段回显插槽-->
<template v-slot:bodyCell="{ column, record, index, text }">
<#list columns as po>
<#if po.classType=='umeditor' || po.classType=='pca' || po.classType=='file'>
<template v-if="column.dataIndex==='${po.fieldName}'">
<#if po.classType=='umeditor'>
<!--富文本件字段回显插槽-->
<div v-html="text"></div>
</#if>
<#if po.classType=='pca'>
<!--省市区字段回显插槽-->
{{ getAreaTextByCode(text) }}
</#if>
<#if po.classType=='file'>
<!--文件字段回显插槽-->
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</#if>
</template>
</#if>
</#list>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal>
<#if bpm_flag==true>
<!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" />
</#if>
</div>
</template>
<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
import { ref, reactive, unref } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './${entityName}.data';
import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import { useMessage } from '/@/hooks/web/useMessage';
<#include "/common/form/native/vue3NativeImport.ftl">
<#if need_category>
import { loadCategoryData } from '/@/api/common/api';
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
<#if need_pca>
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
</#if>
<#if need_popup_dict>
import {getPopDictByCode} from "@/utils/dict";
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
</#if>
<#if is_range>
import { cloneDeep } from "lodash-es";
</#if>
<#if bpm_flag==true>
import { startProcess } from '/@/api/common/api';
const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
</#if>
const { createMessage } = useMessage();
const expandedRowKeys = ref([]);
const queryParam = ref<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
//注册table数据
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '${tableVo.ftlDescription}',
api: list,
columns,
canResize:false,
useSearchForm: false,
isTreeTable: true,
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
params.hasQuery = "true";
<#if is_range>
let rangerQuery = await setRangeQuery();
return Object.assign(params, rangerQuery);
<#else>
return Object.assign(params, queryParam.value);
</#if>
},
<#if need_popup_dict>
afterFetch: afterFetch
</#if>
},
exportConfig: {
name: "${tableVo.ftlDescription}",
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: success
},
});
const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource},{ rowSelection, selectedRowKeys }] = tableContext
const labelCol = reactive({
xs:24,
sm:4,
xl:6,
xxl:4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam.value[k] = params[k];
});
reload();
}
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.add();
}
/**
* 编辑事件
*/
async function handleEdit(record) {
registerModal.value.disableSubmit = false;
registerModal.value.edit(record);
}
/**
* 详情
*/
async function handleDetail(record) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 删除事件
*/
async function handleDelete(record) {
await delete${entityName}({ id: record.id }, success);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = selectedRowKeys.value.filter((item) => !item.includes('loadChild'));
await batchDelete${entityName}({ id: ids }, success);
}
/**
* 成功回调刷新页面
*/
function success() {
(selectedRowKeys.value = []) && reload();
}
/**
* 添加下级
*/
function handleAddSub(record) {
registerModal.value.disableSubmit = false;
registerModal.value.add(record);
}
/**
* 成功回调
*/
async function handleSuccess({ isUpdate, values, expandedArr, changeParent }) {
if (isUpdate) {
if (changeParent) {
reload();
} else {
let data = await list({ id: values.id, pageSize: 1, pageNo: 1, ${pidFieldName}: values['${pidFieldName}'] });
if (data && data.records && data.records.length > 0) {
// 编辑回调
updateTableDataRecord(values.id, data.records[0]);
}else{
updateTableDataRecord(values.id, values);
}
}
} else {
if (!values['id'] || !values['pid']) {
//新增根节点
reload();
} else {
//新增子集
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key);
}
}
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items) && loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',') });
if (res.success && res.result.records.length > 0) {
//已展开的数据批量子节点
let records = res.result.records;
const listMap = new Map();
for (let item of records) {
let pid = item['${pidFieldName}'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if (list) {
list.forEach((data) => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id));
fn(data.children);
}
});
}
};
fn(getDataSource());
}
}
}
/**
* 处理数据集
*/
function getDataByResult(result) {
if (result && result.length > 0) {
return result.map((item) => {
//判断是否标记了带有子节点
if (item['hasChild'] == '1') {
let loadChild = { id: item.id + '_loadChild', name: 'loading...', isLoading: true };
item.children = [loadChild];
}
return item;
});
}
}
/**
*树节点展开合并
*/
async function handleExpand(expanded, record) {
// 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
if (expanded) {
expandedRowKeys.value.push(record.id);
if (record.children.length > 0 && !!record.children[0].isLoading) {
let result = await getChildList({ ${pidFieldName}: record.id});
result = result.records ? result.records : result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null;
record.hasChild = '0';
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id);
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
* 操作表格后处理树节点展开合并
*/
async function expandTreeNode(key) {
let record = findTableDataRecord(key);
expandedRowKeys.value.push(key);
let result = await getChildList({ ${pidFieldName}: key });
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null;
record.hasChild = '0';
}
updateTableDataRecord(key, record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: '${entityPackage}:${tableName}:edit'
}
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
<#if bpm_flag==true>
let dropDownAction = [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, { pid: record.id }),
},
{
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
placement: 'topLeft'
},
auth: '${entityPackage}:${tableName}:delete'
},
{
label: '审批进度',
onClick: handlePreviewPic.bind(null, record),
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
];
if(record.bpmStatus == '1' || !record.bpmStatus){
dropDownAction.push({
label: '发起流程',
popConfirm: {
title: '确认提交流程吗?',
confirm: handleProcess.bind(null, record),
placement: 'topLeft',
}
})
}
return dropDownAction;
<#else>
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, { pid: record.id }),
},
{
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
onClick: handle${btn.buttonCode?cap_first}.bind(null, record),
}
</#if>
</#list>
</#if>
];
</#if>
}
<#if bpm_flag==true>
/**
* 提交流程
*/
async function handleProcess(record) {
let params = {
flowCode: 'dev_${tableName}_001',
id: record.id,
formUrl: '${entityPackagePath}/components/${entityName}Form',
formUrlMobile: ''
}
await startProcess(params);
await reload();
}
/**
* 审批进度
*/
async function handlePreviewPic(record) {
bpmPicModal(true, {
flowCode: 'dev_${tableName}_001',
dataId: record.id,
});
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
<#if btn.buttonStyle=='link'>
function handle${btn.buttonCode?cap_first}(record){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
}
</#if>
</#list>
</#if>
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
queryParam.value = {};
selectedRowKeys.value = [];
//刷新数据
reload();
}
<#if need_popup>
/**
* popup组件值改变事件
*/
function setFieldsValue(map) {
Object.keys(map).map((key) => {
queryParam.value[key] = map[key];
});
}
</#if>
<#if need_pca || need_dept_user>
/**
* form点击事件(以逗号分割)
* @param key
* @param value
*/
function handleFormJoinChange(key, value) {
if (typeof value != 'string') {
queryParam.value[key] = value.join(',');
}
}
</#if>
<#if need_category>
/**
* form点击事件
* @param value
*/
function handleFormChange(key, value) {
queryParam.value[key] = value;
}
/**
* 初始化字典配置
*/
function initDictConfig() {
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
if(!allDictDate['${po.dictField?default("")}']){
Object.assign(allDictDate,{'${po.dictField?default("")}':res})
}
setAuthCache(DB_DICT_DATA_KEY,allDictDate)
}
});
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
<#if is_range>
let rangeField = '${getRangeField(columns)}'
/**
* 设置范围查询条件
*/
async function setRangeQuery(){
let queryParamClone = cloneDeep(queryParam.value);
if (rangeField) {
let fieldsValue = rangeField.split(',');
fieldsValue.forEach(item => {
if (queryParamClone[item]) {
let range = queryParamClone[item];
queryParamClone[item+'_begin'] = range[0];
queryParamClone[item+'_end'] = range[1];
delete queryParamClone[item];
} else {
queryParamClone[item+'_begin'] = '';
queryParamClone[item+'_end'] = '';
}
})
}
return queryParamClone;
}
</#if>
<#if need_popup_dict>
/**
* 翻译Popup字典配置
*/
async function afterFetch(records){
<#list columns as po>
<#if po.isQuery=='Y' || po.isShowList=='Y'>
<#if po.classType=='popup_dict'>
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
records.forEach((item) => {
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
});
}
</#if>
</#if>
</#list>
return records;
}
</#if>
</script>
<style lang="less" scoped>
<#include "/common/form/native/vueNativeSearchStyle.ftl">
</style>
@@ -0,0 +1,93 @@
import { defHttp } from "/@/utils/http/axios";
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/${entityPackagePath}/${entityName?uncap_first}/rootList',
save='/${entityPackagePath}/${entityName?uncap_first}/add',
edit='/${entityPackagePath}/${entityName?uncap_first}/edit',
delete${entityName} = '/${entityPackagePath}/${entityName?uncap_first}/delete',
importExcel = '/${entityPackagePath}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackagePath}/${entityName?uncap_first}/exportXls',
loadTreeData = '/${entityPackagePath}/${entityName?uncap_first}/loadTreeRoot',
getChildList = '/${entityPackagePath}/${entityName?uncap_first}/childList',
getChildListBatch = '/${entityPackagePath}/${entityName?uncap_first}/getChildListBatch',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
* @param params
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除
* @param params
* @param handleSuccess
*/
export const delete${entityName} = (params,handleSuccess) => {
return defHttp.delete({ url: Api.delete${entityName}, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
* @param handleSuccess
*/
export const batchDelete${entityName} = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.delete${entityName}, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
* @param isUpdate
*/
export const saveOrUpdateDict = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params },{ isTransformResponse:false });
}
/**
* 查询全部树形节点数据
* @param params
*/
export const loadTreeData = (params) => defHttp.get({ url: Api.loadTreeData,params });
/**
* 查询子节点数据
* @param params
*/
export const getChildList = (params) => defHttp.get({ url: Api.getChildList, params });
/**
* 批量查询子节点数据
* @param params
*/
export const getChildListBatch = (params) => defHttp.get({ url: Api.getChildListBatch, params },{ isTransformResponse:false });
@@ -0,0 +1,94 @@
<#include "/common/utils.ftl">
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
{
title: '${po.filedComment}',
<#if po.fieldDbName == tableVo.extendParams.textField>
align: 'left',
<#else>
align: 'center',
</#if>
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
text = !text ? "" : (text.length > 10 ? text.substr(0,10) : text);
<#if po.extendParams?exists && po.extendParams.picker?exists>
if(text) {
return getWeekMonthQuarterYear(text)['${po.extendParams.picker}'];
} else {
return text;
}
<#else>
return text;
</#if>
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender: render.renderImage,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}');
},
<#else>
customRender: ({text, record}) => (text ? record['${po.dictText}'] : '');
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
<#-- update-begin---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
// 高级查询数据
export const superQuerySchema = {
<#list columns as po>
<#-- update-begin---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
<#-- update-end---author:chenrui ---date:20240108 for[issues/5755]vue代码不加入逻辑删除字段---------- -->
${superQueryFieldListForVue3(po,po_index)},
</#if>
</#list>
};
<#-- update-end---author:chenrui ---date:20231228 for[QQYUN-7527]vue3代码生成默认带上高级查询---------- -->
@@ -0,0 +1,298 @@
<#include "/common/utils.ftl">
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="${entityName}Form">
<a-row>
<#assign need_category = false>
<#assign bpm_flag=false>
<#assign need_pca = false>
<#assign need_search = false>
<#assign need_dept_user = false>
<#assign need_switch = false>
<#assign need_dept = false>
<#assign need_multi = false>
<#assign need_popup = false>
<#assign need_popup_dict = false>
<#assign need_select_tag = false>
<#assign need_select_tree = false>
<#assign need_time = false>
<#assign need_markdown = false>
<#assign need_upload = false>
<#assign need_image_upload = false>
<#assign need_editor = false>
<#assign need_checkbox = false>
<#assign need_range_number = false>
<#assign is_like = false>
<#assign pidFieldName = "">
<#assign hasOnlyValidate = false>
<#assign form_span = 24>
<#if tableVo.fieldRowNum==2>
<#assign form_span = 12>
<#elseif tableVo.fieldRowNum==3>
<#assign form_span = 8>
<#elseif tableVo.fieldRowNum==4>
<#assign form_span = 6>
</#if>
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
<#assign hasOnlyValidate = true>
</#if>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
<#assign need_select_tree = true>
<a-col :span="${form_span}">
<a-form-item label="父级节点" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
<j-tree-select
placeholder="请选择${po.filedComment}"
v-model:value="formData.${po.fieldName}"
dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
pidField="${tableVo.extendParams.pidField}"
pidValue="0"
hasChildField="${tableVo.extendParams.hasChildren}"
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>>
</j-tree-select>
</a-form-item>
</a-col>
</#if>
<#assign formEntityName>${entityName}Form</#assign>
<#include "/common/form/native/vue3NativeForm.ftl">
</#list>
<#if bpm_flag>
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
</a-col>
</#if>
</a-row>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, unref, defineProps, computed, onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
<#include "/common/form/native/vue3NativeImport.ftl">
import { getValueType } from '/@/utils';
import {loadTreeData, saveOrUpdateDict} from '../${entityName}.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
<#if hasOnlyValidate == true>
import { duplicateValidate } from '/@/utils/helper/validator'
</#if>
<#if bpm_flag>
import { usePermission } from '/@/hooks/web/usePermission';
const { isDisabledAuth, hasPermission, initBpmFormData } = usePermission();
</#if>
const useForm = Form.useForm;
const formRef = ref();
const isUpdate = ref(true);
const expandedRowKeys = ref([]);
const treeData = ref([]);
const pidField = ref<string>('pid');
const emit = defineEmits(['register', 'ok']);
let model: Nullable<Recordable> = null;
const formData = reactive<Record<string, any>>({
id: '',
<#include "/common/init/native/vue3NativeInitValue.ftl">
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//表单验证
const validatorRules = reactive({
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true }
});
// 表单禁用
const disabled = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return false;
}else{
return true;
}
}
return props.formDisabled;
});
<#if bpm_flag>
onMounted(()=>{
initBpmFormData(props.formData);
initFormData();
});
//渲染流程表单数据
const queryByIdUrl = '/${entityPackagePath}/${entityName?uncap_first}/queryById';
async function initFormData(){
if(props.formBpm === true){
let params = {id: props.formData.dataId};
const data = await defHttp.get({url: queryByIdUrl, params});
//设置表单的值
edit({...data});
}
}
// 是否显示提交按钮
const showFlowSubmitButton = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return true
}
}
return false
});
</#if>
/**
* 新增
*/
function add(obj = {}) {
edit(obj);
}
/**
* 编辑
*/
function edit(record) {
nextTick(async () => {
resetFields();
expandedRowKeys.value = [];
treeData.value = await loadTreeData({ async: false, pcode: '' });
const tmpData = {};
Object.keys(formData).forEach((key) => {
if(record.hasOwnProperty(key)){
tmpData[key] = record[key]
}
})
//赋值
Object.assign(formData,tmpData);
model = tmpData
});
}
/**
* 根据pid获取展开的节点
* @param pid
* @param arr
*/
function getExpandKeysByPid(pid, arr) {
if (pid && arr && arr.length > 0) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].key == pid && unref(expandedRowKeys).indexOf(pid) < 0) {
expandedRowKeys.value.push(arr[i].key);
getExpandKeysByPid(arr[i]['parentId'], unref(treeData));
} else {
getExpandKeysByPid(pid, arr[i].children);
}
}
}
}
/**
* 提交数据
*/
async function submitForm() {
try {
// 触发表单验证
await validate();
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
}
confirmLoading.value = true;
const isUpdate = ref<boolean>(false);
//时间格式化
if (formData.id) {
isUpdate.value = true;
}
//循环数据
for (let data in formData) {
//如果该数据是数组并且是字符串类型
if (formData[data] instanceof Array) {
let valueType = getValueType(formRef.value.getProps, data);
//如果是字符串类型的需要变成以逗号分割的字符串
if (valueType === 'string') {
formData[data] = formData[data].join(',');
}
}
}
await saveOrUpdateDict(formData, isUpdate.value)
.then(async (res) => {
if (res.success) {
await getExpandKeysByPid(formData['${pidFieldName}'], unref(treeData));
delete formData['children'];
emit('ok', {
isUpdate: unref(isUpdate),
values: { ...formData },
expandedArr: unref(expandedRowKeys).reverse(),
// 是否更改了父级节点
changeParent: model != null && model['${pidFieldName}'] != formData['${pidFieldName}'],
});
createMessage.success(res.message);
} else {
createMessage.warning(res.message);
}
})
.finally(() => {
confirmLoading.value = false;
});
}
<#if need_popup>
/**
* popup组件值改变事件
*/
function setFieldsValue(map) {
Object.keys(map).map((key) => {
formData[key] = map[key];
});
}
</#if>
<#if need_category || need_select_tree>
/**
* 值改变事件触发
* @param key
* @param value
*/
function handleFormChange(key, value) {
formData[key] = value;
}
</#if>
<#list columns as po>
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
async function ${po.fieldName}Duplicatevalidate(_r, value) {
return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '')
}
</#if>
</#list>
defineExpose({
add,
edit,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>
@@ -0,0 +1,100 @@
<template>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
<template #footer>
<#if buttonList?? && buttonList?size gt 0>
<#list buttonList as btn>
<#if btn.buttonStyle=='form'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
</#list>
</#if>
<a-button @click="handleCancel">取消</a-button>
<a-button :class="{ 'jee-hidden': disableSubmit }" type="primary" @click="handleOk">确认</a-button>
</template>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import ${entityName}Form from './${entityName}Form.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage } = useMessage();
const title = ref<string>('');
const width = ref<number>(800);
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 新增
*/
function add(obj={}) {
title.value = '新增';
visible.value = true;
nextTick(() => {
registerForm.value.add(obj);
});
}
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = disableSubmit.value ? '详情' : '编辑';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback({ isUpdate, values, expandedArr, changeParent }) {
handleCancel();
emit('success', {
isUpdate: isUpdate,
values: values,
expandedArr: expandedArr,
// 是否更改了父级节点
changeParent: changeParent,
});
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
add,
edit,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>
@@ -0,0 +1,402 @@
package ${bussiPackage}.${entityPackage}.controller;
import org.jeecg.common.system.query.QueryGenerator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.jeecg.common.system.query.QueryRuleEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.HashMap;
import org.jeecg.common.util.oConvertUtils;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service;
</#list>
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.shiro.authz.annotation.RequiresPermissions;
<#assign has_multi_query_field=false>
<#list originalColumns as po>
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
<#assign has_multi_query_field=true>
</#if>
</#list>
<#assign enhanceJavaList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.enhanceJavaList??>
<#assign enhanceJavaList = tableVo.extendParams.enhanceJavaList?filter(enhance -> enhance??)>
</#if>
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Tag(name="${tableVo.ftlDescription}")
@RestController
@RequestMapping("/${entityPackagePath}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
<#list subTables as sub>
@Autowired
private I${sub.entityName}Service ${sub.entityName?uncap_first}Service;
</#list>
/*---------------------------------主表处理-begin-------------------------------------*/
/**
* 分页列表查询
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "${tableVo.ftlDescription}-分页列表查询")
@Operation(summary="${tableVo.ftlDescription}-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 查询前触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeQuery()
</#if>
</#list>
</#if>
<#if has_multi_query_field>
// 自定义查询规则
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
// 自定义多选的查询规则为:LIKE_WITH_OR
<#list originalColumns as po>
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
customeRuleMap.put("${po.fieldName}", QueryRuleEnum.LIKE_WITH_OR);
</#if>
</#list>
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap(),customeRuleMap);
<#else>
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
</#if>
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='query' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 查询后触发的方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterQuery()
</#if>
</#list>
</#if>
return Result.OK(pageList);
}
/**
* 添加
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-添加")
@Operation(summary="${tableVo.ftlDescription}-添加")
@RequiresPermissions("${entityPackage}:${tableName}:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 新增前的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeAdd()
</#if>
</#list>
</#if>
${entityName?uncap_first}Service.save(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='add' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 新增后的处理方法,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterAdd()
</#if>
</#list>
</#if>
return Result.OK("添加成功!");
}
/**
* 编辑
* @param ${entityName?uncap_first}
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-编辑")
@Operation(summary="${tableVo.ftlDescription}-编辑")
@RequiresPermissions("${entityPackage}:${tableName}:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 编辑前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeEdit()
</#if>
</#list>
</#if>
${entityName?uncap_first}Service.updateById(${entityName?uncap_first});
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='edit' && enhanceJava.event=='end' && enhanceJava.activeStatus=='1'>
//TODO 编辑后,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.afterEdit()
</#if>
</#list>
</#if>
return Result.OK("编辑成功!");
}
/**
* 通过id删除
* @param id
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-通过id删除")
@Operation(summary="${tableVo.ftlDescription}-通过id删除")
@RequiresPermissions("${entityPackage}:${tableName}:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
${entityName?uncap_first}Service.delMain(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
* @param ids
* @return
*/
@AutoLog(value = "${tableVo.ftlDescription}-批量删除")
@Operation(summary="${tableVo.ftlDescription}-批量删除")
@RequiresPermissions("${entityPackage}:${tableName}:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 导出
* @return
*/
@RequiresPermissions("${entityPackage}:${tableName}:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='export' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导出前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeExport()
</#if>
</#list>
</#if>
return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}");
}
/**
* 导入
* @return
*/
@RequiresPermissions("${entityPackage}:${tableName}:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
<#if enhanceJavaList?size gt 0>
<#list enhanceJavaList as enhanceJava>
<#if enhanceJava.buttonCode=='import' && enhanceJava.event=='start' && enhanceJava.activeStatus=='1'>
//TODO 导入前,代码生成后,请手工实现增强类逻辑;
//${entityName?uncap_first}Service.beforeImport()
</#if>
</#list>
</#if>
return super.importExcel(request, response, ${entityName}.class);
}
/*---------------------------------主表处理-end-------------------------------------*/
<#list subTables as sub>
/*--------------------------------子表处理-${sub.ftlDescription}-begin----------------------------------------------*/
/**
* 通过主表ID查询
* @return
*/
//@AutoLog(value = "${sub.ftlDescription}-通过主表ID查询")
@Operation(summary="${sub.ftlDescription}-通过主表ID查询")
@GetMapping(value = "/list${sub.entityName}ByMainId")
public Result<IPage<${sub.entityName}>> list${sub.entityName}ByMainId(${sub.entityName} ${sub.entityName?uncap_first},
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<${sub.entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${sub.entityName?uncap_first}, req.getParameterMap());
Page<${sub.entityName}> page = new Page<${sub.entityName}>(pageNo, pageSize);
IPage<${sub.entityName}> pageList = ${sub.entityName?uncap_first}Service.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
* @param ${sub.entityName?uncap_first}
* @return
*/
@AutoLog(value = "${sub.ftlDescription}-添加")
@Operation(summary="${sub.ftlDescription}-添加")
@PostMapping(value = "/add${sub.entityName}")
public Result<String> add${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) {
${sub.entityName?uncap_first}Service.save(${sub.entityName?uncap_first});
return Result.OK("添加成功!");
}
/**
* 编辑
* @param ${sub.entityName?uncap_first}
* @return
*/
@AutoLog(value = "${sub.ftlDescription}-编辑")
@Operation(summary="${sub.ftlDescription}-编辑")
@RequestMapping(value = "/edit${sub.entityName}", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) {
${sub.entityName?uncap_first}Service.updateById(${sub.entityName?uncap_first});
return Result.OK("编辑成功!");
}
/**
* 通过id删除
* @param id
* @return
*/
@AutoLog(value = "${sub.ftlDescription}-通过id删除")
@Operation(summary="${sub.ftlDescription}-通过id删除")
@DeleteMapping(value = "/delete${sub.entityName}")
public Result<String> delete${sub.entityName}(@RequestParam(name="id",required=true) String id) {
${sub.entityName?uncap_first}Service.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
* @param ids
* @return
*/
@AutoLog(value = "${sub.ftlDescription}-批量删除")
@Operation(summary="${sub.ftlDescription}-批量删除")
@DeleteMapping(value = "/deleteBatch${sub.entityName}")
public Result<String> deleteBatch${sub.entityName}(@RequestParam(name="ids",required=true) String ids) {
this.${sub.entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 导出
* @return
*/
@RequestMapping(value = "/export${sub.entityName}")
public ModelAndView export${sub.entityName}(HttpServletRequest request, ${sub.entityName} ${sub.entityName?uncap_first}) {
// Step.1 组装查询条件
QueryWrapper<${sub.entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${sub.entityName?uncap_first}, request.getParameterMap());
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
// Step.2 获取导出数据
List<${sub.entityName}> pageList = ${sub.entityName?uncap_first}Service.list(queryWrapper);
List<${sub.entityName}> exportList = null;
// 过滤选中数据
String selections = request.getParameter("selections");
if (oConvertUtils.isNotEmpty(selections)) {
List<String> selectionList = Arrays.asList(selections.split(","));
exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
} else {
exportList = pageList;
}
// Step.3 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
//此处设置的filename无效,前端会重更新设置一下
mv.addObject(NormalExcelConstants.FILE_NAME, "${sub.ftlDescription}");
mv.addObject(NormalExcelConstants.CLASS, ${sub.entityName}.class);
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${sub.ftlDescription}报表", "导出人:" + sysUser.getRealname(), "${sub.ftlDescription}"));
mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
return mv;
}
/**
* 导入
* @return
*/
@RequestMapping(value = "/import${sub.entityName}/{mainId}")
public Result<?> import${sub.entityName}(HttpServletRequest request, HttpServletResponse response, @PathVariable("mainId") String mainId) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// 获取上传文件对象
MultipartFile file = entity.getValue();
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<${sub.entityName}> list = ExcelImportUtil.importExcel(file.getInputStream(), ${sub.entityName}.class, params);
for (${sub.entityName} temp : list) {
<#list sub.foreignKeys as key>
temp.set${key?cap_first}(mainId);
</#list>
}
long start = System.currentTimeMillis();
${sub.entityName?uncap_first}Service.saveBatch(list);
log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
return Result.OK("文件导入成功!数据行数:" + list.size());
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("文件导入失败:" + e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.error("文件导入失败!");
}
/*--------------------------------子表处理-${sub.ftlDescription}-end----------------------------------------------*/
</#list>
}
@@ -0,0 +1,82 @@
<#include "/common/utils.ftl">
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
@Schema(description="${tableVo.ftlDescription}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#assign excel_ignore_classType_arr=['pca','switch','cat_tree']>
<#list originalColumns as po>
<#-- 生成字典Code -->
<#assign list_field_dictCode="">
<#if po.classType='sel_user'>
<#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
<#elseif po.classType='sel_depart'>
<#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
<#elseif po.classType=='link_table'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicCode = "${po.dictField}", dicText = "${po.dictText?split(",")[0]}"'>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}") && !excel_ignore_classType_arr?seq_contains("${po.classType}")>
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
</#if>
</#if>
<#if list_field_dictCode?length gt 1>
@Dict(${list_field_dictCode?substring(2)})
</#if>
</#if>
<#include "/common/blob.ftl">
</#list>
}
@@ -0,0 +1,84 @@
<#include "/common/utils.ftl">
<#list subTables as subTab>
#segment#${subTab.entityName}.java
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.util.Date;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.UnsupportedEncodingException;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${subTab.tableName}")
@Schema(description="${subTab.ftlDescription}")
public class ${subTab.entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
<#assign excel_ignore_classType_arr=['pca','switch','cat_tree']>
<#list subTab.originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.ASSIGN_ID)
<#else>
<#if po.fieldDbType =='Date' || po.fieldDbType =='Datetime'>
<#if po.classType=='date'>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
</#if>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)>
<#if !excel_ignore_arr?seq_contains("${po.fieldName}") && !excel_ignore_classType_arr?seq_contains("${po.classType}")>
@Excel(name = "${po.filedComment}", width = 15)
</#if>
</#if>
</#if>
<#if po.classType =='list' || po.classType =='radio' || po.classType =='list_multi' || po.classType =='checkbox' || po.classType =='sel_search'>
<#if po.dictTable?default("")?trim?length gt 1>
@Dict(dicCode = "${po.dictField}",dicText = "${po.dictText}",dictTable = "${po.dictTable}")
<#elseif po.dictField?default("")?trim?length gt 1>
@Dict(dicCode = "${po.dictField}")
</#if>
</#if>
<#if po.classType =='cat_tree'>
//@Dict(dicCode = "id",dicText = "name",dictTable = "sys_category")
</#if>
<#if po.classType =='sel_depart'>
<#assign list_field_dictCode='dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dictTable = "sys_depart"'>
@Dict(${list_field_dictCode})
</#if>
<#if po.classType =='link_table'>
<#assign list_field_dictCode='dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dictTable = "sys_depart"'>
@Dict(${list_field_dictCode})
</#if>
<#-- 大字段转换 -->
<#include "/common/blob.ftl">
</#list>
}
</#list>
@@ -0,0 +1,17 @@
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}
@@ -0,0 +1,35 @@
<#list subTables as subTab>
#segment#${subTab.entityName}Mapper.java
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> {
/**
* 通过主表id删除子表数据
*
* @param mainId 主表id
* @return boolean
*/
public boolean deleteByMainId(@Param("mainId") String mainId);
/**
* 通过主表id查询子表数据
*
* @param mainId 主表id
* @return List<${subTab.entityName}>
*/
public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId);
}
</#list>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
</mapper>
@@ -0,0 +1,28 @@
<#list subTables as subTab>
<#assign originalForeignKeys = subTab.originalForeignKeys>
#segment#${subTab.entityName}Mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper">
<delete id="deleteByMainId" parameterType="java.lang.String">
DELETE
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</delete>
<select id="selectByMainId" parameterType="java.lang.String" resultType="${bussiPackage}.${entityPackage}.entity.${subTab.entityName}">
SELECT *
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</select>
</mapper>
</#list>
@@ -0,0 +1,36 @@
package ${bussiPackage}.${entityPackage}.service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
/**
* 删除一对多
*
* @param id
*/
public void delMain (String id);
/**
* 批量删除一对多
*
* @param idList
*/
public void delBatchMain (Collection<? extends Serializable> idList);
}
@@ -0,0 +1,25 @@
<#list subTables as subTab>
#segment#I${subTab.entityName}Service.java
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> {
/**
* 通过主表id查询子表数据
*
* @param mainId
* @return List<${subTab.entityName}>
*/
public List<${subTab.entityName}> selectByMainId(String mainId);
}
</#list>
@@ -0,0 +1,56 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper;
</#list>
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.List;
import java.util.Collection;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
@Autowired
private ${entityName}Mapper ${entityName?uncap_first}Mapper;
<#list subTables as sub>
@Autowired
private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper;
</#list>
@Override
@Transactional(rollbackFor = Exception.class)
public void delMain(String id) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id);
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delBatchMain(Collection<? extends Serializable> idList) {
for(Serializable id:idList) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString());
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
}
}

Some files were not shown because too many files have changed in this diff Show More