及模块划分。
目录
摘要 1
一、Front-End 1
二、Server 10
三.需求分析 18
1.引言 18
2、项目概述 19
3、具体需求 25
4、验收验证标准 26
四、项目运行 28
1.运行环境 28
2.使用方法 28
3.部署 40
4.运行 44
5.数据模型 44
6.API 45
3、模块划分
根据以上的设计和分析,服务端可分为管理系统模块,数据模型,API模块,其中API模块根据每个接口功能又分为用户模块,电影模块,场次模块,订单模块,评论模块,优惠券模块,会话模块,验证码模块,收藏模块,密码模块,模块划分非常清晰。
服务端的目录结构如下:
├─venv:虚拟环境
├─Flask-Server:服务端开发的源码
│ ├─top:阿里大于短信SDK
│ ├─instance:私密配置
│ ├─app:服务端主要代码
│ │ ├─admin:管理系统业务逻辑
│ │ ├─static:静态文件
│ │ ├─templates:管理系统界面
│ │ └─api:各模块API
│ │ ├─user.py:用户模块
│ │ ├─movie.py:电影模块
│ │ ├─screen.py:场次模块
│ │ ├─order.py:订单模块
│ │ ├─commetn.py:评论模块
│ │ ├─coupon.py:优惠券模块
│ │ ├─session.py:会话模块
│ │ ├─smscode.py:验证码模块
│ │ ├─favorite.py:收藏模块
│ │ └─password.py:密码模块
│ ├─config.py:普通配置文件
│ ├─gunicornConf.py:Gunicorn配置文件
│ └─server.py:入口文件
└─requirements.txt:第三方包需求文件
4、设计模式
装饰器模式:装饰器模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。装饰器模式通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。在项目中使用了非常多的装饰器,如路由监听,如某些特定的API需要登录。
工厂模式:Flask-Server/app/init.py中实现了一个create_app的函数,完成了 db/config/route/admin 的初始化工作之后,再返回这个 app 对象。把应用的实例创建的过程交给工厂函数,通过工厂函数选择你所要使用的配置,来创建适用于不同环境下的应用。
面向对象编程:应用中使用了面向对象编程的封装思想,按照业务逻辑将代码的各个模块进行了封装,如管理系统模块与API模块,API模块又根据不同的功能分为10个小模块。
三.需求分析
1.引言
1.1、目的
本文档将描述项目的整体结构和功能结构概貌,从总体结构上给出整个系统的轮廓,并对整个应用的功能以及性能需求进行详细描述。便于用户和开发人员进行沟通交流。
1.2、背景
本次待开发软件为电影购票系统。用户使用该可以在本应用实现查看和搜索正在热映和即将上映的电影资讯,对感兴趣的电影可以进行收藏。想要观看某部电影,可以进行下单购票操作。对于已经放映的电影订单,用户可以对该订单对应的电影进行评分评价的操作。
1.3、参考文献
[1] GB-T8567-2006,《计算机软件文档编制规范》[S]
[2] <教师报课系统>需求规格说明书,本文转载自http://www.biyezuopin.vip/onews.asp?id=15593
2、项目概述
2.1、产品描述
开发基于Android平台和移动端web平台的应用程序,实现基础的电影购票功能,并提供电影资讯查询和评分。为互联网购票提供简便高效的平台。
2.2、产品功能
接下来通过用例图来辅助描述产品的功能。
用户可以通过查看资讯来查看电影,也可以通过直接搜索来查看电影。电影资讯包括两种类型:正在热映和即将上映。除了以上两种方式外,在应用首页也会推荐一些热门电影供用户查看。不管是以何种方式查看电影,都可以点击进入详情页面查看某部电影的详细信息。
# -*- coding: utf-8 -*-
from utils import time2stamp
from flask_login import UserMixin
from datetime import datetime, date
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(UserMixin, db.Model):
"""用户"""
__tablename__ = 'users'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(11), doc='手机号码', primary_key=True)
password = db.Column(db.String(32), doc='密码', nullable=False)
payPassword = db.Column(db.String(32), doc='支付密码', nullable=False)
nickname = db.Column(db.String(20), doc='昵称', default='猿眼用户', nullable=False)
money = db.Column(db.Float, doc='账户余额', default=50, nullable=False)
description = db.Column(db.String(50), doc='个性签名', default='这个人很懒,什么也没留下', nullable=False)
avatar = db.Column(db.String(32), doc='头像路径', default='MonkeyEye.webp')
isAdmin = db.Column(db.Boolean, doc='是否管理员', default=False)
orders = db.relationship('Order', backref='users', cascade='all', lazy='dynamic')
coupons = db.relationship('Coupon', backref='users', cascade='all', lazy='dynamic')
favorites = db.relationship('Favorite', backref='users', cascade='all', lazy='dynamic')
comments = db.relationship('Comment', backref='users', cascade='all', lazy='dynamic')
def __repr__(self):
return '%s <%s>' % (self.nickname, self.id)
def __json__(self):
return {
'id': self.id,
'nickname': self.nickname,
'avatar': '/static/images/user/%s' % self.avatar,
'description': self.description,
'money': self.money
}
class Movie(db.Model):
"""电影"""
__tablename__ = 'movies'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
expired = db.Column(db.Boolean, doc='是否下架', default=False, nullable=False)
name = db.Column(db.String(25), doc='电影名称', nullable=False)
description = db.Column(db.Text, doc='电影介绍', default='暂无介绍', nullable=False)
playingTime = db.Column(db.Date, doc='上映时间', default=date.today(), nullable=False)
duration = db.Column(db.SmallInteger, doc='电影时长(分钟)', nullable=False)
movieType = db.Column(db.String(20), doc='电影类型', nullable=False)
playingType = db.Column(db.String(15), doc='放映类型', nullable=False)
rating = db.Column(db.Float, doc='电影评分', default=0)
ratingNum = db.Column(db.SmallInteger, doc='评分人数', default=0)
poster = db.Column(db.String(40), doc='海报路径')
screens = db.relationship('Screen', backref='movies', cascade='all', lazy='dynamic')
recommends = db.relationship('Recommend', backref='movies', cascade='all', lazy='dynamic')
comments = db.relationship('Comment', backref='movies', cascade='all', lazy='dynamic')
favorites = db.relationship('Favorite', backref='movies', cascade='all', lazy='dynamic')
def __repr__(self):
return '%s <%s>' % (self.name, self.id)
def __json__(self):
return {
'id': self.id,
'name': self.name,
'poster': '/static/images/poster/%s' % self.poster,
'movieType': self.movieType,
'playingType': self.playingType,
'playingTime': time2stamp(self.playingTime),
'duration': self.duration,
'rating': self.rating,
'description': self.description,
'ratingNum': self.ratingNum
}
class Screen(db.Model):
"""场次"""
__tablename__ = 'screens'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)
time = db.Column(db.DateTime, doc='场次时间', default=datetime.now(), nullable=False)
hallNum = db.Column(db.String(1), doc='放映厅(1-5)', nullable=False)
price = db.Column(db.Float, doc='票价', default=30, nullable=False)
ticketNum = db.Column(db.SmallInteger, doc='电影总票数', default=120, nullable=False)
orders = db.relationship('Order', backref='screens', cascade='all', lazy='dynamic')
def __repr__(self):
res = {
'id': self.id,
'name': Movie.query.get(self.movieId).name,
'time': self.time.strftime('%Y-%m-%d %X')
}
return '{name} [{time}] <{id}>'.format(**res)
def __json__(self):
movie = Movie.query.get(self.movieId)
return {
'id': self.id,
'movie': movie.__json__(),
'time': time2stamp(self.time),
'price': self.price,
'ticketNum': self.ticketNum,
'hallNum': self.hallNum,
'playingType': movie.playingType
}
class Recommend(db.Model):
"""推荐"""
__tablename__ = 'recommends'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), primary_key=True, nullable=False)
def __json__(self):
movie = Movie.query.get(self.movieId)
return {
'movieId': self.movieId,
'poster': '/static/images/poster/%s' % movie.poster,
'playingTime': time2stamp(movie.playingTime)
}
class Order(db.Model):
"""订单"""
__tablename__ = 'orders'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
screenId = db.Column(db.String(32), db.ForeignKey('screens.id'), nullable=False)
seat = db.Column(db.PickleType, doc='座位号(逗号分隔)', nullable=False)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False)
createTime = db.Column(db.DateTime, doc='创建时间', nullable=False)
status = db.Column(db.Boolean, doc='订单状态(0:未支付,1:已支付)', default=0, nullable=False)
couponId = db.Column(db.String(32), db.ForeignKey('coupons.id'))
payPrice = db.Column(db.Float, doc='实际支付', nullable=False)
totalPrice = db.Column(db.Float, doc='原价', nullable=False)
def __repr__(self):
screen = Screen.query.get(self.screenId)
movie = Movie.query.get(screen.movieId)
res = {
'id': self.id,
'hallNum': screen.hallNum,
'seat': self.seat,
'name': movie.name,
'time': screen.time.strftime('%Y-%m-%d %X')
}
return '{name} {time}放映 {hallNum}号厅{seat}座 订单{id}'.format(**res)
def __json__(self):
screen = Screen.query.get(self.screenId)
movie = Movie.query.get(screen.movieId)
return {
'id': self.id,
'screenId': self.screenId,
'movieId': movie.id,
'duration': movie.duration,
'name': movie.name,
'screenTime': time2stamp(screen.time),
'createTime': time2stamp(self.createTime),
'username': self.username,
'seat': self.seat,
'status': self.status,
'couponId': self.couponId,
'payPrice': self.payPrice,
'totalPrice': self.totalPrice
}
class Coupon(db.Model):
"""优惠券"""
__tablename__ = 'coupons'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
discount = db.Column(db.SmallInteger, doc='折扣', nullable=False, default=5)
condition = db.Column(db.SmallInteger, doc='满多少元可用', default=30, nullable=False)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
expiredTime = db.Column(db.Date, doc='过期时间', nullable=False)
status = db.Column(db.Boolean, doc='状态(0:未使用,1:已使用)', default=0, nullable=False)
def __json__(self):
return {
'id': self.id,
'discount': self.discount,
'condition': self.condition,
'expiredTime': time2stamp(self.expiredTime),
'status': self.status
}
class Favorite(db.Model):
"""收藏"""
__tablename__ = 'favorites'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)
def __json__(self):
return {
'id': self.id,
'username': self.username,
'movie': Movie.query.get(self.movieId).__json__()
}
class Comment(db.Model):
"""评论"""
__tablename__ = 'comments'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键
id = db.Column(db.String(32), primary_key=True)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)
content = db.Column(db.Text, nullable=False, doc='评论内容')
rating = db.Column(db.SmallInteger, nullable=False, doc='电影评分')
def __repr__(self):
return self.id
def __json__(self):
user = User.query.get(self.username)
avatar = '/static/images/user/%s' % user.avatar
return {
'id': self.id,
'username': self.username,
'avatar': avatar,
'content': self.content,
'rating': self.rating,
'nickname': user.nickname
}