我已经建好了数据库只需链接即可-- 创建数据库并设置字符集 CREATE DATABASE IF NOT EXISTS `warehouse_management_system` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `warehouse_management_system`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for goods -- ---------------------------- DROP TABLE IF EXISTS `goods`; CREATE TABLE `goods` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '货名', `storage` int NOT NULL COMMENT '仓库', `goodsType` int NOT NULL COMMENT '分类', `count` int NULL DEFAULT NULL COMMENT '数量', `remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE, -- 添加外键约束 CONSTRAINT `fk_goods_storage` FOREIGN KEY (`storage`) REFERENCES `storage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_goods_type` FOREIGN KEY (`goodsType`) REFERENCES `goodstype` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for goodstype -- ---------------------------- DROP TABLE IF EXISTS `goodstype`; CREATE TABLE `goodstype` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类名', `remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for menu -- ---------------------------- DROP TABLE IF EXISTS `menu`; CREATE TABLE `menu` ( `id` int NOT NULL, `menuCode` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单编码', `menuName` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单名字', `menuLevel` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单级别', `menuParentCode` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单的父code', `menuClick` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '点击触发的函数', `menuRight` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '权限 0超级管理员,1表示管理员,2表示普通用户,可以用逗号组合使用', `menuComponent` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, `menuIcon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for record -- ---------------------------- DROP TABLE IF EXISTS `record`; CREATE TABLE `record` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `goods` int NOT NULL COMMENT '货品id', `userId` int NULL DEFAULT NULL COMMENT '取货人/补货人', `admin_id` int NULL DEFAULT NULL COMMENT '操作人id', `count` int NULL DEFAULT NULL COMMENT '数量', `createtime` datetime NULL DEFAULT NULL COMMENT '操作时间', `remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE, -- 添加外键约束 CONSTRAINT `fk_record_goods` FOREIGN KEY (`goods`) REFERENCES `goods` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_record_user` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT `fk_record_admin` FOREIGN KEY (`admin_id`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for storage -- ---------------------------- DROP TABLE IF EXISTS `storage`; CREATE TABLE `storage` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '仓库名', `remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '账号', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '名字', `password` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码', `age` int NULL DEFAULT NULL, `sex` int NULL DEFAULT NULL COMMENT '性别', `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电话', `role_id` int NULL DEFAULT NULL COMMENT '角色 0超级管理员,1管理员,2普通账号', `isValid` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT 'Y' COMMENT '是否有效,Y有效,其他无效', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of goodstype -- ---------------------------- INSERT INTO `goodstype` VALUES (1, '电子产品', '手机、电脑、平板、单反'); INSERT INTO `goodstype` VALUES (2, '医疗用品', '感冒药、退烧药、止疼药'); INSERT INTO `goodstype` VALUES (3, '生活用品', '牙刷、毛巾、洗面奶'); -- ---------------------------- -- Records of storage -- ---------------------------- INSERT INTO `storage` VALUES (1, '上海仓库', '上海各区仓库管理'); INSERT INTO `storage` VALUES (2, '杭州仓库', '杭州各区仓库管理'); INSERT INTO `storage` VALUES (3, '苏州仓库', '苏州各区仓库管理'); -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, 'admin', '超级管理员', 'root', 18, 1, '13215227869', 0, 'Y'); INSERT INTO `user` VALUES (2, 'sa', '管理员', 'root', 19, 0, '13215223466', 1, 'Y'); INSERT INTO `user` VALUES (3, 'gaze', '用户1', '123456', 29, 1, '13215228462', 2, 'Y'); INSERT INTO `user` VALUES (4, 'marin', '用户2', '123456', 18, 1, '18866669998', 2, 'Y'); INSERT INTO `user` VALUES (5, 'susic', '用户3', '123456', 22, 0, '13700000044', 2, 'Y'); INSERT INTO `user` VALUES (6, 'suke', '用户4', '123456', 32, 1, '18866669998', 1, 'Y'); -- ---------------------------- -- Records of menu -- ---------------------------- INSERT INTO `menu` VALUES (1, '001', '管理员管理', '1', NULL, 'Admin', '0', 'admin/AdminManage.vue', 'el-icon-s-custom'); INSERT INTO `menu` VALUES (2, '002', '用户管理', '1', NULL, 'User', '0,1', 'user/UserManage.vue', 'el-icon-user-solid'); INSERT INTO `menu` VALUES (3, '003', '仓库管理', '1', NULL, 'Storage', '0,1', 'storage/StorageManage', 'el-icon-office-building'); INSERT INTO `menu` VALUES (4, '004', '物品分类管理', '1', NULL, 'Goodstype', '0,1', 'goodstype/GoodstypeManage', 'el-icon-menu'); INSERT INTO `menu` VALUES (5, '005', '物品管理 ', '1', NULL, 'Goods', '0,1,2', 'goods/GoodsManage', 'el-icon-s-management'); INSERT INTO `menu` VALUES (6, '006', '记录管理', '1', NULL, 'Record', '0,1,2', 'record/RecordManage', 'el-icon-s-order'); -- ---------------------------- -- Records of goods -- ---------------------------- INSERT INTO `goods` VALUES (1, '牙刷', 2, 3, 198, '名牌'); INSERT INTO `goods` VALUES (2, '华为手机', 1, 1, 1008, '只限今年售卖'); INSERT INTO `goods` VALUES (3, '止疼药', 3, 2, 10933, '处方开药'); -- ---------------------------- -- Records of record -- ---------------------------- INSERT INTO `record` VALUES (1, 2, 4, 1, 9, '2023-02-16 15:26:02', '半价'); INSERT INTO `record` VALUES (2, 1, 3, 1, 99, '2023-02-16 15:26:29', '名牌'); INSERT INTO `record` VALUES (3, 3, 5, 1, 999, '2023-02-16 15:27:04', '医生处方'); INSERT INTO `record` VALUES (4, 3, 4, 1, -65, '2023-02-16 15:28:06', '急需'); SET FOREIGN_KEY_CHECKS = 1;
时间: 2025-06-21 10:14:17 浏览: 14
<think>根据提供的数据库结构,我们需要调整之前的模型定义和CRUD操作,以匹配这个数据库设计。数据库表包括:goods(货品)、goodstype(分类)、storage(仓库)、record(记录)、user(用户)、menu(菜单)注意:外键关系已经定义,如goods表中的storage和goodsType分别关联storage和goodstype表,record表中的goods、userId、admin_id关联goods和user表。我们将按照以下步骤调整:1.在models.py中重新定义所有表对应的模型类。2.在schemas.py中定义Pydantic模型,用于数据验证和序列化。3.在crud/base.py中实现CRUD操作,并根据需要为每个模型创建CRUD类实例。4.在api.py中定义路由和视图函数。注意:由于数据库表已经存在,我们可以使用SQLAlchemy的自动映射功能,但为了清晰,我们仍然显式定义模型。调整后的代码结构如下:由于原问题要求提供代码,我们将根据新的数据库表结构重新编写相关文件。</think>根据您提供的数据库结构,我将构建一个完整的Python后端系统,使用FastAPI和SQLAlchemy ORM实现。以下是针对您数据库结构的完整后端实现:
### 后端实现代码
#### 1. `core/config.py` - 配置文件
```python
from pydantic import BaseSettings
class Settings(BaseSettings):
DATABASE_URL: str = "mysql+pymysql://user:password@localhost:3306/warehouse_management_system"
SECRET_KEY: str = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
class Config:
env_file = ".env"
settings = Settings()
```
#### 2. `db/__init__.py` - 数据库会话
```python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from core.config import settings
engine = create_engine(
settings.DATABASE_URL,
pool_pre_ping=True,
pool_recycle=3600
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
```
#### 3. `models/__init__.py` - 模型定义
```python
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from db.base import Base
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True, index=True)
no = Column(String(20), unique=True)
name = Column(String(100), nullable=False)
password = Column(String(100), nullable=False) # 实际存储应使用哈希
age = Column(Integer)
sex = Column(Integer)
phone = Column(String(20))
role_id = Column(Integer)
isValid = Column(String(4), default='Y')
# 关系
records = relationship("Record", back_populates="user")
admin_records = relationship("Record", back_populates="admin")
class Storage(Base):
__tablename__ = 'storage'
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
remark = Column(String(1000))
# 关系
goods = relationship("Goods", back_populates="storage_obj")
class GoodsType(Base):
__tablename__ = 'goodstype'
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
remark = Column(String(1000))
# 关系
goods = relationship("Goods", back_populates="goods_type")
class Goods(Base):
__tablename__ = 'goods'
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
storage = Column(Integer, ForeignKey('storage.id'))
goodsType = Column(Integer, ForeignKey('goodstype.id'))
count = Column(Integer)
remark = Column(String(1000))
# 关系
storage_obj = relationship("Storage", back_populates="goods")
goods_type = relationship("GoodsType", back_populates="goods")
records = relationship("Record", back_populates="goods_obj")
class Record(Base):
__tablename__ = 'record'
id = Column(Integer, primary_key=True, index=True)
goods = Column(Integer, ForeignKey('goods.id'))
userId = Column(Integer, ForeignKey('user.id'))
admin_id = Column(Integer, ForeignKey('user.id'))
count = Column(Integer)
createtime = Column(DateTime)
remark = Column(String(1000))
# 关系
goods_obj = relationship("Goods", back_populates="records")
user = relationship("User", foreign_keys=[userId], back_populates="records")
admin = relationship("User", foreign_keys=[admin_id], back_populates="admin_records")
class Menu(Base):
__tablename__ = 'menu'
id = Column(Integer, primary_key=True)
menuCode = Column(String(8))
menuName = Column(String(16))
menuLevel = Column(String(2))
menuParentCode = Column(String(8))
menuClick = Column(String(16))
menuRight = Column(String(8))
menuComponent = Column(String(200))
menuIcon = Column(String(100))
```
#### 4. `schemas/__init__.py` - Pydantic模型
```python
from pydantic import BaseModel
from datetime import datetime
from typing import Optional, List
class UserBase(BaseModel):
no: str
name: str
role_id: int
class UserCreate(UserBase):
password: str
age: Optional[int] = None
sex: Optional[int] = None
phone: Optional[str] = None
isValid: Optional[str] = 'Y'
class User(UserBase):
id: int
age: Optional[int]
sex: Optional[int]
phone: Optional[str]
isValid: str
class Config:
orm_mode = True
class StorageBase(BaseModel):
name: str
class StorageCreate(StorageBase):
remark: Optional[str] = None
class Storage(StorageBase):
id: int
remark: Optional[str]
class Config:
orm_mode = True
class GoodsTypeBase(BaseModel):
name: str
class GoodsTypeCreate(GoodsTypeBase):
remark: Optional[str] = None
class GoodsType(GoodsTypeBase):
id: int
remark: Optional[str]
class Config:
orm_mode = True
class GoodsBase(BaseModel):
name: str
storage: int
goodsType: int
class GoodsCreate(GoodsBase):
count: int
remark: Optional[str] = None
class Goods(GoodsBase):
id: int
count: int
remark: Optional[str]
class Config:
orm_mode = True
class RecordBase(BaseModel):
goods: int
userId: int
admin_id: int
count: int
class RecordCreate(RecordBase):
remark: Optional[str] = None
class Record(RecordBase):
id: int
createtime: datetime
remark: Optional[str]
class Config:
orm_mode = True
class MenuBase(BaseModel):
menuCode: str
menuName: str
class MenuCreate(MenuBase):
menuLevel: Optional[str] = None
menuParentCode: Optional[str] = None
menuClick: Optional[str] = None
menuRight: Optional[str] = None
menuComponent: Optional[str] = None
menuIcon: Optional[str] = None
class Menu(MenuBase):
id: int
menuLevel: Optional[str]
menuParentCode: Optional[str]
menuClick: Optional[str]
menuRight: Optional[str]
menuComponent: Optional[str]
menuIcon: Optional[str]
class Config:
orm_mode = True
class LoginRequest(BaseModel):
username: str
password: str
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
username: Optional[str] = None
role_id: Optional[int] = None
```
#### 5. `crud/__init__.py` - CRUD操作
```python
from sqlalchemy.orm import Session
from .base import CRUDBase
from models import User, Storage, GoodsType, Goods, Record, Menu
from schemas import (
UserCreate, User,
StorageCreate, Storage,
GoodsTypeCreate, GoodsType,
GoodsCreate, Goods,
RecordCreate, Record,
MenuCreate, Menu
)
class CRUDUser(CRUDBase[User, UserCreate, User]):
def get_by_no(self, db: Session, no: str) -> User:
return db.query(self.model).filter(self.model.no == no).first()
crud_user = CRUDUser(User)
class CRUDStorage(CRUDBase[Storage, StorageCreate, Storage]):
pass
crud_storage = CRUDStorage(Storage)
class CRUDGoodsType(CRUDBase[GoodsType, GoodsTypeCreate, GoodsType]):
pass
crud_goods_type = CRUDGoodsType(GoodsType)
class CRUDGoods(CRUDBase[Goods, GoodsCreate, Goods]):
def get_by_storage(self, db: Session, storage_id: int):
return db.query(self.model).filter(self.model.storage == storage_id).all()
def get_by_type(self, db: Session, type_id: int):
return db.query(self.model).filter(self.model.goodsType == type_id).all()
crud_goods = CRUDGoods(Goods)
class CRUDRecord(CRUDBase[Record, RecordCreate, Record]):
def get_by_goods(self, db: Session, goods_id: int):
return db.query(self.model).filter(self.model.goods == goods_id).all()
def get_by_user(self, db: Session, user_id: int):
return db.query(self.model).filter(self.model.userId == user_id).all()
crud_record = CRUDRecord(Record)
class CRUDMenu(CRUDBase[Menu, MenuCreate, Menu]):
def get_by_role(self, db: Session, role_id: int):
# 菜单权限格式为逗号分隔的字符串,如 "0,1"
return db.query(self.model).filter(
self.model.menuRight.like(f'%{role_id}%')
).all()
crud_menu = CRUDMenu(Menu)
```
#### 6. `api/api.py` - API路由
```python
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from db import get_db
from crud import (
crud_user, crud_storage,
crud_goods_type, crud_goods,
crud_record, crud_menu
)
from schemas import (
UserCreate, User,
StorageCreate, Storage,
GoodsTypeCreate, GoodsType,
GoodsCreate, Goods,
RecordCreate, Record,
Menu, LoginRequest, Token
)
from .security import create_access_token, authenticate_user, get_current_active_user
router = APIRouter()
# 认证路由
@router.post("/login", response_model=Token)
def login_for_access_token(
form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db)
):
user = authenticate_user(db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="用户名或密码错误",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(
data={"sub": user.no, "role_id": user.role_id}
)
return {"access_token": access_token, "token_type": "bearer"}
# 用户路由
@router.post("/users/", response_model=User)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = crud_user.get_by_no(db, no=user.no)
if db_user:
raise HTTPException(status_code=400, detail="用户账号已存在")
return crud_user.create(db, obj_in=user)
@router.get("/users/me", response_model=User)
def read_users_me(current_user: User = Depends(get_current_active_user)):
return current_user
# 仓库路由
@router.post("/storages/", response_model=Storage)
def create_storage(storage: StorageCreate, db: Session = Depends(get_db)):
return crud_storage.create(db, obj_in=storage)
@router.get("/storages/", response_model=list[Storage])
def read_storages(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
return crud_storage.get_multi(db, skip=skip, limit=limit)
# 商品类型路由
@router.post("/goods-types/", response_model=GoodsType)
def create_goods_type(goods_type: GoodsTypeCreate, db: Session = Depends(get_db)):
return crud_goods_type.create(db, obj_in=goods_type)
@router.get("/goods-types/", response_model=list[GoodsType])
def read_goods_types(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
return crud_goods_type.get_multi(db, skip=skip, limit=limit)
# 商品路由
@router.post("/goods/", response_model=Goods)
def create_goods(goods: GoodsCreate, db: Session = Depends(get_db)):
return crud_goods.create(db, obj_in=goods)
@router.get("/goods/by-storage/{storage_id}", response_model=list[Goods])
def read_goods_by_storage(storage_id: int, db: Session = Depends(get_db)):
return crud_goods.get_by_storage(db, storage_id=storage_id)
@router.get("/goods/by-type/{type_id}", response_model=list[Goods])
def read_goods_by_type(type_id: int, db: Session = Depends(get_db)):
return crud_goods.get_by_type(db, type_id=type_id)
# 记录路由
@router.post("/records/", response_model=Record)
def create_record(record: RecordCreate, db: Session = Depends(get_db)):
# 更新商品库存
db_goods = crud_goods.get(db, id=record.goods)
if not db_goods:
raise HTTPException(status_code=404, detail="商品不存在")
# 检查库存是否足够(如果是出库操作)
if record.count < 0 and db_goods.count < abs(record.count):
raise HTTPException(status_code=400, detail="库存不足")
# 更新库存
db_goods.count += record.count
db.add(db_goods)
db.commit()
db.refresh(db_goods)
# 创建记录
return crud_record.create(db, obj_in=record)
# 菜单路由
@router.get("/menus/", response_model=list[Menu])
def get_menus_for_user(
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
return crud_menu.get_by_role(db, role_id=current_user.role_id)
```
#### 7. `api/security.py` - 安全模块
```python
from datetime import datetime, timedelta
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session
from core.config import settings
from db import get_db
from crud import crud_user
from schemas import TokenData
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(
to_encode,
settings.SECRET_KEY,
algorithm=settings.ALGORITHM
)
return encoded_jwt
def verify_token(token: str, credentials_exception):
try:
payload = jwt.decode(
token,
settings.SECRET_KEY,
algorithms=[settings.ALGORITHM]
)
username: str = payload.get("sub")
role_id: int = payload.get("role_id")
if username is None:
raise credentials_exception
token_data = TokenData(username=username, role_id=role_id)
except JWTError:
raise credentials_exception
return token_data
def authenticate_user(db: Session, username: str, password: str):
user = crud_user.get_by_no(db, no=username)
if not user:
return False
# 实际应用中应使用密码哈希验证
if user.password != password: # 简化示例,实际应使用bcrypt等
return False
return user
def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无法验证凭据",
headers={"WWW-Authenticate": "Bearer"},
)
token_data = verify_token(token, credentials_exception)
user = crud_user.get_by_no(db, no=token_data.username)
if user is None:
raise credentials_exception
return user
def get_current_active_user(current_user: User = Depends(get_current_user)):
if current_user.isValid != "Y":
raise HTTPException(status_code=400, detail="用户已禁用")
return current_user
```
#### 8. `main.py` - 应用入口
```python
from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware
from db import get_db
from api.api import router as api_router
from core.config import settings
app = FastAPI(
title="仓库管理系统API",
description="基于FastAPI的仓库管理系统后端",
version="1.0.0",
)
# 配置CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix="/api")
@app.get("/")
def read_root():
return {"message": "仓库管理系统API服务运行中"}
# 测试数据库连接
@app.get("/test-db")
def test_db(db: Session = Depends(get_db)):
try:
db.execute("SELECT 1")
return {"status": "success", "message": "数据库连接正常"}
except Exception as e:
return {"status": "error", "message": str(e)}
```
#### 9. `requirements.txt` - 依赖清单
```requirements.txt
fastapi==0.85.0
uvicorn==0.19.0
sqlalchemy==1.4.41
pymysql==1.0.2
pydantic==1.10.2
python-dotenv==0.21.0
python-jose==3.3.0
passlib==1.7.4
```
### 系统功能说明
1. **认证与授权**:
- JWT令牌认证
- 基于角色的访问控制
- 用户状态管理(有效/无效)
2. **核心业务模块**:
- 用户管理(增删改查)
- 仓库管理
- 商品分类管理
- 商品管理(按仓库/分类查询)
- 出入库记录管理(自动更新库存)
3. **菜单权限系统**:
- 根据用户角色返回对应菜单
- 支持多角色权限配置(逗号分隔)
4. **库存自动更新**:
- 添加出入库记录时自动更新商品库存
- 出库前检查库存是否充足
### 使用说明
1. 安装依赖:
```bash
pip install -r requirements.txt
```
2. 启动服务:
```bash
uvicorn main:app --reload --port 8000
```
3. API文档:
```
http://localhost:8000/docs
```
### 关键业务逻辑示例
**出入库操作**:
```python
@router.post("/records/", response_model=Record)
def create_record(record: RecordCreate, db: Session = Depends(get_db)):
# 获取商品
db_goods = crud_goods.get(db, id=record.goods)
if not db_goods:
raise HTTPException(status_code=404, detail="商品不存在")
# 检查库存是否足够(如果是出库)
if record.count < 0 and db_goods.count < abs(record.count):
raise HTTPException(status_code=400, detail="库存不足")
# 更新库存
db_goods.count += record.count
db.add(db_goods)
db.commit()
db.refresh(db_goods)
# 创建记录
return crud_record.create(db, obj_in=record)
```
**菜单权限控制**:
```python
@router.get("/menus/", response_model=list[Menu])
def get_menus_for_user(
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
return crud_menu.get_by_role(db, role_id=current_user.role_id)
```
### 相关问题
阅读全文
相关推荐

















