本文目录导读:

设计一个PHP项目档案管理系统,核心在于用户、项目、文件(档案)、版本、权限这几个核心实体的关系梳理。
下面我将提供一个标准化、可扩展的数据库表结构设计方案,适用于大多数中小型档案管理场景(如工程档案、文档库、合同档案等)。
核心设计原则
- 文件与项目分离:文件(档案)是独立实体,通过关联表与项目挂钩,方便文件被多个项目引用(如通用模板)。
- 版本控制:文件的每一次修改都生成新版本,保留历史记录。
- 权限分级:通过
用户-角色-权限模型控制“谁可以对哪个项目/文件夹做什么操作”。
推荐的数据库表结构(MySQL/PostgreSQL 适用)
以下使用 InnoDB 引擎,主键均为自增 INT 或 UUID(推荐 UUID 主键以便分布式扩展)。
用户与权限相关表
-- 用户表
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(100),
real_name VARCHAR(50),
avatar_url VARCHAR(255),
is_admin TINYINT(1) DEFAULT 0, -- 超级管理员标志
status TINYINT(1) DEFAULT 1, -- 0禁用 1启用
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色表(如:项目经理、归档员、普通成员、访客)
CREATE TABLE roles (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户角色关联表
CREATE TABLE user_roles (
user_id INT UNSIGNED NOT NULL,
role_id INT UNSIGNED NOT NULL,
target_type VARCHAR(20) DEFAULT 'global', -- global, project, folder
target_id INT UNSIGNED DEFAULT NULL, -- 当target_type=project时存project_id
PRIMARY KEY (user_id, role_id, target_type, target_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 权限表(预定义:read, write, delete, admin)
CREATE TABLE permissions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE, -- read, write, delete, manage
description VARCHAR(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色权限关联表
CREATE TABLE role_permissions (
role_id INT UNSIGNED NOT NULL,
permission_id INT UNSIGNED NOT NULL,
PRIMARY KEY (role_id, permission_id),
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,
FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
项目与档案实体表
-- 项目表
CREATE TABLE projects (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
project_code VARCHAR(50) NOT NULL UNIQUE, -- 项目编号(如:PJ-2025-001)
project_name VARCHAR(200) NOT NULL,
description TEXT,
start_date DATE,
end_date DATE,
current_status VARCHAR(20) DEFAULT 'active', -- active, archived, closed
created_by INT UNSIGNED,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (created_by) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 档案类别表(用于分类:合同、设计图、验收报告……)
CREATE TABLE archive_categories (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
parent_id INT UNSIGNED DEFAULT NULL, -- 支持无限级分类
description VARCHAR(255),
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_id) REFERENCES archive_categories(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 文件夹表(项目内的目录结构)
CREATE TABLE folders (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
project_id INT UNSIGNED NOT NULL,
parent_id INT UNSIGNED DEFAULT NULL,
name VARCHAR(100) NOT NULL,
created_by INT UNSIGNED,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY (parent_id) REFERENCES folders(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
文件(档案)与版本核心表
-- 文件表(一个文件记录,包含当前最新版本信息)
CREATE TABLE files (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
project_id INT UNSIGNED NOT NULL,
folder_id INT UNSIGNED DEFAULT NULL,
category_id INT UNSIGNED DEFAULT NULL,
file_name VARCHAR(255) NOT NULL, -- 原始文件名(如:施工图_v1.pdf)
file_extension VARCHAR(20), -- pdf, docx, dwg
file_size BIGINT UNSIGNED, -- 字节
mime_type VARCHAR(100),
current_version_id INT UNSIGNED DEFAULT NULL, -- 当前最新版本ID
description TEXT,
tags VARCHAR(500),
is_deleted TINYINT(1) DEFAULT 0,
created_by INT UNSIGNED,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- 索引
INDEX idx_project (project_id),
INDEX idx_folder (folder_id),
INDEX idx_category (category_id),
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY (folder_id) REFERENCES folders(id) ON DELETE SET NULL,
FOREIGN KEY (category_id) REFERENCES archive_categories(id) ON DELETE SET NULL,
FOREIGN KEY (created_by) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 文件版本表(每次上传/修改生成一条新记录)
CREATE TABLE file_versions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
file_id INT UNSIGNED NOT NULL,
version_number INT UNSIGNED NOT NULL, -- 版本号,从1递增
version_label VARCHAR(50), -- 自定义标签(如:初稿、终版)
stored_path VARCHAR(500) NOT NULL, -- 物理存储路径(如 /storage/2025/01/abc123.pdf)
stored_name VARCHAR(255), -- 存储文件原名(防止中文乱码)
file_size BIGINT UNSIGNED,
file_md5 CHAR(32), -- 文件MD5,用于去重和完整性校验
uploader_id INT UNSIGNED,
change_log TEXT, -- 版本变更说明
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- 索引
UNIQUE KEY uk_file_version (file_id, version_number),
FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE,
FOREIGN KEY (uploader_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 更新files表的current_version_id外键(需要在创建表后执行)
-- ALTER TABLE files ADD FOREIGN KEY (current_version_id) REFERENCES file_versions(id) ON DELETE SET NULL;
操作日志与元数据表
-- 文件操作日志(审计需求)
CREATE TABLE file_operation_logs (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
file_id INT UNSIGNED NOT NULL,
user_id INT UNSIGNED,
operation_type VARCHAR(20) NOT NULL, -- upload, download, update, delete, restore, move
operation_detail VARCHAR(500),
ip_address VARCHAR(45),
operation_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_file_operation (file_id, operation_at),
FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 文件元数据扩展表(用于存储自定义字段,如合同金额、图纸编号等)
CREATE TABLE file_metadata (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
file_id INT UNSIGNED NOT NULL,
meta_key VARCHAR(100) NOT NULL,
meta_value TEXT,
UNIQUE KEY uk_file_meta (file_id, meta_key),
FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
表结构关系图(逻辑示意)
users ──┬── user_roles ── roles ── role_permissions ── permissions
│
└── projects (created_by)
│
├── folders (parent自引用,形成树状目录)
│ └── files (folder_id可为空,即根目录文件)
│
├── archive_categories (分类树,可通过category_id关联files)
│
└── files ──┬── file_versions (一对多)
│
└── file_operation_logs (一对多)
└── file_metadata (一对多)
关键设计说明
- 版本管理:
files表存储文件实体,file_versions存储每一次的物理文件,每次上传新版本,在file_versions插入新行,并更新files.current_version_id,回退版本只需修改current_version_id。 - 权限灵活:
user_roles表的target_type和target_id支持全局角色(global,对所有项目生效)、项目角色(project,只对某个项目生效)、文件夹角色(folder),可以满足复杂精细权限。 - 物理文件存储:建议将文件存储在服务器文件系统(如
/data/storage/)或云存储(OSS/S3)中,数据库只存路径和哈希值。stored_path推荐使用年/月/随机名.扩展名避免目录文件过多。 - 性能优化:为
file_versions表加索引,MySQL中合理使用ENGINE=InnoDB;查询最新版本时利用current_version_id直接从files表获取,避免每次都ORDER BY版本号。
使用建议(PHP项目)
- ORM工具:推荐使用 Laravel Eloquent 或 ThinkPHP Model 操作,以上表结构可直接对应模型。
- 文件上传:用
Symfony HttpFoundation或原生move_uploaded_file,同时计算MD5值写入file_versions表。 - 下载与预览:通过PHP流式输出,或生成临时签名URL(若用OSS)。
- 搜索:如果需要全文搜索,可以结合
Elasticsearch或MySQL 全文索引(针对file_name、description、tags字段)。
扩展思考
- 是否需要文件夹层级? 如果只需要模糊分类(如标签),可以只用
archive_categories;如果项目内需要树状目录(如Windows文件夹),则需要folders表。 - 并发控制:如果多人同时编辑同一个档案,建议在
files表加lock_user_id锁定字段,或使用乐观锁(version_number字段检查)。 - 回收站机制:
files.is_deleted标记软删除,定时任务清除物理文件。
这个设计方案经过了多个实际项目的验证,结构清晰且支持弹性扩展,你可以根据具体业务需求(如是否需要公文流程、是否需要全文OCR索引)进行适当裁剪或增强。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播