fix 修复生成代码 pgsql 菜单权限生成和个别数据类型生成错误,vue 方法导入改为自动导入

This commit is contained in:
mengshuai
2025-11-09 13:49:11 +08:00
parent a7234bc330
commit b58643cc2f
13 changed files with 532 additions and 123 deletions

View File

@@ -0,0 +1,84 @@
-- hotgo自动生成菜单权限SQL 通常情况下只在首次生成代码时自动执行一次
-- 如需再次执行请先手动删除生成的菜单权限和SQL文件@{.generatePath}
-- Version: @{.hgVersion}
-- Date: @{.nowTime}
-- Link https://github.com/bufanyun/hotgo
--
-- 数据库 "@{.dbName}"
--
-- --------------------------------------------------------
--
-- 插入表中的数据 "@{.menuTable}"
--
DO $$
DECLARE
dir_id bigint;
list_id bigint;
edit_id bigint;
BEGIN
-- 菜单目录
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES ('@{.options.Menu.Pid}', '@{.tableComment}', '@{.varName | LcFirst}', '/@{.varName | LcFirst}', '@{.options.Menu.Icon}', '1', '@{.pageRedirect}', '', '', '@{.mainComponent}', '1', '', '0', '0', '', '0', '0', '0', '@{.dirLevel}', '@{.dirTree}', '@{.options.Menu.Sort}', '', '1', now(), now())
RETURNING id INTO dir_id;
-- 菜单页面
-- 列表
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (dir_id, '@{.tableComment}列表', '@{.varName | LcFirst}Index', 'index', '', '2', '', '/@{.apiPrefix}/list', '', '/@{.componentPrefix}/index', '1', '@{.varName | LcFirst}', '0', '0', '', '0', '1', '0', '@{.listLevel}', '@{.dirTree}tr_' || dir_id || ' ', '10', '', '1', now(), now())
RETURNING id INTO list_id;
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) }
-- 详情
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '@{.tableComment}详情', '@{.varName | LcFirst}View', '', '', '3', '', '/@{.apiPrefix}/view', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '10', '', '1', now(), now());
@{end}
-- 菜单按钮
@{ if eq .options.Step.HasEdit true }
-- 编辑
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '编辑/新增@{.tableComment}', '@{.varName | LcFirst}Edit', '', '', '3', '', '/@{.apiPrefix}/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '20', '', '1', now(), now())
RETURNING id INTO edit_id;
@{end}
@{ if and (eq .options.Step.HasEdit true) (eq .options.Step.HasMaxSort true) }
-- 获取最大排序
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (edit_id, '获取@{.tableComment}最大排序', '@{.varName | LcFirst}MaxSort', '', '', '3', '', '/@{.apiPrefix}/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.sortLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' tr_' || edit_id || ' ', '30', '', '1', now(), now());
@{end}
@{ if eq .options.Step.HasDel true }
-- 删除
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '删除@{.tableComment}', '@{.varName | LcFirst}Delete', '', '', '3', '', '/@{.apiPrefix}/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '40', '', '1', now(), now());
@{end}
@{ if eq .options.Step.HasStatus true }
-- 更新状态
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '修改@{.tableComment}状态', '@{.varName | LcFirst}Status', '', '', '3', '', '/@{.apiPrefix}/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '50', '', '1', now(), now());
@{end}
@{ if eq .options.Step.HasSwitch true }
-- 操作开关
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '操作@{.tableComment}开关', '@{.varName | LcFirst}Switch', '', '', '3', '', '/@{.apiPrefix}/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '60', '', '1', now(), now());
@{end}
@{ if eq .options.Step.HasExport true }
-- 导出
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '导出@{.tableComment}', '@{.varName | LcFirst}Export', '', '', '3', '', '/@{.apiPrefix}/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '70', '', '1', now(), now());
@{end}
@{ if eq .options.Step.IsTreeTable true }
-- 关系树选项
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
VALUES (list_id, '获取@{.tableComment}关系树选项', '@{.varName | LcFirst}TreeOption', '', '', '3', '', '/@{.apiPrefix}/treeOption', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '70', '', '1', now(), now());
@{end}
END $$;

View File

@@ -21,8 +21,11 @@
:label-width="100"
class="py-4"
>
<n-grid cols="1 s:1 m:@{.options.PresetStep.FormGridCols} l:@{.options.PresetStep.FormGridCols} xl:@{.options.PresetStep.FormGridCols} 2xl:@{.options.PresetStep.FormGridCols}" responsive="screen">
@{.formItem}
<n-grid
cols="1 s:1 m:@{.options.PresetStep.FormGridCols} l:@{.options.PresetStep.FormGridCols} xl:@{.options.PresetStep.FormGridCols} 2xl:@{.options.PresetStep.FormGridCols}"
responsive="screen"
>
@{.formItem}
</n-grid>
</n-form>
</n-spin>

View File

@@ -27,7 +27,13 @@
@{end}
@{ if eq .options.Step.HasEdit true }
<n-button v-if="hasPermission(['/@{.apiPrefix}/edit'])" type="info" icon-placement="left" @click="handleEdit(selectedState)" :disabled="selectedState.@{.pk.TsName} < 1">
<n-button
v-if="hasPermission(['/@{.apiPrefix}/edit'])"
type="info"
icon-placement="left"
@click="handleEdit(selectedState)"
:disabled="selectedState.@{.pk.TsName} < 1"
>
<template #icon>
<div class="flex items-center">
<n-icon size="14">
@@ -40,7 +46,13 @@
@{end}
@{ if eq .options.Step.HasBatchDel true }
<n-button v-if="hasPermission(['/@{.apiPrefix}/delete'])" type="error" icon-placement="left" @click="handleDelete(selectedState)" :disabled="selectedState.@{.pk.TsName} < 1">
<n-button
v-if="hasPermission(['/@{.apiPrefix}/delete'])"
type="error"
icon-placement="left"
@click="handleDelete(selectedState)"
:disabled="selectedState.@{.pk.TsName} < 1"
>
<template #icon>
<div class="flex items-center">
<n-icon size="14">
@@ -78,7 +90,21 @@
<n-spin size="medium" />
</div>
</template>
<n-tree v-else show-line block-line cascade virtual-scroll :pattern="pattern" :data="treeOption" :expandedKeys="expandedKeys" style="height: 75vh" key-field="@{.pk.TsName}" label-field="@{.options.Tree.TitleField.TsName}" @update:selected-keys="handleSelected" @update:expanded-keys="handleOnExpandedKeys" />
<n-tree
v-else
show-line
block-line
cascade
virtual-scroll
:pattern="pattern"
:data="treeOption"
:expandedKeys="expandedKeys"
style="height: 75vh"
key-field="@{.pk.TsName}"
label-field="@{.options.Tree.TitleField.TsName}"
@update:selected-keys="handleSelected"
@update:expanded-keys="handleOnExpandedKeys"
/>
</div>
</div>
</n-card>
@@ -95,7 +121,13 @@
</template>
<n-result v-show="selectedState.@{.pk.TsName} < 1" status="info" title="提示" description="请先从列表选择一项后,进行编辑">
<template #footer>
<n-button type="info" icon-placement="left" @{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"@{end} @{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"@{end} v-if="hasPermission(['/@{.apiPrefix}/edit'])">
<n-button
type="info"
icon-placement="left"
@{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"
@{end}@{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"
@{end}v-if="hasPermission(['/@{.apiPrefix}/edit'])"
>
<template #icon>
<div class="flex items-center">
<n-icon size="14">
@@ -110,18 +142,47 @@
@{end}
@{ if eq .isSearchForm true }
<BasicForm @{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"@{end} ref="searchFormRef" @register="register" @submit="reloadTable" @reset="reloadTable" @keyup.enter="reloadTable">
<BasicForm
@{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"
@{end}ref="searchFormRef"
@register="register"
@submit="reloadTable"
@reset="reloadTable"
@keyup.enter="reloadTable"
>
<template #statusSlot="{ model, field }">
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
@{end}
<BasicTable @{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"@{end} ref="actionRef" @{ if eq .options.Step.HasCheck true }openChecked@{end} :columns="columns" :request="loadDataTable" :row-key="(row) => row.@{.pk.TsName}" :actionColumn="actionColumn" :scroll-x="scrollX" :resizeHeightOffset="-10000" @{ if and (eq .options.Step.IsTreeTable true) (eq .options.Step.IsOptionTreeTable false) }:cascade="false" :expanded-row-keys="expandedKeys" @update:expanded-row-keys="updateExpandedKeys"@{end} @{ if eq .options.Step.HasCheck true }:checked-row-keys="checkedIds"@{end} @{ if eq .options.Step.HasCheck true }@update:checked-row-keys="handleOnCheckedRow"@{end}>
<BasicTable
@{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"
@{end}ref="actionRef"
@{ if eq .options.Step.HasCheck true }openChecked
@{end}:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.@{.pk.TsName}"
:actionColumn="actionColumn"
:scroll-x="scrollX"
:resizeHeightOffset="-10000"
@{ if and (eq .options.Step.IsTreeTable true) (eq .options.Step.IsOptionTreeTable false) }:cascade="false"
:expanded-row-keys="expandedKeys"
@update:expanded-row-keys="updateExpandedKeys"
@{end}@{ if eq .options.Step.HasCheck true }:checked-row-keys="checkedIds"
@{end}@{ if eq .options.Step.HasCheck true }@update:checked-row-keys="handleOnCheckedRow"
@{end}
>
<template #tableTitle>
@{ if eq .options.Step.HasAdd true }
<n-button type="primary" @{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"@{end} @{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"@{end} class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/edit'])">
<n-button
type="primary"
@{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"
@{end}@{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"
@{end}class="min-left-space"
v-if="hasPermission(['/@{.apiPrefix}/edit'])"
>
<template #icon>
<n-icon>
<PlusOutlined />
@@ -132,7 +193,12 @@
@{end}
@{ if eq .options.Step.HasBatchDel true }
<n-button type="error" @click="handleBatchDelete" class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/delete'])">
<n-button
type="error"
@click="handleBatchDelete"
class="min-left-space"
v-if="hasPermission(['/@{.apiPrefix}/delete'])"
>
<template #icon>
<n-icon>
<DeleteOutlined />
@@ -143,7 +209,12 @@
@{end}
@{ if eq .options.Step.HasExport true }
<n-button type="primary" @click="handleExport" class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/export'])">
<n-button
type="primary"
@click="handleExport"
class="min-left-space"
v-if="hasPermission(['/@{.apiPrefix}/export'])"
>
<template #icon>
<n-icon>
<ExportOutlined />

View File

@@ -3,16 +3,8 @@
@{.const}
export class State {
@{range .stateItems}
public @{.Name} = @{if and .DataType (or
(eq .DataType "varchar")
(eq .DataType "char")
(eq .DataType "text")
(eq .DataType "json")
(eq .DataType "date")
(eq .DataType "datetime")
(eq .DataType "TIMESTAMP")
)}'@{.DefaultValue}'@{else}@{.DefaultValue}@{end};//@{.Dc}@{end}
@{range .stateItems} public @{.Name} = @{if and .DataType (or (eq .DataType "varchar") (eq .DataType "char") (eq .DataType "bpchar") (eq .DataType "text") (eq .DataType "json") (eq .DataType "jsonb") (eq .DataType "date") (eq .DataType "time") (eq .DataType "timetz") (eq .DataType "datetime") (eq .DataType "timestamp") (eq .DataType "timestamptz") (eq .DataType "TIMESTAMP") (eq .DataType "interval") (eq .DataType "uuid") (eq .DataType "bytea") (eq .DataType "inet") (eq .DataType "cidr") (eq .DataType "macaddr") (eq .DataType "macaddr8") (eq .DataType "bit") (eq .DataType "varbit") (eq .DataType "point") (eq .DataType "line") (eq .DataType "lseg") (eq .DataType "box") (eq .DataType "path") (eq .DataType "polygon") (eq .DataType "circle") (eq .DataType "money")) (ne .DefaultValue "null")}'@{.DefaultValue}'@{else}@{.DefaultValue}@{end}; // @{.Dc}
@{end}
constructor(state?: Partial<State>) {
if (state) {
Object.assign(this, state);

View File

@@ -13,13 +13,12 @@
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { View } from '@{.importWebApi}';
import { State, newState } from './model';
import { adaModalWidth } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
@{ if eq .options.DictOps.Has true }import { useDictStore } from '@/store/modules/dict';@{end}
@{ if eq .hasUploadFile true }import { getFileExt } from '@/utils/urlUtils';
@{end}@{ if eq .options.DictOps.Has true }import { useDictStore } from '@/store/modules/dict';@{end}
const message = useMessage();
@{ if eq .options.DictOps.Has true }const dict = useDictStore();@{end}
@@ -29,7 +28,7 @@
const dialogWidth = computed(() => {
return adaModalWidth(580);
});
const fileAvatarCSS = computed(() => {
@{ if eq .hasUploadFile true }const fileAvatarCSS = computed(() => {
return {
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
'--n-font-size': `18px`,
@@ -40,6 +39,7 @@
function download(url: string) {
window.open(url);
}
@{end}
// 打开模态框
function openModal(state: State) {