Merge pull request #200 from 1014TaoTao/v2.0.0

V2.0.0
This commit is contained in:
fastapiadmin
2025-10-14 00:27:14 +08:00
committed by GitHub
29 changed files with 1916 additions and 2602 deletions
+3
View File
@@ -0,0 +1,3 @@
*.js linguist-language=Python
*.css linguist-language=Python
*.html linguist-language=Python
-1
View File
@@ -12,7 +12,6 @@ backend/venv
backend/logs
backend/*.db
backend/site
backend/app/alembic/versions/*
frontend/__pycache__
frontend/.vscode
@@ -0,0 +1,419 @@
"""'Change config_value from String to JSON'
Revision ID: d5460b04e5ce
Revises:
Create Date: 2025-10-08 15:38:49.199390
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import sqlite
# revision identifiers, used by Alembic.
revision: str = 'd5460b04e5ce'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index('ix_system_dict_data_creator_id', table_name='system_dict_data')
op.drop_table('system_dict_data')
op.drop_index('ix_app_job_creator_id', table_name='app_job')
op.drop_table('app_job')
op.drop_index('ix_gen_table_column_creator_id', table_name='gen_table_column')
op.drop_table('gen_table_column')
op.drop_index('ix_system_position_creator_id', table_name='system_position')
op.drop_table('system_position')
op.drop_table('system_role_depts')
op.drop_table('system_role_menus')
op.drop_table('system_user_positions')
op.drop_index('ix_app_myapp_creator_id', table_name='app_myapp')
op.drop_table('app_myapp')
op.drop_index('ix_system_dict_type_creator_id', table_name='system_dict_type')
op.drop_table('system_dict_type')
op.drop_table('app_job_log')
op.drop_index('ix_system_role_creator_id', table_name='system_role')
op.drop_table('system_role')
op.drop_index('ix_system_users_creator_id', table_name='system_users')
op.drop_index('ix_system_users_dept_id', table_name='system_users')
op.drop_table('system_users')
op.drop_index('ix_system_log_creator_id', table_name='system_log')
op.drop_table('system_log')
op.drop_index('ix_system_menu_parent_id', table_name='system_menu')
op.drop_table('system_menu')
op.drop_index('ix_system_notice_creator_id', table_name='system_notice')
op.drop_table('system_notice')
op.drop_index('ix_system_dept_parent_id', table_name='system_dept')
op.drop_table('system_dept')
op.drop_index('ix_app_ai_mcp_creator_id', table_name='app_ai_mcp')
op.drop_table('app_ai_mcp')
op.drop_index('ix_system_param_creator_id', table_name='system_param')
op.drop_table('system_param')
op.drop_index('ix_gen_demo_creator_id', table_name='gen_demo')
op.drop_table('gen_demo')
op.drop_table('system_user_roles')
op.drop_index('ix_gen_table_creator_id', table_name='gen_table')
op.drop_table('gen_table')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('gen_table',
sa.Column('table_name', sa.VARCHAR(length=200), nullable=True),
sa.Column('table_comment', sa.VARCHAR(length=500), nullable=True),
sa.Column('sub_table_name', sa.VARCHAR(length=64), nullable=True),
sa.Column('sub_table_fk_name', sa.VARCHAR(length=64), nullable=True),
sa.Column('class_name', sa.VARCHAR(length=100), nullable=True),
sa.Column('tpl_category', sa.VARCHAR(length=200), nullable=True),
sa.Column('tpl_web_type', sa.VARCHAR(length=30), nullable=True),
sa.Column('package_name', sa.VARCHAR(length=100), nullable=True),
sa.Column('module_name', sa.VARCHAR(length=30), nullable=True),
sa.Column('business_name', sa.VARCHAR(length=30), nullable=True),
sa.Column('function_name', sa.VARCHAR(length=100), nullable=True),
sa.Column('function_author', sa.VARCHAR(length=100), nullable=True),
sa.Column('gen_type', sa.VARCHAR(length=1), nullable=True),
sa.Column('gen_path', sa.VARCHAR(length=200), nullable=True),
sa.Column('options', sa.VARCHAR(length=1000), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_gen_table_creator_id', 'gen_table', ['creator_id'], unique=False)
op.create_table('system_user_roles',
sa.Column('user_id', sa.INTEGER(), nullable=False),
sa.Column('role_id', sa.INTEGER(), nullable=False),
sa.ForeignKeyConstraint(['role_id'], ['system_role.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['system_users.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.PrimaryKeyConstraint('user_id', 'role_id')
)
op.create_table('gen_demo',
sa.Column('name', sa.VARCHAR(length=64), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_gen_demo_creator_id', 'gen_demo', ['creator_id'], unique=False)
op.create_table('system_param',
sa.Column('config_name', sa.VARCHAR(length=500), nullable=False),
sa.Column('config_key', sa.VARCHAR(length=500), nullable=False),
sa.Column('config_value', sa.VARCHAR(length=500), nullable=True),
sa.Column('config_type', sa.BOOLEAN(), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('config_key'),
sa.UniqueConstraint('config_name')
)
op.create_index('ix_system_param_creator_id', 'system_param', ['creator_id'], unique=False)
op.create_table('app_ai_mcp',
sa.Column('name', sa.VARCHAR(length=50), nullable=False),
sa.Column('type', sa.INTEGER(), nullable=False),
sa.Column('url', sa.VARCHAR(length=255), nullable=True),
sa.Column('command', sa.VARCHAR(length=255), nullable=True),
sa.Column('args', sa.VARCHAR(length=255), nullable=True),
sa.Column('env', sqlite.JSON(), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_index('ix_app_ai_mcp_creator_id', 'app_ai_mcp', ['creator_id'], unique=False)
op.create_table('system_dept',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('name', sa.VARCHAR(length=40), nullable=False),
sa.Column('order', sa.INTEGER(), nullable=False),
sa.Column('code', sa.VARCHAR(length=20), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('parent_id', sa.INTEGER(), nullable=True),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['parent_id'], ['system_dept.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('code'),
sa.UniqueConstraint('name')
)
op.create_index('ix_system_dept_parent_id', 'system_dept', ['parent_id'], unique=False)
op.create_table('system_notice',
sa.Column('notice_title', sa.VARCHAR(length=50), nullable=False),
sa.Column('notice_type', sa.VARCHAR(length=50), nullable=False),
sa.Column('notice_content', sa.TEXT(), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_system_notice_creator_id', 'system_notice', ['creator_id'], unique=False)
op.create_table('system_menu',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('name', sa.VARCHAR(length=50), nullable=False),
sa.Column('type', sa.INTEGER(), nullable=False),
sa.Column('order', sa.INTEGER(), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('permission', sa.VARCHAR(length=100), nullable=True),
sa.Column('icon', sa.VARCHAR(length=50), nullable=True),
sa.Column('route_name', sa.VARCHAR(length=100), nullable=True),
sa.Column('route_path', sa.VARCHAR(length=200), nullable=True),
sa.Column('component_path', sa.VARCHAR(length=200), nullable=True),
sa.Column('redirect', sa.VARCHAR(length=200), nullable=True),
sa.Column('hidden', sa.BOOLEAN(), nullable=False),
sa.Column('keep_alive', sa.BOOLEAN(), nullable=False),
sa.Column('always_show', sa.BOOLEAN(), nullable=False),
sa.Column('title', sa.VARCHAR(length=50), nullable=True),
sa.Column('params', sqlite.JSON(), nullable=True),
sa.Column('affix', sa.BOOLEAN(), nullable=False),
sa.Column('parent_id', sa.INTEGER(), nullable=True),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['parent_id'], ['system_menu.id'], ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_index('ix_system_menu_parent_id', 'system_menu', ['parent_id'], unique=False)
op.create_table('system_log',
sa.Column('type', sa.INTEGER(), nullable=False),
sa.Column('request_path', sa.VARCHAR(length=255), nullable=False),
sa.Column('request_method', sa.VARCHAR(length=10), nullable=False),
sa.Column('request_payload', sa.TEXT(), nullable=True),
sa.Column('request_ip', sa.VARCHAR(length=50), nullable=True),
sa.Column('login_location', sa.VARCHAR(length=255), nullable=True),
sa.Column('request_os', sa.VARCHAR(length=64), nullable=True),
sa.Column('request_browser', sa.VARCHAR(length=64), nullable=True),
sa.Column('response_code', sa.INTEGER(), nullable=False),
sa.Column('response_json', sa.TEXT(), nullable=True),
sa.Column('process_time', sa.VARCHAR(length=20), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_system_log_creator_id', 'system_log', ['creator_id'], unique=False)
op.create_table('system_users',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('username', sa.VARCHAR(length=32), nullable=False),
sa.Column('password', sa.VARCHAR(length=255), nullable=False),
sa.Column('name', sa.VARCHAR(length=32), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('mobile', sa.VARCHAR(length=20), nullable=True),
sa.Column('email', sa.VARCHAR(length=64), nullable=True),
sa.Column('gender', sa.VARCHAR(length=1), nullable=True),
sa.Column('avatar', sa.VARCHAR(length=500), nullable=True),
sa.Column('is_superuser', sa.BOOLEAN(), nullable=False),
sa.Column('last_login', sa.DATETIME(), nullable=True),
sa.Column('dept_id', sa.INTEGER(), nullable=True),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.ForeignKeyConstraint(['dept_id'], ['system_dept.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('mobile'),
sa.UniqueConstraint('username')
)
op.create_index('ix_system_users_dept_id', 'system_users', ['dept_id'], unique=False)
op.create_index('ix_system_users_creator_id', 'system_users', ['creator_id'], unique=False)
op.create_table('system_role',
sa.Column('name', sa.VARCHAR(length=40), nullable=False),
sa.Column('code', sa.VARCHAR(length=20), nullable=True),
sa.Column('order', sa.INTEGER(), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('data_scope', sa.INTEGER(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('code'),
sa.UniqueConstraint('name')
)
op.create_index('ix_system_role_creator_id', 'system_role', ['creator_id'], unique=False)
op.create_table('app_job_log',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('job_name', sa.VARCHAR(length=64), nullable=False),
sa.Column('job_group', sa.VARCHAR(length=64), nullable=False),
sa.Column('job_executor', sa.VARCHAR(length=64), nullable=False),
sa.Column('invoke_target', sa.VARCHAR(length=500), nullable=False),
sa.Column('job_args', sa.VARCHAR(length=255), nullable=True),
sa.Column('job_kwargs', sa.VARCHAR(length=255), nullable=True),
sa.Column('job_trigger', sa.VARCHAR(length=255), nullable=True),
sa.Column('job_message', sa.VARCHAR(length=500), nullable=True),
sa.Column('exception_info', sa.VARCHAR(length=2000), nullable=True),
sa.Column('job_id', sa.INTEGER(), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('create_time', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['job_id'], ['app_job.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('system_dict_type',
sa.Column('dict_name', sa.VARCHAR(length=100), nullable=False),
sa.Column('dict_type', sa.VARCHAR(length=100), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('dict_name'),
sa.UniqueConstraint('dict_type')
)
op.create_index('ix_system_dict_type_creator_id', 'system_dict_type', ['creator_id'], unique=False)
op.create_table('app_myapp',
sa.Column('name', sa.VARCHAR(length=64), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('access_url', sa.VARCHAR(length=500), nullable=False),
sa.Column('icon_url', sa.VARCHAR(length=300), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_index('ix_app_myapp_creator_id', 'app_myapp', ['creator_id'], unique=False)
op.create_table('system_user_positions',
sa.Column('user_id', sa.INTEGER(), nullable=False),
sa.Column('position_id', sa.INTEGER(), nullable=False),
sa.ForeignKeyConstraint(['position_id'], ['system_position.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['system_users.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.PrimaryKeyConstraint('user_id', 'position_id')
)
op.create_table('system_role_menus',
sa.Column('role_id', sa.INTEGER(), nullable=False),
sa.Column('menu_id', sa.INTEGER(), nullable=False),
sa.ForeignKeyConstraint(['menu_id'], ['system_menu.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.ForeignKeyConstraint(['role_id'], ['system_role.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.PrimaryKeyConstraint('role_id', 'menu_id')
)
op.create_table('system_role_depts',
sa.Column('role_id', sa.INTEGER(), nullable=False),
sa.Column('dept_id', sa.INTEGER(), nullable=False),
sa.ForeignKeyConstraint(['dept_id'], ['system_dept.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.ForeignKeyConstraint(['role_id'], ['system_role.id'], onupdate='CASCADE', ondelete='CASCADE'),
sa.PrimaryKeyConstraint('role_id', 'dept_id')
)
op.create_table('system_position',
sa.Column('name', sa.VARCHAR(length=40), nullable=False),
sa.Column('order', sa.INTEGER(), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_index('ix_system_position_creator_id', 'system_position', ['creator_id'], unique=False)
op.create_table('gen_table_column',
sa.Column('column_name', sa.VARCHAR(length=200), nullable=True),
sa.Column('column_comment', sa.VARCHAR(length=500), nullable=True),
sa.Column('column_type', sa.VARCHAR(length=100), nullable=True),
sa.Column('python_type', sa.VARCHAR(length=500), nullable=True),
sa.Column('python_field', sa.VARCHAR(length=200), nullable=True),
sa.Column('is_pk', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_increment', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_required', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_unique', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_insert', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_edit', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_list', sa.VARCHAR(length=1), nullable=True),
sa.Column('is_query', sa.VARCHAR(length=1), nullable=True),
sa.Column('query_type', sa.VARCHAR(length=200), nullable=True),
sa.Column('html_type', sa.VARCHAR(length=200), nullable=True),
sa.Column('dict_type', sa.VARCHAR(length=200), nullable=True),
sa.Column('sort', sa.INTEGER(), nullable=True),
sa.Column('table_id', sa.INTEGER(), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.ForeignKeyConstraint(['table_id'], ['gen_table.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_gen_table_column_creator_id', 'gen_table_column', ['creator_id'], unique=False)
op.create_table('app_job',
sa.Column('name', sa.VARCHAR(length=64), nullable=True),
sa.Column('jobstore', sa.VARCHAR(length=64), nullable=True),
sa.Column('executor', sa.VARCHAR(length=64), nullable=True),
sa.Column('trigger', sa.VARCHAR(length=64), nullable=False),
sa.Column('trigger_args', sa.TEXT(), nullable=True),
sa.Column('func', sa.TEXT(), nullable=False),
sa.Column('args', sa.TEXT(), nullable=True),
sa.Column('kwargs', sa.TEXT(), nullable=True),
sa.Column('coalesce', sa.BOOLEAN(), nullable=True),
sa.Column('max_instances', sa.INTEGER(), nullable=True),
sa.Column('start_date', sa.VARCHAR(length=64), nullable=True),
sa.Column('end_date', sa.VARCHAR(length=64), nullable=True),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_app_job_creator_id', 'app_job', ['creator_id'], unique=False)
op.create_table('system_dict_data',
sa.Column('dict_sort', sa.INTEGER(), nullable=False),
sa.Column('dict_label', sa.VARCHAR(length=100), nullable=False),
sa.Column('dict_value', sa.VARCHAR(length=100), nullable=False),
sa.Column('dict_type', sa.VARCHAR(length=100), nullable=False),
sa.Column('status', sa.BOOLEAN(), nullable=False),
sa.Column('css_class', sa.VARCHAR(length=100), nullable=True),
sa.Column('list_class', sa.VARCHAR(length=100), nullable=True),
sa.Column('is_default', sa.BOOLEAN(), nullable=False),
sa.Column('dict_type_id', sa.INTEGER(), nullable=True),
sa.Column('creator_id', sa.INTEGER(), nullable=True),
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('description', sa.TEXT(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=True),
sa.Column('updated_at', sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(['creator_id'], ['system_users.id'], onupdate='CASCADE', ondelete='SET NULL'),
sa.ForeignKeyConstraint(['dict_type_id'], ['system_dict_type.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_system_dict_data_creator_id', 'system_dict_data', ['creator_id'], unique=False)
# ### end Alembic commands ###
@@ -12,7 +12,7 @@ from app.common.request import PaginationService
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.constant import RET
from .param import GenTableQueryParam
from .schema import GenTableDeleteSchema, GenTableSchema, GenTableOutSchema
from .schema import GenTableSchema, GenTableOutSchema
from .service import GenTableColumnService, GenTableService
from app.utils.common_util import bytes2file_response
from app.core.logger import logger
@@ -47,7 +47,7 @@ async def get_gen_db_table_list_controller(
@GenRouter.post("/import", summary="导入表结构", description="导入表结构")
async def import_gen_table_controller(
table_names: List[str] = Query(..., description="表名列表"),
table_names: List[str] = Body(..., description="表名列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:import"])),
) -> JSONResponse:
add_gen_table_list = await GenTableService.get_gen_db_table_list_by_name_service(auth, table_names)
@@ -70,7 +70,7 @@ async def gen_table_detail_controller(
@GenRouter.post("/create", summary="创建表结构", description="创建表结构")
async def create_table_controller(
sql: str = Query(..., description="SQL语句:CREATE TABLE user_demo (\n id INTEGER NOT NULL PRIMARY KEY,\n username VARCHAR(64) NOT NULL UNIQUE,\n);"),
sql: str = Body(..., description="SQL语句:CREATE TABLE user_demo (\n id INTEGER NOT NULL PRIMARY KEY,\n username VARCHAR(64) NOT NULL UNIQUE,\n);"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:create"])),
) -> JSONResponse:
result = await GenTableService.create_table_service(auth, sql)
@@ -92,17 +92,17 @@ async def update_gen_table_controller(
@GenRouter.delete("/delete", summary="删除业务表信息", description="删除业务表信息")
async def delete_gen_table_controller(
data: GenTableDeleteSchema = Body(..., description="业务表ID列表"),
ids: List[int] = Body(..., description="业务表ID列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:delete"]))
) -> JSONResponse:
result = await GenTableService.delete_gen_table_service(auth, data)
result = await GenTableService.delete_gen_table_service(auth, ids)
logger.info('删除业务表信息成功')
return SuccessResponse(msg="删除业务表信息成功", data=result)
@GenRouter.patch("/batch/output", summary="批量生成代码", description="批量生成代码")
async def batch_gen_code_controller(
table_names: List[str] = Query(..., description="表名列表"),
table_names: List[str] = Body(..., description="表名列表"),
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:operate"]))
) -> StreamResponse:
# 检查table_names是否为空
@@ -15,7 +15,6 @@ from .model import GenTableModel, GenTableColumnModel
from .schema import (
GenTableSchema,
GenTableOutSchema,
GenTableDeleteSchema,
GenTableColumnSchema,
GenTableColumnOutSchema,
GenTableColumnDeleteSchema,
@@ -137,12 +136,12 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
await self.db.commit()
return edit_model
async def delete_gen_table(self, data: GenTableDeleteSchema) -> None:
async def delete_gen_table(self, ids: List[int]) -> None:
"""
删除
"""
await self.db.execute(
delete(GenTableModel).where(GenTableModel.id.in_(data.table_ids))
delete(GenTableModel).where(GenTableModel.id.in_(ids))
)
await self.db.flush()
@@ -459,10 +458,10 @@ class GenTableColumnCRUD(CRUDBase[GenTableColumnModel, GenTableColumnSchema, Gen
"""更新业务表字段"""
return await self.update(id=id, data=data)
async def delete_gen_table_column_by_table_id_dao(self, data: GenTableDeleteSchema) -> None:
async def delete_gen_table_column_by_table_id_dao(self, table_ids: List[int]) -> None:
"""根据业务表ID批量删除"""
# 先查询出这些表ID对应的所有字段ID
query = select(GenTableColumnModel.id).where(GenTableColumnModel.table_id.in_(data.table_ids))
query = select(GenTableColumnModel.id).where(GenTableColumnModel.table_id.in_(table_ids))
result = await self.db.execute(query)
column_ids = [row[0] for row in result.fetchall()]
@@ -108,15 +108,6 @@ class GenTableOutSchema(GenTableSchema, BaseSchema):
return values
class GenTableDeleteSchema(BaseModel):
"""
删除代码生成业务表模型
"""
model_config = ConfigDict(alias_generator=to_camel)
table_ids: List[int] = Field(..., description='需要删除的代码生成业务表ID列表')
class GenTableColumnSchema(BaseModel):
"""
代码生成业务表字段创建模型
@@ -16,7 +16,7 @@ from app.api.v1.module_system.auth.schema import AuthSchema
from app.utils.common_util import CamelCaseUtil
from app.utils.gen_util import GenUtils
from app.utils.jinja2_template_util import Jinja2TemplateInitializerUtil, Jinja2TemplateUtil
from .schema import GenTableSchema, GenTableOutSchema, GenTableOutSchema, GenTableDeleteSchema, GenTableColumnSchema, GenTableColumnOutSchema, GenTableColumnDeleteSchema
from .schema import GenTableSchema, GenTableOutSchema, GenTableOutSchema, GenTableColumnSchema, GenTableColumnOutSchema, GenTableColumnDeleteSchema
from .param import GenTableQueryParam
from .crud import GenTableColumnCRUD, GenTableCRUD
@@ -211,13 +211,13 @@ class GenTableService:
raise CustomException(msg='业务表不存在')
@classmethod
async def delete_gen_table_service(cls, auth: AuthSchema, data: GenTableDeleteSchema) -> None:
async def delete_gen_table_service(cls, auth: AuthSchema, ids: List[int]) -> None:
"""删除业务表信息"""
try:
# 先删除相关的字段信息
await GenTableColumnCRUD(auth=auth).delete_gen_table_column_by_table_id_dao(data)
await GenTableColumnCRUD(auth=auth).delete_gen_table_column_by_table_id_dao(ids)
# 再删除表信息
await GenTableCRUD(auth=auth).delete_gen_table(data)
await GenTableCRUD(auth=auth).delete_gen_table(ids)
except Exception as e:
raise CustomException(msg=f'删除失败: {str(e)}')
@@ -6,7 +6,7 @@ from datetime import datetime
from app.core.base_crud import CRUDBase
from .model import UserModel
from .schema import UserCreateSchema,UserForgetPasswordSchema,UserUpdateSchema
from .schema import UserCreateSchema, UserForgetPasswordSchema, UserUpdateSchema
from ..role.crud import RoleCRUD
from ..position.crud import PositionCRUD
@@ -65,7 +65,7 @@ class UserCreateSchema(CurrentUserUpdateSchema):
"""新增"""
model_config = ConfigDict(from_attributes=True)
username: str = Field(default=..., max_length=32, description="用户名")
username: Optional[str] = Field(default=None, max_length=32, description="用户名")
password: Optional[str] = Field(default=None, max_length=128, description="密码哈希值")
status: bool = Field(default=True, description="是否可用")
is_superuser: bool = Field(default=False, description="是否超管")
@@ -82,6 +82,7 @@ class UserUpdateSchema(UserCreateSchema):
last_login: Optional[DateTimeStr] = Field(default=None, description="最后登录时间")
class UserOutSchema(UserCreateSchema, BaseSchema):
"""响应"""
model_config = ConfigDict(arbitrary_types_allowed=True, from_attributes=True)
@@ -69,6 +69,8 @@ class UserService:
@classmethod
async def create_user_service(cls, data: UserCreateSchema, auth: AuthSchema) -> Dict:
if not data.username:
raise CustomException(msg="用户名不能为空")
# 检查用户名是否存在
user = await UserCRUD(auth).get_by_username_crud(username=data.username)
if user:
@@ -97,6 +99,8 @@ class UserService:
@classmethod
async def update_user_service(cls, id: int, data: UserUpdateSchema, auth: AuthSchema) -> Dict:
if not data.username:
raise CustomException(msg="用户名不能为空")
# 检查用户是否存在
user = await UserCRUD(auth).get_by_id_crud(id=id)
if not user:
+1 -24
View File
@@ -162,29 +162,6 @@ class Settings(BaseSettings):
GZIP_MIN_SIZE: int = 1000 # 最小压缩大小(字节)
GZIP_COMPRESS_LEVEL: int = 9 # 压缩级别(1-9)
# # ================================================= #
# # ***************** 演示模型配置 ***************** #
# # ================================================= #
# DEMO_ENABLE: bool # 是否开启演示模式
# DEMO_WHITE_LIST_PATH: List[str] = [ # 演示白名单
# "/api/v1/system/auth/login",
# "/api/v1/system/auth/token/refresh",
# "/api/v1/system/auth/captcha/get",
# "/api/v1/system/auth/logout",
# "/api/v1/system/config/info",
# "/api/v1/system/user/current/info",
# "/api/v1/system/notice/available",
# ]
# DEMO_BLACK_LIST_PATH: List[str] = [ # 演示黑名单
# "/auth/login"
# ]
# DEMO_IP_WHITE_LIST: List[str] = [ # 演示白名单IP
# "127.0.0.1",
# "117.10.167.220",
# "223.104.208.30",
# "42.80.102.171"
# ]
# ================================================= #
# ***************** 静态文件配置 ***************** #
# ================================================= #
@@ -202,7 +179,7 @@ class Settings(BaseSettings):
# ================================================= #
# ***************** 动态文件配置 ***************** #
# ================================================= #
UPLOAD_FILE_PATH: Path = BASE_DIR.joinpath('static/upload') # 上传目录
UPLOAD_FILE_PATH: Path = Path('static/upload') # 上传目录
UPLOAD_MACHINE: str = 'A' # 上传机器标识
ALLOWED_EXTENSIONS: list[str] = [ # 允许的文件类型
# 图片
-1
View File
@@ -12,7 +12,6 @@ from app.api.v1.module_generator.gencode.schema import (
GenTableBaseSchema,
GenTableSchema,
GenTableOutSchema,
GenTableDeleteSchema,
GenTableColumnSchema,
GenTableColumnOutSchema,
GenTableColumnDeleteSchema
+1 -1
View File
@@ -224,7 +224,7 @@ class Jinja2TemplateUtil:
# Vue相关模板
f'{use_web_type}/api.ts.j2',
# SQL脚本模板
'sql/sql.j2',
'sql/sql.sql.j2',
]
if category == GenConstant.TPL_CRUD:
templates.append(f'{use_web_type}/index.vue.j2')
+1 -1
View File
@@ -22,7 +22,7 @@ pydantic-settings==2.5.2 # 配置设置
psutil==6.1.0 # 系统信息
python-multipart==0.0.9 # request.form() 对表单进行「解析」时安装
greenlet==3.1.1 # 协程框架
bcrypt==4.0.1 # 密码加密解析
bcrypt==4.3.0 # 密码加密解析
itsdangerous==2.2.0 # 用于安全处理各种数据,如密码、密钥等
aiofiles==24.1.0 # 文件操作
redis==5.2.1 # redis 同步操作数据库(用户celery配套使用)redis 异步操作数据库 redis已经完全具备了aioredis的功能,无需重复安全,且aioredis已经不再维护也不兼容3.10+的版本
+112 -40
View File
@@ -4,7 +4,7 @@ const API_PATH = "/generator/gencode";
const GencodeAPI = {
// 查询生成表数据
listTable(query: TablePageQuery) {
listTable(query: GenTableQueryParam) {
return request<ApiResponse<PageResult<GenTableOutVO[]>>>({
url: `${API_PATH}/list`,
method: 'get',
@@ -13,25 +13,20 @@ const GencodeAPI = {
},
// 查询db数据库列表
listDbTable(query: TablePageQuery) {
return request<ApiResponse<PageResult<TablePageVO[]>>>({
listDbTable(query: GenTableQueryParam) {
return request<ApiResponse<PageResult<DatabaseTable[]>>>({
url: `${API_PATH}/db/list`,
method: 'get',
params: query
})
},
// 导入表 - 将数组转换为适合FastAPI解析的格式
// 导入表
importTable(table_names: string[]) {
// 构建符合FastAPI期望的查询字符串
let queryString = '';
table_names.forEach((name, index) => {
queryString += `${index === 0 ? '?' : '&'}table_names=${encodeURIComponent(name)}`;
});
return request<ApiResponse>({
url: `${API_PATH}/import${queryString}`,
method: 'post'
url: `${API_PATH}/import`,
method: 'post',
data: table_names
})
},
@@ -48,25 +43,25 @@ const GencodeAPI = {
return request<ApiResponse>({
url: `${API_PATH}/create`,
method: 'post',
params: { sql }
data: sql
})
},
// 修改代码生成信息
updateGenTable(table_id: number, body: GenTableSchema) {
// 更新表信息
updateTable(data: GenTableSchema, table_id: number) {
return request<ApiResponse>({
url: `${API_PATH}/update/${table_id}`,
method: 'put',
data: body,
data
})
},
// 删除表数据
deleteTable(data: GenTableDeleteSchema) {
deleteTable(table_ids: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/delete`,
method: 'delete',
data
data: table_ids
})
},
@@ -75,7 +70,7 @@ const GencodeAPI = {
return request<Blob>({
url: `${API_PATH}/batch/output`,
method: 'patch',
params: { table_names },
data: table_names,
responseType: 'blob'
})
},
@@ -89,9 +84,9 @@ const GencodeAPI = {
},
// 预览生成代码
previewTable(table_id: number) {
return request<ApiResponse<GeneratorPreviewVO[]>>({
url: `${API_PATH}/preview/${table_id}`,
previewTable(id: number) {
return request<ApiResponse<Record<string, string>>>({
url: `${API_PATH}/preview/${id}`,
method: 'get'
})
},
@@ -118,6 +113,15 @@ export interface GeneratorPreviewVO {
}
/** 数据表分页查询参数 */
export interface GenTableQueryParam {
page_no: number;
page_size: number;
table_name?: string;
table_comment?: string;
start_time?: string;
end_time?: string;
}
export interface TablePageQuery extends PageQuery {
/** 表名称 */
table_name?: string;
@@ -146,27 +150,27 @@ export interface GenTableOutVO {
/** 主键 */
id?: number;
/** 表名称 */
table_name: string;
table_name?: string;
/** 表描述 */
table_comment: string;
table_comment?: string;
/** 关联子表的表名 */
sub_table_name?: string;
/** 子表关联的外键名 */
sub_table_fk_name: string;
sub_table_fk_name?: string;
/** 实体类名称 */
class_name: string;
class_name?: string;
/** 使用的模板(crud单表操作 tree树表操作) */
tpl_category?: string;
/** 前端模板类型(element-ui模版 element-plus模版) */
tpl_web_type?: string;
/** 生成包路径 */
package_name: string;
package_name?: string;
/** 生成模块名 */
module_name: string;
module_name?: string;
/** 生成业务名 */
business_name: string;
business_name?: string;
/** 生成功能名 */
function_name: string;
function_name?: string;
/** 生成功能作者 */
function_author?: string;
/** 生成代码方式(0zip压缩包 1自定义路径) */
@@ -191,6 +195,24 @@ export interface GenTableOutVO {
tree?: boolean;
/** 是否为单表 */
crud?: boolean;
/** 表描述 */
description?: string;
/** 列列表 */
columns?: GenTableColumnOutSchema[];
/** 参数选项 */
params?: GenTableOptionModel;
}
/** 表选项模型 */
export interface GenTableOptionModel {
/** 所属父级分类 */
parent_menu_id?: number;
/** 树编码 */
tree_code?: string;
/** 树名称 */
tree_name?: string;
/** 树父编码 */
tree_parent_code?: string;
}
/** 代码生成业务表模型 */
@@ -214,11 +236,11 @@ export interface GenTableColumnSchema {
/** 列描述 */
column_comment?: string;
/** 列类型 */
column_type: string;
column_type?: string;
/** PYTHON类型 */
python_type?: string;
/** PYTHON字段名 */
python_field: string;
python_field?: string;
/** 是否主键(1是) */
is_pk?: string;
/** 是否自增(1是) */
@@ -238,9 +260,9 @@ export interface GenTableColumnSchema {
/** 查询方式(等于、不等于、大于、小于、范围) */
query_type?: string;
/** 显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件) */
html_type: string;
html_type?: string;
/** 字典类型 */
dict_type: string;
dict_type?: string;
/** 排序 */
sort?: number;
/** 功能描述 */
@@ -273,12 +295,6 @@ export interface GenTableColumnOutSchema extends GenTableColumnSchema {
usable_column?: boolean;
}
/** 删除代码生成业务表模型 */
export interface GenTableDeleteSchema {
/** 需要删除的代码生成业务表ID列表 */
table_ids: number[];
}
/** 表详情查询结果 */
export interface GenTableDetailResult {
/** 表信息 */
@@ -288,3 +304,59 @@ export interface GenTableDetailResult {
/** 所有表信息 */
tables: GenTableOutVO[];
}
/**
*
*/
export interface DatabaseTable {
database_name?: string;
table_name?: string;
table_comment?: string;
table_type?: string;
}
/**
*
*/
export interface TableColumn {
column_name: string;
column_comment: string;
}
/**
*
*/
export interface TableInfo {
table_name?: string;
table_comment?: string;
columns?: TableColumn[];
}
/**
*
*/
export interface DictOption {
dict_type: string;
dict_name: string;
}
/**
*
*/
export interface ImportTableQueryForm {
page_no: number;
page_size: number;
table_name?: string;
table_comment?: string;
}
/**
*
*/
export interface BasicInfoFormData {
table_name?: string;
table_comment?: string;
class_name?: string;
function_author?: string;
remark?: string;
}
+19 -11
View File
@@ -220,17 +220,17 @@ export interface positionSelectorType {
export interface InfoFormState {
id?: number;
name: string;
gender: number;
mobile: string;
email: string;
username: string;
dept_name: string;
dept: deptTreeType;
positions: positionSelectorType[];
roles: roleSelectorType[];
avatar: string;
created_at: string;
name?: string;
gender?: number;
mobile?: string;
email?: string;
username?: string;
dept_name?: string;
dept?: deptTreeType;
positions?: positionSelectorType[];
roles?: roleSelectorType[];
avatar?: string;
created_at?: string;
}
export interface PasswordFormState {
@@ -262,3 +262,11 @@ export interface UserForm {
status?: boolean;
description?: string;
}
export interface CurrentUserFormState {
name?: string;
gender?: number;
mobile?: string;
email?: string;
avatar?: string;
}
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1760263323196" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1502" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M420.693333 85.333333C353.28 85.333333 298.666667 139.946667 298.666667 207.36v71.68h183.04c16.64 0 30.293333 24.32 30.293333 40.96H207.36C139.946667 320 85.333333 374.613333 85.333333 442.026667v161.322666c0 67.413333 54.613333 122.026667 122.026667 122.026667h50.346667v-114.346667c0-67.413333 54.186667-122.026667 121.6-122.026666h224c67.413333 0 122.026667-54.229333 122.026666-121.642667V207.36C725.333333 139.946667 670.72 85.333333 603.306667 85.333333z m-30.72 68.693334c17.066667 0 30.72 5.12 30.72 30.293333s-13.653333 38.016-30.72 38.016c-16.64 0-30.293333-12.8-30.293333-37.973333s13.653333-30.336 30.293333-30.336z" fill="#3C78AA" p-id="1503"></path><path d="M766.250667 298.666667v114.346666a121.6 121.6 0 0 1-121.6 121.984H420.693333A121.6 121.6 0 0 0 298.666667 656.597333v160a122.026667 122.026667 0 0 0 122.026666 122.026667h182.613334A122.026667 122.026667 0 0 0 725.333333 816.64v-71.68h-183.082666c-16.64 0-30.250667-24.32-30.250667-40.96h304.64A122.026667 122.026667 0 0 0 938.666667 581.973333v-161.28a122.026667 122.026667 0 0 0-122.026667-122.026666zM354.986667 491.221333l-0.170667 0.170667c0.512-0.085333 1.066667-0.042667 1.621333-0.170667z m279.04 310.442667c16.64 0 30.293333 12.8 30.293333 37.973333a30.293333 30.293333 0 0 1-30.293333 30.293334c-17.066667 0-30.72-5.12-30.72-30.293334s13.653333-37.973333 30.72-37.973333z" fill="#FDD835" p-id="1504"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1760263428378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5841" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M33.792 631.808c0 84.992 214.016 153.6 478.208 153.6 263.168 0 477.184-68.608 478.208-153.6V509.952C891.904 580.608 701.44 614.4 512 614.4c-189.44 0-379.904-33.792-478.208-105.472v122.88z" fill="#00CCFF" p-id="5842"></path><path d="M990.208 747.52C891.904 819.2 701.44 852.992 512 852.992 322.56 852.992 132.096 819.2 33.792 747.52v139.264C60.416 964.608 266.24 1024 512 1024s451.584-59.392 478.208-136.192V747.52zM33.792 392.192c0 84.992 214.016 153.6 478.208 153.6 263.168 0 477.184-68.608 478.208-153.6V270.336c-98.304 71.68-288.768 105.472-478.208 105.472-189.44 0-379.904-33.792-478.208-105.472v121.856z" fill="#00CCFF" p-id="5843"></path><path d="M33.792 153.6a478.208 153.6 0 1 0 956.416 0 478.208 153.6 0 1 0-956.416 0Z" fill="#00CCFF" p-id="5844"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1 -1
View File
@@ -116,6 +116,6 @@ html.sidebar-color-blue .layout-mix .layout__sidebar--left .el-menu {
// 分页区域
.el-pagination {
justify-content: flex-end;
// margin-top: 1px;
// margin-top: 16px;
}
}
+11 -14
View File
@@ -44,7 +44,7 @@
{{ infoFormState.name }}
</span>
<el-text>{{infoFormState.roles.map(item => item.name).join('、')}}</el-text>
<el-text>{{infoFormState.roles?.map(item => item.name).join('、')}}</el-text>
</div>
<el-divider />
@@ -68,7 +68,7 @@
</el-icon>
<span style="vertical-align: middle;">部门</span>
</template>
<span style="vertical-align: middle;">{{ infoFormState.dept.name }}</span>
<span style="vertical-align: middle;">{{ infoFormState.dept?.name }}</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
@@ -77,7 +77,7 @@
</el-icon>
<span style="vertical-align: middle;">岗位</span>
</template>
<span style="vertical-align: middle;">{{infoFormState.positions.map(item => item.name).join('、')}}</span>
<span style="vertical-align: middle;">{{infoFormState.positions?.map(item => item.name).join('、')}}</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
@@ -176,7 +176,7 @@
</el-input>
</el-form-item>
<el-form-item label="确认密码" name="confirm_password">
<el-form-item label="确认密码" name="confirm_password">
<el-input v-model.trim="passwordFormState.confirm_password" type="password" :placeholder="t('login.message.password.confirm')" show-password clearable style="width: 240px;">
<template #prefix>
<Check />
@@ -227,17 +227,17 @@ const infoSubmitting = ref(false);
//
const infoFormState = reactive<InfoFormState>({
name: '',
name: undefined,
gender: 1,
mobile: '',
email: '',
username: '',
dept_name: '',
mobile: undefined,
email: undefined,
username: undefined,
dept_name: undefined,
dept: {},
positions: [],
roles: [],
avatar: '',
created_at: ''
avatar: undefined,
created_at: undefined
});
//
@@ -421,9 +421,6 @@ const handleSave = async () => {
// avatar
const response = await UserAPI.updateCurrentUserInfo({...infoFormState});
await userStore.setUserInfo(response.data.data);
} catch (error) {
console.error(error);
ElMessage.error('保存失败,请重试');
} finally {
infoSubmitting.value = false;
}
File diff suppressed because it is too large Load Diff
@@ -1,48 +0,0 @@
<template>
<el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item label="表名称" prop="tableName">
<el-input v-model="info.table_name" placeholder="请输入仓库名称"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="表描述" prop="tableComment">
<el-input v-model="info.table_comment" placeholder="请输入"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实体类名称" prop="className">
<el-input v-model="info.class_name" placeholder="请输入"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="作者" prop="functionAuthor">
<el-input v-model="info.function_author" placeholder="请输入"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="info.remark" type="textarea" :rows="3"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
defineProps({
info: {
type: Object,
default: null
}
});
//
const rules = ref({
table_name: [{ required: true, message: "请输入表名称", trigger: "blur" }],
table_comment: [{ required: true, message: "请输入表描述", trigger: "blur" }],
class_name: [{ required: true, message: "请输入实体类名称", trigger: "blur" }],
function_author: [{ required: true, message: "请输入作者", trigger: "blur" }]
});
</script>
@@ -1,46 +0,0 @@
<template>
<!-- 创建表 -->
<el-dialog v-model="visible" title="创建表" width="800px" top="5vh" append-to-body>
<span>创建表语句(支持多个建表语句)</span>
<el-input v-model="content" type="textarea" :rows="10" placeholder="请输入文本"></el-input>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleImportTable"> </el-button>
<el-button @click="visible = false"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import GencodeAPI from "@/api/generator/gencode";
import { ElMessage } from 'element-plus';
const visible = ref(false);
const content = ref("");
const emit = defineEmits(["ok"]);
/** 显示弹框 */
function show() {
visible.value = true;
}
/** 导入按钮操作 */
function handleImportTable() {
if (content.value === "") {
ElMessage.error("请输入建表语句");
return;
}
GencodeAPI.createTable(content.value).then(res => {
ElMessage.success(res.data.msg || "创建成功");
if (res.data.code === 200) {
visible.value = false;
emit("ok");
}
});
}
defineExpose({
show,
});
</script>
@@ -1,235 +0,0 @@
<template>
<el-card>
<el-tabs v-model="activeName">
<el-tab-pane label="基本信息" name="basic">
<basic-info-form ref="basicInfo" :info="info" />
</el-tab-pane>
<el-tab-pane label="字段信息" name="columnInfo">
<el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
<el-table-column label="序号" type="index" min-width="5%"/>
<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"></el-input>
</template>
</el-table-column>
<el-table-column
label="物理类型"
prop="columnType"
min-width="10%"
:show-overflow-tooltip="true"
/>
<el-table-column label="Python类型" min-width="11%">
<template #default="scope">
<el-select v-model="scope.row.pythonType">
<el-option label="str" value="str" />
<el-option label="int" value="int" />
<el-option label="float" value="float" />
<el-option label="Decimal" value="Decimal" />
<el-option label="date" value="date" />
<el-option label="time" value="time" />
<el-option label="datetime" value="datetime" />
<el-option label="bytes" value="bytes" />
<el-option label="dict" value="dict" />
<el-option label="list" value="list" />
</el-select>
</template>
</el-table-column>
<el-table-column label="Python属性" min-width="10%">
<template #default="scope">
<el-input v-model="scope.row.pythonField"></el-input>
</template>
</el-table-column>
<el-table-column label="插入" min-width="5%">
<template #default="scope">
<el-checkbox v-model="scope.row.isInsert" true-label="1" false-label="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="编辑" min-width="5%">
<template #default="scope">
<el-checkbox v-model="scope.row.isEdit" true-label="1" false-label="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="列表" min-width="5%">
<template #default="scope">
<el-checkbox v-model="scope.row.isList" true-label="1" false-label="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="查询" min-width="5%">
<template #default="scope">
<el-checkbox v-model="scope.row.isQuery" true-label="1" false-label="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="查询方式" min-width="10%">
<template #default="scope">
<el-select v-model="scope.row.queryType">
<el-option label="=" value="EQ" />
<el-option label="!=" value="NE" />
<el-option label=">" value="GT" />
<el-option label=">=" value="GTE" />
<el-option label="<" value="LT" />
<el-option label="<=" value="LTE" />
<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 v-model="scope.row.isRequired" true-label="1" false-label="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="唯一" min-width="5%">
<template #default="scope">
<el-checkbox v-model="scope.row.isUnique" true-label="1" false-label="0"></el-checkbox>
</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.dictType"
:label="dict.dictName"
:value="dict.dictType">
<span style="float: left">{{ dict.dictName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
</el-option>
</el-select>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="生成信息" name="genInfo">
<!-- 将GenTableSchema类型转换为GenInfo类型 -->
<gen-info-form
ref="genInfo"
:info="convertToGenInfo(info)"
:tables="tables"
/>
</el-tab-pane>
</el-tabs>
<el-form label-width="100px">
<div style="text-align: center;margin-left:-100px;margin-top:10px;">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
</div>
</el-form>
</el-card>
</template>
<script setup lang="ts" name="GenEdit">
import GencodeAPI from "@/api/generator/gencode";
import DictAPI from "@/api/system/dict";
import { ElMessage } from 'element-plus';
import router from '@/router';
import type { GenTableSchema, GenTableDetailResult } from '@/api/generator/gencode';
const route = useRoute();
const basicInfoRef = ref();
const genInfoRef = ref();
const activeName = ref("columnInfo");
const tableHeight = ref(document.documentElement.scrollHeight - 245 + "px");
const tables = ref<Array<any>>([]);
const columns = ref<Array<any>>([]);
const dictOptions = ref<Array<any>>([]);
const info = ref<GenTableSchema>({} as GenTableSchema);
/**
* 将对象转换为GenInfo类型
*/
function convertToGenInfo(tableSchema: any): any {
if (!tableSchema) {
return {};
}
return {
tplCategory: tableSchema.tpl_category,
tplWebType: tableSchema.tpl_web_type,
packageName: tableSchema.package_name,
moduleName: tableSchema.module_name,
businessName: tableSchema.business_name,
functionName: tableSchema.function_name,
genType: tableSchema.gen_type,
parentMenuId: tableSchema.parent_menu_id,
genPath: tableSchema.gen_path,
subTableName: tableSchema.sub_table_name,
subTableFkName: tableSchema.sub_table_fk_name,
treeCode: tableSchema.tree_code,
treeParentCode: tableSchema.tree_parent_code,
treeName: tableSchema.tree_name
};
}
/** 提交按钮 */
function submitForm() {
//
const genTable = Object.assign({}, info.value);
genTable.columns = columns.value;
genTable.tree_code = info.value.tree_code;
genTable.tree_name = info.value.tree_name;
genTable.tree_parent_code = info.value.tree_parent_code;
genTable.parent_menu_id = info.value.parent_menu_id;
// idnumber
if (info.value && info.value.id !== undefined) {
GencodeAPI.updateGenTable(Number(info.value.id), genTable).then((res: any) => {
ElMessage.success(res.data.message || "更新成功");
if (res.data.code === 200) {
close();
}
});
} else {
ElMessage.error("表ID不存在,无法更新");
}
}
function close() {
const pageNum = route.query.page_no || route.query.pageNum;
router.push({ path: "/tool/gen", query: { t: Date.now(), page_no: pageNum } });
}
(() => {
const tableId = route.params && route.params.tableId;
if (tableId) {
//
GencodeAPI.getGenTableDetail(Number(tableId)).then(res => {
if (res.data && res.data.data) {
columns.value = res.data.data.rows || [];
// infocolumns
const tableInfo = res.data.data.info || {};
info.value = {
...tableInfo,
columns: columns.value
};
tables.value = res.data.data.tables || [];
}
});
/** 查询字典下拉列表 */
DictAPI.getDictTypeOptionselect().then((response: any) => {
dictOptions.value = response.data.data || [];
});
}
})();
</script>
@@ -1,424 +0,0 @@
<template>
<el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item prop="tplCategory">
<template #label>生成模板</template>
<el-select v-model="info.tplCategory" @change="tplSelectChange">
<el-option label="单表(增删改查)" value="crud" />
<el-option label="树表(增删改查)" value="tree" />
<el-option label="主子表(增删改查)" value="sub" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="tplWebType">
<template #label>前端类型</template>
<el-select v-model="info.tplWebType">
<el-option label="Vue2 Element UI 模版" value="element-ui" />
<el-option label="Vue3 Element Plus 模版" value="element-plus" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="packageName">
<template #label>
生成包路径
<el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.packageName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="moduleName">
<template #label>
生成模块名
<el-tooltip content="可理解为子系统名,例如 system" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.moduleName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="businessName">
<template #label>
生成业务名
<el-tooltip content="可理解为功能英文名,例如 user" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.businessName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="functionName">
<template #label>
生成功能名
<el-tooltip content="用作类描述,例如 用户" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.functionName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="genType">
<template #label>
生成代码方式
<el-tooltip content="默认为zip压缩包下载,也可以自定义生成路径" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-radio v-model="info.genType" value="0">zip压缩包</el-radio>
<el-radio v-model="info.genType" value="1">自定义路径</el-radio>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
上级菜单
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-tree-select
v-model="info.parentMenuId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
value-key="menuId"
placeholder="请选择系统菜单"
check-strictly
/>
</el-form-item>
</el-col>
<el-col v-if="info.genType == '1'" :span="24">
<el-form-item prop="genPath">
<template #label>
自定义路径
<el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.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="handleResetGenPath">恢复默认的生成基础路径</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<template v-if="info.tplCategory == 'tree'">
<h4 class="form-header">其他信息</h4>
<el-row v-show="info.tplCategory == 'tree'">
<el-col :span="12">
<el-form-item>
<template #label>
树编码字段
<el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-select v-model="info.treeCode" placeholder="请选择">
<el-option
v-for="(column, index) in info.columns || []"
:key="index"
:label="column.columnName + '' + column.columnComment"
:value="column.columnName"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
树父编码字段
<el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-select v-model="info.treeParentCode" placeholder="请选择">
<el-option
v-for="(column, index) in info.columns || []"
:key="index"
:label="column.columnName + '' + column.columnComment"
:value="column.columnName"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
树名称字段
<el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-select v-model="info.treeName" placeholder="请选择">
<el-option
v-for="(column, index) in info.columns || []"
:key="index"
:label="column.columnName + '' + column.columnComment"
:value="column.columnName"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
<template v-if="info.tplCategory == 'sub'">
<h4 class="form-header">关联信息</h4>
<el-row>
<el-col :span="12">
<el-form-item>
<template #label>
关联子表的表名
<el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
<el-option
v-for="(table, index) in tables || []"
:key="index"
:label="(table.tableName || '') + '' + (table.tableComment || '')"
:value="table.tableName || ''"
:disabled="!table.tableName"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
子表关联的外键名
<el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</template>
<el-select v-model="info.subTableFkName" placeholder="请选择">
<el-option
v-for="(column, index) in subColumns"
:key="index"
:label="column.columnName + '' + column.columnComment"
:value="column.columnName"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
</el-form>
</template>
<script setup lang="ts">
import MenuAPI from "@/api/system/menu";
import { ref, computed, onMounted, watch } from 'vue';
import { useRouter } from 'vue-router';
const subColumns = ref<Array<{ columnName: string; columnComment: string }>>([]);
const menuOptions = ref<Array<{ id: number; menuId: number; menuName: string; parent_id: number; children: Array<any> }>>([]);
const router = useRouter();
//
interface TableColumn {
columnName: string;
columnComment: string;
}
interface TableInfo {
tableName?: string;
tableComment?: string;
columns?: TableColumn[];
}
interface GenInfo {
tplCategory?: string;
tplWebType?: string;
packageName?: string;
moduleName?: string;
businessName?: string;
functionName?: string;
genType?: string;
parentMenuId?: number;
genPath?: string;
subTableName?: string;
subTableFkName?: string;
columns?: TableColumn[];
treeCode?: string;
treeParentCode?: string;
treeName?: string;
}
const props = defineProps<{
info?: GenInfo;
tables?: TableInfo[];
}>();
const emit = defineEmits<{
(e: 'update:info', value: GenInfo): void;
}>();
// 使computedinfo
const info = computed<GenInfo>({
get() {
return {
tplCategory: '',
tplWebType: 'element-plus',
packageName: '',
moduleName: '',
businessName: '',
functionName: '',
genType: '0',
parentMenuId: undefined,
genPath: '',
subTableName: '',
subTableFkName: '',
columns: [],
treeCode: '',
treeParentCode: '',
treeName: '',
...props.info
};
},
set(newValue: GenInfo) {
emit('update:info', newValue);
}
});
//
const rules = ref({
tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }],
packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }],
moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }],
businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }],
functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }]
});
function subSelectChange() {
emit('update:info', {
...info.value,
subTableFkName: ""
});
}
function tplSelectChange(value: string) {
if (value !== "sub") {
emit('update:info', {
...info.value,
subTableName: "",
subTableFkName: ""
});
}
}
function setSubTableColumns(value?: string) {
if (!value || !props.tables) {
subColumns.value = [];
return;
}
for (const item of props.tables) {
if (item.tableName === value && item.columns) {
subColumns.value = item.columns;
break;
}
}
}
//
function handleResetGenPath() {
emit('update:info', {
...info.value,
genPath: '/'
});
}
/** 查询菜单下拉树结构 */
function getMenuTreeselect() {
MenuAPI.getMenuList().then((response: any) => {
//
function buildTree(data: any[], idField: string): any[] {
const result: any[] = [];
const map: Record<string, any> = {};
// id
data.forEach(item => {
map[item[idField]] = item;
item.children = [];
// tree-select
if (item.id !== undefined) {
item.menuId = item.id;
}
if (item.menu_name !== undefined) {
item.menuName = item.menu_name;
}
});
//
data.forEach(item => {
if (item.parent_id === 0 || !map[item.parent_id]) {
result.push(item);
} else {
map[item.parent_id].children.push(item);
}
});
return result;
}
if (response && response.data && response.data.data) {
menuOptions.value = buildTree(response.data.data, "id");
}
});
}
onMounted(() => {
getMenuTreeselect();
// tplWebType
if (!props.info?.tplWebType) {
emit('update:info', {
...info.value,
tplWebType: "element-plus"
});
}
});
watch(() => props.info?.subTableName, (val) => {
setSubTableColumns(val);
});
watch(() => props.info?.tplWebType, (val) => {
if (val === '' || val === undefined) {
emit('update:info', {
...info.value,
tplWebType: "element-plus"
});
}
});
</script>
@@ -1,139 +0,0 @@
<template>
<!-- 导入表 -->
<el-dialog v-model="visible" title="导入表" width="800px" top="5vh" append-to-body>
<el-form ref="queryRef" :model="queryFormData" :inline="true">
<el-form-item label="表名称" prop="tableName">
<el-input
v-model="queryFormData.table_name"
placeholder="请输入表名称"
clearable
style="width: 180px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="表描述" prop="tableComment">
<el-input
v-model="queryFormData.table_comment"
placeholder="请输入表描述"
clearable
style="width: 180px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row>
<el-table ref="table" :data="dbTableList" height="300px" @row-click="clickRow" @selection-change="handleSelectionChange">
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="序号" type="index" min-width="55" align="center" fixed>
<template #default="scope">
<span>{{(queryFormData.page_no - 1) * queryFormData.page_size + scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column prop="database_name" label="数据库名称" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="table_name" label="表名称" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="table_comment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="table_type" label="表类型"></el-table-column>
</el-table>
<pagination
v-model:page="queryFormData.page_no"
v-model:limit="queryFormData.page_size"
:total="total"
@pagination="getList"
/>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleImportTable"> </el-button>
<el-button @click="visible = false"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import GencodeAPI from "@/api/generator/gencode";
import { ElMessage } from 'element-plus';
const total = ref(0);
const visible = ref(false);
const tables = ref<Array<string>>([]);
const dbTableList = ref<Array<any>>([]);
const queryRef = ref();
const table = ref();
const queryFormData = reactive({
page_no: 1,
page_size: 10,
table_name: undefined,
table_comment: undefined
});
const emit = defineEmits(["ok"]);
/** 查询参数列表 */
function show() {
getList();
visible.value = true;
}
/** 单击选择行 */
function clickRow(row: any) {
table.value?.toggleRowSelection(row);
}
/** 多选框选中数据 */
function handleSelectionChange(selection: Array<any>) {
tables.value = selection.map(item => item.table_name);
}
/** 查询表数据 */
function getList() {
GencodeAPI.listDbTable(queryFormData).then(res => {
console.log(res.data);
dbTableList.value = res.data.data.items;
total.value = res.data.data.total;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryFormData.page_no = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryRef.value) {
queryRef.value.resetFields();
}
handleQuery();
}
/** 导入按钮操作 */
function handleImportTable() {
const tableNames = tables.value.join(",");
if (tableNames == "") {
ElMessage.error("请选择要导入的表");
return;
}
//
GencodeAPI.importTable(tableNames.split(",")).then((res: any) => {
ElMessage.success(res.data.message);
if (res.data.code === 200) {
visible.value = false;
emit("ok");
}
});
}
defineExpose({
show,
});
</script>
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -191,7 +191,8 @@ export default defineConfig(({ mode }: ConfigEnv) => {
"element-plus/es/components/header/style/index",
"element-plus/es/components/slider/style/index",
"element-plus/es/components/button-group/style/index",
"element-plus/es/components/result/style/index"
"element-plus/es/components/result/style/index",
"element-plus/es/components/checkbox-button/style/index"
],
},
// 构建配置