一、技术架构与环境准备
针对建筑业档案数据量大、文件类型多(如CAD图纸、PDF合同、现场照片)的特点,本方案采用FastAPI作为后端框架,Vue 3作为前端框架,MinIO作为私有对象存储,PostgreSQL作为元数据库。这套组合开源免费,性能强劲,完全满足企业级需求。
在开始编码前,请确保你的开发环境已安装以下基础软件:
- Python 3.9+: 后端运行环境。
- Node.js 16+: 前端运行环境。
- Docker & Docker Compose: 用于一键部署数据库和存储服务。
创建项目根目录construction_archive,并执行以下命令初始化后端环境:
```bash
mkdir construction_archive && cd construction_archive
python3 -m venv venv
source venv/bin/activate Windows下使用 venv\Scripts\activate
pip install fastapi uvicorn sqlalchemy psycopg2-binary python-multipart aiofiles minio
```
二、数据库模型设计
建筑业档案核心在于“项目-文件-版本”的关联。我们需要建立两张核心表:projects(项目表)和documents(档案表)。在根目录下创建models.py文件,写入以下完整代码:
```python
models.py
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from datetime import datetime
Base = declarative_base()
class Project(Base):
__tablename__ = "projects"
id = Column(Integer, primary_key=True, index=True)
project_code = Column(String(50), unique=True, index=True, nullable=False) 项目编号,如:PJ-2023-001
name = Column(String(200), nullable=False) 项目名称
description = Column(Text, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow)
documents = relationship("Document", back_populates="project")
class Document(Base):
__tablename__ = "documents"
id = Column(Integer, primary_key=True, index=True)
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
file_name = Column(String(255), nullable=False) 原始文件名
file_type = Column(String(50), nullable=False) 文件类型:图纸, 合同, 照片
version = Column(Integer, default=1) 版本号
minio_bucket = Column(String(100)) 存储桶名称
minio_object_name = Column(String(255)) 对象存储路径
uploader = Column(String(50)) 上传人
upload_time = Column(DateTime, default=datetime.utcnow)
project = relationship("Project", back_populates="documents")
```
三、MinIO对象存储配置
档案文件不适合直接存入数据库,我们使用MinIO进行S3兼容的存储。为了方便开发,我们使用Docker快速启动一个MinIO服务。在根目录创建docker-compose.yml:
```yaml
version: '3.8'
services:
postgres:
image: postgres:13
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: arch_db
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
minio:
image: minio/minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
volumes:
postgres_data:
minio_data:
```
执行docker-compose up -d启动数据库和存储服务。接着,在根目录创建database.py用于连接数据库和初始化MinIO客户端:
```python
database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import Base
from minio import Minio
import os
数据库配置
SQLALCHEMY_DATABASE_URL = "postgresql://admin:password@localhost:5432/arch_db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
MinIO 配置
minio_client = Minio(
"localhost:9000",
access_key="minioadmin",
secret_key="minioadmin",
secure=False
)
初始化数据库表
def init_db():
Base.metadata.create_all(bind=engine)
检查并创建默认存储桶
if not minio_client.bucket_exists("construction-docs"):
minio_client.make_bucket("construction-docs")
```
四、后端核心业务逻辑实现
创建main.py,实现项目的创建、档案的上传(含自动版本控制)及列表查询接口。这是系统的核心,包含了完整的文件流处理逻辑。
```python
main.py
from fastapi import FastAPI, Depends, HTTPException, UploadFile, File, Form
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from datetime import datetime
import uuid
from database import SessionLocal, init_db, minio_client
from models import Project, Document
app = FastAPI()
允许跨域访问
app.add_middleware(
CORSMiddleware,
allow_origins=[""],
allow_methods=[""],
allow_headers=[""],
)
启动时初始化
@app.on_event("startup")
def on_startup():
init_db()
依赖获取数据库会话
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
1. 创建新项目
@app.post("/projects/")
def create_project(code: str = Form(...), name: str = Form(...), db: Session = Depends(get_db)):
db_proj = Project(project_code=code, name=name)
db.add(db_proj)
db.commit()
db.refresh(db_proj)
return {"id": db_proj.id, "code": db_proj.project_code, "name": db_proj.name}
2. 上传档案(自动版本管理)
@app.post("/projects/{project_id}/upload/")
async def upload_document(
project_id: int,
file: UploadFile = File(...),
file_type: str = Form(...),
uploader: str = Form(...),
db: Session = Depends(get_db)
):
检查项目是否存在
project = db.query(Project).filter(Project.id == project_id).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
查找同名文件的最大版本号
last_version = db.query(Document).filter(
Document.project_id == project_id,
Document.file_name == file.filename
).order_by(Document.version.desc()).first()
new_version = 1
if last_version:
new_version = last_version.version + 1
生成唯一对象名
object_name = f"{project_id}/{file.filename}_v{new_version}_{uuid.uuid4().hex}"
上传文件到MinIO
try:
minio_client.put_object(
"construction-docs",
object_name,
file.file,
length=-1,
part_size=1010241024,
content_type=file.content_type
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Upload failed: {str(e)}")
保存记录到数据库
db_doc = Document(
project_id=project_id,
file_name=file.filename,
file_type=file_type,
version=new_version,
minio_bucket="construction-docs",
minio_object_name=object_name,
uploader=uploader
)
db.add(db_doc)
db.commit()
return {"message": "Upload successful", "version": new_version, "file_id": db_doc.id}
3. 获取项目档案列表
@app.get("/projects/{project_id}/documents/")
def get_documents(project_id: int, db: Session = Depends(get_db)):
docs = db.query(Document).filter(Document.project_id == project_id).all()
return [{
"id": d.id,
"file_name": d.file_name,
"file_type": d.file_type,
"version": d.version,
"uploader": d.uploader,
"upload_time": d.upload_time
} for d in docs]
```
五、前端Vue3界面开发
后端服务启动后,我们开发一个简洁的前端界面。在根目录下执行:
```bash
npm create vite@latest frontend -- --template vue
cd frontend
npm install axios element-plus
```

修改frontend/src/App.vue,实现项目选择和文件拖拽上传功能。这里直接提供完整的单文件组件代码,复制即可使用:
```html
建筑业企业档案管理系统
加载档案
拖拽文件到此处或 点击上传
v{{ scope.row.version }}
```
同时,需要在frontend/src/main.js中引入Element Plus样式:
```javascript
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(ElementPlus)
app.mount('app')
``>
六、系统启动与验证
所有代码已准备就绪,现在启动整个系统进行验证。
第一步:启动后端服务
在项目根目录下,打开终端:
```bash
确保Docker容器正在运行
docker-compose up -d
启动FastAPI后端
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
第二步:启动前端服务
在frontend目录下打开新终端:
```bash
npm run dev
```
第三步:功能验证
- 创建测试数据:使用Postman或curl向
http://localhost:8000/projects/发送POST请求,Body中包含code: "PJ-001"和name: "测试商业大厦项目"。
- 访问界面:浏览器访问前端地址(通常是
http://localhost:5173)。
- 上传测试:将本地的CAD文件或PDF拖入上传区域。系统会自动上传至MinIO,并在PostgreSQL中记录版本号。
- 版本迭代:再次上传同名文件,观察列表中版本号是否自动变为v2。
至此,一个具备版本控制、对象存储、项目隔离功能的建筑业企业档案管理系统雏形已完成。该架构可直接扩展OCR识别、在线预览等高级功能,无需重构。