From 700d76ad5acd1b1f1f041362b2bcbebcb013e709 Mon Sep 17 00:00:00 2001 From: zhangtao <9480807882@qq.com> Date: Wed, 17 Sep 2025 01:33:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(model):=20=E6=B7=BB=E5=8A=A0status?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=A1=A8=E7=A4=BA=E5=90=AF=E7=94=A8=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在myapp模块的ApplicationModel中新增status字段,标识应用是否启用 - 在demo模块的DemoModel中新增status字段,标识示例条目是否启用 - 修改代码生成模块相关模型,替换BaseMixin为CreatorMixin - 删除代码生成模块中Python模板相关文件与Vue前端代码模板,优化代码结构和清理无用模板文件 --- .../api/v1/module_application/myapp/model.py | 3 + .../app/api/v1/module_example/demo/model.py | 3 +- .../app/api/v1/module_generator/__init__.py | 2 + .../api/v1/module_generator/gencode/model.py | 36 +- .../templates/python/controller_template.j2 | 0 .../templates/python/dao_template.j2 | 0 .../templates/python/model_do_template.j2 | 0 .../templates/python/model_vo_template.j2 | 0 .../templates/python/service_template.j2 | 0 .../{ => gencode}/templates/sql/sql.j2 | 0 .../{ => gencode}/templates/vue/api.js.j2 | 0 .../{ => gencode}/templates/vue/index.vue.j2 | 0 .../app/api/v1/module_monitor/job/model.py | 2 +- .../app/api/v1/module_resource/__init__.py | 4 +- .../v1/module_resource/resource/__init__.py | 4 - .../v1/module_resource/resource/controller.py | 24 +- .../app/api/v1/module_system/dept/model.py | 3 +- .../app/api/v1/module_system/dict/model.py | 2 + .../app/api/v1/module_system/menu/model.py | 1 + .../app/api/v1/module_system/notice/model.py | 3 +- .../app/api/v1/module_system/params/model.py | 1 + .../api/v1/module_system/position/model.py | 3 +- .../app/api/v1/module_system/role/model.py | 3 +- .../api/v1/module_system/ticket/controller.py | 2 +- .../app/api/v1/module_system/ticket/model.py | 8 +- .../app/api/v1/module_system/ticket/param.py | 4 +- .../app/api/v1/module_system/ticket/schema.py | 3 +- .../app/api/v1/module_system/user/model.py | 1 + .../v1/module_system/version/controller.py | 2 +- .../app/api/v1/module_system/version/crud.py | 27 +- .../app/api/v1/module_system/version/model.py | 2 +- .../app/api/v1/module_system/version/param.py | 5 +- .../api/v1/module_system/version/schema.py | 6 +- .../api/v1/module_system/version/service.py | 3 +- backend/app/core/base_model.py | 1 - backend/app/core/validator.py | 6 +- backend/app/scripts/data/system_menu.json | 174 +++++- frontend/src/api/system/ticket.ts | 83 +++ frontend/src/api/system/version.ts | 78 +++ frontend/src/views/system/ticket/index.vue | 575 ++++++++++++++++++ frontend/src/views/system/version/index.vue | 480 +++++++++++++++ 41 files changed, 1463 insertions(+), 91 deletions(-) create mode 100644 backend/app/api/v1/module_generator/__init__.py rename backend/app/api/v1/module_generator/{ => gencode}/templates/python/controller_template.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/python/dao_template.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/python/model_do_template.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/python/model_vo_template.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/python/service_template.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/sql/sql.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/vue/api.js.j2 (100%) rename backend/app/api/v1/module_generator/{ => gencode}/templates/vue/index.vue.j2 (100%) create mode 100644 frontend/src/api/system/ticket.ts create mode 100644 frontend/src/api/system/version.ts create mode 100644 frontend/src/views/system/ticket/index.vue create mode 100644 frontend/src/views/system/version/index.vue diff --git a/backend/app/api/v1/module_application/myapp/model.py b/backend/app/api/v1/module_application/myapp/model.py index 5724851e..e453e0f0 100644 --- a/backend/app/api/v1/module_application/myapp/model.py +++ b/backend/app/api/v1/module_application/myapp/model.py @@ -16,6 +16,9 @@ class ApplicationModel(CreatorMixin): # 基本信息(必备字段) name: Mapped[str] = mapped_column(String(64), nullable=False, comment='应用名称', unique=True) + + # 状态 + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") # 访问地址(核心字段) access_url: Mapped[str] = mapped_column(String(500), nullable=False, comment='访问地址') diff --git a/backend/app/api/v1/module_example/demo/model.py b/backend/app/api/v1/module_example/demo/model.py index 33302e1c..5c2d5eaf 100644 --- a/backend/app/api/v1/module_example/demo/model.py +++ b/backend/app/api/v1/module_example/demo/model.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from typing import Optional -from sqlalchemy import String +from sqlalchemy import Boolean, String from sqlalchemy.orm import Mapped, mapped_column from app.core.base_model import CreatorMixin @@ -16,3 +16,4 @@ class DemoModel(CreatorMixin): __table_args__ = ({'comment': '示例表'}) name: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, default='', comment='名称') + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") diff --git a/backend/app/api/v1/module_generator/__init__.py b/backend/app/api/v1/module_generator/__init__.py new file mode 100644 index 00000000..633f8661 --- /dev/null +++ b/backend/app/api/v1/module_generator/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- + diff --git a/backend/app/api/v1/module_generator/gencode/model.py b/backend/app/api/v1/module_generator/gencode/model.py index 2dbe8580..f11c0082 100644 --- a/backend/app/api/v1/module_generator/gencode/model.py +++ b/backend/app/api/v1/module_generator/gencode/model.py @@ -1,36 +1,18 @@ +# -*- coding: utf-8 -*- + from datetime import datetime -from sqlalchemy import Column, DateTime, ForeignKey, Integer, String from sqlalchemy.orm import relationship -from config.database import Base from sqlalchemy import Boolean, Column, ForeignKey, String, Integer, Text, DateTime -from app.core.base_model import BaseMixin -from sqlalchemy import Boolean, Column, ForeignKey, String, Integer, Text, DateTime -from sqlalchemy.orm import relationship - -from app.core.base_model import BaseMixin - -from sqlalchemy import Boolean, Column, ForeignKey, String, Integer, Text, DateTime - -from app.core.base_model import BaseMixin +from app.core.base_model import CreatorMixin -class PageModel(BaseMixin): - __tablename__ = "gen_page" - - page_name = Column(String(length=255), comment='页面名称') - - keywords = Column(String(length=500), comment='页面关键词') - - title = Column(String(length=500), comment='页面title标题') - - -class GenTable(Base): +class GenTable(CreatorMixin): """ - 代码生成业务表 + 代码生成表 """ - __tablename__ = 'gen_table' + __table_args__ = ({'comment': '代码生成表'}) table_id = Column(Integer, primary_key=True, autoincrement=True, comment='编号') table_name = Column(String(200), nullable=True, default='', comment='表名称') @@ -39,9 +21,7 @@ class GenTable(Base): sub_table_fk_name = Column(String(64), nullable=True, comment='子表关联的外键名') class_name = Column(String(100), nullable=True, default='', comment='实体类名称') tpl_category = Column(String(200), nullable=True, default='crud', comment='使用的模板(crud单表操作 tree树表操作)') - tpl_web_type = Column( - String(30), nullable=True, default='', comment='前端模板类型(element-ui模版 element-plus模版)' - ) + tpl_web_type = Column(String(30), nullable=True, default='', comment='前端模板类型(element-ui模版 element-plus模版)') package_name = Column(String(100), nullable=True, comment='生成包路径') module_name = Column(String(30), nullable=True, comment='生成模块名') business_name = Column(String(30), nullable=True, comment='生成业务名') @@ -59,7 +39,7 @@ class GenTable(Base): columns = relationship('GenTableColumn', order_by='GenTableColumn.sort', back_populates='tables') -class GenTableColumn(Base): +class GenTableColumn(CreatorMixin): """ 代码生成业务表字段 """ diff --git a/backend/app/api/v1/module_generator/templates/python/controller_template.j2 b/backend/app/api/v1/module_generator/gencode/templates/python/controller_template.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/python/controller_template.j2 rename to backend/app/api/v1/module_generator/gencode/templates/python/controller_template.j2 diff --git a/backend/app/api/v1/module_generator/templates/python/dao_template.j2 b/backend/app/api/v1/module_generator/gencode/templates/python/dao_template.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/python/dao_template.j2 rename to backend/app/api/v1/module_generator/gencode/templates/python/dao_template.j2 diff --git a/backend/app/api/v1/module_generator/templates/python/model_do_template.j2 b/backend/app/api/v1/module_generator/gencode/templates/python/model_do_template.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/python/model_do_template.j2 rename to backend/app/api/v1/module_generator/gencode/templates/python/model_do_template.j2 diff --git a/backend/app/api/v1/module_generator/templates/python/model_vo_template.j2 b/backend/app/api/v1/module_generator/gencode/templates/python/model_vo_template.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/python/model_vo_template.j2 rename to backend/app/api/v1/module_generator/gencode/templates/python/model_vo_template.j2 diff --git a/backend/app/api/v1/module_generator/templates/python/service_template.j2 b/backend/app/api/v1/module_generator/gencode/templates/python/service_template.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/python/service_template.j2 rename to backend/app/api/v1/module_generator/gencode/templates/python/service_template.j2 diff --git a/backend/app/api/v1/module_generator/templates/sql/sql.j2 b/backend/app/api/v1/module_generator/gencode/templates/sql/sql.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/sql/sql.j2 rename to backend/app/api/v1/module_generator/gencode/templates/sql/sql.j2 diff --git a/backend/app/api/v1/module_generator/templates/vue/api.js.j2 b/backend/app/api/v1/module_generator/gencode/templates/vue/api.js.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/vue/api.js.j2 rename to backend/app/api/v1/module_generator/gencode/templates/vue/api.js.j2 diff --git a/backend/app/api/v1/module_generator/templates/vue/index.vue.j2 b/backend/app/api/v1/module_generator/gencode/templates/vue/index.vue.j2 similarity index 100% rename from backend/app/api/v1/module_generator/templates/vue/index.vue.j2 rename to backend/app/api/v1/module_generator/gencode/templates/vue/index.vue.j2 diff --git a/backend/app/api/v1/module_monitor/job/model.py b/backend/app/api/v1/module_monitor/job/model.py index 558b2915..c7d0ec6c 100644 --- a/backend/app/api/v1/module_monitor/job/model.py +++ b/backend/app/api/v1/module_monitor/job/model.py @@ -26,7 +26,7 @@ class JobModel(CreatorMixin): max_instances: Mapped[int] = mapped_column(Integer, nullable=True, default=1, comment='最大实例数:允许的最大并发执行实例数 工作') start_date: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, comment='开始时间') end_date: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, comment='结束时间') - + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") job_logs: Mapped[Optional[list['JobLogModel']]] = relationship(back_populates="job", lazy="selectin") diff --git a/backend/app/api/v1/module_resource/__init__.py b/backend/app/api/v1/module_resource/__init__.py index fb9ef55e..5cfc9c7c 100644 --- a/backend/app/api/v1/module_resource/__init__.py +++ b/backend/app/api/v1/module_resource/__init__.py @@ -2,10 +2,10 @@ from fastapi import APIRouter -from .resource import ResourceRouter +from .resource.controller import ResourceFileRouter ResourceRouter = APIRouter(prefix="/resource") # 包含所有子路由 -ResourceRouter.include_router(ResourceRouter) \ No newline at end of file +ResourceRouter.include_router(ResourceFileRouter) \ No newline at end of file diff --git a/backend/app/api/v1/module_resource/resource/__init__.py b/backend/app/api/v1/module_resource/resource/__init__.py index f621c93f..40a96afc 100644 --- a/backend/app/api/v1/module_resource/resource/__init__.py +++ b/backend/app/api/v1/module_resource/resource/__init__.py @@ -1,5 +1 @@ # -*- coding: utf-8 -*- - -from .controller import ResourceRouter - -__all__ = ['ResourceRouter'] \ No newline at end of file diff --git a/backend/app/api/v1/module_resource/resource/controller.py b/backend/app/api/v1/module_resource/resource/controller.py index 5b858651..a1e77a6b 100644 --- a/backend/app/api/v1/module_resource/resource/controller.py +++ b/backend/app/api/v1/module_resource/resource/controller.py @@ -23,10 +23,10 @@ from .schema import ( from .service import ResourceService -ResourceRouter = APIRouter(route_class=OperationLogRoute, prefix="/resource", tags=["资源管理"]) +ResourceFileRouter = APIRouter(route_class=OperationLogRoute, prefix="/resource", tags=["资源管理"]) -@ResourceRouter.get("/list", summary="获取目录列表", description="获取指定目录下的文件和子目录列表") +@ResourceFileRouter.get("/list", summary="获取目录列表", description="获取指定目录下的文件和子目录列表") async def get_directory_list_controller( request: Request, path: Optional[str] = Query(None, description="目录路径"), @@ -44,7 +44,7 @@ async def get_directory_list_controller( return SuccessResponse(data=result_dict, msg="获取目录列表成功") -@ResourceRouter.post("/search", summary="搜索资源", description="根据条件搜索资源") +@ResourceFileRouter.post("/search", summary="搜索资源", description="根据条件搜索资源") async def search_resources_controller( request: Request, search: ResourceSearchSchema, @@ -60,7 +60,7 @@ async def search_resources_controller( return SuccessResponse(data=result_list, msg=f"搜索成功,找到 {len(result_list)} 个结果") -@ResourceRouter.post("/upload", summary="上传文件", description="上传文件到指定目录") +@ResourceFileRouter.post("/upload", summary="上传文件", description="上传文件到指定目录") async def upload_file_controller( file: UploadFile, request: Request, @@ -78,7 +78,7 @@ async def upload_file_controller( return SuccessResponse(data=result_dict, msg="上传文件成功") -@ResourceRouter.get("/download", summary="下载文件", description="下载指定文件") +@ResourceFileRouter.get("/download", summary="下载文件", description="下载指定文件") async def download_file_controller( request: Request, path: str = Query(..., description="文件路径"), @@ -103,7 +103,7 @@ async def download_file_controller( ) -@ResourceRouter.delete("/delete", summary="删除文件", description="删除指定文件或目录") +@ResourceFileRouter.delete("/delete", summary="删除文件", description="删除指定文件或目录") async def delete_files_controller( paths: List[str] = Body(..., description="文件路径列表"), auth: AuthSchema = Depends(AuthPermission(permissions=["resource:file:delete"])) @@ -114,7 +114,7 @@ async def delete_files_controller( return SuccessResponse(msg="删除文件成功") -@ResourceRouter.post("/move", summary="移动文件", description="移动文件或目录") +@ResourceFileRouter.post("/move", summary="移动文件", description="移动文件或目录") async def move_file_controller( data: ResourceMoveSchema, auth: AuthSchema = Depends(AuthPermission(permissions=["resource:file:move"])) @@ -125,7 +125,7 @@ async def move_file_controller( return SuccessResponse(msg="移动文件成功") -@ResourceRouter.post("/copy", summary="复制文件", description="复制文件或目录") +@ResourceFileRouter.post("/copy", summary="复制文件", description="复制文件或目录") async def copy_file_controller( data: ResourceCopySchema, auth: AuthSchema = Depends(AuthPermission(permissions=["resource:file:copy"])) @@ -136,7 +136,7 @@ async def copy_file_controller( return SuccessResponse(msg="复制文件成功") -@ResourceRouter.post("/rename", summary="重命名文件", description="重命名文件或目录") +@ResourceFileRouter.post("/rename", summary="重命名文件", description="重命名文件或目录") async def rename_file_controller( data: ResourceRenameSchema, auth: AuthSchema = Depends(AuthPermission(permissions=["resource:file:rename"])) @@ -147,7 +147,7 @@ async def rename_file_controller( return SuccessResponse(msg="重命名文件成功") -@ResourceRouter.post("/create-dir", summary="创建目录", description="在指定路径创建新目录") +@ResourceFileRouter.post("/create-dir", summary="创建目录", description="在指定路径创建新目录") async def create_directory_controller( data: ResourceCreateDirSchema, auth: AuthSchema = Depends(AuthPermission(permissions=["resource:file:create_dir"])) @@ -158,7 +158,7 @@ async def create_directory_controller( return SuccessResponse(msg="创建目录成功") -@ResourceRouter.get("/stats", summary="获取资源统计", description="获取资源统计信息") +@ResourceFileRouter.get("/stats", summary="获取资源统计", description="获取资源统计信息") async def get_resource_stats_controller( request: Request, auth: AuthSchema = Depends(AuthPermission(permissions=["resource:stats:query"])) @@ -172,7 +172,7 @@ async def get_resource_stats_controller( return SuccessResponse(data=result_dict, msg="获取资源统计成功") -@ResourceRouter.post("/export", summary="导出资源列表", description="导出资源列表") +@ResourceFileRouter.post("/export", summary="导出资源列表", description="导出资源列表") async def export_resource_list_controller( request: Request, search: ResourceSearchSchema, diff --git a/backend/app/api/v1/module_system/dept/model.py b/backend/app/api/v1/module_system/dept/model.py index a7e750b2..6a1390c9 100644 --- a/backend/app/api/v1/module_system/dept/model.py +++ b/backend/app/api/v1/module_system/dept/model.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from typing import Optional, List -from sqlalchemy import String, Integer, ForeignKey +from sqlalchemy import Boolean, String, Integer, ForeignKey from sqlalchemy.orm import relationship, Mapped, mapped_column from app.core.base_model import ModelMixin @@ -17,6 +17,7 @@ class DeptModel(ModelMixin): name: Mapped[str] = mapped_column(String(40),nullable=False,unique=True,comment="部门名称") order: Mapped[int] = mapped_column(Integer,nullable=False,default=999,comment="显示排序") code: Mapped[Optional[str]] = mapped_column(String(20),nullable=True,unique=True,comment="部门编码") + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("system_dept.id", ondelete="SET NULL", onupdate="CASCADE"), default=None, index=True, comment="父级部门ID") parent: Mapped[Optional['DeptModel']] = relationship(back_populates='children', remote_side=[id],uselist=False) diff --git a/backend/app/api/v1/module_system/dict/model.py b/backend/app/api/v1/module_system/dict/model.py index 82e1174b..11639ea3 100644 --- a/backend/app/api/v1/module_system/dict/model.py +++ b/backend/app/api/v1/module_system/dict/model.py @@ -17,6 +17,7 @@ class DictTypeModel(CreatorMixin): dict_name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True, comment='字典名称') dict_type: Mapped[str] = mapped_column(String(100), nullable=False, unique=True, comment='字典类型') + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") dict_datas: Mapped[List["DictDataModel"]] = relationship(back_populates="dict_type_rel", lazy="selectin") @@ -32,6 +33,7 @@ class DictDataModel(CreatorMixin): dict_label: Mapped[str] = mapped_column(String(100), nullable=False, comment='字典标签') dict_value: Mapped[str] = mapped_column(String(100), nullable=False, comment='字典键值') dict_type: Mapped[str] = mapped_column(String(100), nullable=False, comment='字典类型') + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") css_class: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment='样式属性(其他样式扩展)') list_class: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment='表格回显样式') is_default: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, comment='是否默认(True是 False否)') diff --git a/backend/app/api/v1/module_system/menu/model.py b/backend/app/api/v1/module_system/menu/model.py index 0347316e..a7b1f30c 100644 --- a/backend/app/api/v1/module_system/menu/model.py +++ b/backend/app/api/v1/module_system/menu/model.py @@ -28,6 +28,7 @@ class MenuModel(ModelMixin): name: Mapped[str] = mapped_column(String(50), nullable=False, comment='菜单名称', unique=True) type: Mapped[int] = mapped_column(Integer, nullable=False, default=2, comment='菜单类型(1:目录 2:菜单 3:按钮/权限 4:链接)') order: Mapped[int] = mapped_column(Integer, nullable=False, default=999, comment='显示排序') + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") permission: Mapped[Optional[str]] = mapped_column(String(100), comment='权限标识(如:system:user:list)') icon: Mapped[Optional[str]] = mapped_column(String(50), comment='菜单图标') route_name: Mapped[Optional[str]] = mapped_column(String(100), comment='路由名称') diff --git a/backend/app/api/v1/module_system/notice/model.py b/backend/app/api/v1/module_system/notice/model.py index 3d641eb1..3f2bba0d 100644 --- a/backend/app/api/v1/module_system/notice/model.py +++ b/backend/app/api/v1/module_system/notice/model.py @@ -6,7 +6,7 @@ from typing import Optional -from sqlalchemy import String, Text +from sqlalchemy import Boolean, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.base_model import CreatorMixin @@ -26,3 +26,4 @@ class NoticeModel(CreatorMixin): notice_title: Mapped[str] = mapped_column(String(50), nullable=False, comment='公告标题') notice_type: Mapped[str] = mapped_column(String(50), nullable=False, comment='公告类型(1通知 2公告)') notice_content: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment='公告内容') + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") diff --git a/backend/app/api/v1/module_system/params/model.py b/backend/app/api/v1/module_system/params/model.py index c432e5a7..2007768d 100644 --- a/backend/app/api/v1/module_system/params/model.py +++ b/backend/app/api/v1/module_system/params/model.py @@ -19,5 +19,6 @@ class ParamsModel(CreatorMixin): config_key: Mapped[str] = mapped_column(String(500), nullable=False, unique=True, comment='参数键名') config_value: Mapped[Optional[str]] = mapped_column(String(500), comment='参数键值') config_type: Mapped[bool] = mapped_column(Boolean, default=False, nullable=True, comment="系统内置(True:是 False:否)") + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") diff --git a/backend/app/api/v1/module_system/position/model.py b/backend/app/api/v1/module_system/position/model.py index 094f455b..4e26a3d1 100644 --- a/backend/app/api/v1/module_system/position/model.py +++ b/backend/app/api/v1/module_system/position/model.py @@ -6,7 +6,7 @@ from typing import List -from sqlalchemy import String, Integer +from sqlalchemy import Boolean, String, Integer from sqlalchemy.orm import relationship, Mapped, mapped_column from app.core.base_model import CreatorMixin @@ -21,6 +21,7 @@ class PositionModel(CreatorMixin): name: Mapped[str] = mapped_column(String(40), nullable=False, unique=True, comment="岗位名称") order: Mapped[int] = mapped_column(Integer, nullable=False, default=1, comment="显示排序") + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") # 用户关联关系 users: Mapped[List["UserModel"]] = relationship(secondary="system_user_positions", back_populates="positions", lazy="selectin") diff --git a/backend/app/api/v1/module_system/role/model.py b/backend/app/api/v1/module_system/role/model.py index dcf36b8e..fd847468 100644 --- a/backend/app/api/v1/module_system/role/model.py +++ b/backend/app/api/v1/module_system/role/model.py @@ -6,7 +6,7 @@ from typing import Optional, List -from sqlalchemy import String, Integer, ForeignKey +from sqlalchemy import Boolean, String, Integer, ForeignKey from sqlalchemy.orm import relationship, Mapped, mapped_column from app.core.base_model import MappedBase, CreatorMixin @@ -75,6 +75,7 @@ class RoleModel(CreatorMixin): name: Mapped[str] = mapped_column(String(40), nullable=False, unique=True, comment="角色名称") code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, unique=True, comment="角色编码") order: Mapped[int] = mapped_column(Integer, nullable=False, default=999, comment="显示排序") + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") data_scope: Mapped[int] = mapped_column(Integer, nullable=False, default=1, comment="数据权限范围") menus: Mapped[List["MenuModel"]] = relationship(secondary="system_role_menus", back_populates="roles", lazy="selectin") diff --git a/backend/app/api/v1/module_system/ticket/controller.py b/backend/app/api/v1/module_system/ticket/controller.py index ad8b9b38..7c36f4db 100644 --- a/backend/app/api/v1/module_system/ticket/controller.py +++ b/backend/app/api/v1/module_system/ticket/controller.py @@ -15,7 +15,7 @@ from .service import TicketService from .schema import TicketCreateSchema, TicketUpdateSchema -TicketRouter = APIRouter(route_class=OperationLogRoute, prefix="/tickets", tags=["工单管理"]) +TicketRouter = APIRouter(route_class=OperationLogRoute, prefix="/ticket", tags=["工单管理"]) @TicketRouter.get("/detail/{id}", summary="获取工单详情", description="获取工单详情") diff --git a/backend/app/api/v1/module_system/ticket/model.py b/backend/app/api/v1/module_system/ticket/model.py index 8f21c46d..669723f0 100644 --- a/backend/app/api/v1/module_system/ticket/model.py +++ b/backend/app/api/v1/module_system/ticket/model.py @@ -17,12 +17,12 @@ class TicketModel(CreatorMixin): __table_args__ = ({'comment': '工单表'}) title: Mapped[str] = mapped_column(String(255), nullable=False, comment='工单标题') - ticket_status: Mapped[str] = mapped_column(String(50), default='1', comment='工单状态(1:待处理 2:处理中 3:已解决 4:已关闭)') - priority: Mapped[str] = mapped_column(String(50), default='medium', comment='优先级(low, medium, high, urgent)') - type: Mapped[Optional[str]] = mapped_column(String(50), comment='工单类型(bug, feature, task)') + status: Mapped[str] = mapped_column(String(50), default='pending', comment='工单状态(pending:待处理 progress:处理中 resolved:已解决 closed:已关闭)') + priority: Mapped[str] = mapped_column(String(50), default='medium', comment='优先级(low:低, medium:中, high:高, urgent:紧急)') + type: Mapped[Optional[str]] = mapped_column(String(50), comment='工单类型(bug:缺陷, feature:功能, task:任务)') assignee_id: Mapped[Optional[int]] = mapped_column(ForeignKey('system_users.id'), comment='指派给用户ID') reporter_id: Mapped[Optional[int]] = mapped_column(ForeignKey('system_users.id'), comment='报告人ID') - project: Mapped[Optional[str]] = mapped_column(String(100), comment='所属项目') + project: Mapped[Optional[str]] = mapped_column(String(100), comment='所属项目或模块') version: Mapped[Optional[str]] = mapped_column(String(50), comment='版本号') # 关系 diff --git a/backend/app/api/v1/module_system/ticket/param.py b/backend/app/api/v1/module_system/ticket/param.py index a55da2fb..bd6d582e 100644 --- a/backend/app/api/v1/module_system/ticket/param.py +++ b/backend/app/api/v1/module_system/ticket/param.py @@ -13,8 +13,7 @@ class TicketQueryParams: def __init__( self, title: Optional[str] = Query(None, description="工单标题"), - status: Optional[bool] = Query(None, description="状态"), - ticket_status: Optional[str] = Query(None, description="工单状态"), + status: Optional[bool] = Query(None, description="工单状态"), priority: Optional[str] = Query(None, description="优先级"), creator: Optional[int] = Query(None, description="创建人"), start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2023-01-01 00:00:00"), @@ -28,7 +27,6 @@ class TicketQueryParams: # 精确查询字段 self.creator_id = creator self.status = status - self.ticket_status = ticket_status # 使用 ticket_status 而不是 status self.priority = priority # 时间范围查询 diff --git a/backend/app/api/v1/module_system/ticket/schema.py b/backend/app/api/v1/module_system/ticket/schema.py index 8549ce51..bc65256a 100644 --- a/backend/app/api/v1/module_system/ticket/schema.py +++ b/backend/app/api/v1/module_system/ticket/schema.py @@ -11,8 +11,7 @@ class TicketCreateSchema(BaseModel): """创建工单""" title: str = Field(..., max_length=255, description='工单标题') description: Optional[str] = Field(default=None, description='工单描述') - status: Optional[bool] = Field(default=True, description='1、启动 2、停止') - ticket_status: Optional[str] = Field(default='1', description='工单处理状态(1:待处理 2:处理中 3:已解决 4:已关闭)') + status: Optional[str] = Field(default='pending', description='工单处理状态(pending:待处理 progress:处理中 resolved:已解决 closed:已关闭)') priority: Optional[str] = Field(default='medium', description='优先级(low, medium, high, urgent)') type: Optional[str] = Field(default='bug', description='工单类型(bug, feature, task)') assignee_id: Optional[int] = Field(default=None, description='指派给用户ID') diff --git a/backend/app/api/v1/module_system/user/model.py b/backend/app/api/v1/module_system/user/model.py index 6381545e..65448283 100644 --- a/backend/app/api/v1/module_system/user/model.py +++ b/backend/app/api/v1/module_system/user/model.py @@ -72,6 +72,7 @@ class UserModel(CreatorMixin): username: Mapped[str] = mapped_column(String(32),nullable=False,unique=True,comment="用户名/登录账号") password: Mapped[str] = mapped_column(String(255),nullable=False,comment="密码哈希") name: Mapped[str] = mapped_column(String(32),nullable=False,comment="昵称") + status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") mobile: Mapped[Optional[str]] = mapped_column(String(20),nullable=True,unique=True,comment="手机号") email: Mapped[Optional[str]] = mapped_column(String(64),nullable=True,unique=True,comment="邮箱") gender: Mapped[Optional[str]] = mapped_column(String(1), default='0',nullable=True,comment="性别(0:男 1:女 2:未知)") diff --git a/backend/app/api/v1/module_system/version/controller.py b/backend/app/api/v1/module_system/version/controller.py index e2b312da..738f20c7 100644 --- a/backend/app/api/v1/module_system/version/controller.py +++ b/backend/app/api/v1/module_system/version/controller.py @@ -15,7 +15,7 @@ from .service import VersionService from .schema import VersionCreateSchema, VersionUpdateSchema -VersionRouter = APIRouter(route_class=OperationLogRoute, prefix="/versions", tags=["版本管理"]) +VersionRouter = APIRouter(route_class=OperationLogRoute, prefix="/version", tags=["版本管理"]) @VersionRouter.get("/detail/{id}", summary="获取版本详情", description="获取版本详情") diff --git a/backend/app/api/v1/module_system/version/crud.py b/backend/app/api/v1/module_system/version/crud.py index 8ef7abc9..fcc479b1 100644 --- a/backend/app/api/v1/module_system/version/crud.py +++ b/backend/app/api/v1/module_system/version/crud.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from typing import Dict, List, Optional, Sequence +from datetime import datetime from app.core.base_crud import CRUDBase from app.api.v1.module_system.auth.schema import AuthSchema @@ -39,7 +40,16 @@ class VersionCRUD(CRUDBase[VersionModel, VersionCreateSchema, VersionUpdateSchem :param data: 版本创建数据 :return: 创建的版本 """ - return await self.create(data=data) + # 处理 released_at 字段,确保字符串转换为 datetime 对象 + data_dict = data.model_dump() + if data_dict.get('released_at') and isinstance(data_dict['released_at'], str): + try: + data_dict['released_at'] = datetime.strptime(data_dict['released_at'], '%Y-%m-%d %H:%M:%S') + except ValueError: + # 如果格式不正确,让数据库层处理错误 + pass + + return await self.create(data=data_dict) async def update_crud(self, id: int, data: VersionUpdateSchema) -> Optional[VersionModel]: """更新版本 @@ -48,7 +58,16 @@ class VersionCRUD(CRUDBase[VersionModel, VersionCreateSchema, VersionUpdateSchem :param data: 版本更新数据 :return: 更新的版本 """ - return await self.update(id=id, data=data) + # 处理 released_at 字段,确保字符串转换为 datetime 对象 + data_dict = data.model_dump(exclude_unset=True, exclude={"id"}) + if data_dict.get('released_at') and isinstance(data_dict['released_at'], str): + try: + data_dict['released_at'] = datetime.strptime(data_dict['released_at'], '%Y-%m-%d %H:%M:%S') + except ValueError: + # 如果格式不正确,让数据库层处理错误 + pass + + return await self.update(id=id, data=data_dict) async def delete_crud(self, ids: List[int]) -> None: """批量删除版本 @@ -65,15 +84,13 @@ class VersionCRUD(CRUDBase[VersionModel, VersionCreateSchema, VersionUpdateSchem """ return await self.get(version_number=version_number) - async def get_by_status_crud(self, status: str, search: Optional[Dict] = None, order_by: Optional[List[Dict[str, str]]] = None) -> Sequence[VersionModel]: + async def get_by_status_crud(self, search: Optional[Dict] = None, order_by: Optional[List[Dict[str, str]]] = None) -> Sequence[VersionModel]: """根据状态获取版本列表 - :param status: 版本状态 :param search: 搜索条件 :param order_by: 排序字段 :return: 版本列表 """ if search is None: search = {} - search['version_status'] = status return await self.list(search=search, order_by=order_by or []) \ No newline at end of file diff --git a/backend/app/api/v1/module_system/version/model.py b/backend/app/api/v1/module_system/version/model.py index 2ea85f0c..4dae1d1d 100644 --- a/backend/app/api/v1/module_system/version/model.py +++ b/backend/app/api/v1/module_system/version/model.py @@ -19,6 +19,6 @@ class VersionModel(CreatorMixin): version_number: Mapped[str] = mapped_column(String(50), nullable=False, comment='版本号') title: Mapped[str] = mapped_column(String(255), nullable=False, comment='版本标题') release_notes: Mapped[Optional[str]] = mapped_column(Text, comment='发布说明') - version_status: Mapped[str] = mapped_column(String(50), default='draft', comment='版本状态(draft, released, archived)') + status: Mapped[str] = mapped_column(String(50), default='draft', comment='版本状态(draft: 草稿, released: 已发布, archived: 已归档)') project: Mapped[Optional[str]] = mapped_column(String(100), comment='所属项目') released_at: Mapped[Optional[datetime]] = mapped_column(DateTime, comment='发布时间') \ No newline at end of file diff --git a/backend/app/api/v1/module_system/version/param.py b/backend/app/api/v1/module_system/version/param.py index 6597f76c..759a330c 100644 --- a/backend/app/api/v1/module_system/version/param.py +++ b/backend/app/api/v1/module_system/version/param.py @@ -13,8 +13,7 @@ class VersionQueryParams: def __init__( self, title: Optional[str] = Query(None, description="版本标题"), - status: Optional[bool] = Query(None, description="状态"), - version_status: Optional[str] = Query(None, description="版本状态"), + status: Optional[str] = Query(None, description="版本状态"), creator: Optional[int] = Query(None, description="创建人"), start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2023-01-01 00:00:00"), end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2023-12-31 23:59:59"), @@ -26,9 +25,7 @@ class VersionQueryParams: # 精确查询字段 self.creator_id = creator - self.status = status - self.version_status = version_status # 使用 version_status 而不是 status # 时间范围查询 if start_time and end_time: diff --git a/backend/app/api/v1/module_system/version/schema.py b/backend/app/api/v1/module_system/version/schema.py index 7932ebb2..9eea0d2b 100644 --- a/backend/app/api/v1/module_system/version/schema.py +++ b/backend/app/api/v1/module_system/version/schema.py @@ -5,6 +5,7 @@ from pydantic import BaseModel, ConfigDict, Field from datetime import datetime from app.core.base_schema import BaseSchema +from app.core.validator import DateTimeStr class VersionCreateSchema(BaseModel): @@ -13,10 +14,9 @@ class VersionCreateSchema(BaseModel): title: str = Field(..., max_length=255, description='版本标题') release_notes: Optional[str] = Field(default=None, description='发布说明') description: Optional[str] = Field(default=None, description='工单描述') - status: Optional[bool] = Field(default=True, description='1、启动 2、停止') - version_status: Optional[str] = Field(default='draft', description='版本状态(draft, released, archived)') + status: Optional[str] = Field(default='draft', description='版本状态(draft: 草稿, released: 已发布, archived: 已归档)') project: Optional[str] = Field(default=None, max_length=100, description='所属项目') - released_at: Optional[datetime] = Field(default=None, description='发布时间') + released_at: Optional[DateTimeStr] = Field(default=None, description='发布时间') class VersionUpdateSchema(VersionCreateSchema): diff --git a/backend/app/api/v1/module_system/version/service.py b/backend/app/api/v1/module_system/version/service.py index 467c8ee9..aa4f5675 100644 --- a/backend/app/api/v1/module_system/version/service.py +++ b/backend/app/api/v1/module_system/version/service.py @@ -70,7 +70,7 @@ class VersionService: await VersionCRUD(auth).delete_crud(ids=ids) @classmethod - async def get_version_by_status_service(cls, auth: AuthSchema, status: str, search: Optional[VersionQueryParams] = None, order_by: Optional[Union[str, List[Dict[str, str]]]] = None) -> List[Dict]: + async def get_version_by_status_service(cls, auth: AuthSchema, search: Optional[VersionQueryParams] = None, order_by: Optional[Union[str, List[Dict[str, str]]]] = None) -> List[Dict]: """根据状态获取版本列表""" # 处理排序参数 processed_order_by = None @@ -81,7 +81,6 @@ class VersionService: processed_order_by = order_by obj_list = await VersionCRUD(auth).get_by_status_crud( - status=status, search=search.__dict__ if search else None, order_by=processed_order_by ) diff --git a/backend/app/core/base_model.py b/backend/app/core/base_model.py index 860256f0..5081eb5d 100644 --- a/backend/app/core/base_model.py +++ b/backend/app/core/base_model.py @@ -41,7 +41,6 @@ class ModelMixin(MappedBase): __abstract__ = True id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment='主键ID') - status: Mapped[bool] = mapped_column(Boolean(), default=True, nullable=False, comment="是否启用(True:启用 False:禁用)") description: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="备注说明") created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, comment='创建时间') updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间') diff --git a/backend/app/core/validator.py b/backend/app/core/validator.py index 2489ab2b..8cd393be 100644 --- a/backend/app/core/validator.py +++ b/backend/app/core/validator.py @@ -13,7 +13,7 @@ from app.core.exceptions import CustomException DateTimeStr = Annotated[ datetime, AfterValidator(lambda x: datetime_validator(x)), - PlainSerializer(lambda x: x, return_type=str), + PlainSerializer(lambda x: x.strftime('%Y-%m-%d %H:%M:%S') if isinstance(x, datetime) else x, return_type=str), WithJsonSchema({'type': 'string'}, mode='serialization') ] @@ -70,7 +70,7 @@ def email_validator(value: str) -> str: return value -def mobile_validator(value: Optional[str]) -> str: +def mobile_validator(value: Optional[str]) -> Optional[str]: """ 手机号验证器 @@ -137,4 +137,4 @@ def role_permission_request_validator(data): if not data.role_ids: raise CustomException(code=RET.BAD_REQUEST.code, msg="角色不能为空") - return data + return data \ No newline at end of file diff --git a/backend/app/scripts/data/system_menu.json b/backend/app/scripts/data/system_menu.json index f2539e75..26e3d6fc 100644 --- a/backend/app/scripts/data/system_menu.json +++ b/backend/app/scripts/data/system_menu.json @@ -1177,6 +1177,162 @@ "description": "初始化数据" } ] + }, + { + "name": "版本管理", + "type": 2, + "icon": "el-icon-Guide", + "order": 10, + "permission": "system:version:query", + "route_name": "Version", + "route_path": "/system/version", + "component_path": "system/version/index", + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "版本管理", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据", + "children": [ + { + "name": "创建版本", + "type": 3, + "icon": null, + "order": 1, + "permission": "system:version:create", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "创建版本", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + }, + { + "name": "修改版本", + "type": 3, + "icon": null, + "order": 2, + "permission": "system:version:update", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "修改版本", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + }, + { + "name": "删除版本", + "type": 3, + "icon": null, + "order": 3, + "permission": "system:version:delete", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "删除版本", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + } + ] + }, + { + "name": "工单管理", + "type": 2, + "icon": "el-icon-Help", + "order": 11, + "permission": "system:ticket:query", + "route_name": "Ticket", + "route_path": "/system/ticket", + "component_path": "system/ticket/index", + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "工单管理", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据", + "children": [ + { + "name": "创建工单", + "type": 3, + "icon": null, + "order": 1, + "permission": "system:ticket:create", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "创建工单", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + }, + { + "name": "修改工单", + "type": 3, + "icon": null, + "order": 2, + "permission": "system:ticket:update", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "修改工单", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + }, + { + "name": "删除工单", + "type": 3, + "icon": null, + "order": 3, + "permission": "system:ticket:delete", + "route_name": null, + "route_path": null, + "component_path": null, + "status": true, + "keep_alive": true, + "hidden": false, + "always_show": false, + "title": "删除工单", + "params": null, + "affix": false, + "redirect": null, + "description": "初始化数据" + } + ] } ] }, @@ -1634,7 +1790,7 @@ { "name": "应用管理", "type": 1, - "icon": "captcha", + "icon": "el-icon-ShoppingBag", "order": 6, "permission": null, "route_name": "Application", @@ -1653,7 +1809,7 @@ { "name": "我的应用", "type": 2, - "icon": "el-icon-DataLine", + "icon": "el-icon-ShoppingCartFull", "order": 1, "permission": "application:myapp:query", "route_name": "ApplicationSystem", @@ -1752,7 +1908,7 @@ { "name": "存储管理", "type": 1, - "icon": "document", + "icon": "el-icon-Coin", "order": 7, "permission": null, "route_name": "Resource", @@ -1963,7 +2119,7 @@ { "name": "存储监控", "type": 2, - "icon": "el-icon-Files", + "icon": "el-icon-PieChart", "order": 2, "permission": "resource:stats:query", "route_name": "Stats", @@ -1984,7 +2140,7 @@ { "name": "AI大模型", "type": 1, - "icon": "el-icon-DataLine", + "icon": "el-icon-Pointer", "order": 8, "permission": null, "route_name": "AI", @@ -2003,7 +2159,7 @@ { "name": "MCP应用", "type": 2, - "icon": "el-icon-DataLine", + "icon": "el-icon-ToiletPaper", "order": 1, "permission": "ai:mcp:chat", "route_name": "MCP", @@ -2045,7 +2201,7 @@ { "name": "代码管理", "type": 1, - "icon": "el-icon-DataLine", + "icon": "code", "order": 9, "permission": null, "route_name": "Gencode", @@ -2064,7 +2220,7 @@ { "name": "代码生成", "type": 2, - "icon": "el-icon-DataLine", + "icon": "code", "order": 1, "permission": "gencode:backcode:query", "route_name": "Backcode", @@ -2083,7 +2239,7 @@ { "name": "前端构建", "type": 2, - "icon": "el-icon-DataLine", + "icon": "el-icon-Wallet", "order": 2, "permission": "gencode:webcode:query", "route_name": "webcode", diff --git a/frontend/src/api/system/ticket.ts b/frontend/src/api/system/ticket.ts new file mode 100644 index 00000000..4a379aff --- /dev/null +++ b/frontend/src/api/system/ticket.ts @@ -0,0 +1,83 @@ +import request from "@/utils/request"; + +const TicketAPI = { + getTicketList(query: TicketPageQuery) { + return request>>({ + url: `/system/ticket/list`, + method: "get", + params: query, + }); + }, + + getTicketDetail(query: number) { + return request>({ + url: `/system/ticket/detail/${query}`, + method: "get", + }); + }, + + createTicket(body: TicketForm) { + return request({ + url: `/system/ticket/create`, + method: "post", + data: body, + }); + }, + + updateTicket(id: number, body: TicketForm) { + return request({ + url: `/system/ticket/update/${id}`, + method: "put", + data: body, + }); + }, + + deleteTicket(body: number[]) { + return request({ + url: `/system/ticket/delete`, + method: "delete", + data: body, + }); + }, + +}; + +export default TicketAPI; + +export interface TicketPageQuery extends PageQuery { + title?: string; + status?: string; + priority?: string; + start_time?: string; + end_time?: string; +} + +export interface TicketTable { + index?: number; + id?: number; + title?: string; + priority?: string; + type?: string; + status?: string; + description?: string; + assignee?: creatorType; + reporter?: creatorType; + project?: string; + version?: string; + created_at?: string; + updated_at?: string; + creator?: creatorType; +} + +export interface TicketForm { + id?: number; + title: string; + priority?: string; + type?: string; + status?: string; + description?: string; + assignee_id?: number; + reporter_id: number; + project?: string; + version?: string; +} \ No newline at end of file diff --git a/frontend/src/api/system/version.ts b/frontend/src/api/system/version.ts new file mode 100644 index 00000000..c7f05b2b --- /dev/null +++ b/frontend/src/api/system/version.ts @@ -0,0 +1,78 @@ +import request from "@/utils/request"; + +const VersionAPI = { + getVersionList(query: VersionPageQuery) { + return request>>({ + url: `/system/version/list`, + method: "get", + params: query, + }); + }, + + getVersionDetail(query: number) { + return request>({ + url: `/system/version/detail/${query}`, + method: "get", + }); + }, + + createVersion(body: VersionForm) { + return request({ + url: `/system/version/create`, + method: "post", + data: body, + }); + }, + + updateVersion(id: number, body: VersionForm) { + return request({ + url: `/system/version/update/${id}`, + method: "put", + data: body, + }); + }, + + deleteVersion(body: number[]) { + return request({ + url: `/system/version/delete`, + method: "delete", + data: body, + }); + }, + +}; + +export default VersionAPI; + +export interface VersionPageQuery extends PageQuery { + title?: string; + status?: string; + start_time?: string; + end_time?: string; +} + +export interface VersionTable { + index?: number; + id?: number; + version_number?: string; + title?: string; + release_notes?: string; + project?: string; + status?: string; + released_at?: string; + description?: string; + created_at?: string; + updated_at?: string; + creator?: creatorType; +} + +export interface VersionForm { + id?: number; + version_number: string; + title: string; + release_notes?: string; + project?: string; + status?: string; + released_at?: string; + description?: string; +} diff --git a/frontend/src/views/system/ticket/index.vue b/frontend/src/views/system/ticket/index.vue new file mode 100644 index 00000000..985449ef --- /dev/null +++ b/frontend/src/views/system/ticket/index.vue @@ -0,0 +1,575 @@ + + + + + + diff --git a/frontend/src/views/system/version/index.vue b/frontend/src/views/system/version/index.vue new file mode 100644 index 00000000..a7f6a038 --- /dev/null +++ b/frontend/src/views/system/version/index.vue @@ -0,0 +1,480 @@ + + + + + +