parent
3bc3f8ed5e
commit
4036ed0fff
@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
__pycache__/
|
||||||
|
*.log
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
FROM python:3.12.4-slim
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt requirements.txt
|
||||||
|
RUN pip config set global.index-url http://mirrors.aliyun.com/pypi/simple && pip config set install.trusted-host mirrors.aliyun.com
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
COPY . ./
|
||||||
|
CMD ["gunicorn", "-w", "4", "--bind", "0.0.0.0:3002", "myapp:app" ]
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import re
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
|
||||||
|
from app import LogService
|
||||||
|
from utils import create_response, StateCode
|
||||||
|
|
||||||
|
bank_bp = Blueprint('bank_server', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
#校验银行卡号
|
||||||
|
@bank_bp.route('/bank/card_verify', methods=['POST'])
|
||||||
|
def bankCardVerify():
|
||||||
|
pattern = r'^\d{13,19}$'
|
||||||
|
# 确保银行卡号是一个完整的 13 到 19 位的数字字符串
|
||||||
|
number = request.json.get('bankCard')
|
||||||
|
state = {
|
||||||
|
"result": bool(re.match(pattern, number))
|
||||||
|
}
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=state)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@bank_bp.route('/bank/pay', methods=['POST'])
|
||||||
|
def pay():
|
||||||
|
# 模拟支付成功,返回
|
||||||
|
state = {"state": "successful", "pay_time": datetime.datetime.now()}
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=state)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@bank_bp.route('/bank/query', methods=['POST'])
|
||||||
|
def query():
|
||||||
|
# 模拟验证成功,返回
|
||||||
|
state = {"state": "successful", "pay_time": datetime.datetime.now()}
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=state)), 200
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import re
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
|
||||||
|
from app import LogService
|
||||||
|
from utils import create_response, StateCode
|
||||||
|
|
||||||
|
id_card_bp = Blueprint('id_card_server', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
#校验身份证号码
|
||||||
|
@id_card_bp.route('/id_card/verify', methods=['POST'])
|
||||||
|
def idCardVerify():
|
||||||
|
print("idCardVerify() 被调用了")
|
||||||
|
pattern = r'^\d{18}$'
|
||||||
|
id_number = request.json.get('idCardNo')
|
||||||
|
print(f"Received ID number: {id_number}") # 先打印看看
|
||||||
|
state = {
|
||||||
|
"result": bool(re.match(pattern, id_number))
|
||||||
|
}
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=state)), 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
from flask import request
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
class LogService:
|
||||||
|
@staticmethod
|
||||||
|
def configure_logging():
|
||||||
|
logger.remove() # 移除默认的日志配置
|
||||||
|
logger.add(
|
||||||
|
"logs/app.log", # 日志文件名
|
||||||
|
rotation="1 week", # 每周轮换
|
||||||
|
retention="1 month", # 保留一个月
|
||||||
|
level="INFO", # 记录 INFO 及以上级别的日志
|
||||||
|
format="{time} - {level} - {message}", # 日志格式
|
||||||
|
backtrace=True, # 打印完整的异常堆栈
|
||||||
|
diagnose=True # 打印详细的异常信息
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def log():
|
||||||
|
logger.info(f"Request Path: {request.path}")
|
||||||
|
logger.info(f"Request Method: {request.method}")
|
||||||
|
logger.info(f"Request Headers: {request.headers}")
|
||||||
|
logger.info(f"Request args: {request.args}")
|
||||||
|
logger.info(f"Request Body: {request.get_data(as_text=True)}")
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
from flask_jwt_extended import create_access_token
|
||||||
|
|
||||||
|
from app import LogService
|
||||||
|
from app.models import Passenger
|
||||||
|
from presenter import PassengerPresenter
|
||||||
|
from utils import StateCode, create_response
|
||||||
|
|
||||||
|
login_bp = Blueprint('login', __name__)
|
||||||
|
|
||||||
|
#登录模块
|
||||||
|
@login_bp.route('/login', methods=['POST'])
|
||||||
|
def login():
|
||||||
|
data = request.json
|
||||||
|
account = data.get('account')
|
||||||
|
password = data.get('password')
|
||||||
|
if not account or not password:
|
||||||
|
return jsonify(create_response(StateCode.PARAMS_ERROR)), 400
|
||||||
|
user = Passenger.verifyPassenger(account, password)
|
||||||
|
if user:
|
||||||
|
# 为新创建的乘客生成访问令牌
|
||||||
|
access_token = create_access_token(identity=str(user.id))
|
||||||
|
user_presenter = PassengerPresenter(user, {"token": access_token}).as_dict()
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=user_presenter)), 200
|
||||||
|
return jsonify(create_response(StateCode.PASSWORD_INCORRECT)), 400
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
from app import db
|
||||||
|
from .order_lib import Order
|
||||||
|
from .passenger_lib import Passenger
|
||||||
|
from .station_lib import Station
|
||||||
|
from .train_lib import Train
|
||||||
|
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
import pdb
|
||||||
|
from datetime import datetime
|
||||||
|
from pypinyin import pinyin, Style
|
||||||
|
from sqlalchemy import func
|
||||||
|
|
||||||
|
from app.models import db
|
||||||
|
|
||||||
|
|
||||||
|
class Station(db.Model):
|
||||||
|
__tablename__: str = 'station'
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(120), unique=True, nullable=False, index=True)
|
||||||
|
pinyin = db.Column(db.String(120))
|
||||||
|
province = db.Column(db.String(120))
|
||||||
|
city = db.Column(db.String(120))
|
||||||
|
district = db.Column(db.String(120))
|
||||||
|
created_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
updated_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<Station {self.name}>'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, data):
|
||||||
|
station = cls(
|
||||||
|
name=data.get('name'),
|
||||||
|
pinyin=''.join([item[0] for item in pinyin(data.get('name'), style=Style.NORMAL)]).upper(),
|
||||||
|
province=data.get('province'),
|
||||||
|
city=data.get('city'),
|
||||||
|
created_at=datetime.now(),
|
||||||
|
updated_at=datetime.now(),
|
||||||
|
)
|
||||||
|
db.session.add(station)
|
||||||
|
db.session.commit()
|
||||||
|
return station
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def destroy(cls, station_id):
|
||||||
|
station = cls.query.get(station_id)
|
||||||
|
if station:
|
||||||
|
db.session.delete(station)
|
||||||
|
db.session.commit()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
from sqlalchemy import func
|
||||||
|
|
||||||
|
from app.models import db
|
||||||
|
|
||||||
|
|
||||||
|
class Ticket(db.Model):
|
||||||
|
__tablename__: str = 'ticket'
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
seat_no = db.Column(db.String(120))
|
||||||
|
seat_class = db.Column(db.String(120))
|
||||||
|
price = db.Column(db.Numeric(8, 2))
|
||||||
|
state = db.Column(db.Integer, default=0)
|
||||||
|
train_no = db.Column(db.String(120), db.ForeignKey('train.train_no'), nullable=False, index=True)
|
||||||
|
passenger_id = db.Column(db.Integer, db.ForeignKey('passenger.id'), nullable=False, index=True)
|
||||||
|
order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False, index=True)
|
||||||
|
from_station = db.Column(db.String(120))
|
||||||
|
to_station = db.Column(db.String(120))
|
||||||
|
date = db.Column(db.String(120))
|
||||||
|
departure_time = db.Column(db.DateTime)
|
||||||
|
arrival_time = db.Column(db.DateTime)
|
||||||
|
created_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
updated_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
order = db.relationship('Order', backref=db.backref('tickets'))
|
||||||
|
passenger = db.relationship('Passenger', backref=db.backref('tickets'))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<Ticket {self.id}>'
|
||||||
|
|
||||||
|
def updateState(self):
|
||||||
|
self.state = 1
|
||||||
|
return self
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generateTicket(cls, item, passenger_id):
|
||||||
|
# Create a new Ticket object
|
||||||
|
ticket = Ticket(
|
||||||
|
seat_class=item["seatClass"],
|
||||||
|
train_no=item["trainNo"],
|
||||||
|
from_station=item["from"],
|
||||||
|
to_station=item["to"],
|
||||||
|
date=item["date"],
|
||||||
|
passenger_id=passenger_id
|
||||||
|
)
|
||||||
|
return ticket
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
from sqlalchemy import func
|
||||||
|
|
||||||
|
from app.models import db
|
||||||
|
|
||||||
|
|
||||||
|
class TrainStation(db.Model):
|
||||||
|
__tablename__: str = 'train_station'
|
||||||
|
|
||||||
|
train_no = db.Column(db.String(120), db.ForeignKey('train.train_no'), primary_key=True, index=True)
|
||||||
|
station_name = db.Column(db.String(120), db.ForeignKey('station.name'), primary_key=True)
|
||||||
|
|
||||||
|
price = db.Column(db.Numeric(8, 2))
|
||||||
|
arrival_time = db.Column(db.DateTime)
|
||||||
|
departure_time = db.Column(db.DateTime)
|
||||||
|
index = db.Column(db.Integer, default=0)
|
||||||
|
created_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
updated_at = db.Column(db.DateTime, default=func.now())
|
||||||
|
|
||||||
|
station = db.relationship('Station', backref=db.backref('train_stations'))
|
||||||
|
train = db.relationship('Train', backref=db.backref('train_stations'))
|
||||||
|
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
import iso8601
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
from flask_jwt_extended import get_jwt_identity, jwt_required
|
||||||
|
|
||||||
|
from app import LogService
|
||||||
|
from app.models import Station
|
||||||
|
from app.models.ticket_lib import Ticket
|
||||||
|
from app.models.train_lib import Train
|
||||||
|
from app.station_manager import station_bp
|
||||||
|
from presenter import StationPresenter
|
||||||
|
from presenter.ticket import TicketPresenter
|
||||||
|
from presenter.train import TrainPresenter
|
||||||
|
from utils import create_response, StateCode
|
||||||
|
|
||||||
|
query_bp = Blueprint('query', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
#控制层,接收前端的请求,调用服务层进行查询车次信息,封装结构并返回
|
||||||
|
@query_bp.route('/trains/query_train', methods=['GET'])
|
||||||
|
def queryTrains(): # 查询车次方法
|
||||||
|
#获取起始站名
|
||||||
|
from_station = request.args.get('from')
|
||||||
|
#获取终点站名
|
||||||
|
to_station = request.args.get('to')
|
||||||
|
#获取日期并用iso8601解析
|
||||||
|
date = iso8601.parse_date(request.args.get('date'))
|
||||||
|
#判断参数是否为空
|
||||||
|
if not from_station or not to_station or not date:
|
||||||
|
return jsonify(create_response(StateCode.PARAMS_ERROR)), 400
|
||||||
|
# 查询车次
|
||||||
|
trains = Train.queryTrains(from_station, to_station, date)
|
||||||
|
# 封装响应数据
|
||||||
|
trains_presenters = [TrainPresenter(train).as_dict() for train in trains]
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=trains_presenters)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@query_bp.route('/tickets', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def getTickets(): # 查询车票方法
|
||||||
|
current_user = get_jwt_identity() # 解码JWT得到用户ID
|
||||||
|
tickets = Ticket.query.filter_by(passenger_id=current_user).all()
|
||||||
|
tickets_presenters = [TicketPresenter(ticket).as_dict() for ticket in tickets]
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=tickets_presenters)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@station_bp.route('/stations', methods=['GET'])
|
||||||
|
def queryStations(): # 查询站点方法
|
||||||
|
stations = Station.query.all()
|
||||||
|
stations_presenters = [StationPresenter(station).as_dict() for station in stations]
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=stations_presenters)), 200
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
from flask import request, jsonify, Blueprint
|
||||||
|
from app import LogService
|
||||||
|
from app.models import Station
|
||||||
|
from presenter import StationPresenter
|
||||||
|
from utils import create_response, StateCode
|
||||||
|
|
||||||
|
station_bp = Blueprint('stations', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@station_bp.route('/stations', methods=['POST'])
|
||||||
|
def createStation(): # 创建站点方法
|
||||||
|
data = request.json
|
||||||
|
new_station = Station.create(data=data)
|
||||||
|
station_presenter = StationPresenter(new_station).as_dict()
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=station_presenter)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@station_bp.route('/stations/quantity_create', methods=['POST'])
|
||||||
|
def quantityCreate(): # 批量创建站点方法
|
||||||
|
stations = request.json.get("stations")
|
||||||
|
for name in stations:
|
||||||
|
station_hash = {"name": name}
|
||||||
|
Station.create(station_hash)
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS)), 200
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
from flask import request, jsonify, Blueprint
|
||||||
|
from app import db, LogService
|
||||||
|
from app.models import Train
|
||||||
|
from app.models.train_lib import buildTrain
|
||||||
|
from presenter.train import TrainPresenter
|
||||||
|
from utils import create_response, StateCode
|
||||||
|
|
||||||
|
trains_bp = Blueprint('trains', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@trains_bp.route('/trains', methods=['GET'])
|
||||||
|
def queryAllTrains():
|
||||||
|
trains = Train.query.all()
|
||||||
|
trains_presenters = [TrainPresenter(train).as_dict() for train in trains]
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=trains_presenters)), 200
|
||||||
|
|
||||||
|
|
||||||
|
@trains_bp.route('/trains', methods=['POST'])
|
||||||
|
def createTrain():
|
||||||
|
data = request.json
|
||||||
|
new_train = buildTrain(data)
|
||||||
|
db.session.add(new_train)
|
||||||
|
db.session.commit()
|
||||||
|
train_presenter = TrainPresenter(new_train).as_dict()
|
||||||
|
LogService.log()
|
||||||
|
return jsonify(create_response(StateCode.SUCCESS, data=train_presenter)), 200
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
# SECRET_KEY = os.environ.get('SECRET_KEY') or 'your_secret_key'
|
||||||
|
# SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
|
SECRET_KEY = '8665e31a29ab7e12cb0f92c1dbobj1e3a6a15230fb17'
|
||||||
|
|
||||||
|
# SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or
|
||||||
|
# 'postgresql://username:password@localhost:5432/your dbname'
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'mysql+pymysql://root:1625344721Qq%40@localhost/mini12306'
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
|
REDIS_URL = "redis://:123456@localhost:6379/0"
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
# version: '3.8'
|
||||||
|
# services:
|
||||||
|
# python:
|
||||||
|
# build:
|
||||||
|
# context: ./
|
||||||
|
# dockerfile: ./Dockerfile
|
||||||
|
# restart: always
|
||||||
|
# environment:
|
||||||
|
# - DATABASE_URL=postgresql://postgres:postgres@db:5432/mini12306_python
|
||||||
|
# - REDIS_URL=redis
|
||||||
|
# - SERVER_LIB_URL=http://py12306.learnerhub.net
|
||||||
|
# ports:
|
||||||
|
# - "3002:3002"
|
||||||
|
# depends_on:
|
||||||
|
# - db
|
||||||
|
# - redis
|
||||||
|
# volumes:
|
||||||
|
# - /var/log/mini12306_python:/app/logs
|
||||||
|
#
|
||||||
|
# redis:
|
||||||
|
# image: redis:alpine
|
||||||
|
# container_name: 12306_redis
|
||||||
|
# volumes:
|
||||||
|
# - redis_data:/data
|
||||||
|
#
|
||||||
|
# db:
|
||||||
|
# image: postgres:15
|
||||||
|
# container_name: 12306_postgres
|
||||||
|
# restart: always
|
||||||
|
# environment:
|
||||||
|
# POSTGRES_USER: postgres
|
||||||
|
# POSTGRES_PASSWORD: postgres
|
||||||
|
# POSTGRES_DB: mini12306_python
|
||||||
|
# volumes:
|
||||||
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# volumes:
|
||||||
|
# postgres_data:
|
||||||
|
# redis_data:
|
||||||
|
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
python:
|
||||||
|
build:
|
||||||
|
context: ./
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=mysql+pymysql://root:123456@db:3306/mini12306_python # 修改数据库连接字符串
|
||||||
|
- REDIS_URL=redis
|
||||||
|
- SERVER_LIB_URL=http://py12306.learnerhub.net
|
||||||
|
ports:
|
||||||
|
- "3002:3002"
|
||||||
|
depends_on:
|
||||||
|
- db # 服务名保持不变,但已指向新的 MySQL 服务
|
||||||
|
- redis
|
||||||
|
volumes:
|
||||||
|
- /var/log/mini12306_python:/app/logs
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
container_name: 12306_redis
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
|
||||||
|
db: # 修改后的 MySQL 服务
|
||||||
|
image: mysql:8.0 # 使用官方 MySQL 镜像
|
||||||
|
container_name: 12306_mysql # 修改容器名称
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: 123456 # MySQL 根密码(建议修改)
|
||||||
|
MYSQL_DATABASE: mini12306_python # 自动创建的数据库
|
||||||
|
MYSQL_USER: app_user # 可选:创建专用用户
|
||||||
|
MYSQL_PASSWORD: user123 # 可选用户密码
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql # MySQL 数据存储路径
|
||||||
|
# 建议添加的健康检查
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql_data: # 修改卷名称
|
||||||
|
redis_data:
|
||||||
@ -0,0 +1 @@
|
|||||||
|
init folder
|
||||||
@ -0,0 +1 @@
|
|||||||
|
Single-database configuration for Flask.
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
# A generic, single database configuration.
|
||||||
|
|
||||||
|
[alembic]
|
||||||
|
# template used to generate migration files
|
||||||
|
# file_template = %%(rev)s_%%(slug)s
|
||||||
|
|
||||||
|
# set to 'true' to run the environment during
|
||||||
|
# the 'revision' command, regardless of autogenerate
|
||||||
|
# revision_environment = false
|
||||||
|
|
||||||
|
|
||||||
|
# Logging configuration
|
||||||
|
[loggers]
|
||||||
|
keys = root,sqlalchemy,alembic,flask_migrate
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys = console
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys = generic
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
level = WARN
|
||||||
|
handlers = console
|
||||||
|
qualname =
|
||||||
|
|
||||||
|
[logger_sqlalchemy]
|
||||||
|
level = WARN
|
||||||
|
handlers =
|
||||||
|
qualname = sqlalchemy.engine
|
||||||
|
|
||||||
|
[logger_alembic]
|
||||||
|
level = INFO
|
||||||
|
handlers =
|
||||||
|
qualname = alembic
|
||||||
|
|
||||||
|
[logger_flask_migrate]
|
||||||
|
level = INFO
|
||||||
|
handlers =
|
||||||
|
qualname = flask_migrate
|
||||||
|
|
||||||
|
[handler_console]
|
||||||
|
class = StreamHandler
|
||||||
|
args = (sys.stderr,)
|
||||||
|
level = NOTSET
|
||||||
|
formatter = generic
|
||||||
|
|
||||||
|
[formatter_generic]
|
||||||
|
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||||
|
datefmt = %H:%M:%S
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
import logging
|
||||||
|
from logging.config import fileConfig
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from alembic import context
|
||||||
|
|
||||||
|
# this is the Alembic Config object, which provides
|
||||||
|
# access to the values within the .ini file in use.
|
||||||
|
config = context.config
|
||||||
|
|
||||||
|
# Interpret the config file for Python logging.
|
||||||
|
# This line sets up loggers basically.
|
||||||
|
fileConfig(config.config_file_name)
|
||||||
|
logger = logging.getLogger('alembic.env')
|
||||||
|
|
||||||
|
|
||||||
|
def get_engine():
|
||||||
|
try:
|
||||||
|
# this works with Flask-SQLAlchemy<3 and Alchemical
|
||||||
|
return current_app.extensions['migrate'].db.get_engine()
|
||||||
|
except (TypeError, AttributeError):
|
||||||
|
# this works with Flask-SQLAlchemy>=3
|
||||||
|
return current_app.extensions['migrate'].db.engine
|
||||||
|
|
||||||
|
|
||||||
|
def get_engine_url():
|
||||||
|
try:
|
||||||
|
return get_engine().url.render_as_string(hide_password=False).replace(
|
||||||
|
'%', '%%')
|
||||||
|
except AttributeError:
|
||||||
|
return str(get_engine().url).replace('%', '%%')
|
||||||
|
|
||||||
|
|
||||||
|
# add your model's MetaData object here
|
||||||
|
# for 'autogenerate' support
|
||||||
|
# from myapp import mymodel
|
||||||
|
# target_metadata = mymodel.Base.metadata
|
||||||
|
config.set_main_option('sqlalchemy.url', get_engine_url())
|
||||||
|
target_db = current_app.extensions['migrate'].db
|
||||||
|
|
||||||
|
# other values from the config, defined by the needs of env.py,
|
||||||
|
# can be acquired:
|
||||||
|
# my_important_option = config.get_main_option("my_important_option")
|
||||||
|
# ... etc.
|
||||||
|
|
||||||
|
|
||||||
|
def get_metadata():
|
||||||
|
if hasattr(target_db, 'metadatas'):
|
||||||
|
return target_db.metadatas[None]
|
||||||
|
return target_db.metadata
|
||||||
|
|
||||||
|
|
||||||
|
def run_migrations_offline():
|
||||||
|
"""Run migrations in 'offline' mode.
|
||||||
|
|
||||||
|
This configures the context with just a URL
|
||||||
|
and not an Engine, though an Engine is acceptable
|
||||||
|
here as well. By skipping the Engine creation
|
||||||
|
we don't even need a DBAPI to be available.
|
||||||
|
|
||||||
|
Calls to context.execute() here emit the given string to the
|
||||||
|
script output.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url = config.get_main_option("sqlalchemy.url")
|
||||||
|
context.configure(
|
||||||
|
url=url, target_metadata=get_metadata(), literal_binds=True
|
||||||
|
)
|
||||||
|
|
||||||
|
with context.begin_transaction():
|
||||||
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
|
def run_migrations_online():
|
||||||
|
"""Run migrations in 'online' mode.
|
||||||
|
|
||||||
|
In this scenario we need to create an Engine
|
||||||
|
and associate a connection with the context.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# this callback is used to prevent an auto-migration from being generated
|
||||||
|
# when there are no changes to the schema
|
||||||
|
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||||
|
def process_revision_directives(context, revision, directives):
|
||||||
|
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||||
|
script = directives[0]
|
||||||
|
if script.upgrade_ops.is_empty():
|
||||||
|
directives[:] = []
|
||||||
|
logger.info('No changes in schema detected.')
|
||||||
|
|
||||||
|
conf_args = current_app.extensions['migrate'].configure_args
|
||||||
|
if conf_args.get("process_revision_directives") is None:
|
||||||
|
conf_args["process_revision_directives"] = process_revision_directives
|
||||||
|
|
||||||
|
connectable = get_engine()
|
||||||
|
|
||||||
|
with connectable.connect() as connection:
|
||||||
|
context.configure(
|
||||||
|
connection=connection,
|
||||||
|
target_metadata=get_metadata(),
|
||||||
|
**conf_args
|
||||||
|
)
|
||||||
|
|
||||||
|
with context.begin_transaction():
|
||||||
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
|
if context.is_offline_mode():
|
||||||
|
run_migrations_offline()
|
||||||
|
else:
|
||||||
|
run_migrations_online()
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
"""${message}
|
||||||
|
|
||||||
|
Revision ID: ${up_revision}
|
||||||
|
Revises: ${down_revision | comma,n}
|
||||||
|
Create Date: ${create_date}
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
${imports if imports else ""}
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = ${repr(up_revision)}
|
||||||
|
down_revision = ${repr(down_revision)}
|
||||||
|
branch_labels = ${repr(branch_labels)}
|
||||||
|
depends_on = ${repr(depends_on)}
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
${upgrades if upgrades else "pass"}
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
${downgrades if downgrades else "pass"}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
"""init databases
|
||||||
|
|
||||||
|
Revision ID: 1b3bc6809b30
|
||||||
|
Revises:
|
||||||
|
Create Date: 2024-08-15 15:09:26.124279
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '1b3bc6809b30'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('log',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('log_user_agent', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_method', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_quest_path', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_ip', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_params', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller_action', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller_id', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('account_id', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('event_name', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('event_content', sa.Text(), nullable=True),
|
||||||
|
sa.Column('operator', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('passenger',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('account', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('password_digest', sa.String(length=2000), nullable=False),
|
||||||
|
sa.Column('id_card_no', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('mobile_no', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('bank_card_no', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('state', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('member_type', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('last_login_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('passenger', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_passenger_account'), ['account'], unique=True)
|
||||||
|
|
||||||
|
op.create_table('station',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('pinyin', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('province', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('city', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('district', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('station', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_station_name'), ['name'], unique=True)
|
||||||
|
|
||||||
|
op.create_table('train',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('train_no', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('departure_station', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('arrival_station', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('departure_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('expiration_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('effective_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('arrival_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('train', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_train_train_no'), ['train_no'], unique=True)
|
||||||
|
|
||||||
|
op.create_table('order',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('order_no', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('price', sa.Numeric(precision=8, scale=2), nullable=True),
|
||||||
|
sa.Column('payment_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('state', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('passenger_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['passenger_id'], ['passenger.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('order_no')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('order', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_order_passenger_id'), ['passenger_id'], unique=False)
|
||||||
|
|
||||||
|
op.create_table('train_station',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('train_no', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('station_name', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('price', sa.Numeric(precision=8, scale=2), nullable=True),
|
||||||
|
sa.Column('arrival_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('departure_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('index', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['station_name'], ['station.name'], ),
|
||||||
|
sa.ForeignKeyConstraint(['train_no'], ['train.train_no'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id', 'train_no', 'station_name')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('train_station', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_train_station_train_no'), ['train_no'], unique=False)
|
||||||
|
|
||||||
|
op.create_table('ticket',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('seat_no', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('seat_class', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('price', sa.Numeric(precision=8, scale=2), nullable=True),
|
||||||
|
sa.Column('state', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('train_no', sa.String(length=120), nullable=False),
|
||||||
|
sa.Column('passenger_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('order_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('from_station', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('to_station', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('date', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('departure_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('arrival_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['order_id'], ['order.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['passenger_id'], ['passenger.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['train_no'], ['train.train_no'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
with op.batch_alter_table('ticket', schema=None) as batch_op:
|
||||||
|
batch_op.create_index(batch_op.f('ix_ticket_order_id'), ['order_id'], unique=False)
|
||||||
|
batch_op.create_index(batch_op.f('ix_ticket_passenger_id'), ['passenger_id'], unique=False)
|
||||||
|
batch_op.create_index(batch_op.f('ix_ticket_train_no'), ['train_no'], unique=False)
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('ticket', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_ticket_train_no'))
|
||||||
|
batch_op.drop_index(batch_op.f('ix_ticket_passenger_id'))
|
||||||
|
batch_op.drop_index(batch_op.f('ix_ticket_order_id'))
|
||||||
|
|
||||||
|
op.drop_table('ticket')
|
||||||
|
with op.batch_alter_table('train_station', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_train_station_train_no'))
|
||||||
|
|
||||||
|
op.drop_table('train_station')
|
||||||
|
with op.batch_alter_table('order', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_order_passenger_id'))
|
||||||
|
|
||||||
|
op.drop_table('order')
|
||||||
|
with op.batch_alter_table('train', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_train_train_no'))
|
||||||
|
|
||||||
|
op.drop_table('train')
|
||||||
|
with op.batch_alter_table('station', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_station_name'))
|
||||||
|
|
||||||
|
op.drop_table('station')
|
||||||
|
with op.batch_alter_table('passenger', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_passenger_account'))
|
||||||
|
|
||||||
|
op.drop_table('passenger')
|
||||||
|
op.drop_table('log')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""remove TrainStation id
|
||||||
|
|
||||||
|
Revision ID: 7866a6e8a75b
|
||||||
|
Revises: 1b3bc6809b30
|
||||||
|
Create Date: 2024-08-15 15:29:40.410360
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '7866a6e8a75b'
|
||||||
|
down_revision = '1b3bc6809b30'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('train_station', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('id')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('train_station', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: b1465436c340
|
||||||
|
Revises: 7866a6e8a75b
|
||||||
|
Create Date: 2025-02-21 16:47:25.383937
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'b1465436c340'
|
||||||
|
down_revision = '7866a6e8a75b'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('log')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('log',
|
||||||
|
sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('log_user_agent', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_method', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_quest_path', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_ip', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_params', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller_action', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('log_controller_id', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('account_id', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('event_name', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('event_content', mysql.TEXT(), nullable=True),
|
||||||
|
sa.Column('operator', mysql.VARCHAR(length=120), nullable=True),
|
||||||
|
sa.Column('created_at', mysql.DATETIME(), nullable=True),
|
||||||
|
sa.Column('updated_at', mysql.DATETIME(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_collate='utf8mb4_0900_ai_ci',
|
||||||
|
mysql_default_charset='utf8mb4',
|
||||||
|
mysql_engine='InnoDB'
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
from .passenger import PassengerPresenter
|
||||||
|
from .station import StationPresenter
|
||||||
|
from .mobile_code import MobileCodePresenter
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
class MobileCodePresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"code": self.data
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
from presenter.ticket import TicketPresenter
|
||||||
|
|
||||||
|
|
||||||
|
class OrderPresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.data.id,
|
||||||
|
"orderNo": self.data.order_no,
|
||||||
|
"price": self.data.price,
|
||||||
|
"state": self.data.state,
|
||||||
|
"paymentTime": self.data.payment_time,
|
||||||
|
"tickets": [TicketPresenter(ticket).as_dict() for ticket in self.data.tickets]
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
class PassengerPresenter:
|
||||||
|
def __init__(self, data, aid_data=None):
|
||||||
|
self.data = data
|
||||||
|
self.aid_data = aid_data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.data.id,
|
||||||
|
"account": self.data.account,
|
||||||
|
"name": self.data.name,
|
||||||
|
"idCardNo": self.data.id_card_no,
|
||||||
|
"mobileNo": self.data.mobile_no,
|
||||||
|
"bankCardNo": self.data.bank_card_no,
|
||||||
|
"state": self.data.state,
|
||||||
|
"memberType": self.data.member_type
|
||||||
|
} | self.aid_data
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class StationPresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.data.id,
|
||||||
|
"name": self.data.name,
|
||||||
|
"pinyin": self.data.pinyin,
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
class TicketPresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.data.id,
|
||||||
|
"seatNo": self.data.seat_no,
|
||||||
|
"seatClass": self.data.seat_class,
|
||||||
|
"price": self.data.price,
|
||||||
|
"state": self.data.state,
|
||||||
|
"trainNo": self.data.train_no,
|
||||||
|
"from": self.data.from_station,
|
||||||
|
"orderNo": self.data.order.order_no,
|
||||||
|
"to": self.data.to_station,
|
||||||
|
"date": self.data.date,
|
||||||
|
"fromTime": self.data.departure_time,
|
||||||
|
"toTime": self.data.arrival_time,
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
from presenter.train_station import TrainStationPresenter
|
||||||
|
|
||||||
|
|
||||||
|
class TrainPresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.data.id,
|
||||||
|
"trainNo": self.data.train_no,
|
||||||
|
"arrTime": self.data.arrival_time,
|
||||||
|
"depTime": self.data.departure_time,
|
||||||
|
"arr": self.data.arrival_station,
|
||||||
|
"dep": self.data.departure_station,
|
||||||
|
"stations": [TrainStationPresenter(station).as_dict() for station in self.data.train_stations]
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
class TrainStationPresenter:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return {
|
||||||
|
"index": self.data.index,
|
||||||
|
"trainNo": self.data.train_no,
|
||||||
|
"name": self.data.station_name,
|
||||||
|
"arrTime": self.data.arrival_time,
|
||||||
|
"depTime": self.data.departure_time,
|
||||||
|
"price": self.data.price,
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
from .response import create_response, StateCode
|
||||||
|
from .server import checkMobile, checkIdCard, checkBankCard
|
||||||
Loading…
Reference in new issue