Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
backend/app/__pycache__/*
frontend/node_modules/*
backend/app/models/__pycache__/*
backend/app/schemas/__pycache__/*
backend/app/routers/__pycache__/*
Empty file added backend/app/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions backend/app/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
92 changes: 92 additions & 0 deletions backend/app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.routers import items, auth, users, laboratories, devices, reservations, experiments, attendances, maintenances, notifications, dashboard
from app.database import engine, Base
from app.models.models import User
from app.database import SessionLocal
from app.utils.auth import get_password_hash

Base.metadata.create_all(bind=engine)

def init_db():
db = SessionLocal()
try:
admin = db.query(User).filter(User.username == "admin").first()
if not admin:
admin_user = User(
username="admin",
password=get_password_hash("admin123"),
name="管理员",
email="admin@example.com",
role="admin",
is_active=True
)
db.add(admin_user)
db.commit()
print("管理员账户已创建: admin / admin123")

teacher = db.query(User).filter(User.username == "teacher").first()
if not teacher:
teacher_user = User(
username="teacher",
password=get_password_hash("teacher123"),
name="张老师",
email="teacher@example.com",
role="teacher",
is_active=True
)
db.add(teacher_user)
db.commit()
print("教师账户已创建: teacher / teacher123")

student = db.query(User).filter(User.username == "student").first()
if not student:
student_user = User(
username="student",
password=get_password_hash("student123"),
name="李学生",
email="student@example.com",
role="student",
student_id="2024001",
major="计算机科学与技术",
grade="2024级",
advisor="张教授",
is_active=True
)
db.add(student_user)
db.commit()
print("学生账户已创建: student / student123")
finally:
db.close()

init_db()

app = FastAPI(title="研究生实验室管理系统", version="1.0.0")

app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

app.include_router(auth.router, prefix="/api/auth", tags=["认证"])
app.include_router(users.router, prefix="/api/users", tags=["用户管理"])
app.include_router(laboratories.router, prefix="/api/laboratories", tags=["实验室管理"])
app.include_router(devices.router, prefix="/api/devices", tags=["设备管理"])
app.include_router(reservations.router, prefix="/api/reservations", tags=["预约管理"])
app.include_router(experiments.router, prefix="/api/experiments", tags=["实验记录"])
app.include_router(attendances.router, prefix="/api/attendances", tags=["考勤管理"])
app.include_router(maintenances.router, prefix="/api/maintenances", tags=["维护管理"])
app.include_router(notifications.router, prefix="/api/notifications", tags=["通知管理"])
app.include_router(dashboard.router, prefix="/api/dashboard", tags=["仪表板"])
app.include_router(items.router, prefix="/api", tags=["示例项目"])

@app.get("/")
def read_root():
return {"message": "欢迎使用研究生实验室管理系统", "version": "1.0.0"}

@app.get("/health")
def health_check():
return {"status": "healthy"}
Empty file added backend/app/models/__init__.py
Empty file.
181 changes: 181 additions & 0 deletions backend/app/models/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, Float, Boolean, Date
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.database import Base

class User(Base):
__tablename__ = "users"

id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, nullable=False, index=True)
password = Column(String(255), nullable=False)
name = Column(String(50), nullable=False)
email = Column(String(100), unique=True, nullable=True)
phone = Column(String(20), nullable=True)
role = Column(String(20), default="student")
student_id = Column(String(20), nullable=True)
major = Column(String(100), nullable=True)
grade = Column(String(20), nullable=True)
advisor = Column(String(50), nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

devices = relationship("Device", back_populates="user")
reservations = relationship("Reservation", back_populates="user")
experiments = relationship("Experiment", back_populates="user")
attendances = relationship("Attendance", back_populates="user")
notifications = relationship("Notification", back_populates="user")

class Laboratory(Base):
__tablename__ = "laboratories"

id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
code = Column(String(50), unique=True, nullable=False, index=True)
location = Column(String(200), nullable=True)
capacity = Column(Integer, default=0)
manager = Column(String(50), nullable=True)
description = Column(Text, nullable=True)
status = Column(String(20), default="available")
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

devices = relationship("Device", back_populates="laboratory")
reservations = relationship("Reservation", back_populates="laboratory")
experiments = relationship("Experiment", back_populates="laboratory")

class Device(Base):
__tablename__ = "devices"

id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
code = Column(String(50), unique=True, nullable=False, index=True)
type = Column(String(50), nullable=True)
model = Column(String(100), nullable=True)
brand = Column(String(100), nullable=True)
serial_number = Column(String(100), nullable=True)
purchase_date = Column(Date, nullable=True)
price = Column(Float, nullable=True)
status = Column(String(20), default="available")
location = Column(String(200), nullable=True)
description = Column(Text, nullable=True)
maintenance_cycle = Column(Integer, default=0)
last_maintenance = Column(Date, nullable=True)

laboratory_id = Column(Integer, ForeignKey("laboratories.id"), nullable=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)

created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

laboratory = relationship("Laboratory", back_populates="devices")
user = relationship("User", back_populates="devices")
reservations = relationship("Reservation", back_populates="device")
maintenances = relationship("Maintenance", back_populates="device")

class Reservation(Base):
__tablename__ = "reservations"

id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False)
purpose = Column(Text, nullable=True)
start_time = Column(DateTime(timezone=True), nullable=False)
end_time = Column(DateTime(timezone=True), nullable=False)
status = Column(String(20), default="pending")
remarks = Column(Text, nullable=True)

user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
laboratory_id = Column(Integer, ForeignKey("laboratories.id"), nullable=True)
device_id = Column(Integer, ForeignKey("devices.id"), nullable=True)

created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

user = relationship("User", back_populates="reservations")
laboratory = relationship("Laboratory", back_populates="reservations")
device = relationship("Device", back_populates="reservations")

class Experiment(Base):
__tablename__ = "experiments"

id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False)
content = Column(Text, nullable=True)
purpose = Column(Text, nullable=True)
hypothesis = Column(Text, nullable=True)
procedure = Column(Text, nullable=True)
result = Column(Text, nullable=True)
conclusion = Column(Text, nullable=True)
status = Column(String(20), default="draft")
start_date = Column(Date, nullable=True)
end_date = Column(Date, nullable=True)

user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
laboratory_id = Column(Integer, ForeignKey("laboratories.id"), nullable=True)

created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

user = relationship("User", back_populates="experiments")
laboratory = relationship("Laboratory", back_populates="experiments")

class Attendance(Base):
__tablename__ = "attendances"

id = Column(Integer, primary_key=True, index=True)
check_in_time = Column(DateTime(timezone=True), nullable=False)
check_out_time = Column(DateTime(timezone=True), nullable=True)
duration = Column(Float, nullable=True)
date = Column(Date, nullable=False, index=True)

user_id = Column(Integer, ForeignKey("users.id"), nullable=False)

created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

user = relationship("User", back_populates="attendances")

class Maintenance(Base):
__tablename__ = "maintenances"

id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False)
description = Column(Text, nullable=True)
type = Column(String(20), default="routine")
status = Column(String(20), default="scheduled")
scheduled_date = Column(Date, nullable=True)
completed_date = Column(Date, nullable=True)
cost = Column(Float, nullable=True)
remarks = Column(Text, nullable=True)

device_id = Column(Integer, ForeignKey("devices.id"), nullable=False)

created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

device = relationship("Device", back_populates="maintenances")

class Notification(Base):
__tablename__ = "notifications"

id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False)
content = Column(Text, nullable=True)
type = Column(String(20), default="info")
is_read = Column(Boolean, default=False)

user_id = Column(Integer, ForeignKey("users.id"), nullable=True)

created_at = Column(DateTime(timezone=True), server_default=func.now())

user = relationship("User", back_populates="notifications")

class Item(Base):
__tablename__ = "items"

id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
description = Column(String(500), nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
Empty file added backend/app/routers/__init__.py
Empty file.
Loading