# 完整代码清单 本章汇总 Position 岗位模块涉及的全部文件,便于开发时快速查阅和复制。 ## 后端文件清单 ### 1. 数据模型 `src/modules/system/position/models.py` ```python from sqlalchemy import Column, String, Integer, text from core.base_db import base_db from core.base_model import base_model from core.config import DB_PREFIX # ============================================================ # 岗位模型 # ============================================================ class Position(base_model, base_db): """岗位模型类""" # ============================================================ # 表名配置 # ============================================================ __tablename__ = DB_PREFIX + "position" __table_comment__ = "岗位表" # ============================================================ # 字段定义 # ============================================================ # 岗位名称 name = Column(String(255), nullable=False, index=True, comment="岗位名称") # 岗位状态:1-在用 2-停用 status = Column(Integer, default=0, server_default=text('0'), index=True, comment="岗位状态:1-在用 2-停用") # 岗位排序 sort = Column(Integer, default=0, server_default=text('0'), comment="岗位排序") # ============================================================ # 内置方法 # ============================================================ def __repr__(self): """返回岗位名称作为字符串表示""" return '岗位:{}'.format(self.name) ``` ### 2. 表单验证 `src/modules/system/position/schemas.py` ```python # +====================================================================== # | 模块: 岗位表单验证 # | 说明: 岗位创建/编辑/状态更新的请求数据校验 # +====================================================================== from typing import Optional from pydantic import BaseModel, Field from core.base_schemas import BaseForm # ============================================================ # 岗位表单类 # ============================================================ class PositionForm(BaseForm): """岗位创建/编辑表单""" name: str = Field(..., min_length=1, max_length=150, description="岗位名称") status: int = Field(..., ge=1, le=2, description="岗位状态:1-在用 2-停用") sort: int = Field(..., ge=0, le=99999, description="岗位排序") # ============================================================ # 设置状态表单类 # ============================================================ class PositionStatusForm(BaseModel): """岗位状态更新表单""" id: int = Field(..., gt=0, description="岗位ID") status: int = Field(..., ge=1, le=2, description="岗位状态:1-在用 2-停用") ``` ### 3. 数据访问层 `src/modules/system/position/repository.py` ```python # +====================================================================== # | 模块: 岗位数据访问层 # | 说明: 封装岗位模型的数据访问操作 # +====================================================================== from modules.system.position.models import Position from core.base_repository import BaseRepository # ============================================================ # 岗位仓库类 # ============================================================ class PositionRepository(BaseRepository[Position]): """岗位数据仓库,继承基础仓库获得通用 CRUD 能力""" pass # ============================================================ # 仓库实例 # ============================================================ position_repo = PositionRepository(Position) ``` ### 4. 业务逻辑层 `src/modules/system/position/service.py` ```python # +====================================================================== # | 模块: 岗位业务逻辑层 # | 说明: 岗位的增删改查、唯一性校验、状态管理等业务处理 # +====================================================================== from typing import Optional from core.base_service import BaseService from modules.system.position.models import Position from modules.system.position.repository import position_repo from modules.system.user.models import User from modules.system.user.repository import user_repo from utils.request import parse_id_list # ============================================================ # 岗位业务服务类 # ============================================================ class PositionService(BaseService[Position]): """岗位业务服务类,继承基础服务获得通用 CRUD 能力""" # 数据访问与模型 repo = position_repo model = Position # 分页差异点 page_like_fields = ('name',) page_eq_fields = ('status',) page_order_by = (('sort', 'asc'),) # 唯一性校验 unique_fields = {'name': '岗位名称不能重复'} # ============================================================ # 删除前校验 # ============================================================ def _before_delete(self, ids) -> Optional[str]: """删除前校验:存在用户引用该岗位时禁止删除,避免用户岗位悬空""" id_list = parse_id_list(str(ids)) if id_list and user_repo.filter(User.position_id.in_(id_list), User.is_delete == 0).first(): return "存在用户引用该岗位,请先调整用户岗位" return None # ============================================================ # 获取岗位数据列表 # ============================================================ def get_position_list(self, request): """获取岗位数据列表""" # 与 /page 一致的筛选条件:name 模糊、status 精确;保留软删过滤与排序 query = self._apply_page_filters(self.repo.filter_by(), request) query = query.order_by(self.model.sort.asc()) # 返回结果 return [v.to_dict() for v in query.all()] # ============================================================ # 模块级单例 # ============================================================ position_service = PositionService() ``` ### 5. API 端点 `src/api/v1/endpoints/position.py` ```python # +====================================================================== # | 模块: 岗位路由层 # | 说明: 提供岗位信息的增删改查、状态管理、列表获取等 API 接口 # +====================================================================== from fastapi import APIRouter, Request from modules.system.position.schemas import PositionForm, PositionStatusForm from core.access_decorators import check_demo from core.access_decorators import permission_required from modules.system.position.service import position_service from core import R # ============================================================ # 创建路由实例 # ============================================================ router = APIRouter() # ============================================================ # 查询分页数据 # ============================================================ @router.get('/page', summary='查询分页数据') @permission_required("sys:position:page") def page(request: Request): """ 获取岗位分页列表 :param request: FastAPI请求对象 :return: 分页数据响应 """ return position_service.get_page(request) # ============================================================ # 查询岗位详情 # ============================================================ @router.get('/detail/{id}', summary='查询岗位详情') @permission_required("sys:position:detail") def detail(request: Request, id): """ 根据岗位ID查询详细信息 :param request: FastAPI请求对象 :param id: 岗位ID(路径参数) :return: 岗位详情数据 """ return R.ok(data=position_service.get_detail(id)) # ============================================================ # 获取岗位列表 # ============================================================ @router.get('/list', summary='获取岗位列表') @permission_required("sys:position:list") def get_position_list(request: Request): """ 获取所有岗位列表(无分页,用于下拉选择) :param request: FastAPI请求对象 :return: 岗位列表数据 """ return R.ok(data=position_service.get_position_list(request)) # ============================================================ # 添加岗位 # ============================================================ @router.post('/add', summary='添加岗位') @permission_required("sys:position:add") @check_demo def add(request: Request, data: PositionForm): """ 新增岗位 :param request: FastAPI请求对象 :param data: 岗位表单数据 :return: 添加结果响应 """ return position_service.add(request, data) # ============================================================ # 更新岗位 # ============================================================ @router.put('/update', summary='更新岗位') @permission_required("sys:position:update") @check_demo def update(request: Request, data: PositionForm): """ 更新岗位信息 :param request: FastAPI请求对象 :param data: 岗位表单数据(必须包含 id 字段) :return: 更新结果响应 """ return position_service.update(request, data) # ============================================================ # 删除岗位 # ============================================================ @router.delete('/delete/{id}', summary='删除岗位') @permission_required("sys:position:delete") @check_demo def delete(request: Request, id): """ 根据ID删除单个岗位 :param request: FastAPI请求对象 :param id: 岗位ID(路径参数) :return: 删除结果响应 """ return position_service.delete(id) # ============================================================ # 设置岗位状态 # ============================================================ @router.put('/status', summary='设置岗位状态') @permission_required("sys:position:status") @check_demo def status(request: Request, data: PositionStatusForm): """ 修改岗位状态(启用/禁用) :param request: FastAPI请求对象 :param data: 状态表单数据 :return: 状态更新结果响应 """ return position_service.update_status(request, data) # ============================================================ # 批量删除岗位 # ============================================================ @router.delete('/batchDelete', summary='批量删除岗位') @permission_required("sys:position:batchDelete") @check_demo async def batch_delete(request: Request): """ 批量删除岗位(请求体需传入 ID 数组) Request Body 示例: [1, 2, 3] # 岗位ID数组 :param request: FastAPI请求对象 :return: 批量删除结果响应 """ return await position_service.batch_delete(request) ``` ### 6. 路由注册(追加到 `src/api/v1/router.py`) ```python # 导入 from api.v1.endpoints.position import router as position_router # 注册 v1.include_router(position_router, prefix="/position", tags=["岗位管理"]) ``` ## 前端文件清单 ### 7. API 请求 `ui/src/api/system/position.ts` ```typescript import { http } from '@/utils/http/axios'; /** * @description: 岗位列表 */ export function getPositionList(params?) { return http.request({ url: '/position/page', method: 'GET', params, }); } /** * 获取全部岗位列表 * @param params 参数 * @returns 返回结果 */ export function getPositionAllList(params?) { return http.request({ url: '/position/list', method: 'GET', params, }); } /** * @description: 根据ID获取详情 */ export function getPositionDetail(positionId) { return http.request({ url: '/position/detail/' + positionId, method: 'get', }); } /** * @description: 添加岗位 */ export function positionAdd(data: any) { return http.request({ url: '/position/add', method: 'POST', data, }); } /** * @description: 更新岗位 */ export function positionUpdate(data: any) { return http.request({ url: '/position/update', method: 'PUT', data, }); } /** * @description: 删除岗位 */ export function positionDelete(positionId) { return http.request({ url: '/position/delete/' + positionId, method: 'DELETE', }); } /** * @description: 批量删除岗位 */ export function positionBatchDelete(data: any) { return http.request({ url: '/position/batchDelete', method: 'DELETE', data, }); } ``` ### 8. 页面视图(4 个文件) 参考 [3.10 前端页面视图](/zh/volume2/fe-view) 中的完整代码,包含以下文件: | 文件 | 说明 | |:----|:----| | `ui/src/views/system/position/index.vue` | 主页面:搜索 + 表格 + 操作 | | `ui/src/views/system/position/edit.vue` | 编辑弹窗:新增/编辑表单 | | `ui/src/views/system/position/columns.ts` | 表格列定义 | | `ui/src/views/system/position/querySchemas.ts` | 搜索表单 Schema | ### 9. 路由配置(追加到 `ui/src/router/routes/system.ts`) ```typescript { path: 'position', name: 'Position', component: () => import('/@/views/system/position/index.vue'), meta: { title: '岗位管理' }, }, ``` ## 开发检查清单 完成后端开发后,按顺序检查: - [ ] `models.py` 已定义模型,表名含 `DB_PREFIX` 前缀 - [ ] `schemas.py` 已定义表单类,继承 `BaseForm` - [ ] `repository.py` 已定义仓库类 + 模块级单例 - [ ] `service.py` 已声明 `repo` / `model` / 分页配置 / 唯一性校验 + 单例 - [ ] `endpoint.py` 已定义路由 + 权限装饰器 + 演示模式装饰器 - [ ] `router.py` 已导入并注册路由 - [ ] 菜单管理中已添加权限节点 - [ ] 接口可通过 Swagger 文档正常调用 完成前端开发后,按顺序检查: - [ ] `api/system/position.ts` 已封装所有接口 - [ ] `views/system/position/index.vue` 主页面已实现 - [ ] `views/system/position/edit.vue` 编辑弹窗已实现 - [ ] `views/system/position/columns.ts` 列定义已配置 - [ ] `views/system/position/querySchemas.ts` 搜索 Schema 已配置 - [ ] 路由配置已追加到 `system.ts` - [ ] 后端菜单已配置组件路径 - [ ] 页面可正常访问和操作 ## 总结 完整模块涉及后端 5 个文件(models/schemas/repository/service/endpoint)+ 路由注册 + 权限配置,前端 4 个文件(index.vue/edit.vue/columns.ts/querySchemas.ts)+ API 文件。代码生成器可根据数据库表自动生成全套代码。