feat: 添加代码生成功能

This commit is contained in:
2025-03-04 00:54:33 +08:00
parent c790233aee
commit bd13f1cfdc
16 changed files with 1758 additions and 1 deletions

View File

@@ -0,0 +1,95 @@
<template>
<el-form ref="ruleFormRef" :model="newFormInline" label-width="82px">
<el-row :gutter="30">
[% for column in columns if column.is_insert or column.is_edit %]
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="[[ column.column_comment ]]" prop="[[ column.python_name ]]">
[% if column.show_type == "input" %]
<el-input
v-model="newFormInline.[[ column.python_name ]]"
placeholder="请输入[[ column.column_comment ]]~"
clearable
/>
[% elif column.show_type == "textarea" %]
<el-input
v-model="newFormInline.[[ column.python_name ]]"
type="textarea"
placeholder="请输入[[ column.column_comment ]]~"
clearable
/>
[% elif column.show_type == "select" %]
<el-select
v-model="newFormInline.[[ column.python_name ]]"
placeholder="请选择[[ column.column_comment ]]~"
filterable
clearable
>
<el-option
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
[% elif column.show_type == "radio" %]
<el-radio-group v-model="newFormInline.[[ column.python_name ]]">
<el-radio
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.value"
>{{ item.label }}
</el-radio>
</el-radio-group>
[% elif column.show_type == "checkbox" %]
<el-checkbox-group v-model="newFormInline.[[ column.python_name ]]">
<el-checkbox
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
[% elif column.show_type == "datetime" %]
<el-date-picker
v-model="newFormInline.[[ column.python_name ]]"
type="datetime"
placeholder="请选择[[ column.column_comment ]]~"
format="YYYY-MM-DD HH:mm:ss"
value-format="x" />
[% endif %]
</el-form-item>
</re-col>
[% endfor %]
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { ref } from "vue";
import ReCol from "@/components/ReCol";
import type { FormRules } from "element-plus";
import { [[ class_name ]]Info } from "types/[[ name ]]";
interface FormItemProps {
[% for column in columns if column.is_list %]
/** [[ column.column_comment ]] */
[[ column.python_name ]]: [[ column.typescript_type ]];
[% endfor %]
}
interface FormProps {
formInline: FormItemProps;
}
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
[% for column in columns if column.is_list %]
/** [[ column.column_comment ]] */
[[ column.python_name ]]: "",
[% endfor %]
})
});
const newFormInline = ref<ConfigInfo>(props.formInline);
/** 自定义表单规则校验 */
const formRules = reactive<FormRules>({
[% for column in columns if column.is_insert or column.is_edit %]
[[ column.python_name ]]: [{ required: [[ 'true' if column.is_required else 'false' ]], message: "请输入[[ column.column_comment ]]~", trigger: "blur" }],
[% endfor %]
});
defineExpose({ newFormInline });
</script>

View File

@@ -0,0 +1,237 @@
<template>
<div class="main">
<el-form
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
>
[% for column in columns if column.is_query %]
<el-form-item label="[[ column.column_comment ]]" prop="[[ column.python_name ]]">
[% if column.show_type == "input" %]
<el-input
v-model="form.[[ column.python_name ]]"
placeholder="请输入[[ column.column_comment ]]~"
class="!w-[200px]"
clearable
/>
[% elif column.show_type == "textarea" %]
<el-input
v-model="form.[[ column.python_name ]]"
type="textarea"
placeholder="请输入[[ column.column_comment ]]~"
class="!w-[200px]"
clearable
/>
[% elif column.show_type == "select" %]
<el-select
v-model="form.[[ column.python_name ]]"
placeholder="请选择[[ column.column_comment ]]~"
class="!w-[200px]"
clearable
>
<el-option
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
[% elif column.show_type == "radio" %]
<el-radio-group v-model="form.[[ column.python_name ]]">
<el-radio
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.value"
>{{ item.label }}
</el-radio>
</el-radio-group>
[% elif column.show_type == "checkbox" %]
<el-checkbox-group v-model="form.[[ column.python_name ]]">
<el-checkbox
v-for="item in options.[[ column.python_name ]]"
:key="item.value"
:label="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
[% elif column.show_type == "datetime" %]
<el-date-picker
v-model="form.[[ column.python_name ]]"
type="datetime"
placeholder="请选择[[ column.column_comment ]]~"
format="YYYY-MM-DD HH:mm:ss"
value-format="x" />
[% endif %]
</el-form-item>
[% endfor %]
<el-form-item>
<el-button
type="primary"
:icon="useRenderIcon('ri:search-line')"
:loading="loading"
@click="onSearch"
>
{{ t("buttons:Search") }}
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
{{ t("buttons:Reset") }}
</el-button>
</el-form-item>
</el-form>
<PureTableBar title="{{ description }}管理" :columns="columns" @refresh="onSearch">
<template #buttons>
<el-button
v-if="hasAuth('[[ name ]]:btn:add')"
type="primary"
:icon="useRenderIcon(AddFill)"
@click="openDialog('新增')"
>
{{ t("buttons:Add") }}
</el-button>
</template>
<template v-slot="{ size, dynamicColumns }">
<div
v-if="selectedNum > 0"
v-motion-fade
class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center"
>
<div class="flex-auto">
<span
style="font-size: var(--el-font-size-base)"
class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]"
>
已选 {{ selectedNum }} 项
</span>
<el-button type="primary" text @click="onSelectionCancel">
{{ t("buttons:Deselect") }}
</el-button>
</div>
<el-popconfirm
v-if="hasAuth('[[ name ]]:btn:delete')"
title="是否确认删除?"
@confirm="onbatchDel"
>
<template #reference>
<el-button type="danger" text class="mr-1">
{{ t("buttons:DeleteInBatches") }}
</el-button>
</template>
</el-popconfirm>
</div>
<pure-table
ref="tableRef"
row-key="id"
adaptive
border
stripe
:adaptiveConfig="{ offsetBottom: 45 }"
align-whole="center"
table-layout="auto"
:loading="loading"
:size="size"
:data="dataList"
:columns="dynamicColumns"
:pagination="pagination"
:paginationSmall="size === 'small' ? true : false"
:header-cell-style="{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@selection-change="handleSelectionChange"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
>
<template #operation="{ row }">
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:disabled="!hasAuth('[[ name ]]:btn:update')"
:icon="useRenderIcon(EditPen)"
@click="openDialog('修改', row)"
>
{{ t("buttons:Update") }}
</el-button>
<el-popconfirm
:title="`是否确认删除配置名为 ${row.name} 的这条数据`"
@confirm="handleDelete(row)"
>
<template #reference>
<el-button
class="reset-margin"
link
:disabled="!hasAuth('[[ name ]]:btn:delete')"
type="danger"
:size="size"
:icon="useRenderIcon(Delete)"
>
{{ t("buttons:Delete") }}
</el-button>
</template>
</el-popconfirm>
</template>
</pure-table>
</template>
</PureTableBar>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: "{{ class_name }}Index"
});
import { ref } from "vue";
import { use[[ class_name ]] } from "./utils/hook";
import { useI18n } from "vue-i18n";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Delete from "@iconify-icons/ep/delete";
import EditPen from "@iconify-icons/ep/edit-pen";
import Refresh from "@iconify-icons/ep/refresh";
import AddFill from "@iconify-icons/ri/add-circle-line";
const { t } = useI18n();
import { hasAuth } from "@/utils/auth";
/**
* 表格Ref
*/
const tableRef = ref();
const formRef = ref();
const {
form,
dataList,
loading,
pagination,
columns,
selectedNum,
onSearch,
openDialog,
resetForm,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange,
onSelectionCancel,
onbatchDel
} = use[[ class_name ]](tableRef);
</script>
<style scoped lang="scss">
:deep(.el-dropdown-menu__item i) {
margin: 0;
}
:deep(.el-button:focus-visible) {
outline: none;
}
.main-content {
margin: 24px 24px 0 !important;
}
.search-form {
:deep(.el-form-item) {
margin-bottom: 12px;
}
}
</style>