feat(代码生成): 支持anyline 动态获取表元数据

- 1. 支持代码生成模板 从 github获取
- 2. 重构代码生成的默认值从配置类获取
This commit is contained in:
冷冷 2024-07-15 23:17:09 +08:00
parent a90f2be1e3
commit fecc5d8bcb
18 changed files with 1296 additions and 746 deletions

View File

@ -15,6 +15,21 @@ export function list() {
}); });
} }
export function online() {
return request({
url: '/gen/template/online',
method: 'get',
});
}
export function checkVersion() {
return request({
url: '/gen/template/checkVersion',
method: 'get',
});
}
export function addObj(obj?: Object) { export function addObj(obj?: Object) {
return request({ return request({
url: '/gen/template', url: '/gen/template',

View File

@ -21,6 +21,13 @@ export const validateNull = (val: any) => {
}; };
export const rule = { export const rule = {
overLength(rule: any, value: any, callback: any) {
if (value?.length > 255) {
callback(new Error('输入内容过长,请重新输入'));
} else {
callback();
}
},
/** /**
* 线 * 线
* *

View File

@ -26,6 +26,7 @@ export default {
}, },
dictItem: { dictItem: {
index: '#', index: '#',
name: 'dict item',
importsysDictItemTip: 'import SysDictItem', importsysDictItemTip: 'import SysDictItem',
id: 'id', id: 'id',
dictId: 'dictId', dictId: 'dictId',

View File

@ -29,6 +29,7 @@ export default {
}, },
dictItem: { dictItem: {
index: '#', index: '#',
name: '字典项',
importsysDictItemTip: '导入字典项', importsysDictItemTip: '导入字典项',
id: '编号', id: '编号',
dictId: ' dictId', dictId: ' dictId',

View File

@ -1,81 +1,85 @@
<template> <template>
<el-dialog :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible" :close-on-click-modal="false" draggable> <el-dialog :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible"
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading"> :close-on-click-modal="false" draggable>
<el-row :gutter="20"> <el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-col :span="12" class="mb20"> <el-row :gutter="20">
<el-form-item :label="t('datasourceconf.dsType')" prop="dsType"> <el-col :span="12" class="mb20">
<el-select v-model="form.dsType" :placeholder="t('datasourceconf.inputdsTypeTip')"> <el-form-item :label="t('datasourceconf.dsType')" prop="dsType">
<el-option :key="item.value" :label="item.label" :value="item.value" v-for="item in ds_type"> </el-option> <el-select v-model="form.dsType" :placeholder="t('datasourceconf.inputdsTypeTip')">
</el-select> <el-option :key="item.value" :label="item.label" :value="item.value" v-for="item in ds_type"></el-option>
</el-form-item> </el-select>
</el-col> </el-form-item>
<el-col :span="12" class="mb20"> </el-col>
<el-form-item :label="t('datasourceconf.name')" prop="name"> <el-col :span="12" class="mb20">
<el-input v-model="form.name" :placeholder="t('datasourceconf.inputnameTip')" /> <el-form-item :label="t('datasourceconf.name')" prop="name">
</el-form-item> <el-input v-model="form.name" :placeholder="t('datasourceconf.inputnameTip')"/>
</el-col> </el-form-item>
<el-col :span="12" class="mb20"> </el-col>
<el-form-item :label="t('datasourceconf.username')" prop="username"> <el-col :span="12" class="mb20">
<el-input v-model="form.username" :placeholder="t('datasourceconf.inputusernameTip')" /> <el-form-item :label="t('datasourceconf.username')" prop="username">
</el-form-item> <el-input v-model="form.username" :placeholder="t('datasourceconf.inputusernameTip')"/>
</el-col> </el-form-item>
<el-col :span="12" class="mb20"> </el-col>
<el-form-item :label="t('datasourceconf.password')" prop="password"> <el-col :span="12" class="mb20">
<el-input v-model="form.password" :placeholder="t('datasourceconf.inputpasswordTip')" /> <el-form-item :label="t('datasourceconf.password')" prop="password">
</el-form-item> <el-input v-model="form.password" :placeholder="t('datasourceconf.inputpasswordTip')"/>
</el-col> </el-form-item>
<el-col :span="12" class="mb20"> </el-col>
<el-form-item :label="t('datasourceconf.confType')" prop="confType"> <el-col :span="12" class="mb20">
<el-radio-group v-model="form.confType"> <el-form-item :label="t('datasourceconf.confType')" prop="confType">
<el-radio :label="Number(item.value)" v-for="(item, index) in ds_config_type" border :key="index">{{ item.label }} </el-radio> <el-radio-group v-model="form.confType">
</el-radio-group> <el-radio :label="Number(item.value)" v-for="(item, index) in ds_config_type" border :key="index">
</el-form-item> {{ item.label }}
</el-col> </el-radio>
<el-col :span="12" class="mb20" v-if="form.confType === 0 && form.dsType === 'mssql'"> </el-radio-group>
<el-form-item :label="t('datasourceconf.instance')" prop="instance"> </el-form-item>
<el-input v-model="form.instance" :placeholder="t('datasourceconf.inputinstanceTip')" /> </el-col>
</el-form-item> <el-col :span="12" class="mb20" v-if="form.confType === 0 && form.dsType === 'mssql'">
</el-col> <el-form-item :label="t('datasourceconf.instance')" prop="instance">
<el-col :span="12" class="mb20" v-if="form.confType === 0"> <el-input v-model="form.instance" :placeholder="t('datasourceconf.inputinstanceTip')"/>
<el-form-item :label="t('datasourceconf.port')" prop="port"> </el-form-item>
<el-input-number v-model="form.port" :placeholder="t('datasourceconf.inputportTip')" /> </el-col>
</el-form-item> <el-col :span="12" class="mb20" v-if="form.confType === 0">
</el-col> <el-form-item :label="t('datasourceconf.port')" prop="port">
<el-col :span="12" class="mb20" v-if="form.confType === 0"> <el-input-number v-model="form.port" :placeholder="t('datasourceconf.inputportTip')"/>
<el-form-item :label="t('datasourceconf.host')" prop="host"> </el-form-item>
<el-input v-model="form.host" :placeholder="t('datasourceconf.inputhostTip')" /> </el-col>
</el-form-item> <el-col :span="12" class="mb20" v-if="form.confType === 0">
</el-col> <el-form-item :label="t('datasourceconf.host')" prop="host">
<el-col :span="12" class="mb20" v-if="form.confType === 0"> <el-input v-model="form.host" :placeholder="t('datasourceconf.inputhostTip')"/>
<el-form-item :label="t('datasourceconf.dsName')" prop="dsName"> </el-form-item>
<el-input v-model="form.dsName" :placeholder="t('datasourceconf.inputdsNameTip')" /> </el-col>
</el-form-item> <el-col :span="12" class="mb20" v-if="form.confType === 0">
</el-col> <el-form-item :label="t('datasourceconf.dsName')" prop="dsName">
<el-col :span="24" class="mb20" v-if="form.confType === 1"> <el-input v-model="form.dsName" :placeholder="t('datasourceconf.inputdsNameTip')"/>
<el-form-item :label="t('datasourceconf.url')" prop="url"> </el-form-item>
<el-input v-model="form.url" type="textarea" :placeholder="t('datasourceconf.inputurlTip')" /> </el-col>
</el-form-item> <el-col :span="24" class="mb20" v-if="form.confType === 1">
</el-col> <el-form-item :label="t('datasourceconf.url')" prop="url">
</el-row> <el-input v-model="form.url" type="textarea" :placeholder="t('datasourceconf.inputurlTip')"/>
</el-form> </el-form-item>
<template #footer> </el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button> <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button> <el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts" name="systemDatasourceConfDialog"> <script setup lang="ts" name="systemDatasourceConfDialog">
import { useMessage } from '/@/hooks/message'; import {useMessage} from '/@/hooks/message';
import { getObj, addObj, putObj } from '/@/api/gen/datasource'; import {getObj, addObj, putObj} from '/@/api/gen/datasource';
import { useI18n } from 'vue-i18n'; import {useI18n} from 'vue-i18n';
import { useDict } from '/@/hooks/dict'; import {useDict} from '/@/hooks/dict';
import {rule} from "/@/utils/validate";
// / // /
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);
const { t } = useI18n(); const {t} = useI18n();
// //
const dataFormRef = ref(); const dataFormRef = ref();
@ -83,23 +87,23 @@ const visible = ref(false);
const loading = ref(false); const loading = ref(false);
// //
const { ds_config_type, ds_type } = useDict('ds_config_type', 'ds_type'); const {ds_config_type, ds_type} = useDict('ds_config_type', 'ds_type');
// //
const form = reactive({ const form = reactive({
id: '', id: '',
name: '', name: '',
url: '', url: '',
username: '', username: '',
password: ('' as string) || undefined, password: ('' as string) || undefined,
createTime: '', createTime: '',
updateTime: '', updateTime: '',
dsType: '', dsType: 'mysql',
confType: 0, confType: 0,
dsName: '', dsName: '',
instance: '', instance: '',
port: 0, port: 0,
host: '', host: '',
}); });
/** /**
@ -109,80 +113,86 @@ const form = reactive({
* @param {*} callback * @param {*} callback
*/ */
const validateDsName = (_rule, value, callback) => { const validateDsName = (_rule, value, callback) => {
var re = /(?=.*[a-z])(?=.*_)/; var re = /(?=.*[a-z])(?=.*_)/;
if (value && !re.test(value)) { if (value && !re.test(value)) {
callback(new Error('数据源名称不合法, 组名_数据源名形式')); callback(new Error('数据源名称不合法, 组名_数据源名形式'));
} else { } else {
callback(); callback();
} }
}; };
// //
const dataRules = ref({ const dataRules = ref({
name: [ name: [
{ required: true, message: '别名不能为空', trigger: 'blur' }, {required: true, message: '别名不能为空', trigger: 'blur'},
{ validator: validateDsName, trigger: 'blur' }, {validator: validateDsName, trigger: 'blur'},
], ],
url: [{ required: true, message: 'jdbcurl不能为空', trigger: 'blur' }], url: [{required: true, message: 'jdbcurl不能为空', trigger: 'blur'}, {
username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }], min: 10,
password: [{ required: true, message: '密码不能为空', trigger: 'blur' }], max: 500,
dsType: [{ required: true, message: '数据库类型不能为空', trigger: 'blur' }], message: 'URL长度必须介于 10 和 500 字符之间',
confType: [{ required: true, message: '配置类型不能为空', trigger: 'blur' }], trigger: 'blur'
dsName: [{ required: true, message: '数据库名称不能为空', trigger: 'blur' }], },],
instance: [{ required: true, message: '实例不能为空', trigger: 'blur' }], username: [{ validator: rule.overLength, trigger: 'blur' },{required: true, message: '用户名不能为空', trigger: 'blur'}],
port: [{ required: true, message: '端口不能为空', trigger: 'blur' }], password: [{ validator: rule.overLength, trigger: 'blur' },{required: true, message: '密码不能为空', trigger: 'blur'}],
host: [{ required: true, message: '主机不能为空', trigger: 'blur' }], dsType: [{required: true, message: '数据库类型不能为空', trigger: 'blur'}],
confType: [{required: true, message: '配置类型不能为空', trigger: 'blur'}],
dsName: [{ validator: rule.overLength, trigger: 'blur' },{required: true, message: '数据库名称不能为空', trigger: 'blur'}],
instance: [{ validator: rule.overLength, trigger: 'blur' },{required: true, message: '实例不能为空', trigger: 'blur'}],
port: [{required: true, message: '端口不能为空', trigger: 'blur'}],
host: [{ validator: rule.overLength, trigger: 'blur' },{required: true, message: '主机不能为空', trigger: 'blur'}],
}); });
// //
const openDialog = async (id: string) => { const openDialog = async (id: string) => {
visible.value = true; visible.value = true;
form.id = ''; form.id = '';
// //
nextTick(() => { nextTick(() => {
dataFormRef.value?.resetFields(); dataFormRef.value?.resetFields();
}); });
// DatasourceConf // DatasourceConf
if (id) { if (id) {
form.id = id; form.id = id;
await getDatasourceConfData(id); await getDatasourceConfData(id);
// //
form.password = '********'; form.password = '********';
} }
}; };
// //
const onSubmit = async () => { const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {}); const valid = await dataFormRef.value.validate().catch(() => {
if (!valid) return false; });
if (!valid) return false;
form.password = form.password?.includes('******') ? undefined : form.password; form.password = form.password?.includes('******') ? undefined : form.password;
try { try {
loading.value = true; loading.value = true;
form.id ? await putObj(form) : await addObj(form); form.id ? await putObj(form) : await addObj(form);
useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText')); useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
visible.value = false; visible.value = false;
emit('refresh'); emit('refresh');
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg); useMessage().error(err.msg);
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; };
// //
const getDatasourceConfData = (id: string) => { const getDatasourceConfData = (id: string) => {
// //
return getObj(id).then((res: any) => { return getObj(id).then((res: any) => {
Object.assign(form, res.data); Object.assign(form, res.data);
}); });
}; };
// //
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
</script> </script>

View File

@ -4,13 +4,13 @@
<el-row class="ml10" v-show="showSearch"> <el-row class="ml10" v-show="showSearch">
<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef"> <el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
<el-form-item :label="$t('datasourceconf.dsName')" prop="dsName"> <el-form-item :label="$t('datasourceconf.dsName')" prop="dsName">
<el-input :placeholder="$t('datasourceconf.inputdsNameTip')" formDialogRef style="max-width: 180px" v-model="state.queryForm.dsName" /> <el-input :placeholder="$t('datasourceconf.inputdsNameTip')" v-model="state.queryForm.dsName" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="getDataList" icon="search" type="primary"> <el-button @click="getDataList" icon="search" type="primary">
{{ $t('common.queryBtn') }} {{ $t('common.queryBtn') }}
</el-button> </el-button>
<el-button @click="resetQuery" formDialogRef icon="Refresh">{{ $t('common.resetBtn') }} </el-button> <el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }} </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>

View File

@ -0,0 +1,71 @@
<template>
<el-drawer title="设计历史" v-model="visible" draggable>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%" @sort-change="sortChangeHandle">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="createTime" label="设计时间" show-overflow-tooltip />
<el-table-column label="操作" width="150">
<template #default="scope">
<el-button icon="refresh" text type="primary" @click="handleRollback(scope.row.id)">回滚</el-button>
<el-button icon="delete" text type="primary" @click="handleDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
</el-drawer>
</template>
<script setup lang="ts" name="systemFormHistoryDialog">
import { BasicTableProps, useTable } from '/@/hooks/table';
import { delFormObj, fetchFormList } from '/@/api/gen/table';
import { useMessage, useMessageBox } from '/@/hooks/message';
import { useI18n } from 'vue-i18n';
const emit = defineEmits(['refresh']);
const route = useRoute();
const { t } = useI18n();
//
const visible = ref(false);
// table hook
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchFormList,
createdIsNeed: false,
descs: ['create_time'],
});
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle } = useTable(state);
//
const handleDelete = async (id: string) => {
try {
await useMessageBox().confirm(t('common.delConfirmText'));
} catch {
return;
}
try {
await delFormObj(id);
getDataList();
useMessage().success(t('common.delSuccessText'));
} catch (err: any) {
useMessage().error(err.msg);
}
};
//
const handleRollback = (id: string) => {
emit('refresh', id);
};
//
const openDialog = () => {
const { tableName, dsName } = route.query;
visible.value = true;
state.queryForm.dsName = dsName;
state.queryForm.tableName = tableName;
getDataList();
};
//
defineExpose({
openDialog,
});
</script>

View File

@ -0,0 +1,132 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<v-form-designer ref="vfDesignerRef" :banned-widgets="bannedWidgets" :designer-config="designerConfig">
<template #customToolButtons>
<el-button link type="primary" @click="saveJsonConfig">保存</el-button>
<el-button link type="primary" @click="exportSfcConfig">导出</el-button>
<el-button link type="primary" @click="formDialogRef.openDialog()">历史</el-button>
</template>
</v-form-designer>
</div>
<form-dialog ref="formDialogRef" @refresh="handleRefresh" />
</div>
</template>
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import { fetchFormById, useFormConfSaveApi, useGeneratorVFormApi, useGeneratorVFormSfcApi } from '/@/api/gen/table';
import { useMessage, useMessageBox } from '/@/hooks/message';
import { handleBlobFile } from '/@/utils/other';
import mittBus from '/@/utils/mitt';
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const { t } = useI18n();
const route = useRoute();
const vfDesignerRef = ref();
const formDialogRef = ref();
const bannedWidgets = reactive(['tab', 'card', 'table', 'cascader']);
const designerConfig = reactive({
//
languageMenu: false,
//GitHub
externalLink: false,
//
formTemplates: false,
//
widgetNameReadonly: false,
//
eventCollapse: false,
//
clearDesignerButton: true,
//
previewFormButton: false,
//JSON
importJsonButton: false,
//JSON
exportJsonButton: false,
//
exportCodeButton: true,
//SFC
generateSFCButton: false,
});
onMounted(() => {
importJsonConfig();
});
// json
const importJsonConfig = () => {
const { tableName, dsName } = route.query;
if (tableName && dsName) {
useGeneratorVFormApi(dsName, tableName).then((res) => {
vfDesignerRef.value.loadJson(res);
});
} else {
useMessageBox()
.confirm('表单初始化失败,请重新选择表点击设计打开')
.then(() => {
// tab
mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
});
}
};
const handleRefresh = (id: string) => {
fetchFormById(id).then((res) => {
vfDesignerRef.value.loadJson(JSON.parse(res.data.formInfo));
useMessage().success(t('common.optSuccessText'));
});
};
const saveJsonConfig = () => {
const { tableName, dsName } = route.query;
if (tableName && dsName) {
//
const formJson = vfDesignerRef.value.getFormJson();
useFormConfSaveApi({
dsName,
tableName,
formInfo: JSON.stringify(formJson),
}).then(() => {
useMessage().success(t('common.optSuccessText'));
});
}
};
const exportSfcConfig = async () => {
try {
const { tableName, dsName } = route.query;
if (!tableName || !dsName) throw new Error('表名或数据源名称不能为空');
const formJson = vfDesignerRef.value.getFormJson();
const { data } = await useFormConfSaveApi({
dsName,
tableName,
formInfo: JSON.stringify(formJson),
});
const sfcRes = await useGeneratorVFormSfcApi(data.id);
handleBlobFile(sfcRes, 'form.vue');
} catch (error: any) {
useMessage().error(error.message);
}
};
</script>
<style lang="scss">
body {
margin: 0;
}
</style>

View File

@ -1,33 +1,32 @@
<template> <template>
<el-dialog :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible" width="600" <el-dialog :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible" width="600" :close-on-click-modal="false" draggable>
:close-on-click-modal="false" draggable> <el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-form-item :label="t('fieldtype.columnType')" prop="columnType"> <el-form-item :label="t('fieldtype.columnType')" prop="columnType">
<el-input v-model="form.columnType" :placeholder="t('fieldtype.inputcolumnTypeTip')"/> <el-input v-model="form.columnType" :placeholder="t('fieldtype.inputcolumnTypeTip')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('fieldtype.attrType')" prop="attrType"> <el-form-item :label="t('fieldtype.attrType')" prop="attrType">
<el-input v-model="form.attrType" :placeholder="t('fieldtype.inputattrTypeTip')"/> <el-input v-model="form.attrType" :placeholder="t('fieldtype.inputattrTypeTip')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('fieldtype.packageName')" prop="packageName"> <el-form-item :label="t('fieldtype.packageName')" prop="packageName">
<el-input v-model="form.packageName" :placeholder="t('fieldtype.inputpackageNameTip')"/> <el-input v-model="form.packageName" :placeholder="t('fieldtype.inputpackageNameTip')" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button> <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button> <el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts" name="systemFieldTypeDialog"> <script setup lang="ts" name="systemFieldTypeDialog">
import {useMessage} from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import {getObj, addObj, putObj, validateColumnType} from '/@/api/gen/fieldtype'; import { getObj, addObj, putObj, validateColumnType } from '/@/api/gen/fieldtype';
import {useI18n} from 'vue-i18n'; import { useI18n } from 'vue-i18n';
// / // /
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);
const {t} = useI18n(); const { t } = useI18n();
// //
const dataFormRef = ref(); const dataFormRef = ref();
@ -36,74 +35,73 @@ const loading = ref(false);
// //
const form = reactive({ const form = reactive({
id: '', id: '',
columnType: '', columnType: '',
attrType: '', attrType: '',
packageName: '', packageName: '',
createTime: '', createTime: '',
}); });
// //
const dataRules = ref({ const dataRules = ref({
columnType: [ columnType: [
{required: true, message: '字段类型不能为空', trigger: 'blur'}, { required: true, message: '字段类型不能为空', trigger: 'blur' },
{ {
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
validateColumnType(rule, value, callback, form.id !== ''); validateColumnType(rule, value, callback, form.id !== '');
}, },
}, },
], ],
attrType: [{required: true, message: '属性类型不能为空', trigger: 'blur'}], attrType: [{ required: true, message: '属性类型不能为空', trigger: 'blur' }],
}); });
// //
const openDialog = (id: string) => { const openDialog = (id: string) => {
visible.value = true; visible.value = true;
// //
nextTick(() => { nextTick(() => {
dataFormRef.value?.resetFields(); dataFormRef.value?.resetFields();
}); });
// idform.idFieldType // idform.idFieldType
if (id) { if (id) {
form.id = id; form.id = id;
getFieldTypeData(id); getFieldTypeData(id);
} else { } else {
// form.id // form.id
form.id = ''; form.id = '';
} }
}; };
// //
const onSubmit = async () => { const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => { const valid = await dataFormRef.value.validate().catch(() => {});
}); if (!valid) return false;
if (!valid) return false;
try { try {
loading.value = true; loading.value = true;
form.id ? await putObj(form) : await addObj(form); form.id ? await putObj(form) : await addObj(form);
useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText')); useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
visible.value = false; visible.value = false;
emit('refresh'); emit('refresh');
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg); useMessage().error(err.msg);
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; };
// //
const getFieldTypeData = (id: string) => { const getFieldTypeData = (id: string) => {
// //
getObj(id).then((res: any) => { getObj(id).then((res: any) => {
Object.assign(form, res.data); Object.assign(form, res.data);
}); });
}; };
// //
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
</script> </script>

View File

@ -2,16 +2,16 @@
<div class="layout-padding"> <div class="layout-padding">
<el-card class="layout-padding-auto" shadow="hover"> <el-card class="layout-padding-auto" shadow="hover">
<el-steps :active="active" finish-status="success" simple> <el-steps :active="active" finish-status="success" simple>
<el-step title="基础信息" @click="go(0)" /> <el-step title="基础信息" @click="go(0)"/>
<el-step title="数据修改" @click="go(1)" /> <el-step title="数据修改" @click="go(1)"/>
</el-steps> </el-steps>
</el-card> </el-card>
<el-card class="layout-padding-auto mt5" shadow="hover"> <el-card class="layout-padding-auto mt5" shadow="hover">
<!-- 生成基本信息设置 --> <!-- 生成基本信息设置 -->
<generator ref="generatorRef" :tableName="tableName" :dsName="dsName" v-if="active === 0" /> <generator ref="generatorRef" :tableName="tableName" :dsName="dsName" v-if="active === 0"/>
<!-- 字段编辑设置 --> <!-- 字段编辑设置 -->
<edit-table ref="editTableRef" :tableName="tableName" :dsName="dsName" v-if="active === 1" /> <edit-table ref="editTableRef" :tableName="tableName" :dsName="dsName" v-if="active === 1"/>
<div style="text-align: center"> <div style="text-align: center">
<el-button style="margin-top: 12px" @click="go(1)" v-if="active === 0">下一步</el-button> <el-button style="margin-top: 12px" @click="go(1)" v-if="active === 0">下一步</el-button>
@ -22,17 +22,17 @@
</el-card> </el-card>
<!-- 预览基本信息 --> <!-- 预览基本信息 -->
<preview-dialog ref="previewDialogRef" /> <preview-dialog ref="previewDialogRef"/>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useI18n } from 'vue-i18n'; import {useI18n} from 'vue-i18n';
import { useGeneratorCodeApi } from '/@/api/gen/table'; import {useGeneratorCodeApi} from '/@/api/gen/table';
import { useMessage } from '/@/hooks/message'; import {useMessage} from '/@/hooks/message';
import { downBlobFile } from '/@/utils/other'; import {downBlobFile} from '/@/utils/other';
const { t } = useI18n(); const {t} = useI18n();
const Generator = defineAsyncComponent(() => import('../table/generator.vue')); const Generator = defineAsyncComponent(() => import('../table/generator.vue'));
const EditTable = defineAsyncComponent(() => import('../table/edit.vue')); const EditTable = defineAsyncComponent(() => import('../table/edit.vue'));
const PreviewDialog = defineAsyncComponent(() => import('../table/preview.vue')); const PreviewDialog = defineAsyncComponent(() => import('../table/preview.vue'));
@ -47,19 +47,24 @@ const dsName = ref();
const editTableRef = ref(); const editTableRef = ref();
const generatorType = ref(); const generatorType = ref();
// tab
const go = async (activeNum: number) => { const go = async (activeNum: number) => {
if (active.value === activeNum) return; try {
active.value = activeNum; if (activeNum === 0) {
await editTableRef.value.submitHandle();
if (activeNum === 0) { } else if (activeNum === 1) {
await editTableRef.value.submitHandle(); const dataform = await generatorRef.value.submitHandle();
} else if (activeNum === 1) { tableId.value = dataform.id;
const dataform = await generatorRef.value.submitHandle(); generatorType.value = dataform.generatorType;
tableId.value = dataform.id; }
generatorType.value = dataform.generatorType; if (active.value === activeNum) return;
active.value = activeNum;
} catch (e) {
console.error(e);
} }
}; };
//
const preview = async () => { const preview = async () => {
await editTableRef.value.submitHandle(); await editTableRef.value.submitHandle();
previewDialogRef.value.openDialog(tableId.value); previewDialogRef.value.openDialog(tableId.value);

View File

@ -1,35 +1,35 @@
<template> <template>
<el-dialog v-model="visible" :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" width="600"> <el-dialog v-model="visible" :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" width="600">
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading"> <el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-form-item :label="t('group.groupName')" prop="groupName"> <el-form-item :label="t('group.groupName')" prop="groupName">
<el-input v-model="form.groupName" :placeholder="t('group.inputGroupNameTip')"/> <el-input v-model="form.groupName" :placeholder="t('group.inputGroupNameTip')" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('group.templateType')" prop="templateId"> <el-form-item :label="$t('group.templateType')" prop="templateId">
<el-select v-model="form.templateId" :placeholder="$t('group.selectType')" class="w100" clearable multiple> <el-select v-model="form.templateId" :placeholder="$t('group.selectType')" clearable multiple>
<el-option v-for="item in templateData" :key="item.id" :label="item.templateName" :value="item.id"/> <el-option v-for="item in templateData" :key="item.id" :label="item.templateName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="t('group.groupDesc')" prop="groupDesc"> <el-form-item :label="t('group.groupDesc')" prop="groupDesc">
<el-input type="textarea" maxlength="150" rows="3" v-model="form.groupDesc" :placeholder="t('group.inputGroupDescTip')"/> <el-input type="textarea" maxlength="100" :rows="5" v-model="form.groupDesc" :placeholder="t('group.inputGroupDescTip')" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button> <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button> <el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" name="GenGroupDialog" setup> <script lang="ts" name="GenGroupDialog" setup>
import {useMessage} from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import {addObj, getObj, putObj} from '/@/api/gen/group'; import { addObj, getObj, putObj } from '/@/api/gen/group';
import {useI18n} from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import {list as templateList} from '/@/api/gen/template'; import { list as templateList } from '/@/api/gen/template';
// / // /
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);
const {t} = useI18n(); const { t } = useI18n();
// //
const dataFormRef = ref(); const dataFormRef = ref();
@ -40,81 +40,80 @@ const templateData = ref<any[]>([]);
// //
const form = reactive({ const form = reactive({
id: '', id: '',
groupName: '', groupName: '',
groupDesc: '', groupDesc: '',
templateId: [] as string[], templateId: [] as string[],
putList: [], putList: [],
}); });
// //
const dataRules = ref({ const dataRules = ref({
groupName: [{required: true, message: '分组名称不能为空', trigger: 'blur'}], groupName: [{ required: true, message: '分组名称不能为空', trigger: 'blur' }],
templateId: [{required: true, message: '模板不能为空', trigger: 'blur'}], templateId: [{ required: true, message: '模板不能为空', trigger: 'blur' }],
}); });
const openDialog = (id: string) => { const openDialog = (id: string) => {
visible.value = true; visible.value = true;
form.id = ''; form.id = '';
// //
nextTick(() => { nextTick(() => {
dataFormRef.value.resetFields(); dataFormRef.value.resetFields();
}); });
// id genGroup // id genGroup
if (id) { if (id) {
form.id = id; form.id = id;
getgenGroupData(id); getgenGroupData(id);
} }
// //
getTemplateData(); getTemplateData();
}; };
// //
const onSubmit = async () => { const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => { const valid = await dataFormRef.value.validate().catch(() => {});
}); if (!valid) return false;
if (!valid) return false;
try { try {
loading.value = true; loading.value = true;
form.id ? await putObj(form) : await addObj(form); form.id ? await putObj(form) : await addObj(form);
useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText')); useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
visible.value = false; visible.value = false;
emit('refresh'); emit('refresh');
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg); useMessage().error(err.msg);
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; };
// //
const getgenGroupData = (id: string) => { const getgenGroupData = (id: string) => {
// //
getObj(id).then((res: any) => { getObj(id).then((res: any) => {
Object.assign(form, res.data); Object.assign(form, res.data);
form.templateId = []; form.templateId = [];
if (res.data.templateList) { if (res.data.templateList) {
let list = res.data.templateList; let list = res.data.templateList;
list.forEach((item) => { list.forEach((item) => {
form.templateId.push(item.id); form.templateId.push(item.id);
}); });
} }
}); });
}; };
// //
const getTemplateData = () => { const getTemplateData = () => {
templateList().then((res) => { templateList().then((res) => {
templateData.value = res.data; templateData.value = res.data;
}); });
}; };
// //
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
</script> </script>

View File

@ -0,0 +1,151 @@
<template>
<el-dialog title="新增字典" v-model="visible" width="600">
<el-form :model="dataForm" :rules="dataRules" label-width="100px" ref="dicDialogFormRef" v-loading="loading">
<el-form-item :label="$t('sysdict.systemFlag')" prop="systemFlag">
<el-radio-group v-model="dataForm.systemFlag">
<el-radio border :key="index" :label="item.value" v-for="(item, index) in dict_type">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('sysdict.dictType')" prop="dictType">
<el-input :placeholder="$t('sysdict.inputDictTypeTip')" :disabled="dataForm.id !== ''" clearable
v-model="dataForm.dictType"></el-input>
</el-form-item>
<el-form-item :label="$t('sysdict.description')" prop="description">
<el-input :placeholder="$t('sysdict.inputDescriptionTip')" clearable v-model="dataForm.description"></el-input>
</el-form-item>
<el-col :span="24" class="mb20">
<el-form-item :label="t('dictItem.name')" prop="columns">
<el-table :data="dataForm.columns" border style="width: 100%" max-height="500">
<el-table-column type="index" :label="t('createTable.index')" width="50">
<template #header>
<el-button icon="Plus" size="small" type="primary" circle @click="onAddItem"></el-button>
</template>
<template #default="scope">
<el-button icon="Minus" size="small" type="danger" circle
@click="handleDelete(scope.$index, scope.row)"></el-button>
</template>
</el-table-column>
<el-table-column prop="label" :label="$t('dictItem.label')" show-overflow-tooltip>
<template #default="scope">
<el-input v-model="scope.row.label" :placeholder="t('dictItem.inputLabelTip')"/>
</template>
</el-table-column>
<el-table-column prop="value" :label="$t('dictItem.itemValue')" show-overflow-tooltip>
<template #default="scope">
<el-input v-model="scope.row.value" :placeholder="t('dictItem.inputItemValueTip')"/>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button @click="onSubmit" type="primary" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" name="systemDicDialog" setup>
import {useI18n} from 'vue-i18n';
import {addItemObj, addObj, getObj, validateDictType} from '/@/api/admin/dict';
import {useDict} from '/@/hooks/dict';
import {useMessage} from '/@/hooks/message';
import {rule} from '/@/utils/validate';
// /
const emit = defineEmits(['refresh']);
const {dict_type} = useDict('dict_type');
const {t} = useI18n();
//
const dicDialogFormRef = ref();
const visible = ref(false);
const loading = ref(false);
const selectRow = ref({});
const dataForm = reactive({
id: '',
dictType: '',
description: '',
systemFlag: '0',
remarks: '',
columns: [] as any
});
const dataRules = reactive({
dictType: [
{validator: rule.overLength, trigger: 'blur'},
{required: true, message: '类型不能为空', trigger: 'blur'},
{validator: rule.validatorNameCn, trigger: 'blur'},
{
validator: (rule: any, value: any, callback: any) => {
validateDictType(rule, value, callback, dataForm.id !== '');
},
trigger: 'blur',
},
],
systemFlag: [{required: true, message: '字典类型不能为空', trigger: 'blur'}],
description: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '描述不能为空',
trigger: 'blur'
}],
columns: [{required: true, message: '字典项不能为空', trigger: 'blur'}],
});
//
const openDialog = () => {
visible.value = true;
dataForm.id = '';
nextTick(() => {
dicDialogFormRef.value?.resetFields();
});
};
//
const onSubmit = async () => {
const valid = await dicDialogFormRef.value.validate().catch(() => {
});
if (!valid) return false;
try {
loading.value = true;
//
const {data} = await addObj(dataForm);
// addItemObj
dataForm.columns.forEach(async (item: any) => {
item.dictId = data.id;
item.dictType = dataForm.dictType;
await addItemObj(item);
});
useMessage().success(t('common.addSuccessText'));
visible.value = false;
emit('refresh', dataForm.dictType);
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
let index = 1;
const onAddItem = () => {
dataForm.columns.push({sortOrder: `${index++}`});
}
const handleDelete = (index: number, row: any) => {
dataForm.columns.splice(index, 1)
}
//
defineExpose({
openDialog,
});
</script>

View File

@ -2,10 +2,11 @@
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<!-- 属性设置面板 --> <!-- 属性设置面板 -->
<el-tab-pane label="属性设置" name="field"> <el-tab-pane label="属性设置" name="field">
<sc-form-table ref="fieldTable" v-model="fieldList" :hideAdd="true" :hideDelete="true" drag-sort placeholder="暂无数据"> <sc-form-table ref="fieldTable" v-model="fieldList" :hideAdd="true" :hideDelete="true" drag-sort
placeholder="暂无数据">
<el-table-column label="主键" prop="primaryPk" width="80" show-overflow-tooltip> <el-table-column label="主键" prop="primaryPk" width="80" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.primaryPk" true-label="1" false-label="0" disabled></el-checkbox> <el-checkbox v-model="row.primaryPk" true-value="1" false-value="0" disabled></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="字段名" prop="fieldName" show-overflow-tooltip></el-table-column> <el-table-column label="字段名" prop="fieldName" show-overflow-tooltip></el-table-column>
@ -23,21 +24,25 @@
<el-table-column label="属性类型" prop="attrType" show-overflow-tooltip> <el-table-column label="属性类型" prop="attrType" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.attrType" placeholder="请选择属性类型" @change="handleChangeRow(row)"> <el-select v-model="row.attrType" placeholder="请选择属性类型" @change="handleChangeRow(row)">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="自动填充" prop="autoFill" show-overflow-tooltip> <el-table-column label="自动填充" prop="autoFill" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.autoFill" placeholder="请选择类型"> <el-select v-model="row.autoFill" placeholder="请选择类型">
<el-option v-for="item in fillList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in fillList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="字典类型" prop="fieldDict" show-overflow-tooltip> <el-table-column label="字典名称" prop="fieldDict" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.fieldDict" placeholder="请选择类型" filterable clearable :disabled="row.primaryPk === '1'"> <el-select v-model="row.fieldDict" placeholder="请选择类型" filterable clearable
<el-option v-for="item in fieldDictList" :key="item.value" :label="item.label" :value="item.value" /> :disabled="row.primaryPk === '1'">
<template #prefix>
<el-button icon="Plus" type="primary" link @click.stop="handleAddDict(row)"></el-button>
</template>
<el-option v-for="item in fieldDictList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
@ -50,30 +55,33 @@
<el-table-column label="说明" prop="fieldComment" show-overflow-tooltip></el-table-column> <el-table-column label="说明" prop="fieldComment" show-overflow-tooltip></el-table-column>
<el-table-column label="列表显示" prop="gridItem" width="100" show-overflow-tooltip> <el-table-column label="列表显示" prop="gridItem" width="100" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.gridItem" true-label="1" false-label="0" :disabled="row.primaryPk === '1'"></el-checkbox> <el-checkbox v-model="row.gridItem" true-value="1" false-value="0"
:disabled="row.primaryPk === '1'"></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否排序" prop="gridSort" width="100" show-overflow-tooltip> <el-table-column label="是否排序" prop="gridSort" width="100" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.gridSort" true-label="1" false-label="0" :disabled="row.primaryPk === '1'"></el-checkbox> <el-checkbox v-model="row.gridSort" true-value="1" false-value="0"
:disabled="row.primaryPk === '1'"></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="查询显示" prop="gridSort" width="100" show-overflow-tooltip> <el-table-column label="查询显示" prop="gridSort" width="100" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.queryItem" true-label="1" false-label="0" :disabled="row.primaryPk === '1'"></el-checkbox> <el-checkbox v-model="row.queryItem" true-value="1" false-value="0"
:disabled="row.primaryPk === '1'"></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="查询表单类型" prop="queryFormType" show-overflow-tooltip> <el-table-column label="查询表单类型" prop="queryFormType" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.queryFormType" placeholder="请选择查询表单类型" :disabled="row.primaryPk === '1'"> <el-select v-model="row.queryFormType" placeholder="请选择查询表单类型" :disabled="row.primaryPk === '1'">
<el-option v-for="item in queryTypeList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in queryTypeList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="查询方式" prop="queryType" show-overflow-tooltip> <el-table-column label="查询方式" prop="queryType" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.queryType" placeholder="请选择查询方式" :disabled="row.primaryPk === '1'"> <el-select v-model="row.queryType" placeholder="请选择查询方式" :disabled="row.primaryPk === '1'">
<el-option v-for="item in queryList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in queryList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
@ -86,38 +94,44 @@
<el-table-column label="表单类型" prop="formType" show-overflow-tooltip> <el-table-column label="表单类型" prop="formType" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.formType" placeholder="请选择表单类型" :disabled="row.primaryPk === '1'"> <el-select v-model="row.formType" placeholder="请选择表单类型" :disabled="row.primaryPk === '1'">
<el-option v-for="item in formTypeList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in formTypeList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否显示" prop="formItem" width="100" show-overflow-tooltip> <el-table-column label="是否显示" prop="formItem" width="100" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.formItem" true-label="1" false-label="0" :disabled="row.primaryPk === '1'"></el-checkbox> <el-checkbox v-model="row.formItem" true-value="1" false-value="0"
:disabled="row.primaryPk === '1'"></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="表单必填" prop="formRequired" width="100" show-overflow-tooltip> <el-table-column label="表单必填" prop="formRequired" width="100" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.formRequired" true-label="1" false-label="0" :disabled="row.primaryPk === '1'"></el-checkbox> <el-checkbox v-model="row.formRequired" true-value="1" false-value="0"
:disabled="row.primaryPk === '1'"></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="表单效验" prop="formValidator" show-overflow-tooltip> <el-table-column label="表单效验" prop="formValidator" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.formValidator" placeholder="请选择表单效验" :disabled="row.primaryPk === '1'"> <el-select v-model="row.formValidator" placeholder="请选择表单效验" :disabled="row.primaryPk === '1'">
<el-option v-for="item in formValidatorList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in formValidatorList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
</sc-form-table> </sc-form-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<!-- 新增字典 -->
<form-dialog ref="formDialogRef" @refresh="handleDictRefresh"/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useTableFieldSubmitApi, useTableApi, fetchDictList } from '/@/api/gen/table'; import {useTableFieldSubmitApi, useTableApi, fetchDictList} from '/@/api/gen/table';
import { list } from '/@/api/gen/fieldtype'; import {list} from '/@/api/gen/fieldtype';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
const scFormTable = defineAsyncComponent(() => import('/@/components/FormTable/index.vue')); const scFormTable = defineAsyncComponent(() => import('/@/components/FormTable/index.vue'));
const FormDialog = defineAsyncComponent(() => import('./add-dict.vue'));
const activeName = ref(); const activeName = ref();
const tableId = ref(''); const tableId = ref('');
@ -135,66 +149,69 @@ const visible = ref(false);
const sortable = ref() as any; const sortable = ref() as any;
const formDialogRef = ref();
const typeList = ref([]) as any; const typeList = ref([]) as any;
const fieldDictList = ref([]) as any; const fieldDictList = ref([]) as any;
const selectRow = ref();
const dsName = ref(); const dsName = ref();
const tableName = ref(); const tableName = ref();
const fieldList = ref([]); const fieldList = ref([]);
const fillList = reactive([ const fillList = reactive([
{ label: 'DEFAULT', value: 'DEFAULT' }, {label: 'DEFAULT', value: 'DEFAULT'},
{ label: 'INSERT', value: 'INSERT' }, {label: 'INSERT', value: 'INSERT'},
{ label: 'UPDATE', value: 'UPDATE' }, {label: 'UPDATE', value: 'UPDATE'},
{ label: 'INSERT_UPDATE', value: 'INSERT_UPDATE' }, {label: 'INSERT_UPDATE', value: 'INSERT_UPDATE'},
]); ]);
const queryList = reactive([ const queryList = reactive([
{ label: '=', value: '=' }, {label: '=', value: '='},
{ label: '!=', value: '!=' }, {label: '!=', value: '!='},
{ label: '>', value: '>' }, {label: '>', value: '>'},
{ label: '>=', value: '>=' }, {label: '>=', value: '>='},
{ label: '<', value: '<' }, {label: '<', value: '<'},
{ label: '<=', value: '<=' }, {label: '<=', value: '<='},
{ label: 'like', value: 'like' }, {label: 'like', value: 'like'},
{ label: 'left like', value: 'left like' }, {label: 'left like', value: 'left like'},
{ label: 'right like', value: 'right like' }, {label: 'right like', value: 'right like'},
]); ]);
const formTypeList = reactive([ const formTypeList = reactive([
{ label: '单行文本', value: 'text' }, {label: '单行文本', value: 'text'},
{ label: '多行文本', value: 'textarea' }, {label: '多行文本', value: 'textarea'},
{ label: '数字', value: 'number' }, {label: '数字', value: 'number'},
{ label: '富文本编辑器', value: 'editor' }, {label: '富文本编辑器', value: 'editor'},
{ label: '下拉框', value: 'select' }, {label: '下拉框', value: 'select'},
{ label: '单选按钮', value: 'radio' }, {label: '单选按钮', value: 'radio'},
{ label: '复选框', value: 'checkbox' }, {label: '复选框', value: 'checkbox'},
{ label: '日期', value: 'date' }, {label: '日期', value: 'date'},
{ label: '日期时间', value: 'datetime' }, {label: '日期时间', value: 'datetime'},
{ label: '文件上传', value: 'upload-file' }, {label: '文件上传', value: 'upload-file'},
{ label: '图片上传', value: 'upload-img' }, {label: '图片上传', value: 'upload-img'},
]); ]);
const queryTypeList = reactive([ const queryTypeList = reactive([
{ label: '单行文本', value: 'text' }, {label: '单行文本', value: 'text'},
{ label: '多行文本', value: 'textarea' }, {label: '多行文本', value: 'textarea'},
{ label: '数字', value: 'number' }, {label: '数字', value: 'number'},
{ label: '下拉框', value: 'select' }, {label: '下拉框', value: 'select'},
{ label: '单选按钮', value: 'radio' }, {label: '单选按钮', value: 'radio'},
{ label: '复选框', value: 'checkbox' }, {label: '复选框', value: 'checkbox'},
{ label: '日期', value: 'date' }, {label: '日期', value: 'date'},
{ label: '日期时间', value: 'datetime' }, {label: '日期时间', value: 'datetime'},
]); ]);
const formValidatorList = reactive([ const formValidatorList = reactive([
{ label: '数字', value: 'number' }, {label: '去重', value: 'duplicate'},
{ label: '字母', value: 'letter' }, {label: '数字', value: 'number'},
{ label: '字母和数字', value: 'letterAndNumber' }, {label: '字母', value: 'letter'},
{ label: '手机号码', value: 'mobilePhone' }, {label: '字母和数字', value: 'letterAndNumber'},
{ label: '字母开头,仅可包含数字', value: 'letterStartNumberIncluded' }, {label: '手机号码', value: 'mobilePhone'},
{ label: '禁止中文输入', value: 'noChinese' }, {label: '字母开头,仅可包含数字', value: 'letterStartNumberIncluded'},
{ label: '必须中文输入', value: 'chinese' }, {label: '禁止中文输入', value: 'noChinese'},
{ label: '电子邮箱', value: 'email' }, {label: '必须中文输入', value: 'chinese'},
{ label: 'URL网址', value: 'url' }, {label: '电子邮箱', value: 'email'},
{label: 'URL网址', value: 'url'},
]); ]);
const propToType = reactive({ const propToType = reactive({
@ -222,11 +239,33 @@ const propToType = reactive({
varchar: 'text', varchar: 'text',
}); });
/**
* 属性修改触发事件
* @param row
*/
const handleChangeRow = (row: any) => { const handleChangeRow = (row: any) => {
row.queryFormType = propToType[row.attrType]; row.queryFormType = propToType[row.attrType];
row.formType = propToType[row.attrType]; row.formType = propToType[row.attrType];
}; };
/**
* 添加字典
* @param row
*/
const handleAddDict = (row: object) => {
selectRow.value = row;
formDialogRef.value.openDialog();
};
/**
* 刷新字典
* @param dictType
*/
const handleDictRefresh = async (dictType: string) => {
await getDictList();
selectRow.value.fieldDict = dictType;
};
const openDialog = (dName: string, tName: string) => { const openDialog = (dName: string, tName: string) => {
visible.value = true; visible.value = true;
tableName.value = tName; tableName.value = tName;
@ -256,7 +295,7 @@ const rowDrop = () => {
sortable.value = Sortable.create(el, { sortable.value = Sortable.create(el, {
handle: '.drag-btn', handle: '.drag-btn',
onEnd: (e: any) => { onEnd: (e: any) => {
const { newIndex, oldIndex } = e; const {newIndex, oldIndex} = e;
const currRow = fieldList.value.splice(oldIndex, 1)[0]; const currRow = fieldList.value.splice(oldIndex, 1)[0];
fieldList.value.splice(newIndex, 0, currRow); fieldList.value.splice(newIndex, 0, currRow);
}, },
@ -272,7 +311,7 @@ const getTable = (dsName: string, tableName: string) => {
.then((res) => { .then((res) => {
tableId.value = res.data.id; tableId.value = res.data.id;
fieldList.value = res.data.fieldList.map((item) => { fieldList.value = res.data.fieldList.map((item) => {
item.queryFormType ? item.queryFormType : propToType[item.fieldType]; item.queryFormType ? item.queryFormType : propToType[item.fieldType];
item.formType ? item.formType : propToType[item.fieldType]; item.formType ? item.formType : propToType[item.fieldType];
return item; return item;
}); });
@ -285,24 +324,24 @@ const getTable = (dsName: string, tableName: string) => {
const getFieldTypeList = async () => { const getFieldTypeList = async () => {
typeList.value = []; typeList.value = [];
// //
const { data } = await list(); const {data} = await list();
// //
const typeMap = new Map(); const typeMap = new Map();
data.forEach((item: any) => { data.forEach((item: any) => {
const { attrType, columnType } = item; const {attrType, columnType} = item;
if (!typeMap.has(attrType)) { if (!typeMap.has(attrType)) {
typeMap.set(attrType, columnType); typeMap.set(attrType, columnType);
typeList.value.push({ label: attrType, value: attrType }); typeList.value.push({label: attrType, value: attrType});
} }
}); });
// Object // Object
typeList.value.push({ label: 'Object', value: 'Object' }); typeList.value.push({label: 'Object', value: 'Object'});
}; };
const getDictList = () => { const getDictList = () => {
fetchDictList().then((res) => { fetchDictList().then((res) => {
for (const item of res.data) { for (const item of res.data) {
fieldDictList.value.push({ label: item.description, value: item.dictType }); fieldDictList.value.push({label: item.description, value: item.dictType});
} }
}); });
}; };

View File

@ -7,7 +7,11 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb20"> <el-col :span="12" class="mb20">
<el-form-item label="说明" prop="tableComment"> <el-form-item prop="tableComment">
<template #label>
<span>注释</span>
<tip content="注释"/>
</template>
<el-input placeholder="说明" v-model="dataForm.tableComment"></el-input> <el-input placeholder="说明" v-model="dataForm.tableComment"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -31,14 +35,22 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb20"> <el-col :span="12" class="mb20">
<el-form-item label="模块名" prop="moduleName"> <el-form-item prop="moduleName">
<template #label>
<span>模块名</span>
<tip content="所属微服务模块名称,对应微服务路由前缀 (单体固定 admin"/>
</template>
<el-input placeholder="模块名" v-model="dataForm.moduleName"></el-input> <el-input placeholder="模块名" v-model="dataForm.moduleName"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12" class="mb20"> <el-col :span="12" class="mb20">
<el-form-item label="功能名" prop="functionName"> <el-form-item prop="functionName">
<template #label>
<span>功能名</span>
<tip content="对应生成的Controller @RequestMapping 请求路径"/>
</template>
<el-input placeholder="功能名" v-model="dataForm.functionName"></el-input> <el-input placeholder="功能名" v-model="dataForm.functionName"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -55,24 +67,32 @@
<el-col :span="12" class="mb20"> <el-col :span="12" class="mb20">
<el-form-item label="表单布局" prop="formLayout"> <el-form-item label="表单布局" prop="formLayout">
<el-radio-group v-model="dataForm.formLayout"> <el-radio-group v-model="dataForm.formLayout">
<el-radio border :label="1">一列</el-radio> <el-radio border :value="1">一列</el-radio>
<el-radio border :label="2">两列</el-radio> <el-radio border :value="2">两列</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb20"> <el-col :span="12" class="mb20">
<el-form-item label="生成方式" prop="generatorType"> <el-form-item label="生成方式" prop="generatorType">
<el-radio-group v-model="dataForm.generatorType"> <el-radio-group v-model="dataForm.generatorType">
<el-radio border label="1">自定义路径</el-radio> <el-radio border value="1">自定义路径</el-radio>
<el-radio border label="0">ZIP 压缩包</el-radio> <el-radio border value="0">ZIP 压缩包</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24" class="mb20"> <el-col :span="24" class="mb20">
<el-form-item label="后端生成路径" prop="backendPath" v-if="dataForm.generatorType === '1'"> <el-form-item prop="backendPath" v-if="dataForm.generatorType === '1'">
<template #label>
<span>后端生成路径</span>
<tip content="后端模块biz所在文件全路径比如D:\data\pigx\pigx-upms\pigx-upms-biz"/>
</template>
<el-input placeholder="后端生成路径" v-model="dataForm.backendPath"></el-input> <el-input placeholder="后端生成路径" v-model="dataForm.backendPath"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="前端生成路径" prop="frontendPath" v-if="dataForm.generatorType === '1'"> <el-form-item prop="frontendPath" v-if="dataForm.generatorType === '1'">
<template #label>
<span>前端生成路径</span>
<tip content="前端所在文件全路径比如D:\data\pigx-ui"/>
</template>
<el-input placeholder="前端生成路径" v-model="dataForm.frontendPath"></el-input> <el-input placeholder="前端生成路径" v-model="dataForm.frontendPath"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -83,7 +103,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import {putObj, useTableApi} from '/@/api/gen/table'; import {putObj, useTableApi} from '/@/api/gen/table';
import {list as groupList} from '/@/api/gen/group'; import {list as groupList} from '/@/api/gen/group';
import {checkVersion, online} from '/@/api/gen/template';
import {Local} from '/@/utils/storage'; import {Local} from '/@/utils/storage';
import {rule} from "/@/utils/validate";
import {useMessage, useMessageBox} from "/@/hooks/message";
const props = defineProps({ const props = defineProps({
tableName: { tableName: {
@ -127,7 +150,7 @@ const getTable = (dsName: string, tableName: string) => {
.then((res) => { .then((res) => {
Object.assign(dataForm, res.data); Object.assign(dataForm, res.data);
let list = res.data.groupList; let list = res.data.groupList;
dataForm.style = list[0].id; dataForm.style = list[0]?.id;
// 使 // 使
const frontendPath = Local.get('frontendPath'); const frontendPath = Local.get('frontendPath');
@ -144,24 +167,66 @@ const getTable = (dsName: string, tableName: string) => {
}; };
const dataRules = ref({ const dataRules = ref({
tableName: [{required: true, message: '必填项不能为空', trigger: 'blur'}], tableName: [{validator: rule.overLength, trigger: 'blur'}, {
tableComment: [{required: true, message: '必填项不能为空', trigger: 'blur'}], required: true,
className: [{required: true, message: '必填项不能为空', trigger: 'blur'}], message: '必填项不能为空',
packageName: [{required: true, message: '必填项不能为空', trigger: 'blur'}], trigger: 'blur'
author: [{required: true, message: '必填项不能为空', trigger: 'blur'}], }],
moduleName: [{required: true, message: '必填项不能为空', trigger: 'blur'}], tableComment: [{validator: rule.overLength, trigger: 'blur'}, {
functionName: [{required: true, message: '必填项不能为空', trigger: 'blur'}], required: true,
generatorType: [{required: true, message: '必填项不能为空', trigger: 'blur'}], message: '必填项不能为空',
formLayout: [{required: true, message: '必填项不能为空', trigger: 'blur'}], trigger: 'blur'
backendPath: [{required: true, message: '必填项不能为空', trigger: 'blur'}], }],
frontendPath: [{required: true, message: '必填项不能为空', trigger: 'blur'}], className: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
packageName: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
author: [{validator: rule.overLength, trigger: 'blur'}, {required: true, message: '必填项不能为空', trigger: 'blur'}],
moduleName: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
functionName: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
generatorType: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
formLayout: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
backendPath: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
frontendPath: [{validator: rule.overLength, trigger: 'blur'}, {
required: true,
message: '必填项不能为空',
trigger: 'blur'
}],
style: [{required: true, message: '必填项不能为空', trigger: 'blur'}], style: [{required: true, message: '必填项不能为空', trigger: 'blur'}],
}); });
// //
const submitHandle = async () => { const submitHandle = async () => {
try { try {
await dataFormRef.value.validate(); const valid = await dataFormRef.value.validate(); //
if (!valid) return false;
loading.value = true; loading.value = true;
await putObj(Object.assign(dataForm, childForm.value)); await putObj(Object.assign(dataForm, childForm.value));
visible.value = false; visible.value = false;
@ -171,7 +236,7 @@ const submitHandle = async () => {
return Promise.reject(); return Promise.reject();
} finally { } finally {
//Local 便使 //Local 便使
if (dataForm.generatorType === '1') { if (dataForm.generatorType === "1") {
Local.set('frontendPath', dataForm.frontendPath); Local.set('frontendPath', dataForm.frontendPath);
Local.set('backendPath', dataForm.backendPath); Local.set('backendPath', dataForm.backendPath);
} }
@ -180,11 +245,40 @@ const submitHandle = async () => {
}; };
const genGroupList = () => { const genGroupList = () => {
groupList().then((res) => { groupList().then(({data}) => {
groupDataList.value = res.data; if (data && data.length > 0 ){
}); groupDataList.value = data;
}
})
}; };
/**
* 检查模板版本
*/
const checkTemplateVersion = async () => {
checkVersion().then(({data}) => {
if (!data) {
useMessageBox().confirm('模板发现新版本,是否更新?').then(() => {
//
online().then(() => {
useMessage().success('更新成功');
genGroupList()
});
}).catch(() => {
})
}
})
};
watch(
() => childForm,
() => {
const {childTableName} = childForm.value || {};
tableNameStr.value = childTableName ? `${props.tableName} + ${childTableName}` : props.tableName;
},
{deep: true, immediate: true}
);
onMounted(() => { onMounted(() => {
// //
if (dataFormRef.value) { if (dataFormRef.value) {
@ -196,6 +290,7 @@ onMounted(() => {
getTable(dataForm.dsName, dataForm.tableName); getTable(dataForm.dsName, dataForm.tableName);
genGroupList(); genGroupList();
checkTemplateVersion()
}); });
defineExpose({ defineExpose({

View File

@ -1,75 +1,78 @@
<template> <template>
<div class="layout-padding"> <div class="layout-padding">
<div class="layout-padding-auto layout-padding-view"> <div class="layout-padding-auto layout-padding-view">
<el-row class="ml10" v-show="showSearch"> <el-row class="ml10" v-show="showSearch">
<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef"> <el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
<el-form-item label="数据源" prop="name"> <el-form-item label="数据源" prop="name">
<el-select @change="getDataList" placeholder="请选择数据源" style="width: 100%" v-model="state.queryForm.dsName"> <el-select @change="getDataList" placeholder="请选择数据源" v-model="state.queryForm.dsName">
<el-option label="默认数据源" value="master"></el-option> <el-option label="默认数据源" value="master"></el-option>
<el-option :key="ds.id" :label="ds.name" :value="ds.name" v-for="ds in datasourceList"> </el-option> <el-option :key="ds.id" :label="ds.name" :value="ds.name" v-for="ds in datasourceList"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="$t('table.tableName')" prop="tableName"> <el-form-item :label="$t('table.tableName')" prop="tableName">
<el-input :placeholder="$t('table.inputtableNameTip')" style="max-width: 180px" v-model="state.queryForm.tableName" /> <el-input :placeholder="$t('table.inputtableNameTip')" v-model="state.queryForm.tableName"/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="getDataList" icon="search" type="primary"> <el-button @click="getDataList" icon="search" type="primary">
{{ $t('common.queryBtn') }} {{ $t('common.queryBtn') }}
</el-button> </el-button>
<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button> <el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>
<el-row> <el-row>
<div class="mb8" style="width: 100%"> <div class="mb8" style="width: 100%">
<right-toolbar <right-toolbar
:export="true" :export="true"
@exportExcel="exportExcel" @exportExcel="exportExcel"
@queryTable="getDataList" @queryTable="getDataList"
class="ml10" class="ml10"
style="float: right; margin-right: 20px" style="float: right; margin-right: 20px"
v-model:showSearch="showSearch" v-model:showSearch="showSearch"
></right-toolbar> ></right-toolbar>
</div> </div>
</el-row> </el-row>
<el-table <el-table
:data="state.dataList" :data="state.dataList"
style="width: 100%" style="width: 100%"
v-loading="state.loading" v-loading="state.loading"
border border
:cell-style="tableStyle.cellStyle" :cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle" :header-cell-style="tableStyle.headerCellStyle"
> >
<el-table-column :label="t('table.index')" type="index" width="60" /> <el-table-column :label="t('table.index')" type="index" width="60"/>
<el-table-column :label="t('table.tableName')" prop="tableName" show-overflow-tooltip /> <el-table-column :label="t('table.tableName')" prop="name" show-overflow-tooltip/>
<el-table-column :label="t('table.tableDesc')" prop="tableComment" show-overflow-tooltip /> <el-table-column :label="t('table.tableDesc')" prop="comment" show-overflow-tooltip/>
<el-table-column :label="t('table.createTime')" prop="createTime" show-overflow-tooltip /> <el-table-column :label="t('table.createTime')" prop="createTime" show-overflow-tooltip/>
<el-table-column :label="$t('common.action')" width="200"> <el-table-column :label="$t('common.action')" width="250">
<template #default="scope"> <template #default="scope">
<el-button icon="Refresh" @click="syncTable(scope.row)" text type="primary"> <el-button icon="Refresh" @click="syncTable(scope.row)" text type="primary">
{{ $t('gen.syncBtn') }} {{ $t('gen.syncBtn') }}
</el-button> </el-button>
<el-button icon="FolderOpened" @click="openGen(scope.row)" text type="primary">{{ $t('gen.genBtn') }} </el-button> <el-button icon="FolderOpened" @click="openGen(scope.row)" text type="primary">{{
</template> $t('gen.genBtn')
</el-table-column> }}
</el-table> </el-button>
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" /> </template>
</div> </el-table-column>
</div> </el-table>
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination"/>
</div>
</div>
</template> </template>
<script lang="ts" name="systemTable" setup> <script lang="ts" name="systemTable" setup>
import { BasicTableProps, useTable } from '/@/hooks/table'; import {BasicTableProps, useTable} from '/@/hooks/table';
import { fetchList, useSyncTableApi, useTableApi } from '/@/api/gen/table'; import {fetchList, useSyncTableApi, useTableApi} from '/@/api/gen/table';
import { list } from '/@/api/gen/datasource'; import {list} from '/@/api/gen/datasource';
import { useMessage } from '/@/hooks/message'; import {useMessage} from '/@/hooks/message';
import { useI18n } from 'vue-i18n'; import {useI18n} from 'vue-i18n';
import { validateNull } from '/@/utils/validate'; import {validateNull} from '/@/utils/validate';
// //
const router = useRouter(); const router = useRouter();
// //
const { t } = useI18n(); const {t} = useI18n();
// //
const queryRef = ref(); const queryRef = ref();
const showSearch = ref(true); const showSearch = ref(true);
@ -77,61 +80,61 @@ const showSearch = ref(true);
const datasourceList = ref(); const datasourceList = ref();
const state: BasicTableProps = reactive<BasicTableProps>({ const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: { queryForm: {
dsName: 'master', dsName: 'master',
}, },
pageList: fetchList, pageList: fetchList,
createdIsNeed: false, createdIsNeed: false,
}); });
// table hook // table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, downBlobFile, tableStyle } = useTable(state); const {getDataList, currentChangeHandle, sizeChangeHandle, downBlobFile, tableStyle} = useTable(state);
// //
onMounted(() => { onMounted(() => {
list().then((res) => { list().then((res) => {
datasourceList.value = res.data; datasourceList.value = res.data;
// //
if (datasourceList.value.length > 0) { if (datasourceList.value.length > 0) {
state.queryForm.dsName = datasourceList.value[0].name; state.queryForm.dsName = datasourceList.value[0].name;
} }
getDataList(); getDataList();
}); });
}); });
const openGen = (row) => { const openGen = (row) => {
useTableApi(state.queryForm.dsName, row.tableName) useTableApi(state.queryForm.dsName, row.name)
.then((res) => { .then((res) => {
if (validateNull(res.data.fieldList)) { if (validateNull(res.data.fieldList)) {
syncTable(row); syncTable(row);
} }
}) })
.finally(() => { .finally(() => {
router.push({ router.push({
path: '/gen/gener/index', path: '/gen/gener/index',
query: { query: {
tableName: row.tableName, tableName: row.name,
dsName: state.queryForm.dsName, dsName: state.queryForm.dsName,
}, },
}); });
}); });
}; };
// //
const syncTable = (row) => { const syncTable = (row: { name: string }) => {
useSyncTableApi(state.queryForm.dsName, row.tableName).then(() => { useSyncTableApi(state.queryForm.dsName, row.name).then(() => {
useMessage().success(t('common.optSuccessText')); useMessage().success(t('common.optSuccessText'));
}); });
}; };
// //
const resetQuery = () => { const resetQuery = () => {
queryRef.value.resetFields(); queryRef.value.resetFields();
getDataList(); getDataList();
}; };
// excel // excel
const exportExcel = () => { const exportExcel = () => {
downBlobFile('/gen/table/export', state.queryForm, 'table.xlsx'); downBlobFile('/gen/table/export', state.queryForm, 'table.xlsx');
}; };
</script> </script>

View File

@ -1,33 +1,33 @@
<template> <template>
<el-dialog fullscreen title="代码预览" v-model="visible" width="90%" top="3vh" append-to-body :close-on-click-modal="false"> <el-dialog fullscreen title="代码预览" v-model="visible" width="90%" top="3vh" append-to-body :close-on-click-modal="false">
<splitpanes> <splitpanes>
<pane size="25"> <pane size="25">
<el-scrollbar height="calc(100vh - 100px)" class="mt20"> <el-scrollbar height="calc(100vh - 100px)" class="mt20">
<el-tree <el-tree
ref="treeRef" ref="treeRef"
node-key="id" node-key="id"
:data="preview.fileTree" :data="preview.fileTree"
:expand-on-click-node="false" :expand-on-click-node="false"
highlight-current highlight-current
@node-click="handleNodeClick" @node-click="handleNodeClick"
/> />
</el-scrollbar> </el-scrollbar>
</pane> </pane>
<pane> <pane>
<el-tabs v-model="preview.activeName" @tab-click="handleTabClick"> <el-tabs v-model="preview.activeName" @tab-click="handleTabClick">
<el-tab-pane <el-tab-pane
v-for="item in previewCodegen" v-for="item in previewCodegen"
:label="item.codePath.substring(item.codePath.lastIndexOf('/') + 1)" :label="item.codePath.substring(item.codePath.lastIndexOf('/') + 1)"
:name="item.codePath" :name="item.codePath"
:key="item.codePath" :key="item.codePath"
> >
<SvgIcon name="ele-CopyDocument" :size="25" class="copy_btn" @click="copyText(item.code)" /> <SvgIcon name="ele-CopyDocument" :size="25" class="copy_btn" @click="copyText(item.code)" />
</el-tab-pane> </el-tab-pane>
<code-editor ref="codeEditorRef" theme="darcula" v-model="previewCodeStr" mode="go" readOnly height="calc(100vh - 100px)"></code-editor> <code-editor ref="codeEditorRef" theme="darcula" v-model="previewCodeStr" mode="go" readOnly height="calc(100vh - 100px)"></code-editor>
</el-tabs> </el-tabs>
</pane> </pane>
</splitpanes> </splitpanes>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts" name="preview"> <script setup lang="ts" name="preview">
import { useGeneratorPreviewApi } from '/@/api/gen/table'; import { useGeneratorPreviewApi } from '/@/api/gen/table';
@ -40,10 +40,10 @@ const { copyText } = commonFunction();
const visible = ref(false); const visible = ref(false);
// ======== ======== // ======== ========
const preview = reactive({ const preview = reactive({
open: false, open: false,
titel: '代码预览', titel: '代码预览',
fileTree: [], fileTree: [],
activeName: '', activeName: '',
}); });
const previewCodegen = ref([]); const previewCodegen = ref([]);
@ -51,8 +51,8 @@ const previewCodeStr = ref('');
const fileTreeOriginal = ref([] as any[]); const fileTreeOriginal = ref([] as any[]);
const openDialog = async (id: string) => { const openDialog = async (id: string) => {
await getGenCodeFile(id); await getGenCodeFile(id);
visible.value = true; visible.value = true;
}; };
const loading = ref(false); const loading = ref(false);
@ -63,43 +63,43 @@ const codeEditorRef = ref();
* @param id 需要渲染的资源 ID * @param id 需要渲染的资源 ID
*/ */
const getGenCodeFile = (id: string) => { const getGenCodeFile = (id: string) => {
loading.value = true; loading.value = true;
fileTreeOriginal.value = []; fileTreeOriginal.value = [];
useGeneratorPreviewApi(id) useGeneratorPreviewApi(id)
.then((res: any) => { .then((res: any) => {
previewCodegen.value = res; previewCodegen.value = res;
for (let index in res) { for (let index in res) {
fileTreeOriginal.value.push(res[index].codePath); fileTreeOriginal.value.push(res[index].codePath);
} }
// //
previewCodeStr.value = res[0].code; previewCodeStr.value = res[0].code;
preview.activeName = res[0].codePath; preview.activeName = res[0].codePath;
const files = handleFiles(fileTreeOriginal); const files = handleFiles(fileTreeOriginal);
preview.fileTree = handleTree(files, 'id', 'parentId', 'children', '/'); preview.fileTree = handleTree(files, 'id', 'parentId', 'children', '/');
}) })
.finally(() => { .finally(() => {
loading.value = false; loading.value = false;
}); });
}; };
const handleNodeClick = async (data: any, node: any) => { const handleNodeClick = async (data: any, node: any) => {
if (node && !node.isLeaf) { if (node && !node.isLeaf) {
return false; return false;
} }
preview.activeName = data.id; preview.activeName = data.id;
const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === data.id); const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === data.id);
if (filteredCode.length > 0) { if (filteredCode.length > 0) {
previewCodeStr.value = filteredCode[0].code; previewCodeStr.value = filteredCode[0].code;
} }
}; };
const handleTabClick = (item: any) => { const handleTabClick = (item: any) => {
const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === item.paneName); const filteredCode = previewCodegen.value.filter((code: any) => code.codePath === item.paneName);
if (filteredCode.length > 0) { if (filteredCode.length > 0) {
previewCodeStr.value = filteredCode[0].code; previewCodeStr.value = filteredCode[0].code;
} }
}; };
/** /**
@ -108,51 +108,51 @@ const handleTabClick = (item: any) => {
* @returns {*[]} * @returns {*[]}
*/ */
const handleFiles = (fileTreeOriginal: any) => { const handleFiles = (fileTreeOriginal: any) => {
const exists = {}; const exists = {};
const files = [] as any[]; const files = [] as any[];
// //
for (const data of fileTreeOriginal.value) { for (const data of fileTreeOriginal.value) {
let paths = []; let paths = [];
if (data.includes('\\')) { if (data.includes('\\')) {
paths = data.split('\\'); paths = data.split('\\');
} else { } else {
paths = data.split('/'); paths = data.split('/');
} }
let fullPath = ''; // id let fullPath = ''; // id
// path // path
for (let i = 0; i < paths.length; i++) { for (let i = 0; i < paths.length; i++) {
// files // files
const oldFullPath = fullPath; const oldFullPath = fullPath;
// replaceAll tabs replaceAll // replaceAll tabs replaceAll
fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i]; fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i];
if (exists[fullPath]) { if (exists[fullPath]) {
continue; continue;
} }
// files // files
exists[fullPath] = true; exists[fullPath] = true;
files.push({ files.push({
id: fullPath, id: fullPath,
label: paths[i], label: paths[i],
parentId: oldFullPath || '/', parentId: oldFullPath || '/',
templateName: data.k, templateName: data.k,
}); });
} }
} }
return files; return files;
}; };
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.copy_btn { .copy_btn {
position: absolute; position: absolute;
top: 10px; top: 10px;
right: 20px; right: 20px;
z-index: 9; z-index: 9;
color: white; color: white;
} }
</style> </style>

View File

@ -1,33 +1,33 @@
<template> <template>
<el-dialog fullscreen :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible"> <el-dialog fullscreen :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible">
<el-form :model="form" :rules="dataRules" formDialogRef ref="dataFormRef" v-loading="loading"> <el-form :model="form" :rules="dataRules" formDialogRef ref="dataFormRef" v-loading="loading">
<el-container> <el-container>
<el-aside width="80%"> <el-aside width="80%">
<code-editor v-model="form.templateCode" theme="darcula" mode="velocity" height="700"></code-editor> <code-editor v-model="form.templateCode" theme="darcula" mode="velocity" height="700"></code-editor>
</el-aside> </el-aside>
<el-main> <el-main>
<el-row> <el-row>
<el-form-item :label="t('template.templateName')" prop="templateName"> <el-form-item :label="t('template.templateName')" prop="templateName">
<el-input :placeholder="t('template.inputTemplateNameTip')" v-model="form.templateName" /> <el-input :placeholder="t('template.inputTemplateNameTip')" v-model="form.templateName" />
</el-form-item> </el-form-item>
<el-form-item :label="t('template.desc')" prop="templateDesc"> <el-form-item :label="t('template.desc')" prop="templateDesc">
<el-input :placeholder="t('template.inputDescTip')" v-model="form.templateDesc" /> <el-input :placeholder="t('template.inputDescTip')" v-model="form.templateDesc" />
</el-form-item> </el-form-item>
<el-form-item :label="t('template.generatorPath')" prop="generatorPath"> <el-form-item :label="t('template.generatorPath')" prop="generatorPath">
<el-input :placeholder="t('template.inputGeneratorPathTip')" v-model="form.generatorPath" /> <el-input :placeholder="t('template.inputGeneratorPathTip')" v-model="form.generatorPath" />
</el-form-item> </el-form-item>
</el-row> </el-row>
</el-main> </el-main>
</el-container> </el-container>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button> <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button @click="onSubmit" type="primary" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button> <el-button @click="onSubmit" type="primary" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" name="GenTemplateDialog" setup> <script lang="ts" name="GenTemplateDialog" setup>
@ -35,6 +35,7 @@
import { useMessage } from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import { addObj, getObj, putObj } from '/@/api/gen/template'; import { addObj, getObj, putObj } from '/@/api/gen/template';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import {rule} from "/@/utils/validate";
const CodeEditor = defineAsyncComponent(() => import('/@/components/CodeEditor/index.vue')); const CodeEditor = defineAsyncComponent(() => import('/@/components/CodeEditor/index.vue'));
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);
@ -50,76 +51,76 @@ const loading = ref(false);
// //
const form = reactive({ const form = reactive({
id: '', id: '',
templateName: '', templateName: '',
generatorPath: '', generatorPath: '',
templateDesc: '', templateDesc: '',
templateCode: '', templateCode: '',
}); });
// //
const dataRules = ref({ const dataRules = ref({
templateName: [{ required: true, message: '模板名称不能为空', trigger: 'blur' }], templateName: [{ validator: rule.overLength, trigger: 'blur' },{ required: true, message: '模板名称不能为空', trigger: 'blur' }],
generatorPath: [{ required: true, message: '模板路径不能为空', trigger: 'blur' }], generatorPath: [{ validator: rule.overLength, trigger: 'blur' },{ required: true, message: '模板路径不能为空', trigger: 'blur' }],
templateDesc: [{ required: true, message: '模板描述不能为空', trigger: 'blur' }], templateDesc: [{ validator: rule.overLength, trigger: 'blur' },{ required: true, message: '模板描述不能为空', trigger: 'blur' }],
}); });
// //
const openDialog = (id: string) => { const openDialog = (id: string) => {
visible.value = true; visible.value = true;
form.id = ''; form.id = '';
// //
nextTick(() => { nextTick(() => {
dataFormRef.value?.resetFields(); dataFormRef.value?.resetFields();
}); });
// genTemplate // genTemplate
if (id) { if (id) {
form.id = id; form.id = id;
getgenTemplateData(id); getgenTemplateData(id);
} }
}; };
// //
const onSubmit = async () => { const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {}); const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false; if (!valid) return false;
// //
try { try {
loading.value = true; loading.value = true;
form.id ? await putObj(form) : await addObj(form); form.id ? await putObj(form) : await addObj(form);
useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText')); useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
visible.value = false; visible.value = false;
emit('refresh'); emit('refresh');
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg); useMessage().error(err.msg);
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; };
// //
const getgenTemplateData = (id: string) => { const getgenTemplateData = (id: string) => {
// //
getObj(id).then((res: any) => { getObj(id).then((res: any) => {
Object.assign(form, res.data); Object.assign(form, res.data);
}); });
}; };
// //
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
</script> </script>
<style scoped> <style scoped>
.splitpanes__pane { .splitpanes__pane {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-family: Helvetica, Arial, sans-serif; font-family: Helvetica, Arial, sans-serif;
color: rgba(255, 255, 255, 0.6); color: rgba(255, 255, 255, 0.6);
font-size: 5em; font-size: 5em;
} }
</style> </style>

View File

@ -1,92 +1,101 @@
<template> <template>
<div class="layout-padding"> <div class="layout-padding">
<div class="layout-padding-auto layout-padding-view"> <div class="layout-padding-auto layout-padding-view">
<el-row class="ml10" v-show="showSearch"> <el-row class="ml10" v-show="showSearch">
<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef"> <el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
<el-form-item :label="$t('template.templateName')" prop="templateName"> <el-form-item :label="$t('template.templateName')" prop="templateName">
<el-input :placeholder="t('template.inputTemplateNameTip')" style="max-width: 180px" v-model="state.queryForm.templateName" /> <el-input :placeholder="t('template.inputTemplateNameTip')" style="max-width: 180px"
</el-form-item> v-model="state.queryForm.templateName"/>
<el-form-item> </el-form-item>
<el-button @click="getDataList" formDialogRef icon="search" type="primary"> <el-form-item>
{{ $t('common.queryBtn') }} <el-button @click="getDataList" formDialogRef icon="search" type="primary">
</el-button> {{ $t('common.queryBtn') }}
<el-button @click="resetQuery" formDialogRef icon="Refresh">{{ $t('common.resetBtn') }} </el-button> </el-button>
</el-form-item> <el-button @click="resetQuery" formDialogRef icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
</el-form> </el-form-item>
</el-row> </el-form>
<el-row> </el-row>
<div class="mb8" style="width: 100%"> <el-row>
<el-button @click="formDialogRef.openDialog()" class="ml10" icon="folder-add" type="primary" v-auth="'codegen_template_add'"> <div class="mb8" style="width: 100%">
{{ $t('common.addBtn') }} <el-button @click="formDialogRef.openDialog()" class="ml10" icon="folder-add" type="primary"
</el-button> v-auth="'codegen_template_add'">
<el-button {{ $t('common.addBtn') }}
plain </el-button>
:disabled="multiple" <el-button
@click="handleDelete(selectObjs)" plain
class="ml10" :disabled="multiple"
icon="Delete" @click="handleDelete(selectObjs)"
type="primary" class="ml10"
v-auth="'codegen_template_del'" icon="Delete"
> type="primary"
{{ $t('common.delBtn') }} v-auth="'codegen_template_del'"
</el-button> >
<right-toolbar {{ $t('common.delBtn') }}
:export="'codegen_template_export'" </el-button>
@exportExcel="exportExcel" <el-button @click="onlineUpdate" class="ml10" icon="download" plain :disabled="updateDisabled"
@queryTable="getDataList" v-auth="'codegen_template_add'">
class="ml10" 更新
style="float: right; margin-right: 20px" </el-button>
v-model:showSearch="showSearch" <right-toolbar
></right-toolbar> :export="'codegen_template_export'"
</div> @exportExcel="exportExcel"
</el-row> @queryTable="getDataList"
<el-table class="ml10"
:data="state.dataList" style="float: right; margin-right: 20px"
@selection-change="handleSelectionChange" v-model:showSearch="showSearch"
style="width: 100%" ></right-toolbar>
v-loading="state.loading" </div>
border </el-row>
:cell-style="tableStyle.cellStyle" <el-table
:header-cell-style="tableStyle.headerCellStyle" :data="state.dataList"
> @selection-change="handleSelectionChange"
<el-table-column align="center" type="selection" width="40" /> style="width: 100%"
<el-table-column :label="t('template.index')" type="index" width="60" /> v-loading="state.loading"
<el-table-column :label="t('template.templateName')" prop="templateName" show-overflow-tooltip /> border
<el-table-column :label="t('template.generatorPath')" prop="generatorPath" show-overflow-tooltip /> :cell-style="tableStyle.cellStyle"
<el-table-column :label="t('template.desc')" prop="templateDesc" show-overflow-tooltip /> :header-cell-style="tableStyle.headerCellStyle"
<el-table-column :label="t('template.createTime')" prop="createTime" show-overflow-tooltip /> >
<el-table-column :label="$t('common.action')" width="150"> <el-table-column align="center" type="selection" width="40"/>
<template #default="scope"> <el-table-column :label="t('template.index')" type="index" width="60"/>
<el-button icon="edit-pen" @click="formDialogRef.openDialog(scope.row.id)" text type="primary" v-auth="'codegen_template_edit'" <el-table-column :label="t('template.templateName')" prop="templateName" show-overflow-tooltip/>
>{{ $t('common.editBtn') }} <el-table-column :label="t('template.generatorPath')" prop="generatorPath" show-overflow-tooltip/>
</el-button> <el-table-column :label="t('template.desc')" prop="templateDesc" show-overflow-tooltip/>
<el-button icon="delete" @click="handleDelete([scope.row.id])" text type="primary" v-auth="'codegen_template_del'" <el-table-column :label="t('template.createTime')" prop="createTime" show-overflow-tooltip/>
>{{ $t('common.delBtn') }} <el-table-column :label="$t('common.action')" width="150">
</el-button> <template #default="scope">
</template> <el-button icon="edit-pen" @click="formDialogRef.openDialog(scope.row.id)" text type="primary"
</el-table-column> v-auth="'codegen_template_edit'"
</el-table> >{{ $t('common.editBtn') }}
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" /> </el-button>
</div> <el-button icon="delete" @click="handleDelete([scope.row.id])" text type="primary"
v-auth="'codegen_template_del'"
>{{ $t('common.delBtn') }}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination"/>
</div>
<!-- 编辑新增 --> <!-- 编辑新增 -->
<form-dialog @refresh="getDataList()" ref="formDialogRef" /> <form-dialog @refresh="getDataList()" ref="formDialogRef"/>
</div> </div>
</template> </template>
<script lang="ts" name="systemGenTemplate" setup> <script lang="ts" name="systemGenTemplate" setup>
import { BasicTableProps, useTable } from '/@/hooks/table'; import {BasicTableProps, useTable} from '/@/hooks/table';
import { delObjs, fetchList } from '/@/api/gen/template'; import {delObjs, fetchList, online} from '/@/api/gen/template';
import { useMessage, useMessageBox } from '/@/hooks/message'; import {useMessage, useMessageBox} from '/@/hooks/message';
import { useI18n } from 'vue-i18n'; import {useI18n} from 'vue-i18n';
// //
const FormDialog = defineAsyncComponent(() => import('./form.vue')); const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const { t } = useI18n(); const {t} = useI18n();
// //
// //
const formDialogRef = ref(); const formDialogRef = ref();
const updateDisabled = ref(false);
// //
const queryRef = ref(); const queryRef = ref();
const showSearch = ref(true); const showSearch = ref(true);
@ -95,48 +104,61 @@ const selectObjs = ref([]) as any;
const multiple = ref(true); const multiple = ref(true);
const state: BasicTableProps = reactive<BasicTableProps>({ const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {}, queryForm: {},
pageList: fetchList, pageList: fetchList,
descs: ['create_time'], descs: ['create_time'],
}); });
// table hook // table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, downBlobFile, tableStyle } = useTable(state); const {getDataList, currentChangeHandle, sizeChangeHandle, downBlobFile, tableStyle} = useTable(state);
// //
const resetQuery = () => { const resetQuery = () => {
// //
queryRef.value.resetFields(); queryRef.value.resetFields();
// //
selectObjs.value = []; selectObjs.value = [];
getDataList(); getDataList();
}; };
// excel // excel
const exportExcel = () => { const exportExcel = () => {
downBlobFile('/gen/template/export', state.queryForm, 'template.xlsx'); downBlobFile('/gen/template/export', state.queryForm, 'template.xlsx');
}; };
// //
const handleSelectionChange = (objs: { id: string }[]) => { const handleSelectionChange = (objs: { id: string }[]) => {
selectObjs.value = objs.map(({ id }) => id); selectObjs.value = objs.map(({id}) => id);
multiple.value = !objs.length; multiple.value = !objs.length;
}; };
// //
const handleDelete = async (ids: string[]) => { const handleDelete = async (ids: string[]) => {
try { try {
await useMessageBox().confirm(t('common.delConfirmText')); await useMessageBox().confirm(t('common.delConfirmText'));
} catch { } catch {
return; return;
} }
try { try {
await delObjs(ids); await delObjs(ids);
getDataList(); getDataList();
useMessage().success(t('common.delSuccessText')); useMessage().success(t('common.delSuccessText'));
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg); useMessage().error(err.msg);
} }
};
const onlineUpdate = async () => {
try {
updateDisabled.value = true;
const {data} = await online();
getDataList();
useMessage().success(data);
} catch (err: any) {
useMessage().error(err.msg);
} finally {
updateDisabled.value = false;
}
}; };
</script> </script>