# +====================================================================== # | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ] # +---------------------------------------------------------------------- # | Copyright (c) 2021-2026 一米阳光团队 版权所有 # +---------------------------------------------------------------------- # | 开源协议: Apache-2.0 # | 重要声明: 未经书面许可,不得移除或修改本框架相关版权标识。 # +---------------------------------------------------------------------- # | 官方网站: https://www.djangoadmin.cn # +---------------------------------------------------------------------- # | 研发团队: 一米阳光团队 荣誉出品 # +====================================================================== # | 版权和免责声明: # | 一、知识产权声明 # | 本团队对该软件框架产品(以下简称"本产品")拥有完整知识产权,包括但不限于商标权、专利权、 # | 著作权、商业秘密等。前述权利均受中华人民共和国及相关国际法律法规保护。未经本团队书面授权, # | 任何个人或单位不得基于本产品本身申请任何形式的知识产权。 # | 二、使用限制与禁止条款 # | 您理解并同意,禁止将本产品用于以下任何行为: # | 1. 任何违反中华人民共和国法律法规的用途; # | 2. 任何侵害他人合法权益(包括但不限于人身权、财产权、知识产权等)的行为; # | 3. 任何危害国家安全、公共利益及社会道德风尚的行为。 # | 三、责任豁免 # | 因使用本产品而产生的任何损失或法律纠纷(包括但不限于直接损失、间接损失、附带损失、衍生损失 # | 以及因违约、侵权等引发的责任),本团队均不承担任何法律责任。若因违规使用本产品导致任何第三 # | 方提起索赔或行政机关进行调查,您应独立承担全部责任。 # | 四、违约与法律责任 # | 如发现任何违反本声明的行为,本团队有权: # | 1. 无条件配合公安机关及其他有权机关的调查取证工作; # | 2. 依法追究相关方的民事责任,并要求赔偿全部损失; # | 3. 保留进一步采取刑事控告等法律措施的权利。 # | 五、许可范围说明 # | 1、被授权方应视本产品源代码为核心机密信息,负有最高标准的保密与保管义务。禁止以任何形式(包 # | 括但不限于直接或间接的分享、复制、传播、分发、转售、出租、开源、反向工程、反编译、反汇编或通 # | 过网络服务提供给任何第三方)泄露、披露或处置源代码的全部或部分内容。任何未经授权的复制、使用、 # | 传播行为均构成对本团队知识产权的严重侵权,本团队有权依法追究其全部法律责任,并要求赔偿因此造 # | 成的一切经济损失及商誉损害。 # | 2、本产品仅限于公司或个人在法律允许范围内,用于内部且合规的软件产品研发。具体权利义务以《软件 # | 许可协议》附件为准。 # +====================================================================== """ 岗位模型模块 ============================================================= 提供岗位管理的数据模型定义,用于定义员工岗位信息。 企业级特性: 1. 使用枚举类管理状态常量,确保类型安全 2. 状态文本自动转换,便于前端展示 3. 便捷的查询方法,提高开发效率 4. 继承 BaseModel 和 BaseDB,复用通用功能 5. __init__ 由 BaseModel 统一管理,无需重复定义 模型说明: 岗位用于标识用户的职位,如:技术总监、产品经理、开发工程师等。 通过 sort 字段控制显示顺序,数值越小越靠前。 """ from enum import IntEnum from typing import Optional, List from application.models.base_db import BaseDB from application.models.base_model import BaseModel from config import DB_PREFIX from extensions import db from utils.request import like_contains # ============================================================ # 岗位状态枚举 # ============================================================ class PositionStatus(IntEnum): """ 岗位状态枚举 使用 IntEnum 确保类型安全,避免魔法数字。 可直接用于数据库查询和比较。 Example: # 查询启用状态的岗位 Position.query.filter(Position.status == PositionStatus.ENABLED) # 创建岗位时设置状态 position = Position(name='经理', status=PositionStatus.ENABLED) # 判断岗位是否启用 if position.status == PositionStatus.ENABLED: print("岗位已启用") """ DISABLED = 0 # 停用 ENABLED = 1 # 启用 # ============================================================ # 岗位模型 # ============================================================ class Position(BaseModel, BaseDB): """ 岗位模型 用于存储员工岗位信息,如:技术总监、产品经理等。 继承自 BaseModel(通用字段)和 BaseDB(数据库操作方法)。 Attributes: id: 主键ID(继承自 BaseModel) name: 岗位名称(String(255),必填) status: 岗位状态(使用 PositionStatus 枚举,默认停用) sort: 岗位排序(Integer,默认0,数值越小越靠前) 便捷属性: status_text: 获取状态文本("启用"/"停用") is_enabled: 判断是否启用 is_disabled: 判断是否停用 自定义查询: get_enabled(): 获取所有启用的岗位 get_by_name(): 根据名称精确查询 search_by_name(): 根据名称模糊搜索 """ # ============================================================ # 表配置 # ============================================================ # 表名:使用配置前缀 + 模型名 __tablename__ = DB_PREFIX + "position" # ============================================================ # 字段定义 # ============================================================ # 岗位名称:必填字段,最长255字符 name = db.Column( db.String(255), nullable=False, comment="岗位名称" ) # 岗位状态:使用枚举确保类型安全 # 默认值为停用,创建后需手动启用 status = db.Column( db.Integer, default=PositionStatus.DISABLED, comment="岗位状态:0-停用 1-启用" ) # 岗位排序:数值越小越靠前 # 用于列表展示时的排序控制 sort = db.Column( db.Integer, default=0, comment="岗位排序" ) # ============================================================ # 注意:__init__ 方法在 BaseModel 中已实现,无需重复定义 # BaseModel 已处理驼峰转换、字段过滤等逻辑 # ============================================================ # ============================================================ # 便捷属性 # ============================================================ @property def status_text(self) -> str: """ 获取岗位状态文本 将数字状态转换为可读的中文文本。 用于前端展示或日志记录。 Returns: str: "启用" 或 "停用" """ status_map = { PositionStatus.DISABLED: '停用', PositionStatus.ENABLED: '启用' } return status_map.get(self.status, '未知') @property def is_enabled(self) -> bool: """ 判断岗位是否启用 Returns: bool: 启用返回 True,否则返回 False """ return self.status == PositionStatus.ENABLED @property def is_disabled(self) -> bool: """ 判断岗位是否停用 Returns: bool: 停用返回 True,否则返回 False """ return self.status == PositionStatus.DISABLED # ============================================================ # 自定义查询方法 # ============================================================ @classmethod def get_enabled(cls) -> List['Position']: """ 获取所有启用的岗位 按排序值升序排列,适用于下拉选择框等场景。 只返回未删除且状态为启用的岗位。 Returns: List[Position]: 启用的岗位列表 Example: positions = Position.get_enabled() for pos in positions: print(pos.name, pos.status_text) """ return cls.query.filter( cls.is_delete == 0, cls.status == PositionStatus.ENABLED ).order_by(cls.sort.asc()).all() @classmethod def get_by_name(cls, name: Optional[str]) -> Optional['Position']: """ 根据岗位名称精确查询 用于检查岗位名称是否已存在等场景。 Args: name: 岗位名称 Returns: Optional[Position]: 岗位对象,不存在或名称为空时返回 None Example: position = Position.get_by_name('经理') if position: print("岗位已存在") """ if not name: return None return cls.query.filter( cls.name == name, cls.is_delete == 0 ).first() @classmethod def search_by_name(cls, name: Optional[str]) -> List['Position']: """ 根据岗位名称模糊搜索 支持名称关键字匹配,按排序值升序排列。 适用于搜索建议或筛选场景。 Args: name: 岗位名称关键字 Returns: List[Position]: 匹配的岗位列表 Example: positions = Position.search_by_name('经理') for pos in positions: print(pos.name) """ if not name: return [] return cls.query.filter( cls.name.like(like_contains(name), escape='\\'), cls.is_delete == 0 ).order_by(cls.sort.asc()).all() # ============================================================ # 魔法方法 # ============================================================ def __repr__(self) -> str: """ 返回模型的字符串表示 用于调试和日志输出。 Returns: str: 格式为 "岗位:{name}" """ return f'岗位:{self.name}'