weipengfei ede29e638b 更新
2024-04-27 14:40:02 +08:00

620 lines
28 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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 #header>
<el-checkbox
:true-label="1"
:false-label="0"
:checked="is_required"
@change="handleAllRequired"
/>
<span class="ml-2">必填</span>
</template>
<template v-slot="{ row }">
<el-checkbox
v-model="row.is_required"
:true-label="1"
:false-label="0"
/>
</template>
</el-table-column>
<el-table-column label="插入" width="80">
<template #header>
<el-checkbox
:true-label="1"
:false-label="0"
:checked="is_insert"
@change="handleAllInsert"
/>
<span class="ml-2">插入</span>
</template>
<template v-slot="{ row }">
<el-checkbox
v-model="row.is_insert"
:true-label="1"
:false-label="0"
/>
</template>
</el-table-column>
<el-table-column label="编辑" width="80">
<template #header>
<el-checkbox
:true-label="1"
:false-label="0"
:checked="is_update"
@change="handleAllUpdate"
/>
<span class="ml-2">编辑</span>
</template>
<template v-slot="{ row }">
<el-checkbox
v-model="row.is_update"
:true-label="1"
:false-label="0"
/>
</template>
</el-table-column>
<el-table-column label="列表" width="80">
<template #header>
<el-checkbox
:true-label="1"
:false-label="0"
:checked="is_lists"
@change="handleAllLists"
/>
<span class="ml-2">列表</span>
</template>
<template v-slot="{ row }">
<el-checkbox
v-model="row.is_lists"
:true-label="1"
:false-label="0"
/>
</template>
</el-table-column>
<el-table-column label="查询" width="80">
<template #header>
<el-checkbox
:true-label="1"
:false-label="0"
:checked="is_query"
@change="handleAllQuery"
/>
<span class="ml-2">查询</span>
</template>
<template v-slot="{ row }">
<el-checkbox
v-model="row.is_query"
:true-label="1"
:false-label="0"
@change="handleQueryChange(row)"
/>
</template>
</el-table-column>
<el-table-column label="查询方式">
<template v-slot="{ row }">
<el-select class="w-[280px]" 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 class="w-[280px]"
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 :label="0">单表curd</el-radio>
<el-radio :label="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 :label="0">物理删除</el-radio>
<el-radio :label="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 :label="0">压缩包下载</el-radio>
<el-radio :label="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 :label="1">自动构建</el-radio>
<el-radio :label="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="mini">
<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 { generateEdit, tableDetail } from '@/api/tools/code'
import type { FormInstance } from 'element-plus'
import feedback from '@/utils/feedback'
import { useDictOptions } from '@/hooks/useDictOptions'
import { dictTypeAll } from '@/api/setting/dict'
import { menuAll } from '@/api/perms/menu'
import RelationsAdd from '../components/relations-add.vue'
import { cloneDeep } from 'lodash'
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()
const is_required = computed(()=>{
return formData.table_column.findIndex(item=>item.is_required==0) ? false : true
})
const handleAllRequired = (e:any)=>{
formData.table_column.forEach((item:any)=>{
item.is_required = e;
})
}
const is_insert = computed(()=>{
return formData.table_column.findIndex(item=>item.is_insert==0) ? false : true
})
const handleAllInsert = (e:any)=>{
formData.table_column.forEach((item:any)=>{
item.is_insert = e;
})
}
const is_update = computed(()=>{
return formData.table_column.findIndex(item=>item.is_update==0) ? false : true
})
const handleAllUpdate = (e:any)=>{
formData.table_column.forEach((item:any)=>{
item.is_update = e;
})
}
const is_lists = computed(()=>{
return formData.table_column.findIndex(item=>item.is_lists==0) ? false : true
})
const handleAllLists = (e:any)=>{
formData.table_column.forEach((item:any)=>{
item.is_lists = e;
})
}
const is_query = computed(()=>{
return formData.table_column.findIndex(item=>item.is_query==0) ? false : true
})
const handleAllQuery = (e:any)=>{
formData.table_column.forEach((item:any)=>{
item.is_query = e;
})
}
</script>