Vue3 重构:基础设施 -> 代码生成
This commit is contained in:
parent
812300cc04
commit
f33935868d
@ -2,56 +2,56 @@ import request from '@/config/axios'
|
||||
import type { CodegenUpdateReqVO, CodegenCreateListReqVO } from './types'
|
||||
|
||||
// 查询列表代码生成表定义
|
||||
export const getCodegenTablePageApi = (params) => {
|
||||
export const getCodegenTablePage = (params) => {
|
||||
return request.get({ url: '/infra/codegen/table/page', params })
|
||||
}
|
||||
|
||||
// 查询详情代码生成表定义
|
||||
export const getCodegenTableApi = (id: number) => {
|
||||
export const getCodegenTable = (id: number) => {
|
||||
return request.get({ url: '/infra/codegen/detail?tableId=' + id })
|
||||
}
|
||||
|
||||
// 新增代码生成表定义
|
||||
export const createCodegenTableApi = (data: CodegenCreateListReqVO) => {
|
||||
export const createCodegenTable = (data: CodegenCreateListReqVO) => {
|
||||
return request.post({ url: '/infra/codegen/create', data })
|
||||
}
|
||||
|
||||
// 修改代码生成表定义
|
||||
export const updateCodegenTableApi = (data: CodegenUpdateReqVO) => {
|
||||
export const updateCodegenTable = (data: CodegenUpdateReqVO) => {
|
||||
return request.put({ url: '/infra/codegen/update', data })
|
||||
}
|
||||
|
||||
// 基于数据库的表结构,同步数据库的表和字段定义
|
||||
export const syncCodegenFromDBApi = (id: number) => {
|
||||
export const syncCodegenFromDB = (id: number) => {
|
||||
return request.put({ url: '/infra/codegen/sync-from-db?tableId=' + id })
|
||||
}
|
||||
|
||||
// 基于 SQL 建表语句,同步数据库的表和字段定义
|
||||
export const syncCodegenFromSQLApi = (id: number, sql: string) => {
|
||||
export const syncCodegenFromSQL = (id: number, sql: string) => {
|
||||
return request.put({ url: '/infra/codegen/sync-from-sql?tableId=' + id + '&sql=' + sql })
|
||||
}
|
||||
|
||||
// 预览生成代码
|
||||
export const previewCodegenApi = (id: number) => {
|
||||
export const previewCodegen = (id: number) => {
|
||||
return request.get({ url: '/infra/codegen/preview?tableId=' + id })
|
||||
}
|
||||
|
||||
// 下载生成代码
|
||||
export const downloadCodegenApi = (id: number) => {
|
||||
export const downloadCodegen = (id: number) => {
|
||||
return request.download({ url: '/infra/codegen/download?tableId=' + id })
|
||||
}
|
||||
|
||||
// 获得表定义
|
||||
export const getSchemaTableListApi = (params) => {
|
||||
export const getSchemaTableList = (params) => {
|
||||
return request.get({ url: '/infra/codegen/db/table/list', params })
|
||||
}
|
||||
|
||||
// 基于数据库的表结构,创建代码生成器的表定义
|
||||
export const createCodegenListApi = (data) => {
|
||||
export const createCodegenList = (data) => {
|
||||
return request.post({ url: '/infra/codegen/create-list', data })
|
||||
}
|
||||
|
||||
// 删除代码生成表定义
|
||||
export const deleteCodegenTableApi = (id: number) => {
|
||||
export const deleteCodegenTable = (id: number) => {
|
||||
return request.delete({ url: '/infra/codegen/delete?tableId=' + id })
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ export type CodegenPreviewVO = {
|
||||
code: string
|
||||
}
|
||||
export type CodegenUpdateReqVO = {
|
||||
table: CodegenTableVO
|
||||
table: CodegenTableVO | any
|
||||
columns: CodegenColumnVO[]
|
||||
}
|
||||
export type CodegenCreateListReqVO = {
|
||||
|
@ -298,7 +298,8 @@ export default {
|
||||
typeUpdate: '字典类型编辑',
|
||||
dataCreate: '字典数据新增',
|
||||
dataUpdate: '字典数据编辑',
|
||||
fileUpload: '上传文件'
|
||||
fileUpload: '上传文件',
|
||||
back: '返回'
|
||||
},
|
||||
dialog: {
|
||||
dialog: '弹窗',
|
||||
|
@ -1,67 +1,74 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<ContentDetailWrap :title="title" @back="push('/infra/codegen')">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="基本信息" name="basicInfo">
|
||||
<BasicInfoForm ref="basicInfoRef" :basicInfo="tableCurrentRow" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="字段信息" name="cloum">
|
||||
<CloumInfoForm ref="cloumInfoRef" :info="cloumCurrentRow" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #right>
|
||||
<XButton
|
||||
type="primary"
|
||||
:title="t('action.save')"
|
||||
:loading="loading"
|
||||
@click="submitForm()"
|
||||
/>
|
||||
</template>
|
||||
</ContentDetailWrap>
|
||||
</ContentWrap>
|
||||
<content-wrap v-loading="loading">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="基本信息" name="basicInfo">
|
||||
<basic-info-form ref="basicInfoRef" :table="formData.table" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="字段信息" name="colum">
|
||||
<colum-info-form ref="columInfoRef" :columns="formData.columns" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="生成信息" name="generateInfo">
|
||||
<generate-info-form ref="generateInfoRef" :table="formData.table" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item style="text-align: center; margin-left: -100px; margin-top: 10px">
|
||||
<el-button type="primary" @click="submitForm" :loading="submitLoading">
|
||||
{{ t('action.save') }}
|
||||
</el-button>
|
||||
<el-button @click="close">{{ t('action.back') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</content-wrap>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { BasicInfoForm, CloumInfoForm } from './components'
|
||||
import { getCodegenTableApi, updateCodegenTableApi } from '@/api/infra/codegen'
|
||||
import { CodegenTableVO, CodegenColumnVO, CodegenUpdateReqVO } from '@/api/infra/codegen/types'
|
||||
import { BasicInfoForm, ColumInfoForm, GenerateInfoForm } from './components'
|
||||
import * as CodegenApi from '@/api/infra/codegen'
|
||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||
import { CodegenUpdateReqVO } from '@/api/infra/codegen/types'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { push } = useRouter()
|
||||
const { push, currentRoute } = useRouter()
|
||||
const { query } = useRoute()
|
||||
const { delView } = useTagsViewStore()
|
||||
const loading = ref(false)
|
||||
const title = ref('代码生成')
|
||||
const submitLoading = ref(false)
|
||||
const activeName = ref('basicInfo')
|
||||
const cloumInfoRef = ref(null)
|
||||
const tableCurrentRow = ref<CodegenTableVO>()
|
||||
const cloumCurrentRow = ref<CodegenColumnVO[]>([])
|
||||
const basicInfoRef = ref<ComponentRef<typeof BasicInfoForm>>()
|
||||
const columInfoRef = ref<ComponentRef<typeof ColumInfoForm>>()
|
||||
const generateInfoRef = ref<ComponentRef<typeof GenerateInfoForm>>()
|
||||
const formData = ref<CodegenUpdateReqVO>({
|
||||
table: {},
|
||||
columns: []
|
||||
})
|
||||
|
||||
const getList = async () => {
|
||||
const getDetail = async () => {
|
||||
const id = query.id as unknown as number
|
||||
if (id) {
|
||||
loading.value = true
|
||||
// 获取表详细信息
|
||||
const res = await getCodegenTableApi(id)
|
||||
title.value = '修改[ ' + res.table.tableName + ' ]生成配置'
|
||||
tableCurrentRow.value = res.table
|
||||
cloumCurrentRow.value = res.columns
|
||||
formData.value = await CodegenApi.getCodegenTable(id)
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
const submitForm = async () => {
|
||||
const basicInfo = unref(basicInfoRef)
|
||||
const basicForm = await basicInfo?.elFormRef?.validate()?.catch(() => {})
|
||||
if (basicForm) {
|
||||
const basicInfoData = (await basicInfo?.getFormData()) as CodegenTableVO
|
||||
const genTable: CodegenUpdateReqVO = {
|
||||
table: basicInfoData,
|
||||
columns: cloumCurrentRow.value
|
||||
}
|
||||
await updateCodegenTableApi(genTable)
|
||||
if (!unref(formData)) return
|
||||
try {
|
||||
await unref(basicInfoRef)?.validate()
|
||||
await unref(generateInfoRef)?.validate()
|
||||
await CodegenApi.updateCodegenTable(unref(formData))
|
||||
message.success(t('common.updateSuccess'))
|
||||
push('/infra/codegen')
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
/** 关闭按钮 */
|
||||
const close = () => {
|
||||
delView(unref(currentRoute))
|
||||
push('/infra/codegen')
|
||||
}
|
||||
onMounted(() => {
|
||||
getList()
|
||||
getDetail()
|
||||
})
|
||||
</script>
|
||||
|
@ -1,183 +1,93 @@
|
||||
<template>
|
||||
<Form :rules="rules" @register="register" />
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表名称" prop="tableName">
|
||||
<el-input placeholder="请输入仓库名称" v-model="formData.tableName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表描述" prop="tableComment">
|
||||
<el-input placeholder="请输入" v-model="formData.tableComment" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="className">
|
||||
<template #label>
|
||||
<span>
|
||||
实体类名称
|
||||
<el-tooltip
|
||||
content="默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。"
|
||||
placement="top"
|
||||
>
|
||||
<Icon icon="ep:question-filled" class="" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<el-input placeholder="请输入" v-model="formData.className" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="作者" prop="author">
|
||||
<el-input placeholder="请输入" v-model="formData.author" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="3" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useForm } from '@/hooks/web/useForm'
|
||||
import { FormSchema } from '@/types/form'
|
||||
import { CodegenTableVO } from '@/api/infra/codegen/types'
|
||||
import { getIntDictOptions } from '@/utils/dict'
|
||||
import { listSimpleMenusApi } from '@/api/system/menu'
|
||||
import { handleTree, defaultProps } from '@/utils/tree'
|
||||
import { PropType } from 'vue'
|
||||
|
||||
const emits = defineEmits(['update:basicInfo'])
|
||||
const props = defineProps({
|
||||
basicInfo: {
|
||||
table: {
|
||||
type: Object as PropType<Nullable<CodegenTableVO>>,
|
||||
default: () => null
|
||||
}
|
||||
})
|
||||
|
||||
const templateTypeOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE)
|
||||
const sceneOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE)
|
||||
const menuOptions = ref<any>([]) // 树形结构
|
||||
const getTree = async () => {
|
||||
const res = await listSimpleMenusApi()
|
||||
menuOptions.value = handleTree(res)
|
||||
}
|
||||
const formRef = ref()
|
||||
const formData = ref({
|
||||
tableName: '',
|
||||
tableComment: '',
|
||||
className: '',
|
||||
author: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
tableName: [required],
|
||||
tableComment: [required],
|
||||
className: [required],
|
||||
author: [required],
|
||||
templateType: [required],
|
||||
scene: [required],
|
||||
moduleName: [required],
|
||||
businessName: [required],
|
||||
businessPackage: [required],
|
||||
classComment: [required]
|
||||
})
|
||||
const schema = reactive<FormSchema[]>([
|
||||
{
|
||||
label: '上级菜单',
|
||||
field: 'parentMenuId',
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
data: menuOptions,
|
||||
props: defaultProps,
|
||||
checkStrictly: true,
|
||||
nodeKey: 'id'
|
||||
},
|
||||
labelMessage: '分配到指定菜单下,例如 系统管理',
|
||||
colProps: {
|
||||
span: 24
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '表名称',
|
||||
field: 'tableName',
|
||||
component: 'Input',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '表描述',
|
||||
field: 'tableComment',
|
||||
component: 'Input',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '实体类名称',
|
||||
field: 'className',
|
||||
component: 'Input',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '类名称',
|
||||
field: 'className',
|
||||
component: 'Input',
|
||||
labelMessage: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '生成模板',
|
||||
field: 'templateType',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: templateTypeOptions
|
||||
},
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '生成场景',
|
||||
field: 'scene',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: sceneOptions
|
||||
},
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '模块名',
|
||||
field: 'moduleName',
|
||||
component: 'Input',
|
||||
labelMessage: '模块名,即一级目录,例如 system、infra、tool 等等',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '业务名',
|
||||
field: 'businessName',
|
||||
component: 'Input',
|
||||
labelMessage: '业务名,即二级目录,例如 user、permission、dict 等等',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '类描述',
|
||||
field: 'classComment',
|
||||
component: 'Input',
|
||||
labelMessage: '用作类描述,例如 用户',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '作者',
|
||||
field: 'author',
|
||||
component: 'Input',
|
||||
colProps: {
|
||||
span: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
field: 'remark',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
type: 'textarea',
|
||||
rows: 4
|
||||
},
|
||||
colProps: {
|
||||
span: 24
|
||||
}
|
||||
}
|
||||
])
|
||||
const { register, methods, elFormRef } = useForm({
|
||||
schema
|
||||
author: [required]
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.basicInfo,
|
||||
(basicInfo) => {
|
||||
if (!basicInfo) return
|
||||
const { setValues } = methods
|
||||
setValues(basicInfo)
|
||||
() => props.table,
|
||||
(table) => {
|
||||
if (!table) return
|
||||
formData.value = table
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
// ========== 初始化 ==========
|
||||
onMounted(async () => {
|
||||
await getTree()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => formData.value,
|
||||
(val) => {
|
||||
emits('update:basicInfo', val)
|
||||
}
|
||||
)
|
||||
defineExpose({
|
||||
elFormRef,
|
||||
getFormData: methods.getFormData
|
||||
validate: async () => unref(formRef)?.validate()
|
||||
})
|
||||
</script>
|
||||
|
@ -1,137 +0,0 @@
|
||||
<template>
|
||||
<vxe-table
|
||||
ref="dragTable"
|
||||
border
|
||||
:data="info"
|
||||
max-height="600"
|
||||
stripe
|
||||
class="xtable-scrollbar"
|
||||
:column-config="{ resizable: true }"
|
||||
>
|
||||
<vxe-column title="字段列名" field="columnName" fixed="left" width="10%" />
|
||||
<vxe-colgroup title="基础属性">
|
||||
<vxe-column title="字段描述" field="columnComment" width="10%">
|
||||
<template #default="{ row }">
|
||||
<vxe-input v-model="row.columnComment" placeholder="请输入字段描述" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="物理类型" field="dataType" width="10%" />
|
||||
<vxe-column title="Java类型" width="10%" field="javaType">
|
||||
<template #default="{ row }">
|
||||
<vxe-select v-model="row.javaType" placeholder="请选择Java类型">
|
||||
<vxe-option label="Long" value="Long" />
|
||||
<vxe-option label="String" value="String" />
|
||||
<vxe-option label="Integer" value="Integer" />
|
||||
<vxe-option label="Double" value="Double" />
|
||||
<vxe-option label="BigDecimal" value="BigDecimal" />
|
||||
<vxe-option label="LocalDateTime" value="LocalDateTime" />
|
||||
<vxe-option label="Boolean" value="Boolean" />
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="java属性" width="8%" field="javaField">
|
||||
<template #default="{ row }">
|
||||
<vxe-input v-model="row.javaField" placeholder="请输入java属性" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="增删改查">
|
||||
<vxe-column title="插入" width="40px" field="createOperation">
|
||||
<template #default="{ row }">
|
||||
<vxe-checkbox true-label="true" false-label="false" v-model="row.createOperation" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="编辑" width="40px" field="updateOperation">
|
||||
<template #default="{ row }">
|
||||
<vxe-checkbox true-label="true" false-label="false" v-model="row.updateOperation" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="列表" width="40px" field="listOperationResult">
|
||||
<template #default="{ row }">
|
||||
<vxe-checkbox true-label="true" false-label="false" v-model="row.listOperationResult" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="查询" width="40px" field="listOperation">
|
||||
<template #default="{ row }">
|
||||
<vxe-checkbox true-label="true" false-label="false" v-model="row.listOperation" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="允许空" width="40px" field="nullable">
|
||||
<template #default="{ row }">
|
||||
<vxe-checkbox true-label="true" false-label="false" v-model="row.nullable" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="查询方式" width="60px" field="listOperationCondition">
|
||||
<template #default="{ row }">
|
||||
<vxe-select v-model="row.listOperationCondition" placeholder="请选择查询方式">
|
||||
<vxe-option label="=" value="=" />
|
||||
<vxe-option label="!=" value="!=" />
|
||||
<vxe-option label=">" value=">" />
|
||||
<vxe-option label=">=" value=">=" />
|
||||
<vxe-option label="<" value="<>" />
|
||||
<vxe-option label="<=" value="<=" />
|
||||
<vxe-option label="LIKE" value="LIKE" />
|
||||
<vxe-option label="BETWEEN" value="BETWEEN" />
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-column title="显示类型" width="10%" field="htmlType">
|
||||
<template #default="{ row }">
|
||||
<vxe-select v-model="row.htmlType" placeholder="请选择显示类型">
|
||||
<vxe-option label="文本框" value="input" />
|
||||
<vxe-option label="文本域" value="textarea" />
|
||||
<vxe-option label="下拉框" value="select" />
|
||||
<vxe-option label="单选框" value="radio" />
|
||||
<vxe-option label="复选框" value="checkbox" />
|
||||
<vxe-option label="日期控件" value="datetime" />
|
||||
<vxe-option label="图片上传" value="imageUpload" />
|
||||
<vxe-option label="文件上传" value="fileUpload" />
|
||||
<vxe-option label="富文本控件" value="editor" />
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="字典类型" width="10%" field="dictType">
|
||||
<template #default="{ row }">
|
||||
<vxe-select v-model="row.dictType" clearable filterable placeholder="请选择字典类型">
|
||||
<vxe-option
|
||||
v-for="dict in dictOptions"
|
||||
:key="dict.id"
|
||||
:label="dict.name"
|
||||
:value="dict.type"
|
||||
/>
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="示例" field="example">
|
||||
<template #default="{ row }">
|
||||
<vxe-input v-model="row.example" placeholder="请输入示例" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { DictTypeVO } from '@/api/system/dict/types'
|
||||
import { CodegenColumnVO } from '@/api/infra/codegen/types'
|
||||
import { listSimpleDictType } from '@/api/system/dict/dict.type'
|
||||
|
||||
const props = defineProps({
|
||||
info: {
|
||||
type: Array as unknown as PropType<CodegenColumnVO[]>,
|
||||
default: () => null
|
||||
}
|
||||
})
|
||||
/** 查询字典下拉列表 */
|
||||
const dictOptions = ref<DictTypeVO[]>()
|
||||
const getDictOptions = async () => {
|
||||
const res = await listSimpleDictType()
|
||||
dictOptions.value = res
|
||||
}
|
||||
onMounted(async () => {
|
||||
await getDictOptions()
|
||||
})
|
||||
defineExpose({
|
||||
info: props.info
|
||||
})
|
||||
</script>
|
157
src/views/infra/codegen/components/ColumInfoForm.vue
Normal file
157
src/views/infra/codegen/components/ColumInfoForm.vue
Normal file
@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<el-table ref="dragTable" :data="formData" row-key="columnId" :max-height="tableHeight">
|
||||
<el-table-column
|
||||
label="字段列名"
|
||||
prop="columnName"
|
||||
min-width="10%"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column label="字段描述" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.columnComment" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="物理类型"
|
||||
prop="dataType"
|
||||
min-width="10%"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column label="Java类型" min-width="11%">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.javaType">
|
||||
<el-option label="Long" value="Long" />
|
||||
<el-option label="String" value="String" />
|
||||
<el-option label="Integer" value="Integer" />
|
||||
<el-option label="Double" value="Double" />
|
||||
<el-option label="BigDecimal" value="BigDecimal" />
|
||||
<el-option label="LocalDateTime" value="LocalDateTime" />
|
||||
<el-option label="Boolean" value="Boolean" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="java属性" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.javaField" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="插入" min-width="4%">
|
||||
<template #default="scope">
|
||||
<el-checkbox true-label="true" false-label="false" v-model="scope.row.createOperation" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编辑" min-width="4%">
|
||||
<template #default="scope">
|
||||
<el-checkbox true-label="true" false-label="false" v-model="scope.row.updateOperation" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="列表" min-width="4%">
|
||||
<template #default="scope">
|
||||
<el-checkbox
|
||||
true-label="true"
|
||||
false-label="false"
|
||||
v-model="scope.row.listOperationResult"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询" min-width="4%">
|
||||
<template #default="scope">
|
||||
<el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperation" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询方式" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.listOperationCondition">
|
||||
<el-option label="=" value="=" />
|
||||
<el-option label="!=" value="!=" />
|
||||
<el-option label=">" value=">" />
|
||||
<el-option label=">=" value=">=" />
|
||||
<el-option label="<" value="<>" />
|
||||
<el-option label="<=" value="<=" />
|
||||
<el-option label="LIKE" value="LIKE" />
|
||||
<el-option label="BETWEEN" value="BETWEEN" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="允许空" min-width="5%">
|
||||
<template #default="scope">
|
||||
<el-checkbox true-label="true" false-label="false" v-model="scope.row.nullable" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="显示类型" min-width="12%">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.htmlType">
|
||||
<el-option label="文本框" value="input" />
|
||||
<el-option label="文本域" value="textarea" />
|
||||
<el-option label="下拉框" value="select" />
|
||||
<el-option label="单选框" value="radio" />
|
||||
<el-option label="复选框" value="checkbox" />
|
||||
<el-option label="日期控件" value="datetime" />
|
||||
<el-option label="图片上传" value="imageUpload" />
|
||||
<el-option label="文件上传" value="fileUpload" />
|
||||
<el-option label="富文本控件" value="editor" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字典类型" min-width="12%">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
|
||||
<el-option
|
||||
v-for="dict in dictOptions"
|
||||
:key="dict.id"
|
||||
:label="dict.name"
|
||||
:value="dict.type"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="示例" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.example" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { CodegenColumnVO } from '@/api/infra/codegen/types'
|
||||
import { DictTypeVO, listSimpleDictType } from '@/api/system/dict/dict.type'
|
||||
|
||||
const emits = defineEmits(['update:columns'])
|
||||
const props = defineProps({
|
||||
columns: {
|
||||
type: Array as unknown as PropType<CodegenColumnVO[]>,
|
||||
default: () => null
|
||||
}
|
||||
})
|
||||
|
||||
const formData = ref<CodegenColumnVO[]>([])
|
||||
const tableHeight = document.documentElement.scrollHeight - 350 + 'px'
|
||||
|
||||
/** 查询字典下拉列表 */
|
||||
const dictOptions = ref<DictTypeVO[]>()
|
||||
const getDictOptions = async () => {
|
||||
dictOptions.value = await listSimpleDictType()
|
||||
}
|
||||
onMounted(async () => {
|
||||
await getDictOptions()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.columns,
|
||||
(columns) => {
|
||||
if (!columns) return
|
||||
formData.value = columns
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => formData.value,
|
||||
(val) => {
|
||||
emits('update:columns', val)
|
||||
}
|
||||
)
|
||||
</script>
|
379
src/views/infra/codegen/components/GenerateInfoForm.vue
Normal file
379
src/views/infra/codegen/components/GenerateInfoForm.vue
Normal file
@ -0,0 +1,379 @@
|
||||
<template>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="150px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="templateType" label="生成模板">
|
||||
<el-select v-model="formData.templateType" @change="tplSelectChange">
|
||||
<el-option
|
||||
v-for="dict in getDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE)"
|
||||
:key="parseInt(dict.value)"
|
||||
:label="dict.label"
|
||||
:value="parseInt(dict.value)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="scene" label="生成场景">
|
||||
<el-select v-model="formData.scene">
|
||||
<el-option
|
||||
v-for="dict in getDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE)"
|
||||
:key="parseInt(dict.value)"
|
||||
:label="dict.label"
|
||||
:value="parseInt(dict.value)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <el-form-item prop="packageName">-->
|
||||
<!-- <span slot="label">-->
|
||||
<!-- 生成包路径-->
|
||||
<!-- <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">-->
|
||||
<!-- <i class="el-icon-question"></i>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </span>-->
|
||||
<!-- <el-input v-model="formData.packageName" />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="moduleName">
|
||||
<template #label>
|
||||
<span>
|
||||
模块名
|
||||
<el-tooltip
|
||||
content="模块名,即一级目录,例如 system、infra、tool 等等"
|
||||
placement="top"
|
||||
>
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="formData.moduleName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="businessName">
|
||||
<template #label>
|
||||
<span>
|
||||
业务名
|
||||
<el-tooltip
|
||||
content="业务名,即二级目录,例如 user、permission、dict 等等"
|
||||
placement="top"
|
||||
>
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="formData.businessName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <el-form-item prop="businessPackage">-->
|
||||
<!-- <span slot="label">-->
|
||||
<!-- 业务包-->
|
||||
<!-- <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">-->
|
||||
<!-- <i class="el-icon-question"></i>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </span>-->
|
||||
<!-- <el-input v-model="formData.businessPackage" />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="className">
|
||||
<template #label>
|
||||
<span>
|
||||
类名称
|
||||
<el-tooltip
|
||||
content="类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等"
|
||||
placement="top"
|
||||
>
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="formData.className" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="classComment">
|
||||
<template #label>
|
||||
<span>
|
||||
类描述
|
||||
<el-tooltip content="用作类描述,例如 用户" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="formData.classComment" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
上级菜单
|
||||
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-tree-select
|
||||
v-model="formData.parentMenuId"
|
||||
placeholder="请选择系统菜单"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
:data="menus"
|
||||
:props="menuTreeProps"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" v-if="formData.genType === '1'">
|
||||
<el-form-item prop="genPath">
|
||||
<template #label>
|
||||
<span>
|
||||
自定义路径
|
||||
<el-tooltip
|
||||
content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下"
|
||||
placement="top"
|
||||
>
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="formData.genPath">
|
||||
<template #append>
|
||||
<el-dropdown>
|
||||
<el-button type="primary">
|
||||
最近路径快速选择
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="formData.genPath = '/'">
|
||||
恢复默认的生成基础路径
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-show="formData.tplCategory === 'tree'">
|
||||
<h4 class="form-header">其他信息</h4>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
树编码字段
|
||||
<el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-select v-model="formData.treeCode" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(column, index) in formData.columns"
|
||||
:key="index"
|
||||
:label="column.columnName + ':' + column.columnComment"
|
||||
:value="column.columnName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
树父编码字段
|
||||
<el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-select v-model="formData.treeParentCode" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(column, index) in formData.columns"
|
||||
:key="index"
|
||||
:label="column.columnName + ':' + column.columnComment"
|
||||
:value="column.columnName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
树名称字段
|
||||
<el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<el-select v-model="formData.treeName" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(column, index) in formData.columns"
|
||||
:key="index"
|
||||
:label="column.columnName + ':' + column.columnComment"
|
||||
:value="column.columnName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-show="formData.tplCategory === 'sub'">
|
||||
<h4 class="form-header">关联信息</h4>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
关联子表的表名
|
||||
<el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-select v-model="formData.subTableName" placeholder="请选择" @change="subSelectChange">
|
||||
<el-option
|
||||
v-for="(table0, index) in tables"
|
||||
:key="index"
|
||||
:label="table0.tableName + ':' + table0.tableComment"
|
||||
:value="table0.tableName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
子表关联的外键名
|
||||
<el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
|
||||
<Icon icon="ep:question-filled" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-select v-model="formData.subTableFkName" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(column, index) in subColumns"
|
||||
:key="index"
|
||||
:label="column.columnName + ':' + column.columnComment"
|
||||
:value="column.columnName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { CodegenTableVO } from '@/api/infra/codegen/types'
|
||||
import * as MenuApi from '@/api/system/menu'
|
||||
import { PropType } from 'vue'
|
||||
import { getDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { handleTree } from '@/utils/tree'
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const emits = defineEmits(['update:basicInfo'])
|
||||
const props = defineProps({
|
||||
table: {
|
||||
type: Object as PropType<Nullable<CodegenTableVO>>,
|
||||
default: () => null
|
||||
}
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const formData = ref({
|
||||
templateType: null,
|
||||
scene: null,
|
||||
moduleName: '',
|
||||
businessName: '',
|
||||
className: '',
|
||||
classComment: '',
|
||||
parentMenuId: null,
|
||||
genPath: '',
|
||||
treeCode: '',
|
||||
treeParentCode: '',
|
||||
treeName: '',
|
||||
tplCategory: '',
|
||||
subTableName: '',
|
||||
subTableFkName: '',
|
||||
genType: ''
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
templateType: [required],
|
||||
scene: [required],
|
||||
moduleName: [required],
|
||||
businessName: [required],
|
||||
businessPackage: [required],
|
||||
className: [required],
|
||||
classComment: [required]
|
||||
})
|
||||
|
||||
const tables = ref([])
|
||||
const subColumns = ref([])
|
||||
const menus = ref<any[]>([])
|
||||
const menuTreeProps = {
|
||||
label: 'name'
|
||||
}
|
||||
|
||||
/** 选择子表名触发 */
|
||||
const subSelectChange = () => {
|
||||
formData.value.subTableFkName = ''
|
||||
}
|
||||
/** 选择生成模板触发 */
|
||||
const tplSelectChange = (value) => {
|
||||
if (value !== 1) {
|
||||
// TODO 芋艿:暂时不考虑支持树形结构
|
||||
message.error(
|
||||
'暂时不考虑支持【树形】和【主子表】的代码生成。原因是:导致 vm 模板过于复杂,不利于胖友二次开发'
|
||||
)
|
||||
return false
|
||||
}
|
||||
if (value !== 'sub') {
|
||||
formData.value.subTableName = ''
|
||||
formData.value.subTableFkName = ''
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.table,
|
||||
(table) => {
|
||||
if (!table) return
|
||||
formData.value = table as any
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => formData.value,
|
||||
(val) => {
|
||||
emits('update:basicInfo', val)
|
||||
}
|
||||
)
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const resp = await MenuApi.listSimpleMenusApi()
|
||||
menus.value = handleTree(resp)
|
||||
} catch {}
|
||||
})
|
||||
defineExpose({
|
||||
validate: async () => unref(formRef)?.validate()
|
||||
})
|
||||
</script>
|
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<!-- 导入表 -->
|
||||
<XModal title="导入表" v-model="visible">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
||||
<Dialog :title="modelTitle" v-model="modelVisible">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true">
|
||||
<el-form-item label="数据源" prop="dataSourceConfigId">
|
||||
<el-select v-model="queryParams.dataSourceConfigId" placeholder="请选择数据源" clearable>
|
||||
<el-select v-model="queryParams.dataSourceConfigId" placeholder="请选择数据源">
|
||||
<el-option
|
||||
v-for="config in dataSourceConfigs"
|
||||
:key="config.id"
|
||||
@ -13,52 +12,64 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入表名称" clearable />
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入表名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="表描述" prop="comment">
|
||||
<el-input v-model="queryParams.comment" placeholder="请输入表描述" clearable />
|
||||
<el-input
|
||||
v-model="queryParams.comment"
|
||||
placeholder="请输入表描述"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ep:search"
|
||||
:title="t('common.query')"
|
||||
@click="handleQuery()"
|
||||
/>
|
||||
<XButton preIcon="ep:refresh-right" :title="t('common.reset')" @click="resetQuery()" />
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<vxe-table
|
||||
ref="xTable"
|
||||
:data="dbTableList"
|
||||
v-loading="dbLoading"
|
||||
:checkbox-config="{ highlight: true, range: true }"
|
||||
height="260px"
|
||||
class="xtable-scrollbar"
|
||||
>
|
||||
<vxe-column type="checkbox" width="60" />
|
||||
<vxe-column field="name" title="表名称" />
|
||||
<vxe-column field="comment" title="表描述" />
|
||||
</vxe-table>
|
||||
|
||||
<el-row>
|
||||
<el-table
|
||||
v-loading="dbLoading"
|
||||
@row-click="clickRow"
|
||||
ref="tableRef"
|
||||
:data="dbTableList"
|
||||
@selection-change="handleSelectionChange"
|
||||
height="260px"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="表名称" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="comment" label="表描述" :show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
</el-row>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<XButton type="primary" :title="t('action.import')" @click="handleImportTable()" />
|
||||
<XButton :title="t('dialog.close')" @click="handleClose()" />
|
||||
<el-button @click="handleImportTable" type="primary" :disabled="tables.length === 0">{{
|
||||
t('action.import')
|
||||
}}</el-button>
|
||||
<el-button @click="handleClose">{{ t('dialog.close') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</XModal>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { VxeTableInstance } from 'vxe-table'
|
||||
import type { DatabaseTableVO } from '@/api/infra/codegen/types'
|
||||
import { getSchemaTableListApi, createCodegenListApi } from '@/api/infra/codegen'
|
||||
import { getDataSourceConfigListApi, DataSourceConfigVO } from '@/api/infra/dataSourceConfig'
|
||||
import * as CodegenApi from '@/api/infra/codegen'
|
||||
import { getDataSourceConfigList, DataSourceConfigVO } from '@/api/infra/dataSourceConfig'
|
||||
import { ElTable } from 'element-plus'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const emit = defineEmits(['ok'])
|
||||
// ======== 显示页面 ========
|
||||
const visible = ref(false)
|
||||
|
||||
const modelVisible = ref(false) // 弹窗的是否展示
|
||||
const modelTitle = ref('导入表') // 弹窗的标题
|
||||
const dbLoading = ref(true)
|
||||
const queryParams = reactive({
|
||||
name: undefined,
|
||||
@ -67,10 +78,9 @@ const queryParams = reactive({
|
||||
})
|
||||
const dataSourceConfigs = ref<DataSourceConfigVO[]>([])
|
||||
const show = async () => {
|
||||
const res = await getDataSourceConfigListApi()
|
||||
dataSourceConfigs.value = res
|
||||
queryParams.dataSourceConfigId = dataSourceConfigs.value[0].id
|
||||
visible.value = true
|
||||
dataSourceConfigs.value = await getDataSourceConfigList()
|
||||
queryParams.dataSourceConfigId = dataSourceConfigs.value[0].id as number
|
||||
modelVisible.value = true
|
||||
await getList()
|
||||
}
|
||||
/** 查询表数据 */
|
||||
@ -79,8 +89,7 @@ const dbTableList = ref<DatabaseTableVO[]>([])
|
||||
/** 查询表数据 */
|
||||
const getList = async () => {
|
||||
dbLoading.value = true
|
||||
const res = await getSchemaTableListApi(queryParams)
|
||||
dbTableList.value = res
|
||||
dbTableList.value = await CodegenApi.getSchemaTableList(queryParams)
|
||||
dbLoading.value = false
|
||||
}
|
||||
// 查询操作
|
||||
@ -91,23 +100,22 @@ const handleQuery = async () => {
|
||||
const resetQuery = async () => {
|
||||
queryParams.name = undefined
|
||||
queryParams.comment = undefined
|
||||
queryParams.dataSourceConfigId = 0
|
||||
queryParams.dataSourceConfigId = dataSourceConfigs.value[0].id as number
|
||||
await getList()
|
||||
}
|
||||
const xTable = ref<VxeTableInstance>()
|
||||
const tableRef = ref<typeof ElTable>()
|
||||
/** 多选框选中数据 */
|
||||
const tables = ref<string[]>([])
|
||||
|
||||
const clickRow = (row) => {
|
||||
unref(tableRef)?.toggleRowSelection(row)
|
||||
}
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection) => {
|
||||
tables.value = selection.map((item) => item.name)
|
||||
}
|
||||
/** 导入按钮操作 */
|
||||
const handleImportTable = async () => {
|
||||
if (xTable.value?.getCheckboxRecords().length === 0) {
|
||||
message.error('请选择要导入的表')
|
||||
return
|
||||
}
|
||||
xTable.value?.getCheckboxRecords().forEach((item) => {
|
||||
tables.value.push(item.name)
|
||||
})
|
||||
await createCodegenListApi({
|
||||
await CodegenApi.createCodegenList({
|
||||
dataSourceConfigId: queryParams.dataSourceConfigId,
|
||||
tableNames: tables.value
|
||||
})
|
||||
@ -116,7 +124,7 @@ const handleImportTable = async () => {
|
||||
handleClose()
|
||||
}
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
modelVisible.value = false
|
||||
tables.value = []
|
||||
}
|
||||
defineExpose({
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<XModal title="预览" v-model="preview.open">
|
||||
<Dialog
|
||||
:title="modelTitle"
|
||||
v-model="modelVisible"
|
||||
align-center
|
||||
width="60%"
|
||||
class="app-infra-codegen-preview-container"
|
||||
>
|
||||
<div class="flex">
|
||||
<el-card class="w-1/4" :gutter="12" shadow="hover">
|
||||
<el-scrollbar height="calc(100vh - 88px - 40px - 50px)">
|
||||
@ -10,6 +16,7 @@
|
||||
:expand-on-click-node="false"
|
||||
highlight-current
|
||||
@node-click="handleNodeClick"
|
||||
default-expand-all
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
@ -21,38 +28,34 @@
|
||||
:name="item.filePath"
|
||||
:key="item.filePath"
|
||||
>
|
||||
<XTextButton style="float: right" :title="t('common.copy')" @click="copy(item.code)" />
|
||||
<el-button text type="primary" class="float-right" @click="copy(item.code)">
|
||||
{{ t('common.copy') }}
|
||||
</el-button>
|
||||
<pre>{{ item.code }}</pre>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</XModal>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { handleTree2 } from '@/utils/tree'
|
||||
import { previewCodegenApi } from '@/api/infra/codegen'
|
||||
import { CodegenTableVO, CodegenPreviewVO } from '@/api/infra/codegen/types'
|
||||
import * as CodegenApi from '@/api/infra/codegen'
|
||||
import { CodegenPreviewVO } from '@/api/infra/codegen/types'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const modelVisible = ref(false) // 弹窗的是否展示
|
||||
const modelTitle = ref('代码预览') // 弹窗的标题
|
||||
// ======== 显示页面 ========
|
||||
const preview = reactive({
|
||||
open: false,
|
||||
titel: '代码预览',
|
||||
fileTree: [],
|
||||
activeName: ''
|
||||
})
|
||||
const previewCodegen = ref<CodegenPreviewVO[]>()
|
||||
const show = async (row: CodegenTableVO) => {
|
||||
const res = await previewCodegenApi(row.id)
|
||||
let file = handleFiles(res)
|
||||
previewCodegen.value = res
|
||||
preview.fileTree = handleTree2(file, 'id', 'parentId', 'children', '/')
|
||||
preview.activeName = res[0].filePath
|
||||
preview.open = true
|
||||
}
|
||||
|
||||
const handleNodeClick = async (data, node) => {
|
||||
if (node && !node.isLeaf) {
|
||||
return false
|
||||
@ -132,14 +135,30 @@ const copy = async (text: string) => {
|
||||
const { copy, copied, isSupported } = useClipboard({ source: text })
|
||||
if (!isSupported) {
|
||||
message.error(t('common.copyError'))
|
||||
} else {
|
||||
await copy()
|
||||
if (unref(copied)) {
|
||||
message.success(t('common.copySuccess'))
|
||||
}
|
||||
return
|
||||
}
|
||||
await copy()
|
||||
if (unref(copied)) {
|
||||
message.success(t('common.copySuccess'))
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const openModal = async (id: number) => {
|
||||
modelVisible.value = true
|
||||
const res = await CodegenApi.previewCodegen(id)
|
||||
let file = handleFiles(res)
|
||||
previewCodegen.value = res
|
||||
preview.fileTree = handleTree2(file, 'id', 'parentId', 'children', '/')
|
||||
preview.activeName = res[0].filePath
|
||||
}
|
||||
defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.app-infra-codegen-preview-container {
|
||||
.el-scrollbar .el-scrollbar__wrap .el-scrollbar__view {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import BasicInfoForm from './BasicInfoForm.vue'
|
||||
import CloumInfoForm from './CloumInfoForm.vue'
|
||||
import ColumInfoForm from './ColumInfoForm.vue'
|
||||
import GenerateInfoForm from './GenerateInfoForm.vue'
|
||||
import ImportTable from './ImportTable.vue'
|
||||
import Preview from './Preview.vue'
|
||||
export { BasicInfoForm, CloumInfoForm, ImportTable, Preview }
|
||||
export { BasicInfoForm, ColumInfoForm, GenerateInfoForm, ImportTable, Preview }
|
||||
|
@ -1,56 +1,124 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 列表 -->
|
||||
<XTable @register="registerTable">
|
||||
<template #toolbar_buttons>
|
||||
<!-- 操作:导入 -->
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ep:zoom-in"
|
||||
:title="t('action.import')"
|
||||
v-hasPermi="['infra:codegen:create']"
|
||||
@click="openImportTable()"
|
||||
<!-- 搜索 -->
|
||||
<content-wrap>
|
||||
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
|
||||
<el-form-item label="表名称" prop="tableName">
|
||||
<el-input
|
||||
v-model="queryParams.tableName"
|
||||
placeholder="请输入表名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</template>
|
||||
<template #actionbtns_default="{ row }">
|
||||
<!-- 操作:预览 -->
|
||||
<XTextButton
|
||||
preIcon="ep:view"
|
||||
:title="t('action.preview')"
|
||||
v-hasPermi="['infra:codegen:query']"
|
||||
@click="handlePreview(row)"
|
||||
</el-form-item>
|
||||
<el-form-item label="表描述" prop="tableComment">
|
||||
<el-input
|
||||
v-model="queryParams.tableComment"
|
||||
placeholder="请输入表描述"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<!-- 操作:编辑 -->
|
||||
<XTextButton
|
||||
preIcon="ep:edit"
|
||||
:title="t('action.edit')"
|
||||
v-hasPermi="['infra:codegen:update']"
|
||||
@click="handleUpdate(row.id)"
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
/>
|
||||
<!-- 操作:删除 -->
|
||||
<XTextButton
|
||||
preIcon="ep:delete"
|
||||
:title="t('action.del')"
|
||||
v-hasPermi="['infra:codegen:delete']"
|
||||
@click="deleteData(row.id)"
|
||||
/>
|
||||
<!-- 操作:同步 -->
|
||||
<XTextButton
|
||||
preIcon="ep:refresh"
|
||||
:title="t('action.sync')"
|
||||
v-hasPermi="['infra:codegen:update']"
|
||||
@click="handleSynchDb(row)"
|
||||
/>
|
||||
<!-- 操作:生成 -->
|
||||
<XTextButton
|
||||
preIcon="ep:download"
|
||||
:title="t('action.generate')"
|
||||
v-hasPermi="['infra:codegen:download']"
|
||||
@click="handleGenTable(row)"
|
||||
/>
|
||||
</template>
|
||||
</XTable>
|
||||
</ContentWrap>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
|
||||
<el-button type="primary" v-hasPermi="['infra:codegen:create']" @click="openImportTable()">
|
||||
<Icon icon="ep:zoom-in" class="mr-5px" />{{ t('action.import') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</content-wrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<content-wrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="数据源" align="center" :formatter="dataSourceConfigNameFormat" />
|
||||
<el-table-column label="表名称" align="center" prop="tableName" width="200" />
|
||||
<el-table-column
|
||||
label="表描述"
|
||||
align="center"
|
||||
prop="tableComment"
|
||||
:show-overflow-tooltip="true"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column label="实体" align="center" prop="className" width="200" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
label="更新时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="300px"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handlePreview(scope.row)"
|
||||
v-hasPermi="['infra:codegen:preview']"
|
||||
>预览</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleUpdate(scope.row.id)"
|
||||
v-hasPermi="['infra:codegen:update']"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:codegen:delete']"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleSynchDb(scope.row)"
|
||||
v-hasPermi="['infra:codegen:update']"
|
||||
>同步</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleGenTable(scope.row)"
|
||||
v-hasPermi="['infra:codegen:download']"
|
||||
>生成代码</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</content-wrap>
|
||||
|
||||
<!-- 弹窗:导入表 -->
|
||||
<ImportTable ref="importRef" @ok="reload()" />
|
||||
<!-- 弹窗:预览代码 -->
|
||||
@ -59,19 +127,70 @@
|
||||
<script setup lang="ts" name="Codegen">
|
||||
import download from '@/utils/download'
|
||||
import * as CodegenApi from '@/api/infra/codegen'
|
||||
import * as DataSourceConfigApi from '@/api/infra/dataSourceConfig'
|
||||
import { CodegenTableVO } from '@/api/infra/codegen/types'
|
||||
import { allSchemas } from './codegen.data'
|
||||
import { ImportTable, Preview } from './components'
|
||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
|
||||
import { DataSourceConfigVO } from '@/api/infra/dataSourceConfig'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
const { push } = useRouter() // 路由跳转
|
||||
// 列表相关的变量
|
||||
const [registerTable, { reload, deleteData }] = useXTable({
|
||||
allSchemas: allSchemas,
|
||||
getListApi: CodegenApi.getCodegenTablePageApi,
|
||||
deleteApi: CodegenApi.deleteCodegenTableApi
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
tableName: undefined,
|
||||
tableComment: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
const dataSourceConfigs = ref<DataSourceConfigVO[]>([]) // 数据源列表
|
||||
|
||||
/** 查询参数列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await CodegenApi.getCodegenTablePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
getList()
|
||||
dataSourceConfigs.value = await DataSourceConfigApi.getDataSourceConfigList()
|
||||
})
|
||||
|
||||
// 数据源配置的名字
|
||||
const dataSourceConfigNameFormat = (row) => {
|
||||
for (const config of dataSourceConfigs.value) {
|
||||
if (row.dataSourceConfigId === config.id) {
|
||||
return config.name
|
||||
}
|
||||
}
|
||||
return '未知【' + row.leaderUserId + '】'
|
||||
}
|
||||
|
||||
// 导入操作
|
||||
const importRef = ref()
|
||||
@ -81,27 +200,39 @@ const openImportTable = () => {
|
||||
// 预览操作
|
||||
const previewRef = ref()
|
||||
const handlePreview = (row: CodegenTableVO) => {
|
||||
previewRef.value.show(row)
|
||||
previewRef.value.openModal(row.id)
|
||||
}
|
||||
// 编辑操作
|
||||
const handleUpdate = (rowId: number) => {
|
||||
push('/codegen/edit?id=' + rowId)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await CodegenApi.deleteCodegenTable(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
// 同步操作
|
||||
const handleSynchDb = (row: CodegenTableVO) => {
|
||||
const handleSynchDb = async (row: CodegenTableVO) => {
|
||||
// 基于 DB 同步
|
||||
const tableName = row.tableName
|
||||
message
|
||||
.confirm('确认要强制同步' + tableName + '表结构吗?', t('common.reminder'))
|
||||
.then(async () => {
|
||||
await CodegenApi.syncCodegenFromDBApi(row.id)
|
||||
message.success('同步成功')
|
||||
})
|
||||
try {
|
||||
await message.confirm('确认要强制同步' + tableName + '表结构吗?', t('common.reminder'))
|
||||
await CodegenApi.syncCodegenFromDB(row.id)
|
||||
message.success('同步成功')
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// 生成代码操作
|
||||
const handleGenTable = async (row: CodegenTableVO) => {
|
||||
const res = await CodegenApi.downloadCodegenApi(row.id)
|
||||
const res = await CodegenApi.downloadCodegen(row.id)
|
||||
download.zip(res, 'codegen-' + row.className + '.zip')
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user