【开源项目--稻草】Day06

news2024/11/23 1:18:02

【开源项目--稻草】Day06

  • 1. 学生提问与解答功能
  • 2. 显示create.html
    • 2.1 HomeController中代码
    • 2.2 复用网页的标签导航条
  • 3. 创建问题发布界面
    • 3.1 富文本编辑器
  • 4.多选下列框
  • 5.动态加载所有标签和老师
  • 6. 发布问题的业务处理

1. 学生提问与解答功能

在这里插入图片描述
学生提问:

提问时指定标签和回答问题的老师

讲师回复:

指定讲师登录系统后可以对学员的提问进行回复

评论:

学员收到讲师回复后可以对回复进行评论(追问)

讲课也可以进行评论(追答或补充)

问题状态:

学生刚提问时为:未回复

讲师回复后为:已回复

问题解决后为:已解决

  • 问题怎么能称为解决?
  1. 学员标记为解决状态
  2. 讲师可以将问题标记为解决
  3. 问题超过一定时间,自动解决

我们先开发的模块是学员的问题发布功能
在这里插入图片描述

2. 显示create.html

将static/question/create.html

复制到

templates/question/create.html

并编写控制器代码显示这个页面

2.1 HomeController中代码

   // 显示学生问题发布页面
    @GetMapping("/question/create.html")
    public ModelAndView createQuestion(){
        //templates/question/create.html
        return new ModelAndView("question/create");
    }

2.2 复用网页的标签导航条

我们在index.html页面中已经开发过显示数据库中所有标签到页面的导航条中的代码

现在create.html又需要这样的功能,难道我们要再开发一次吗? 显然不是的

我们可以使用Thymeleaf提供的fragment模板来替换当前页面的内容

使用步骤

步骤1:

定义模板

在index.html页面中,将要复用的html区域用特定标签标记

th:fragment=“xxx”

<div class="container-fluid"  th:fragment="tags_nav" >
    <!-- 代码略 -->
</div>

步骤2:

套用模板

现在是create.html需要复用代码,所以是这个页面套用模板

th:replace="xxx"来套用

保证页面支持th:的写法不报错

<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">

套用模板

<div class="container-fluid" th:replace="index::tags_nav" >
  <div class="nav font-weight-light">
  <!-- 代码略 -->
  </div>
</div>

其中th:replace="index::tags_nav"的意思是

用index.html页面中名为tags_nav的模板中的代码替换掉当前编写套用标记的html标签

最后在代码临结束之前,引入ajax和Vue代码

</body>
<script src="../js/utils.js"></script>
<script src="../js/tags_nav.js"></script>
</html>

3. 创建问题发布界面

3.1 富文本编辑器

富文本编辑器适用于那些需要格式甚至是图片的用户输入需求

这样的编辑器都是基于标签的

只是在这个标签的基础上添加了很多js代码或相关插件的实现,我们无需手动开发

市面上有很多功能全面的免费的富文本编辑器工具,其中比较流行的就是我们使用的这个

summernote官方网站是:www.summernote.org

下载它的支持后再页面上编写如下代码引入样式和js文件

<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../bower_components/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../bower_components/summernote/dist/summernote-bs4.min.css"><script src="../bower_components/jquery/dist/jquery.min.js"></script>
<script src="../bower_components/popper.js/dist/umd/popper.min.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../bower_components/polyfill/dist/polyfill.min.js"></script>
<script src="../bower_components/summernote/dist/summernote-bs4.js"></script>
<script src="../bower_components/summernote/dist/lang/summernote-zh-CN.min.js"></script>

在页面中需要富文本编辑器的位置编写如下代码

<textarea name="content" id="summernote"></textarea>

最终通过编写js代码来开启这个编辑器的效果

<script>
    $(document).ready(function() {
        $('#summernote').summernote({
            height: 300,  //高度
            tabsize: 2,   //tab大小
            lang: 'zh-CN',//中文支持
            placeholder: '请输入问题的详细描述...'
        });
    });
</script>

一般这个代码在页面最后位置

4.多选下列框

网页中的下拉列表框是一个能够多选,并且有选中后样式的功能的控件

这个控件是由Vue提供的插件Vue-Select实现的

官方网站是 https://vue-select.org/

依赖JQuery同时也依赖Vue核心的js

除此之外还需要引入一些依赖

<link rel="stylesheet" 
  href="../bower_components/vue-select/dist/vue-select.css">
<script src="../bower_components/vue/dist/vue.js"></script>
<script src="../bower_components/vue-select/dist/vue-select.js"></script>

在这里插入图片描述
在create.html的form表单中找到选择标签和老师的下拉框

将他们的代码修改为:

<!-- 这个id是自己添加的!!!注意!!!!  -->
<div class="col-8" id="createQuestionApp">
      <h4 class="border-bottom m-2 p-2 font-weight-light"><i class="fa fa-question-circle-o" aria-hidden="true"></i>
        填写问题</h4>
      <form >
        <div class="form-group">
          <label for="title">标题:</label>
          <input type="text" class="form-control" id="title" name="title" placeholder="请填写标题3~50字符"
                 pattern="^.{3,50}$" required v-model="title">
        </div>
        <div class="form-group">
          <label >请至少选择一个标签:</label>
          <v-select multiple required v-bind:options="tags"
          v-model="selectedTags" placeholder="请选择问题的标签"
          >
          </v-select>
        </div>
        <div class="form-group">
          <label >请选择老师:</label>
          <v-select multiple required
                    v-bind:options="teachers"
                    v-model="selectedTeachers"
                    placeholder="请选择回答的老师"
          >
          </v-select>
        </div>
        <div class="form-group">
          <!--富文本编辑器 start-->
          <label for="summernote">问题正文</label>
          <textarea name="content" id="summernote"></textarea>
          <!--富文本编辑器 end-->
        </div>
        <button type="submit" class="btn btn-primary mt-3">提交问题</button>
      </form>
    </div>

上面表单修改完成后,js文件中指定createQuestion.js引用添加依赖

</body>
<script src="../js/utils.js"></script>
<script src="../js/tags_nav.js"></script>
<script src="../js/createQuestion.js"></script>
</html>

createQuestion.js文件中的内容

不连接数据库可以写为:

Vue.component('v-select', VueSelect.VueSelect);
let createQuestionApp = new Vue({
    el:'#createQuestionApp',
    data:{
        title:'',
        selectedTags:[],
        tags:['Java基础','Java OOP', 'Java SE'],
        selectedTeachers:[],
        teachers:['范传奇', '王克晶''刘国斌']
    }
});

测试可以发现,我们成功的可以选择做个标签和老师了

下面的工作就是从数据库加载所有标签和老师

5.动态加载所有标签和老师

动态加载所有标签的实现非常简单,因为我们直接可以调用现成的控制器方法

返回所有Tag的集合

createQuestion.js中编写代码如下

//启动v-select标签
Vue.component("v-select", VueSelect.VueSelect);
let createQuestionApp = new Vue({
    el: "#createQuestionApp",
    data: {
        title:"",
        selectedTags:[],
        tags:[],
        selectedTeachers:[],
        teachers:["苍老师","范老师","克晶老师"]
    },
    methods: {
        loadTags:function(){
            $.ajax({
                url:"/v1/tags",
                method:"get",
                success:function(r){
                    console.log(r);
                    if(r.code==OK){
                        let list=r.data;//获得所有标签数组
                        //list=[{id:1,name:"java基础"},{...},{...}]
                        let tags=[];
                        for(let i=0;i<list.length;i++){
                            //push方法表示向这个数组的最后位置添加元素
                            //效果和java中list的add方法一致
                            tags.push(list[i].name);
                        }
                        console.log(tags);
                        createQuestionApp.tags=tags;
                    }
                }
            });
        }
    },
    created:function(){
        this.loadTags();
    }
});

动态加载所有老师

实现步骤

步骤1:

添加业务逻辑层接口方法IUserService

	// 查询所有老师用户的方法
    List<User> getMasters();

步骤2:

实现这个业务逻辑层接口的方法UserServiceImpl

    @Override
    public List<User> getMasters() {
        QueryWrapper<User> query=new QueryWrapper<>();
        query.eq("type",1);
        List<User> list=userMapper.selectList(query);
        return list;
    }

步骤3:

编写控制层:UserController中设计路径v1/users/master,返回R<List>即可

@RestController
@RequestMapping("/v1/users")
public class UserController {@Autowired
    IUserService userService;@GetMapping("/master")
    public R<List<User>> master(){
        List<User> masters=userService.getMasters();
        return R.ok(masters);
    }
}

步骤4:

参照绑定所有标签的Vue代码绑定所有老师即可

//启动v-select标签
Vue.component("v-select", VueSelect.VueSelect);
let createQuestionApp = new Vue({
    el: "#createQuestionApp",
    data: {
        title:"",
        selectedTags:[],
        tags:[],
        selectedTeachers:[],
        teachers:["苍老师","范老师","克晶老师"]
    },
    methods: {
        loadTags:function(){
            $.ajax({
                url:"/v1/tags",
                method:"get",
                success:function(r){
                    console.log(r);
                    if(r.code==OK){
                        let list=r.data;//获得所有标签数组
                        //list=[{id:1,name:"java基础"},{...},{...}]
                        let tags=[];
                        for(let i=0;i<list.length;i++){
                            //push方法表示向这个数组的最后位置添加元素
                            //效果和java中list的add方法一致
                            tags.push(list[i].name);
                        }
                        console.log(tags);
                        createQuestionApp.tags=tags;
                    }
                }
            });
        },
        loadTeachers:function(){
            $.ajax({
                url:"/v1/users/master",
                method:"get",
                success:function(r){
                    console.log(r);
                    if(r.code==OK){
                        let list=r.data;//获得所有讲师数组
                        let teachers=[];
                        for(let i=0;i<list.length;i++){
                            //push方法表示向这个数组的最后位置添加元素
                            //效果和java中list的add方法一致
                            teachers.push(list[i].nickname);
                        }
                        console.log(teachers);
                        createQuestionApp.teachers=teachers;
                    }
                }
            });
        }
    },
    created:function(){
        this.loadTags();
        this.loadTeachers();
    }
});

6. 发布问题的业务处理

我们先来完成数据提交到控制器的内容

步骤1:

为了这次提交新建一个Vo类 QuestionVo

@Data
public class QuestionVo implements Serializable {@NotBlank(message = "标题不能为空")
    @Pattern(regexp = "^.{3,50}$",message = "标题长度在3~50个字符之间")
    private String title;private String[] tagNames={};
    private String[] teacherNickNames={};@NotBlank(message = "问题内容不能为空")
    private String content;
    
}

步骤2:

开发发布问题的控制器代码

在QuestionController中代码如下

	// 学生发布问题的控制器方法
    @PostMapping
    public R createQuestion(
            @Validated QuestionVo questionVo,
            BindingResult result){
        if(result.hasErrors()){
            String message=result.getFieldError()
                    .getDefaultMessage();
            log.warn(message);
            return R.unproecsableEntity(message);
        }
        if(questionVo.getTagNames().length==0){
            log.warn("必须选择至少一个标签");
            return R.unproecsableEntity("必须选择至少一个标签");
        }
        if(questionVo.getTeacherNickNames().length==0){
            log.warn("必须选择至少一个老师");
            return R.unproecsableEntity("必须选择至少一个老师");
        }
        //这里应该将vo对象交由service层去新增
        log.debug("接收到表单数据{}",questionVo);
        return R.ok("发布成功!");
    }

步骤3:

找到create.html的form标签

使用v-on:submit.prevent绑定提交事件 .prevent是阻止表单提交用的

<form v-on:submit.prevent="createQuestion">

步骤4:

在createQuestion.js

文件中新增createQuestion方法

并在方法中收集要提交的信息,最后使用ajax提交到控制器

 createQuestion:function(){
            let content=$("#summernote").val();
            console.log(content);
            //定义一个data对象,用于ajax提交信息到控制器
            let data={
                title:this.title,
                tagNames:this.selectedTags,
                teacherNickNames:this.selectedTeachers,
                content:content
            }
            console.log(data);
            $.ajax({
                url:"/v1/questions",
                traditional:true,//使用传统数组的编码方式,SpringMvc才能接收
                method:"post",
                data:data,
                success:function(r){
                    console.log(r)
                    if(r.code== OK){
                        console.log(r.message);
                    }else{
                        console.log(r.message);
                    }
                }
            });
        }

下面我们需要完成新增问题的业务逻辑的开发

首先来了解一下我们需要什么操作才能完成这个业务
在这里插入图片描述
举例
在这里插入图片描述
步骤1:

讲师的信息也是可以保存在换存中来避免多次访问数据库来提交运行效率的

所以我们参照对标签的处理方法,对所有讲师也进行缓存

IUserService中

	// 查询所有老师用户的方法
    List<User> getMasters();
    //查询所有老师用户的Map方法
    Map<String,User> getMasterMap();

步骤2

参照TagServiceImpl中对标签的缓存,处理讲师缓存

UserServiceImpl代码如下

private final List<User> masters=
            new CopyOnWriteArrayList<>();
    private final Map<String,User> masterMap=
            new ConcurrentHashMap<>();
    private final Timer timer=new Timer();
    //初始化块:在构造方法运行前开始运行
    {
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                synchronized (masters){
                    masters.clear();
                    masterMap.clear();
                }
            }
        },1000*60*30,1000*60*30);
    }
​
​
​
    @Override
    public List<User> getMasters() {
        if(masters.isEmpty()){
            synchronized (masters){
                if(masters.isEmpty()){
                    QueryWrapper<User> query=new QueryWrapper<>();
                    query.eq("type",1);
                    //将所有老师缓存masters集合中
                    masters.addAll(userMapper.selectList(query));
                    for(User u: masters){
                        masterMap.put(u.getNickname(),u);
                    }
                    //脱敏:将敏感信息从数组(集合\map)中移除
                    for(User u: masters){
                        u.setPassword("");
                    }
                }
            }
        }
        return masters;
    }@Override
    public Map<String, User> getMasterMap() {
        if(masterMap.isEmpty()){
            getMasters();
        }
        return masterMap;
    }

步骤3:

编写IQuestionService接口中发布问题的方法

步骤4:

在QuestionServiceImpl类中实现接口中定义的方法

业务的步骤大概为

// 获取当前登录用户信息(可以验证登录情况)// 将该问题包含的标签拼接成字符串以","分割 以便添加tag_names列// 构造Question对象// 新增Question对象// 处理新增的Question和对应Tag的关系// 处理新增的Question和对应User(老师)的关系

代码如下

@Autowired
    QuestionTagMapper questionTagMapper;@Override
    public void saveQuestion(QuestionVo questionVo) {
        log.debug("收到问题数据{}",questionVo);
        // 获取当前登录用户信息(可以验证登录情况)
        String username=userService.currentUsername();
        User user=userMapper.findUserByUsername(username);
        // 将该问题包含的标签拼接成字符串以","分割 以便添加tag_names列
        StringBuilder bud=new StringBuilder();
        for(String tag : questionVo.getTagNames()){
            bud.append(tag).append(",");
        }
        //删除最后一个","
        bud.deleteCharAt(bud.length()-1);
        String tagNames=bud.toString();// 构造Question对象
        Question question=new Question()
                .setTitle(questionVo.getTitle())
                .setContent(questionVo.getContent())
                .setUserId(user.getId())
                .setUserNickName(user.getUsername())
                .setTagNames(tagNames)
                .setCreatetime(LocalDateTime.now())
                .setStatus(0)
                .setPageViews(0)
                .setPublicStatus(0)
                .setDeleteStatus(0);
        // 新增Question对象
        int num=questionMapper.insert(question);
        if(num!=1){
            throw  new ServiceException("服务器忙!");
        }
        log.debug("保存了对象:{}",question);
        // 处理新增的Question和对应Tag的关系
        Map<String,Tag> name2TagMap=tagService.getName2TagMap();
        for(String tagName : questionVo.getTagNames()){
            //根据本次循环的标签名称获得对应的标签对象
            Tag tag=name2TagMap.get(tagName);
            //构建QuestionTag实体类对象
            QuestionTag questionTag=new QuestionTag()
                    .setQuestionId(question.getId())
                    .setTagId(tag.getId());
            //执行新增
            num=questionTagMapper.insert(questionTag);
            if(num!=1){
                throw new ServiceException("数据库忙!");
            }
            log.debug("新增了问题和标签的关系:{}",questionTag);
        }// 处理新增的Question和对应User(老师)的关系}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode-Java(02)

5. 最长回文子串 首先用start和end记录开始和结尾位置&#xff0c;遍历每一个字符&#xff0c;对于每一个字符有两种情况&#xff0c;第一种情况&#xff0c;从一个字符中心扩展&#xff0c;得到len1&#xff0c;第二种情况&#xff0c;从两个字符中心扩展&#xff0c;得到len2…

MFC第二十七天 通过动态链表实现游戏角色动态增加、WM_ERASEBKGND背景刷新的原理、RegisterClass注册窗口与框架程序开发

文章目录 通过动态链表实现游戏角色动态增加CMemoryDC.hCFlashDlg.hCFlashDlg.cpp WM_ERASEBKGND背景刷新的原理RegisterClass注册窗口与框架程序开发CFrameRegister 通过动态链表实现游戏角色动态增加 CMemoryDC.h #pragma once#include "resource.h"/*内存DC类简介…

【Shell】基础语法(二)

文章目录 一、Shell基本语法文件名代换命令代换算术代换转义字符引号 二、Shell脚本语法条件测试分支结构循环 三、总结 一、Shell基本语法 文件名代换 用于匹配的字符称为通配符&#xff08;Wildcard&#xff09;&#xff0c;如&#xff1a;* ? [ ] 具体如下&#xff1a; *…

【Datawhale AI 夏令营第二期】AI 量化模型预测挑战赛

文章目录 赛题分析赛题背景赛事任务赛题数据集评价指标 Baseline实践导入模块EDA特征工程模型训练与验证结果输出 改进 赛题分析 赛题背景 量化金融在国外已经有数十年的历程&#xff0c;而在国内兴起还不到十年。这是一个极具挑战的领域。量化金融结合了数理统计、金融理论、…

DataWhale 机器学习夏令营第二期——AI量化模型预测挑战赛 学习记录

DataWhale 机器学习夏令营第二期 学习记录一 (2023.08.06)1. 问题建模1.1 赛事数据数据集情况数据中缺失值类别和数值特征的基本分布 1.2 评价指标中间价的计算方式价格移动方向说明 1.3 线下验证 DataWhale 机器学习夏令营第二期 ——AI量化模型预测挑战赛 已跑通baseline&…

排查吞吐量和 SNR 方面的 Wi-Fi 问题

服务交付对于客户在选择品牌时要考虑很重要&#xff0c;组织依靠其网络向全球客户无缝提供服务&#xff0c;强大的网络连接对于更好的最终用户体验至关重要&#xff0c;而高质量访问的关键是两个关键指标&#xff1a; 吞吐量信噪比 &#xff08;SNR&#xff09; 为了获得更好…

解决word打字卡顿问题的方法

❤ 2023.8.5 ❤ 最近整理论文&#xff0c;本来我是wps死忠粉&#xff0c;奈何wps不支持latex公式。。。 无奈用起了word&#xff0c;但是谁想字数稍微多了一点&#xff0c;word就卡得欲仙欲死&#xff0c;打个字过去2s才显示出来&#xff0c;删除的时候都不知道自己删了几个字…

基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220(1)----套件概述

基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220----1.套件概述 套件概述样品申请特征系统控制和生态系统访问功能示意图系统框图跳线设置开发板原理图 套件概述 STM32C011F4Px_STSPIN220 是一款基于 STM32C011F4Px 的低压步进电机驱动套件。其中&#xff0c;STSPIN220 是一…

离散化的两种实现方式【sort或者map】

离散化 定义 把无限空间中有限的个体映射到有限的空间中去&#xff0c;以此提高算法的时空效率。通俗的说&#xff0c;离散化是在不改变数据相对大小的条件下&#xff0c;对数据进行相应的缩小。 适用范围&#xff1a;数组中元素值域很大&#xff0c;但个数不是很多。 比如将…

Navicat远程连接Linux的MySQL

打开Linux终端&#xff0c;进入root权限&#xff0c;用vim打开MySQL的配置文件 vim /etc/mysql/mysql.conf.d/mysqld.cnf将bind-address的值改为0.0.0.0 进入MySQL mysql -u root -p 将root用户改为允许远程登录 update user set host % where user root; 创建用户 CRE…

码出高效_第二章 | 面向对象_上

目录 一. OOP理念1. 概念辨析2. 四大特性1. 抽象2. 封装3. 继承4. 多态 二. 初识Java1. JDKJDK 5-11的重要类、特性及重大改变 2. JRE关于JVM 三. 类1. 概述2. 接口和抽象类1. 概念及相同点2. 不同点3. 总结 3. 内部类4. 访问权限控制1. 由来2. public/private/无/private3. 推…

无涯教程-Perl - endgrent函数

描述 此功能告诉系统您不再希望使用getgrent从groups文件中读取条目。 语法 以下是此函数的简单语法- endgrent返回值 此函数不返回任何值。 Perl 中的 endgrent函数 - 无涯教程网无涯教程网提供描述此功能告诉系统您不再希望使用getgrent从groups文件中读取条目。 语法以…

开源项目-私人牙医管理系统

哈喽,大家好,今天给大家带来一个开源项目-私人牙医管理系统,项目使用springboot+mysql技术实现 私人牙医管理系统的主要功能包括客户管理,医生管理,药品管理,文章管理模块 登录 客户管理 客户管理主要有客户数据,客户列表,添加客户功能 客户数据 客户列表 添加…

VIOOVI的精益生产探析:深入了解精益生产的本质

精益生产它是利用杜绝浪费和稳定、连续生产的作业流程&#xff0c;是通过系统性的结构管理、生产人员组织以及市场端的供求现状等方面的因素做对应的调整、变革。具备有一定战斗力的生产管理体系&#xff0c;可以很快的根据市场端需求做出对应的调整&#xff0c;而且实现生产过…

黑马大数据学习笔记5-案例

目录 需求分析背景介绍目标需求数据内容DBeaver连接到Hive建库建表加载数据 ETL数据清洗数据问题需求实现查看结果扩展 指标计算需求需求指标统计 可视化展示BIFineBI的介绍及安装FineBI配置数据源及数据准备 可视化展示 P73~77 https://www.bilibili.com/video/BV1WY4y197g7?…

如何使用win10专业版系统自带远程桌面公司内网电脑,从而实现居家办公?

使用win10专业版自带远程桌面公司内网电脑 文章目录 使用win10专业版自带远程桌面公司内网电脑 在现代社会中&#xff0c;各类电子硬件已经遍布我们身边&#xff0c;除了应用在个人娱乐场景的消费类电子产品外&#xff0c;各项工作也离不开电脑的帮助&#xff0c;特别是涉及到数…

router和route的区别

简单理解为&#xff0c;route是用来获取路由信息的&#xff0c;router是用来操作路由的。 一、router router是VueRouter的实例&#xff0c;通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象&#xff0c;这个对象中是一个全局的对象&#xff0c;他包含了所…

vue结合three.js加载3D模型报404错误

使用vue结合three.js加载3D模型时报404的错误&#xff0c;加载字体库也会报404错误&#xff0c;同样的方法。 vue项目虽然使用npm install three安装了three&#xff0c;但是有些静态资源时读取不到的&#xff0c;当出现异常的404错误时&#xff0c;比如加载3D模型资源时&…

第5章 运算符、表达式和语句

本章介绍以下内容&#xff1a; 关键字&#xff1a;while、typedef 运算符&#xff1a;、-、*、/、%、、--、(类型名) C语言的各种运算符&#xff0c;包括用于普通数学运算的运算符 运算符优先级以及语句、表达式的含义 while循环 复合语句、自动类型转换和强制类型转换 如何编写…

虚拟机不能使用 console 的问题

原理&#xff1a;arm 系统默认走ttyAMA0&#xff0c;x86 默认走ttyS0&#xff0c;而tty0 是走的GPU 串行端口终端(/dev/ttySn) 串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。 计算机把每个串行端口都看作是一个字符设备。有段时间这些串行端口设备…