暂时删除vue3模板,因为vue3前端项目未正式发布,减少大家的误解

pull/3201/head
zhangdaiscott 2021-11-08 15:25:38 +08:00
parent c767f094fc
commit 46e024bfbc
13 changed files with 0 additions and 2788 deletions

View File

@ -1,244 +0,0 @@
<template>
<div>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<ExcelButton :config="excelConfig"></ExcelButton>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
</div>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import ExcelButton from '/@/components/jeecg/ExcelButton.vue'
import {useModal} from '/@/components/Modal';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import {columns, searchFormSchema} from './${entityName?uncap_first}.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName?uncap_first}.api';
<#if list_need_category>
import { loadCategoryData } from '/@/api/common/api'
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload}] = useTable({
title: '${tableVo.ftlDescription}',
api: list,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode!='single'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
striped: true,
useSearchForm: true,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
actionColumn: {
width: 120,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: 'right',
},
})
/**
* excel导入导出配置
*/
const excelConfig = {
export: {
name:'${tableVo.ftlDescription}',
url: getExportUrl,
},
import: {
url: getImportUrl,
success: reload,
}
}
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 30,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
<#if list_need_category>
/**
* 初始化字典配置
*/
function initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
if(!allDictDate['${po.dictField?default("")}']){
Object.assign(allDictDate,{'${po.dictField?default("")}':res})
}
setAuthCache(DB_DICT_DATA_KEY,allDictDate)
}
})
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
</script>
<style scoped>
</style>

View File

@ -1,61 +0,0 @@
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/list',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除单个
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}

View File

@ -1,352 +0,0 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];

View File

@ -1,58 +0,0 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../${entityName?uncap_first}.data';
import {saveOrUpdate} from '../${entityName?uncap_first}.api';
// Emits声明
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({confirmLoading: false,showFooter:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -1,82 +0,0 @@
import {defHttp} from "/@/utils/http/axios";
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/rootList',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
delete${entityName} = '/sys/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot',
getChildList = '/${entityPackage}/${entityName?uncap_first}/childList',
getChildListBatch = '/${entityPackage}/${entityName?uncap_first}/getChildListBatch',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
* @param params
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除
*/
export const delete${entityName} = (params,handleSuccess) => {
return defHttp.delete({url: Api.delete${entityName}, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete${entityName} = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdateDict = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
/**
* 查询全部树形节点数据
* @param params
*/
export const loadTreeData = (params) =>
defHttp.get({url: Api.loadTreeData,params});
/**
* 查询子节点数据
* @param params
*/
export const getChildList = (params) =>
defHttp.get({url: Api.getChildList, params});
/**
* 批量查询子节点数据
* @param params
*/
export const getChildListBatch = (params) =>
defHttp.get({url: Api.getChildListBatch, params},{isTransformResponse:false});

View File

@ -1,352 +0,0 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];

View File

@ -1,87 +0,0 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/src/components/Modal';
import {BasicForm, useForm} from '/src/components/Form';
import {formSchema} from '../${entityName?uncap_first}.data';
import {loadTreeData, saveOrUpdateDict} from '../${entityName?uncap_first}.api';
// 获取emit
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const expandedRowKeys = ref([]);
const treeData = ref([]);
//表单配置
const [registerForm, {resetFields, setFieldsValue, validate, updateSchema}] = useForm({
schemas: formSchema,
showActionButtonGroup: false,
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
expandedRowKeys.value = [];
setModalProps({confirmLoading: false, minHeight: 80});
isUpdate.value = !!data?.isUpdate;
if (data?.record) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
//父级节点树信息
treeData.value = await loadTreeData({'async': false,'pcode':''});
updateSchema({
field: 'pid',
componentProps: {treeData},
});
});
//设置标题
const getTitle = computed(() => (!unref(isUpdate) ? '新增字典' : '编辑字典'));
/**
* 根据pid获取展开的节点
* @param pid
* @param arr
*/
function getExpandKeysByPid(pid,arr){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid && unref(expandedRowKeys).indexOf(pid)<0){
expandedRowKeys.value.push(arr[i].key);
getExpandKeysByPid(arr[i]['parentId'],unref(treeData))
}else{
getExpandKeysByPid(pid,arr[i].children)
}
}
}
}
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdateDict(values, isUpdate.value);
//关闭弹窗
closeModal();
//展开的节点信息
await getExpandKeysByPid(values['pid'],unref(treeData))
//刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息)
emit('success', {isUpdate: unref(isUpdate), values:{...values},expandedArr: unref(expandedRowKeys).reverse()});
} finally {
setModalProps({confirmLoading: false});
}
}
</script>

View File

@ -1,295 +0,0 @@
<template>
<div class="p-4">
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
<a-upload name="file" :showUploadList="false" :customRequest="(file)=>handleImportXls(file,getImportUrl,importSuccess)">
<a-button type="primary" preIcon="ant-design:import-outlined">导入</a-button>
</a-upload>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="handleExportXls('${tableVo.ftlDescription}管理',getExportUrl)"> 导出</a-button>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
</BasicTable>
<!--字典弹窗-->
<${entityName}Modal @register="registerModal" @success="handleSuccess"/>
</div>
</template>
<script lang="ts" setup>
//ts语法
import {ref, computed, unref, toRaw, nextTick} from 'vue';
import {BasicTable, useTable, TableAction} from '/src/components/Table';
import {useDrawer} from '/src/components/Drawer';
import ${entityName}Modal from './components/${entityName}Modal.vue';
import {useModal} from '/src/components/Modal';
import {useMethods} from '/src/hooks/system/useMethods';
import {columns} from './${entityName}.data';
import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
const checkedKeys = ref<Array<string | number>>([]);
const expandedRowKeys = ref([]);
const {handleExportXls,handleImportXls} = useMethods();
//字典model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource}] = useTable({
api: list,
rowKey: 'id',
columns,
striped: true,
useSearchForm: false,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
canResize: false,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: undefined,
},
})
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 10,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleCreate() {
openModal(true, {
isUpdate: false,
});
}
/**
* 编辑事件
*/
async function handleEdit(record) {
openModal(true, {
record,
isUpdate: true,
});
}
/**
* 详情
*/
async function handleDetail(record) {
openModal(true, {
record,
isUpdate: true,
hideFooter: true,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await delete${entityName}({id: record.id}, importSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = checkedKeys.value.filter(item => !item.includes('loading'))
await batchDelete${entityName}({ids: ids}, importSuccess);
}
/**
* 导入
*/
function importSuccess() {
reload() && (expandedRowKeys.value = []);
}
/**
* 添加下级
*/
function handleAddSub(record) {
openModal(true, {
record,
isUpdate: false,
});
}
/**
* 成功回调
*/
async function handleSuccess({isUpdate, values, expandedArr}) {
if (isUpdate) {
//编辑回调
updateTableDataRecord(values.id, values);
} else {
if(!values['pid']){
//新增根节点
reload();
}else{
//新增子集
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key)
}
}
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items)&&loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',')});
if (res.success && res.result.records.length>0) {
//已展开的数据批量子节点
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item['pid'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if(list) {
list.forEach(data => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
};
fn(getDataSource())
}
}
}
/**
* 处理数据集
*/
function getDataByResult(result){
if(result && result.length>0){
return result.map(item=>{
//判断是否标记了带有子节点
if(item["hasChild"]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
}
}
/**
*树节点展开合并
* */
async function handleExpand(expanded, record) {
// 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
if (expanded) {
expandedRowKeys.value.push(record.id)
if (record.children.length > 0 && !!record.children[0].isLoading) {
let result = await getChildList({pid: record.id});
result=result.records?result.records:result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id)
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
*操作表格后处理树节点展开合并
* */
async function expandTreeNode(key) {
let record = findTableDataRecord(key)
expandedRowKeys.value.push(key);
let result = await getChildList({pid: key});
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
updateTableDataRecord(key, record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
},
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, {pid: record.id}),
}
]
}
</script>
<style scoped>
</style>

View File

@ -1,244 +0,0 @@
<template>
<div>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<ExcelButton :config="excelConfig"></ExcelButton>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
</div>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import ExcelButton from '/@/components/jeecg/ExcelButton.vue'
import {useModal} from '/@/components/Modal';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import {columns, searchFormSchema} from './${entityName?uncap_first}.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName?uncap_first}.api';
<#if list_need_category>
import { loadCategoryData } from '/@/api/common/api'
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload}] = useTable({
title: '${tableVo.ftlDescription}',
api: list,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode!='single'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
striped: true,
useSearchForm: true,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
actionColumn: {
width: 120,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: 'right',
},
})
/**
* excel导入导出配置
*/
const excelConfig = {
export: {
name:'${tableVo.ftlDescription}',
url: getExportUrl,
},
import: {
url: getImportUrl,
success: reload,
}
}
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 30,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
<#if list_need_category>
/**
* 初始化字典配置
*/
function initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
if(!allDictDate['${po.dictField?default("")}']){
Object.assign(allDictDate,{'${po.dictField?default("")}':res})
}
setAuthCache(DB_DICT_DATA_KEY,allDictDate)
}
})
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
</script>
<style scoped>
</style>

View File

@ -1,72 +0,0 @@
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/list',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
<#list subTables as sub><#rt/>
${sub.entityName?uncap_first}List = '/${entityPackage}/${entityName?uncap_first}/query${sub.entityName}ByMainId',
</#list>
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
<#list subTables as sub><#rt/>
/**
* 查询子表数据
* @param params
*/
export const ${sub.entityName?uncap_first}List = Api.${sub.entityName?uncap_first}List;
</#list>
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除单个
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}

View File

@ -1,698 +0,0 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import {JVxeTypes,JVxeColumn} from '/@/components/jeecg/JVxeTable/types'
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
//子表单数据
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list sub.colums as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
</#if>
</#list>
//子表表格配置
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
<#assign popupBackFields = "">
<#-- 循环子表的列 开始 -->
<#list sub.colums as col><#rt/>
<#if col.isShow =='Y'>
<#if col.filedComment !='外键' >
{
title: '${col.filedComment}',
key: '${autoStringSuffixForModel(col)}',
<#if col.classType =='date'>
type: JVxeTypes.date,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='datetime'>
type: JVxeTypes.datetime,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='textarea'>
type: JVxeTypes.textarea,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif "int,decimal,double,"?contains(col.classType)>
type: JVxeTypes.inputNumber,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list' || col.classType =='radio'>
type: JVxeTypes.select,
options:[],
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list_multi' || col.classType =='checkbox'>
type: JVxeTypes.selectMultiple,
options:[],
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_search'>
type: JVxeTypes.selectSearch,
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='image'>
type: JVxeTypes.image,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='file'>
type: JVxeTypes.file,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='switch'>
type: JVxeTypes.checkbox,
<#if col.dictField == 'is_open'>
customValue: ['Y', 'N'],
<#else>
customValue: ${col.dictField},
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='popup'>
<#if popupBackFields?length gt 0>
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
<#else>
<#assign popupBackFields = "${col.dictText}">
</#if>
type: JVxeTypes.popup,
popupCode:"${col.dictTable}",
field:"${col.dictField}",
orgFields:"${col.dictField}",
destFields:"${Format.underlineToHump(col.dictText)}",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#else>
type: JVxeTypes.input,
<#if col.readonly=='Y'>
disabled:true,
</#if>
</#if>
<#if col.classType =='list_multi' || col.classType =='checkbox'>
width:"250px",
<#else>
width:"200px",
</#if>
<#if col.classType =='file'>
placeholder: '请选择文件',
<#else>
placeholder: '请输入${'$'}{title}',
</#if>
<#if col.defaultVal??>
<#if col.fieldDbType=="BigDecimal" || col.fieldDbType=="double" || col.fieldDbType=="int">
defaultValue:${col.defaultVal},
<#else>
defaultValue:"${col.defaultVal}",
</#if>
<#else>
defaultValue:'',
</#if>
<#-- 子表的校验 -->
<#assign subFieldValidType = col.fieldValidType!''>
<#-- 非空校验 -->
<#if col.nullable == 'N' || subFieldValidType == '*'>
validateRules: [{ required: true, message: '${'$'}{title}不能为空' }],
<#-- 其他情况下,只要有值就被认为是正则校验 -->
<#elseif subFieldValidType?length gt 0>
<#assign subMessage = '格式不正确'>
<#if subFieldValidType == 'only' >
<#assign subMessage = '不能重复'>
</#if>
validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }],
</#if>
},
</#if>
</#if>
</#list>
<#-- 循环子表的列 结束 -->
]
</#if>
</#list>

View File

@ -1,179 +0,0 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm" ref="formRef"/>
<!-- 子表单区域 -->
<a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs">
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form>
</a-tab-pane>
<#else>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<JVxeTable
keep-source
resizable
:ref="refKeys[${sub_index}]"
:loading="${sub.entityName?uncap_first}Table.loading"
:columns="${sub.entityName?uncap_first}Table.columns"
:dataSource="${sub.entityName?uncap_first}Table.dataSource"
:maxHeight="300"
:rowNumber="true"
:rowSelection="true"
:toolbar="true"
/>
</a-tab-pane>
</#if>
</#list>
</a-tabs>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref,reactive} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import { JVxeTable } from '/@/components/jeecg/JVxeTable'
import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts'
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
import ${sub.entityName}Form from './${sub.entityName}Form.vue'
</#if>
</#list>
import {formSchema<#list subTables as sub><#if sub.foreignRelationType =='0'>,${sub.entityName?uncap_first}Columns</#if></#list>} from '../${entityName?uncap_first}.data';
import {saveOrUpdate<#list subTables as sub>,${sub.entityName?uncap_first}List</#list>} from '../${entityName?uncap_first}.api';
import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
// Emits声明
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]);
<#assign hasOne2Many = false>
<#assign hasOne2One = false>
const activeKey = ref('${subTables[0].entityName?uncap_first}');
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
<#assign hasOne2Many = true>
const ${sub.entityName?uncap_first} = ref();
</#if>
<#if sub.foreignRelationType =='1'>
<#assign hasOne2One = true>
const ${sub.entityName?uncap_first}Form = ref();
</#if>
</#list>
const tableRefs = {<#list subTables as sub><#if sub.foreignRelationType =='0'>${sub.entityName?uncap_first}, <#assign hasOne2Many = true></#if></#list>};
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
const ${sub.entityName?uncap_first}Table = reactive({
loading: false,
dataSource: [],
columns:${sub.entityName?uncap_first}Columns
})
</#if>
</#list>
//表单配置
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await reset();
setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.initFormData(${sub.entityName?uncap_first}List,data?.record?.id)
</#if>
</#list>
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
requestSubTableData(${sub.entityName?uncap_first}List, {id:data?.record?.id}, ${sub.entityName?uncap_first}Table)
</#if>
</#list>
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
});
//方法配置
const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys<#if hasOne2One==true>,validateSubForm</#if>);
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
async function reset(){
await resetFields();
activeKey.value = ref('${subTables[0].entityName?uncap_first}');
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}Table.dataSource = [];
</#if>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.resetFields();
</#if>
</#list>
}
function classifyIntoFormData(allValues) {
let main = Object.assign({}, allValues.formValue)
return {
...main, // 展开
<#assign subManyIndex = 0>
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}List: allValues.tablesValue[${subManyIndex}].tableData,
<#assign subManyIndex = subManyIndex+1>
<#else>
${sub.entityName?uncap_first}List: ${sub.entityName?uncap_first}Form.value.getFormData(),
</#if>
</#list>
}
}
<#if hasOne2One==true>
//校验所有一对一子表表单
function validateSubForm(allValues){
return new Promise((resolve,reject)=>{
Promise.all([
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.validateForm(${sub_index}),
</#if>
</#list>
]).then(() => {
resolve(allValues)
}).catch(e => {
if (e.error === VALIDATE_FAILED) {
// 如果有未通过表单验证的子表就自动跳转到它所在的tab
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
} else {
console.error(e)
}
})
})
}
</#if>
//表单提交事件
async function requestAddOrEdit(values) {
try {
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -1,64 +0,0 @@
<#list subTables as sub>
<#if sub.foreignRelationType=='1'>
#segment#${sub.entityName}Form.vue
<template>
<BasicForm @register="registerForm"/>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
import {BasicForm, useForm} from '/@/components/Form/index';
import {${sub.entityName?uncap_first}FormSchema} from '../${entityName?uncap_first}.data';
import {defHttp} from '/@/utils/http/axios';
import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
export default defineComponent({
name:"${sub.entityName}Form",
components: {BasicForm},
emits:['register'],
setup(_,{emit}) {
const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
labelWidth: 150,
schemas: ${sub.entityName?uncap_first}FormSchema,
showActionButtonGroup: false,
});
/**
*初始化加载数据
*/
function initFormData(url,id){
if(id){
defHttp.get({url,params:{id}},{isTransformResponse:false}).then(res=>{
res.success && setFieldsValue({...res.result[0]});
})
}
}
/**
*获取表单数据
*/
function getFormData(){
return [getFieldsValue()];
}
/**
*表单校验
*/
function validateForm(index){
return new Promise((resolve, reject) => {
// 验证子表表单
validate().then(()=>{
return resolve()
}).catch(()=> {
return reject({ error: VALIDATE_FAILED ,index})
})
})
}
return {
registerForm,
resetFields,
initFormData,
getFormData,
validateForm
}
}
})
</script>
</#if>
</#list>