Compare commits
2 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a1d0fe9407 | 4 months ago |
|
|
4620a275d1 | 4 months ago |
@ -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,10 @@
|
||||
# 从 app 模块导入 db 对象,不过该导入未被使用,后续可考虑移除
|
||||
from app import db
|
||||
# 从当前包的 order_lib 模块导入 Order 类
|
||||
from .order_lib import Order
|
||||
# 从当前包的 passenger_lib 模块导入 Passenger 类
|
||||
from .passenger_lib import Passenger
|
||||
# 从当前包的 station_lib 模块导入 Station 类
|
||||
from .station_lib import Station
|
||||
# 从当前包的 train_lib 模块导入 Train 类
|
||||
from .train_lib import Train
|
||||
@ -0,0 +1,40 @@
|
||||
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:
|
||||
@ -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,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,13 @@
|
||||
# myapp.py
|
||||
# 从 app 模块导入 create_app 函数和 LogService 类
|
||||
from app import create_app, LogService
|
||||
# 从 utils 模块导入 response
|
||||
from utils import response
|
||||
|
||||
# 调用 create_app 函数创建 Flask 应用实例
|
||||
app = create_app()
|
||||
|
||||
# 当脚本作为主程序运行时
|
||||
if __name__ == "__main__":
|
||||
# 以调试模式运行 Flask 应用
|
||||
app.run(debug=True)
|
||||
@ -0,0 +1,12 @@
|
||||
# 从当前包的 passenger 模块中导入 PassengerPresenter 类
|
||||
# PassengerPresenter 类可能用于将乘客相关的数据进行处理和展示,
|
||||
# 例如将数据库中的乘客数据转换为适合前端展示的格式
|
||||
from .passenger import PassengerPresenter
|
||||
# 从当前包的 station 模块中导入 StationPresenter 类
|
||||
# StationPresenter 类可能用于处理和展示站点相关的数据,
|
||||
# 比如将站点信息从数据库模型转换为易于使用的字典形式
|
||||
from .station import StationPresenter
|
||||
# 从当前包的 mobile_code 模块中导入 MobileCodePresenter 类
|
||||
# MobileCodePresenter 类可能用于处理和展示手机验证码相关的数据,
|
||||
# 例如将验证码数据进行格式化,以便在接口中返回给客户端
|
||||
from .mobile_code import MobileCodePresenter
|
||||
@ -0,0 +1,21 @@
|
||||
Flask~=3.0.3
|
||||
Flask-SQLAlchemy
|
||||
psycopg2-binary
|
||||
PyJWT
|
||||
Flask-Migrate
|
||||
itsdangerous
|
||||
redis~=5.0.8
|
||||
Flask-JWT-Extended
|
||||
pypinyin~=0.52.0
|
||||
Werkzeug~=3.0.3
|
||||
SQLAlchemy~=2.0.32
|
||||
alembic~=1.13.2
|
||||
python-dateutil
|
||||
requests
|
||||
gunicorn==22.0.0
|
||||
Levenshtein==0.25.1
|
||||
munkres==1.1.4
|
||||
argparse==1.4.0
|
||||
flask-cors==4.0.1
|
||||
loguru
|
||||
iso8601
|
||||
@ -0,0 +1,9 @@
|
||||
# 从当前包的 response 模块中导入 create_response 函数和 StateCode 类
|
||||
# create_response 函数可能用于创建统一格式的响应数据,方便接口返回规范的数据
|
||||
# StateCode 类可能用于定义不同的状态码,以便在响应中明确表示操作结果
|
||||
from .response import create_response, StateCode
|
||||
# 从当前包的 server 模块中导入三个检查函数
|
||||
# checkMobile 函数可能用于检查手机号码的格式是否正确
|
||||
# checkIdCard 函数可能用于检查身份证号码的格式和有效性
|
||||
# checkBankCard 函数可能用于检查银行卡号码的格式和有效性
|
||||
from .server import checkMobile, checkIdCard, checkBankCard
|
||||
Loading…
Reference in new issue