仿12306购票系统(3)

前面完成了乘车人登录功能的实现,本篇主要是控制台方面的管理

对于整体的控制台的设计,为了能够快速的检验,不进行登录拦截,在控制台的这个模块的controller层增加admin,以及在登录界面的拦截器排除掉admin.

车站

即都有那些车站

create table `station` (
    `id` bigint not null comment 'id',
     `name` varchar(20) not null comment '站名',
     `name_pinyin` varchar(50) not null comment '站名拼音',
     `name_py` varchar(50) not null comment '站名拼音首字母',
     `create_time` datetime(3) comment '新增时间',
     `update_time` datetime(3) comment '修改时间',
     primary key (`id`),
     unique key `name_unique` (`name`)
) engine=innodb default charset=utf8mb4 comment='车站';

首先,使用bigint类型的id作为主键,可以支持大量的车站记录。使用唯一标识进行每个车站的管理,便于数据库管理和关联其他表。为了方便查询车站,添加了站名,站名拼音和站名拼音首字母。

火车基础数据的管理

就是一辆火车的数据,这里设计如下

drop table if exists `train`;
create table `train` (
  `id` bigint not null comment 'id',
  `code` varchar(20) not null comment '车次编号',
  `type` char(1) not null comment '车次类型|枚举[TrainTypeEnum]',
  `start` varchar(20) not null comment '始发站',
  `start_pinyin` varchar(50) not null comment '始发站拼音',
  `start_time` time not null comment '出发时间',
  `end` varchar(20) not null comment '终点站',
  `end_pinyin` varchar(50) not null comment '终点站拼音',
  `end_time` time not null comment '到站时间',
  `create_time` datetime(3) comment '新增时间',
  `update_time` datetime(3) comment '修改时间',
  primary key (`id`),
  unique key `code_unique` (`code`)
) engine=innodb default charset=utf8mb4 comment='车次';

其中的车次类型是因为火车不仅仅有动车,还有高铁,普通列车等。可以仿照乘客表的乘客类型来进行车次车次类型的设计。为了计算不同车次的票价,在枚举类中为不同的车次类型增加系数,例如,高铁为1.2,表示票价=1.2*每公里单价*公里,实际上可能更加的复杂。这里只是基础讨论功能的实现。看上面的事件类型发现,出发时间,到站时间和新增时间与修改时间的类型不同,其中datatime类型非常适合需要同时记录具体哪一天的什么时候发生的场景。time类型记录事件发生的具体时间。这样设计是因为此时是基础的数据功能,并不是每日的车次,火车每天出发的时间是一定的,因此不需要记录具体的日期。

为了是选择时间,而不是手动的输入时间,可以在前端增加控件,如果是time类型,增加a-time-picker,如果是time类型,增加a-datepicker,为了方便,可以在自定义的代码生成器实现。

<#elseif field.javaType=='Date'>
          <#if field.type=='time'>
        <a-time-picker v-model:value="${domain}.${field.nameHump}" valueFormat="HH:mm:ss" placeholder="请选择时间" />
          <#elseif field.type=='date'>
        <a-date-picker v-model:value="${domain}.${field.nameHump}" valueFormat="YYYY-MM-DD" placeholder="请选择日期" />
          <#else>
        <a-date-picker v-model:value="${domain}.${field.nameHump}" valueFormat="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择日期" />
          </#if>

火车车站的管理

就是车次的车站,一列火车要经过那些车站。

create table `train_station` (
  `id` bigint not null comment 'id',
  `train_code` varchar(20) not null comment '车次编号',
  `index` int not null comment '站序',
  `name` varchar(20) not null comment '站名',
  `name_pinyin` varchar(50) not null comment '站名拼音',
  `in_time` time comment '进站时间',
  `out_time` time comment '出站时间',
  `stop_time` time comment '停站时长',
  `km` decimal(8, 2) not null comment '里程(公里)|从上一站到本站的距离',
  `create_time` datetime(3) comment '新增时间',
  `update_time` datetime(3) comment '修改时间',
  primary key (`id`),
  unique key `train_code_index_unique` (`train_code`, `index`),
  unique key `train_code_name_unique` (`train_code`, `name`)
) engine=innodb default charset=utf8mb4 comment='火车车站';

其中的车次编号和某辆火车进行关联,站序指的是从始发站到终点站经过的车站顺序的排列。停站时常是可以通过进站和出站时间进行计算,为了方便查询,将id作为主键。在实际的情况中,一辆火车从起点到终点不会经过某个站两次,因此需要增加唯一键来进行数据的检验。如何将这两张表进行关联呢,在train表中一个唯一键code,使用唯一键进行关联,方便业务上的一些功能,train_code的起名就是和train这张表的code字段进行关联。当然如果没有设计唯一键,可以考虑使用id进行关联。

火车车厢

create table `train_carriage` (
  `id` bigint not null comment 'id',
  `train_code` varchar(20) not null comment '车次编号',
  `index` int not null comment '厢号',
  `seat_type` char(1) not null comment '座位类型|枚举[SeatTypeEnum]',
  `seat_count` int not null comment '座位数',
  `row_count` int not null comment '排数',
  `col_count` int not null comment '列数',
  `create_time` datetime(3) comment '新增时间',
  `update_time` datetime(3) comment '修改时间',
  unique key `train_code_index_unique` (`train_code`, `index`),
  primary key (`id`)
) engine=innodb default charset=utf8mb4 comment='火车车厢';

每一列车厢都要对应一列火车,因此需要根火车表进行关联,即train_index,由于不可能发生一列火车有两个相同编号的车厢,因此需要进行车次编号和厢号的关联。由于不同的车厢有不同的作为类型,因此可以将其进行枚举。

座位表

        对于一辆火车来说,没有座位表是不完整的,由于座位属于某个车次,因此需要和火车进行关联,座位应该属于某个车厢,因此应该和车厢有所关联。同车厢内,每个座位可以按照行和列进行唯一的查找,每一个车厢都是从123往后排的,因此需要一个同车厢坐序。

        在进行枚举座位行类中,设定一等座一排四个,二等座一排5个,增加code和desc,最后要增加一个type,来描述是什么类型。这个type就是对于的SeatType的枚举类,假设传入一个一等座,可以根据type等于1查出一等座对应的列,这样前端做一些下拉框就比较方便,知道一等座,就能知道有那些可以选择。

    /**
     * 根据车箱的座位类型,筛选出所有的列,比如车箱类型是一等座,则筛选出columnList={ACDF}
     */
    public static List<SeatColEnum> getColsByType(String seatType) {
        List<SeatColEnum> colList = new ArrayList<>();
        EnumSet<SeatColEnum> seatColEnums = EnumSet.allOf(SeatColEnum.class);
        for (SeatColEnum anEnum : seatColEnums) {
            if (seatType.equals(anEnum.getType())) {
                colList.add(anEnum);
            }
        }
        return colList;
    }

优化

输入车站名称后自动显示拼音,前端可以引入"pinyin-pro"组件

watch(()=> station.value.name, () => {
      if (Tool.isNotEmpty(station.value.name)) {
        station.value.namePinyin = pinyin(station.value.name, {
          toneType: 'none'}).replaceAll(" ", "");
        station.value.namePy = pinyin(station.value.name, {
          pattern: 'first',
          toneType: 'none'}).replaceAll(" ","");
      }
    },{immediate: true});

利用watch函数监听响应式数据的变化。监听的是station.value.name的变化,并在变化时更新station.value.namePinyinstation.value.namePy两个属性。第一个参数是要监听的数据,第二个参数是回调函数,表示如果发生变换,立即执行回调函数

火车车站的车次编号应该座位下拉框:首先后端提供一个接口查询所有的车次,然后前端界面的更改。对于查询接口来说,不需要参数,将查到的车站按照降序排列,以List形式进行返回。

    public List<TrainQueryResp> queryAll() {
        TrainExample trainExample = new TrainExample();
        trainExample.setOrderByClause("code desc");
        List<Train> trainList= trainMapper.selectByExample(trainExample);
        return BeanUtil.copyToList(trainList, TrainQueryResp.class);
    }
    
        @GetMapping("/query-all")
    public CommonResp<List<TrainQueryResp>> queryList() {
        List<TrainQueryResp> list = trainService.queryAll();
        return new CommonResp<>(list);
    }

然后前端去拿到后端的数据

const queryTrainCode = () => {
      axios.get("/business/admin/train/query-all").then((response) => {
        let data = response.data;
        if (data.success) {
          console.log(data.content);
        } else {
          notification.error({description: data.message});
        }
      });
    };
        <a-select v-model:value="trainStation.trainCode" show-search
            :filterOption="filterTrainCodeOption">
          <a-select-option v-for="item in trains" :key="item.code" :value="item.code" :label="item.code + item.start + item.end">
            {{item.code}} | {{item.start}} ~ {{item.end}}
          </a-select-option>
        </a-select>

    const filterTrainCodeOption = (input, option) => {
      console.log(input, option)
      return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
    };
  • v-model:value="trainStation.trainCode": 将选择器的值绑定到trainStation对象的trainCode属性上,当选择一个选项时,trainStation.trainCode会自动更新为所选的值。
  • show-search: 启用搜索框,允许通过输入来过滤列表中的选项。
  • :filterOption="filterTrainCodeOption": 使用自定义的过滤函数filterTrainCodeOption来决定哪些选项应该在用户输入时显示。
  • v-for="item in trains": 遍历trains数组
  • :key="item.code": 为每个选项指定一个唯一的键,这里使用的是列车代码。
  • :value="item.code": 设置选项的值为列车代码,这将与v-model绑定的值对应。
  • :label="item.code + item.start + item.end": 定义选项的标签,这里是将列车代码、始发站和终点站的信息组合起来作为选项的显示文本。
  • {{item.code}} | {{item.start}} ~ {{item.end}}: 更好地显示
  • filterTrainCodeOption筛选列车选项的函数

为了方便,可以将车次制作成一个组件,然后引入到各个模块,然后车站也可以做出下拉框组件,引入到各个模块。限于篇幅,这里不在赘述。

查询

        由于火车各部分的数据量庞大,如果将所有数据全部显示,将会给系统带来显著的性能压力,并可能影响体验。因此,引入了条件查询机制,以便根据用户的具体需求动态加载和展示相关数据,从而优化性能并提升系统的响应速度。

对于后端的车站查询接口来说,如果是传入的train_code不为空,就根据请求参数得到的trainCode来进行查询,座位和车厢同理,只需要修改service层代码,以及增加参数的请求类型。

if(ObjectUtil.isNotEmpty(req.getTrainCode())) {
    criteria.andTrainCodeEqualTo(req.getTrainCode());
}
        
package com.month.train.business.req;

import com.month.train.common.req.PageReq;

public class TrainSeatQueryReq extends PageReq {

    private String trainCode;

    public String getTrainCode() {
        return trainCode;
    }

    public void setTrainCode(String trainCode) {
        this.trainCode = trainCode;
    }

    @Override
    public String toString() {
        return "TrainSeatQueryReq{" +
                "trainCode='" + trainCode + '\'' +
                "} " + super.toString();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978267.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

74道高级Java面试合集,java开发模式面试题

前言 今天我们来说说Redis为什么高性能&#xff1f;如何做高可用&#xff1f; Redis为什么这么快&#xff1f; Redis是单线程的&#xff0c;避免了多线程的上下文切换和并发控制开销&#xff1b;Redis大部分操作时基于内存&#xff0c;读写数据不需要磁盘I/O&#xff0c;所以速…

【江科协-STM32】5. 输出比较

1. 输出比较简介 OC(Output Compare)输出比较。 输出比较可以通过CNT&#xff08;CNT计数器&#xff09;与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形。 :::tip CNT计数器是正向计数器。它只能正向累…

轻量级日志管理平台Grafana Loki

文章目录 轻量级日志管理平台Grafana Loki背景什么是Loki为什么使用 Grafana Loki&#xff1f;架构Log Storage Grafana部署使用基于 Docker Compose 安装 LokiMinIO K8s集群部署Loki采集Helm 部署方式和案例 参考 轻量级日志管理平台Grafana Loki 背景 在微服务以及云原生时…

使用 Postman 访问 Keycloak 端点

1. 引言 在本教程中&#xff0c;我们将首先快速回顾 OAuth 2.0、OpenID 和 Keycloak。然后&#xff0c;我们将了解 Keycloak REST API 以及如何在 Postman 中调用它们。 2. OAuth 2.0 OAuth 2.0 是一个授权框架&#xff0c;它允许经过身份验证的用户通过令牌向第三方授予访问…

WEB1~6通杀

##解题思路 这六道题&#xff0c;通杀了&#xff0c;只因为是PHP的特性 来&#xff0c;看web6&#xff0c;过滤最复杂的正则&#xff0c;而且不能解析成大于999的值&#xff0c;但是&#xff0c;php是弱类型的语言&#xff0c;我只要输入任意字符数字&#xff0c;最终值就为0&…

I2C协议简介:串行通信的关键技术

目录 一、总线通信基本概念 二、I2C总线协议介绍 1. 时序图解析 &#xff08;1&#xff09;起始信号 &#xff08;2&#xff09;应答信号 &#xff08;3&#xff09;终止信号 &#xff08;4&#xff09;设备地址 &#xff08;5&#xff09;I2C传输方法 ​编辑 &#…

第二十四:5.2【搭建 pinia 环境】axios 异步调用数据

第一步安装&#xff1a;npm install pinia 第二步&#xff1a;操作src/main.ts 改变里面的值的信息&#xff1a; <div class"count"><h2>当前求和为&#xff1a;{{ sum }}</h2><select v-model.number"n">  // .number 这里是…

Web漏洞——命令注入漏洞学习

一、什么是命令注入漏洞 想象一下&#xff0c;你家有一个智能管家机器人。这个机器人可以通过你发出的指令来完成各种任务&#xff0c;比如“请打开电视机、播放音乐、开灯等等”。你只需要对它说&#xff1a;“请打开电视”&#xff0c;它就会去执行这个任务。但是&#xff0…

大模型自动提示优化(APO)综述笔记

自大型语言模型&#xff08;LLMs&#xff09;出现以来&#xff0c;提示工程一直是各种自然语言处理&#xff08;NLP&#xff09;任务中激发期望响应的关键步骤。然而&#xff0c;由于模型的快速进步、任务的多样性和相关最佳实践的变化&#xff0c;提示工程对最终用户来说仍然是…

快速排序(详解)c++

快速排序(Quick Sort)&#xff0c;既然敢起这样的名字&#xff0c;说明它是常⻅排序算法中较为优秀的。事实上&#xff0c;在很多情况下&#xff0c;快排确实是效率较⾼的算法&#xff1b;c的排序是以快排为基础&#xff0c;再加上堆排和插入排序做优化实现的&#xff0c;我们这…

【工具变量】公司企业数字领导力(2004-2023年)

数据简介&#xff1a;企业数字化领导力是指在数字经济时代&#xff0c;领导者通过战略性地使用数字资产、引领组织变革&#xff0c;使企业在数字化环境中获得持续成功的能力。对于上市公司而言&#xff0c;这种领导力尤为重要&#xff0c;因为它直接关系到企业的战略方向、市场…

浅谈新能源汽车充电桩建设问题分析及解决方案

摘要&#xff1a; 在全球倡导低碳减排的大背景下&#xff0c;新能源成为热门行业在全球范围内得以开展。汽车尾气排放会在一定程度上加重温室效应&#xff0c;并且化石能源的日渐紧缺也迫切对新能源汽车发展提出新要求。现阶段的新能源汽车以电力汽车为主&#xff0c;与燃油汽…

seacmsv9报错注入

1、seacms的介绍 ​ seacms中文名&#xff1a;海洋影视管理系统。是一个采用了php5mysql架构的影视网站框架&#xff0c;因此&#xff0c;如果该框架有漏洞&#xff0c;那使用了该框架的各个网站都会有相同问题。 2、源码的分析 漏洞的部分源码如下&#xff1a; <?php …

python学习四

python运算符与表达式 表达式: Python中的表达式是一种计算结果的代码片段。它可以包 含变量、运算符、常数和函数调用,用于执行各种数学、逻辑 和功能操作 算术运算符: 比较(关系)运算符: 赋值运算符: 逻辑运算符: 位运算符: 成员运算符: 身份运算符 <

Nginx面试宝典【刷题系列】

文章目录 1、nginx是如何实现高并发的&#xff1f;2、Nginx如何处理HTTP请求&#xff1f;3、使用“反向代理服务器”的优点是什么?4、列举Nginx服务器的最佳用途。5、Nginx服务器上的Master和Worker进程分别是什么?6、什么是C10K问题?7、请陈述stub_status和sub_filter指令的…

数字可调控开关电源设计(论文+源码)

1 设计要求 在本次数字可调控开关电源设计过程中&#xff0c;对关键参数设定如下&#xff1a; &#xff08;1&#xff09;输入电压&#xff1a;DC24-26V,输出电压&#xff1a;12-24&#xff08;可调&#xff09;&#xff1b; &#xff08;2&#xff09;输出电压误差&#xf…

清华大学《AIGC发展研究3.0》

大家好&#xff0c;我是吾鳴。 AIGC已经爆火好长一段时间了&#xff0c;特别是DeepSeek的爆火&#xff0c;直接让很多之前没有体会过推理模型的人可以免费的使用上推理模型&#xff0c;同时DeepSeek产品形态也是全球首创&#xff0c;就是直接把AI的思考过程展示给你看&#xff…

模型和数据集的平台之在Hugging Face上进行模型下载、上传以及创建专属Space

模型下载 步骤&#xff1a; 注册Hugging Face平台 https://huggingface.co/ 新建一个hf_download_josn.py 文件 touch hf_download_josn.py 编写hf_download_josn.py文件 import os from huggingface_hub import hf_hub_download# 指定模型标识符 repo_id "inter…

脚本无法获取响应主体(原因:CORS Missing Allow Credentials)

背景&#xff1a; 前端的端口号8080&#xff0c;后端8000。需在前端向后端传一个参数&#xff0c;让后端访问数据库去检测此参数是否出现过。涉及跨域请求&#xff0c;一直有这个bug是404文件找不到。 在修改过程当中不小心删除了一段代码&#xff0c;出现了这个bug&#xff…

C#实现本地AI聊天功能(Deepseek R1及其他模型)。

前言 1、C#实现本地AI聊天功能 WPFOllamaSharpe实现本地聊天功能,可以选择使用Deepseek 及其他模型。 2、此程序默认你已经安装好了Ollama。 在运行前需要线安装好Ollama,如何安装请自行搜索 Ollama下载地址&#xff1a; https://ollama.org.cn Ollama模型下载地址&#xf…