初始化地区合伙人
This commit is contained in:
531
src/views/dev_tools/code/edit.vue
Normal file
531
src/views/dev_tools/code/edit.vue
Normal file
@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<div class="code-edit">
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-page-header content="编辑数据表" @back="$router.back()" />
|
||||
</el-card>
|
||||
<el-card class="mt-4 !border-none" shadow="never">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
class="ls-form"
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
:rules="rules"
|
||||
>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="基础信息" name="base">
|
||||
<el-form-item label="表名称" prop="table_name">
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.table_name"
|
||||
placeholder="请输入表名称"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="表描述" prop="table_comment">
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.table_comment"
|
||||
placeholder="请输入表描述"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="作者">
|
||||
<div class="w-80">
|
||||
<el-input v-model="formData.author" clearable />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
class="w-full"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 4 }"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="字段管理" name="column">
|
||||
<el-table :data="formData.table_column">
|
||||
<el-table-column label="字段列名" prop="column_name" />
|
||||
<el-table-column label="字段描述" prop="column_comment" min-width="120">
|
||||
<template v-slot="{ row }">
|
||||
<el-input v-model="row.column_comment" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="物理类型" prop="column_type" />
|
||||
<el-table-column label="必填" width="80">
|
||||
<template v-slot="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.is_required"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="插入" width="80">
|
||||
<template v-slot="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.is_insert"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编辑" width="80">
|
||||
<template v-slot="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.is_update"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="列表" width="80">
|
||||
<template v-slot="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.is_lists"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询" width="80">
|
||||
<template v-slot="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.is_query"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询方式">
|
||||
<template v-slot="{ row }">
|
||||
<el-select v-model="row.query_type">
|
||||
<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="120">
|
||||
<template v-slot="{ row }">
|
||||
<el-select v-model="row.view_type">
|
||||
<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="imageSelect" />
|
||||
<el-option label="富文本控件" value="editor" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字典类型" min-width="120">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.dict_type"
|
||||
clearable
|
||||
:disabled="
|
||||
!(
|
||||
row.view_type == 'select' ||
|
||||
row.view_type == 'radio' ||
|
||||
row.view_type == 'checkbox'
|
||||
)
|
||||
"
|
||||
placeholder="字典类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in optionsData.dict_type"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.type"
|
||||
:disabled="!item.status"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="生成配置" name="config">
|
||||
<el-form-item label="模板类型" prop="template_type">
|
||||
<el-radio-group v-model="formData.template_type">
|
||||
<el-radio :value="0">单表(curd)</el-radio>
|
||||
<el-radio :value="1">树表(curd)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="删除类型" prop="delete.type">
|
||||
<el-radio-group v-model="formData.delete.type">
|
||||
<el-radio :value="0">物理删除</el-radio>
|
||||
<el-radio :value="1">软删除</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="删除字段"
|
||||
prop="delete.name"
|
||||
v-if="formData.delete.type == 1"
|
||||
>
|
||||
<el-select class="w-80" v-model="formData.delete.name" clearable>
|
||||
<el-option
|
||||
v-for="item in formData.table_column"
|
||||
:key="item.id"
|
||||
:value="item.column_name"
|
||||
:label="`${item.column_name}:${item.column_comment}`"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<template v-if="formData.template_type == 1">
|
||||
<el-form-item label="树表ID" prop="treePrimary">
|
||||
<div>
|
||||
<el-select
|
||||
class="w-80"
|
||||
v-model="formData.tree.tree_id"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in formData.table_column"
|
||||
:key="item.id"
|
||||
:value="item.column_name"
|
||||
:label="`${item.column_name}:${item.column_comment}`"
|
||||
/>
|
||||
</el-select>
|
||||
<div class="form-tips">指定树表的主要ID,一般为主键</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="树表父ID" prop="treeParent">
|
||||
<div>
|
||||
<el-select
|
||||
class="w-80"
|
||||
v-model="formData.tree.tree_pid"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in formData.table_column"
|
||||
:key="item.id"
|
||||
:value="item.column_name"
|
||||
:label="`${item.column_name}:${item.column_comment}`"
|
||||
/>
|
||||
</el-select>
|
||||
<div class="form-tips">指定树表的父ID,比如:parent_id</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="树名称" prop="treeName">
|
||||
<el-select class="w-80" v-model="formData.tree.tree_name" clearable>
|
||||
<el-option
|
||||
v-for="item in formData.table_column"
|
||||
:key="item.id"
|
||||
:value="item.column_name"
|
||||
:label="`${item.column_name}:${item.column_comment}`"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="类描述">
|
||||
<div class="w-80">
|
||||
<div>
|
||||
<el-input
|
||||
v-model="formData.class_comment"
|
||||
placeholder="请输入文件描述"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
<div>
|
||||
例:填写test,生成文件描述为test控制器(test逻辑/test模型)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="生成方式" prop="generate_type">
|
||||
<el-radio-group v-model="formData.generate_type">
|
||||
<el-radio :value="0">压缩包下载</el-radio>
|
||||
<el-radio :value="1">生成到模块</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="模块名" prop="module_name">
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.module_name"
|
||||
placeholder="请输入模块名"
|
||||
clearable
|
||||
/>
|
||||
<div class="form-tips">生成文件所在模块</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="类目录">
|
||||
<div class="w-80">
|
||||
<div>
|
||||
<el-input
|
||||
v-model="formData.class_dir"
|
||||
placeholder="请输入文件所在目录"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
<div>
|
||||
例:填写test,则在app/模块名/controller/test下生成控制器
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="父级菜单" prop="menu.pid">
|
||||
<el-tree-select
|
||||
class="w-80"
|
||||
v-model="formData.menu.pid"
|
||||
:data="optionsData.menu"
|
||||
clearable
|
||||
node-key="id"
|
||||
:props="{
|
||||
label: 'name'
|
||||
}"
|
||||
default-expand-all
|
||||
placeholder="请选择父级菜单"
|
||||
check-strictly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单名称" prop="menu.name">
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.menu.name"
|
||||
placeholder="请输入菜单名称"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单构建" prop="menu.type" required>
|
||||
<div>
|
||||
<el-radio-group v-model="formData.menu.type">
|
||||
<el-radio :value="1">自动构建</el-radio>
|
||||
<el-radio :value="0">手动添加</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="form-tips">
|
||||
自动构建:自动执行生成菜单sql。手动添加:自行添加菜单。
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="关联配置" name="relations">
|
||||
<el-button type="primary" @click="showEditPopup('add')">
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增关联
|
||||
</el-button>
|
||||
<div class="mt-4">
|
||||
<el-table :data="formData.relations" size="small">
|
||||
<el-table-column prop="type" label="关联类型">
|
||||
<template #default="{ row }">
|
||||
<dict-value :value="row.type" :options="relationTypes" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="关联名称" />
|
||||
<el-table-column prop="model" label="关联模型" />
|
||||
<el-table-column prop="local_key" label="关联键">
|
||||
<template #default="{ row }">
|
||||
<dict-value
|
||||
:value="row.local_key"
|
||||
:options="formData.table_column"
|
||||
:config="{
|
||||
label: 'column_comment',
|
||||
value: 'column_name'
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="foreign_key" label="外键" />
|
||||
<el-table-column label="操作">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="showEditPopup('edit', row, $index)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button link type="danger" @click="handelDelete($index)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<relations-add
|
||||
:column="formData.table_column"
|
||||
:types="relationTypes"
|
||||
v-if="showEdit"
|
||||
ref="editRef"
|
||||
@add="handleAdd"
|
||||
@edit="handleEdit"
|
||||
@close="showEdit = false"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<footer-btns>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="tableEdit">
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
import { menuAll } from '@/api/perms/menu'
|
||||
import { dictTypeAll } from '@/api/setting/dict'
|
||||
import { generateEdit, tableDetail } from '@/api/tools/code'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
import RelationsAdd from '../components/relations-add.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const activeName = ref('column')
|
||||
const showEdit = ref(false)
|
||||
const relationTypes = [
|
||||
{
|
||||
name: '一对一',
|
||||
value: 'has_one'
|
||||
},
|
||||
{
|
||||
name: '一对多',
|
||||
value: 'has_many'
|
||||
}
|
||||
]
|
||||
const formData = reactive({
|
||||
id: '',
|
||||
table_name: '',
|
||||
table_comment: '',
|
||||
author: '',
|
||||
remark: '',
|
||||
template_type: 0,
|
||||
generate_type: 0,
|
||||
module_name: '',
|
||||
class_dir: '',
|
||||
class_comment: '',
|
||||
table_column: [] as any[],
|
||||
menu: {
|
||||
pid: 0,
|
||||
name: '',
|
||||
type: 0
|
||||
},
|
||||
tree: {
|
||||
tree_id: 0,
|
||||
tree_pid: 0,
|
||||
tree_name: 0
|
||||
},
|
||||
delete: {
|
||||
name: '',
|
||||
type: 0
|
||||
},
|
||||
relations: [] as any[]
|
||||
})
|
||||
let editIndex = 0
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
const editRef = shallowRef<InstanceType<typeof RelationsAdd>>()
|
||||
const rules = reactive({
|
||||
table_name: [{ required: true, message: '请输入表名称' }],
|
||||
table_comment: [{ required: true, message: '请输入表描述' }],
|
||||
module_name: [{ required: true, message: '请输入模块名' }],
|
||||
generate_type: [{ required: true, trigger: 'change' }],
|
||||
template_type: [{ required: true, trigger: 'change' }],
|
||||
['menu.pid']: [{ required: true, message: '请选择父级菜单' }],
|
||||
['menu.name']: [{ required: true, message: '请输入菜单名称' }],
|
||||
['delete.type']: [{ required: true, trigger: 'change' }],
|
||||
['delete.name']: [{ required: true, message: '请选择删除字段' }]
|
||||
})
|
||||
|
||||
const showEditPopup = async (type: string, data?: any, index?: number) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
if (data && index !== undefined) {
|
||||
editRef.value?.setFormData(data)
|
||||
editIndex = index
|
||||
}
|
||||
editRef.value?.open(type)
|
||||
}
|
||||
|
||||
const handleAdd = (data: any) => {
|
||||
const newData = cloneDeep(toRaw(data))
|
||||
formData.relations.push(newData)
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
const newData = cloneDeep(toRaw(data))
|
||||
console.log(editIndex)
|
||||
formData.relations.splice(editIndex, 1, newData)
|
||||
}
|
||||
|
||||
const handelDelete = (index: number) => {
|
||||
formData.relations.splice(index, 1)
|
||||
}
|
||||
const getDetails = async () => {
|
||||
const data = await tableDetail({
|
||||
id: route.query.id
|
||||
})
|
||||
Object.keys(formData).forEach((key) => {
|
||||
//@ts-ignore
|
||||
formData[key] = data[key]
|
||||
})
|
||||
|
||||
watch(
|
||||
() => formData.generate_type,
|
||||
(value) => {
|
||||
if (value == 1) {
|
||||
feedback
|
||||
.confirm('生成到模块方式如遇同名文件会覆盖旧文件,确定要选择此方式吗?')
|
||||
.catch(() => {
|
||||
formData.generate_type = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const { optionsData } = useDictOptions<{
|
||||
dict_type: any[]
|
||||
menu: any[]
|
||||
}>({
|
||||
dict_type: {
|
||||
api: dictTypeAll
|
||||
},
|
||||
menu: {
|
||||
api: menuAll,
|
||||
transformData(data) {
|
||||
const menu = { id: 0, name: '顶级', children: [] }
|
||||
menu.children = data
|
||||
return [menu]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const onSubmit = async () => {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
await generateEdit(formData)
|
||||
router.back()
|
||||
} catch (error: any) {
|
||||
for (const err in error) {
|
||||
const isInRules = Object.keys(rules).includes(err)
|
||||
isInRules && feedback.msgError(error[err][0]?.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getDetails()
|
||||
</script>
|
||||
223
src/views/dev_tools/code/index.vue
Normal file
223
src/views/dev_tools/code/index.vue
Normal file
@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div class="code-generation">
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-form class="mb-[-16px]" :model="formData" inline>
|
||||
<el-form-item class="w-[280px]" label="表名称">
|
||||
<el-input v-model="formData.table_name" clearable @keyup.enter="resetPage" />
|
||||
</el-form-item>
|
||||
<el-form-item class="w-[280px]" label="表描述">
|
||||
<el-input v-model="formData.table_comment" clearable @keyup.enter="resetPage" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||
<el-button @click="resetParams">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never" v-loading="pager.loading">
|
||||
<div class="flex">
|
||||
<data-table
|
||||
v-perms="['tools.generator/selectTable']"
|
||||
class="inline-block mr-[10px]"
|
||||
@success="getLists"
|
||||
>
|
||||
<el-button type="primary">
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
导入数据表
|
||||
</el-button>
|
||||
</data-table>
|
||||
<el-button
|
||||
v-perms="['tools.generator/delete']"
|
||||
:disabled="!selectData.length"
|
||||
@click="handleDelete(selectData)"
|
||||
type="danger"
|
||||
>
|
||||
<template #icon>
|
||||
<icon name="el-icon-Delete" />
|
||||
</template>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['tools.generator/generate']"
|
||||
:disabled="!selectData.length"
|
||||
@click="handleGenerate(selectData)"
|
||||
>
|
||||
生成代码
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<el-table
|
||||
:data="pager.lists"
|
||||
size="large"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="表名称" prop="table_name" min-width="180" />
|
||||
<el-table-column label="表描述" prop="table_comment" min-width="180" />
|
||||
<el-table-column label="创建时间" prop="create_time" min-width="180" />
|
||||
<el-table-column label="更新时间" prop="update_time" min-width="180" />
|
||||
<el-table-column label="操作" width="160" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<el-button
|
||||
v-perms="['tools.generator/preview']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handlePreview(row.id)"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
|
||||
<el-button type="primary" link>
|
||||
<router-link
|
||||
v-perms="['tools.generator/edit']"
|
||||
:to="{
|
||||
path: getRoutePath('tools.generator/edit'),
|
||||
query: {
|
||||
id: row.id
|
||||
}
|
||||
}"
|
||||
>
|
||||
编辑
|
||||
</router-link>
|
||||
</el-button>
|
||||
<el-dropdown
|
||||
class="ml-2"
|
||||
@command="handleCommand($event, row)"
|
||||
v-perms="[
|
||||
'tools.generator/generate',
|
||||
'tools.generator/syncColumn',
|
||||
'tools.generator/delete'
|
||||
]"
|
||||
>
|
||||
<el-button type="primary" link>
|
||||
更多
|
||||
<icon name="el-icon-ArrowDown" :size="14" />
|
||||
</el-button>
|
||||
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<div v-perms="['tools.generator/generate']">
|
||||
<el-dropdown-item command="generate">
|
||||
<el-button type="primary" link>
|
||||
生成代码
|
||||
</el-button>
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
<div v-perms="['tools.generator/syncColumn']">
|
||||
<el-dropdown-item command="sync">
|
||||
<el-button type="primary" link>
|
||||
同步
|
||||
</el-button>
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
<div v-perms="['tools.generator/delete']">
|
||||
<el-dropdown-item command="delete">
|
||||
<el-button type="danger" link> 删除 </el-button>
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</el-card>
|
||||
<code-preview
|
||||
v-if="previewState.show"
|
||||
v-model="previewState.show"
|
||||
:code="previewState.code"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="codeGenerate">
|
||||
import {
|
||||
generateCode,
|
||||
generateDelete,
|
||||
generatePreview,
|
||||
generateTable,
|
||||
syncColumn
|
||||
} from '@/api/tools/code'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import { getRoutePath } from '@/router'
|
||||
import { isProdMode } from '@/utils/env'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
import CodePreview from '../components/code-preview.vue'
|
||||
import DataTable from '../components/data-table.vue'
|
||||
|
||||
const formData = reactive({
|
||||
table_name: '',
|
||||
table_comment: ''
|
||||
})
|
||||
|
||||
const previewState = reactive({
|
||||
show: false,
|
||||
loading: false,
|
||||
code: []
|
||||
})
|
||||
|
||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
||||
fetchFun: generateTable,
|
||||
params: formData
|
||||
})
|
||||
|
||||
const selectData = ref<any[]>([])
|
||||
const handleSelectionChange = (val: any[]) => {
|
||||
selectData.value = val.map(({ id }) => id)
|
||||
}
|
||||
|
||||
const handleSync = async (id: number) => {
|
||||
await feedback.confirm('确定要同步表结构?')
|
||||
await syncColumn({ id })
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number | any[]) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await generateDelete({ id })
|
||||
getLists()
|
||||
}
|
||||
|
||||
const handlePreview = async (id: number) => {
|
||||
const data: any = await generatePreview({ id })
|
||||
previewState.code = data
|
||||
previewState.show = true
|
||||
}
|
||||
|
||||
const hasGenerateTypeInModule = (data: any[]) => {
|
||||
return data.some((item) => item.generate_type == 1)
|
||||
}
|
||||
|
||||
const handleGenerate = async (selectData: any[]) => {
|
||||
if (isProdMode() && hasGenerateTypeInModule(selectData)) {
|
||||
return feedback.msgError('生成方式为生成到模块,请在前端开发模式下使用,详细参考文档')
|
||||
}
|
||||
const data: any = await generateCode({ id: selectData })
|
||||
if (data.file) {
|
||||
window.open(data.file, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
const handleCommand = (command: any, row: any) => {
|
||||
switch (command) {
|
||||
case 'generate':
|
||||
handleGenerate([row.id])
|
||||
break
|
||||
case 'sync':
|
||||
handleSync(row.id)
|
||||
break
|
||||
case 'delete':
|
||||
handleDelete(row.id)
|
||||
}
|
||||
}
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
64
src/views/dev_tools/components/code-preview.vue
Normal file
64
src/views/dev_tools/components/code-preview.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="code-preview">
|
||||
<el-dialog v-model="show" width="900px" title="代码预览">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane
|
||||
v-for="(item, index) in code"
|
||||
:label="item.name"
|
||||
:name="`index${index}`"
|
||||
:key="index"
|
||||
>
|
||||
<div class="flex" style="height: 50vh">
|
||||
<el-scrollbar class="flex-1">
|
||||
<highlightjs autodetect :code="item.content" />
|
||||
</el-scrollbar>
|
||||
<div>
|
||||
<el-button @click="handleCopy(item.content)" type="primary" link>
|
||||
<template #icon>
|
||||
<icon name="el-icon-CopyDocument" />
|
||||
</template>
|
||||
复制
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useClipboard from 'vue-clipboard3'
|
||||
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
code: any[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:modelValue', value: boolean): void
|
||||
}>()
|
||||
const { toClipboard } = useClipboard()
|
||||
|
||||
const activeTab = ref('index0')
|
||||
|
||||
const handleCopy = async (text: string) => {
|
||||
try {
|
||||
await toClipboard(text)
|
||||
feedback.msgSuccess('复制成功')
|
||||
} catch (e) {
|
||||
feedback.msgError('复制失败')
|
||||
}
|
||||
}
|
||||
|
||||
const show = computed<boolean>({
|
||||
get() {
|
||||
return props.modelValue
|
||||
},
|
||||
set(value) {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
94
src/views/dev_tools/components/data-table.vue
Normal file
94
src/views/dev_tools/components/data-table.vue
Normal file
@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="data-table">
|
||||
<popup
|
||||
ref="popupRef"
|
||||
:clickModalClose="false"
|
||||
title="选择表"
|
||||
width="900px"
|
||||
:async="true"
|
||||
@confirm="handleConfirm"
|
||||
>
|
||||
<template #trigger>
|
||||
<slot></slot>
|
||||
</template>
|
||||
<el-form class="ls-form" :model="formData" inline>
|
||||
<el-form-item class="w-[280px]" label="表名称">
|
||||
<el-input v-model="formData.name" clearable @keyup.enter="resetPage" />
|
||||
</el-form-item>
|
||||
<el-form-item class="w-[280px]" label="表描述">
|
||||
<el-input v-model="formData.comment" clearable @keyup.enter="resetPage" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||
<el-button @click="resetParams">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="m-4" v-loading="pager.loading">
|
||||
<el-table
|
||||
height="400"
|
||||
size="large"
|
||||
:data="pager.lists"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="表名称" prop="name" min-width="150" />
|
||||
<el-table-column label="表描述" prop="comment" min-width="160" />
|
||||
<el-table-column label="创建时间" prop="create_time" min-width="180" />
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dataTable, selectTable } from '@/api/tools/code'
|
||||
import Pagination from '@/components/pagination/index.vue'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'success'): void
|
||||
}>()
|
||||
|
||||
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
||||
|
||||
const formData = reactive({
|
||||
name: '', // 表名称
|
||||
comment: '' // 表描述
|
||||
})
|
||||
|
||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
||||
fetchFun: dataTable,
|
||||
params: formData,
|
||||
size: 10
|
||||
})
|
||||
|
||||
const selectData = ref<any[]>([])
|
||||
|
||||
const handleSelectionChange = (val: any[]) => {
|
||||
selectData.value = val.map(({ name, comment }) => ({
|
||||
name,
|
||||
comment
|
||||
}))
|
||||
}
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!selectData.value.length) return feedback.msgError('请选择数据表')
|
||||
await selectTable({
|
||||
table: selectData.value
|
||||
})
|
||||
popupRef.value?.close()
|
||||
emit('success')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => popupRef.value?.visible,
|
||||
(value) => {
|
||||
if (value) getLists()
|
||||
}
|
||||
)
|
||||
</script>
|
||||
162
src/views/dev_tools/components/relations-add.vue
Normal file
162
src/views/dev_tools/components/relations-add.vue
Normal file
@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div class="edit-popup">
|
||||
<popup
|
||||
ref="popupRef"
|
||||
:title="popupTitle"
|
||||
:async="true"
|
||||
width="550px"
|
||||
@confirm="handleSubmit"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
|
||||
<el-form-item label="关联类型" prop="type">
|
||||
<el-select class="flex-1" v-model="formData.type" placeholder="请选择关联类型">
|
||||
<el-option
|
||||
v-for="(item, index) in types"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关联名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入关联名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关联模型" prop="model">
|
||||
<el-select class="flex-1" v-model="formData.model" placeholder="请选择关联模型">
|
||||
<el-option
|
||||
v-for="item in optionsData.models"
|
||||
:label="item"
|
||||
:value="item"
|
||||
:key="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关联健" prop="local_key">
|
||||
<el-select
|
||||
class="flex-1"
|
||||
v-model="formData.local_key"
|
||||
clearable
|
||||
placeholder="请选择关联健"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in column"
|
||||
:key="item.id"
|
||||
:value="item.column_name"
|
||||
:label="`${item.column_name}:${item.column_comment}`"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="外键" prop="foreign_key">
|
||||
<el-input
|
||||
v-model="formData.foreign_key"
|
||||
placeholder="关联表外键或中间表的外键"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
import { getModels } from '@/api/tools/code'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
|
||||
defineProps({
|
||||
column: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => []
|
||||
},
|
||||
types: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['add', 'close', 'edit'])
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
||||
const mode = ref<'add' | 'edit'>('add')
|
||||
const popupTitle = computed(() => {
|
||||
return mode.value == 'edit' ? '编辑关联' : '新增关联'
|
||||
})
|
||||
const formData = reactive({
|
||||
name: '',
|
||||
model: '',
|
||||
type: '',
|
||||
local_key: '',
|
||||
foreign_key: ''
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入关联名称'
|
||||
}
|
||||
],
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择关联类型'
|
||||
}
|
||||
],
|
||||
model: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择关联模型'
|
||||
}
|
||||
],
|
||||
local_key: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择关联健'
|
||||
}
|
||||
],
|
||||
foreign_key: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入外键'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const { optionsData } = useDictOptions<{
|
||||
models: any[]
|
||||
}>({
|
||||
models: {
|
||||
api: getModels
|
||||
}
|
||||
})
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await formRef.value?.validate()
|
||||
popupRef.value?.close()
|
||||
emit(mode.value, formData)
|
||||
}
|
||||
|
||||
const open = (type = 'add') => {
|
||||
mode.value = type as 'add' | 'edit'
|
||||
popupRef.value?.open()
|
||||
}
|
||||
|
||||
const setFormData = (data: Record<any, any>) => {
|
||||
for (const key in formData) {
|
||||
if (data[key] != null && data[key] != undefined) {
|
||||
//@ts-ignore
|
||||
formData[key] = data[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
setFormData
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user