完整资源获取
点击下载完整资源
1、资源项目源码均已通过严格测试验证,保证能够正常运行;
2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;
3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
基于Flask、Bootstrap和MySQL的项目审批系统是一个高效、实用的解决方案,旨在满足现代企业对内部流程管理的需求。以下是对该系统的综述:
一、系统背景与意义
随着信息化时代的到来,企业内部流程管理的重要性日益凸显。项目审批系统作为其中的重要一环,能够帮助企业实现高效、规范的工作流程。基于Flask、Bootstrap和MySQL的项目审批系统,结合了后端强大的数据处理能力、前端友好的用户界面设计以及稳定的数据存储支持,成为提升企业内部管理效能的有效工具。
二、技术选型
Flask:
Flask是一个轻量级的Python Web开发框架,以其简洁的API和高度可扩展性深受开发者喜爱。
在本系统中,Flask扮演了后端核心的角色,负责处理HTTP请求、业务逻辑以及数据交互。
Flask的蓝图(Blueprint)功能使得大型应用的组织变得有序,而内置的Jinja2模板引擎则方便了页面的渲染和动态内容的生成。
Bootstrap:
Bootstrap是由Twitter开发的一款流行的前端框架,提供了丰富的预定义样式、组件和JavaScript插件,极大地提高了网页开发的效率。
在本系统中,Bootstrap被用于设计审批系统的界面,确保了响应式布局,使得系统在不同设备上都能提供良好的用户体验。
通过使用Bootstrap的表格、表单、按钮和导航等元素,可以快速构建出专业且美观的审批流程界面。
MySQL:
MySQL是广泛使用的开源关系型数据库管理系统,为项目提供了稳定的数据存储支持。
在审批系统中,MySQL负责存储审批流程的各个环节,如项目信息、审批状态、用户角色等数据。
Flask通过SQLAlchemy(一个强大的Python ORM库)与MySQL进行交互,简化了数据库操作,使得开发者能专注于业务逻辑而非底层SQL语法。
三、系统结构
系统结构方面,基于Flask、Bootstrap和MySQL的项目审批系统通常包含以下几个关键部分:
app.py:Flask应用的主入口,包含了应用的初始化、路由设置和数据库配置。
templates:存放Jinja2模板文件,如审批表单、审批结果展示页面等。
static:存放Bootstrap和其他前端资源,如CSS样式表、JavaScript文件和图片。
models.py:定义了与数据库交互的模型类,对应MySQL中的表结构。
forms.py:定义了Flask-WTF表单类,用于处理用户输入和验证。
views.py:定义了视图函数,处理HTTP请求并返回响应。
四、功能模块
在实际应用中,基于Flask、Bootstrap和MySQL的项目审批系统可能包括如下功能模块:
用户管理:用户注册、登录、权限分配等。
项目提交:用户提交项目申请,包含项目详情、预算等信息。
审批流程:设定多级审批规则,每个阶段可指定审批人。
审批决策:审批人查看项目详情,做出批准或拒绝的决定,并记录审批意见。
追踪状态:实时显示项目审批进度,所有相关用户都能查看。
历史记录:保存审批历史,便于后期查询和审计。
五、总结
基于Flask、Bootstrap和MySQL的项目审批系统是一个高效、实用的解决方案,能够满足现代企业对内部流程管理的需求。通过结合后端强大的数据处理能力、前端友好的用户界面设计以及稳定的数据存储支持,该系统能够帮助企业实现审批流程的自动化,提高工作效率,同时确保数据的安全性和一致性。无论是对于小型团队还是大型企业,这样的系统都是提升内部管理效能的有效工具。
基于Flask+Bootstrap+Mysql的项目审批系统部署介绍
安装相关库
$ git clone https://github.com/rmboot/approvalsystem
$ cd approvalsystem
$ pipenv install
$ pipenv shell
初始化数据库
模型映射到数据库
$ python manage.py db init
$ python manage.py db migrate
$ python manage.py db upgrade
初始化role,status,dept表
在数据库控制台执行init.sql的SQL语句
初始化user表
1.取消user.py文件视图函数index的注释,执行
$ flask run
* Running on http://127.0.0.1:5000/
2.访问 http://127.0.0.1:5000/ 会生成相应用户,并打印提示信息
3.Press CTRL+C 关闭Flask,将取消的注释再次注释
所有配置完成,再次执行,然后去登录吧
$ flask run
* Running on http://127.0.0.1:5000/
Pipenv 下载速度太慢可以选择指定源
$ pipenv install --pypi-mirror https://pypi.tuna.tsinghua.edu.cn/simple
部分源码(表结构部分)
from flask_login import current_user
from flask_wtf import FlaskForm
from flask_ckeditor import CKEditorField
from flask_wtf.file import FileField, FileAllowed, FileRequired
from wtforms import StringField, SubmitField, BooleanField, PasswordField, SelectField, TextAreaField
from wtforms.validators import DataRequired, Regexp, Length, EqualTo, ValidationError
from approval_system.extensions import archives
from approval_system.models import User, Dept, Role
class LoginForm(FlaskForm):
number = StringField('学号/工号', validators=[DataRequired(), Length(8, 12)])
password = PasswordField('密码', validators=[DataRequired(), Length(1, 100)])
remember = BooleanField()
submit = SubmitField('登录')
class RegisterForm(FlaskForm):
number = StringField('学号', validators=[DataRequired(), Length(12, 12), Regexp('^[0-9]*$', message='学号只能包含0-9')])
name = StringField('姓名', validators=[DataRequired(), Length(1, 60)])
dept_id = SelectField('学院', coerce=int, validators=[DataRequired()])
phone = StringField('手机号', validators=[DataRequired(), Length(11, 11)])
password = PasswordField('密码', validators=[DataRequired(), Length(1, 100), EqualTo('password1')])
password1 = PasswordField('确认密码', validators=[DataRequired(), Length(1, 100)])
submit = SubmitField('注册')
def __init__(self, *args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.dept_id.choices = [(dept.id, dept.name) for dept in Dept.query.filter(Dept.id > 1).all()]
def validate_number(self, field):
if User.query.filter_by(number=field.data).first():
raise ValidationError('该学号已经被注册')
class RegisterAdminForm(FlaskForm):
number = StringField('工号', validators=[DataRequired(), Length(8, 8), Regexp('^[0-9]*$', message='工号只能包含0-9')])
name = StringField('姓名', validators=[DataRequired(), Length(1, 60)])
dept_id = SelectField('学院/部门', coerce=int, validators=[DataRequired()])
role_id = SelectField('角色', coerce=int, validators=[DataRequired()])
phone = StringField('手机号', validators=[DataRequired(), Length(11, 11)])
password = PasswordField('密码', validators=[DataRequired(), Length(1, 100), EqualTo('password1')])
password1 = PasswordField('确认密码', validators=[DataRequired(), Length(1, 100)])
submit = SubmitField('注册')
def __init__(self, *args, **kwargs):
super(RegisterAdminForm, self).__init__(*args, **kwargs)
self.dept_id.choices = [(dept.id, dept.name) for dept in Dept.query.order_by(Dept.id.desc()).all()]
self.role_id.choices = [(role.id, role.info) for role in Role.query.filter(Role.id > 1).all()]
def validate_number(self, field):
if User.query.filter_by(number=field.data).first():
raise ValidationError('该工号已经被注册')
class SettingForm(FlaskForm):
number = StringField('学号/工号', validators=[DataRequired(), Length(8, 12), Regexp('^[0-9]*$', message='学号/工号只能包含0-9')])
name = StringField('姓名', validators=[DataRequired(), Length(1, 60)])
dept_id = SelectField('学院', coerce=int, validators=[DataRequired()])
phone = StringField('手机号', validators=[DataRequired(), Length(11, 11)])
submit = SubmitField('提交')
def __init__(self, *args, **kwargs):
super(SettingForm, self).__init__(*args, **kwargs)
if current_user.dept_id == 1:
self.dept_id.choices = [(current_user.dept_id, current_user.dept.name)]
else:
self.dept_id.choices = [(dept.id, dept.name) for dept in Dept.query.filter(Dept.id > 1).all()]
def validate_number(self, field):
if current_user.number == field.data:
return
if User.query.filter_by(number=field.data).first():
raise ValidationError('该学号/工号已经被注册')
class PasswordForm(FlaskForm):
old_password = PasswordField('原密码', validators=[DataRequired(), Length(1, 100)])
password = PasswordField('新密码', validators=[DataRequired(), Length(1, 100), EqualTo('password1')])
password1 = PasswordField('确认密码', validators=[DataRequired(), Length(1, 100)])
submit = SubmitField('提交')
def validate_old_password(self, field):
if not current_user.validate_password(field.data):
raise ValidationError('原密码错误')
class ApplyFormBase(FlaskForm):
name = StringField('项目名', validators=[DataRequired(), Length(1, 60)])
info = CKEditorField('项目描述', validators=[DataRequired()])
file = FileField('项目文件', render_kw={'multiple': 'multiple'}, validators=[
FileRequired(), FileAllowed(archives, '必须为压缩文件')
])
t_id = SelectField('导师', coerce=int, validators=[DataRequired()])
submit = SubmitField('立即申请')
class ApplyForm(ApplyFormBase):
def __init__(self, *args, **kwargs):
super(ApplyForm, self).__init__(*args, **kwargs)
self.t_id.choices = [(t.id, t.name) for t in
User.query.filter(User.dept_id == current_user.dept_id, User.role_id == 2).all()]
class ReApplyForm(ApplyForm):
name, info, file, submit = None, None, None, None
submit0 = SubmitField('重新申请')
class MyApplyForm(ApplyFormBase):
file, t_id, submit = None, None, None
submit1 = SubmitField('立即更改')
class FileApplyForm(ApplyFormBase):
name, info, t_id, submit = None, None, None, None
submit2 = SubmitField('立即上传')
class CommentForm(FlaskForm):
body = TextAreaField('', validators=[DataRequired()])
submit3 = SubmitField('提交评论')
class NoticeForm(FlaskForm):
title = StringField('标题', validators=[DataRequired(), Length(1, 100)])
body = CKEditorField('公告内容', validators=[DataRequired()])
submit = SubmitField('发布公告')
class MyNoticeForm(FlaskForm):
title = StringField('标题', validators=[DataRequired(), Length(1, 100)])
body = CKEditorField('公告内容', validators=[DataRequired()])
submit = SubmitField('立即更改')
class UserSearchForm(FlaskForm):
number = StringField('学号/工号', validators=[DataRequired(), Length(8, 12), Regexp('^[0-9]*$', message='学号/工号只能包含0-9')])
submit = SubmitField('搜索')
class PasswordResetForm(FlaskForm):
new_password = StringField('密码', default='12345678', validators=[DataRequired(), Length(1, 100)])
submit1 = SubmitField('重置')