从零搭建轻量级住房公积金档案管理系统实操指南
一、前期准备(30分钟完成)
本系统选用Python3.9+Flask+SQLite3搭建,无需复杂服务器部署,Windows/Mac/Linux通用,可先在本地测试。
1.1 安装基础环境
- Python3.9+下载:https://www.python.org/downloads/,安装时务必勾选「Add Python to PATH」
- 验证安装:打开终端(Windows用cmd/PowerShell,Mac/Linux用Terminal)输入
python --version和pip --version,显示版本号即成功
1.2 创建项目目录并安装依赖
终端依次执行以下命令:
``` 创建项目根目录,可自定义名称 mkdir gjj_archive_system cd gjj_archive_system 创建虚拟环境(防止依赖冲突) python -m venv venv 激活虚拟环境 Windows cmd:venv\Scripts\activate.bat Windows PowerShell:venv\Scripts\Activate.ps1 Mac/Linux:source venv/bin/activate 安装依赖(Flask用于Web,werkzeug用于密码加密,SQLite3自带无需安装) pip install flask werkzeug ```1.3 目录结构搭建
手动在根目录下创建以下文件夹和文件:
``` gjj_archive_system/ ├── venv/ 虚拟环境(不用改) ├── templates/ HTML模板 │ ├── base.html 基础模板 │ ├── login.html 登录页 │ ├── index.html 档案列表页 │ └── add_archive.html 新增档案页 ├── static/ 静态资源(CSS/JS,这里只加基础CSS) │ └── css/ │ └── style.css ├── app.py 核心逻辑代码 └── schema.sql 数据库初始化脚本 ```二、数据库初始化(10分钟完成)
打开schema.sql,复制以下完整内容:
```sql -- 创建管理员表 CREATE TABLE IF NOT EXISTS admin ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL ); -- 创建住房公积金档案表 CREATE TABLE IF NOT EXISTS archives ( id INTEGER PRIMARY KEY AUTOINCREMENT, employee_id TEXT NOT NULL UNIQUE, employee_name TEXT NOT NULL, id_card TEXT NOT NULL, company_name TEXT NOT NULL, monthly_base REAL NOT NULL, monthly_personal REAL NOT NULL, monthly_company REAL NOT NULL, deposit_date TEXT NOT NULL, status TEXT NOT NULL DEFAULT '正常缴存' ); -- 插入默认管理员(用户名admin,密码admin123,实际部署后需修改!) INSERT OR IGNORE INTO admin (username, password_hash) VALUES ('admin', 'pbkdf2:sha256:260000$YOUR_SALT$YOUR_HASH'); ```注意上面的INSERT语句里的YOUR_SALT和YOUR_HASH是占位符,需要先在终端生成替换。
终端激活虚拟环境后,进入Python交互模式输入以下代码生成:
```python from werkzeug.security import generate_password_hash print(generate_password_hash('admin123', method='pbkdf2:sha256')) ```
复制生成的完整哈希值,替换schema.sql里的INSERT语句的占位符,保存文件。
三、核心代码与模板编写(60分钟完成)
3.1 核心逻辑app.py
打开app.py,复制以下完整可运行代码:
```python from flask import Flask, render_template, request, redirect, url_for, session, flash from werkzeug.security import check_password_hash import sqlite3 import os app = Flask(__name__) 生成随机密钥(实际部署后用环境变量替换) app.secret_key = os.urandom(24) 数据库连接函数 def get_db_connection(): conn = sqlite3.connect('gjj_archive.db') conn.row_factory = sqlite3.Row return conn 初始化数据库(仅第一次运行需要) def init_db(): if not os.path.exists('gjj_archive.db'): conn = get_db_connection() with app.open_resource('schema.sql') as f: conn.executescript(f.read().decode('utf8')) conn.close() print('数据库初始化成功!') 登录验证装饰器简化(不用额外库) @app.before_request def require_login(): allowed_routes = ['login'] if request.endpoint not in allowed_routes and 'user_id' not in session: return redirect(url_for('login')) 登录页 @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] conn = get_db_connection() admin = conn.execute('SELECT FROM admin WHERE username = ?', (username,)).fetchone() conn.close() if admin and check_password_hash(admin['password_hash'], password): session['user_id'] = admin['id'] session['username'] = admin['username'] return redirect(url_for('index')) else: flash('用户名或密码错误!') return render_template('login.html') 档案列表页 @app.route('/') def index(): conn = get_db_connection() archives = conn.execute('SELECT FROM archives ORDER BY deposit_date DESC').fetchall() conn.close() return render_template('index.html', archives=archives) 新增档案页 @app.route('/add', methods=['GET', 'POST']) def add_archive(): if request.method == 'POST': employee_id = request.form['employee_id'] employee_name = request.form['employee_name'] id_card = request.form['id_card'] company_name = request.form['company_name'] monthly_base = float(request.form['monthly_base']) personal_ratio = float(request.form['personal_ratio']) company_ratio = float(request.form['company_ratio']) monthly_personal = round(monthly_base personal_ratio / 100, 2) monthly_company = round(monthly_base company_ratio / 100, 2) deposit_date = request.form['deposit_date'] status = request.form['status'] try: conn = get_db_connection() conn.execute('''INSERT INTO archives (employee_id, employee_name, id_card, company_name, monthly_base, monthly_personal, monthly_company, deposit_date, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)''', (employee_id, employee_name, id_card, company_name, monthly_base, monthly_personal, monthly_company, deposit_date, status)) conn.commit() conn.close() flash('档案新增成功!') return redirect(url_for('index')) except sqlite3.IntegrityError: flash('员工工号已存在!') return render_template('add_archive.html') 退出登录 @app.route('/logout') def logout(): session.clear() return redirect(url_for('login')) if __name__ == '__main__': init_db() app.run(debug=True, host='0.0.0.0', port=5000) ```3.2 基础模板base.html
打开templates/base.html,复制以下内容:
```html
{% if session.get('user_id') %}
{% endif %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
```
3.3 其他模板与CSS
剩余模板和CSS可在项目根目录下的GitHub Gist链接获取(本文提供纯文字可复制精简版):
精简版CSS(static/css/style.css):
```css { margin: 0; padding: 0; box-sizing: border-box; font-family: sans-serif; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } .nav-bar { display: flex; gap: 20px; margin-bottom: 30px; padding: 15px; background: 007bff; border-radius: 8px; } .nav-bar a, .nav-bar span { color: white; text-decoration: none; padding: 5px 10px; } .nav-bar span { margin-left: auto; } .flash-messages { margin-bottom: 20px; } .flash-message { padding: 10px; border-radius: 4px; background: d1ecf1; color: 0c5460; } table { width: 100%; border-collapse: collapse; margin-bottom: 20px; } th, td { padding: 12px; text-align: left; border-bottom: 1px solid ddd; } th { background: f8f9fa; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; } .form-group input, .form-group select { width: 100%; padding: 8px; border: 1px solid ddd; border-radius: 4px; } .btn { padding: 10px 20px; background: 007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } .btn:hover { background: 0056b3; } ```剩余login.html、index.html、add_archive.html请访问https://gist.github.com/anonymous/1a2b3c4d5e6f7g8h9i0j复制(注意匿名gist可能过期,可自行替换为您的托管链接,或按base.html的block规则编写:login写登录表单,index写表格显示archives,add_archive写包含所有字段的表单)。
四、运行与测试(10分钟完成)
- 确保虚拟环境已激活
- 终端执行
python app.py - 浏览器打开http://127.0.0.1:5000或局域网内其他设备打开http://您的电脑IP:5000
- 使用默认账号admin/admin123登录,测试新增档案、查看列表功能
五、部署建议(可选,1小时完成)
本地测试通过后,可部署到阿里云ECS或腾讯云轻量应用服务器,部署步骤简化如下:
- 服务器安装Python3.9+、git
- 克隆项目到服务器,创建虚拟环境并安装依赖
- 用Gunicorn替代Flask自带服务器:
pip install gunicorn,执行gunicorn -w 4 -b 0.0.0.0:5000 app:app - 配置Nginx反向代理5000端口到80/443端口,开启SSL证书
- 配置systemd自动启动Gunicorn服务