# Mini-12306 软件系统开发详解 ## 引言 在当今数字化时代,在线票务系统变得越来越重要。Mini-12306 软件系统作为一个简化版的铁路票务系统,涵盖了前后端开发的诸多技术,为开发者提供了一个很好的学习和实践平台。本文将深入剖析 Mini-12306 软件系统的前后端源码,介绍其开发语言、框架、项目结构以及关键功能的实现。 ## 前端开发 ### 开发语言与框架 Mini-12306 前端采用了 HTML、JavaScript 和 CSS 作为基础开发语言,这些是前端开发的基石。同时,项目使用了 Vue2、uni-app 和 uview 等框架来简化开发流程。 - **Vue2**:是一个渐进式 JavaScript 框架,用于构建用户界面。它具有响应式数据绑定、组件化开发等特性,使得代码的可维护性和可扩展性大大提高。 - **uni-app**:是一个使用 Vue.js 开发跨平台应用的前端框架,开发者可以使用一套代码同时发布到多个平台,如小程序、App 等,极大地提高了开发效率。 - **uview**:是一个基于 uni-app 的 UI 框架,提供了丰富的组件和样式,方便开发者快速搭建界面。 ### 项目结构与配置 项目的根目录下有 `.gitignore` 文件,用于指定不需要被 Git 跟踪的文件和文件夹,如 `node_modules`、`dist` 等。`package-lock.json` 文件记录了项目依赖的具体版本信息,确保项目在不同环境下的一致性。 ```json { "name": "Mini-12306", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { "dayjs": "^1.11.11", "uview-ui": "^2.0.36" } }, "node_modules/dayjs": { "version": "1.11.11", "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz", "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/uview-ui": { "version": "2.0.36", "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.36.tgz", "integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA==", "engines": { "HBuilderX": "^3.1.0" } } } } ``` ### 页面与接口实现 以 `QueryTrainView.vue` 页面为例,该页面实现了列车查询功能。用户可以选择出发地、目的地和日期,页面会根据用户的选择调用 `apiTrains.get` 接口获取列车信息,并将结果展示给用户。 ```vue <template> <!-- 页面模板代码 --> </template> <script> import apiTrains from "@/api/trains.js"; export default { data() { return { allowableDates: [], from: "", to: "", date: "", trains: [], loading: false }; }, computed: { queryTrainParams() { return { from: this.from, to: this.to, date: this.date }; } }, watch: { queryTrainParams(val) { this.handleQueryTrain(val); } }, onLoad(query) { const { from, to, date } = query; this.from = decodeURIComponent(from); this.to = decodeURIComponent(to); this.date = this.$u.dayjs(decodeURIComponent(date)).format(); this.initAllowableDates(); }, onReady() { uni.setNavigationBarTitle({ title: `${this.from} > ${this.to}` }); uni.setNavigationBarColor({ backgroundColor: "#3c9cff", frontColor: "#ffffff" }); }, methods: { initAllowableDates() { for (let i = 0; i < 15; i += 1) { this.allowableDates.push(this.$u.dayjs().add(i, "day").format()); } }, handleChangeDate(date) { this.date = date; }, handleQueryTrain(params) { if (!params || !params.from || !params.to || !params.date) { uni.switchTab({ url: "/pages/HomeView/HomeView" }); } uni.showLoading({ title: "正在加载", mask: true }); this.loading = true; apiTrains .get({ from: params.from, to: params.to, date: params.date }) .then((res) => { this.trains = res.data.map((trn) => ({ ...trn, query: this.formatTrainToQuery(trn, params.from, params.to) })); }) .catch(() => {}) .then(() => { uni.hideLoading(); this.loading = false; }); }, handleToByTicket(train) { if (!this.$store.state.auth.id) { uni.navigateTo({ url: "/pages/LoginView/LoginView" }); return; } uni.navigateTo({ url: `/pages/BuyTicketView/BuyTicketView?train_no=${encodeURIComponent( train.trainNo )}&from=${encodeURIComponent( train.query.from )}&from_time=${encodeURIComponent( train.query.fromTime )}&to=${encodeURIComponent( train.query.to )}&to_time=${encodeURIComponent( train.query.toTime )}&date=${encodeURIComponent(this.date)}` }); }, formatTrainToQuery(train, from, to) { const stations = train.stations; const fromIndex = stations.findIndex((stn) => stn.name === from); const toIndex = stations.findIndex((stn) => stn.name === to); let price = 0; for (let i = fromIndex; i <= toIndex; i += 1) { price += stations[i].price; } return { from: from, fromTime: stations[fromIndex].depTime, to: to, toTime: stations[toIndex].arrTime }; } } }; </script> <style scoped lang="scss"> /* 页面样式代码 */ </style> ``` ## 后端开发 ### 开发语言与框架 后端采用 Python 语言,使用了 Flask 框架来构建 Web 应用。Flask 是一个轻量级的 Web 框架,具有简洁、灵活的特点,适合快速开发小型项目。同时,项目还使用了 Flask-SQLAlchemy 进行数据库操作,Flask-JWT-Extended 进行身份验证等。 ### 项目结构与配置 项目的目录结构清晰,主要包括 `app` 目录(存放主要接口业务代码)、`logs` 目录(存放日志文件)、`migrations` 目录(存放数据库迁移文件)等。 ```plaintext Mini-12306 -- app //主要接口业务代码 ---- models //定义了数据库表结构与抽象类方法 -- logs //日志存储 -- migrations //执行迁移后的数据库版本文件,请查看Flask-Migrate使用方法。 -- presenter //渲染文件,用于数据序列化 -- utils //工具包 ---- response.py //定义返回数据结构及定义状态码 -- Dockerfile //docker容器化文件 -- docker-compose.yml //容器编排文件 ``` ### 数据库设计与迁移 项目使用 PostgreSQL 作为数据库,通过 SQLAlchemy 进行数据库操作。`migrations` 目录下的文件记录了数据库的迁移历史,使用 Flask-Migrate 可以方便地管理数据库迁移。 ```python # 初始化 Alembic 目录 flask db init # 生成迁移脚本 flask db migrate -m "Initial migration" # 执行迁移 flask db upgrade ``` ### 接口实现 以用户注册和登录接口为例,展示了后端接口的实现方式。用户注册接口 `register_bp.route('/register')` 会验证用户输入的信息,如账号、密码、手机号码等,若信息合法则创建新用户并返回令牌。用户登录接口 `login_bp.route('/login')` 会验证用户的账号和密码,若验证通过则返回令牌。 ```python # app/passenger_manager.py from flask import Blueprint, request, jsonify from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity from app import redis_client, LogService from app.models.passenger_lib import Passenger, isAvailable from presenter import PassengerPresenter from utils import StateCode, create_response, checkMobile, checkIdCard, checkBankCard register_bp = Blueprint('register', __name__) @register_bp.route('/register', methods=['POST']) def register(): data = request.json account = data.get('account') password = data.get('password') mobile_no = data.get('mobileNo') mobile_code = data.get('mobileCode') id_card_no = data.get('idCardNo') bank_card_no = data.get('bankCard') if not account or not password: return jsonify(create_response(StateCode.PARAMS_ERROR)), 400 if not checkMobile(mobile_no): return jsonify(create_response(StateCode.MOBILE_ERROR)), 400 if not verifyCode(mobile_no, mobile_code): return jsonify(create_response(StateCode.MOBILE_CODE_ERROR)), 400 if not checkIdCard(id_card_no): return jsonify(create_response(StateCode.ID_CARD_ERROR)), 400 if isAvailable(account): return jsonify(create_response(StateCode.USER_ALREADY_EXISTS)), 400 if not checkBankCard(bank_card_no): return jsonify(create_response(StateCode.BANK_CARD_ERROR)), 400 new_passenger = Passenger.create(data=data) access_token = create_access_token(identity=new_passenger.id) user_presenter = PassengerPresenter(new_passenger, {"token": access_token}).as_dict() LogService.log() return jsonify(create_response(StateCode.SUCCESS, data=user_presenter)), 200 # app/login_manager.py @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=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 ``` ## 总结 Mini-12306 软件系统是一个完整的前后端项目,涵盖了前端页面开发、后端接口实现、数据库设计与管理等多个方面。通过学习和分析这个项目,开发者可以深入了解如何使用 Vue2、uni-app、Flask 等框架进行前后端开发,以及如何使用 SQLAlchemy 进行数据库操作。同时,项目中使用的 Docker 和 Flask-Migrate 等工具也为项目的部署和维护提供了便利。希望本文对开发者在学习和实践 Web 开发方面有所帮助。