网站首页/ 信息中心/ 档案百科/

档案整理管理系统:从零搭建可落地的数字化方案

发布时间:2026年09月14日 05:35:25 浏览量:0

一、系统架构与核心模块设计

一个完整的档案整理管理系统核心包含三个部分:档案录入与存储、档案检索与浏览、系统权限与安全。我们将采用前后端分离架构进行构建,前端负责用户交互,后端提供数据接口和业务逻辑,数据库负责持久化存储。

1.1 技术栈选型

选择成熟、稳定、文档齐全的技术组合,确保零门槛部署和后期维护。

二、开发环境准备与项目初始化

2.1 环境安装

确保你的操作系统(Windows/macOS/Linux)已安装以下软件,版本需完全匹配。

安装后,在终端分别执行以下命令验证安装成功:

``` node --version npm --version mysql --version ```

2.2 数据库初始化

登录MySQL,创建数据库和核心表结构。

第一步,登录MySQL并创建数据库:

``` mysql -u root -p 输入你的root密码 CREATE DATABASE IF NOT EXISTS archive_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE archive_db; ```

第二步,执行以下SQL语句,创建档案信息表、用户表、操作日志表:

``` -- 用户表 CREATE TABLE `sys_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '登录名', `password_hash` varchar(255) NOT NULL COMMENT '密码哈希', `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名', `role` enum('admin','operator','viewer') NOT NULL DEFAULT 'viewer' COMMENT '角色', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uniq_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 档案信息表 CREATE TABLE `archive` ( `id` int NOT NULL AUTO_INCREMENT, `archive_number` varchar(100) NOT NULL COMMENT '档案编号', `title` varchar(500) NOT NULL COMMENT '档案标题', `category` varchar(100) NOT NULL COMMENT '分类', `keywords` varchar(500) DEFAULT NULL COMMENT '关键词,逗号分隔', `storage_location` varchar(500) NOT NULL COMMENT '物理存放位置或OSS路径', `file_name` varchar(255) NOT NULL COMMENT '原始文件名', `file_size` bigint DEFAULT NULL COMMENT '文件大小(字节)', `upload_user_id` int NOT NULL COMMENT '上传用户ID', `upload_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `description` text COMMENT '详细描述', PRIMARY KEY (`id`), UNIQUE KEY `uniq_archive_number` (`archive_number`), KEY `idx_category` (`category`), KEY `idx_keywords` (`keywords`(100)), CONSTRAINT `fk_upload_user` FOREIGN KEY (`upload_user_id`) REFERENCES `sys_user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 操作日志表 CREATE TABLE `operation_log` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `operation_type` varchar(50) NOT NULL COMMENT '操作类型', `target_id` int DEFAULT NULL COMMENT '操作目标ID', `detail` text COMMENT '操作详情', `ip_address` varchar(45) DEFAULT NULL, `operated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_operated_at` (`operated_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ```

三、后端服务搭建

3.1 创建后端项目

档案整理管理系统:从零搭建可落地的数字化方案

在合适目录下,打开终端,执行以下命令:

``` mkdir archive-backend && cd archive-backend npm init -y npm install koa koa-router koa-body koa-static koa2-cors mysql2 jsonwebtoken bcryptjs npm install --save-dev nodemon ```

创建项目入口文件 app.js 和基础目录结构:

``` const Koa = require('koa'); const Router = require('koa-router'); const koaBody = require('koa-body'); const cors = require('koa2-cors'); const path = require('path'); const fs = require('fs'); const app = new Koa(); const router = new Router(); // 创建上传文件目录 const uploadDir = path.join(__dirname, 'uploads'); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } // 中间件配置 app.use(cors({ origin: '', // 生产环境应替换为具体前端地址 credentials: true })); app.use(koaBody({ multipart: true, formidable: { uploadDir: uploadDir, keepExtensions: true, maxFileSize: 100 1024 1024 // 100MB } })); app.use(router.routes()).use(router.allowedMethods()); // 启动服务器 const PORT = 3000; app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); }); ```

3.2 数据库连接与配置

在项目根目录创建 config/db.js 文件:

``` const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'your_mysql_password', // 替换为你的MySQL密码 database: 'archive_db', waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); module.exports = pool; ```

3.3 实现核心API接口

创建 routes/archive.js 文件,实现档案上传和查询接口。

实现档案上传接口:

``` const Router = require('koa-router'); const router = new Router({ prefix: '/api/archive' }); const pool = require('../config/db'); const path = require('path'); const fs = require('fs'); // 档案上传接口 router.post('/upload', async (ctx) => { const file = ctx.request.files.file; const { archiveNumber, title, category, keywords, description } = ctx.request.body; const userId = 1; // 此处应从JWT token中解析出真实用户ID,为简化示例写死 if (!file) { ctx.status = 400; ctx.body = { code: 400, message: '未选择文件' }; return; } const connection = await pool.getConnection(); try { await connection.beginTransaction(); // 保存文件到本地uploads目录 const fileExt = path.extname(file.originalFilename); const newFileName = `${Date.now()}_${Math.random().toString(36).substr(2)}${fileExt}`; const newFilePath = path.join(__dirname, '../uploads', newFileName); fs.renameSync(file.filepath, newFilePath); // 插入档案记录到数据库 const [result] = await connection.execute( `INSERT INTO archive (archive_number, title, category, keywords, storage_location, file_name, file_size, upload_user_id, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [archiveNumber, title, category, keywords, `/uploads/${newFileName}`, file.originalFilename, file.size, userId, description] ); // 插入操作日志 await connection.execute( `INSERT INTO operation_log (user_id, operation_type, target_id, detail, ip_address) VALUES (?, ?, ?, ?, ?)`, [userId, 'UPLOAD', result.insertId, `上传档案【${title}】`, ctx.request.ip] ); await connection.commit(); ctx.body = { code: 200, message: '上传成功', data: { id: result.insertId } }; } catch (error) { await connection.rollback(); ctx.status = 500; ctx.body = { code: 500, message: '服务器内部错误', error: error.message }; } finally { connection.release(); } }); // 档案查询接口(支持分页、分类和关键词筛选) router.get('/list', async (ctx) => { const { page = 1, pageSize = 10, category, keyword } = ctx.query; const offset = (page - 1) pageSize; let sql = `SELECT SQL_CALC_FOUND_ROWS a., u.real_name as uploader FROM archive a LEFT JOIN sys_user u ON a.upload_user_id = u.id WHERE 1=1`; let params = []; if (category) { sql += ` AND a.category = ?`; params.push(category); } if (keyword) { sql += ` AND (a.title LIKE ? OR a.keywords LIKE ? OR a.archive_number LIKE ?)`; const likeKeyword = `%${keyword}%`; params.push(likeKeyword, likeKeyword, likeKeyword); } sql += ` ORDER BY a.upload_time DESC LIMIT ? OFFSET ?`; params.push(parseInt(pageSize), parseInt(offset)); const connection = await pool.getConnection(); try { const [rows] = await connection.execute(sql, params); const [[{ total }]] = await connection.execute(`SELECT FOUND_ROWS() as total`); ctx.body = { code: 200, data: { list: rows, pagination: { page: parseInt(page), pageSize: parseInt(pageSize), total } } }; } catch (error) { ctx.status = 500; ctx.body = { code: 500, message: '查询失败', error: error.message }; } finally { connection.release(); } }); module.exports = router; ```

app.js 中引入并使用这个路由:

``` const archiveRouter = require('./routes/archive'); // ... 其他中间件之后 app.use(archiveRouter.routes()); ```

四、前端管理界面开发

4.1 创建前端项目

打开新的终端窗口,执行以下命令:

``` npm create vue@latest archive-frontend 进入项目创建流程,按提示选择: √ Add TypeScript? ... No √ Add JSX Support? ... No √ Add Vue Router for Single Page Application? ... No √ Add Pinia for state management? ... No √ Add Vitest for Unit Testing? ... No √ Add an End-to-End Testing Solution? » No √ Add ESLint for code quality? ... No cd archive-frontend npm install element-plus axios npm run dev ```

4.2 实现档案上传组件

修改 src/App.vue 文件,替换为以下内容:

```