针对国有资产监督管理部门对档案管理的保密性与培训实操性要求,本指南将构建一套基于Python Flask的轻量级档案培训平台。该系统无需配置复杂的服务器环境,支持本地化部署,具备视频教学、PDF档案查阅及学习进度追踪功能,完全满足内网环境下的全员培训需求。
技术栈确定为:Python 3.9 + Flask + SQLite。选择SQLite是因为其为文件型数据库,无需额外安装数据库服务,且便于备份迁移,非常适合单机或小规模内网部署。
在开始编写代码前,需确保操作系统中已安装Python环境。请打开命令行终端,执行以下命令确认Python版本(建议3.9及以上):
```bash python --version ```接下来,我们在本地创建一个名为sas_training_sys的项目文件夹,并进入该目录:
```bash mkdir sas_training_sys cd sas_training_sys ```为了隔离项目依赖,我们需要创建并激活虚拟环境。执行以下命令:
```bash python -m venv venv Windows激活命令 venv\Scripts\activate Linux/Mac激活命令 source venv/bin/activate ```安装核心依赖库Flask,用于快速构建Web服务:
```bash pip install flask ```我们需要设计三张核心表:users(存储学员账号)、courses(存储培训档案/视频信息)、progress(记录学习进度)。在项目根目录下创建一个名为schema.sql的文件,并写入以下SQL语句:
```sql DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS courses; DROP TABLE IF EXISTS progress; CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, role TEXT DEFAULT 'student' ); CREATE TABLE courses ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, file_path TEXT NOT NULL, category TEXT NOT NULL ); CREATE TABLE progress ( user_id INTEGER, course_id INTEGER, status INTEGER DEFAULT 0, PRIMARY KEY (user_id, course_id) ); -- 初始化管理员账号 (密码: admin123) INSERT INTO users (username, password, role) VALUES ('admin', 'pbkdf2:sha256:260000$salt$hash', 'admin'); -- 注意:实际密码哈希将在代码中生成,此处仅作表结构示意 ```在项目根目录下创建文件上传目录用于存储培训资料:
```bash mkdir uploads ```创建核心应用文件app.py。该文件将包含数据库连接、用户认证、文件上传及页面路由的所有逻辑。请直接复制以下完整代码:
```python import os import sqlite3 from flask import Flask, render_template, request, redirect, url_for, session, flash, send_from_directory from werkzeug.utils import SecurityError from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.utils import secure_filename app = Flask(__name__) app.secret_key = 'sas_secret_key_change_in_production' 生产环境请修改此密钥 app.config['UPLOAD_FOLDER'] = 'uploads' app.config['DATABASE'] = 'sas_training.db' app.config['MAX_CONTENT_LENGTH'] = 500 1024 1024 限制上传文件最大500MB 允许上传的文件扩展名 ALLOWED_EXTENSIONS = {'pdf', 'mp4', 'png', 'jpg', 'jpeg'} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def get_db_connection(): conn = sqlite3.connect(app.config['DATABASE']) conn.row_factory = sqlite3.Row return conn def init_db(): conn = get_db_connection() with app.open_resource('schema.sql', mode='r') as f: conn.executescript(f.read()) conn.commit() conn.close() 初始化数据库(如果不存在) if not os.path.exists(app.config['DATABASE']): init_db() 初始化时手动写入管理员账号 conn = get_db_connection() pw_hash = generate_password_hash('admin123') conn.execute('INSERT INTO users (username, password, role) VALUES (?, ?, ?)', ('admin', pw_hash, 'admin')) conn.commit() conn.close() @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] conn = get_db_connection() user = conn.execute('SELECT FROM users WHERE username = ?', (username,)).fetchone() conn.close() if user and check_password_hash(user['password'], password): session['user_id'] = user['id'] session['role'] = user['role'] return redirect(url_for('index')) else: flash('用户名或密码错误') return render_template('login.html') @app.route('/logout') def logout(): session.clear() return redirect(url_for('login')) @app.route('/') def index(): if 'user_id' not in session: return redirect(url_for('login')) conn = get_db_connection() 管理员看所有,学员看所有(可根据需求加权限过滤) courses = conn.execute('SELECT FROM courses').fetchall() 获取当前用户的学习进度 progress_list = conn.execute('SELECT course_id FROM progress WHERE user_id = ?', (session['user_id'],)).fetchall() learned_ids = [p['course_id'] for p in progress_list] conn.close() return render_template('index.html', courses=courses, learned_ids=learned_ids) @app.route('/upload', methods=['GET', 'POST']) def upload_file(): if 'user_id' not in session or session['role'] != 'admin': return redirect(url_for('index')) if request.method == 'POST': if 'file' not in request.files: flash('没有文件部分') return redirect(request.url) file = request.files['file'] title = request.form['title'] category = request.form['category'] if file.filename == '': flash('未选择文件') return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) 确保上传目录存在 os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) conn = get_db_connection() conn.execute('INSERT INTO courses (title, file_path, category) VALUES (?, ?, ?)', (title, filename, category)) conn.commit() conn.close() flash('档案上传成功') return redirect(url_for('index')) return render_template('upload.html') @app.route('/study/
为了保持零门槛,我们不使用Vue/React等复杂框架,而是使用Flask默认的Jinja2模板引擎配合原生HTML。首先在根目录创建templates文件夹:
```bash mkdir templates ``>1. 登录页面 (templates/login.html)
```html2. 首页/课程列表页 (templates/index.html)
```html3. 档案上传页 (templates/upload.html)
```html4. 学习/查看页 (templates/study.html)
```html所有代码文件已准备就绪,项目结构应如下所示:
确保虚拟环境已激活,在终端执行以下命令启动服务:
```bash python app.py ```当终端显示 Running on http://0.0.0.0:5000 时,说明服务启动成功。
打开浏览器访问 http://localhost