Commit 7e5256dcd7c88166813492507e9bf7001d893092

Authored by zhangdaiscott
1 parent 650f048b

代码生成器升级

1.支持插入菜单sql生成
2.vue3模板大升级
3.提供vue3原生表单模板生成
Showing 98 changed files with 5297 additions and 526 deletions

Too many changes to show.

To preserve performance only 68 of 98 files are displayed.

jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl 0 → 100644
  1 +<#if need_select_tag>
  2 + JDictSelectTag,
  3 +</#if>
  4 +<#if need_switch>
  5 + JSwitch,
  6 +</#if>
  7 +<#if need_multi>
  8 + JSelectMultiple,
  9 +</#if>
  10 +<#if need_search>
  11 + JSearchSelect,
  12 +</#if>
  13 +<#if need_popup>
  14 + JPopup,
  15 +</#if>
  16 +<#if need_category>
  17 + JCategorySelect,
  18 +</#if>
  19 +<#if need_dept>
  20 + JSelectDept,
  21 +</#if>
  22 +<#if need_dept_user>
  23 + JSelectUserByDept,
  24 +</#if>
  25 +<#if need_select_tree>
  26 + JTreeSelect,
  27 +</#if>
  28 +<#if need_time>
  29 + TimePicker,
  30 +</#if>
  31 +<#if need_pca>
  32 + JAreaLinkage,
  33 +</#if>
  34 +<#if need_upload>
  35 + JUpload,
  36 +</#if>
  37 +<#if need_image_upload>
  38 + JImageUpload,
  39 +</#if>
  40 +<#if need_markdown>
  41 + JMarkdownEditor,
  42 +</#if>
  43 +<#if need_editor>
  44 + JEditor,
  45 +</#if>
  46 +<#if need_checkbox>
  47 + JCheckbox,
  48 +</#if>
0 49 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl 0 → 100644
  1 +<#include "/common/utils.ftl">
  2 +<#if po.isShow =='Y' && po.fieldName != 'id' && isNotPidField(tableVo, po.fieldDbName)>
  3 +<#assign form_field_dictCode="">
  4 + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
  5 + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  6 + <#elseif po.dictField?default("")?trim?length gt 1>
  7 + <#assign form_field_dictCode="${po.dictField}">
  8 + </#if>
  9 + <a-col :span="${form_span}">
  10 + <a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
  11 + <#if po.classType =='date'>
  12 + <a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  13 + <#elseif po.classType =='datetime'>
  14 + <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<#else>:disabled="disabled"</#if>/>
  15 + <#elseif po.classType =='time'>
  16 + <#assign need_time = true>
  17 + <time-picker placeholder="请选择${po.filedComment}" value-format="HH:mm:ss" v-model:value="formData.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  18 + <#elseif po.classType =='popup'>
  19 + <#assign need_popup = true>
  20 + <#assign sourceFields = po.dictField?default("")?trim?split(",")/>
  21 + <#assign targetFields = po.dictText?default("")?trim?split(",")/>
  22 + <j-popup
  23 + placeholder="请选择${po.filedComment}"
  24 + v-model:value="formData.${po.fieldName}"
  25 + code="${po.dictTable}"
  26 + :fieldConfig="[
  27 + <#list sourceFields as fieldName>
  28 + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' },
  29 + </#list>
  30 + ]"
  31 + :multi="${po.extendParams.popupMulti?c}"
  32 + :setFieldsValue="setFieldsValue"
  33 + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if><#rt>
  34 + />
  35 + <#elseif po.classType =='sel_depart'>
  36 + <#assign need_dept = true>
  37 + <j-select-dept v-model:value="formData.${po.fieldName}" :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
  38 + <#elseif po.classType =='switch'>
  39 + <#assign need_switch = true>
  40 + <j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-switch>
  41 + <#elseif po.classType =='pca'>
  42 + <#assign need_pca = true>
  43 + <j-area-linkage v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
  44 + <#elseif po.classType =='markdown'>
  45 + <#assign need_markdown = true>
  46 + <j-markdown-editor v-model:value="formData.${autoStringSuffixForModel(po)}" id="${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-markdown-editor>
  47 + <#elseif po.classType =='password'>
  48 + <a-input-password v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  49 + <#elseif po.classType =='sel_user'>
  50 + <#assign need_dept_user = true>
  51 + <j-select-user-by-dept v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  52 + <#elseif po.classType =='textarea'>
  53 + <a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  54 + <#elseif po.classType=='radio'>
  55 + <#assign need_select_tag = true>
  56 + <j-dict-select-tag type='radio' v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  57 + <#elseif po.classType=='list'>
  58 + <#assign need_select_tag = true>
  59 + <j-dict-select-tag v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  60 + <#elseif po.classType=='list_multi'>
  61 + <#assign need_multi = true>
  62 + <j-select-multiple type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> :triggerChange="false"/>
  63 + <#elseif po.classType=='checkbox'>
  64 + <#assign need_checkbox = true>
  65 + <j-checkbox type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  66 + <#elseif po.classType=='sel_search'>
  67 + <#assign need_search = true>
  68 + <j-search-select v-model:value="formData.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
  69 + <#elseif po.classType=='cat_tree'>
  70 + <#assign need_category = true>
  71 + <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<#else>:disabled="disabled"</#if> @change="(value) => handleFormChange('${po.fieldName}', value)" />
  72 + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  73 + <a-input-number v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  74 + <#elseif po.classType=='file'>
  75 + <#assign need_upload = true>
  76 + <j-upload v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> <#if po.uploadnum??>:maxCount=${po.uploadnum}</#if>></j-upload>
  77 + <#elseif po.classType=='image'>
  78 + <#assign need_image_upload = true>
  79 + <j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-image-upload>
  80 + <#elseif po.classType=='umeditor'>
  81 + <#assign need_editor = true>
  82 + <j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
  83 + <#elseif po.fieldDbType=='Blob'>
  84 + <a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input>
  85 + <#elseif po.classType == 'sel_tree'>
  86 + <#assign need_select_tree = true>
  87 + <j-tree-select
  88 + <#if po.dictText??>
  89 + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
  90 + dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
  91 + <#elseif po.dictText?split(',')[1]??>
  92 + pidField="${po.dictText?split(',')[1]}"
  93 + <#elseif po.dictText?split(',')[3]??>
  94 + hasChildField="${po.dictText?split(',')[3]}"
  95 + </#if>
  96 + </#if>
  97 + pidValue="${po.dictField}"
  98 + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>
  99 + v-model:value="formData.${po.fieldName}"
  100 + @change="(value) => handleFormChange('${po.fieldName}', value)">
  101 + </j-tree-select>
  102 + <#else>
  103 + <a-input v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input>
  104 + </#if>
  105 + </a-form-item>
  106 + </a-col>
  107 +</#if>
0 108 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl 0 → 100644
  1 +<#if need_select_tag>
  2 + import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
  3 +</#if>
  4 +<#if need_switch>
  5 + import JSwitch from '/@/components/Form/src/jeecg/components/JSwitch.vue';
  6 +</#if>
  7 +<#if need_multi>
  8 + import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
  9 +</#if>
  10 +<#if need_search>
  11 + import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
  12 +</#if>
  13 +<#if need_popup>
  14 + import JPopup from '/@/components/Form/src/jeecg/components/JPopup.vue';
  15 +</#if>
  16 +<#if need_category>
  17 + import JCategorySelect from '/@/components/Form/src/jeecg/components/JCategorySelect.vue';
  18 +</#if>
  19 +<#if need_dept>
  20 + import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
  21 +</#if>
  22 +<#if need_dept_user>
  23 + import JSelectUserByDept from '/@/components/Form/src/jeecg/components/JSelectUserByDept.vue';
  24 +</#if>
  25 +<#if need_select_tree>
  26 + import JTreeSelect from '/@/components/Form/src/jeecg/components/JTreeSelect.vue';
  27 +</#if>
  28 +<#if need_time>
  29 + import { TimePicker } from 'ant-design-vue';
  30 +</#if>
  31 +<#if need_pca>
  32 + import JAreaLinkage from '/@/components/Form/src/jeecg/components/JAreaLinkage.vue';
  33 +</#if>
  34 +<#if need_upload>
  35 + import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
  36 +</#if>
  37 +<#if need_image_upload>
  38 + import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
  39 +</#if>
  40 +<#if need_markdown>
  41 + import JMarkdownEditor from '/@/components/Form/src/jeecg/components/JMarkdownEditor.vue';
  42 +</#if>
  43 +<#if need_editor>
  44 + import JEditor from '/@/components/Form/src/jeecg/components/JEditor.vue';
  45 +</#if>
  46 +<#if need_checkbox>
  47 + import JCheckbox from "/@/components/Form/src/jeecg/components/JCheckbox.vue";
  48 +</#if>
0 49 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl 0 → 100644
  1 +<#if po.isQuery=='Y'>
  2 +<#assign query_flag=true>
  3 + <#if query_field_no==2>
  4 + <template v-if="toggleSearchStatus">
  5 + </#if>
  6 + <#assign query_field_dictCode="">
  7 + <#if po.dictTable?default("")?trim?length gt 1>
  8 + <#assign need_select_tag = true>
  9 + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  10 + <#elseif po.dictField?default("")?trim?length gt 1>
  11 + <#assign need_select_tag = true>
  12 + <#assign query_field_dictCode="${po.dictField}">
  13 + </#if>
  14 + <#if po.queryMode=='single'>
  15 + <#if query_field_no gt 1> </#if><a-col :lg="8">
  16 + <#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
  17 + <#if po.classType=='sel_search'>
  18 + <#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}" />
  19 + <#elseif po.classType=='sel_user'>
  20 + <#if query_field_no gt 1> </#if><j-select-user-by-dept placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" />
  21 + <#elseif po.classType=='switch'>
  22 + <#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 />
  23 + <#elseif po.classType=='sel_depart'>
  24 + <#if query_field_no gt 1> </#if><j-select-dept placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" checkStrictly />
  25 + <#elseif po.classType=='list_multi'>
  26 + <#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model:value="queryParam.${po.fieldName}" />
  27 + <#elseif po.classType=='cat_tree'>
  28 + <#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)" />
  29 + <#elseif po.classType=='date'>
  30 + <#if query_field_no gt 1> </#if><a-date-picker valueFormat="YYYY-MM-DD" placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" />
  31 + <#elseif po.classType=='datetime'>
  32 + <#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}" />
  33 + <#elseif po.classType=='pca'>
  34 + <#if query_field_no gt 1> </#if><j-area-linkage v-model:value="queryParam.${po.fieldName}" placeholder="请选择${po.filedComment}" @change="(value) => handleAreaChange('${po.fieldName}', value)" />
  35 + <#elseif po.classType=='sel_tree'>
  36 + <#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}" />
  37 + <#elseif po.classType=='popup'>
  38 + <#assign sourceFields = po.dictField?default("")?trim?split(",")/>
  39 + <#assign targetFields = po.dictText?default("")?trim?split(",")/>
  40 + <#if query_field_no gt 1> </#if><j-popup
  41 + <#if query_field_no gt 1> </#if>placeholder="请选择${po.filedComment}"
  42 + <#if query_field_no gt 1> </#if>v-model:value="queryParam.${po.fieldName}"
  43 + <#if query_field_no gt 1> </#if>code="${po.dictTable}"
  44 + <#if query_field_no gt 1> </#if>:fieldConfig="[
  45 + <#list sourceFields as fieldName>
  46 + <#if query_field_no gt 1> </#if>{ source: '${fieldName}', target: '${targetFields[fieldName_index]}' },
  47 + </#list>
  48 + <#if query_field_no gt 1> </#if>]"
  49 + <#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}"
  50 + <#if query_field_no gt 1> </#if>:setFieldsValue="setFieldsValue" />
  51 + <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
  52 + <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
  53 + <#if po.dictTable?default("")?trim?length gt 1>
  54 + <#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
  55 + <#elseif po.dictField?default("")?trim?length gt 1>
  56 + <#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
  57 + <#else>
  58 + <#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input>
  59 + </#if>
  60 + <#else>
  61 + <#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input>
  62 + </#if>
  63 + <#if query_field_no gt 1> </#if></a-form-item>
  64 + <#if query_field_no gt 1> </#if></a-col>
  65 + <#else>
  66 + <#if query_field_no gt 1> </#if><a-col :lg="8">
  67 + <#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
  68 + <#if po.classType=='date'>
  69 + <#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust"/>
  70 + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
  71 + <#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择结束日期" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust"/>
  72 + <#elseif po.classType=='datetime'>
  73 + <#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" />
  74 + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
  75 + <#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" />
  76 + <#else>
  77 + <#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust"></a-input>
  78 + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
  79 + <#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust"></a-input>
  80 + </#if>
  81 + <#if query_field_no gt 1> </#if></a-form-item>
  82 + <#if query_field_no gt 1> </#if></a-col>
  83 + </#if>
  84 + <#assign query_field_no=query_field_no+1>
  85 + </#if>
0 86 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl 0 → 100644
  1 +<#assign sourceFields = col.dictField?default("")?trim?split(",")/>
  2 +<#assign targetFields = col.dictText?default("")?trim?split(",")/>
  3 + type: JVxeTypes.popup,
  4 + popupCode:"${col.dictTable}",
  5 + fieldConfig: [
  6 + <#list sourceFields as fieldName>
  7 + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' },
  8 + </#list>
  9 + ],
  10 + <#if col.readonly=='Y'>
  11 + disabled:true,
  12 + </#if>
  13 +
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl 0 → 100644
  1 +<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
  2 +<#assign targetFields = po.dictText?default("")?trim?split(",")/>
  3 + component: 'JPopup',
  4 + componentProps: ({ formActionType }) => {
  5 + const {setFieldsValue} = formActionType;
  6 + return{
  7 + setFieldsValue:setFieldsValue,
  8 + code:"${po.dictTable}",
  9 + fieldConfig: [
  10 + <#list sourceFields as fieldName>
  11 + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' },
  12 + </#list>
  13 + ],
  14 + multi:${po.extendParams.popupMulti?c}
  15 + }
  16 + },
  17 +
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl 0 → 100644
  1 +-- 注意:该页面对应的前台目录为views/${entityPackage}文件夹下
  2 +-- 如果你想更改到其他目录,请修改sql中component字段对应的值
  3 +
  4 +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)
  5 +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}', NULL, '${tableVo.ftlDescription}', '/${entityPackage}/${entityName?uncap_first}List', '${entityPackage}/${entityName}List', NULL, NULL, 0, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
0 6 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl
... ... @@ -25,7 +25,7 @@
25 25 <#return text?uncap_first>
26 26 </#function>
27 27 <#-- 驼峰转下划线 -->
28   -<#function camelToDashed(str, case='normal')>
  28 +<#function camelToDashed(str, case='lower')>
29 29 <#return camelToChar(str, "_", case)>
30 30 </#function>
31 31 <#---->
... ... @@ -130,4 +130,44 @@
130 130 <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}">
131 131 </#if>
132 132 </#if>
  133 +</#function>
  134 +
  135 +
  136 +<#-- vue3 获取表单modal的宽度-->
  137 +<#function getModalWidth fieldRowNum>
  138 + <#assign modal_width = 800>
  139 + <#if fieldRowNum==2>
  140 + <#assign modal_width = 896>
  141 + <#elseif fieldRowNum==3>
  142 + <#assign modal_width = 1024>
  143 + <#elseif fieldRowNum==4>
  144 + <#assign modal_width = 1280>
  145 + </#if>
  146 + <#return modal_width>
  147 +</#function>
  148 +
  149 +<#-- vue3 获取表单 colspan -->
  150 +<#function getFormSpan fieldRowNum>
  151 + <#assign form_span = 24>
  152 + <#if fieldRowNum==2>
  153 + <#assign form_span = 12>
  154 + <#elseif fieldRowNum==3>
  155 + <#assign form_span = 8>
  156 + <#elseif fieldRowNum==4>
  157 + <#assign form_span = 6>
  158 + </#if>
  159 + <#return form_span>
  160 +</#function>
  161 +
  162 +<#-- vue3 native 判断字段名不是 pidField -->
  163 +<#function isNotPidField(tableVo, fieldDbName) >
  164 + <#assign flag = true>
  165 + <#if tableVo??>
  166 + <#if tableVo.extendParams??>
  167 + <#if tableVo.extendParams.pidField?default("")?trim == fieldDbName>
  168 + <#assign flag = false>
  169 + </#if>
  170 + </#if>
  171 + </#if>
  172 + <#return flag>
133 173 </#function>
134 174 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl 0 → 100644
  1 +<#assign fieldValidType = po.fieldValidType!''>
  2 +<#-- 非空校验 -->
  3 +<#if po.nullable == 'N' || fieldValidType == '*'>
  4 +{ required: true, message: '请输入${po.filedComment}!'}<#rt>,
  5 +<#elseif fieldValidType!=''>
  6 +{ required: false}<#rt>,
  7 +</#if>
  8 +<#-- 唯一校验 -->
  9 +<#if fieldValidType == 'only'>
  10 + { validator: ${po.fieldName}Duplicatevalidate }<#rt>
  11 +<#-- 6到16位数字 -->
  12 +<#elseif fieldValidType == 'n6-16'>
  13 + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}<#rt>,
  14 +<#-- 6到16位任意字符 -->
  15 +<#elseif fieldValidType == '*6-16'>
  16 + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}<#rt>,
  17 +<#-- 6到18位字符串 -->
  18 +<#elseif fieldValidType == 's6-18'>
  19 + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}<#rt>,
  20 +<#-- 网址 -->
  21 +<#elseif fieldValidType == 'url'>
  22 + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}<#rt>,
  23 +<#-- 电子邮件 -->
  24 +<#elseif fieldValidType == 'e'>
  25 + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}<#rt>,
  26 +<#-- 手机号码 -->
  27 +<#elseif fieldValidType == 'm'>
  28 + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}<#rt>,
  29 +<#-- 邮政编码 -->
  30 +<#elseif fieldValidType == 'p'>
  31 + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}<#rt>,
  32 +<#-- 字母 -->
  33 +<#elseif fieldValidType == 's'>
  34 + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}<#rt>,
  35 +<#-- 数字 -->
  36 +<#elseif fieldValidType == 'n'>
  37 + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}<#rt>,
  38 +<#-- 整数 -->
  39 +<#elseif fieldValidType == 'z'>
  40 + { pattern: /^-?\d+$/, message: '请输入整数!'}<#rt>,
  41 +<#-- 金额 -->
  42 +<#elseif fieldValidType == 'money'>
  43 + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}<#rt>,
  44 +<#-- 正则校验 -->
  45 +<#elseif fieldValidType != '' && fieldValidType != '*'>
  46 + { pattern: '${fieldValidType}', message: '不符合校验规则!'}<#rt>,
  47 +<#else>
  48 + <#t>
  49 +</#if>
0 50 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl 0 → 100644
  1 +<#include "../../utils.ftl">
  2 +<#list columns as po>
  3 + <#if po.isShow == 'Y' && poHasCheck(po)>
  4 + ${po.fieldName}: [<#include "vue3CoreNative.ftl">],
  5 + </#if>
  6 +</#list>
0 7 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl 0 → 100644
  1 +<#include "../utils.ftl">
  2 + <#if col.isShow == 'Y' && poHasCheck(col)>
  3 + validateRules: [
  4 + <#if col.fieldName != 'id'>
  5 + <#assign subFieldValidType = col.fieldValidType!''>
  6 + <#-- 非空校验 -->
  7 + <#if col.nullable == 'N' || fieldValidType == '*'>
  8 + { required: true, message: '${'$'}{title}不能为空' },
  9 + <#elseif fieldValidType!=''>
  10 + { required: false},
  11 + </#if>
  12 + <#-- 其他情况下,只要有值就被认为是正则校验 -->
  13 + <#if subFieldValidType?length gt 0>
  14 + <#assign subMessage = '格式不正确'>
  15 + <#if subFieldValidType == 'only' >
  16 + <#assign subMessage = '不能重复'>
  17 + </#if>
  18 + { pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }
  19 + <#t>
  20 + </#if>
  21 + </#if>
  22 + ],
  23 + </#if>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
  1 +<#include "/common/utils.ftl">
1 2 package ${bussiPackage}.${entityPackage}.entity;
2 3  
3 4 import java.io.Serializable;
... ... @@ -36,9 +37,9 @@ public class ${entityName} implements Serializable {
36 37 <#-- 生成字典Code -->
37 38 <#assign list_field_dictCode="">
38 39 <#if po.classType='sel_user'>
39   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  40 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
40 41 <#elseif po.classType='sel_depart'>
41   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  42 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
42 43 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
43 44 <#if po.dictTable?default("")?trim?length gt 1>
44 45 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei
... ... @@ -48,7 +48,7 @@
48 48 @input="popupCallback"
49 49 <#if po.readonly=='Y'>disabled</#if>/>
50 50 <#elseif po.classType =='sel_depart'>
51   - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if> />
  51 + <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> />
52 52 <#elseif po.classType =='switch'>
53 53 <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
54 54 <#elseif po.classType =='pca'>
... ... @@ -58,7 +58,7 @@
58 58 <#elseif po.classType =='password'>
59 59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 60 <#elseif po.classType =='sel_user'>
61   - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  61 + <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>/>
62 62 <#elseif po.classType =='textarea'>
63 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 64 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei
... ... @@ -46,6 +46,10 @@
46 46 <template #htmlSlot="{text}">
47 47 <div v-html="text"></div>
48 48 </template>
  49 + <!--省市区字段回显插槽-->
  50 + <template #pcaSlot="{text}">
  51 + {{ getAreaTextByCode(text) }}
  52 + </template>
49 53 <template #fileSlot="{text}">
50 54 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
51 55 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
... ... @@ -64,6 +68,10 @@
64 68 import ${entityName}Modal from './components/${entityName}Modal.vue'
65 69 import {columns, searchFormSchema} from './${entityName}.data';
66 70 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api';
  71 + import { downloadFile } from '/@/utils/common/renderUtils';
  72 + <#if list_need_pca>
  73 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  74 + </#if>
67 75 <#if list_need_category>
68 76 import { loadCategoryData } from '/@/api/common/api'
69 77 import { getAuthCache, setAuthCache } from '/@/utils/auth';
... ... @@ -84,6 +92,17 @@
84 92 schemas: searchFormSchema,
85 93 autoSubmitOnEnter:true,
86 94 showAdvancedButton:true,
  95 + fieldMapToNumber: [
  96 + <#list columns as po>
  97 + <#if po.isQuery=='Y'>
  98 + <#if po.queryMode!='single'>
  99 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  100 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
  101 + </#if>
  102 + </#if>
  103 + </#if>
  104 + </#list>
  105 + ],
87 106 fieldMapToTime: [
88 107 <#list columns as po>
89 108 <#if po.isQuery=='Y'>
... ... @@ -100,6 +119,7 @@
100 119 },
101 120 actionColumn: {
102 121 width: 120,
  122 + fixed:'right'
103 123 },
104 124 },
105 125 exportConfig: {
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi
  1 +<#include "/common/utils.ftl">
1 2 import {BasicColumn} from '/@/components/Table';
2 3 import {FormSchema} from '/@/components/Table';
3 4 import { rules} from '/@/utils/helper/validator';
... ... @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [
24 25 slots: { customRender: 'htmlSlot' },
25 26 <#elseif po.classType=='pca'>
26 27 dataIndex: '${po.fieldName}',
27   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  28 + slots: { customRender: 'pcaSlot' },
28 29 <#elseif po.classType=='file'>
29 30 dataIndex: '${po.fieldName}',
30 31 slots: { customRender: 'fileSlot' },
... ... @@ -56,7 +57,7 @@ export const columns: BasicColumn[] = [
56 57 return render.renderCategoryTree(text,'${po.dictField?default("")}')
57 58 },
58 59 <#else>
59   - customRender: (text, record) => (text ? record['${po.dictText}'] : '')
  60 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
60 61 </#if>
61 62 <#else>
62 63 dataIndex: '${po.fieldName}'
... ... @@ -83,7 +84,7 @@ export const searchFormSchema: FormSchema[] = [
83 84 <#if po.queryMode=='single'>
84 85 {
85 86 label: "${po.filedComment}",
86   - field: "${po.fieldName}",
  87 + field: ${autoStringSuffix(po)},
87 88 <#if po.classType=='sel_search'>
88 89 component: 'JSearchSelect',
89 90 componentProps:{
... ... @@ -94,17 +95,23 @@ export const searchFormSchema: FormSchema[] = [
94 95 <#elseif po.classType=='switch'>
95 96 component: 'JSwitch',
96 97 componentProps:{
  98 + query:true,
97 99 <#if po.dictField != 'is_open'>
98   - options:"${po.dictField}"
  100 + options:${po.dictField}
99 101 </#if>
100 102 },
101 103 <#elseif po.classType=='sel_depart'>
102 104 component: 'JSelectDept',
103 105 <#elseif po.classType=='list_multi'>
104   - component: 'JMultiSelectTag',//暂无该组件
  106 + component: 'JSelectMultiple',
105 107 componentProps:{
106   - dictCode:"query_field_dictCode?default("")"
107   - },
  108 + <#if po.dictTable?default("")?trim?length gt 1>
  109 + dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
  110 + <#elseif po.dictField?default("")?trim?length gt 1>
  111 + dictCode:"${po.dictField}",
  112 + </#if>
  113 + triggerChange: true
  114 + },
108 115 <#elseif po.classType=='cat_tree'>
109 116 component: 'JCategorySelect',
110 117 componentProps:{
... ... @@ -117,19 +124,15 @@ export const searchFormSchema: FormSchema[] = [
117 124 componentProps: {
118 125 showTime:true
119 126 },
  127 + <#elseif po.classType =='time'>
  128 + component: 'TimePicker',
  129 + componentProps: {
  130 + valueFormat: 'HH:mm:ss'
  131 + },
120 132 <#elseif po.classType=='pca'>
121 133 component: 'JAreaLinkage',
122 134 <#elseif po.classType=='popup'>
123   - component: 'JPopup',
124   - componentProps: ({ formActionType }) => {
125   - const {setFieldsValue} = formActionType;
126   - return{
127   - setFieldsValue:setFieldsValue,
128   - code:"${po.dictTable}",
129   - fieldConfig:"${po.dictField}",
130   - multi:${po.extendParams.popupMulti?c},
131   - }
132   - },
  135 + <#include "/common/form/vue3popup.ftl">
133 136 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
134 137 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
135 138 component: 'JDictSelectTag',
... ... @@ -156,6 +159,8 @@ export const searchFormSchema: FormSchema[] = [
156 159 componentProps: {
157 160 showTime:true
158 161 },
  162 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  163 + component: 'JRangeNumber',
159 164 <#else>
160 165 component: 'Input', //TODO 范围查询
161 166 </#if>
... ... @@ -188,27 +193,22 @@ export const formSchema: FormSchema[] = [
188 193 </#if>
189 194 {
190 195 label: '${po.filedComment}',
191   - field: '${po.fieldName}',
  196 + field: ${autoStringSuffix(po)},
192 197 <#if po.classType =='date'>
193 198 component: 'DatePicker',
194   - <#elseif po.fieldType =='datetime'>
  199 + <#elseif po.classType =='datetime'>
195 200 component: 'DatePicker',
196 201 componentProps: {
197   - showTime:true
  202 + showTime: true,
  203 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
198 204 },
199   - <#elseif po.fieldType =='time'>
  205 + <#elseif po.classType =='time'>
200 206 component: 'TimePicker',
  207 + componentProps: {
  208 + valueFormat: 'HH:mm:ss'
  209 + },
201 210 <#elseif po.classType =='popup'>
202   - component: 'JPopup',
203   - componentProps: ({ formActionType }) => {
204   - const {setFieldsValue} = formActionType;
205   - return{
206   - setFieldsValue:setFieldsValue,
207   - code:"${po.dictTable}",
208   - fieldConfig:${po.dictField},
209   - multi:${po.extendParams.popupMulti?c},
210   - }
211   - },
  211 + <#include "/common/form/vue3popup.ftl">
212 212 <#elseif po.classType =='sel_depart'>
213 213 component: 'JSelectDept',
214 214 <#elseif po.classType =='switch'>
... ... @@ -230,14 +230,14 @@ export const formSchema: FormSchema[] = [
230 230 labelKey:'realname',
231 231 },
232 232 <#elseif po.classType =='textarea'>
233   - component: 'InputTextArea',//TODO 注意string转换问题
  233 + component: 'InputTextArea',
234 234 <#elseif po.classType=='list' || po.classType=='radio'>
235 235 component: 'JDictSelectTag',
236 236 componentProps:{
237 237 dictCode:"${form_field_dictCode}"
238 238 },
239 239 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
240   - component: 'JMultiSelectTag',//TODO 暂无该组件
  240 + component: 'JSelectMultiple',
241 241 componentProps:{
242 242 dictCode:"${form_field_dictCode}"
243 243 },
... ... @@ -272,7 +272,7 @@ export const formSchema: FormSchema[] = [
272 272 </#if>
273 273 },
274 274 <#elseif po.classType=='umeditor'>
275   - component: 'JCodeEditor', //TODO String后缀暂未添加
  275 + component: 'JEditor',
276 276 <#elseif po.classType == 'sel_tree'>
277 277 component: 'JTreeSelect',
278 278 componentProps:{
... ... @@ -290,7 +290,6 @@ export const formSchema: FormSchema[] = [
290 290 <#else>
291 291 component: 'Input',
292 292 </#if>
293   - <#include "/common/utils.ftl">
294 293 <#if po.isShow == 'Y' && poHasCheck(po)>
295 294 dynamicRules: ({model,schema}) => {
296 295 <#if po.fieldName != 'id'>
... ... @@ -304,16 +303,16 @@ export const formSchema: FormSchema[] = [
304 303 </#if>
305 304 <#-- 唯一校验 -->
306 305 <#if fieldValidType == 'only'>
307   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  306 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
308 307 <#-- 6到16位数字 -->
309 308 <#elseif fieldValidType == 'n6-16'>
310 309 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
311 310 <#-- 6到16位任意字符 -->
312 311 <#elseif fieldValidType == '*6-16'>
313 312 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
314   - <#-- 6到18位字符串 -->
  313 + <#-- 6到18位字 -->
315 314 <#elseif fieldValidType == 's6-18'>
316   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  315 + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
317 316 <#-- 网址 -->
318 317 <#elseif fieldValidType == 'url'>
319 318 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei
  1 +<#include "/common/utils.ftl">
1 2 <template>
2   - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
  3 + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
3 4 <BasicForm @register="registerForm"/>
4 5 </BasicModal>
5 6 </template>
... ... @@ -18,6 +19,7 @@
18 19 labelWidth: 150,
19 20 schemas: formSchema,
20 21 showActionButtonGroup: false,
  22 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
21 23 });
22 24 //表单赋值
23 25 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
... ... @@ -54,5 +56,12 @@
54 56 </script>
55 57  
56 58 <style lang="less" scoped>
  59 + /** 时间和数字输入框样式 */
  60 + :deep(.ant-input-number){
  61 + width: 100%
  62 + }
57 63  
  64 + :deep(.ant-calendar-picker){
  65 + width: 100%
  66 + }
58 67 </style>
59 68 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei 0 → 100644
  1 +<template>
  2 + <div>
  3 +<#assign query_field_no=0>
  4 +<#assign need_category = false>
  5 +<#assign need_pca = false>
  6 +<#assign need_search = false>
  7 +<#assign need_dept_user = false>
  8 +<#assign need_switch = false>
  9 +<#assign need_dept = false>
  10 +<#assign need_multi = false>
  11 +<#assign need_popup = false>
  12 +<#assign need_select_tag = false>
  13 +<#assign need_select_tree = false>
  14 +<#assign need_time = false>
  15 +<#assign bpm_flag=false>
  16 +<#assign need_markdown = false>
  17 +<#assign need_upload = false>
  18 +<#assign need_image_upload = false>
  19 +<#assign need_editor = false>
  20 +<#assign need_checkbox = false>
  21 +<#assign query_flag = false>
  22 + <!--查询区域-->
  23 + <div class="jeecg-basic-table-form-container">
  24 + <a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
  25 + <a-row :gutter="24">
  26 +<#-- 开始循环 -->
  27 +<#list columns as po>
  28 +<#if po.fieldDbName=='bpm_status'>
  29 + <#assign bpm_flag=true>
  30 +</#if>
  31 +<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
  32 +<#assign need_category=true>
  33 +</#if>
  34 +<#if po.classType=='pca'>
  35 +<#assign need_pca=true>
  36 +</#if>
  37 +<#if po.classType=='sel_search'>
  38 +<#assign need_search = true>
  39 +</#if>
  40 +<#if po.classType=='sel_user'>
  41 +<#assign need_dept_user = true>
  42 +</#if>
  43 +<#if po.classType=='sel_depart'>
  44 +<#assign need_dept = true>
  45 +</#if>
  46 +<#if po.classType=='switch'>
  47 +<#assign need_switch = true>
  48 +</#if>
  49 +<#if po.classType=='list_multi'>
  50 +<#assign need_multi = true>
  51 +</#if>
  52 +<#if po.classType=='popup'>
  53 +<#assign need_popup = true>
  54 +</#if>
  55 +<#if po.classType=='sel_tree'>
  56 +<#assign need_select_tree = true>
  57 +</#if>
  58 +<#if po.classType=='time'>
  59 +<#assign need_time = true>
  60 +</#if>
  61 + <#include "/common/form/native/vue3NativeSearch.ftl">
  62 +</#list>
  63 +<#if query_field_no gt 2>
  64 + </template>
  65 +</#if>
  66 +<#if query_flag>
  67 + <a-col :xl="6" :lg="7" :md="8" :sm="24">
  68 + <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  69 + <a-col :lg="6">
  70 + <a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
  71 + <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
  72 + <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
  73 + {{ toggleSearchStatus ? '收起' : '展开' }}
  74 + <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
  75 + </a>
  76 + </a-col>
  77 + </span>
  78 + </a-col>
  79 +</#if>
  80 + </a-row>
  81 + </a-form>
  82 + </div>
  83 +<#-- 结束循环 -->
  84 + <!--引用表格-->
  85 + <BasicTable @register="registerTable" :rowSelection="rowSelection">
  86 + <!--插槽:table标题-->
  87 + <template #tableTitle>
  88 + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
  89 + <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
  90 + <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
  91 + <a-dropdown v-if="selectedRowKeys.length > 0">
  92 + <template #overlay>
  93 + <a-menu>
  94 + <a-menu-item key="1" @click="batchHandleDelete">
  95 + <Icon icon="ant-design:delete-outlined"></Icon>
  96 + 删除
  97 + </a-menu-item>
  98 + </a-menu>
  99 + </template>
  100 + <a-button>批量操作
  101 + <Icon icon="mdi:chevron-down"></Icon>
  102 + </a-button>
  103 + </a-dropdown>
  104 + </template>
  105 + <!--操作栏-->
  106 + <template #action="{ record }">
  107 + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
  108 + </template>
  109 + <!--字段回显插槽-->
  110 + <template #htmlSlot="{text}">
  111 + <div v-html="text"></div>
  112 + </template>
  113 + <!--省市区字段回显插槽-->
  114 + <template #pcaSlot="{text}">
  115 + {{ getAreaTextByCode(text) }}
  116 + </template>
  117 + <template #fileSlot="{text}">
  118 + <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
  119 + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
  120 + </template>
  121 + </BasicTable>
  122 + <!-- 表单区域 -->
  123 + <${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal>
  124 + </div>
  125 +</template>
  126 +
  127 +<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
  128 + import { ref, reactive } from 'vue';
  129 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  130 + import { useListPage } from '/@/hooks/system/useListPage';
  131 + import { columns } from './${entityName}.data';
  132 + import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './${entityName}.api';
  133 + import { downloadFile } from '/@/utils/common/renderUtils';
  134 + import ${entityName}Modal from './components/${entityName}Modal.vue'
  135 + <#include "/common/form/native/vue3NativeImport.ftl">
  136 +<#if need_category>
  137 + import { loadCategoryData } from '/@/api/common/api';
  138 + import { getAuthCache, setAuthCache } from '/@/utils/auth';
  139 + import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
  140 +</#if>
  141 +<#if need_pca>
  142 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  143 +</#if>
  144 +
  145 + const queryParam = ref<any>({});
  146 + const toggleSearchStatus = ref<boolean>(false);
  147 + const registerModal = ref();
  148 + //注册table数据
  149 + const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
  150 + tableProps: {
  151 + title: '${tableVo.ftlDescription}',
  152 + api: list,
  153 + columns,
  154 + canResize:false,
  155 + useSearchForm: false,
  156 + actionColumn: {
  157 + width: 120,
  158 + fixed: 'right',
  159 + },
  160 + beforeFetch: (params) => {
  161 + return Object.assign(params, queryParam.value);
  162 + },
  163 + },
  164 + exportConfig: {
  165 + name: "${tableVo.ftlDescription}",
  166 + url: getExportUrl,
  167 + },
  168 + importConfig: {
  169 + url: getImportUrl,
  170 + success: handleSuccess
  171 + },
  172 + });
  173 + const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
  174 + const labelCol = reactive({
  175 + xs: { span: 24 },
  176 + sm: { span: 7 },
  177 + });
  178 + const wrapperCol = reactive({
  179 + xs: { span: 24 },
  180 + sm: { span: 16 },
  181 + });
  182 +
  183 + /**
  184 + * 新增事件
  185 + */
  186 + function handleAdd() {
  187 + registerModal.value.disableSubmit = false;
  188 + registerModal.value.add();
  189 + }
  190 +
  191 + /**
  192 + * 编辑事件
  193 + */
  194 + function handleEdit(record: Recordable) {
  195 + registerModal.value.disableSubmit = false;
  196 + registerModal.value.edit(record);
  197 + }
  198 +
  199 + /**
  200 + * 详情
  201 + */
  202 + function handleDetail(record: Recordable) {
  203 + registerModal.value.disableSubmit = true;
  204 + registerModal.value.edit(record);
  205 + }
  206 +
  207 + /**
  208 + * 删除事件
  209 + */
  210 + async function handleDelete(record) {
  211 + await deleteOne({ id: record.id }, handleSuccess);
  212 + }
  213 +
  214 + /**
  215 + * 批量删除事件
  216 + */
  217 + async function batchHandleDelete() {
  218 + await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
  219 + }
  220 +
  221 + /**
  222 + * 成功回调
  223 + */
  224 + function handleSuccess() {
  225 + (selectedRowKeys.value = []) && reload();
  226 + }
  227 +
  228 + /**
  229 + * 操作栏
  230 + */
  231 + function getTableAction(record) {
  232 + return [
  233 + {
  234 + label: '编辑',
  235 + onClick: handleEdit.bind(null, record),
  236 + },
  237 + ];
  238 + }
  239 +
  240 + /**
  241 + * 下拉操作栏
  242 + */
  243 + function getDropDownAction(record) {
  244 + return [
  245 + {
  246 + label: '详情',
  247 + onClick: handleDetail.bind(null, record),
  248 + },
  249 + {
  250 + label: '删除',
  251 + popConfirm: {
  252 + title: '是否确认删除',
  253 + confirm: handleDelete.bind(null, record),
  254 + },
  255 + },
  256 + ];
  257 + }
  258 +
  259 + /**
  260 + * 查询
  261 + */
  262 + function searchQuery() {
  263 + reload();
  264 + }
  265 +
  266 + /**
  267 + * 重置
  268 + */
  269 + function searchReset() {
  270 + queryParam.value = {};
  271 + selectedRowKeys.value = [];
  272 + //刷新数据
  273 + reload();
  274 + }
  275 +
  276 + <#if need_popup>
  277 + /**
  278 + * popup组件值改变事件
  279 + */
  280 + function setFieldsValue(map) {
  281 + Object.keys(map).map((key) => {
  282 + queryParam.value[key] = map[key];
  283 + });
  284 + }
  285 + </#if>
  286 +
  287 + <#if need_pca>
  288 + /**
  289 + * 省市区点击事件
  290 + * @param key
  291 + * @param value
  292 + */
  293 + function handleAreaChange(key, value) {
  294 + queryParam.value[key] = value.join(',');
  295 + }
  296 + </#if>
  297 +
  298 + <#if need_category>
  299 + /**
  300 + * form点击事件
  301 + * @param value
  302 + */
  303 + function handleFormChange(key, value) {
  304 + queryParam.value[key] = value;
  305 + }
  306 +
  307 + /**
  308 + * 初始化字典配置
  309 + */
  310 + function initDictConfig() {
  311 + <#list columns as po>
  312 + <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
  313 + <#if po.classType=='cat_tree' && need_category==true>
  314 + loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
  315 + if (res) {
  316 + let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
  317 + if(!allDictDate['${po.dictField?default("")}']){
  318 + Object.assign(allDictDate,{'${po.dictField?default("")}':res})
  319 + }
  320 + setAuthCache(DB_DICT_DATA_KEY,allDictDate)
  321 + }
  322 + });
  323 + </#if>
  324 + </#if>
  325 + </#list>
  326 + }
  327 + initDictConfig();
  328 + </#if>
  329 +</script>
  330 +
  331 +<style lang="less" scoped>
  332 + .jeecg-basic-table-form-container {
  333 + .table-page-search-submitButtons {
  334 + display: block;
  335 + margin-bottom: 24px;
  336 + white-space: nowrap;
  337 + }
  338 + .query-group-cust{
  339 + width: calc(50% - 15px);
  340 + min-width: 100px !important;
  341 + }
  342 + .query-group-split-cust{
  343 + width: 30px;
  344 + display: inline-block;
  345 + text-align: center
  346 + }
  347 + }
  348 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi 0 → 100644
  1 +import { defHttp } from '/@/utils/http/axios';
  2 +import { Modal } from 'ant-design-vue';
  3 +
  4 +enum Api {
  5 + list = '/${entityPackage}/${entityName?uncap_first}/list',
  6 + save='/${entityPackage}/${entityName?uncap_first}/add',
  7 + edit='/${entityPackage}/${entityName?uncap_first}/edit',
  8 + deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete',
  9 + deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
  10 + importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
  11 + exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
  12 +}
  13 +
  14 +/**
  15 + * 导出api
  16 + * @param params
  17 + */
  18 +export const getExportUrl = Api.exportXls;
  19 +
  20 +/**
  21 + * 导入api
  22 + */
  23 +export const getImportUrl = Api.importExcel;
  24 +
  25 +/**
  26 + * 列表接口
  27 + * @param params
  28 + */
  29 +export const list = (params) => defHttp.get({ url: Api.list, params });
  30 +
  31 +/**
  32 + * 删除单个
  33 + * @param params
  34 + * @param handleSuccess
  35 + */
  36 +export const deleteOne = (params,handleSuccess) => {
  37 + return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
  38 + handleSuccess();
  39 + });
  40 +}
  41 +
  42 +/**
  43 + * 批量删除
  44 + * @param params
  45 + * @param handleSuccess
  46 + */
  47 +export const batchDelete = (params, handleSuccess) => {
  48 + Modal.confirm({
  49 + title: '确认删除',
  50 + content: '是否删除选中数据',
  51 + okText: '确认',
  52 + cancelText: '取消',
  53 + onOk: () => {
  54 + return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
  55 + handleSuccess();
  56 + });
  57 + }
  58 + });
  59 +}
  60 +
  61 +/**
  62 + * 保存或者更新
  63 + * @param params
  64 + * @param isUpdate
  65 + */
  66 +export const saveOrUpdate = (params, isUpdate) => {
  67 + let url = isUpdate ? Api.edit : Api.save;
  68 + return defHttp.post({ url: url, params }, { isTransformResponse: false });
  69 +}
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi 0 → 100644
  1 +<#include "/common/utils.ftl">
  2 +import {BasicColumn} from '/@/components/Table';
  3 +import {FormSchema} from '/@/components/Table';
  4 +import { rules} from '/@/utils/helper/validator';
  5 +import { render } from '/@/utils/common/renderUtils';
  6 +//列表数据
  7 +export const columns: BasicColumn[] = [
  8 + <#list columns as po>
  9 + <#if po.isShowList =='Y' && po.fieldName !='id'>
  10 + {
  11 + title: '${po.filedComment}',
  12 + align: "center",
  13 + <#if po.sort=='Y'>
  14 + sorter: true,
  15 + </#if>
  16 + <#if po.classType=='date'>
  17 + dataIndex: '${po.fieldName}',
  18 + customRender:({text}) =>{
  19 + return !text?"":(text.length>10?text.substr(0,10):text);
  20 + },
  21 + <#elseif po.fieldDbType=='Blob'>
  22 + dataIndex: '${po.fieldName}String'
  23 + <#elseif po.classType=='umeditor'>
  24 + dataIndex: '${po.fieldName}',
  25 + slots: { customRender: 'htmlSlot' },
  26 + <#elseif po.classType=='pca'>
  27 + dataIndex: '${po.fieldName}',
  28 + slots: { customRender: 'pcaSlot' },
  29 + <#elseif po.classType=='file'>
  30 + dataIndex: '${po.fieldName}',
  31 + slots: { customRender: 'fileSlot' },
  32 + <#elseif po.classType=='image'>
  33 + dataIndex: '${po.fieldName}',
  34 + customRender: render.renderImage,
  35 + <#elseif po.classType=='switch'>
  36 + dataIndex: '${po.fieldName}',
  37 +<#assign switch_extend_arr=['Y','N']>
  38 +<#if po.dictField?default("")?contains("[")>
  39 +<#assign switch_extend_arr=po.dictField?eval>
  40 +</#if>
  41 +<#list switch_extend_arr as a>
  42 +<#if a_index == 0>
  43 +<#assign switch_extend_arr1=a>
  44 +<#else>
  45 +<#assign switch_extend_arr2=a>
  46 +</#if>
  47 +</#list>
  48 + customRender:({text}) => {
  49 + return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
  50 + },
  51 + <#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'>
  52 + dataIndex: '${po.fieldName}_dictText'
  53 + <#elseif po.classType=='cat_tree'>
  54 + dataIndex: '${po.fieldName}',
  55 + <#if po.dictText?default("")?trim?length == 0>
  56 + customRender:({text}) => {
  57 + return render.renderCategoryTree(text,'${po.dictField?default("")}');
  58 + },
  59 + <#else>
  60 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '');
  61 + </#if>
  62 + <#else>
  63 + dataIndex: '${po.fieldName}'
  64 + </#if>
  65 + },
  66 + </#if>
  67 + </#list>
  68 +];
  69 +
  70 +//查询数据
  71 +export const searchFormSchema: FormSchema[] = [
  72 +<#-- 开始循环 -->
  73 +<#list columns as po>
  74 +<#if po.fieldDbName=='bpm_status'>
  75 + <#assign bpm_flag=true>
  76 +</#if>
  77 +<#if po.isQuery=='Y'>
  78 +<#assign query_flag=true>
  79 + <#assign query_field_dictCode="">
  80 + <#if po.dictTable?default("")?trim?length gt 1>
  81 + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  82 + <#elseif po.dictField?default("")?trim?length gt 1>
  83 + <#assign query_field_dictCode="${po.dictField}">
  84 + </#if>
  85 +<#if po.queryMode=='single'>
  86 + {
  87 + label: "${po.filedComment}",
  88 + field: ${autoStringSuffix(po)},
  89 +<#if po.classType=='sel_search'>
  90 + component: 'JSearchSelect',
  91 + componentProps:{
  92 + dict: "${po.dictTable},${po.dictText},${po.dictField}"
  93 + },
  94 +<#elseif po.classType=='sel_user'>
  95 + component: 'JSelectUserByDept',
  96 +<#elseif po.classType=='switch'>
  97 + component: 'JSwitch',
  98 + componentProps:{
  99 + <#if po.dictField != 'is_open'>
  100 + options: "${po.dictField}"
  101 + </#if>
  102 + },
  103 + <#elseif po.classType=='sel_depart'>
  104 + component: 'JSelectDept',
  105 + <#elseif po.classType=='list_multi'>
  106 + component: 'JSelectMultiple',
  107 + componentProps: {
  108 + <#if po.dictTable?default("")?trim?length gt 1>
  109 + dictCode: "${po.dictTable},${po.dictText},${po.dictField}"
  110 + <#elseif po.dictField?default("")?trim?length gt 1>
  111 + dictCode: "${po.dictField}"
  112 + </#if>
  113 + },
  114 + <#elseif po.classType=='cat_tree'>
  115 + component: 'JCategorySelect',
  116 + componentProps:{
  117 + pcode: "${po.dictField?default("")}",//back和事件未添加,暂时有问题
  118 + },
  119 +<#elseif po.classType=='date'>
  120 + component: 'DatePicker',
  121 +<#elseif po.classType=='datetime'>
  122 + component: 'DatePicker',
  123 + componentProps: {
  124 + showTime: true,
  125 + },
  126 + <#elseif po.classType =='time'>
  127 + component: 'TimePicker',
  128 + componentProps: {
  129 + valueFormat: 'HH:mm:ss',
  130 + },
  131 +<#elseif po.classType=='pca'>
  132 + component: 'JAreaLinkage',
  133 +<#elseif po.classType=='popup'>
  134 + <#include "/common/form/vue3popup.ftl">
  135 +<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
  136 +<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
  137 + component: 'JDictSelectTag',
  138 + componentProps:{
  139 + <#if po.dictTable?default("")?trim?length gt 1>
  140 + dictCode: "${po.dictTable},${po.dictText},${po.dictField}"
  141 + <#elseif po.dictField?default("")?trim?length gt 1>
  142 + dictCode: "${po.dictField}"
  143 + </#if>
  144 + },
  145 +<#else>
  146 + component: 'Input',
  147 +</#if>
  148 + colProps: {span: 6},
  149 + },
  150 +<#else>
  151 + {
  152 + label: "${po.filedComment}",
  153 + field: "${po.fieldName}",
  154 +<#if po.classType=='date'>
  155 + component: 'RangePicker',
  156 +<#elseif po.classType=='datetime'>
  157 + component: 'RangePicker',
  158 + componentProps: {
  159 + showTime: true,
  160 + },
  161 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  162 + component: 'JRangeNumber',
  163 +<#else>
  164 + component: 'Input', //TODO 范围查询
  165 +</#if>
  166 + colProps: {span: 6},
  167 + },
  168 +</#if>
  169 +</#if>
  170 +</#list>
  171 +<#-- 结束循环 -->
  172 +];
  173 +
  174 +//表单数据
  175 +export const formSchema: FormSchema[] = [
  176 +<#assign form_cat_tree = false>
  177 +<#assign form_cat_back = "">
  178 +<#assign bpm_flag=false>
  179 +<#assign id_exists = false>
  180 +<#list columns as po><#rt/>
  181 +<#if po.fieldDbName=='bpm_status'>
  182 + <#assign bpm_flag=true>
  183 +</#if>
  184 +<#if po.fieldDbName == 'id'>
  185 + <#assign id_exists = true>
  186 +</#if>
  187 +<#if po.isShow =='Y'>
  188 +<#assign form_field_dictCode="">
  189 + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
  190 + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  191 + <#elseif po.dictField?default("")?trim?length gt 1>
  192 + <#assign form_field_dictCode="${po.dictField}">
  193 + </#if>
  194 + {
  195 + label: '${po.filedComment}',
  196 + field: ${autoStringSuffix(po)},
  197 + <#if po.classType =='date'>
  198 + component: 'DatePicker',
  199 + <#elseif po.classType =='datetime'>
  200 + component: 'DatePicker',
  201 + componentProps: {
  202 + showTime: true,
  203 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
  204 + },
  205 + <#elseif po.classType =='time'>
  206 + component: 'TimePicker',
  207 + componentProps: {
  208 + valueFormat: 'HH:mm:ss'
  209 + },
  210 + <#elseif po.classType =='popup'>
  211 + <#include "/common/form/vue3popup.ftl">
  212 + <#elseif po.classType =='sel_depart'>
  213 + component: 'JSelectDept',
  214 + <#elseif po.classType =='switch'>
  215 + component: 'JSwitch',
  216 + componentProps:{
  217 + <#if po.dictField != 'is_open'>
  218 + options: ${po.dictField}
  219 + </#if>
  220 + },
  221 + <#elseif po.classType =='pca'>
  222 + component: 'JAreaLinkage',
  223 + <#elseif po.classType =='markdown'>
  224 + component: 'JMarkdownEditor',//注意string转换问题
  225 + <#elseif po.classType =='password'>
  226 + component: 'InputPassword',
  227 + <#elseif po.classType =='sel_user'>
  228 + component: 'JSelectUserByDept',
  229 + componentProps:{
  230 + labelKey: 'realname',
  231 + },
  232 + <#elseif po.classType =='textarea'>
  233 + component: 'InputTextArea',
  234 + <#elseif po.classType=='list' || po.classType=='radio'>
  235 + component: 'JDictSelectTag',
  236 + componentProps:{
  237 + dictCode: "${form_field_dictCode}"
  238 + },
  239 + <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
  240 + component: 'JSelectMultiple',
  241 + componentProps:{
  242 + dictCode: "${form_field_dictCode}"
  243 + },
  244 + <#elseif po.classType=='sel_search'>
  245 + component: 'JSearchSelect',
  246 + componentProps:{
  247 + dict: "${form_field_dictCode}"
  248 + },
  249 +<#elseif po.classType=='cat_tree'>
  250 + <#assign form_cat_tree = true>
  251 + component: 'JCategorySelect',
  252 + componentProps:{
  253 + pcode: "${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
  254 + },
  255 + <#if po.dictText?default("")?trim?length gt 1>
  256 + <#assign form_cat_back = "${po.dictText}">
  257 + </#if>
  258 + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  259 + component: 'InputNumber',
  260 + <#elseif po.classType=='file'>
  261 + component: 'JUpload',
  262 + componentProps:{
  263 + <#if po.uploadnum??>
  264 + maxCount: ${po.uploadnum}
  265 + </#if>
  266 + },
  267 + <#elseif po.classType=='image'>
  268 + component: 'JImageUpload',
  269 + componentProps:{
  270 + <#if po.uploadnum??>
  271 + fileMax: ${po.uploadnum}
  272 + </#if>
  273 + },
  274 + <#elseif po.classType=='umeditor'>
  275 + component: 'JEditor',
  276 + <#elseif po.classType == 'sel_tree'>
  277 + component: 'JTreeSelect',
  278 + componentProps:{
  279 + <#if po.dictText??>
  280 + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
  281 + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
  282 + <#elseif po.dictText?split(',')[1]??>
  283 + pidField: "${po.dictText?split(',')[1]}",
  284 + <#elseif po.dictText?split(',')[3]??>
  285 + hasChildField: "${po.dictText?split(',')[3]}",
  286 + </#if>
  287 + </#if>
  288 + pidValue: "${po.dictField}",
  289 + },
  290 + <#else>
  291 + component: 'Input',
  292 + </#if>
  293 + <#if po.isShow == 'Y' && poHasCheck(po)>
  294 + dynamicRules: ({model,schema}) => {
  295 + <#if po.fieldName != 'id'>
  296 + <#assign fieldValidType = po.fieldValidType!''>
  297 + return [
  298 + <#-- 非空校验 -->
  299 + <#if po.nullable == 'N' || fieldValidType == '*'>
  300 + { required: true, message: '请输入${po.filedComment}!'},
  301 + <#elseif fieldValidType!=''>
  302 + { required: false},
  303 + </#if>
  304 + <#-- 唯一校验 -->
  305 + <#if fieldValidType == 'only'>
  306 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
  307 + <#-- 6到16位数字 -->
  308 + <#elseif fieldValidType == 'n6-16'>
  309 + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
  310 + <#-- 6到16位任意字符 -->
  311 + <#elseif fieldValidType == '*6-16'>
  312 + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
  313 + <#-- 6到18位字符串 -->
  314 + <#elseif fieldValidType == 's6-18'>
  315 + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  316 + <#-- 网址 -->
  317 + <#elseif fieldValidType == 'url'>
  318 + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
  319 + <#-- 电子邮件 -->
  320 + <#elseif fieldValidType == 'e'>
  321 + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
  322 + <#-- 手机号码 -->
  323 + <#elseif fieldValidType == 'm'>
  324 + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
  325 + <#-- 邮政编码 -->
  326 + <#elseif fieldValidType == 'p'>
  327 + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
  328 + <#-- 字母 -->
  329 + <#elseif fieldValidType == 's'>
  330 + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
  331 + <#-- 数字 -->
  332 + <#elseif fieldValidType == 'n'>
  333 + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
  334 + <#-- 整数 -->
  335 + <#elseif fieldValidType == 'z'>
  336 + { pattern: /^-?\d+$/, message: '请输入整数!'},
  337 + <#-- 金额 -->
  338 + <#elseif fieldValidType == 'money'>
  339 + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
  340 + <#-- 正则校验 -->
  341 + <#elseif fieldValidType != '' && fieldValidType != '*'>
  342 + { pattern: '${fieldValidType}', message: '不符合校验规则!'},
  343 + <#-- 无校验 -->
  344 + <#else>
  345 + <#t>
  346 + </#if>
  347 + ];
  348 + </#if>
  349 + },
  350 + </#if>
  351 + <#if po.readonly=='Y'>
  352 + dynamicDisabled: true
  353 + </#if>
  354 + },
  355 +</#if>
  356 +</#list>
  357 +<#if id_exists == false>
  358 + // TODO 主键隐藏字段,目前写死为ID
  359 + {
  360 + label: '',
  361 + field: 'id',
  362 + component: 'Input',
  363 + show: false,
  364 + },
  365 +</#if>
  366 +];
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei 0 → 100644
  1 +<#include "/common/utils.ftl">
  2 +<template>
  3 + <a-spin :spinning="confirmLoading">
  4 + <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
  5 + <a-row>
  6 +<#assign need_category = false>
  7 +<#assign bpm_flag=false>
  8 +<#assign need_pca = false>
  9 +<#assign need_search = false>
  10 +<#assign need_dept_user = false>
  11 +<#assign need_switch = false>
  12 +<#assign need_dept = false>
  13 +<#assign need_multi = false>
  14 +<#assign need_popup = false>
  15 +<#assign need_select_tag = false>
  16 +<#assign need_select_tree = false>
  17 +<#assign need_time = false>
  18 +<#assign need_markdown = false>
  19 +<#assign need_upload = false>
  20 +<#assign need_image_upload = false>
  21 +<#assign need_editor = false>
  22 +<#assign need_checkbox = false>
  23 +<#assign hasOnlyValidate = false>
  24 +<#assign form_span = 24>
  25 +<#if tableVo.fieldRowNum==2>
  26 +<#assign form_span = 12>
  27 +<#elseif tableVo.fieldRowNum==3>
  28 +<#assign form_span = 8>
  29 +<#elseif tableVo.fieldRowNum==4>
  30 +<#assign form_span = 6>
  31 +</#if>
  32 +<#list columns as po>
  33 +<#if po.fieldDbName=='bpm_status'>
  34 + <#assign bpm_flag=true>
  35 +</#if>
  36 +<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
  37 + <#assign hasOnlyValidate = true>
  38 +</#if>
  39 + <#include "/common/form/native/vue3NativeForm.ftl">
  40 +</#list>
  41 + </a-row>
  42 + </a-form>
  43 + </a-spin>
  44 +</template>
  45 +
  46 +<script lang="ts" setup>
  47 + import { ref, reactive, defineExpose, nextTick, defineProps, computed } from 'vue';
  48 + import { defHttp } from '/@/utils/http/axios';
  49 + import { useMessage } from '/@/hooks/web/useMessage';
  50 + import moment from 'moment';
  51 + <#include "/common/form/native/vue3NativeImport.ftl">
  52 + import { getValueType } from '/@/utils';
  53 + import { saveOrUpdate } from '../${entityName}.api';
  54 + import { Form } from 'ant-design-vue';
  55 + <#if hasOnlyValidate == true>
  56 + import { duplicateValidate } from '/@/utils/helper/validator'
  57 + </#if>
  58 +
  59 + const props = defineProps({
  60 + disabled: { type: Boolean, default: false },
  61 + });
  62 + const formRef = ref();
  63 + const useForm = Form.useForm;
  64 + const emit = defineEmits(['register', 'ok']);
  65 + const formData = reactive<Record<string, any>>({
  66 +<#list columns as po>
  67 + <#if po.isShow == 'Y'>
  68 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  69 + ${po.fieldName}: undefined,
  70 + <#elseif po.fieldDbType=='Blob'>
  71 + ${po.fieldName}String: '',
  72 + <#else>
  73 + ${po.fieldName}: '',
  74 + </#if>
  75 + </#if>
  76 +</#list>
  77 + });
  78 + const { createMessage } = useMessage();
  79 + const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
  80 + const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
  81 + const confirmLoading = ref<boolean>(false);
  82 + //表单验证
  83 + const validatorRules = {
  84 + <#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
  85 + };
  86 + const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });
  87 +
  88 + /**
  89 + * 新增
  90 + */
  91 + function add() {
  92 + edit({});
  93 + }
  94 +
  95 + /**
  96 + * 编辑
  97 + */
  98 + function edit(record) {
  99 + nextTick(() => {
  100 + resetFields();
  101 + //赋值
  102 + Object.assign(formData, record);
  103 + });
  104 + }
  105 +
  106 + /**
  107 + * 提交数据
  108 + */
  109 + async function submitForm() {
  110 + // 触发表单验证
  111 + await validate();
  112 + confirmLoading.value = true;
  113 + const isUpdate = ref<boolean>(false);
  114 + //时间格式化
  115 + let model = formData;
  116 + if (model.id) {
  117 + isUpdate.value = true;
  118 + }
  119 + //循环数据
  120 + for (let data in model) {
  121 + //如果该数据是数组并且是字符串类型
  122 + if (model[data] instanceof Array) {
  123 + let valueType = getValueType(formRef.value.getProps, data);
  124 + //如果是字符串类型的需要变成以逗号分割的字符串
  125 + if (valueType === 'string') {
  126 + model[data] = model[data].join(',');
  127 + }
  128 + }
  129 + }
  130 + await saveOrUpdate(model, isUpdate.value)
  131 + .then((res) => {
  132 + if (res.success) {
  133 + createMessage.success(res.message);
  134 + emit('ok');
  135 + } else {
  136 + createMessage.warning(res.message);
  137 + }
  138 + })
  139 + .finally(() => {
  140 + confirmLoading.value = false;
  141 + });
  142 + }
  143 +
  144 + <#if need_popup>
  145 + /**
  146 + * popup组件值改变事件
  147 + */
  148 + function setFieldsValue(map) {
  149 + Object.keys(map).map((key) => {
  150 + formData[key] = map[key];
  151 + });
  152 + }
  153 + </#if>
  154 +
  155 + <#if need_category || need_select_tree>
  156 + /**
  157 + * 值改变事件触发
  158 + * @param key
  159 + * @param value
  160 + */
  161 + function handleFormChange(key, value) {
  162 + formData[key] = value;
  163 + }
  164 + </#if>
  165 + <#list columns as po>
  166 + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
  167 + async function ${po.fieldName}Duplicatevalidate(_r, value) {
  168 + return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '')
  169 + }
  170 + </#if>
  171 + </#list>
  172 + defineExpose({
  173 + add,
  174 + edit,
  175 + submitForm,
  176 + });
  177 +</script>
  178 +
  179 +<style lang="less" scoped>
  180 + .antd-modal-form {
  181 + height: 500px !important;
  182 + overflow-y: auto;
  183 + padding: 24px 24px 24px 24px;
  184 + }
  185 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei 0 → 100644
  1 +<template>
  2 + <a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
  3 + <${entityName}Form ref="registerForm" @ok="submitCallback" :disabled="disableSubmit"></${entityName}Form>
  4 + </a-modal>
  5 +</template>
  6 +
  7 +<script lang="ts" setup>
  8 + import { ref, nextTick, defineExpose } from 'vue';
  9 + import ${entityName}Form from './${entityName}Form.vue'
  10 +
  11 + const title = ref<string>('');
  12 + const width = ref<number>(800);
  13 + const visible = ref<boolean>(false);
  14 + const disableSubmit = ref<boolean>(false);
  15 + const registerForm = ref();
  16 + const emit = defineEmits(['register', 'success']);
  17 +
  18 + /**
  19 + * 新增
  20 + */
  21 + function add() {
  22 + title.value = '新增';
  23 + visible.value = true;
  24 + nextTick(() => {
  25 + registerForm.value.add();
  26 + });
  27 + }
  28 +
  29 + /**
  30 + * 编辑
  31 + * @param record
  32 + */
  33 + function edit(record) {
  34 + title.value = disableSubmit.value ? '详情' : '编辑';
  35 + visible.value = true;
  36 + nextTick(() => {
  37 + registerForm.value.edit(record);
  38 + });
  39 + }
  40 +
  41 + /**
  42 + * 确定按钮点击事件
  43 + */
  44 + function handleOk() {
  45 + registerForm.value.submitForm();
  46 + }
  47 +
  48 + /**
  49 + * form保存回调事件
  50 + */
  51 + function submitCallback() {
  52 + handleCancel();
  53 + emit('success');
  54 + }
  55 +
  56 + /**
  57 + * 取消按钮回调事件
  58 + */
  59 + function handleCancel() {
  60 + visible.value = false;
  61 + }
  62 +
  63 + defineExpose({
  64 + add,
  65 + edit,
  66 + disableSubmit,
  67 + });
  68 +</script>
  69 +
  70 +<style>
  71 + /**隐藏样式-modal确定按钮 */
  72 + .jee-hidden {
  73 + display: none !important;
  74 + }
  75 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
... ... @@ -205,17 +205,14 @@ public class ${entityName}Controller {
205 205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
206 206 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
207 207  
208   - //Step.2 获取导出数据
209   - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper);
210   - // 过滤选中数据
  208 + //配置选中数据查询条件
211 209 String selections = request.getParameter("selections");
212   - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>();
213   - if(oConvertUtils.isEmpty(selections)) {
214   - ${entityName?uncap_first}List = queryList;
215   - }else {
  210 + if(oConvertUtils.isNotEmpty(selections)) {
216 211 List<String> selectionList = Arrays.asList(selections.split(","));
217   - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
  212 + queryWrapper.in("id",selectionList);
218 213 }
  214 + //Step.2 获取导出数据
  215 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper);
219 216  
220 217 // Step.3 组装pageList
221 218 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
  1 +<#include "/common/utils.ftl">
1 2 package ${bussiPackage}.${entityPackage}.entity;
2 3  
3 4 import java.io.Serializable;
... ... @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 32 <#-- 生成字典Code -->
32 33 <#assign list_field_dictCode="">
33 34 <#if po.classType='sel_user'>
34   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  35 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
35 36 <#elseif po.classType='sel_depart'>
36   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  37 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
37 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 39 <#if po.dictTable?default("")?trim?length gt 1>
39 40 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
  1 +<#include "/common/utils.ftl">
1 2 <#list subTables as subTab>
2 3 #segment#${subTab.entityName}.java
3 4 package ${bussiPackage}.${entityPackage}.entity;
... ... @@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable {
32 33 <#-- 生成字典Code -->
33 34 <#assign list_field_dictCode="">
34 35 <#if po.classType='sel_user'>
35   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  36 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
36 37 <#elseif po.classType='sel_depart'>
37   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  38 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
38 39 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
39 40 <#if po.dictTable?default("")?trim?length gt 1>
40 41 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei
... ... @@ -48,7 +48,7 @@
48 48 @input="popupCallback"
49 49 <#if po.readonly=='Y'>disabled</#if>/>
50 50 <#elseif po.classType =='sel_depart'>
51   - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/>
  51 + <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> />
52 52 <#elseif po.classType =='switch'>
53 53 <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
54 54 <#elseif po.classType =='pca'>
... ... @@ -58,7 +58,7 @@
58 58 <#elseif po.classType =='password'>
59 59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 60 <#elseif po.classType =='sel_user'>
61   - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  61 + <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>/>
62 62 <#elseif po.classType =='textarea'>
63 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 64 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei
... ... @@ -44,7 +44,7 @@
44 44 :multi="${po.extendParams.popupMulti?c}"
45 45 @input="popupCallback"/>
46 46 <#elseif po.classType =='sel_depart'>
47   - <j-select-depart v-model="model.${po.fieldName}" multi/>
  47 + <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> />
48 48 <#elseif po.classType =='switch'>
49 49 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch>
50 50 <#elseif po.classType =='pca'>
... ... @@ -54,7 +54,7 @@
54 54 <#elseif po.classType =='password'>
55 55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/>
56 56 <#elseif po.classType =='sel_user'>
57   - <j-select-user-by-dep v-model="model.${po.fieldName}"/>
  57 + <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>/>
58 58 <#elseif po.classType =='textarea'>
59 59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/>
60 60 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
  1 +<#include "/common/utils.ftl">
1 2 package ${bussiPackage}.${entityPackage}.entity;
2 3  
3 4 import java.io.Serializable;
... ... @@ -32,9 +33,9 @@ public class ${entityName} implements Serializable {
32 33 <#-- 生成字典Code -->
33 34 <#assign list_field_dictCode="">
34 35 <#if po.classType='sel_user'>
35   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  36 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
36 37 <#elseif po.classType='sel_depart'>
37   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  38 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
38 39 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
39 40 <#if po.dictTable?default("")?trim?length gt 1>
40 41 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei
... ... @@ -56,9 +56,9 @@
56 56 @input="popupCallback"
57 57 <#if po.readonly=='Y'>disabled</#if>/>
58 58 <#elseif po.classType =='sel_depart'>
59   - <j-select-depart v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  59 + <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> />
60 60 <#elseif po.classType =='sel_user'>
61   - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  61 + <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>/>
62 62 <#elseif po.classType =='textarea'>
63 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 64 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei
... ... @@ -8,6 +8,13 @@
8 8 <#assign hasChildrenField = po.fieldName>
9 9 </#if>
10 10 </#list>
  11 +<#assign list_need_pca=false>
  12 +<#-- 开始循环 -->
  13 +<#list columns as po>
  14 +<#if po.classType=='pca'>
  15 +<#assign list_need_pca=true>
  16 +</#if>
  17 +</#list>
11 18 <template>
12 19 <div>
13 20 <!--引用表格-->
... ... @@ -34,8 +41,20 @@
34 41 </template>
35 42 <!--操作栏-->
36 43 <template #action="{ record }">
37   - <TableAction :actions="getTableAction(record)"/>
  44 + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
38 45 </template>
  46 + <!--字段回显插槽-->
  47 + <template #htmlSlot="{text}">
  48 + <div v-html="text"></div>
  49 + </template>
  50 + <!--省市区字段回显插槽-->
  51 + <template #pcaSlot="{text}">
  52 + {{ getAreaTextByCode(text) }}
  53 + </template>
  54 + <template #fileSlot="{text}">
  55 + <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
  56 + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
  57 + </template>
39 58 </BasicTable>
40 59 <!--字典弹窗-->
41 60 <${entityName}Modal @register="registerModal" @success="handleSuccess"/>
... ... @@ -49,9 +68,12 @@
49 68 import {useModal} from '/@/components/Modal';
50 69 import { useListPage } from '/@/hooks/system/useListPage'
51 70 import ${entityName}Modal from './components/${entityName}Modal.vue';
52   - import {columns} from './${entityName}.data';
  71 + import {columns,searchFormSchema} from './${entityName}.data';
  72 + import { downloadFile } from '/@/utils/common/renderUtils';
53 73 import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
54   -
  74 + <#if list_need_pca>
  75 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  76 + </#if>
55 77 const expandedRowKeys = ref([]);
56 78 //字典model
57 79 const [registerModal, {openModal}] = useModal();
... ... @@ -62,6 +84,36 @@
62 84 title: '${tableVo.ftlDescription}',
63 85 columns,
64 86 canResize:false,
  87 + formConfig: {
  88 + labelWidth: 120,
  89 + schemas: searchFormSchema,
  90 + autoSubmitOnEnter:true,
  91 + showAdvancedButton:true,
  92 + fieldMapToNumber: [
  93 + <#list columns as po>
  94 + <#if po.isQuery=='Y'>
  95 + <#if po.queryMode!='single'>
  96 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  97 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
  98 + </#if>
  99 + </#if>
  100 + </#if>
  101 + </#list>
  102 + ],
  103 + fieldMapToTime: [
  104 + <#list columns as po>
  105 + <#if po.isQuery=='Y'>
  106 + <#if po.queryMode!='single'>
  107 + <#if po.classType=='date'>
  108 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
  109 + <#elseif po.classType=='datetime'>
  110 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
  111 + </#if>
  112 + </#if>
  113 + </#if>
  114 + </#list>
  115 + ],
  116 + },
65 117 actionColumn: {
66 118 width: 240,
67 119 },
... ... @@ -120,13 +172,13 @@
120 172 */
121 173 async function batchHandleDelete() {
122 174 const ids = selectedRowKeys.value.filter(item => !item.includes('loading'))
123   - await batchDelete${entityName}({ids: ids}, importSuccess);
  175 + await batchDelete${entityName}({id: ids}, importSuccess);
124 176 }
125 177 /**
126 178 * 导入
127 179 */
128 180 function importSuccess() {
129   - reload() && (expandedRowKeys.value = []);
  181 + (selectedRowKeys.value = []) && reload();
130 182 }
131 183 /**
132 184 * 添加下级
... ... @@ -140,12 +192,16 @@
140 192 /**
141 193 * 成功回调
142 194 */
143   - async function handleSuccess({isUpdate, values, expandedArr}) {
  195 + async function handleSuccess({isUpdate, values, expandedArr, changeParent}) {
144 196 if (isUpdate) {
145   - //编辑回调
146   - updateTableDataRecord(values.id, values);
  197 + if (changeParent) {
  198 + reload();
  199 + } else {
  200 + // 编辑回调
  201 + updateTableDataRecord(values.id, values);
  202 + }
147 203 } else {
148   - if(!values['${pidFieldName}']){
  204 + if(!values['id'] || !values['${pidFieldName}']){
149 205 //新增根节点
150 206 reload();
151 207 }else{
... ... @@ -264,18 +320,28 @@
264 320 onClick: handleEdit.bind(null, record),
265 321 },
266 322 {
267   - label: '删除',
268   - popConfirm: {
269   - title: '确定删除吗?',
270   - confirm: handleDelete.bind(null, record),
271   - },
272   - },
273   - {
274 323 label: '添加下级',
275 324 onClick: handleAddSub.bind(null, {${pidFieldName}: record.id}),
276 325 }
277 326 ]
278 327 }
  328 + /**
  329 + * 下拉操作栏
  330 + */
  331 + function getDropDownAction(record){
  332 + return [
  333 + {
  334 + label: '详情',
  335 + onClick: handleDetail.bind(null, record),
  336 + }, {
  337 + label: '删除',
  338 + popConfirm: {
  339 + title: '确定删除吗?',
  340 + confirm: handleDelete.bind(null, record),
  341 + }
  342 + }
  343 + ]
  344 + }
279 345 </script>
280 346  
281 347 <style scoped>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi
... ... @@ -6,7 +6,6 @@ enum Api {
6 6 save='/${entityPackage}/${entityName?uncap_first}/add',
7 7 edit='/${entityPackage}/${entityName?uncap_first}/edit',
8 8 delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete',
9   - deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
10 9 importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
11 10 exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
12 11 loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot',
... ... @@ -49,7 +48,7 @@ export const batchDelete${entityName} = (params, handleSuccess) =&gt; {
49 48 okText: '确认',
50 49 cancelText: '取消',
51 50 onOk: () => {
52   - return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
  51 + return defHttp.delete({url: Api.delete${entityName}, data: params}, {joinParamsToUrl: true}).then(() => {
53 52 handleSuccess();
54 53 });
55 54 }
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi
  1 +<#include "/common/utils.ftl">
1 2 import {BasicColumn} from '/@/components/Table';
2 3 import {FormSchema} from '/@/components/Table';
3 4 import { rules} from '/@/utils/helper/validator';
... ... @@ -28,7 +29,7 @@ export const columns: BasicColumn[] = [
28 29 slots: { customRender: 'htmlSlot' },
29 30 <#elseif po.classType=='pca'>
30 31 dataIndex: '${po.fieldName}',
31   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  32 + slots: { customRender: 'pcaSlot' },
32 33 <#elseif po.classType=='file'>
33 34 dataIndex: '${po.fieldName}',
34 35 slots: { customRender: 'fileSlot' },
... ... @@ -60,7 +61,7 @@ export const columns: BasicColumn[] = [
60 61 return render.renderCategoryTree(text,'${po.dictField?default("")}')
61 62 },
62 63 <#else>
63   - customRender: (text, record) => (text ? record['${po.dictText}'] : '')
  64 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
64 65 </#if>
65 66 <#else>
66 67 dataIndex: '${po.fieldName}'
... ... @@ -105,9 +106,14 @@ export const searchFormSchema: FormSchema[] = [
105 106 <#elseif po.classType=='sel_depart'>
106 107 component: 'JSelectDept',
107 108 <#elseif po.classType=='list_multi'>
108   - component: 'JMultiSelectTag',//暂无该组件
109   - componentProps:{
110   - dictCode:"query_field_dictCode?default("")"
  109 + component: 'JSelectMultiple',
  110 + componentProps:{
  111 + <#if po.dictTable?default("")?trim?length gt 1>
  112 + dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
  113 + <#elseif po.dictField?default("")?trim?length gt 1>
  114 + dictCode:"${po.dictField}",
  115 + </#if>
  116 + triggerChange: true
111 117 },
112 118 <#elseif po.classType=='cat_tree'>
113 119 component: 'JCategorySelect',
... ... @@ -124,15 +130,22 @@ export const searchFormSchema: FormSchema[] = [
124 130 <#elseif po.classType=='pca'>
125 131 component: 'JAreaLinkage',
126 132 <#elseif po.classType=='popup'>
127   - component: 'JPopup',
128   - componentProps: ({ formActionType }) => {
129   - const {setFieldsValue} = formActionType;
130   - return{
131   - setFieldsValue:setFieldsValue,
132   - code:"${po.dictTable}",
133   - fieldConfig:"${po.dictField}",
134   - multi:${po.extendParams.popupMulti?c},
135   - }
  133 + <#include "/common/form/vue3popup.ftl">
  134 +<#elseif po.classType == 'sel_tree'>
  135 + component: 'JTreeSelect',
  136 + componentProps:{
  137 + <#if po.dictText??>
  138 + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
  139 + dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
  140 + </#if>
  141 + <#if po.dictText?split(',')[1]??>
  142 + pidField:"${po.dictText?split(',')[1]}",
  143 + </#if>
  144 + <#if po.dictText?split(',')[3]??>
  145 + hasChildField:"${po.dictText?split(',')[3]}",
  146 + </#if>
  147 + </#if>
  148 + pidValue:"${po.dictField}",
136 149 },
137 150 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
138 151 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
... ... @@ -160,6 +173,13 @@ export const searchFormSchema: FormSchema[] = [
160 173 componentProps: {
161 174 showTime:true
162 175 },
  176 +<#elseif po.classType == 'time'>
  177 + component: 'TimePicker',
  178 + componentProps:{
  179 + valueFormat: 'HH:mm:ss',
  180 + },
  181 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  182 + component: 'JRangeNumber',
163 183 <#else>
164 184 component: 'Input', //TODO 范围查询
165 185 </#if>
... ... @@ -192,7 +212,7 @@ export const formSchema: FormSchema[] = [
192 212 </#if>
193 213 {
194 214 label: '${po.filedComment}',
195   - field: '${po.fieldName}',
  215 + field: ${autoStringSuffix(po)},
196 216 <#if po.fieldDbName == tableVo.extendParams.pidField>
197 217 component: 'JTreeSelect',
198 218 componentProps: {
... ... @@ -203,24 +223,19 @@ export const formSchema: FormSchema[] = [
203 223 },
204 224 <#elseif po.classType =='date'>
205 225 component: 'DatePicker',
206   - <#elseif po.fieldType =='datetime'>
  226 + <#elseif po.classType =='datetime'>
207 227 component: 'DatePicker',
208 228 componentProps: {
209   - showTime:true
  229 + showTime:true,
  230 + valueFormat: 'YYYY-MM-DD hh:mm:ss'
210 231 },
211   - <#elseif po.fieldType =='time'>
  232 + <#elseif po.classType =='time'>
212 233 component: 'TimePicker',
  234 + componentProps:{
  235 + valueFormat: 'HH:mm:ss',
  236 + },
213 237 <#elseif po.classType =='popup'>
214   - component: 'JPopup',
215   - componentProps: ({ formActionType }) => {
216   - const {setFieldsValue} = formActionType;
217   - return{
218   - setFieldsValue:setFieldsValue,
219   - code:"${po.dictTable}",
220   - fieldConfig:${po.dictField},
221   - multi:${po.extendParams.popupMulti?c},
222   - }
223   - },
  238 + <#include "/common/form/vue3popup.ftl">
224 239 <#elseif po.classType =='sel_depart'>
225 240 component: 'JSelectDept',
226 241 <#elseif po.classType =='switch'>
... ... @@ -242,14 +257,14 @@ export const formSchema: FormSchema[] = [
242 257 labelKey:'realname',
243 258 },
244 259 <#elseif po.classType =='textarea'>
245   - component: 'InputTextArea',//TODO 注意string转换问题
  260 + component: 'InputTextArea',
246 261 <#elseif po.classType=='list' || po.classType=='radio'>
247 262 component: 'JDictSelectTag',
248 263 componentProps:{
249 264 dictCode:"${form_field_dictCode}"
250 265 },
251 266 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
252   - component: 'JMultiSelectTag',//TODO 暂无该组件
  267 + component: 'JSelectMultiple',
253 268 componentProps:{
254 269 dictCode:"${form_field_dictCode}"
255 270 },
... ... @@ -284,7 +299,7 @@ export const formSchema: FormSchema[] = [
284 299 </#if>
285 300 },
286 301 <#elseif po.classType=='umeditor'>
287   - component: 'JCodeEditor', //TODO String后缀暂未添加
  302 + component: 'JEditor',
288 303 <#elseif po.classType == 'sel_tree'>
289 304 component: 'JTreeSelect',
290 305 componentProps:{
... ... @@ -318,16 +333,16 @@ export const formSchema: FormSchema[] = [
318 333 </#if>
319 334 <#-- 唯一校验 -->
320 335 <#if fieldValidType == 'only'>
321   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  336 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
322 337 <#-- 6到16位数字 -->
323 338 <#elseif fieldValidType == 'n6-16'>
324 339 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
325 340 <#-- 6到16位任意字符 -->
326 341 <#elseif fieldValidType == '*6-16'>
327 342 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
328   - <#-- 6到18位字符串 -->
  343 + <#-- 6到18位字 -->
329 344 <#elseif fieldValidType == 's6-18'>
330   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  345 + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
331 346 <#-- 网址 -->
332 347 <#elseif fieldValidType == 'url'>
333 348 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei
  1 +<#include "/common/utils.ftl">
1 2 <#assign pidFieldName = "">
2 3 <#assign hasChildrenField = "">
3 4 <#list originalColumns as po>
... ... @@ -9,7 +10,7 @@
9 10 </#if>
10 11 </#list>
11 12 <template>
12   - <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
  13 + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit">
13 14 <BasicForm @register="registerForm"/>
14 15 </BasicModal>
15 16 </template>
... ... @@ -24,10 +25,13 @@
24 25 const isUpdate = ref(true);
25 26 const expandedRowKeys = ref([]);
26 27 const treeData = ref([]);
  28 + // 当前编辑的数据
  29 + let model:Nullable<Recordable> = null;
27 30 //表单配置
28   - const [registerForm, {resetFields, setFieldsValue, validate, updateSchema}] = useForm({
  31 + const [registerForm, {setProps,resetFields, setFieldsValue, validate, updateSchema}] = useForm({
29 32 schemas: formSchema,
30 33 showActionButtonGroup: false,
  34 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
31 35 labelCol: {
32 36 xs: { span: 24 },
33 37 sm: { span: 4 },
... ... @@ -42,16 +46,21 @@
42 46 //重置表单
43 47 await resetFields();
44 48 expandedRowKeys.value = [];
45   - setModalProps({confirmLoading: false, minHeight: 80});
  49 + setModalProps({confirmLoading: false, minHeight: 80 ,showOkBtn: !!!data?.hideFooter});
46 50 isUpdate.value = !!data?.isUpdate;
47 51 if (data?.record) {
  52 + model = data.record;
48 53 //表单赋值
49 54 await setFieldsValue({
50 55 ...data.record,
51 56 });
  57 + } else {
  58 + model = null;
52 59 }
53 60 //父级节点树信息
54 61 treeData.value = await loadTreeData({'async': false,'pcode':''});
  62 + // 隐藏底部时禁用整个表单
  63 + setProps({ disabled: !!data?.hideFooter })
55 64 });
56 65 //设置标题
57 66 const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
... ... @@ -85,9 +94,25 @@
85 94 //展开的节点信息
86 95 await getExpandKeysByPid(values['${pidFieldName}'],unref(treeData))
87 96 //刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息)
88   - emit('success', {isUpdate: unref(isUpdate), values:{...values},expandedArr: unref(expandedRowKeys).reverse()});
  97 + emit('success', {
  98 + isUpdate: unref(isUpdate),
  99 + values: {...values},
  100 + expandedArr: unref(expandedRowKeys).reverse(),
  101 + // 是否更改了父级节点
  102 + changeParent: model != null && (model['${pidFieldName}'] != values['${pidFieldName}']),
  103 + });
89 104 } finally {
90 105 setModalProps({confirmLoading: false});
91 106 }
92 107 }
93 108 </script>
  109 +<style lang="less" scoped>
  110 + /** 时间和数字输入框样式 */
  111 + :deep(.ant-input-number){
  112 + width: 100%
  113 + }
  114 +
  115 + :deep(.ant-calendar-picker){
  116 + width: 100%
  117 + }
  118 +</style>
94 119 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei 0 → 100644
  1 +<template>
  2 + <div>
  3 +<#assign pidFieldName = "">
  4 +<#assign hasChildrenField = "">
  5 +<#list originalColumns as po>
  6 + <#if po.fieldDbName == tableVo.extendParams.pidField>
  7 + <#assign pidFieldName = po.fieldName>
  8 + </#if>
  9 + <#if po.fieldDbName == tableVo.extendParams.hasChildren>
  10 + <#assign hasChildrenField = po.fieldName>
  11 + </#if>
  12 +</#list>
  13 +<#assign query_field_no=0>
  14 +<#assign need_category = false>
  15 +<#assign need_pca = false>
  16 +<#assign need_search = false>
  17 +<#assign need_dept_user = false>
  18 +<#assign need_switch = false>
  19 +<#assign need_dept = false>
  20 +<#assign need_multi = false>
  21 +<#assign need_popup = false>
  22 +<#assign need_select_tag = false>
  23 +<#assign need_select_tree = false>
  24 +<#assign need_time = false>
  25 +<#assign bpm_flag=false>
  26 +<#assign need_markdown = false>
  27 +<#assign need_upload = false>
  28 +<#assign need_image_upload = false>
  29 +<#assign need_editor = false>
  30 +<#assign need_checkbox = false>
  31 +<#assign query_flag = false>
  32 + <!--查询区域-->
  33 + <div class="jeecg-basic-table-form-container">
  34 + <a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
  35 + <a-row :gutter="24">
  36 +<#-- 开始循环 -->
  37 +<#list columns as po>
  38 +<#if po.fieldDbName=='bpm_status'>
  39 + <#assign bpm_flag=true>
  40 +</#if>
  41 +<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
  42 +<#assign need_category=true>
  43 +</#if>
  44 +<#if po.classType=='pca'>
  45 +<#assign need_pca=true>
  46 +</#if>
  47 +<#if po.classType=='sel_search'>
  48 +<#assign need_search = true>
  49 +</#if>
  50 +<#if po.classType=='sel_user'>
  51 +<#assign need_dept_user = true>
  52 +</#if>
  53 +<#if po.classType=='sel_depart'>
  54 +<#assign need_dept = true>
  55 +</#if>
  56 +<#if po.classType=='switch'>
  57 +<#assign need_switch = true>
  58 +</#if>
  59 +<#if po.classType=='list_multi'>
  60 +<#assign need_multi = true>
  61 +</#if>
  62 +<#if po.classType=='popup'>
  63 +<#assign need_popup = true>
  64 +</#if>
  65 +<#if po.classType=='sel_tree'>
  66 +<#assign need_select_tree = true>
  67 +</#if>
  68 +<#if po.classType=='time'>
  69 +<#assign need_time = true>
  70 +</#if>
  71 + <#include "/common/form/native/vue3NativeSearch.ftl">
  72 +</#list>
  73 +<#if query_field_no gt 2>
  74 + </template>
  75 +</#if>
  76 +<#if query_flag>
  77 + <a-col :xl="6" :lg="7" :md="8" :sm="24">
  78 + <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  79 + <a-col :lg="6">
  80 + <a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
  81 + <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
  82 + <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
  83 + {{ toggleSearchStatus ? '收起' : '展开' }}
  84 + <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
  85 + </a>
  86 + </a-col>
  87 + </span>
  88 + </a-col>
  89 +</#if>
  90 + </a-row>
  91 + </a-form>
  92 + </div>
  93 +<#-- 结束循环 -->
  94 + <!--引用表格-->
  95 + <BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
  96 + <!--插槽:table标题-->
  97 + <template #tableTitle>
  98 + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
  99 + <a-dropdown v-if="selectedRowKeys.length > 0">
  100 + <template #overlay>
  101 + <a-menu>
  102 + <a-menu-item key="1" @click="batchHandleDelete">
  103 + <Icon icon="ant-design:delete-outlined"></Icon>
  104 + 删除
  105 + </a-menu-item>
  106 + </a-menu>
  107 + </template>
  108 + <a-button
  109 + >批量操作
  110 + <Icon icon="ant-design:down-outlined"></Icon>
  111 + </a-button>
  112 + </a-dropdown>
  113 + </template>
  114 + <!--操作栏-->
  115 + <template #action="{ record }">
  116 + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
  117 + </template>
  118 + <!--字段回显插槽-->
  119 + <template #htmlSlot="{ text }">
  120 + <div v-html="text"></div>
  121 + </template>
  122 + <!--省市区字段回显插槽-->
  123 + <template #pcaSlot="{ text }">
  124 + {{ getAreaTextByCode(text) }}
  125 + </template>
  126 + <template #fileSlot="{ text }">
  127 + <span v-if="!text" style="font-size: 12px; font-style: italic">无文件</span>
  128 + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
  129 + </template>
  130 + </BasicTable>
  131 + <!-- 表单区域 -->
  132 + <${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal>
  133 + </div>
  134 +</template>
  135 +
  136 +<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup>
  137 + import { ref, reactive, unref } from 'vue';
  138 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  139 + import { useListPage } from '/@/hooks/system/useListPage';
  140 + import { columns } from './${entityName}.data';
  141 + import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
  142 + import { downloadFile } from '/@/utils/common/renderUtils';
  143 + import ${entityName}Modal from './components/${entityName}Modal.vue'
  144 + <#include "/common/form/native/vue3NativeImport.ftl">
  145 +<#if need_category>
  146 + import { loadCategoryData } from '/@/api/common/api';
  147 + import { getAuthCache, setAuthCache } from '/@/utils/auth';
  148 + import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
  149 +</#if>
  150 +<#if need_pca>
  151 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  152 +</#if>
  153 +
  154 + const expandedRowKeys = ref([]);
  155 + const queryParam = ref<any>({});
  156 + const toggleSearchStatus = ref<boolean>(false);
  157 + const registerModal = ref();
  158 + //注册table数据
  159 + const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
  160 + tableProps: {
  161 + title: '${tableVo.ftlDescription}',
  162 + api: list,
  163 + columns,
  164 + canResize:false,
  165 + useSearchForm: false,
  166 + actionColumn: {
  167 + width: 120,
  168 + fixed: 'right',
  169 + },
  170 + beforeFetch: (params) => {
  171 + return Object.assign(params, queryParam.value);
  172 + },
  173 + },
  174 + exportConfig: {
  175 + name: "${tableVo.ftlDescription}",
  176 + url: getExportUrl,
  177 + },
  178 + importConfig: {
  179 + url: getImportUrl,
  180 + success: success
  181 + },
  182 + });
  183 + const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource},{ rowSelection, selectedRowKeys }] = tableContext
  184 + const labelCol = reactive({
  185 + xs: { span: 24 },
  186 + sm: { span: 7 },
  187 + });
  188 + const wrapperCol = reactive({
  189 + xs: { span: 24 },
  190 + sm: { span: 16 },
  191 + });
  192 +
  193 + /**
  194 + * 新增事件
  195 + */
  196 + function handleAdd() {
  197 + registerModal.value.disableSubmit = false;
  198 + registerModal.value.add();
  199 + }
  200 +
  201 + /**
  202 + * 编辑事件
  203 + */
  204 + async function handleEdit(record) {
  205 + registerModal.value.disableSubmit = false;
  206 + registerModal.value.edit(record);
  207 + }
  208 +
  209 + /**
  210 + * 详情
  211 + */
  212 + async function handleDetail(record) {
  213 + registerModal.value.disableSubmit = true;
  214 + registerModal.value.edit(record);
  215 + }
  216 +
  217 + /**
  218 + * 删除事件
  219 + */
  220 + async function handleDelete(record) {
  221 + await delete${entityName}({ id: record.id }, success);
  222 + }
  223 +
  224 + /**
  225 + * 批量删除事件
  226 + */
  227 + async function batchHandleDelete() {
  228 + const ids = selectedRowKeys.value.filter((item) => !item.includes('loading'));
  229 + await batchDelete${entityName}({ id: ids }, success);
  230 + }
  231 +
  232 + /**
  233 + * 成功回调刷新页面
  234 + */
  235 + function success() {
  236 + (selectedRowKeys.value = []) && reload();
  237 + }
  238 +
  239 + /**
  240 + * 添加下级
  241 + */
  242 + function handleAddSub(record) {
  243 + registerModal.value.disableSubmit = false;
  244 + registerModal.value.add(record);
  245 + }
  246 +
  247 + /**
  248 + * 成功回调
  249 + */
  250 + async function handleSuccess({ isUpdate, values, expandedArr, changeParent }) {
  251 + if (isUpdate) {
  252 + if (changeParent) {
  253 + reload();
  254 + } else {
  255 + // 编辑回调
  256 + updateTableDataRecord(values.id, values);
  257 + }
  258 + } else {
  259 + if (!values['id'] || !values['pid']) {
  260 + //新增根节点
  261 + reload();
  262 + } else {
  263 + //新增子集
  264 + expandedRowKeys.value = [];
  265 + for (let key of unref(expandedArr)) {
  266 + await expandTreeNode(key);
  267 + }
  268 + }
  269 + }
  270 + }
  271 +
  272 + /**
  273 + * 接口请求成功后回调
  274 + */
  275 + function onFetchSuccess(result) {
  276 + getDataByResult(result.items) && loadDataByExpandedRows();
  277 + }
  278 +
  279 + /**
  280 + * 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
  281 + */
  282 + async function loadDataByExpandedRows() {
  283 + if (unref(expandedRowKeys).length > 0) {
  284 + const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',') });
  285 + if (res.success && res.result.records.length > 0) {
  286 + //已展开的数据批量子节点
  287 + let records = res.result.records;
  288 + const listMap = new Map();
  289 + for (let item of records) {
  290 + let pid = item['${pidFieldName}'];
  291 + if (unref(expandedRowKeys).includes(pid)) {
  292 + let mapList = listMap.get(pid);
  293 + if (mapList == null) {
  294 + mapList = [];
  295 + }
  296 + mapList.push(item);
  297 + listMap.set(pid, mapList);
  298 + }
  299 + }
  300 + let childrenMap = listMap;
  301 + let fn = (list) => {
  302 + if (list) {
  303 + list.forEach((data) => {
  304 + if (unref(expandedRowKeys).includes(data.id)) {
  305 + data.children = getDataByResult(childrenMap.get(data.id));
  306 + fn(data.children);
  307 + }
  308 + });
  309 + }
  310 + };
  311 + fn(getDataSource());
  312 + }
  313 + }
  314 + }
  315 +
  316 + /**
  317 + * 处理数据集
  318 + */
  319 + function getDataByResult(result) {
  320 + if (result && result.length > 0) {
  321 + return result.map((item) => {
  322 + //判断是否标记了带有子节点
  323 + if (item['hasChild'] == '1') {
  324 + let loadChild = { id: item.id + '_loadChild', name: 'loading...', isLoading: true };
  325 + item.children = [loadChild];
  326 + }
  327 + return item;
  328 + });
  329 + }
  330 + }
  331 +
  332 + /**
  333 + *树节点展开合并
  334 + */
  335 + async function handleExpand(expanded, record) {
  336 + // 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
  337 + if (expanded) {
  338 + expandedRowKeys.value.push(record.id);
  339 + if (record.children.length > 0 && !!record.children[0].isLoading) {
  340 + let result = await getChildList({ ${pidFieldName}: record.id});
  341 + result = result.records ? result.records : result;
  342 + if (result && result.length > 0) {
  343 + record.children = getDataByResult(result);
  344 + } else {
  345 + record.children = null;
  346 + record.hasChild = '0';
  347 + }
  348 + }
  349 + } else {
  350 + let keyIndex = expandedRowKeys.value.indexOf(record.id);
  351 + if (keyIndex >= 0) {
  352 + expandedRowKeys.value.splice(keyIndex, 1);
  353 + }
  354 + }
  355 + }
  356 +
  357 + /**
  358 + * 操作表格后处理树节点展开合并
  359 + */
  360 + async function expandTreeNode(key) {
  361 + let record = findTableDataRecord(key);
  362 + expandedRowKeys.value.push(key);
  363 + let result = await getChildList({ ${pidFieldName}: key });
  364 + if (result && result.length > 0) {
  365 + record.children = getDataByResult(result);
  366 + } else {
  367 + record.children = null;
  368 + record.hasChild = '0';
  369 + }
  370 + updateTableDataRecord(key, record);
  371 + }
  372 +
  373 + /**
  374 + * 操作栏
  375 + */
  376 + function getTableAction(record) {
  377 + return [
  378 + {
  379 + label: '编辑',
  380 + onClick: handleEdit.bind(null, record),
  381 + }
  382 + ];
  383 + }
  384 +
  385 + /**
  386 + * 下拉操作栏
  387 + */
  388 + function getDropDownAction(record) {
  389 + return [
  390 + {
  391 + label: '详情',
  392 + onClick: handleDetail.bind(null, record),
  393 + },
  394 + {
  395 + label: '添加下级',
  396 + onClick: handleAddSub.bind(null, { pid: record.id }),
  397 + },
  398 + {
  399 + label: '删除',
  400 + popConfirm: {
  401 + title: '确定删除吗?',
  402 + confirm: handleDelete.bind(null, record),
  403 + },
  404 + },
  405 + ];
  406 + }
  407 +
  408 + /**
  409 + * 查询
  410 + */
  411 + function searchQuery() {
  412 + reload();
  413 + }
  414 +
  415 + /**
  416 + * 重置
  417 + */
  418 + function searchReset() {
  419 + queryParam.value = {};
  420 + selectedRowKeys.value = [];
  421 + //刷新数据
  422 + reload();
  423 + }
  424 +
  425 + <#if need_popup>
  426 + /**
  427 + * popup组件值改变事件
  428 + */
  429 + function setFieldsValue(map) {
  430 + Object.keys(map).map((key) => {
  431 + queryParam.value[key] = map[key];
  432 + });
  433 + }
  434 + </#if>
  435 +
  436 + <#if need_pca>
  437 + /**
  438 + * 省市区点击事件
  439 + * @param key
  440 + * @param value
  441 + */
  442 + function handleAreaChange(key, value) {
  443 + queryParam.value[key] = value.join(',');
  444 + }
  445 + </#if>
  446 +
  447 + <#if need_category>
  448 + /**
  449 + * form点击事件
  450 + * @param value
  451 + */
  452 + function handleFormChange(key, value) {
  453 + queryParam.value[key] = value;
  454 + }
  455 +
  456 + /**
  457 + * 初始化字典配置
  458 + */
  459 + function initDictConfig() {
  460 + <#list columns as po>
  461 + <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
  462 + <#if po.classType=='cat_tree' && need_category==true>
  463 + loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
  464 + if (res) {
  465 + let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
  466 + if(!allDictDate['${po.dictField?default("")}']){
  467 + Object.assign(allDictDate,{'${po.dictField?default("")}':res})
  468 + }
  469 + setAuthCache(DB_DICT_DATA_KEY,allDictDate)
  470 + }
  471 + });
  472 + </#if>
  473 + </#if>
  474 + </#list>
  475 + }
  476 + initDictConfig();
  477 + </#if>
  478 +</script>
  479 +
  480 +<style lang="less" scoped>
  481 + .jeecg-basic-table-form-container {
  482 + .table-page-search-submitButtons {
  483 + display: block;
  484 + margin-bottom: 24px;
  485 + white-space: nowrap;
  486 + }
  487 + .query-group-cust{
  488 + width: calc(50% - 15px);
  489 + min-width: 100px !important;
  490 + }
  491 + .query-group-split-cust{
  492 + width: 30px;
  493 + display: inline-block;
  494 + text-align: center
  495 + }
  496 + }
  497 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi 0 → 100644
  1 +import { defHttp } from "/@/utils/http/axios";
  2 +import { Modal } from 'ant-design-vue';
  3 +
  4 +enum Api {
  5 + list = '/${entityPackage}/${entityName?uncap_first}/rootList',
  6 + save='/${entityPackage}/${entityName?uncap_first}/add',
  7 + edit='/${entityPackage}/${entityName?uncap_first}/edit',
  8 + delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete',
  9 + importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
  10 + exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
  11 + loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot',
  12 + getChildList = '/${entityPackage}/${entityName?uncap_first}/childList',
  13 + getChildListBatch = '/${entityPackage}/${entityName?uncap_first}/getChildListBatch',
  14 +}
  15 +
  16 +/**
  17 + * 导出api
  18 + * @param params
  19 + */
  20 +export const getExportUrl = Api.exportXls;
  21 +
  22 +/**
  23 + * 导入api
  24 + * @param params
  25 + */
  26 +export const getImportUrl = Api.importExcel;
  27 +
  28 +/**
  29 + * 列表接口
  30 + * @param params
  31 + */
  32 +export const list = (params) => defHttp.get({ url: Api.list, params });
  33 +
  34 +/**
  35 + * 删除
  36 + * @param params
  37 + * @param handleSuccess
  38 + */
  39 +export const delete${entityName} = (params,handleSuccess) => {
  40 + return defHttp.delete({ url: Api.delete${entityName}, params }, { joinParamsToUrl: true }).then(() => {
  41 + handleSuccess();
  42 + });
  43 +}
  44 +
  45 +/**
  46 + * 批量删除
  47 + * @param params
  48 + * @param handleSuccess
  49 + */
  50 +export const batchDelete${entityName} = (params, handleSuccess) => {
  51 + Modal.confirm({
  52 + title: '确认删除',
  53 + content: '是否删除选中数据',
  54 + okText: '确认',
  55 + cancelText: '取消',
  56 + onOk: () => {
  57 + return defHttp.delete({ url: Api.delete${entityName}, data: params }, { joinParamsToUrl: true }).then(() => {
  58 + handleSuccess();
  59 + });
  60 + }
  61 + });
  62 +}
  63 +
  64 +/**
  65 + * 保存或者更新
  66 + * @param params
  67 + * @param isUpdate
  68 + */
  69 +export const saveOrUpdateDict = (params, isUpdate) => {
  70 + let url = isUpdate ? Api.edit : Api.save;
  71 + return defHttp.post({ url: url, params },{ isTransformResponse:false });
  72 +}
  73 +
  74 +/**
  75 + * 查询全部树形节点数据
  76 + * @param params
  77 + */
  78 +export const loadTreeData = (params) => defHttp.get({ url: Api.loadTreeData,params });
  79 +
  80 +/**
  81 + * 查询子节点数据
  82 + * @param params
  83 + */
  84 +export const getChildList = (params) => defHttp.get({ url: Api.getChildList, params });
  85 +
  86 +/**
  87 + * 批量查询子节点数据
  88 + * @param params
  89 + */
  90 +export const getChildListBatch = (params) => defHttp.get({ url: Api.getChildListBatch, params },{ isTransformResponse:false });
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi 0 → 100644
  1 +<#include "/common/utils.ftl">
  2 +import {BasicColumn} from '/@/components/Table';
  3 +import {FormSchema} from '/@/components/Table';
  4 +import { rules} from '/@/utils/helper/validator';
  5 +import { render } from '/@/utils/common/renderUtils';
  6 +//列表数据
  7 +export const columns: BasicColumn[] = [
  8 + <#list columns as po>
  9 + <#if po.isShowList =='Y' && po.fieldName !='id'>
  10 + {
  11 + title: '${po.filedComment}',
  12 + <#if po.fieldDbName == tableVo.extendParams.textField>
  13 + align: 'left',
  14 + <#else>
  15 + align: 'center',
  16 + </#if>
  17 + <#if po.sort=='Y'>
  18 + sorter: true,
  19 + </#if>
  20 + <#if po.classType=='date'>
  21 + dataIndex: '${po.fieldName}',
  22 + customRender:({text}) =>{
  23 + return !text?"":(text.length>10?text.substr(0,10):text);
  24 + },
  25 + <#elseif po.fieldDbType=='Blob'>
  26 + dataIndex: '${po.fieldName}String'
  27 + <#elseif po.classType=='umeditor'>
  28 + dataIndex: '${po.fieldName}',
  29 + slots: { customRender: 'htmlSlot' },
  30 + <#elseif po.classType=='pca'>
  31 + dataIndex: '${po.fieldName}',
  32 + slots: { customRender: 'pcaSlot' },
  33 + <#elseif po.classType=='file'>
  34 + dataIndex: '${po.fieldName}',
  35 + slots: { customRender: 'fileSlot' },
  36 + <#elseif po.classType=='image'>
  37 + dataIndex: '${po.fieldName}',
  38 + customRender: render.renderImage,
  39 + <#elseif po.classType=='switch'>
  40 + dataIndex: '${po.fieldName}',
  41 +<#assign switch_extend_arr=['Y','N']>
  42 +<#if po.dictField?default("")?contains("[")>
  43 +<#assign switch_extend_arr=po.dictField?eval>
  44 +</#if>
  45 +<#list switch_extend_arr as a>
  46 +<#if a_index == 0>
  47 +<#assign switch_extend_arr1=a>
  48 +<#else>
  49 +<#assign switch_extend_arr2=a>
  50 +</#if>
  51 +</#list>
  52 + customRender:({text}) => {
  53 + return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
  54 + },
  55 + <#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'>
  56 + dataIndex: '${po.fieldName}_dictText'
  57 + <#elseif po.classType=='cat_tree'>
  58 + dataIndex: '${po.fieldName}',
  59 + <#if po.dictText?default("")?trim?length == 0>
  60 + customRender:({text}) => {
  61 + return render.renderCategoryTree(text,'${po.dictField?default("")}');
  62 + },
  63 + <#else>
  64 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '');
  65 + </#if>
  66 + <#else>
  67 + dataIndex: '${po.fieldName}'
  68 + </#if>
  69 + },
  70 + </#if>
  71 + </#list>
  72 +];
  73 +
  74 +//查询数据
  75 +export const searchFormSchema: FormSchema[] = [
  76 +<#-- 开始循环 -->
  77 +<#list columns as po>
  78 +<#if po.fieldDbName=='bpm_status'>
  79 + <#assign bpm_flag=true>
  80 +</#if>
  81 +<#if po.isQuery=='Y'>
  82 +<#assign query_flag=true>
  83 + <#assign query_field_dictCode="">
  84 + <#if po.dictTable?default("")?trim?length gt 1>
  85 + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  86 + <#elseif po.dictField?default("")?trim?length gt 1>
  87 + <#assign query_field_dictCode="${po.dictField}">
  88 + </#if>
  89 +<#if po.queryMode=='single'>
  90 + {
  91 + label: "${po.filedComment}",
  92 + field: "${po.fieldName}",
  93 +<#if po.classType=='sel_search'>
  94 + component: 'JSearchSelect',
  95 + componentProps: {
  96 + dict:"${po.dictTable},${po.dictText},${po.dictField}"
  97 + },
  98 +<#elseif po.classType=='sel_user'>
  99 + component: 'JSelectUserByDept',
  100 +<#elseif po.classType=='switch'>
  101 + component: 'JSwitch',
  102 + componentProps: {
  103 + <#if po.dictField != 'is_open'>
  104 + options: '${po.dictField}',
  105 + </#if>
  106 + },
  107 + <#elseif po.classType=='sel_depart'>
  108 + component: 'JSelectDept',
  109 + <#elseif po.classType=='list_multi'>
  110 + component: 'JSelectMultiple',
  111 + componentProps: {
  112 + <#if po.dictTable?default("")?trim?length gt 1>
  113 + options: "${po.dictField}",
  114 + dictCode: "${po.dictTable},${po.dictText},${po.dictField}",
  115 + <#elseif po.dictField?default("")?trim?length gt 1>
  116 + dictCode: "${po.dictField}",
  117 + </#if>
  118 + triggerChange: true
  119 + },
  120 + <#elseif po.classType=='cat_tree'>
  121 + component: 'JCategorySelect',
  122 + componentProps:{
  123 + pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
  124 + },
  125 +<#elseif po.classType=='date'>
  126 + component: 'DatePicker',
  127 +<#elseif po.classType=='datetime'>
  128 + component: 'DatePicker',
  129 + componentProps: {
  130 + showTime: true
  131 + },
  132 +<#elseif po.classType=='pca'>
  133 + component: 'JAreaLinkage',
  134 +<#elseif po.classType=='popup'>
  135 + <#include "/common/form/vue3popup.ftl">
  136 +<#elseif po.classType == 'sel_tree'>
  137 + component: 'JTreeSelect',
  138 + componentProps: {
  139 + <#if po.dictText??>
  140 + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
  141 + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
  142 + </#if>
  143 + <#if po.dictText?split(',')[1]??>
  144 + pidField: "${po.dictText?split(',')[1]}",
  145 + </#if>
  146 + <#if po.dictText?split(',')[3]??>
  147 + hasChildField: "${po.dictText?split(',')[3]}",
  148 + </#if>
  149 + </#if>
  150 + pidValue: "${po.dictField}",
  151 + },
  152 +<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
  153 +<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
  154 + component: 'JDictSelectTag',
  155 + componentProps:{
  156 + <#if po.dictTable?default("")?trim?length gt 1>
  157 + dictCode: "${po.dictTable},${po.dictText},${po.dictField}"
  158 + <#elseif po.dictField?default("")?trim?length gt 1>
  159 + dictCode: "${po.dictField}"
  160 + </#if>
  161 + },
  162 +<#else>
  163 + component: 'Input',
  164 +</#if>
  165 + colProps: {span: 6},
  166 + },
  167 +<#else>
  168 + {
  169 + label: "${po.filedComment}",
  170 + field: "${po.fieldName}",
  171 +<#if po.classType=='date'>
  172 + component: 'RangePicker',
  173 +<#elseif po.classType=='datetime'>
  174 + component: 'RangePicker',
  175 + componentProps: {
  176 + showTime: true
  177 + },
  178 +<#elseif po.classType == 'time'>
  179 + component: 'TimePicker',
  180 + componentProps:{
  181 + valueFormat: 'HH:mm:ss',
  182 + },
  183 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  184 + component: 'JRangeNumber',
  185 +<#else>
  186 + component: 'Input', //TODO 范围查询
  187 +</#if>
  188 + colProps: {span: 6},
  189 + },
  190 +</#if>
  191 +</#if>
  192 +</#list>
  193 +<#-- 结束循环 -->
  194 +];
  195 +
  196 +//表单数据
  197 +export const formSchema: FormSchema[] = [
  198 +<#assign form_cat_tree = false>
  199 +<#assign form_cat_back = "">
  200 +<#assign bpm_flag=false>
  201 +<#assign id_exists = false>
  202 +<#list columns as po><#rt/>
  203 +<#if po.fieldDbName=='bpm_status'>
  204 + <#assign bpm_flag=true>
  205 +</#if>
  206 +<#if po.fieldDbName == 'id'>
  207 + <#assign id_exists = true>
  208 +</#if>
  209 +<#if po.isShow =='Y'>
  210 +<#assign form_field_dictCode="">
  211 + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
  212 + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
  213 + <#elseif po.dictField?default("")?trim?length gt 1>
  214 + <#assign form_field_dictCode="${po.dictField}">
  215 + </#if>
  216 + {
  217 + label: '${po.filedComment}',
  218 + field: ${autoStringSuffix(po)},
  219 + <#if po.fieldDbName == tableVo.extendParams.pidField>
  220 + component: 'JTreeSelect',
  221 + componentProps: {
  222 + dict: "${tableVo.tableName},${tableVo.extendParams.textField},id",
  223 + pidField: "${tableVo.extendParams.pidField}",
  224 + pidValue: "0",
  225 + hasChildField: "${tableVo.extendParams.hasChildren}",
  226 + },
  227 + <#elseif po.classType =='date'>
  228 + component: 'DatePicker',
  229 + <#elseif po.classType =='datetime'>
  230 + component: 'DatePicker',
  231 + componentProps: {
  232 + showTime:true,
  233 + valueFormat: 'YYYY-MM-DD hh:mm:ss'
  234 + },
  235 + <#elseif po.classType =='time'>
  236 + component: 'TimePicker',
  237 + componentProps:{
  238 + valueFormat: 'HH:mm:ss',
  239 + },
  240 + <#elseif po.classType =='popup'>
  241 + <#include "/common/form/vue3popup.ftl">
  242 + <#elseif po.classType =='sel_depart'>
  243 + component: 'JSelectDept',
  244 + <#elseif po.classType =='switch'>
  245 + component: 'JSwitch',
  246 + componentProps:{
  247 + <#if po.dictField != 'is_open'>
  248 + options:${po.dictField}
  249 + </#if>
  250 + },
  251 + <#elseif po.classType =='pca'>
  252 + component: 'JAreaLinkage',
  253 + <#elseif po.classType =='markdown'>
  254 + component: 'JMarkdownEditor',//注意string转换问题
  255 + <#elseif po.classType =='password'>
  256 + component: 'InputPassword',
  257 + <#elseif po.classType =='sel_user'>
  258 + component: 'JSelectUserByDept',
  259 + componentProps:{
  260 + labelKey: 'realname',
  261 + },
  262 + <#elseif po.classType =='textarea'>
  263 + component: 'InputTextArea',
  264 + <#elseif po.classType=='list' || po.classType=='radio'>
  265 + component: 'JDictSelectTag',
  266 + componentProps:{
  267 + dictCode: "${form_field_dictCode}"
  268 + },
  269 + <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
  270 + component: 'JSelectMultiple',
  271 + componentProps:{
  272 + dictCode: "${form_field_dictCode}"
  273 + },
  274 + <#elseif po.classType=='sel_search'>
  275 + component: 'JSearchSelect',
  276 + componentProps:{
  277 + dict: "${form_field_dictCode}"
  278 + },
  279 +<#elseif po.classType=='cat_tree'>
  280 + <#assign form_cat_tree = true>
  281 + component: 'JCategorySelect',
  282 + componentProps:{
  283 + pcode: "${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
  284 + },
  285 + <#if po.dictText?default("")?trim?length gt 1>
  286 + <#assign form_cat_back = "${po.dictText}">
  287 + </#if>
  288 + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  289 + component: 'InputNumber',
  290 + <#elseif po.classType=='file'>
  291 + component: 'JUpload',
  292 + componentProps:{
  293 + <#if po.uploadnum??>
  294 + maxCount: ${po.uploadnum}
  295 + </#if>
  296 + },
  297 + <#elseif po.classType=='image'>
  298 + component: 'JImageUpload',
  299 + componentProps:{
  300 + <#if po.uploadnum??>
  301 + fileMax: ${po.uploadnum}
  302 + </#if>
  303 + },
  304 + <#elseif po.classType=='umeditor'>
  305 + component: 'JEditor',
  306 + <#elseif po.classType == 'sel_tree'>
  307 + component: 'JTreeSelect',
  308 + componentProps:{
  309 + <#if po.dictText??>
  310 + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
  311 + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
  312 + </#if>
  313 + <#if po.dictText?split(',')[1]??>
  314 + pidField: "${po.dictText?split(',')[1]}",
  315 + </#if>
  316 + <#if po.dictText?split(',')[3]??>
  317 + hasChildField: "${po.dictText?split(',')[3]}",
  318 + </#if>
  319 + </#if>
  320 + pidValue: "${po.dictField}",
  321 + },
  322 + <#else>
  323 + component: 'Input',
  324 + </#if>
  325 + <#include "/common/utils.ftl">
  326 + <#if po.isShow == 'Y' && poHasCheck(po)>
  327 + dynamicRules: ({ model, schema }) => {
  328 + <#if po.fieldName != 'id'>
  329 + <#assign fieldValidType = po.fieldValidType!''>
  330 + return [
  331 + <#-- 非空校验 -->
  332 + <#if po.nullable == 'N' || fieldValidType == '*'>
  333 + { required: true, message: '请输入${po.filedComment}!' },
  334 + <#elseif fieldValidType!=''>
  335 + { required: false },
  336 + </#if>
  337 + <#-- 唯一校验 -->
  338 + <#if fieldValidType == 'only'>
  339 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
  340 + <#-- 6到16位数字 -->
  341 + <#elseif fieldValidType == 'n6-16'>
  342 + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!' },
  343 + <#-- 6到16位任意字符 -->
  344 + <#elseif fieldValidType == '*6-16'>
  345 + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!' },
  346 + <#-- 6到18位字母 -->
  347 + <#elseif fieldValidType == 's6-18'>
  348 + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!' },
  349 + <#-- 网址 -->
  350 + <#elseif fieldValidType == 'url'>
  351 + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!' },
  352 + <#-- 电子邮件 -->
  353 + <#elseif fieldValidType == 'e'>
  354 + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件! },
  355 + <#-- 手机号码 -->
  356 + <#elseif fieldValidType == 'm'>
  357 + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!' },
  358 + <#-- 邮政编码 -->
  359 + <#elseif fieldValidType == 'p'>
  360 + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!' },
  361 + <#-- 字母 -->
  362 + <#elseif fieldValidType == 's'>
  363 + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!' },
  364 + <#-- 数字 -->
  365 + <#elseif fieldValidType == 'n'>
  366 + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!' },
  367 + <#-- 整数 -->
  368 + <#elseif fieldValidType == 'z'>
  369 + { pattern: /^-?\d+$/, message: '请输入整数!' },
  370 + <#-- 金额 -->
  371 + <#elseif fieldValidType == 'money'>
  372 + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!' },
  373 + <#-- 正则校验 -->
  374 + <#elseif fieldValidType != '' && fieldValidType != '*'>
  375 + { pattern: '${fieldValidType}', message: '不符合校验规则!' },
  376 + <#-- 无校验 -->
  377 + <#else>
  378 + <#t>
  379 + </#if>
  380 + ];
  381 + </#if>
  382 + },
  383 + </#if>
  384 + <#if po.readonly=='Y'>
  385 + dynamicDisabled: true
  386 + </#if>
  387 + },
  388 +</#if>
  389 +</#list>
  390 +<#if id_exists == false>
  391 + // TODO 主键隐藏字段,目前写死为ID
  392 + {
  393 + label: '',
  394 + field: 'id',
  395 + component: 'Input',
  396 + show: false,
  397 + },
  398 +</#if>
  399 +];
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei 0 → 100644
  1 +<#include "/common/utils.ftl">
  2 +<template>
  3 + <a-spin :spinning="confirmLoading">
  4 + <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
  5 + <a-row>
  6 +<#assign need_category = false>
  7 +<#assign bpm_flag=false>
  8 +<#assign need_pca = false>
  9 +<#assign need_search = false>
  10 +<#assign need_dept_user = false>
  11 +<#assign need_switch = false>
  12 +<#assign need_dept = false>
  13 +<#assign need_multi = false>
  14 +<#assign need_popup = false>
  15 +<#assign need_select_tag = false>
  16 +<#assign need_select_tree = false>
  17 +<#assign need_time = false>
  18 +<#assign need_markdown = false>
  19 +<#assign need_upload = false>
  20 +<#assign need_image_upload = false>
  21 +<#assign need_editor = false>
  22 +<#assign need_checkbox = false>
  23 +<#assign pidFieldName = "">
  24 +<#assign hasOnlyValidate = false>
  25 +<#assign form_span = 24>
  26 +<#if tableVo.fieldRowNum==2>
  27 +<#assign form_span = 12>
  28 +<#elseif tableVo.fieldRowNum==3>
  29 +<#assign form_span = 8>
  30 +<#elseif tableVo.fieldRowNum==4>
  31 +<#assign form_span = 6>
  32 +</#if>
  33 +<#list columns as po>
  34 +<#if po.fieldDbName=='bpm_status'>
  35 + <#assign bpm_flag=true>
  36 +</#if>
  37 +<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
  38 + <#assign hasOnlyValidate = true>
  39 +</#if>
  40 + <#if po.fieldDbName == tableVo.extendParams.pidField>
  41 + <#assign pidFieldName = po.fieldName>
  42 + <a-col :span="${form_span}">
  43 + <a-form-item label="父级节点" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
  44 + <j-tree-select
  45 + placeholder="请选择${po.filedComment}"
  46 + v-model:value="formData.${po.fieldName}"
  47 + dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
  48 + pidField="${tableVo.extendParams.pidField}"
  49 + pidValue="0"
  50 + hasChildField="${tableVo.extendParams.hasChildren}"
  51 + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>>
  52 + </j-tree-select>
  53 + </a-form-item>
  54 + </a-col>
  55 + </#if>
  56 + <#include "/common/form/native/vue3NativeForm.ftl">
  57 +</#list>
  58 + </a-row>
  59 + </a-form>
  60 + </a-spin>
  61 +</template>
  62 +
  63 +<script lang="ts" setup>
  64 + import { ref, reactive, defineExpose, nextTick, unref, defineProps, computed } from 'vue';
  65 + import { defHttp } from '/@/utils/http/axios';
  66 + import { useMessage } from '/@/hooks/web/useMessage';
  67 + import moment from 'moment';
  68 + <#include "/common/form/native/vue3NativeImport.ftl">
  69 + import { getValueType } from '/@/utils';
  70 + import { validateDuplicateValue } from '/@/utils/helper/validator';
  71 + import {loadTreeData, saveOrUpdateDict} from '../${entityName}.api';
  72 + import { Form } from 'ant-design-vue';
  73 + <#if hasOnlyValidate == true>
  74 + import { duplicateValidate } from '/@/utils/helper/validator'
  75 + </#if>
  76 +
  77 + const useForm = Form.useForm;
  78 + const formRef = ref();
  79 + const isUpdate = ref(true);
  80 + const expandedRowKeys = ref([]);
  81 + const treeData = ref([]);
  82 + const pidField = ref<string>('pid');
  83 + const emit = defineEmits(['register', 'ok']);
  84 + let model: Nullable<Recordable> = null;
  85 + const formData = reactive<Record<string, any>>({
  86 +<#list columns as po>
  87 + <#if po.isShow == 'Y'>
  88 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  89 + ${po.fieldName}: undefined,
  90 + <#elseif po.fieldDbType=='Blob'>
  91 + ${po.fieldName}String: '',
  92 + <#else>
  93 + ${po.fieldName}: '',
  94 + </#if>
  95 + </#if>
  96 +</#list>
  97 + });
  98 + const { createMessage } = useMessage();
  99 + const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
  100 + const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
  101 + const confirmLoading = ref<boolean>(false);
  102 + //表单验证
  103 + const validatorRules = {
  104 + <#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
  105 + };
  106 + const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });
  107 + const props = defineProps({
  108 + disabled: { type: Boolean, default: false },
  109 + });
  110 +
  111 + /**
  112 + * 新增
  113 + */
  114 + function add(obj = {}) {
  115 + edit(obj);
  116 + }
  117 +
  118 + /**
  119 + * 编辑
  120 + */
  121 + function edit(record) {
  122 + nextTick(async () => {
  123 + resetFields();
  124 + expandedRowKeys.value = [];
  125 + treeData.value = await loadTreeData({ async: false, pcode: '' });
  126 + //赋值
  127 + Object.assign(formData, record);
  128 + });
  129 + }
  130 +
  131 + /**
  132 + * 根据pid获取展开的节点
  133 + * @param pid
  134 + * @param arr
  135 + */
  136 + function getExpandKeysByPid(pid, arr) {
  137 + if (pid && arr && arr.length > 0) {
  138 + for (let i = 0; i < arr.length; i++) {
  139 + if (arr[i].key == pid && unref(expandedRowKeys).indexOf(pid) < 0) {
  140 + expandedRowKeys.value.push(arr[i].key);
  141 + getExpandKeysByPid(arr[i]['parentId'], unref(treeData));
  142 + } else {
  143 + getExpandKeysByPid(pid, arr[i].children);
  144 + }
  145 + }
  146 + }
  147 + }
  148 +
  149 + /**
  150 + * 提交数据
  151 + */
  152 + async function submitForm() {
  153 + // 触发表单验证
  154 + await validate();
  155 + confirmLoading.value = true;
  156 + const isUpdate = ref<boolean>(false);
  157 + //时间格式化
  158 + if (formData.id) {
  159 + isUpdate.value = true;
  160 + }
  161 + //循环数据
  162 + for (let data in formData) {
  163 + //如果该数据是数组并且是字符串类型
  164 + if (formData[data] instanceof Array) {
  165 + let valueType = getValueType(formRef.value.getProps, data);
  166 + //如果是字符串类型的需要变成以逗号分割的字符串
  167 + if (valueType === 'string') {
  168 + formData[data] = formData[data].join(',');
  169 + }
  170 + }
  171 + }
  172 + await saveOrUpdateDict(formData, isUpdate.value)
  173 + .then(async (res) => {
  174 + if (res.success) {
  175 + await getExpandKeysByPid(formData['${pidFieldName}'], unref(treeData));
  176 + emit('ok', {
  177 + isUpdate: unref(isUpdate),
  178 + values: { ...formData },
  179 + expandedArr: unref(expandedRowKeys).reverse(),
  180 + // 是否更改了父级节点
  181 + changeParent: model != null && model['${pidFieldName}'] != formData['${pidFieldName}'],
  182 + });
  183 + createMessage.success(res.message);
  184 + } else {
  185 + createMessage.warning(res.message);
  186 + }
  187 + })
  188 + .finally(() => {
  189 + confirmLoading.value = false;
  190 + });
  191 + }
  192 +
  193 + <#if need_popup>
  194 + /**
  195 + * popup组件值改变事件
  196 + */
  197 + function setFieldsValue(map) {
  198 + Object.keys(map).map((key) => {
  199 + formData[key] = map[key];
  200 + });
  201 + }
  202 + </#if>
  203 +
  204 + <#if need_category || need_select_tree>
  205 + /**
  206 + * 值改变事件触发
  207 + * @param key
  208 + * @param value
  209 + */
  210 + function handleFormChange(key, value) {
  211 + formData[key] = value;
  212 + }
  213 + </#if>
  214 +
  215 + <#list columns as po>
  216 + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
  217 + async function ${po.fieldName}Duplicatevalidate(_r, value) {
  218 + return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '')
  219 + }
  220 + </#if>
  221 + </#list>
  222 + defineExpose({
  223 + add,
  224 + edit,
  225 + submitForm,
  226 + });
  227 +</script>
  228 +
  229 +<style lang="less" scoped>
  230 + .antd-modal-form {
  231 + height: 500px !important;
  232 + overflow-y: auto;
  233 + padding: 24px 24px 24px 24px;
  234 + }
  235 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei 0 → 100644
  1 +<template>
  2 + <a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
  3 + <${entityName}Form ref="registerForm" @ok="submitCallback" :disabled="disableSubmit"></${entityName}Form>
  4 + </a-modal>
  5 +</template>
  6 +
  7 +<script lang="ts" setup>
  8 + import { ref, nextTick, defineExpose } from 'vue';
  9 + import ${entityName}Form from './${entityName}Form.vue'
  10 +
  11 + const title = ref<string>('');
  12 + const width = ref<number>(800);
  13 + const visible = ref<boolean>(false);
  14 + const disableSubmit = ref<boolean>(false);
  15 + const registerForm = ref();
  16 + const emit = defineEmits(['register', 'success']);
  17 +
  18 + /**
  19 + * 新增
  20 + */
  21 + function add(obj={}) {
  22 + title.value = '新增';
  23 + visible.value = true;
  24 + nextTick(() => {
  25 + registerForm.value.add(obj);
  26 + });
  27 + }
  28 +
  29 + /**
  30 + * 编辑
  31 + * @param record
  32 + */
  33 + function edit(record) {
  34 + title.value = disableSubmit.value ? '详情' : '编辑';
  35 + visible.value = true;
  36 + nextTick(() => {
  37 + registerForm.value.edit(record);
  38 + });
  39 + }
  40 +
  41 + /**
  42 + * 确定按钮点击事件
  43 + */
  44 + function handleOk() {
  45 + registerForm.value.submitForm();
  46 + }
  47 +
  48 + /**
  49 + * form保存回调事件
  50 + */
  51 + function submitCallback({ isUpdate, values, expandedArr, changeParent }) {
  52 + handleCancel();
  53 + emit('success', {
  54 + isUpdate: isUpdate,
  55 + values: values,
  56 + expandedArr: expandedArr,
  57 + // 是否更改了父级节点
  58 + changeParent: changeParent,
  59 + });
  60 + }
  61 +
  62 + /**
  63 + * 取消按钮回调事件
  64 + */
  65 + function handleCancel() {
  66 + visible.value = false;
  67 + }
  68 +
  69 + defineExpose({
  70 + add,
  71 + edit,
  72 + disableSubmit,
  73 + });
  74 +</script>
  75 +
  76 +<style>
  77 + /**隐藏样式-modal确定按钮 */
  78 + .jee-hidden {
  79 + display: none !important;
  80 + }
  81 +</style>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
  1 +<#include "/common/utils.ftl">
1 2 package ${bussiPackage}.${entityPackage}.entity;
2 3  
3 4 import java.io.Serializable;
... ... @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 32 <#-- 生成字典Code -->
32 33 <#assign list_field_dictCode="">
33 34 <#if po.classType='sel_user'>
34   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  35 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
35 36 <#elseif po.classType='sel_depart'>
36   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  37 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
37 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 39 <#if po.dictTable?default("")?trim?length gt 1>
39 40 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
  1 +<#include "/common/utils.ftl">
1 2 <#list subTables as subTab>
2 3 #segment#${subTab.entityName}.java
3 4 package ${bussiPackage}.${entityPackage}.entity;
... ... @@ -65,7 +66,8 @@ public class ${subTab.entityName} implements Serializable {
65 66 @Dict(dicCode = "id",dicText = "name",dictTable = "sys_category")
66 67 </#if>
67 68 <#if po.classType =='sel_depart'>
68   - @Dict(dicCode = "id",dicText = "depart_name",dictTable = "sys_depart")
  69 + <#assign list_field_dictCode='dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dictTable = "sys_depart"'>
  70 + @Dict(${list_field_dictCode})
69 71 </#if>
70 72 <#-- 大字段转换 -->
71 73 <#include "/common/blob.ftl">
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei
... ... @@ -193,7 +193,7 @@
193 193 <#assign sub_seq=1>
194 194 <#list subTables as sub>
195 195 <a-tab-pane tab="${sub.ftlDescription}" key="${sub_seq}" <#if sub_seq gt 1>forceRender</#if>>
196   - <${sub.entityName}List :mainId="selectedMainId" />
  196 + <${sub.entityName}List :mainId="${sub.entityName?uncap_first}MainId" />
197 197 </a-tab-pane>
198 198 <#assign sub_seq=sub_seq+1>
199 199 </#list>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei
... ... @@ -44,7 +44,7 @@
44 44 @input="popupCallback"
45 45 <#if po.readonly=='Y'>disabled</#if>/>
46 46 <#elseif po.classType =='sel_depart'>
47   - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/>
  47 + <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> />
48 48 <#elseif po.classType =='switch'>
49 49 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
50 50 <#elseif po.classType =='pca'>
... ... @@ -54,7 +54,7 @@
54 54 <#elseif po.classType =='password'>
55 55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
56 56 <#elseif po.classType =='sel_user'>
57   - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  57 + <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>/>
58 58 <#elseif po.classType =='textarea'>
59 59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 60 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei
... ... @@ -46,7 +46,7 @@
46 46 @input="popupCallback"
47 47 <#if po.readonly=='Y'>disabled</#if>/>
48 48 <#elseif po.classType =='sel_depart'>
49   - <j-select-depart v-model="model.${po.fieldName}"multi <#if po.readonly=='Y'>disabled</#if>/>
  49 + <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> />
50 50 <#elseif po.classType =='switch'>
51 51 <j-switch v-model="model.${po.fieldName}"<#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
52 52 <#elseif po.classType =='pca'>
... ... @@ -56,7 +56,7 @@
56 56 <#elseif po.classType =='password'>
57 57 <a-input-password v-model="model.${po.fieldName}"placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
58 58 <#elseif po.classType =='sel_user'>
59   - <j-select-user-by-dep v-model="model.${po.fieldName}"<#if po.readonly=='Y'>disabled</#if>/>
  59 + <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>/>
60 60 <#elseif po.classType =='textarea'>
61 61 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
62 62 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei
... ... @@ -46,6 +46,10 @@
46 46 <template #htmlSlot="{text}">
47 47 <div v-html="text"></div>
48 48 </template>
  49 + <!--省市区字段回显插槽-->
  50 + <template #pcaSlot="{text}">
  51 + {{ getAreaTextByCode(text) }}
  52 + </template>
49 53 <template #fileSlot="{text}">
50 54 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
51 55 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
... ... @@ -77,6 +81,10 @@
77 81 </#list>
78 82 import {columns, searchFormSchema} from './${entityName}.data';
79 83 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api';
  84 + import {downloadFile} from '/@/utils/common/renderUtils';
  85 + <#if list_need_pca>
  86 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  87 + </#if>
80 88 <#if list_need_category>
81 89 import { loadCategoryData } from '/@/api/common/api'
82 90 import { getAuthCache, setAuthCache } from '/@/utils/auth';
... ... @@ -94,6 +102,17 @@
94 102 rowSelection: {type: 'radio'},
95 103 formConfig: {
96 104 schemas: searchFormSchema,
  105 + fieldMapToNumber: [
  106 + <#list columns as po>
  107 + <#if po.isQuery=='Y'>
  108 + <#if po.queryMode!='single'>
  109 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  110 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
  111 + </#if>
  112 + </#if>
  113 + </#if>
  114 + </#list>
  115 + ],
97 116 fieldMapToTime: [
98 117 <#list columns as po>
99 118 <#if po.isQuery=='Y'>
... ... @@ -108,14 +127,15 @@
108 127 </#list>
109 128 ],
110 129 },
111   - actionColumn: {
  130 + actionColumn: {
112 131 width: 120,
113   - },
114   - pagination:{
115   - current: 1,
116   - pageSize: 5,
117   - pageSizeOptions: ['5', '10', '20'],
118   - }
  132 + fixed:'right'
  133 + },
  134 + pagination:{
  135 + current: 1,
  136 + pageSize: 5,
  137 + pageSizeOptions: ['5', '10', '20'],
  138 + }
119 139 },
120 140 exportConfig: {
121 141 name:"${tableVo.ftlDescription}",
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi
  1 +<#include "/common/utils.ftl">
1 2 import {BasicColumn} from '/@/components/Table';
2 3 import {FormSchema} from '/@/components/Table';
3 4 import { rules} from '/@/utils/helper/validator';
... ... @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [
24 25 slots: { customRender: 'htmlSlot' },
25 26 <#elseif po.classType=='pca'>
26 27 dataIndex: '${po.fieldName}',
27   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  28 + slots: { customRender: 'pcaSlot' },
28 29 <#elseif po.classType=='file'>
29 30 dataIndex: '${po.fieldName}',
30 31 slots: { customRender: 'fileSlot' },
... ... @@ -91,17 +92,23 @@ export const searchFormSchema: FormSchema[] = [
91 92 <#elseif po.classType=='switch'>
92 93 component: 'JSwitch',
93 94 componentProps:{
  95 + query:true,
94 96 <#if po.dictField != 'is_open'>
95   - options:"${po.dictField}"
  97 + options:${po.dictField}
96 98 </#if>
97 99 },
98 100 <#elseif po.classType=='sel_depart'>
99 101 component: 'JSelectDept',
100 102 <#elseif po.classType=='list_multi'>
101   - component: 'JMultiSelectTag',//暂无该组件
  103 + component: 'JSelectMultiple',
102 104 componentProps:{
103   - dictCode:"query_field_dictCode?default("")"
104   - },
  105 + <#if po.dictTable?default("")?trim?length gt 1>
  106 + dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
  107 + <#elseif po.dictField?default("")?trim?length gt 1>
  108 + dictCode:"${po.dictField}",
  109 + </#if>
  110 + triggerChange: true
  111 + },
105 112 <#elseif po.classType=='cat_tree'>
106 113 component: 'JCategorySelect',
107 114 componentProps:{
... ... @@ -117,16 +124,7 @@ export const searchFormSchema: FormSchema[] = [
117 124 <#elseif po.classType=='pca'>
118 125 component: 'JAreaLinkage',
119 126 <#elseif po.classType=='popup'>
120   - component: 'JPopup',
121   - componentProps: ({ formActionType }) => {
122   - const {setFieldsValue} = formActionType;
123   - return{
124   - setFieldsValue:setFieldsValue,
125   - code:"${po.dictTable}",
126   - fieldConfig:"${po.dictField}",
127   - multi:${po.extendParams.popupMulti?c},
128   - }
129   - },
  127 + <#include "/common/form/vue3popup.ftl">
130 128 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
131 129 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
132 130 component: 'JDictSelectTag',
... ... @@ -153,6 +151,8 @@ export const searchFormSchema: FormSchema[] = [
153 151 componentProps: {
154 152 showTime:true
155 153 },
  154 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  155 + component: 'JRangeNumber',
156 156 <#else>
157 157 component: 'Input', //TODO 范围查询
158 158 </#if>
... ... @@ -186,27 +186,22 @@ export const formSchema: FormSchema[] = [
186 186 </#if>
187 187 {
188 188 label: '${po.filedComment}',
189   - field: '${po.fieldName}',
  189 + field: ${autoStringSuffix(po)},
190 190 <#if po.classType =='date'>
191 191 component: 'DatePicker',
192   - <#elseif po.fieldType =='datetime'>
  192 + <#elseif po.classType =='datetime'>
193 193 component: 'DatePicker',
194 194 componentProps: {
195   - showTime:true
  195 + showTime:true,
  196 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
196 197 },
197   - <#elseif po.fieldType =='time'>
  198 + <#elseif po.classType =='time'>
198 199 component: 'TimePicker',
  200 + componentProps: {
  201 + valueFormat: 'HH:mm:ss'
  202 + },
199 203 <#elseif po.classType =='popup'>
200   - component: 'JPopup',
201   - componentProps: ({ formActionType }) => {
202   - const {setFieldsValue} = formActionType;
203   - return{
204   - setFieldsValue:setFieldsValue,
205   - code:"${po.dictTable}",
206   - fieldConfig:${po.dictField},
207   - multi:${po.extendParams.popupMulti?c},
208   - }
209   - },
  204 + <#include "/common/form/vue3popup.ftl">
210 205 <#elseif po.classType =='sel_depart'>
211 206 component: 'JSelectDept',
212 207 <#elseif po.classType =='switch'>
... ... @@ -235,7 +230,7 @@ export const formSchema: FormSchema[] = [
235 230 dictCode:"${form_field_dictCode}"
236 231 },
237 232 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
238   - component: 'JMultiSelectTag',//TODO 暂无该组件
  233 + component: 'JSelectMultiple',
239 234 componentProps:{
240 235 dictCode:"${form_field_dictCode}"
241 236 },
... ... @@ -270,7 +265,7 @@ export const formSchema: FormSchema[] = [
270 265 </#if>
271 266 },
272 267 <#elseif po.classType=='umeditor'>
273   - component: 'JCodeEditor', //TODO String后缀暂未添加
  268 + component: 'JEditor',
274 269 <#elseif po.classType == 'sel_tree'>
275 270 component: 'JTreeSelect',
276 271 componentProps:{
... ... @@ -302,16 +297,16 @@ export const formSchema: FormSchema[] = [
302 297 </#if>
303 298 <#-- 唯一校验 -->
304 299 <#if fieldValidType == 'only'>
305   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  300 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
306 301 <#-- 6到16位数字 -->
307 302 <#elseif fieldValidType == 'n6-16'>
308 303 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
309 304 <#-- 6到16位任意字符 -->
310 305 <#elseif fieldValidType == '*6-16'>
311 306 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
312   - <#-- 6到18位字符串 -->
  307 + <#-- 6到18位字 -->
313 308 <#elseif fieldValidType == 's6-18'>
314   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  309 + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
315 310 <#-- 网址 -->
316 311 <#elseif fieldValidType == 'url'>
317 312 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ... @@ -387,7 +382,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
387 382 slots: { customRender: 'htmlSlot' },
388 383 <#elseif po.classType=='pca'>
389 384 dataIndex: '${po.fieldName}',
390   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  385 + slots: { customRender: 'pcaSlot' },
391 386 <#elseif po.classType=='file'>
392 387 dataIndex: '${po.fieldName}',
393 388 slots: { customRender: 'fileSlot' },
... ... @@ -419,7 +414,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
419 414 return render.renderCategoryTree(text,'${po.dictField?default("")}')
420 415 },
421 416 <#else>
422   - customRender: (text, record) => (text ? record['${po.dictText}'] : '')
  417 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
423 418 </#if>
424 419 <#else>
425 420 dataIndex: '${po.fieldName}'
... ... @@ -452,27 +447,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
452 447 </#if>
453 448 {
454 449 label: '${po.filedComment}',
455   - field: '${po.fieldName}',
  450 + field: ${autoStringSuffix(po)},
456 451 <#if po.classType =='date'>
457 452 component: 'DatePicker',
458   - <#elseif po.fieldType =='datetime'>
  453 + <#elseif po.classType =='datetime'>
459 454 component: 'DatePicker',
460 455 componentProps: {
461   - showTime:true
  456 + showTime:true,
  457 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
462 458 },
463   - <#elseif po.fieldType =='time'>
  459 + <#elseif po.classType =='time'>
464 460 component: 'TimePicker',
  461 + componentProps: {
  462 + valueFormat: 'HH:mm:ss'
  463 + },
465 464 <#elseif po.classType =='popup'>
466   - component: 'JPopup',
467   - componentProps: ({ formActionType }) => {
468   - const {setFieldsValue} = formActionType;
469   - return{
470   - setFieldsValue:setFieldsValue,
471   - code:"${po.dictTable}",
472   - fieldConfig:${po.dictField},
473   - multi:${po.extendParams.popupMulti?c},
474   - }
475   - },
  465 + <#include "/common/form/vue3popup.ftl">
476 466 <#elseif po.classType =='sel_depart'>
477 467 component: 'JSelectDept',
478 468 <#elseif po.classType =='switch'>
... ... @@ -494,14 +484,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
494 484 labelKey:'realname',
495 485 },
496 486 <#elseif po.classType =='textarea'>
497   - component: 'InputTextArea',//TODO 注意string转换问题
  487 + component: 'InputTextArea',
498 488 <#elseif po.classType=='list' || po.classType=='radio'>
499 489 component: 'JDictSelectTag',
500 490 componentProps:{
501 491 dictCode:"${form_field_dictCode}"
502 492 },
503 493 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
504   - component: 'JMultiSelectTag',//TODO 暂无该组件
  494 + component: 'JSelectMultiple',
505 495 componentProps:{
506 496 dictCode:"${form_field_dictCode}"
507 497 },
... ... @@ -536,7 +526,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
536 526 </#if>
537 527 },
538 528 <#elseif po.classType=='umeditor'>
539   - component: 'JCodeEditor', //TODO String后缀暂未添加
  529 + component: 'JEditor',
540 530 <#elseif po.classType == 'sel_tree'>
541 531 component: 'JTreeSelect',
542 532 componentProps:{
... ... @@ -568,16 +558,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
568 558 </#if>
569 559 <#-- 唯一校验 -->
570 560 <#if fieldValidType == 'only'>
571   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  561 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
572 562 <#-- 6到16位数字 -->
573 563 <#elseif fieldValidType == 'n6-16'>
574 564 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
575 565 <#-- 6到16位任意字符 -->
576 566 <#elseif fieldValidType == '*6-16'>
577 567 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
578   - <#-- 6到18位字符串 -->
  568 + <#-- 6到18位字 -->
579 569 <#elseif fieldValidType == 's6-18'>
580   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  570 + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
581 571 <#-- 网址 -->
582 572 <#elseif fieldValidType == 'url'>
583 573 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei
... ... @@ -51,6 +51,7 @@
51 51 import {${sub.entityName?uncap_first}List, ${sub.entityName?uncap_first}Delete, ${sub.entityName?uncap_first}DeleteBatch, ${sub.entityName?uncap_first}ExportXlsUrl, ${sub.entityName?uncap_first}ImportUrl } from './${entityName}.api';
52 52 import {isEmpty} from "/@/utils/is";
53 53 import {useMessage} from '/@/hooks/web/useMessage';
  54 + import {downloadFile} from '/@/utils/common/renderUtils';
54 55  
55 56 //接收主表id
56 57 const mainId = inject('mainId') || '';
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei
  1 +<#include "/common/utils.ftl">
1 2 <template>
2   - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
  3 + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
3 4 <BasicForm @register="registerForm"/>
4 5 </BasicModal>
5 6 </template>
... ... @@ -18,6 +19,7 @@
18 19 labelWidth: 150,
19 20 schemas: formSchema,
20 21 showActionButtonGroup: false,
  22 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
21 23 });
22 24 //表单赋值
23 25 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
... ... @@ -54,5 +56,12 @@
54 56 </script>
55 57  
56 58 <style lang="less" scoped>
  59 + /** 时间和数字输入框样式 */
  60 + :deep(.ant-input-number){
  61 + width: 100%
  62 + }
57 63  
  64 + :deep(.ant-calendar-picker){
  65 + width: 100%
  66 + }
58 67 </style>
59 68 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei
... ... @@ -2,7 +2,7 @@
2 2 <#list subTables as sub>
3 3 #segment#${sub.entityName}Modal.vue
4 4 <template>
5   - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
  5 + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
6 6 <BasicForm @register="registerForm"/>
7 7 </BasicModal>
8 8 </template>
... ... @@ -24,6 +24,7 @@
24 24 labelWidth: 150,
25 25 schemas: ${sub.entityName?uncap_first}FormSchema,
26 26 showActionButtonGroup: false,
  27 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
27 28 });
28 29 //表单赋值
29 30 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
... ... @@ -63,4 +64,14 @@
63 64 }
64 65 }
65 66 </script>
  67 +<style lang="less" scoped>
  68 + /** 时间和数字输入框样式 */
  69 + :deep(.ant-input-number){
  70 + width: 100%
  71 + }
  72 +
  73 + :deep(.ant-calendar-picker){
  74 + width: 100%
  75 + }
  76 +</style>
66 77 </#list>
67 78 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
... ... @@ -200,17 +200,14 @@ public class ${entityName}Controller {
200 200 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
201 201 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
202 202  
203   - //Step.2 获取导出数据
204   - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper);
205   - // 过滤选中数据
  203 + //配置选中数据查询条件
206 204 String selections = request.getParameter("selections");
207   - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>();
208   - if(oConvertUtils.isEmpty(selections)) {
209   - ${entityName?uncap_first}List = queryList;
210   - }else {
211   - List<String> selectionList = Arrays.asList(selections.split(","));
212   - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
  205 + if(oConvertUtils.isNotEmpty(selections)) {
  206 + List<String> selectionList = Arrays.asList(selections.split(","));
  207 + queryWrapper.in("id",selectionList);
213 208 }
  209 + //Step.2 获取导出数据
  210 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper);
214 211  
215 212 // Step.3 组装pageList
216 213 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
  1 +<#include "/common/utils.ftl">
1 2 package ${bussiPackage}.${entityPackage}.entity;
2 3  
3 4 import java.io.Serializable;
... ... @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 32 <#-- 生成字典Code -->
32 33 <#assign list_field_dictCode="">
33 34 <#if po.classType='sel_user'>
34   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  35 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
35 36 <#elseif po.classType='sel_depart'>
36   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  37 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
37 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 39 <#if po.dictTable?default("")?trim?length gt 1>
39 40 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
  1 +<#include "/common/utils.ftl">
1 2 <#list subTables as subTab>
2 3 #segment#${subTab.entityName}.java
3 4 package ${bussiPackage}.${entityPackage}.entity;
... ... @@ -33,9 +34,9 @@ public class ${subTab.entityName} implements Serializable {
33 34 <#-- 生成字典Code -->
34 35 <#assign list_field_dictCode="">
35 36 <#if po.classType='sel_user'>
36   - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'>
  37 + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'>
37 38 <#elseif po.classType='sel_depart'>
38   - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'>
  39 + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'>
39 40 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
40 41 <#if po.dictTable?default("")?trim?length gt 1>
41 42 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei
... ... @@ -41,7 +41,7 @@
41 41 @input="popupCallback"
42 42 <#if po.readonly=='Y'>disabled</#if>/>
43 43 <#elseif po.classType =='sel_depart'>
44   - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/>
  44 + <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> />
45 45 <#elseif po.classType =='switch'>
46 46 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
47 47 <#elseif po.classType =='pca'>
... ... @@ -51,7 +51,7 @@
51 51 <#elseif po.classType =='password'>
52 52 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
53 53 <#elseif po.classType =='sel_user'>
54   - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
  54 + <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>/>
55 55 <#elseif po.classType =='textarea'>
56 56 <a-textarea v-decorator="[${autoStringSuffix(po)}${autoWriteRules(po)}]" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
57 57 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei
... ... @@ -36,9 +36,9 @@
36 36 <#elseif po.classType =='switch'>
37 37 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch>
38 38 <#elseif po.classType =='sel_depart'>
39   - <j-select-depart v-model="model.${po.fieldName}" />
  39 + <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> />
40 40 <#elseif po.classType =='sel_user'>
41   - <j-select-user-by-dep v-model="model.${po.fieldName}" />
  41 + <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>/>
42 42 <#elseif po.classType =='textarea'>
43 43 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/>
44 44 <#elseif po.classType=='list' || po.classType=='radio'>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei
... ... @@ -60,6 +60,10 @@
60 60 <template #htmlSlot="{text}">
61 61 <div v-html="text"></div>
62 62 </template>
  63 + <!--省市区字段回显插槽-->
  64 + <template #pcaSlot="{text}">
  65 + {{ getAreaTextByCode(text) }}
  66 + </template>
63 67 <template #fileSlot="{text}">
64 68 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
65 69 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
... ... @@ -81,6 +85,10 @@
81 85 </#list>
82 86 import {columns, searchFormSchema} from './${entityName}.data';
83 87 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api';
  88 + import {downloadFile} from '/@/utils/common/renderUtils';
  89 + <#if list_need_pca>
  90 + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
  91 + </#if>
84 92 <#if list_need_category>
85 93 import { loadCategoryData } from '/@/api/common/api'
86 94 import { getAuthCache, setAuthCache } from '/@/utils/auth';
... ... @@ -102,6 +110,17 @@
102 110 schemas: searchFormSchema,
103 111 autoSubmitOnEnter:true,
104 112 showAdvancedButton:true,
  113 + fieldMapToNumber: [
  114 + <#list columns as po>
  115 + <#if po.isQuery=='Y'>
  116 + <#if po.queryMode!='single'>
  117 + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  118 + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
  119 + </#if>
  120 + </#if>
  121 + </#if>
  122 + </#list>
  123 + ],
105 124 fieldMapToTime: [
106 125 <#list columns as po>
107 126 <#if po.isQuery=='Y'>
... ... @@ -116,9 +135,10 @@
116 135 </#list>
117 136 ],
118 137 },
119   - actionColumn: {
  138 + actionColumn: {
120 139 width: 120,
121   - },
  140 + fixed:'right'
  141 + },
122 142 },
123 143 exportConfig: {
124 144 name:"${tableVo.ftlDescription}",
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi
  1 +<#include "/common/utils.ftl">
1 2 import {BasicColumn} from '/@/components/Table';
2 3 import {FormSchema} from '/@/components/Table';
3 4 import { rules} from '/@/utils/helper/validator';
... ... @@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [
25 26 slots: { customRender: 'htmlSlot' },
26 27 <#elseif po.classType=='pca'>
27 28 dataIndex: '${po.fieldName}',
28   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  29 + slots: { customRender: 'pcaSlot' },
29 30 <#elseif po.classType=='file'>
30 31 dataIndex: '${po.fieldName}',
31 32 slots: { customRender: 'fileSlot' },
... ... @@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [
57 58 return render.renderCategoryTree(text,'${po.dictField?default("")}')
58 59 },
59 60 <#else>
60   - customRender: (text, record) => (text ? record['${po.dictText}'] : '')
  61 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
61 62 </#if>
62 63 <#else>
63 64 dataIndex: '${po.fieldName}'
... ... @@ -84,7 +85,7 @@ export const searchFormSchema: FormSchema[] = [
84 85 <#if po.queryMode=='single'>
85 86 {
86 87 label: "${po.filedComment}",
87   - field: "${po.fieldName}",
  88 + field: ${autoStringSuffix(po)},
88 89 <#if po.classType=='sel_search'>
89 90 component: 'JSearchSelect',
90 91 componentProps:{
... ... @@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [
95 96 <#elseif po.classType=='switch'>
96 97 component: 'JSwitch',
97 98 componentProps:{
  99 + query:true,
98 100 <#if po.dictField != 'is_open'>
99   - options:"${po.dictField}"
  101 + options:${po.dictField}
100 102 </#if>
101 103 },
102 104 <#elseif po.classType=='sel_depart'>
103 105 component: 'JSelectDept',
104 106 <#elseif po.classType=='list_multi'>
105   - component: 'JMultiSelectTag',//暂无该组件
106   - componentProps:{
107   - dictCode:"query_field_dictCode?default("")"
  107 + component: 'JSelectMultiple',
  108 + componentProps:{
  109 + <#if po.dictTable?default("")?trim?length gt 1>
  110 + dictCode:"${po.dictTable},${po.dictText},${po.dictField}",
  111 + <#elseif po.dictField?default("")?trim?length gt 1>
  112 + dictCode:"${po.dictField}",
  113 + </#if>
  114 + triggerChange: true
108 115 },
109 116 <#elseif po.classType=='cat_tree'>
110 117 component: 'JCategorySelect',
... ... @@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [
121 128 <#elseif po.classType=='pca'>
122 129 component: 'JAreaLinkage',
123 130 <#elseif po.classType=='popup'>
124   - component: 'JPopup',
125   - componentProps: ({ formActionType }) => {
126   - const {setFieldsValue} = formActionType;
127   - return{
128   - setFieldsValue:setFieldsValue,
129   - code:"${po.dictTable}",
130   - fieldConfig:"${po.dictField}",
131   - multi:${po.extendParams.popupMulti?c},
132   - }
133   - },
  131 + <#include "/common/form/vue3popup.ftl">
134 132 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
135 133 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
136 134 component: 'JDictSelectTag',
... ... @@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [
157 155 componentProps: {
158 156 showTime:true
159 157 },
  158 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  159 + component: 'JRangeNumber',
160 160 <#else>
161 161 component: 'Input', //TODO 范围查询
162 162 </#if>
... ... @@ -189,28 +189,23 @@ export const formSchema: FormSchema[] = [
189 189 </#if>
190 190 {
191 191 label: '${po.filedComment}',
192   - field: '${po.fieldName}',
  192 + field: ${autoStringSuffix(po)},
193 193 <#if po.classType =='date'>
194 194 component: 'DatePicker',
195   - <#elseif po.fieldType =='datetime'>
  195 + <#elseif po.classType =='datetime'>
196 196 component: 'DatePicker',
197 197 componentProps: {
198   - showTime:true
  198 + showTime:true,
  199 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
199 200 },
200   - <#elseif po.fieldType =='time'>
  201 + <#elseif po.classType =='time'>
201 202 component: 'TimePicker',
  203 + componentProps: {
  204 + valueFormat: 'HH:mm:ss'
  205 + },
202 206 <#elseif po.classType =='popup'>
203   - component: 'JPopup',
204   - componentProps: ({ formActionType }) => {
205   - const {setFieldsValue} = formActionType;
206   - return{
207   - setFieldsValue:setFieldsValue,
208   - code:"${po.dictTable}",
209   - fieldConfig:${po.dictField},
210   - multi:${po.extendParams.popupMulti?c},
211   - }
212   - },
213   - <#elseif po.classType =='sel_depart'>
  207 + <#include "/common/form/vue3popup.ftl">
  208 + <#elseif po.classType =='sel_depart'>
214 209 component: 'JSelectDept',
215 210 <#elseif po.classType =='switch'>
216 211 component: 'JSwitch',
... ... @@ -231,14 +226,14 @@ export const formSchema: FormSchema[] = [
231 226 labelKey:'realname',
232 227 },
233 228 <#elseif po.classType =='textarea'>
234   - component: 'InputTextArea',//TODO 注意string转换问题
  229 + component: 'InputTextArea',
235 230 <#elseif po.classType=='list' || po.classType=='radio'>
236 231 component: 'JDictSelectTag',
237 232 componentProps:{
238 233 dictCode:"${form_field_dictCode}"
239 234 },
240 235 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
241   - component: 'JMultiSelectTag',//TODO 暂无该组件
  236 + component: 'JSelectMultiple',
242 237 componentProps:{
243 238 dictCode:"${form_field_dictCode}"
244 239 },
... ... @@ -273,7 +268,7 @@ export const formSchema: FormSchema[] = [
273 268 </#if>
274 269 },
275 270 <#elseif po.classType=='umeditor'>
276   - component: 'JCodeEditor', //TODO String后缀暂未添加
  271 + component: 'JEditor',
277 272 <#elseif po.classType == 'sel_tree'>
278 273 component: 'JTreeSelect',
279 274 componentProps:{
... ... @@ -305,16 +300,16 @@ export const formSchema: FormSchema[] = [
305 300 </#if>
306 301 <#-- 唯一校验 -->
307 302 <#if fieldValidType == 'only'>
308   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  303 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
309 304 <#-- 6到16位数字 -->
310 305 <#elseif fieldValidType == 'n6-16'>
311 306 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
312 307 <#-- 6到16位任意字符 -->
313 308 <#elseif fieldValidType == '*6-16'>
314 309 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
315   - <#-- 6到18位字符串 -->
  310 + <#-- 6到18位字 -->
316 311 <#elseif fieldValidType == 's6-18'>
317   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  312 + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
318 313 <#-- 网址 -->
319 314 <#elseif fieldValidType == 'url'>
320 315 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ... @@ -390,7 +385,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
390 385 slots: { customRender: 'htmlSlot' },
391 386 <#elseif po.classType=='pca'>
392 387 dataIndex: '${po.fieldName}',
393   - slots: { customRender: 'pcaSlot' },//TODO 未翻译
  388 + slots: { customRender: 'pcaSlot' },
394 389 <#elseif po.classType=='file'>
395 390 dataIndex: '${po.fieldName}',
396 391 slots: { customRender: 'fileSlot' },
... ... @@ -422,7 +417,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
422 417 return render.renderCategoryTree(text,'${po.dictField?default("")}')
423 418 },
424 419 <#else>
425   - customRender: (text, record) => (text ? record['${po.dictText}'] : '')
  420 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
426 421 </#if>
427 422 <#else>
428 423 dataIndex: '${po.fieldName}'
... ... @@ -436,10 +431,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
436 431 <#assign form_cat_tree = false>
437 432 <#assign form_cat_back = "">
438 433 <#assign bpm_flag=false>
  434 +<#assign sub_id_exists=false>
439 435 <#list sub.colums as po><#rt/>
440 436 <#if po.fieldDbName=='bpm_status'>
441 437 <#assign bpm_flag=true>
442 438 </#if>
  439 +<#if po.fieldDbName=='id'>
  440 + <#assign sub_id_exists=true>
  441 +</#if>
443 442 <#if po.isShow =='Y'>
444 443 <#assign form_field_dictCode="">
445 444 <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
... ... @@ -449,27 +448,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
449 448 </#if>
450 449 {
451 450 label: '${po.filedComment}',
452   - field: '${po.fieldName}',
  451 + field: ${autoStringSuffix(po)},
453 452 <#if po.classType =='date'>
454 453 component: 'DatePicker',
455   - <#elseif po.fieldType =='datetime'>
  454 + <#elseif po.classType =='datetime'>
456 455 component: 'DatePicker',
457 456 componentProps: {
458   - showTime:true
  457 + showTime:true,
  458 + valueFormat: 'YYYY-MM-DD HH:mm:ss'
459 459 },
460   - <#elseif po.fieldType =='time'>
  460 + <#elseif po.classType =='time'>
461 461 component: 'TimePicker',
  462 + componentProps: {
  463 + valueFormat: 'HH:mm:ss'
  464 + },
462 465 <#elseif po.classType =='popup'>
463   - component: 'JPopup',
464   - componentProps: ({ formActionType }) => {
465   - const {setFieldsValue} = formActionType;
466   - return{
467   - setFieldsValue:setFieldsValue,
468   - code:"${po.dictTable}",
469   - fieldConfig:${po.dictField},
470   - multi:${po.extendParams.popupMulti?c},
471   - }
472   - },
  466 + <#include "/common/form/vue3popup.ftl">
473 467 <#elseif po.classType =='sel_depart'>
474 468 component: 'JSelectDept',
475 469 <#elseif po.classType =='switch'>
... ... @@ -491,14 +485,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
491 485 labelKey:'realname',
492 486 },
493 487 <#elseif po.classType =='textarea'>
494   - component: 'InputTextArea',//TODO 注意string转换问题
  488 + component: 'InputTextArea',
495 489 <#elseif po.classType=='list' || po.classType=='radio'>
496 490 component: 'JDictSelectTag',
497 491 componentProps:{
498 492 dictCode:"${form_field_dictCode}"
499 493 },
500 494 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
501   - component: 'JMultiSelectTag',//TODO 暂无该组件
  495 + component: 'JSelectMultiple',
502 496 componentProps:{
503 497 dictCode:"${form_field_dictCode}"
504 498 },
... ... @@ -533,7 +527,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
533 527 </#if>
534 528 },
535 529 <#elseif po.classType=='umeditor'>
536   - component: 'JCodeEditor', //TODO String后缀暂未添加
  530 + component: 'JEditor',
537 531 <#elseif po.classType == 'sel_tree'>
538 532 component: 'JTreeSelect',
539 533 componentProps:{
... ... @@ -565,16 +559,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
565 559 </#if>
566 560 <#-- 唯一校验 -->
567 561 <#if fieldValidType == 'only'>
568   - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
  562 + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
569 563 <#-- 6到16位数字 -->
570 564 <#elseif fieldValidType == 'n6-16'>
571 565 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
572 566 <#-- 6到16位任意字符 -->
573 567 <#elseif fieldValidType == '*6-16'>
574 568 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
575   - <#-- 6到18位字符串 -->
  569 + <#-- 6到18位字 -->
576 570 <#elseif fieldValidType == 's6-18'>
577   - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
  571 + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
578 572 <#-- 网址 -->
579 573 <#elseif fieldValidType == 'url'>
580 574 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
... ... @@ -616,6 +610,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
616 610 },
617 611 </#if>
618 612 </#list>
  613 +<#if sub_id_exists == false>
  614 + {
  615 + label: '',
  616 + field: 'id',
  617 + component: 'Input',
  618 + show: false
  619 + },
  620 +</#if>
619 621 ];
620 622 </#if>
621 623 </#list>
... ... @@ -642,12 +644,20 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
642 644 <#if col.readonly=='Y'>
643 645 disabled:true,
644 646 </#if>
  647 +<#elseif col.classType =='time'>
  648 + type: JVxeTypes.time,
  649 + <#if col.readonly=='Y'>
  650 + disabled:true,
  651 + </#if>
645 652 <#elseif col.classType =='textarea'>
646 653 type: JVxeTypes.textarea,
647 654 <#if col.readonly=='Y'>
648 655 disabled:true,
649 656 </#if>
650   -<#elseif "int,decimal,double,"?contains(col.classType)>
  657 +<#-- update-begin-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 -->
  658 +<#-- elseif "int,decimal,double,"?contains(col.classType) -->
  659 +<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'>
  660 +<#-- update-end-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 -->
651 661 type: JVxeTypes.inputNumber,
652 662 <#if col.readonly=='Y'>
653 663 disabled:true,
... ... @@ -684,6 +694,16 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
684 694 <#if col.readonly=='Y'>
685 695 disabled:true,
686 696 </#if>
  697 +<#elseif col.classType =='sel_depart'>
  698 + type: JVxeTypes.departSelect,
  699 + <#if col.readonly=='Y'>
  700 + disabled:true,
  701 + </#if>
  702 +<#elseif col.classType =='sel_user'>
  703 + type: JVxeTypes.userSelect,
  704 + <#if col.readonly=='Y'>
  705 + disabled:true,
  706 + </#if>
687 707 <#elseif col.classType =='image'>
688 708 type: JVxeTypes.image,
689 709 token:true,
... ... @@ -707,9 +727,9 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
707 727 <#elseif col.classType =='switch'>
708 728 type: JVxeTypes.checkbox,
709 729 <#if col.dictField == 'is_open'>
710   - customValue: ['Y', 'N'],
  730 + customValue: ['Y', 'N'],
711 731 <#else>
712   - customValue: ${col.dictField},
  732 + customValue: ${col.dictField},
713 733 </#if>
714 734 <#if col.readonly=='Y'>
715 735 disabled:true,
... ... @@ -720,18 +740,11 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
720 740 <#else>
721 741 <#assign popupBackFields = "${col.dictText}">
722 742 </#if>
723   - type: JVxeTypes.popup,
724   - popupCode:"${col.dictTable}",
725   - field:"${col.dictField}",
726   - orgFields:"${col.dictField}",
727   - destFields:"${Format.underlineToHump(col.dictText)}",
728   - <#if col.readonly=='Y'>
729   - disabled:true,
730   - </#if>
  743 + <#include "/common/form/vue3Jvxepopup.ftl">
731 744 <#else>
732   - type: JVxeTypes.input,
  745 + type: JVxeTypes.input,
733 746 <#if col.readonly=='Y'>
734   - disabled:true,
  747 + disabled:true,
735 748 </#if>
736 749 </#if>
737 750 <#if col.classType =='list_multi' || col.classType =='checkbox'>
... ... @@ -754,18 +767,7 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
754 767 defaultValue:'',
755 768 </#if>
756 769 <#-- 子表的校验 -->
757   -<#assign subFieldValidType = col.fieldValidType!''>
758   -<#-- 非空校验 -->
759   -<#if col.nullable == 'N' || subFieldValidType == '*'>
760   - validateRules: [{ required: true, message: '${'$'}{title}不能为空' }],
761   -<#-- 其他情况下,只要有值就被认为是正则校验 -->
762   -<#elseif subFieldValidType?length gt 0>
763   -<#assign subMessage = '格式不正确'>
764   -<#if subFieldValidType == 'only' >
765   - <#assign subMessage = '不能重复'>
766   -</#if>
767   - validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }],
768   -</#if>
  770 + <#include "/common/validatorRulesTemplate/sub-vue3.ftl">
769 771 },
770 772 </#if>
771 773 </#if>
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql 0 → 100644
  1 +<#include "/common/sql/menu_insert.ftl">
0 2 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei
  1 +<#include "/common/utils.ftl">
1 2 <template>
2   - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
  3 + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
3 4 <BasicForm @register="registerForm" ref="formRef"/>
4 5 <!-- 子表单区域 -->
5 6 <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs">
... ... @@ -7,7 +8,7 @@
7 8 <#assign refKey = sub.entityName?uncap_first/>
8 9 <#if sub.foreignRelationType =='1'>
9 10 <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true">
10   - <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form>
  11 + <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form" :disabled="formDisabled"></${sub.entityName}Form>
11 12 </a-tab-pane>
12 13  
13 14 <#else>
... ... @@ -19,7 +20,8 @@
19 20 :loading="${sub.entityName?uncap_first}Table.loading"
20 21 :columns="${sub.entityName?uncap_first}Table.columns"
21 22 :dataSource="${sub.entityName?uncap_first}Table.dataSource"
22   - :maxHeight="300"
  23 + :height="340"
  24 + :disabled="formDisabled"
23 25 :rowNumber="true"
24 26 :rowSelection="true"
25 27 :toolbar="true"
... ... @@ -48,6 +50,7 @@
48 50 // Emits声明
49 51 const emit = defineEmits(['register','success']);
50 52 const isUpdate = ref(true);
  53 + const formDisabled = ref(false);
51 54 const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]);
52 55 <#assign hasOne2Many = false>
53 56 <#assign hasOne2One = false>
... ... @@ -77,6 +80,7 @@
77 80 labelWidth: 150,
78 81 schemas: formSchema,
79 82 showActionButtonGroup: false,
  83 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
80 84 });
81 85 //表单赋值
82 86 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
... ... @@ -84,6 +88,7 @@
84 88 await reset();
85 89 setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
86 90 isUpdate.value = !!data?.isUpdate;
  91 + formDisabled.value = !data?.showFooter;
87 92 if (unref(isUpdate)) {
88 93 //表单赋值
89 94 await setFieldsValue({
... ... @@ -176,5 +181,12 @@
176 181 </script>
177 182  
178 183 <style lang="less" scoped>
  184 + /** 时间和数字输入框样式 */
  185 + :deep(.ant-input-number){
  186 + width: 100%
  187 + }
179 188  
  189 + :deep(.ant-calendar-picker){
  190 + width: 100%
  191 + }
180 192 </style>
181 193 \ No newline at end of file
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei
  1 +<#include "/common/utils.ftl">
1 2 <#list subTables as sub>
2 3 <#if sub.foreignRelationType=='1'>
3 4 #segment#${sub.entityName}Form.vue
... ... @@ -15,11 +16,18 @@
15 16 name:"${sub.entityName}Form",
16 17 components: {BasicForm},
17 18 emits:['register'],
18   - setup(_,{emit}) {
19   - const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
  19 + props:{
  20 + disabled: {
  21 + type: Boolean,
  22 + default: false
  23 + }
  24 + },
  25 + setup(props,{emit}) {
  26 + const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
20 27 labelWidth: 150,
21 28 schemas: ${sub.entityName?uncap_first}FormSchema,
22 29 showActionButtonGroup: false,
  30 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
23 31 });
24 32 /**
25 33 *初始化加载数据
... ... @@ -30,13 +38,22 @@
30 38 res.success && setFieldsValue({...res.result.records[0]});
31 39 })
32 40 }
  41 + setProps({disabled: props.disabled})
33 42 }
34   - /**
35   - *获取表单数据
36   - */
  43 +
  44 + /**
  45 + *获取表单数据
  46 + */
37 47 function getFormData(){
38   - return [getFieldsValue()];
  48 + let formData = getFieldsValue();
  49 + Object.keys(formData).map(k=>{
  50 + if(formData[k] instanceof Array){
  51 + formData[k] = formData[k].join(',')
  52 + }
  53 + });
  54 + return [formData];
39 55 }
  56 +
40 57 /**
41 58 *表单校验
42 59 */
... ...
jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
... ... @@ -205,17 +205,14 @@ public class ${entityName}Controller {
205 205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
206 206 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
207 207  
208   - //Step.2 获取导出数据
209   - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper);
210   - // 过滤选中数据
  208 + //配置选中数据查询条件
211 209 String selections = request.getParameter("selections");
212   - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>();
213   - if(oConvertUtils.isEmpty(selections)) {
214   - ${entityName?uncap_first}List = queryList;
215   - }else {
216   - List<String> selectionList = Arrays.asList(selections.split(","));
217   - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
  210 + if(oConvertUtils.isNotEmpty(selections)) {
  211 + List<String> selectionList = Arrays.asList(selections.split(","));
  212 + queryWrapper.in("id",selectionList);
218 213 }
  214 + //Step.2 获取导出数据
  215 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper);
219 216  
220 217 // Step.3 组装pageList
221 218 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();
... ...