课程设计——基于Flask+Bootstrap+Mysql的项目审批系统(含源码+数据库)

完整资源获取
点击下载完整资源

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

初始化数据库

Mysql创建新用户并授权数据库权限

模型映射到数据库

$ 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('重置')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白话机器学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值