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 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 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,7 +25,7 @@
25 <#return text?uncap_first> 25 <#return text?uncap_first>
26 </#function> 26 </#function>
27 <#-- 驼峰转下划线 --> 27 <#-- 驼峰转下划线 -->
28 -<#function camelToDashed(str, case='normal')> 28 +<#function camelToDashed(str, case='lower')>
29 <#return camelToChar(str, "_", case)> 29 <#return camelToChar(str, "_", case)>
30 </#function> 30 </#function>
31 <#----> 31 <#---->
@@ -130,4 +130,44 @@ @@ -130,4 +130,44 @@
130 <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}"> 130 <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}">
131 </#if> 131 </#if>
132 </#if> 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 </#function> 173 </#function>
134 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 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 package ${bussiPackage}.${entityPackage}.entity; 2 package ${bussiPackage}.${entityPackage}.entity;
2 3
3 import java.io.Serializable; 4 import java.io.Serializable;
@@ -36,9 +37,9 @@ public class ${entityName} implements Serializable { @@ -36,9 +37,9 @@ public class ${entityName} implements Serializable {
36 <#-- 生成字典Code --> 37 <#-- 生成字典Code -->
37 <#assign list_field_dictCode=""> 38 <#assign list_field_dictCode="">
38 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 43 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
43 <#if po.dictTable?default("")?trim?length gt 1> 44 <#if po.dictTable?default("")?trim?length gt 1>
44 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 \ No newline at end of file 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,7 +48,7 @@
48 @input="popupCallback" 48 @input="popupCallback"
49 <#if po.readonly=='Y'>disabled</#if>/> 49 <#if po.readonly=='Y'>disabled</#if>/>
50 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 52 <#elseif po.classType =='switch'>
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> 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 <#elseif po.classType =='pca'> 54 <#elseif po.classType =='pca'>
@@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
58 <#elseif po.classType =='password'> 58 <#elseif po.classType =='password'>
59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 62 <#elseif po.classType =='textarea'>
63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 <#elseif po.classType=='list' || po.classType=='radio'> 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,6 +46,10 @@
46 <template #htmlSlot="{text}"> 46 <template #htmlSlot="{text}">
47 <div v-html="text"></div> 47 <div v-html="text"></div>
48 </template> 48 </template>
  49 + <!--省市区字段回显插槽-->
  50 + <template #pcaSlot="{text}">
  51 + {{ getAreaTextByCode(text) }}
  52 + </template>
49 <template #fileSlot="{text}"> 53 <template #fileSlot="{text}">
50 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> 54 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
51 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> 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,6 +68,10 @@
64 import ${entityName}Modal from './components/${entityName}Modal.vue' 68 import ${entityName}Modal from './components/${entityName}Modal.vue'
65 import {columns, searchFormSchema} from './${entityName}.data'; 69 import {columns, searchFormSchema} from './${entityName}.data';
66 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; 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 <#if list_need_category> 75 <#if list_need_category>
68 import { loadCategoryData } from '/@/api/common/api' 76 import { loadCategoryData } from '/@/api/common/api'
69 import { getAuthCache, setAuthCache } from '/@/utils/auth'; 77 import { getAuthCache, setAuthCache } from '/@/utils/auth';
@@ -84,6 +92,17 @@ @@ -84,6 +92,17 @@
84 schemas: searchFormSchema, 92 schemas: searchFormSchema,
85 autoSubmitOnEnter:true, 93 autoSubmitOnEnter:true,
86 showAdvancedButton:true, 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 fieldMapToTime: [ 106 fieldMapToTime: [
88 <#list columns as po> 107 <#list columns as po>
89 <#if po.isQuery=='Y'> 108 <#if po.isQuery=='Y'>
@@ -100,6 +119,7 @@ @@ -100,6 +119,7 @@
100 }, 119 },
101 actionColumn: { 120 actionColumn: {
102 width: 120, 121 width: 120,
  122 + fixed:'right'
103 }, 123 },
104 }, 124 },
105 exportConfig: { 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 import {BasicColumn} from '/@/components/Table'; 2 import {BasicColumn} from '/@/components/Table';
2 import {FormSchema} from '/@/components/Table'; 3 import {FormSchema} from '/@/components/Table';
3 import { rules} from '/@/utils/helper/validator'; 4 import { rules} from '/@/utils/helper/validator';
@@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [ @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [
24 slots: { customRender: 'htmlSlot' }, 25 slots: { customRender: 'htmlSlot' },
25 <#elseif po.classType=='pca'> 26 <#elseif po.classType=='pca'>
26 dataIndex: '${po.fieldName}', 27 dataIndex: '${po.fieldName}',
27 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 28 + slots: { customRender: 'pcaSlot' },
28 <#elseif po.classType=='file'> 29 <#elseif po.classType=='file'>
29 dataIndex: '${po.fieldName}', 30 dataIndex: '${po.fieldName}',
30 slots: { customRender: 'fileSlot' }, 31 slots: { customRender: 'fileSlot' },
@@ -56,7 +57,7 @@ export const columns: BasicColumn[] = [ @@ -56,7 +57,7 @@ export const columns: BasicColumn[] = [
56 return render.renderCategoryTree(text,'${po.dictField?default("")}') 57 return render.renderCategoryTree(text,'${po.dictField?default("")}')
57 }, 58 },
58 <#else> 59 <#else>
59 - customRender: (text, record) => (text ? record['${po.dictText}'] : '') 60 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
60 </#if> 61 </#if>
61 <#else> 62 <#else>
62 dataIndex: '${po.fieldName}' 63 dataIndex: '${po.fieldName}'
@@ -83,7 +84,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -83,7 +84,7 @@ export const searchFormSchema: FormSchema[] = [
83 <#if po.queryMode=='single'> 84 <#if po.queryMode=='single'>
84 { 85 {
85 label: "${po.filedComment}", 86 label: "${po.filedComment}",
86 - field: "${po.fieldName}", 87 + field: ${autoStringSuffix(po)},
87 <#if po.classType=='sel_search'> 88 <#if po.classType=='sel_search'>
88 component: 'JSearchSelect', 89 component: 'JSearchSelect',
89 componentProps:{ 90 componentProps:{
@@ -94,17 +95,23 @@ export const searchFormSchema: FormSchema[] = [ @@ -94,17 +95,23 @@ export const searchFormSchema: FormSchema[] = [
94 <#elseif po.classType=='switch'> 95 <#elseif po.classType=='switch'>
95 component: 'JSwitch', 96 component: 'JSwitch',
96 componentProps:{ 97 componentProps:{
  98 + query:true,
97 <#if po.dictField != 'is_open'> 99 <#if po.dictField != 'is_open'>
98 - options:"${po.dictField}" 100 + options:${po.dictField}
99 </#if> 101 </#if>
100 }, 102 },
101 <#elseif po.classType=='sel_depart'> 103 <#elseif po.classType=='sel_depart'>
102 component: 'JSelectDept', 104 component: 'JSelectDept',
103 <#elseif po.classType=='list_multi'> 105 <#elseif po.classType=='list_multi'>
104 - component: 'JMultiSelectTag',//暂无该组件 106 + component: 'JSelectMultiple',
105 componentProps:{ 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 <#elseif po.classType=='cat_tree'> 115 <#elseif po.classType=='cat_tree'>
109 component: 'JCategorySelect', 116 component: 'JCategorySelect',
110 componentProps:{ 117 componentProps:{
@@ -117,19 +124,15 @@ export const searchFormSchema: FormSchema[] = [ @@ -117,19 +124,15 @@ export const searchFormSchema: FormSchema[] = [
117 componentProps: { 124 componentProps: {
118 showTime:true 125 showTime:true
119 }, 126 },
  127 + <#elseif po.classType =='time'>
  128 + component: 'TimePicker',
  129 + componentProps: {
  130 + valueFormat: 'HH:mm:ss'
  131 + },
120 <#elseif po.classType=='pca'> 132 <#elseif po.classType=='pca'>
121 component: 'JAreaLinkage', 133 component: 'JAreaLinkage',
122 <#elseif po.classType=='popup'> 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 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> 136 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
134 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> 137 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
135 component: 'JDictSelectTag', 138 component: 'JDictSelectTag',
@@ -156,6 +159,8 @@ export const searchFormSchema: FormSchema[] = [ @@ -156,6 +159,8 @@ export const searchFormSchema: FormSchema[] = [
156 componentProps: { 159 componentProps: {
157 showTime:true 160 showTime:true
158 }, 161 },
  162 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  163 + component: 'JRangeNumber',
159 <#else> 164 <#else>
160 component: 'Input', //TODO 范围查询 165 component: 'Input', //TODO 范围查询
161 </#if> 166 </#if>
@@ -188,27 +193,22 @@ export const formSchema: FormSchema[] = [ @@ -188,27 +193,22 @@ export const formSchema: FormSchema[] = [
188 </#if> 193 </#if>
189 { 194 {
190 label: '${po.filedComment}', 195 label: '${po.filedComment}',
191 - field: '${po.fieldName}', 196 + field: ${autoStringSuffix(po)},
192 <#if po.classType =='date'> 197 <#if po.classType =='date'>
193 component: 'DatePicker', 198 component: 'DatePicker',
194 - <#elseif po.fieldType =='datetime'> 199 + <#elseif po.classType =='datetime'>
195 component: 'DatePicker', 200 component: 'DatePicker',
196 componentProps: { 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 component: 'TimePicker', 206 component: 'TimePicker',
  207 + componentProps: {
  208 + valueFormat: 'HH:mm:ss'
  209 + },
201 <#elseif po.classType =='popup'> 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 <#elseif po.classType =='sel_depart'> 212 <#elseif po.classType =='sel_depart'>
213 component: 'JSelectDept', 213 component: 'JSelectDept',
214 <#elseif po.classType =='switch'> 214 <#elseif po.classType =='switch'>
@@ -230,14 +230,14 @@ export const formSchema: FormSchema[] = [ @@ -230,14 +230,14 @@ export const formSchema: FormSchema[] = [
230 labelKey:'realname', 230 labelKey:'realname',
231 }, 231 },
232 <#elseif po.classType =='textarea'> 232 <#elseif po.classType =='textarea'>
233 - component: 'InputTextArea',//TODO 注意string转换问题 233 + component: 'InputTextArea',
234 <#elseif po.classType=='list' || po.classType=='radio'> 234 <#elseif po.classType=='list' || po.classType=='radio'>
235 component: 'JDictSelectTag', 235 component: 'JDictSelectTag',
236 componentProps:{ 236 componentProps:{
237 dictCode:"${form_field_dictCode}" 237 dictCode:"${form_field_dictCode}"
238 }, 238 },
239 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 239 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
240 - component: 'JMultiSelectTag',//TODO 暂无该组件 240 + component: 'JSelectMultiple',
241 componentProps:{ 241 componentProps:{
242 dictCode:"${form_field_dictCode}" 242 dictCode:"${form_field_dictCode}"
243 }, 243 },
@@ -272,7 +272,7 @@ export const formSchema: FormSchema[] = [ @@ -272,7 +272,7 @@ export const formSchema: FormSchema[] = [
272 </#if> 272 </#if>
273 }, 273 },
274 <#elseif po.classType=='umeditor'> 274 <#elseif po.classType=='umeditor'>
275 - component: 'JCodeEditor', //TODO String后缀暂未添加 275 + component: 'JEditor',
276 <#elseif po.classType == 'sel_tree'> 276 <#elseif po.classType == 'sel_tree'>
277 component: 'JTreeSelect', 277 component: 'JTreeSelect',
278 componentProps:{ 278 componentProps:{
@@ -290,7 +290,6 @@ export const formSchema: FormSchema[] = [ @@ -290,7 +290,6 @@ export const formSchema: FormSchema[] = [
290 <#else> 290 <#else>
291 component: 'Input', 291 component: 'Input',
292 </#if> 292 </#if>
293 - <#include "/common/utils.ftl">  
294 <#if po.isShow == 'Y' && poHasCheck(po)> 293 <#if po.isShow == 'Y' && poHasCheck(po)>
295 dynamicRules: ({model,schema}) => { 294 dynamicRules: ({model,schema}) => {
296 <#if po.fieldName != 'id'> 295 <#if po.fieldName != 'id'>
@@ -304,16 +303,16 @@ export const formSchema: FormSchema[] = [ @@ -304,16 +303,16 @@ export const formSchema: FormSchema[] = [
304 </#if> 303 </#if>
305 <#-- 唯一校验 --> 304 <#-- 唯一校验 -->
306 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 307 <#-- 6到16位数字 -->
309 <#elseif fieldValidType == 'n6-16'> 308 <#elseif fieldValidType == 'n6-16'>
310 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 309 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
311 <#-- 6到16位任意字符 --> 310 <#-- 6到16位任意字符 -->
312 <#elseif fieldValidType == '*6-16'> 311 <#elseif fieldValidType == '*6-16'>
313 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 312 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
314 - <#-- 6到18位字符串 --> 313 + <#-- 6到18位字 -->
315 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 317 <#elseif fieldValidType == 'url'>
319 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 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 \ No newline at end of file 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 <template> 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 <BasicForm @register="registerForm"/> 4 <BasicForm @register="registerForm"/>
4 </BasicModal> 5 </BasicModal>
5 </template> 6 </template>
@@ -18,6 +19,7 @@ @@ -18,6 +19,7 @@
18 labelWidth: 150, 19 labelWidth: 150,
19 schemas: formSchema, 20 schemas: formSchema,
20 showActionButtonGroup: false, 21 showActionButtonGroup: false,
  22 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
21 }); 23 });
22 //表单赋值 24 //表单赋值
23 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { 25 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@@ -54,5 +56,12 @@ @@ -54,5 +56,12 @@
54 </script> 56 </script>
55 57
56 <style lang="less" scoped> 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 </style> 67 </style>
59 \ No newline at end of file 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 \ No newline at end of file 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,17 +205,14 @@ public class ${entityName}Controller {
205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); 205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
206 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); 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 String selections = request.getParameter("selections"); 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 List<String> selectionList = Arrays.asList(selections.split(",")); 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 // Step.3 组装pageList 217 // Step.3 组装pageList
221 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); 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 package ${bussiPackage}.${entityPackage}.entity; 2 package ${bussiPackage}.${entityPackage}.entity;
2 3
3 import java.io.Serializable; 4 import java.io.Serializable;
@@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 <#-- 生成字典Code --> 32 <#-- 生成字典Code -->
32 <#assign list_field_dictCode=""> 33 <#assign list_field_dictCode="">
33 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 <#if po.dictTable?default("")?trim?length gt 1> 39 <#if po.dictTable?default("")?trim?length gt 1>
39 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 <#list subTables as subTab> 2 <#list subTables as subTab>
2 #segment#${subTab.entityName}.java 3 #segment#${subTab.entityName}.java
3 package ${bussiPackage}.${entityPackage}.entity; 4 package ${bussiPackage}.${entityPackage}.entity;
@@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable { @@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable {
32 <#-- 生成字典Code --> 33 <#-- 生成字典Code -->
33 <#assign list_field_dictCode=""> 34 <#assign list_field_dictCode="">
34 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 39 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
39 <#if po.dictTable?default("")?trim?length gt 1> 40 <#if po.dictTable?default("")?trim?length gt 1>
40 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 \ No newline at end of file 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,7 +48,7 @@
48 @input="popupCallback" 48 @input="popupCallback"
49 <#if po.readonly=='Y'>disabled</#if>/> 49 <#if po.readonly=='Y'>disabled</#if>/>
50 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 52 <#elseif po.classType =='switch'>
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> 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 <#elseif po.classType =='pca'> 54 <#elseif po.classType =='pca'>
@@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
58 <#elseif po.classType =='password'> 58 <#elseif po.classType =='password'>
59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 59 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 62 <#elseif po.classType =='textarea'>
63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 <#elseif po.classType=='list' || po.classType=='radio'> 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,7 +44,7 @@
44 :multi="${po.extendParams.popupMulti?c}" 44 :multi="${po.extendParams.popupMulti?c}"
45 @input="popupCallback"/> 45 @input="popupCallback"/>
46 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 48 <#elseif po.classType =='switch'>
49 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> 49 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch>
50 <#elseif po.classType =='pca'> 50 <#elseif po.classType =='pca'>
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 <#elseif po.classType =='password'> 54 <#elseif po.classType =='password'>
55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/> 55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/>
56 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 58 <#elseif po.classType =='textarea'>
59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> 59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/>
60 <#elseif po.classType=='list' || po.classType=='radio'> 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 package ${bussiPackage}.${entityPackage}.entity; 2 package ${bussiPackage}.${entityPackage}.entity;
2 3
3 import java.io.Serializable; 4 import java.io.Serializable;
@@ -32,9 +33,9 @@ public class ${entityName} implements Serializable { @@ -32,9 +33,9 @@ public class ${entityName} implements Serializable {
32 <#-- 生成字典Code --> 33 <#-- 生成字典Code -->
33 <#assign list_field_dictCode=""> 34 <#assign list_field_dictCode="">
34 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 39 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
39 <#if po.dictTable?default("")?trim?length gt 1> 40 <#if po.dictTable?default("")?trim?length gt 1>
40 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 \ No newline at end of file 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,9 +56,9 @@
56 @input="popupCallback" 56 @input="popupCallback"
57 <#if po.readonly=='Y'>disabled</#if>/> 57 <#if po.readonly=='Y'>disabled</#if>/>
58 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 62 <#elseif po.classType =='textarea'>
63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 63 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
64 <#elseif po.classType=='list' || po.classType=='radio'> 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,6 +8,13 @@
8 <#assign hasChildrenField = po.fieldName> 8 <#assign hasChildrenField = po.fieldName>
9 </#if> 9 </#if>
10 </#list> 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 <template> 18 <template>
12 <div> 19 <div>
13 <!--引用表格--> 20 <!--引用表格-->
@@ -34,8 +41,20 @@ @@ -34,8 +41,20 @@
34 </template> 41 </template>
35 <!--操作栏--> 42 <!--操作栏-->
36 <template #action="{ record }"> 43 <template #action="{ record }">
37 - <TableAction :actions="getTableAction(record)"/> 44 + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
38 </template> 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 </BasicTable> 58 </BasicTable>
40 <!--字典弹窗--> 59 <!--字典弹窗-->
41 <${entityName}Modal @register="registerModal" @success="handleSuccess"/> 60 <${entityName}Modal @register="registerModal" @success="handleSuccess"/>
@@ -49,9 +68,12 @@ @@ -49,9 +68,12 @@
49 import {useModal} from '/@/components/Modal'; 68 import {useModal} from '/@/components/Modal';
50 import { useListPage } from '/@/hooks/system/useListPage' 69 import { useListPage } from '/@/hooks/system/useListPage'
51 import ${entityName}Modal from './components/${entityName}Modal.vue'; 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 import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api'; 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 const expandedRowKeys = ref([]); 77 const expandedRowKeys = ref([]);
56 //字典model 78 //字典model
57 const [registerModal, {openModal}] = useModal(); 79 const [registerModal, {openModal}] = useModal();
@@ -62,6 +84,36 @@ @@ -62,6 +84,36 @@
62 title: '${tableVo.ftlDescription}', 84 title: '${tableVo.ftlDescription}',
63 columns, 85 columns,
64 canResize:false, 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 actionColumn: { 117 actionColumn: {
66 width: 240, 118 width: 240,
67 }, 119 },
@@ -120,13 +172,13 @@ @@ -120,13 +172,13 @@
120 */ 172 */
121 async function batchHandleDelete() { 173 async function batchHandleDelete() {
122 const ids = selectedRowKeys.value.filter(item => !item.includes('loading')) 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 function importSuccess() { 180 function importSuccess() {
129 - reload() && (expandedRowKeys.value = []); 181 + (selectedRowKeys.value = []) && reload();
130 } 182 }
131 /** 183 /**
132 * 添加下级 184 * 添加下级
@@ -140,12 +192,16 @@ @@ -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 if (isUpdate) { 196 if (isUpdate) {
145 - //编辑回调  
146 - updateTableDataRecord(values.id, values); 197 + if (changeParent) {
  198 + reload();
  199 + } else {
  200 + // 编辑回调
  201 + updateTableDataRecord(values.id, values);
  202 + }
147 } else { 203 } else {
148 - if(!values['${pidFieldName}']){ 204 + if(!values['id'] || !values['${pidFieldName}']){
149 //新增根节点 205 //新增根节点
150 reload(); 206 reload();
151 }else{ 207 }else{
@@ -264,18 +320,28 @@ @@ -264,18 +320,28 @@
264 onClick: handleEdit.bind(null, record), 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 label: '添加下级', 323 label: '添加下级',
275 onClick: handleAddSub.bind(null, {${pidFieldName}: record.id}), 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 </script> 345 </script>
280 346
281 <style scoped> 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,7 +6,6 @@ enum Api {
6 save='/${entityPackage}/${entityName?uncap_first}/add', 6 save='/${entityPackage}/${entityName?uncap_first}/add',
7 edit='/${entityPackage}/${entityName?uncap_first}/edit', 7 edit='/${entityPackage}/${entityName?uncap_first}/edit',
8 delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete', 8 delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete',
9 - deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',  
10 importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel', 9 importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
11 exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls', 10 exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
12 loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot', 11 loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot',
@@ -49,7 +48,7 @@ export const batchDelete${entityName} = (params, handleSuccess) =&gt; { @@ -49,7 +48,7 @@ export const batchDelete${entityName} = (params, handleSuccess) =&gt; {
49 okText: '确认', 48 okText: '确认',
50 cancelText: '取消', 49 cancelText: '取消',
51 onOk: () => { 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 handleSuccess(); 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 import {BasicColumn} from '/@/components/Table'; 2 import {BasicColumn} from '/@/components/Table';
2 import {FormSchema} from '/@/components/Table'; 3 import {FormSchema} from '/@/components/Table';
3 import { rules} from '/@/utils/helper/validator'; 4 import { rules} from '/@/utils/helper/validator';
@@ -28,7 +29,7 @@ export const columns: BasicColumn[] = [ @@ -28,7 +29,7 @@ export const columns: BasicColumn[] = [
28 slots: { customRender: 'htmlSlot' }, 29 slots: { customRender: 'htmlSlot' },
29 <#elseif po.classType=='pca'> 30 <#elseif po.classType=='pca'>
30 dataIndex: '${po.fieldName}', 31 dataIndex: '${po.fieldName}',
31 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 32 + slots: { customRender: 'pcaSlot' },
32 <#elseif po.classType=='file'> 33 <#elseif po.classType=='file'>
33 dataIndex: '${po.fieldName}', 34 dataIndex: '${po.fieldName}',
34 slots: { customRender: 'fileSlot' }, 35 slots: { customRender: 'fileSlot' },
@@ -60,7 +61,7 @@ export const columns: BasicColumn[] = [ @@ -60,7 +61,7 @@ export const columns: BasicColumn[] = [
60 return render.renderCategoryTree(text,'${po.dictField?default("")}') 61 return render.renderCategoryTree(text,'${po.dictField?default("")}')
61 }, 62 },
62 <#else> 63 <#else>
63 - customRender: (text, record) => (text ? record['${po.dictText}'] : '') 64 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
64 </#if> 65 </#if>
65 <#else> 66 <#else>
66 dataIndex: '${po.fieldName}' 67 dataIndex: '${po.fieldName}'
@@ -105,9 +106,14 @@ export const searchFormSchema: FormSchema[] = [ @@ -105,9 +106,14 @@ export const searchFormSchema: FormSchema[] = [
105 <#elseif po.classType=='sel_depart'> 106 <#elseif po.classType=='sel_depart'>
106 component: 'JSelectDept', 107 component: 'JSelectDept',
107 <#elseif po.classType=='list_multi'> 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 <#elseif po.classType=='cat_tree'> 118 <#elseif po.classType=='cat_tree'>
113 component: 'JCategorySelect', 119 component: 'JCategorySelect',
@@ -124,15 +130,22 @@ export const searchFormSchema: FormSchema[] = [ @@ -124,15 +130,22 @@ export const searchFormSchema: FormSchema[] = [
124 <#elseif po.classType=='pca'> 130 <#elseif po.classType=='pca'>
125 component: 'JAreaLinkage', 131 component: 'JAreaLinkage',
126 <#elseif po.classType=='popup'> 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 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> 150 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
138 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> 151 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
@@ -160,6 +173,13 @@ export const searchFormSchema: FormSchema[] = [ @@ -160,6 +173,13 @@ export const searchFormSchema: FormSchema[] = [
160 componentProps: { 173 componentProps: {
161 showTime:true 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 <#else> 183 <#else>
164 component: 'Input', //TODO 范围查询 184 component: 'Input', //TODO 范围查询
165 </#if> 185 </#if>
@@ -192,7 +212,7 @@ export const formSchema: FormSchema[] = [ @@ -192,7 +212,7 @@ export const formSchema: FormSchema[] = [
192 </#if> 212 </#if>
193 { 213 {
194 label: '${po.filedComment}', 214 label: '${po.filedComment}',
195 - field: '${po.fieldName}', 215 + field: ${autoStringSuffix(po)},
196 <#if po.fieldDbName == tableVo.extendParams.pidField> 216 <#if po.fieldDbName == tableVo.extendParams.pidField>
197 component: 'JTreeSelect', 217 component: 'JTreeSelect',
198 componentProps: { 218 componentProps: {
@@ -203,24 +223,19 @@ export const formSchema: FormSchema[] = [ @@ -203,24 +223,19 @@ export const formSchema: FormSchema[] = [
203 }, 223 },
204 <#elseif po.classType =='date'> 224 <#elseif po.classType =='date'>
205 component: 'DatePicker', 225 component: 'DatePicker',
206 - <#elseif po.fieldType =='datetime'> 226 + <#elseif po.classType =='datetime'>
207 component: 'DatePicker', 227 component: 'DatePicker',
208 componentProps: { 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 component: 'TimePicker', 233 component: 'TimePicker',
  234 + componentProps:{
  235 + valueFormat: 'HH:mm:ss',
  236 + },
213 <#elseif po.classType =='popup'> 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 <#elseif po.classType =='sel_depart'> 239 <#elseif po.classType =='sel_depart'>
225 component: 'JSelectDept', 240 component: 'JSelectDept',
226 <#elseif po.classType =='switch'> 241 <#elseif po.classType =='switch'>
@@ -242,14 +257,14 @@ export const formSchema: FormSchema[] = [ @@ -242,14 +257,14 @@ export const formSchema: FormSchema[] = [
242 labelKey:'realname', 257 labelKey:'realname',
243 }, 258 },
244 <#elseif po.classType =='textarea'> 259 <#elseif po.classType =='textarea'>
245 - component: 'InputTextArea',//TODO 注意string转换问题 260 + component: 'InputTextArea',
246 <#elseif po.classType=='list' || po.classType=='radio'> 261 <#elseif po.classType=='list' || po.classType=='radio'>
247 component: 'JDictSelectTag', 262 component: 'JDictSelectTag',
248 componentProps:{ 263 componentProps:{
249 dictCode:"${form_field_dictCode}" 264 dictCode:"${form_field_dictCode}"
250 }, 265 },
251 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 266 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
252 - component: 'JMultiSelectTag',//TODO 暂无该组件 267 + component: 'JSelectMultiple',
253 componentProps:{ 268 componentProps:{
254 dictCode:"${form_field_dictCode}" 269 dictCode:"${form_field_dictCode}"
255 }, 270 },
@@ -284,7 +299,7 @@ export const formSchema: FormSchema[] = [ @@ -284,7 +299,7 @@ export const formSchema: FormSchema[] = [
284 </#if> 299 </#if>
285 }, 300 },
286 <#elseif po.classType=='umeditor'> 301 <#elseif po.classType=='umeditor'>
287 - component: 'JCodeEditor', //TODO String后缀暂未添加 302 + component: 'JEditor',
288 <#elseif po.classType == 'sel_tree'> 303 <#elseif po.classType == 'sel_tree'>
289 component: 'JTreeSelect', 304 component: 'JTreeSelect',
290 componentProps:{ 305 componentProps:{
@@ -318,16 +333,16 @@ export const formSchema: FormSchema[] = [ @@ -318,16 +333,16 @@ export const formSchema: FormSchema[] = [
318 </#if> 333 </#if>
319 <#-- 唯一校验 --> 334 <#-- 唯一校验 -->
320 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 337 <#-- 6到16位数字 -->
323 <#elseif fieldValidType == 'n6-16'> 338 <#elseif fieldValidType == 'n6-16'>
324 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 339 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
325 <#-- 6到16位任意字符 --> 340 <#-- 6到16位任意字符 -->
326 <#elseif fieldValidType == '*6-16'> 341 <#elseif fieldValidType == '*6-16'>
327 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 342 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
328 - <#-- 6到18位字符串 --> 343 + <#-- 6到18位字 -->
329 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 347 <#elseif fieldValidType == 'url'>
333 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 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 \ No newline at end of file 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 <#assign pidFieldName = ""> 2 <#assign pidFieldName = "">
2 <#assign hasChildrenField = ""> 3 <#assign hasChildrenField = "">
3 <#list originalColumns as po> 4 <#list originalColumns as po>
@@ -9,7 +10,7 @@ @@ -9,7 +10,7 @@
9 </#if> 10 </#if>
10 </#list> 11 </#list>
11 <template> 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 <BasicForm @register="registerForm"/> 14 <BasicForm @register="registerForm"/>
14 </BasicModal> 15 </BasicModal>
15 </template> 16 </template>
@@ -24,10 +25,13 @@ @@ -24,10 +25,13 @@
24 const isUpdate = ref(true); 25 const isUpdate = ref(true);
25 const expandedRowKeys = ref([]); 26 const expandedRowKeys = ref([]);
26 const treeData = ref([]); 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 schemas: formSchema, 32 schemas: formSchema,
30 showActionButtonGroup: false, 33 showActionButtonGroup: false,
  34 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
31 labelCol: { 35 labelCol: {
32 xs: { span: 24 }, 36 xs: { span: 24 },
33 sm: { span: 4 }, 37 sm: { span: 4 },
@@ -42,16 +46,21 @@ @@ -42,16 +46,21 @@
42 //重置表单 46 //重置表单
43 await resetFields(); 47 await resetFields();
44 expandedRowKeys.value = []; 48 expandedRowKeys.value = [];
45 - setModalProps({confirmLoading: false, minHeight: 80}); 49 + setModalProps({confirmLoading: false, minHeight: 80 ,showOkBtn: !!!data?.hideFooter});
46 isUpdate.value = !!data?.isUpdate; 50 isUpdate.value = !!data?.isUpdate;
47 if (data?.record) { 51 if (data?.record) {
  52 + model = data.record;
48 //表单赋值 53 //表单赋值
49 await setFieldsValue({ 54 await setFieldsValue({
50 ...data.record, 55 ...data.record,
51 }); 56 });
  57 + } else {
  58 + model = null;
52 } 59 }
53 //父级节点树信息 60 //父级节点树信息
54 treeData.value = await loadTreeData({'async': false,'pcode':''}); 61 treeData.value = await loadTreeData({'async': false,'pcode':''});
  62 + // 隐藏底部时禁用整个表单
  63 + setProps({ disabled: !!data?.hideFooter })
55 }); 64 });
56 //设置标题 65 //设置标题
57 const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑')); 66 const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
@@ -85,9 +94,25 @@ @@ -85,9 +94,25 @@
85 //展开的节点信息 94 //展开的节点信息
86 await getExpandKeysByPid(values['${pidFieldName}'],unref(treeData)) 95 await getExpandKeysByPid(values['${pidFieldName}'],unref(treeData))
87 //刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息) 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 } finally { 104 } finally {
90 setModalProps({confirmLoading: false}); 105 setModalProps({confirmLoading: false});
91 } 106 }
92 } 107 }
93 </script> 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 \ No newline at end of file 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 \ No newline at end of file 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 package ${bussiPackage}.${entityPackage}.entity; 2 package ${bussiPackage}.${entityPackage}.entity;
2 3
3 import java.io.Serializable; 4 import java.io.Serializable;
@@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 <#-- 生成字典Code --> 32 <#-- 生成字典Code -->
32 <#assign list_field_dictCode=""> 33 <#assign list_field_dictCode="">
33 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 <#if po.dictTable?default("")?trim?length gt 1> 39 <#if po.dictTable?default("")?trim?length gt 1>
39 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 <#list subTables as subTab> 2 <#list subTables as subTab>
2 #segment#${subTab.entityName}.java 3 #segment#${subTab.entityName}.java
3 package ${bussiPackage}.${entityPackage}.entity; 4 package ${bussiPackage}.${entityPackage}.entity;
@@ -65,7 +66,8 @@ public class ${subTab.entityName} implements Serializable { @@ -65,7 +66,8 @@ public class ${subTab.entityName} implements Serializable {
65 @Dict(dicCode = "id",dicText = "name",dictTable = "sys_category") 66 @Dict(dicCode = "id",dicText = "name",dictTable = "sys_category")
66 </#if> 67 </#if>
67 <#if po.classType =='sel_depart'> 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 </#if> 71 </#if>
70 <#-- 大字段转换 --> 72 <#-- 大字段转换 -->
71 <#include "/common/blob.ftl"> 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,7 +193,7 @@
193 <#assign sub_seq=1> 193 <#assign sub_seq=1>
194 <#list subTables as sub> 194 <#list subTables as sub>
195 <a-tab-pane tab="${sub.ftlDescription}" key="${sub_seq}" <#if sub_seq gt 1>forceRender</#if>> 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 </a-tab-pane> 197 </a-tab-pane>
198 <#assign sub_seq=sub_seq+1> 198 <#assign sub_seq=sub_seq+1>
199 </#list> 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 \ No newline at end of file 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,7 +44,7 @@
44 @input="popupCallback" 44 @input="popupCallback"
45 <#if po.readonly=='Y'>disabled</#if>/> 45 <#if po.readonly=='Y'>disabled</#if>/>
46 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 48 <#elseif po.classType =='switch'>
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> 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 <#elseif po.classType =='pca'> 50 <#elseif po.classType =='pca'>
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 <#elseif po.classType =='password'> 54 <#elseif po.classType =='password'>
55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 55 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
56 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 58 <#elseif po.classType =='textarea'>
59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 59 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
60 <#elseif po.classType=='list' || po.classType=='radio'> 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,7 +46,7 @@
46 @input="popupCallback" 46 @input="popupCallback"
47 <#if po.readonly=='Y'>disabled</#if>/> 47 <#if po.readonly=='Y'>disabled</#if>/>
48 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 50 <#elseif po.classType =='switch'>
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> 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 <#elseif po.classType =='pca'> 52 <#elseif po.classType =='pca'>
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 <#elseif po.classType =='password'> 56 <#elseif po.classType =='password'>
57 <a-input-password v-model="model.${po.fieldName}"placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 57 <a-input-password v-model="model.${po.fieldName}"placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
58 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 60 <#elseif po.classType =='textarea'>
61 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 61 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
62 <#elseif po.classType=='list' || po.classType=='radio'> 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,6 +46,10 @@
46 <template #htmlSlot="{text}"> 46 <template #htmlSlot="{text}">
47 <div v-html="text"></div> 47 <div v-html="text"></div>
48 </template> 48 </template>
  49 + <!--省市区字段回显插槽-->
  50 + <template #pcaSlot="{text}">
  51 + {{ getAreaTextByCode(text) }}
  52 + </template>
49 <template #fileSlot="{text}"> 53 <template #fileSlot="{text}">
50 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> 54 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
51 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> 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,6 +81,10 @@
77 </#list> 81 </#list>
78 import {columns, searchFormSchema} from './${entityName}.data'; 82 import {columns, searchFormSchema} from './${entityName}.data';
79 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; 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 <#if list_need_category> 88 <#if list_need_category>
81 import { loadCategoryData } from '/@/api/common/api' 89 import { loadCategoryData } from '/@/api/common/api'
82 import { getAuthCache, setAuthCache } from '/@/utils/auth'; 90 import { getAuthCache, setAuthCache } from '/@/utils/auth';
@@ -94,6 +102,17 @@ @@ -94,6 +102,17 @@
94 rowSelection: {type: 'radio'}, 102 rowSelection: {type: 'radio'},
95 formConfig: { 103 formConfig: {
96 schemas: searchFormSchema, 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 fieldMapToTime: [ 116 fieldMapToTime: [
98 <#list columns as po> 117 <#list columns as po>
99 <#if po.isQuery=='Y'> 118 <#if po.isQuery=='Y'>
@@ -108,14 +127,15 @@ @@ -108,14 +127,15 @@
108 </#list> 127 </#list>
109 ], 128 ],
110 }, 129 },
111 - actionColumn: { 130 + actionColumn: {
112 width: 120, 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 exportConfig: { 140 exportConfig: {
121 name:"${tableVo.ftlDescription}", 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 import {BasicColumn} from '/@/components/Table'; 2 import {BasicColumn} from '/@/components/Table';
2 import {FormSchema} from '/@/components/Table'; 3 import {FormSchema} from '/@/components/Table';
3 import { rules} from '/@/utils/helper/validator'; 4 import { rules} from '/@/utils/helper/validator';
@@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [ @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [
24 slots: { customRender: 'htmlSlot' }, 25 slots: { customRender: 'htmlSlot' },
25 <#elseif po.classType=='pca'> 26 <#elseif po.classType=='pca'>
26 dataIndex: '${po.fieldName}', 27 dataIndex: '${po.fieldName}',
27 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 28 + slots: { customRender: 'pcaSlot' },
28 <#elseif po.classType=='file'> 29 <#elseif po.classType=='file'>
29 dataIndex: '${po.fieldName}', 30 dataIndex: '${po.fieldName}',
30 slots: { customRender: 'fileSlot' }, 31 slots: { customRender: 'fileSlot' },
@@ -91,17 +92,23 @@ export const searchFormSchema: FormSchema[] = [ @@ -91,17 +92,23 @@ export const searchFormSchema: FormSchema[] = [
91 <#elseif po.classType=='switch'> 92 <#elseif po.classType=='switch'>
92 component: 'JSwitch', 93 component: 'JSwitch',
93 componentProps:{ 94 componentProps:{
  95 + query:true,
94 <#if po.dictField != 'is_open'> 96 <#if po.dictField != 'is_open'>
95 - options:"${po.dictField}" 97 + options:${po.dictField}
96 </#if> 98 </#if>
97 }, 99 },
98 <#elseif po.classType=='sel_depart'> 100 <#elseif po.classType=='sel_depart'>
99 component: 'JSelectDept', 101 component: 'JSelectDept',
100 <#elseif po.classType=='list_multi'> 102 <#elseif po.classType=='list_multi'>
101 - component: 'JMultiSelectTag',//暂无该组件 103 + component: 'JSelectMultiple',
102 componentProps:{ 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 <#elseif po.classType=='cat_tree'> 112 <#elseif po.classType=='cat_tree'>
106 component: 'JCategorySelect', 113 component: 'JCategorySelect',
107 componentProps:{ 114 componentProps:{
@@ -117,16 +124,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -117,16 +124,7 @@ export const searchFormSchema: FormSchema[] = [
117 <#elseif po.classType=='pca'> 124 <#elseif po.classType=='pca'>
118 component: 'JAreaLinkage', 125 component: 'JAreaLinkage',
119 <#elseif po.classType=='popup'> 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 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> 128 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
131 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> 129 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
132 component: 'JDictSelectTag', 130 component: 'JDictSelectTag',
@@ -153,6 +151,8 @@ export const searchFormSchema: FormSchema[] = [ @@ -153,6 +151,8 @@ export const searchFormSchema: FormSchema[] = [
153 componentProps: { 151 componentProps: {
154 showTime:true 152 showTime:true
155 }, 153 },
  154 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  155 + component: 'JRangeNumber',
156 <#else> 156 <#else>
157 component: 'Input', //TODO 范围查询 157 component: 'Input', //TODO 范围查询
158 </#if> 158 </#if>
@@ -186,27 +186,22 @@ export const formSchema: FormSchema[] = [ @@ -186,27 +186,22 @@ export const formSchema: FormSchema[] = [
186 </#if> 186 </#if>
187 { 187 {
188 label: '${po.filedComment}', 188 label: '${po.filedComment}',
189 - field: '${po.fieldName}', 189 + field: ${autoStringSuffix(po)},
190 <#if po.classType =='date'> 190 <#if po.classType =='date'>
191 component: 'DatePicker', 191 component: 'DatePicker',
192 - <#elseif po.fieldType =='datetime'> 192 + <#elseif po.classType =='datetime'>
193 component: 'DatePicker', 193 component: 'DatePicker',
194 componentProps: { 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 component: 'TimePicker', 199 component: 'TimePicker',
  200 + componentProps: {
  201 + valueFormat: 'HH:mm:ss'
  202 + },
199 <#elseif po.classType =='popup'> 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 <#elseif po.classType =='sel_depart'> 205 <#elseif po.classType =='sel_depart'>
211 component: 'JSelectDept', 206 component: 'JSelectDept',
212 <#elseif po.classType =='switch'> 207 <#elseif po.classType =='switch'>
@@ -235,7 +230,7 @@ export const formSchema: FormSchema[] = [ @@ -235,7 +230,7 @@ export const formSchema: FormSchema[] = [
235 dictCode:"${form_field_dictCode}" 230 dictCode:"${form_field_dictCode}"
236 }, 231 },
237 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 232 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
238 - component: 'JMultiSelectTag',//TODO 暂无该组件 233 + component: 'JSelectMultiple',
239 componentProps:{ 234 componentProps:{
240 dictCode:"${form_field_dictCode}" 235 dictCode:"${form_field_dictCode}"
241 }, 236 },
@@ -270,7 +265,7 @@ export const formSchema: FormSchema[] = [ @@ -270,7 +265,7 @@ export const formSchema: FormSchema[] = [
270 </#if> 265 </#if>
271 }, 266 },
272 <#elseif po.classType=='umeditor'> 267 <#elseif po.classType=='umeditor'>
273 - component: 'JCodeEditor', //TODO String后缀暂未添加 268 + component: 'JEditor',
274 <#elseif po.classType == 'sel_tree'> 269 <#elseif po.classType == 'sel_tree'>
275 component: 'JTreeSelect', 270 component: 'JTreeSelect',
276 componentProps:{ 271 componentProps:{
@@ -302,16 +297,16 @@ export const formSchema: FormSchema[] = [ @@ -302,16 +297,16 @@ export const formSchema: FormSchema[] = [
302 </#if> 297 </#if>
303 <#-- 唯一校验 --> 298 <#-- 唯一校验 -->
304 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 301 <#-- 6到16位数字 -->
307 <#elseif fieldValidType == 'n6-16'> 302 <#elseif fieldValidType == 'n6-16'>
308 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 303 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
309 <#-- 6到16位任意字符 --> 304 <#-- 6到16位任意字符 -->
310 <#elseif fieldValidType == '*6-16'> 305 <#elseif fieldValidType == '*6-16'>
311 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 306 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
312 - <#-- 6到18位字符串 --> 307 + <#-- 6到18位字 -->
313 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 311 <#elseif fieldValidType == 'url'>
317 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 312 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
@@ -387,7 +382,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ @@ -387,7 +382,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
387 slots: { customRender: 'htmlSlot' }, 382 slots: { customRender: 'htmlSlot' },
388 <#elseif po.classType=='pca'> 383 <#elseif po.classType=='pca'>
389 dataIndex: '${po.fieldName}', 384 dataIndex: '${po.fieldName}',
390 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 385 + slots: { customRender: 'pcaSlot' },
391 <#elseif po.classType=='file'> 386 <#elseif po.classType=='file'>
392 dataIndex: '${po.fieldName}', 387 dataIndex: '${po.fieldName}',
393 slots: { customRender: 'fileSlot' }, 388 slots: { customRender: 'fileSlot' },
@@ -419,7 +414,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ @@ -419,7 +414,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
419 return render.renderCategoryTree(text,'${po.dictField?default("")}') 414 return render.renderCategoryTree(text,'${po.dictField?default("")}')
420 }, 415 },
421 <#else> 416 <#else>
422 - customRender: (text, record) => (text ? record['${po.dictText}'] : '') 417 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
423 </#if> 418 </#if>
424 <#else> 419 <#else>
425 dataIndex: '${po.fieldName}' 420 dataIndex: '${po.fieldName}'
@@ -452,27 +447,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -452,27 +447,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
452 </#if> 447 </#if>
453 { 448 {
454 label: '${po.filedComment}', 449 label: '${po.filedComment}',
455 - field: '${po.fieldName}', 450 + field: ${autoStringSuffix(po)},
456 <#if po.classType =='date'> 451 <#if po.classType =='date'>
457 component: 'DatePicker', 452 component: 'DatePicker',
458 - <#elseif po.fieldType =='datetime'> 453 + <#elseif po.classType =='datetime'>
459 component: 'DatePicker', 454 component: 'DatePicker',
460 componentProps: { 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 component: 'TimePicker', 460 component: 'TimePicker',
  461 + componentProps: {
  462 + valueFormat: 'HH:mm:ss'
  463 + },
465 <#elseif po.classType =='popup'> 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 <#elseif po.classType =='sel_depart'> 466 <#elseif po.classType =='sel_depart'>
477 component: 'JSelectDept', 467 component: 'JSelectDept',
478 <#elseif po.classType =='switch'> 468 <#elseif po.classType =='switch'>
@@ -494,14 +484,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -494,14 +484,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
494 labelKey:'realname', 484 labelKey:'realname',
495 }, 485 },
496 <#elseif po.classType =='textarea'> 486 <#elseif po.classType =='textarea'>
497 - component: 'InputTextArea',//TODO 注意string转换问题 487 + component: 'InputTextArea',
498 <#elseif po.classType=='list' || po.classType=='radio'> 488 <#elseif po.classType=='list' || po.classType=='radio'>
499 component: 'JDictSelectTag', 489 component: 'JDictSelectTag',
500 componentProps:{ 490 componentProps:{
501 dictCode:"${form_field_dictCode}" 491 dictCode:"${form_field_dictCode}"
502 }, 492 },
503 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 493 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
504 - component: 'JMultiSelectTag',//TODO 暂无该组件 494 + component: 'JSelectMultiple',
505 componentProps:{ 495 componentProps:{
506 dictCode:"${form_field_dictCode}" 496 dictCode:"${form_field_dictCode}"
507 }, 497 },
@@ -536,7 +526,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -536,7 +526,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
536 </#if> 526 </#if>
537 }, 527 },
538 <#elseif po.classType=='umeditor'> 528 <#elseif po.classType=='umeditor'>
539 - component: 'JCodeEditor', //TODO String后缀暂未添加 529 + component: 'JEditor',
540 <#elseif po.classType == 'sel_tree'> 530 <#elseif po.classType == 'sel_tree'>
541 component: 'JTreeSelect', 531 component: 'JTreeSelect',
542 componentProps:{ 532 componentProps:{
@@ -568,16 +558,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -568,16 +558,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
568 </#if> 558 </#if>
569 <#-- 唯一校验 --> 559 <#-- 唯一校验 -->
570 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 562 <#-- 6到16位数字 -->
573 <#elseif fieldValidType == 'n6-16'> 563 <#elseif fieldValidType == 'n6-16'>
574 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 564 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
575 <#-- 6到16位任意字符 --> 565 <#-- 6到16位任意字符 -->
576 <#elseif fieldValidType == '*6-16'> 566 <#elseif fieldValidType == '*6-16'>
577 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 567 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
578 - <#-- 6到18位字符串 --> 568 + <#-- 6到18位字 -->
579 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 572 <#elseif fieldValidType == 'url'>
583 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 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 \ No newline at end of file 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,6 +51,7 @@
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'; 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 import {isEmpty} from "/@/utils/is"; 52 import {isEmpty} from "/@/utils/is";
53 import {useMessage} from '/@/hooks/web/useMessage'; 53 import {useMessage} from '/@/hooks/web/useMessage';
  54 + import {downloadFile} from '/@/utils/common/renderUtils';
54 55
55 //接收主表id 56 //接收主表id
56 const mainId = inject('mainId') || ''; 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 <template> 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 <BasicForm @register="registerForm"/> 4 <BasicForm @register="registerForm"/>
4 </BasicModal> 5 </BasicModal>
5 </template> 6 </template>
@@ -18,6 +19,7 @@ @@ -18,6 +19,7 @@
18 labelWidth: 150, 19 labelWidth: 150,
19 schemas: formSchema, 20 schemas: formSchema,
20 showActionButtonGroup: false, 21 showActionButtonGroup: false,
  22 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
21 }); 23 });
22 //表单赋值 24 //表单赋值
23 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { 25 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@@ -54,5 +56,12 @@ @@ -54,5 +56,12 @@
54 </script> 56 </script>
55 57
56 <style lang="less" scoped> 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 </style> 67 </style>
59 \ No newline at end of file 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,7 +2,7 @@
2 <#list subTables as sub> 2 <#list subTables as sub>
3 #segment#${sub.entityName}Modal.vue 3 #segment#${sub.entityName}Modal.vue
4 <template> 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 <BasicForm @register="registerForm"/> 6 <BasicForm @register="registerForm"/>
7 </BasicModal> 7 </BasicModal>
8 </template> 8 </template>
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 labelWidth: 150, 24 labelWidth: 150,
25 schemas: ${sub.entityName?uncap_first}FormSchema, 25 schemas: ${sub.entityName?uncap_first}FormSchema,
26 showActionButtonGroup: false, 26 showActionButtonGroup: false,
  27 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
27 }); 28 });
28 //表单赋值 29 //表单赋值
29 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { 30 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@@ -63,4 +64,14 @@ @@ -63,4 +64,14 @@
63 } 64 }
64 } 65 }
65 </script> 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 </#list> 77 </#list>
67 \ No newline at end of file 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,17 +200,14 @@ public class ${entityName}Controller {
200 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); 200 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
201 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); 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 String selections = request.getParameter("selections"); 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 // Step.3 组装pageList 212 // Step.3 组装pageList
216 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); 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 package ${bussiPackage}.${entityPackage}.entity; 2 package ${bussiPackage}.${entityPackage}.entity;
2 3
3 import java.io.Serializable; 4 import java.io.Serializable;
@@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable {
31 <#-- 生成字典Code --> 32 <#-- 生成字典Code -->
32 <#assign list_field_dictCode=""> 33 <#assign list_field_dictCode="">
33 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 38 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
38 <#if po.dictTable?default("")?trim?length gt 1> 39 <#if po.dictTable?default("")?trim?length gt 1>
39 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 <#list subTables as subTab> 2 <#list subTables as subTab>
2 #segment#${subTab.entityName}.java 3 #segment#${subTab.entityName}.java
3 package ${bussiPackage}.${entityPackage}.entity; 4 package ${bussiPackage}.${entityPackage}.entity;
@@ -33,9 +34,9 @@ public class ${subTab.entityName} implements Serializable { @@ -33,9 +34,9 @@ public class ${subTab.entityName} implements Serializable {
33 <#-- 生成字典Code --> 34 <#-- 生成字典Code -->
34 <#assign list_field_dictCode=""> 35 <#assign list_field_dictCode="">
35 <#if po.classType='sel_user'> 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 <#elseif po.classType='sel_depart'> 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 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> 40 <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'>
40 <#if po.dictTable?default("")?trim?length gt 1> 41 <#if po.dictTable?default("")?trim?length gt 1>
41 <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> 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 \ No newline at end of file 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,7 +41,7 @@
41 @input="popupCallback" 41 @input="popupCallback"
42 <#if po.readonly=='Y'>disabled</#if>/> 42 <#if po.readonly=='Y'>disabled</#if>/>
43 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='switch'> 45 <#elseif po.classType =='switch'>
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> 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 <#elseif po.classType =='pca'> 47 <#elseif po.classType =='pca'>
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 <#elseif po.classType =='password'> 51 <#elseif po.classType =='password'>
52 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 52 <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
53 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 55 <#elseif po.classType =='textarea'>
56 <a-textarea v-decorator="[${autoStringSuffix(po)}${autoWriteRules(po)}]" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> 56 <a-textarea v-decorator="[${autoStringSuffix(po)}${autoWriteRules(po)}]" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
57 <#elseif po.classType=='list' || po.classType=='radio'> 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,9 +36,9 @@
36 <#elseif po.classType =='switch'> 36 <#elseif po.classType =='switch'>
37 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> 37 <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch>
38 <#elseif po.classType =='sel_depart'> 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 <#elseif po.classType =='sel_user'> 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 <#elseif po.classType =='textarea'> 42 <#elseif po.classType =='textarea'>
43 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> 43 <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/>
44 <#elseif po.classType=='list' || po.classType=='radio'> 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,6 +60,10 @@
60 <template #htmlSlot="{text}"> 60 <template #htmlSlot="{text}">
61 <div v-html="text"></div> 61 <div v-html="text"></div>
62 </template> 62 </template>
  63 + <!--省市区字段回显插槽-->
  64 + <template #pcaSlot="{text}">
  65 + {{ getAreaTextByCode(text) }}
  66 + </template>
63 <template #fileSlot="{text}"> 67 <template #fileSlot="{text}">
64 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> 68 <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
65 <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> 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,6 +85,10 @@
81 </#list> 85 </#list>
82 import {columns, searchFormSchema} from './${entityName}.data'; 86 import {columns, searchFormSchema} from './${entityName}.data';
83 import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; 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 <#if list_need_category> 92 <#if list_need_category>
85 import { loadCategoryData } from '/@/api/common/api' 93 import { loadCategoryData } from '/@/api/common/api'
86 import { getAuthCache, setAuthCache } from '/@/utils/auth'; 94 import { getAuthCache, setAuthCache } from '/@/utils/auth';
@@ -102,6 +110,17 @@ @@ -102,6 +110,17 @@
102 schemas: searchFormSchema, 110 schemas: searchFormSchema,
103 autoSubmitOnEnter:true, 111 autoSubmitOnEnter:true,
104 showAdvancedButton:true, 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 fieldMapToTime: [ 124 fieldMapToTime: [
106 <#list columns as po> 125 <#list columns as po>
107 <#if po.isQuery=='Y'> 126 <#if po.isQuery=='Y'>
@@ -116,9 +135,10 @@ @@ -116,9 +135,10 @@
116 </#list> 135 </#list>
117 ], 136 ],
118 }, 137 },
119 - actionColumn: { 138 + actionColumn: {
120 width: 120, 139 width: 120,
121 - }, 140 + fixed:'right'
  141 + },
122 }, 142 },
123 exportConfig: { 143 exportConfig: {
124 name:"${tableVo.ftlDescription}", 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 import {BasicColumn} from '/@/components/Table'; 2 import {BasicColumn} from '/@/components/Table';
2 import {FormSchema} from '/@/components/Table'; 3 import {FormSchema} from '/@/components/Table';
3 import { rules} from '/@/utils/helper/validator'; 4 import { rules} from '/@/utils/helper/validator';
@@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [ @@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [
25 slots: { customRender: 'htmlSlot' }, 26 slots: { customRender: 'htmlSlot' },
26 <#elseif po.classType=='pca'> 27 <#elseif po.classType=='pca'>
27 dataIndex: '${po.fieldName}', 28 dataIndex: '${po.fieldName}',
28 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 29 + slots: { customRender: 'pcaSlot' },
29 <#elseif po.classType=='file'> 30 <#elseif po.classType=='file'>
30 dataIndex: '${po.fieldName}', 31 dataIndex: '${po.fieldName}',
31 slots: { customRender: 'fileSlot' }, 32 slots: { customRender: 'fileSlot' },
@@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [ @@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [
57 return render.renderCategoryTree(text,'${po.dictField?default("")}') 58 return render.renderCategoryTree(text,'${po.dictField?default("")}')
58 }, 59 },
59 <#else> 60 <#else>
60 - customRender: (text, record) => (text ? record['${po.dictText}'] : '') 61 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
61 </#if> 62 </#if>
62 <#else> 63 <#else>
63 dataIndex: '${po.fieldName}' 64 dataIndex: '${po.fieldName}'
@@ -84,7 +85,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -84,7 +85,7 @@ export const searchFormSchema: FormSchema[] = [
84 <#if po.queryMode=='single'> 85 <#if po.queryMode=='single'>
85 { 86 {
86 label: "${po.filedComment}", 87 label: "${po.filedComment}",
87 - field: "${po.fieldName}", 88 + field: ${autoStringSuffix(po)},
88 <#if po.classType=='sel_search'> 89 <#if po.classType=='sel_search'>
89 component: 'JSearchSelect', 90 component: 'JSearchSelect',
90 componentProps:{ 91 componentProps:{
@@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [ @@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [
95 <#elseif po.classType=='switch'> 96 <#elseif po.classType=='switch'>
96 component: 'JSwitch', 97 component: 'JSwitch',
97 componentProps:{ 98 componentProps:{
  99 + query:true,
98 <#if po.dictField != 'is_open'> 100 <#if po.dictField != 'is_open'>
99 - options:"${po.dictField}" 101 + options:${po.dictField}
100 </#if> 102 </#if>
101 }, 103 },
102 <#elseif po.classType=='sel_depart'> 104 <#elseif po.classType=='sel_depart'>
103 component: 'JSelectDept', 105 component: 'JSelectDept',
104 <#elseif po.classType=='list_multi'> 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 <#elseif po.classType=='cat_tree'> 116 <#elseif po.classType=='cat_tree'>
110 component: 'JCategorySelect', 117 component: 'JCategorySelect',
@@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [
121 <#elseif po.classType=='pca'> 128 <#elseif po.classType=='pca'>
122 component: 'JAreaLinkage', 129 component: 'JAreaLinkage',
123 <#elseif po.classType=='popup'> 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 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> 132 <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
135 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> 133 <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
136 component: 'JDictSelectTag', 134 component: 'JDictSelectTag',
@@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [ @@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [
157 componentProps: { 155 componentProps: {
158 showTime:true 156 showTime:true
159 }, 157 },
  158 +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
  159 + component: 'JRangeNumber',
160 <#else> 160 <#else>
161 component: 'Input', //TODO 范围查询 161 component: 'Input', //TODO 范围查询
162 </#if> 162 </#if>
@@ -189,28 +189,23 @@ export const formSchema: FormSchema[] = [ @@ -189,28 +189,23 @@ export const formSchema: FormSchema[] = [
189 </#if> 189 </#if>
190 { 190 {
191 label: '${po.filedComment}', 191 label: '${po.filedComment}',
192 - field: '${po.fieldName}', 192 + field: ${autoStringSuffix(po)},
193 <#if po.classType =='date'> 193 <#if po.classType =='date'>
194 component: 'DatePicker', 194 component: 'DatePicker',
195 - <#elseif po.fieldType =='datetime'> 195 + <#elseif po.classType =='datetime'>
196 component: 'DatePicker', 196 component: 'DatePicker',
197 componentProps: { 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 component: 'TimePicker', 202 component: 'TimePicker',
  203 + componentProps: {
  204 + valueFormat: 'HH:mm:ss'
  205 + },
202 <#elseif po.classType =='popup'> 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 component: 'JSelectDept', 209 component: 'JSelectDept',
215 <#elseif po.classType =='switch'> 210 <#elseif po.classType =='switch'>
216 component: 'JSwitch', 211 component: 'JSwitch',
@@ -231,14 +226,14 @@ export const formSchema: FormSchema[] = [ @@ -231,14 +226,14 @@ export const formSchema: FormSchema[] = [
231 labelKey:'realname', 226 labelKey:'realname',
232 }, 227 },
233 <#elseif po.classType =='textarea'> 228 <#elseif po.classType =='textarea'>
234 - component: 'InputTextArea',//TODO 注意string转换问题 229 + component: 'InputTextArea',
235 <#elseif po.classType=='list' || po.classType=='radio'> 230 <#elseif po.classType=='list' || po.classType=='radio'>
236 component: 'JDictSelectTag', 231 component: 'JDictSelectTag',
237 componentProps:{ 232 componentProps:{
238 dictCode:"${form_field_dictCode}" 233 dictCode:"${form_field_dictCode}"
239 }, 234 },
240 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 235 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
241 - component: 'JMultiSelectTag',//TODO 暂无该组件 236 + component: 'JSelectMultiple',
242 componentProps:{ 237 componentProps:{
243 dictCode:"${form_field_dictCode}" 238 dictCode:"${form_field_dictCode}"
244 }, 239 },
@@ -273,7 +268,7 @@ export const formSchema: FormSchema[] = [ @@ -273,7 +268,7 @@ export const formSchema: FormSchema[] = [
273 </#if> 268 </#if>
274 }, 269 },
275 <#elseif po.classType=='umeditor'> 270 <#elseif po.classType=='umeditor'>
276 - component: 'JCodeEditor', //TODO String后缀暂未添加 271 + component: 'JEditor',
277 <#elseif po.classType == 'sel_tree'> 272 <#elseif po.classType == 'sel_tree'>
278 component: 'JTreeSelect', 273 component: 'JTreeSelect',
279 componentProps:{ 274 componentProps:{
@@ -305,16 +300,16 @@ export const formSchema: FormSchema[] = [ @@ -305,16 +300,16 @@ export const formSchema: FormSchema[] = [
305 </#if> 300 </#if>
306 <#-- 唯一校验 --> 301 <#-- 唯一校验 -->
307 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 304 <#-- 6到16位数字 -->
310 <#elseif fieldValidType == 'n6-16'> 305 <#elseif fieldValidType == 'n6-16'>
311 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 306 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
312 <#-- 6到16位任意字符 --> 307 <#-- 6到16位任意字符 -->
313 <#elseif fieldValidType == '*6-16'> 308 <#elseif fieldValidType == '*6-16'>
314 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 309 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
315 - <#-- 6到18位字符串 --> 310 + <#-- 6到18位字 -->
316 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 314 <#elseif fieldValidType == 'url'>
320 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 315 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
@@ -390,7 +385,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ @@ -390,7 +385,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
390 slots: { customRender: 'htmlSlot' }, 385 slots: { customRender: 'htmlSlot' },
391 <#elseif po.classType=='pca'> 386 <#elseif po.classType=='pca'>
392 dataIndex: '${po.fieldName}', 387 dataIndex: '${po.fieldName}',
393 - slots: { customRender: 'pcaSlot' },//TODO 未翻译 388 + slots: { customRender: 'pcaSlot' },
394 <#elseif po.classType=='file'> 389 <#elseif po.classType=='file'>
395 dataIndex: '${po.fieldName}', 390 dataIndex: '${po.fieldName}',
396 slots: { customRender: 'fileSlot' }, 391 slots: { customRender: 'fileSlot' },
@@ -422,7 +417,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ @@ -422,7 +417,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
422 return render.renderCategoryTree(text,'${po.dictField?default("")}') 417 return render.renderCategoryTree(text,'${po.dictField?default("")}')
423 }, 418 },
424 <#else> 419 <#else>
425 - customRender: (text, record) => (text ? record['${po.dictText}'] : '') 420 + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '')
426 </#if> 421 </#if>
427 <#else> 422 <#else>
428 dataIndex: '${po.fieldName}' 423 dataIndex: '${po.fieldName}'
@@ -436,10 +431,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -436,10 +431,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
436 <#assign form_cat_tree = false> 431 <#assign form_cat_tree = false>
437 <#assign form_cat_back = ""> 432 <#assign form_cat_back = "">
438 <#assign bpm_flag=false> 433 <#assign bpm_flag=false>
  434 +<#assign sub_id_exists=false>
439 <#list sub.colums as po><#rt/> 435 <#list sub.colums as po><#rt/>
440 <#if po.fieldDbName=='bpm_status'> 436 <#if po.fieldDbName=='bpm_status'>
441 <#assign bpm_flag=true> 437 <#assign bpm_flag=true>
442 </#if> 438 </#if>
  439 +<#if po.fieldDbName=='id'>
  440 + <#assign sub_id_exists=true>
  441 +</#if>
443 <#if po.isShow =='Y'> 442 <#if po.isShow =='Y'>
444 <#assign form_field_dictCode=""> 443 <#assign form_field_dictCode="">
445 <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> 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,27 +448,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
449 </#if> 448 </#if>
450 { 449 {
451 label: '${po.filedComment}', 450 label: '${po.filedComment}',
452 - field: '${po.fieldName}', 451 + field: ${autoStringSuffix(po)},
453 <#if po.classType =='date'> 452 <#if po.classType =='date'>
454 component: 'DatePicker', 453 component: 'DatePicker',
455 - <#elseif po.fieldType =='datetime'> 454 + <#elseif po.classType =='datetime'>
456 component: 'DatePicker', 455 component: 'DatePicker',
457 componentProps: { 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 component: 'TimePicker', 461 component: 'TimePicker',
  462 + componentProps: {
  463 + valueFormat: 'HH:mm:ss'
  464 + },
462 <#elseif po.classType =='popup'> 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 <#elseif po.classType =='sel_depart'> 467 <#elseif po.classType =='sel_depart'>
474 component: 'JSelectDept', 468 component: 'JSelectDept',
475 <#elseif po.classType =='switch'> 469 <#elseif po.classType =='switch'>
@@ -491,14 +485,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -491,14 +485,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
491 labelKey:'realname', 485 labelKey:'realname',
492 }, 486 },
493 <#elseif po.classType =='textarea'> 487 <#elseif po.classType =='textarea'>
494 - component: 'InputTextArea',//TODO 注意string转换问题 488 + component: 'InputTextArea',
495 <#elseif po.classType=='list' || po.classType=='radio'> 489 <#elseif po.classType=='list' || po.classType=='radio'>
496 component: 'JDictSelectTag', 490 component: 'JDictSelectTag',
497 componentProps:{ 491 componentProps:{
498 dictCode:"${form_field_dictCode}" 492 dictCode:"${form_field_dictCode}"
499 }, 493 },
500 <#elseif po.classType=='list_multi' || po.classType=='checkbox'> 494 <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
501 - component: 'JMultiSelectTag',//TODO 暂无该组件 495 + component: 'JSelectMultiple',
502 componentProps:{ 496 componentProps:{
503 dictCode:"${form_field_dictCode}" 497 dictCode:"${form_field_dictCode}"
504 }, 498 },
@@ -533,7 +527,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -533,7 +527,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
533 </#if> 527 </#if>
534 }, 528 },
535 <#elseif po.classType=='umeditor'> 529 <#elseif po.classType=='umeditor'>
536 - component: 'JCodeEditor', //TODO String后缀暂未添加 530 + component: 'JEditor',
537 <#elseif po.classType == 'sel_tree'> 531 <#elseif po.classType == 'sel_tree'>
538 component: 'JTreeSelect', 532 component: 'JTreeSelect',
539 componentProps:{ 533 componentProps:{
@@ -565,16 +559,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -565,16 +559,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
565 </#if> 559 </#if>
566 <#-- 唯一校验 --> 560 <#-- 唯一校验 -->
567 <#if fieldValidType == 'only'> 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 <#-- 6到16位数字 --> 563 <#-- 6到16位数字 -->
570 <#elseif fieldValidType == 'n6-16'> 564 <#elseif fieldValidType == 'n6-16'>
571 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, 565 { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
572 <#-- 6到16位任意字符 --> 566 <#-- 6到16位任意字符 -->
573 <#elseif fieldValidType == '*6-16'> 567 <#elseif fieldValidType == '*6-16'>
574 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, 568 { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
575 - <#-- 6到18位字符串 --> 569 + <#-- 6到18位字 -->
576 <#elseif fieldValidType == 's6-18'> 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 <#elseif fieldValidType == 'url'> 573 <#elseif fieldValidType == 'url'>
580 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, 574 { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
@@ -616,6 +610,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ @@ -616,6 +610,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
616 }, 610 },
617 </#if> 611 </#if>
618 </#list> 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 </#if> 622 </#if>
621 </#list> 623 </#list>
@@ -642,12 +644,20 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ @@ -642,12 +644,20 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
642 <#if col.readonly=='Y'> 644 <#if col.readonly=='Y'>
643 disabled:true, 645 disabled:true,
644 </#if> 646 </#if>
  647 +<#elseif col.classType =='time'>
  648 + type: JVxeTypes.time,
  649 + <#if col.readonly=='Y'>
  650 + disabled:true,
  651 + </#if>
645 <#elseif col.classType =='textarea'> 652 <#elseif col.classType =='textarea'>
646 type: JVxeTypes.textarea, 653 type: JVxeTypes.textarea,
647 <#if col.readonly=='Y'> 654 <#if col.readonly=='Y'>
648 disabled:true, 655 disabled:true,
649 </#if> 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 type: JVxeTypes.inputNumber, 661 type: JVxeTypes.inputNumber,
652 <#if col.readonly=='Y'> 662 <#if col.readonly=='Y'>
653 disabled:true, 663 disabled:true,
@@ -684,6 +694,16 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ @@ -684,6 +694,16 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
684 <#if col.readonly=='Y'> 694 <#if col.readonly=='Y'>
685 disabled:true, 695 disabled:true,
686 </#if> 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 <#elseif col.classType =='image'> 707 <#elseif col.classType =='image'>
688 type: JVxeTypes.image, 708 type: JVxeTypes.image,
689 token:true, 709 token:true,
@@ -707,9 +727,9 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ @@ -707,9 +727,9 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
707 <#elseif col.classType =='switch'> 727 <#elseif col.classType =='switch'>
708 type: JVxeTypes.checkbox, 728 type: JVxeTypes.checkbox,
709 <#if col.dictField == 'is_open'> 729 <#if col.dictField == 'is_open'>
710 - customValue: ['Y', 'N'], 730 + customValue: ['Y', 'N'],
711 <#else> 731 <#else>
712 - customValue: ${col.dictField}, 732 + customValue: ${col.dictField},
713 </#if> 733 </#if>
714 <#if col.readonly=='Y'> 734 <#if col.readonly=='Y'>
715 disabled:true, 735 disabled:true,
@@ -720,18 +740,11 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ @@ -720,18 +740,11 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
720 <#else> 740 <#else>
721 <#assign popupBackFields = "${col.dictText}"> 741 <#assign popupBackFields = "${col.dictText}">
722 </#if> 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 <#else> 744 <#else>
732 - type: JVxeTypes.input, 745 + type: JVxeTypes.input,
733 <#if col.readonly=='Y'> 746 <#if col.readonly=='Y'>
734 - disabled:true, 747 + disabled:true,
735 </#if> 748 </#if>
736 </#if> 749 </#if>
737 <#if col.classType =='list_multi' || col.classType =='checkbox'> 750 <#if col.classType =='list_multi' || col.classType =='checkbox'>
@@ -754,18 +767,7 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ @@ -754,18 +767,7 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
754 defaultValue:'', 767 defaultValue:'',
755 </#if> 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 </#if> 772 </#if>
771 </#if> 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 \ No newline at end of file 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 <template> 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 <BasicForm @register="registerForm" ref="formRef"/> 4 <BasicForm @register="registerForm" ref="formRef"/>
4 <!-- 子表单区域 --> 5 <!-- 子表单区域 -->
5 <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs"> 6 <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs">
@@ -7,7 +8,7 @@ @@ -7,7 +8,7 @@
7 <#assign refKey = sub.entityName?uncap_first/> 8 <#assign refKey = sub.entityName?uncap_first/>
8 <#if sub.foreignRelationType =='1'> 9 <#if sub.foreignRelationType =='1'>
9 <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true"> 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 </a-tab-pane> 12 </a-tab-pane>
12 13
13 <#else> 14 <#else>
@@ -19,7 +20,8 @@ @@ -19,7 +20,8 @@
19 :loading="${sub.entityName?uncap_first}Table.loading" 20 :loading="${sub.entityName?uncap_first}Table.loading"
20 :columns="${sub.entityName?uncap_first}Table.columns" 21 :columns="${sub.entityName?uncap_first}Table.columns"
21 :dataSource="${sub.entityName?uncap_first}Table.dataSource" 22 :dataSource="${sub.entityName?uncap_first}Table.dataSource"
22 - :maxHeight="300" 23 + :height="340"
  24 + :disabled="formDisabled"
23 :rowNumber="true" 25 :rowNumber="true"
24 :rowSelection="true" 26 :rowSelection="true"
25 :toolbar="true" 27 :toolbar="true"
@@ -48,6 +50,7 @@ @@ -48,6 +50,7 @@
48 // Emits声明 50 // Emits声明
49 const emit = defineEmits(['register','success']); 51 const emit = defineEmits(['register','success']);
50 const isUpdate = ref(true); 52 const isUpdate = ref(true);
  53 + const formDisabled = ref(false);
51 const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]); 54 const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]);
52 <#assign hasOne2Many = false> 55 <#assign hasOne2Many = false>
53 <#assign hasOne2One = false> 56 <#assign hasOne2One = false>
@@ -77,6 +80,7 @@ @@ -77,6 +80,7 @@
77 labelWidth: 150, 80 labelWidth: 150,
78 schemas: formSchema, 81 schemas: formSchema,
79 showActionButtonGroup: false, 82 showActionButtonGroup: false,
  83 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
80 }); 84 });
81 //表单赋值 85 //表单赋值
82 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { 86 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@@ -84,6 +88,7 @@ @@ -84,6 +88,7 @@
84 await reset(); 88 await reset();
85 setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter}); 89 setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
86 isUpdate.value = !!data?.isUpdate; 90 isUpdate.value = !!data?.isUpdate;
  91 + formDisabled.value = !data?.showFooter;
87 if (unref(isUpdate)) { 92 if (unref(isUpdate)) {
88 //表单赋值 93 //表单赋值
89 await setFieldsValue({ 94 await setFieldsValue({
@@ -176,5 +181,12 @@ @@ -176,5 +181,12 @@
176 </script> 181 </script>
177 182
178 <style lang="less" scoped> 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 </style> 192 </style>
181 \ No newline at end of file 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 <#list subTables as sub> 2 <#list subTables as sub>
2 <#if sub.foreignRelationType=='1'> 3 <#if sub.foreignRelationType=='1'>
3 #segment#${sub.entityName}Form.vue 4 #segment#${sub.entityName}Form.vue
@@ -15,11 +16,18 @@ @@ -15,11 +16,18 @@
15 name:"${sub.entityName}Form", 16 name:"${sub.entityName}Form",
16 components: {BasicForm}, 17 components: {BasicForm},
17 emits:['register'], 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 labelWidth: 150, 27 labelWidth: 150,
21 schemas: ${sub.entityName?uncap_first}FormSchema, 28 schemas: ${sub.entityName?uncap_first}FormSchema,
22 showActionButtonGroup: false, 29 showActionButtonGroup: false,
  30 + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
23 }); 31 });
24 /** 32 /**
25 *初始化加载数据 33 *初始化加载数据
@@ -30,13 +38,22 @@ @@ -30,13 +38,22 @@
30 res.success && setFieldsValue({...res.result.records[0]}); 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 function getFormData(){ 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,17 +205,14 @@ public class ${entityName}Controller {
205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); 205 QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
206 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); 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 String selections = request.getParameter("selections"); 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 // Step.3 组装pageList 217 // Step.3 组装pageList
221 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); 218 List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();