基于SSM框架的狼途汽车门店管理系统的设计与实现

news2024/11/17 7:39:21

基于SSM框架的狼途汽车门店管理系统的设计与实现

✌全网粉丝20W+,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌

🍅文末获取项目下载方式🍅


一、项目背景介绍:

汽车美容这个概念进入中国都已经有十多年之久了,汽车的美容方式也逐渐发展的多式多样。众多4S店在中国的立足也说明着汽车美容行业其实已经正式的走向了成熟的发展时期。不得不说,中国的汽车市场是非常庞大的,得益于中国的经济发展速度太迅猛了,人们的生活水平日益提升,很多大城市已经能做到汽车是家庭的必备品,甚至于很多家庭都不止一台汽车。汽车多了,那么汽车门店也像春后的竹笋一般出现在我国的各地。
汽车的服务行业算是一个比较不错的“产业”。主要是因为这个行业是属于社会经济高速发展的产物,是根据汽车保有量的增加而随之形成的新型行业。那么大火的汽车的后服务市场究竟是什么呢?汽车的后服务市场可以这样理解,你买完车之后,你如果想让车的内饰变得更加美观,这时候门店就能帮你解决这个问题。从宏观的角度上来说,其实就是有关于购车后的所有服务门店都可以帮你解决你的需求。但是由于我国的汽车后服务市场其实才算是刚刚起步,属于极度不稳定的状态。今后这几年之间是肯定会进行一场激烈的竞争,经过重新洗牌之后的结局才是真正汽车服务业的开始。届时,能通过这些竞争“存活”下来的门店必定是那些懂得用信息化管理技术去运营的。因为只有这些会抓住机会的店家才能运筹帷幄。
虽说这几年中国互联网技术发展的还算比较不错,但是较于西方那些发达国家,其实还是有一点差距的。原因在于欧美那些国家主要推崇的都是O2O模式,该模式其实就是利用起互联网在现今社会的优势,用真正的信息化去管理门店。让门店真正可以做到“无人管理”。中国在O2O模式的应用上还算是比较少的,中国汽车门店其实很多还是使用纯线下的方式在运营。这种运营方式其实不符合现在的发展境况,毕竟现在是属于信息化的时代。一个门店如果是纯线下的模式在面对庞大的信息量的时候,人工管理是没有什么办法管理的。面对这种情况,其实是可以借鉴一下那些欧美国家的做法,使用数据库去存取这些信息,发挥出互联网时代应该有的优势,用一个功能完善、轻量、能处理大量数据的汽车门店管理系统去管理门店,从而真正的实现机械化管理,让汽车门店的运营变得更加便利与先进。

二、项目技术简介:

  1. JAVA:Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
  2. Spring:Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
  3. Mybatis:MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。
    iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
  4. Bootstrap:Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。 国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。
  5. Html:HTML的全称为超文本标记语言,是一种标记语言。它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整体。HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字,图形、动画、声音、表格、链接等。
    超文本是一种组织信息的方式,它通过超级链接方法将文本中的文字、图表与其他信息媒体相关联。这些相互关联的信息媒体可能在同一文本中,也可能是其他文件,或是地理位置相距遥远的某台计算机上的文件。这种组织信息方式将分布在不同位置的信息资源用随机方式进行连接,为人们查找,检索信息提供方便。

三、系统功能模块介绍:

功能模块图

四、数据库设计:

1:管理员表
(admin)

字段名类型默认值列注释
idbigint(20)NULL主键ID
user_namevarchar(50)NULL用户名
pass_wordvarchar(255)NULL密码
head_imgvarchar(200)NULL头像
nick_namevarchar(50)NULL昵称
typeint(3)NULL类型[1:员工

2:配件表
(parts)

字段名类型默认值列注释
idbigint(20)NULL主键ID
parts_namevarchar(50)NULL配件名称
supplier_idbigint(20)NULL所属供应商
pricevarchar(10)NULL单价
stockint(20)NULL库存
cover_imgvarchar(200)NULL配件
contenttextNULL配件用途
type_idbigint(20)NULL所属分类
current_stockint(20)NULL当前库存

3:配件分类
(parts_type)

字段名类型默认值列注释
idbigint(20)NULL主键ID
parts_type_namevarchar(255)NULL配件分类

4:服务项目表
(projects)

字段名类型默认值列注释
idbigint(20)NULL主键ID
subscribe_idbigint(20)NULL预约表ID
user_idbigint(20)NULL用户ID
contenttextNULL主要服务内容
typeint(3)NULL项目类别[1:汽车美容

5:用户预约表
(subscribe)

字段名类型默认值列注释
idbigint(20)NULL主键ID
user_idbigint(20)NULL用户ID
su_infotextNULL预约内容
subscribe_timedatetimeNULL预约时间
statusint(3)NULL预约状态[1:预约中

6:供应商表
(supplier)

字段名类型默认值列注释
idbigint(20)NULL主键ID
supplier_namevarchar(50)NULL供应商名称
supplier_typevarchar(50)NULL供应商类别
supplier_localtionvarchar(255)NULL供应商所在地址
supplier_boss_namevarchar(50)NULL供应商联系人名称
supplier_telvarchar(20)NULL联系电话

7:项目配件表
(user_parts)

字段名类型默认值列注释
idbigint(20)NULL主键ID
parts_idbigint(20)NULL配件ID
use_numint(20)NULL使用数量
projects_idbigint(20)NULL维修项目ID

8:用户表(users)

字段名类型默认值列注释
idbigint(20)NULL主键ID
user_namevarchar(255)NULL用户名
pass_wordvarchar(255)NULL密码
nick_namevarchar(50)NULL昵称
sexint(3)NULL性别[1:男

五、功能模块:

  1. 前台页面的功能实现:当点击马上预约的时候,就会弹出预约信息的模态框,预约信息包括了姓名、电话、预约的门店(可以下拉选择)、预约的业务(下拉选择)、预约的时间、备注说明。点击确定预约以后会提示用户预约成功。点击ok之后就可以返回门店首页。

    前台页面的功能实现

  2. 登录页面功能的实现:当输入账号不存在或者密码错误的时候,会提示账号或者密码错误。当输入的账号密码正确的时候,会跳转到员工信息页面,并在菜单栏显示当前登录的用户名

    登录页面功能的实现

  3. 员工页面功能的实现:点击添加/编辑的时候,会跳转到编辑页面。当输入的信息不符合条件的时候将不允许被保存 。
    点击导出员工表的时候,会直接生成一张包含所有员工信息的表格返回给用户。
    点击导入按钮的时候,会有下载模板和选择文件,用户可以下载模板,然后再模板表格填写员工数据,再选择刚才编写的文件,点击保存之后就会跳转回员工信息页面。

    员工页面功能的实现

  4. 权限页面功能的实现:因为系统的代码可能会改动,那么就需要在页面提供一个按钮,作用是为了权限表达式和数据库的权限表达式同步。点击重新加载按钮,会提示是否重新加载权限。点击确定之后会更新权限页面。

    权限页面功能的实现

  5. 公告页面功能的实现:点击查看按钮的时候对应的已读状态会改成已读。而且会跳转至公告查看的页面。
    点击发布按钮的时候状态会变成已发布,同时刷新公告页面。

    公告页面功能的实现

  6. 门店信息页面功能的实现:点击编辑的时候进入到信息编辑页面,有个查看附件的按钮,点击该按钮的时候会打开门店的营业执照照片。可以选择文件作为营业执照的照片进行上传。

    门店信息页面功能的实现

  7. 预约信息页面功能的实现:点击确认预约的时候,预约单的状态会变成履行中。点击取消预约的时候,预约单的状态会变成废弃。

    预约信息页面功能的实现

六、代码示例:

前台页面的功能实现
 /**
   * 展示前端页面方法
   * @param model
   * @return
   */
  @RequestMapping("/index")
  public String index(Model model){
    //获取所有的数据字典
List<SystemDictionary>systemDictionaries=systemDictionaryService.selectTitle("business");
    model.addAttribute("systemDictionaries",systemDictionaries);
   //获取总店对象
    Business business = businessService.getBymainStore(true);
    model.addAttribute("business",business);
    //获取所有的门店信息
    List<Business> businesses = businessService.listAll();
    model.addAttribute("businesses",businesses);
    return "index";
  }
登录页面功能的实现
public class LoginController {

  @Autowired
  private IEmployeeService employeeService;

  @RequestMapping("/empLogin")
  @ResponseBody
  public JsonResult empLogin(String username,String password){
    try {
       UsernamePasswordToken token = new UsernamePasswordToken(username,password);
       SecurityUtils.getSubject().login(token);
       return new JsonResult();
    }  catch (UnknownAccountException e) {
      return new JsonResult(false, "账号不存在");
    } catch (IncorrectCredentialsException e) {
      return new JsonResult(false, "密码错误");
    } catch (Exception e) {
      e.printStackTrace();
      return new JsonResult(false, "登录异常,请联系管理员");
    }
  }
员工页面功能的实现
public class CheckLoginInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {

      if (handler instanceof HandlerMethod){
        //拦截到的都是请求动态资源的请求
        //判断是否有登录  有放行  没有跳转登录页面
        Object emp = request.getSession().getAttribute(UserContext.USER_IN_SESSION);
        if (emp == null){
          response.sendRedirect("/login.html");
          return false;
        }
      }

    return true;
  }
}
权限页面功能的实现
 public void reload() {
        //1.一次性的把数据库所有的权限信息查出来.
        List<Permission> permissions = permissionMapper.selectAll();
        //2.创建一个set集合  用来存储权限表达式
        Set<String> expressionSet = new HashSet<>();
        for(Permission p:permissions){
            //3.将所有的权限信息去从加到集合中
            expressionSet.add(p.getExpression());
        }
        //获取到所有贴了RequiredPermission注解,取出注解上的name和expression,
        // 封装成Permission,保存到数据库中
        //HandlerMethod代表每一个控制的方法引用
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhm.getHandlerMethods();
        Collection<HandlerMethod> values = handlerMethods.values();
        for(HandlerMethod method:values){
            // 获取方法的注解
            RequiresPermissions annotation = method.getMethodAnnotation(RequiresPermissions.class);
            // 方法上有贴我们的自定义权限注解
            if (annotation != null) {
                // 获取方法的注解 name 和 expression 值
                String name = annotation.value()[1];
                String expression = annotation.value()[0];
                // 存入到数据库之前要判断一下, 若数据库中不存在就存入
                if(!expressionSet.contains(expression)) {
                    Permission permission = new Permission();
                    permission.setName(name);
                    permission.setExpression(expression);
                    permissionMapper.insert(permission);
                }
            }
        }
}
公告页面功能的实现
  @Override
    public Notice get(Long id) {
        Notice notice = noticeMapper.selectByPrimaryKey(id);
        //点击查看的时候中间表插入数据
            noticeMapper.insertEmpNotice(UserContext.getEmployee().getId(),id);
        return notice;
}
门店信息页面功能的实现
 @RequiresPermissions(value = {"business:saveOrUpdate","门店编辑"}, logical = Logical.OR)
    public String saveOrUpdate(Business business, MultipartFile file) throws Exception {
     if (file != null && file.getSize()>0) {
         //处理上传的操作
         String realPath = servletContext.getRealPath("/");
         //如果存在 编辑的时候上传带就把之前的删除
         if (StringUtils.hasText(business.getLicenseImg())) {
             //拼出删除的路径
             String deletePath = realPath + business.getLicenseImg();
             FileUploadUtil.deleteFile(deletePath);
         }
         String filePath = FileUploadUtil.uploadFile(file, realPath);
         business.setLicenseImg(filePath);
     }
        if (business.getId() == null) {
            businessService.save(business);
        } else {
            businessService.update(business);
        }
        return "redirect:/business/list";
}
预约信息页面功能的实现
//修改预约单状态功能
 @RequestMapping("/updateStatus")
    public String updateStatus(Long id ,Integer status){
        appointmentService.updateStatus(id,status);
        return "redirect:/appointment/list";
}

void updateStatus(@Param("id") Long id, @Param("status") Integer status);

<update id="updateStatus">
    update appointment
    set status = #{status}
    where id = #{id}
  </update>

七、论文参考:

八、项目总结:

在本次毕业设计期间,自己学会了很多新技术。以前百度开发技术的时候总觉得这些东西了解一下就好了,到时候不是手到擒来的事情吗。通过这次毕业设计项目的开发才真正认识到一个技术如果仅仅只是了解,那么你就只能说出技术的要点,让你真正去实现就会发现比登天都难。其实计算机方面的知识重在实践,只有你真正的把这些技术用熟才能说是对其的了解。
但是由于是第一次自己手动开发一个整套的基于SSM框架的项目,所以系统的问题还是有很多的。例如前端页面选取问题上,本人是采用了各个框架技术的模板页面;数据库中表的设计可能也会存在关系错乱的问题。但是在这次开发过程中也收获了很多之前没有的开发经验。对Bootstrap、Jquery、Freemarker、mybatis等框架或者技术有了更深层次的认识。同样也为自己毕业以后的学习生活和工作打下了坚实的基础。
在本次设计中收获最大的其实并不是对技术的掌握,而是了解到开发一个项目必须得做好规划。不能像无头苍蝇一般没有头绪,只有把项目的全部流程详细的规划好,用文档去记录起来,然后一步一步的实现项目的需求才能让系统具有生命。在开发过程中也不会一帆风顺,遇到系统出现问题的时候,我从以前的束手无策变成现在的冷静也得益于此次开发。现在的我遇到问题都会先分析系统的流程情况,再根据流程情况去分析代码实现的逻辑问题,实在解决不了就会借助百度的力量。当问题十分棘手的情况下会选择询问毕设导师周少波老师请求帮助。我觉得在毕业之后的工作时也应该有这样的态度,才能真正去把项目开发好。
本次毕业设计所做出的项目可能还无法满足真正的企业要求,与真正实际应用还是有着一定的差距的。原因在于搜集的信息不够充足、对实际情况了解不够深入、对系统的分析不够彻底。但是有了这次的开发经验,我相信在以后的开发之路上我能避免走很多弯路,也能开发出真正能应用于现实生活中的项目系统。

九、源码获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻获取联系方式👇🏻👇🏻👇🏻

链接点击直达:下载链接

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

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

相关文章

AutoCAD学习之基本操作学习笔记

AutoCAD学习 基本操作&#xff08;23.2.15~23.2.17&#xff09; CtrlN 新建一个CAD文档F7 删除格栅F3 对象捕捉&#xff08;很重要啊&#xff0c;如果一直开着&#xff0c;操作起来很费劲。&#xff09;&#xff0c;需要关掉&#xff0c;注意使用snipaste&#xff0c;会不停地…

QT 文件监视系统QFileSystemWatcher监视目录的改变directoryChanged和监视文件的改变fileChanged

QT 文件监视系统QFileSystemWatcher监视目录的改变相关操作说明mainwindow.hmainwindow.cpp调试结果相关操作说明 添加头文件 Header: #include qmake: QT core bool QFileSystemWatcher::addPath(const QString &path)如果路径存在&#xff0c;则会向文件系统监视器添…

Prometheus Docker安装及监控自身

前提环境&#xff1a; Docker环境 涉及参考文档&#xff1a; 安装Prometheus开始 Prometheusnode_exporter Agent组件 一、部署Prometheus 1、启动容器将文件拷贝出来 docker run -d prom/prometheus2、容器将文件拷贝出来 docker cp 容器ID:/usr/share/prometheus/conso…

深度学习笔记:误差反向传播(1)

1 计算图 计算图使用图&#xff08;由节点和边构成的图&#xff09;来表达算式。 如图&#xff0c;我们用节点代表运算符号&#xff0c;用边代表传入的参数&#xff0c;即可算出购买苹果和橘子的总价格。 2 计算图的局部计算 局部计算意味着每个节点只处理和其相关的运算&…

网页设计html期末大作业

网页设计html期末大作业网页设计期末大作业-自制网站大一期末作业&#xff0c;外卖网站设计网页设计期末大作业-精美商城-首页框架网页设计期末大作业-自制网站 有导航栏&#xff0c;轮播图&#xff0c;按钮均可点进去&#xff0c;如下图所示 点我下载资源》》》》 大一期末…

linux ubuntu查日志信息以及错误排查

目录 一、linux的日志文件 1、常用日志文件 2、其他日志文件 二、历史日志的查看 1、查看Logrotate的配置信息 2、查看日志配置 一、linux的日志文件 Linux系统中最有趣的(可能也是最重要的)目录之一是/var/log。根据文件系统层次结构标准&#xff0c;在系统中运行的大多数…

java面试题-泛型异常反射

泛型1.什么是泛型&#xff1f;Java是一种强类型语言&#xff0c;数据类型在编译时必须确定。如果我们想要在代码中使用不同类型的数据&#xff0c;那么就需要为每种类型分别写出相应的代码。这样会导致代码冗长、重复&#xff0c;也不便于维护。为了解决这个问题&#xff0c;Ja…

嵌入式Linux入门级板卡的神经网络框架ncnn移植与测试-米尔i.MX6UL开发板

本篇测评由电子发烧友的优秀测评者“ALSET”提供。 米尔 MYD-Y6ULX-V2 开发板&#xff0c;基于 NXP i.MX6UL/i.MX6UL L处理器&#xff0c;该开发板被米尔称之为经典王牌产品。本次测试目标是在此开发板上进行神经网络框架ncnn的移植与测试开发&#xff0c;测试ncnn在此开发板上…

高可用的“异地多活”架构设计

前言 后台服务可以划分为两类&#xff0c;有状态和无状态。高可用对于无状态的应用来说是比较简单的&#xff0c;无状态的应用&#xff0c;只需要通过 F5 或者任何代理的方式就可以很好的解决。后文描述的主要是针对有状态的服务进行分析。 服务端进行状态维护主要是通过磁盘…

Orin 安装CUDA CUDNN TensorRT Opencv和输入法的环境配置

有两种方法可以安装CUDA环境 第一种方法-用命令按照 在刷机完成的Orin&#xff0c;执行如下命令&#xff1a; sudo apt update sudo apt upgrade sudo apt install nvidia-jetpack -y注释–如果在执行第三行命令&#xff0c;报错的话&#xff0c;先查看nvidia-l4t-apt-so…

初识K8s

概览 k8s 概念和架构从零搭建K8s 集群k8s 核心概念搭建集群监控平台搭建高可用k8s集群集群环境 实际部署项目 k8s 概念和架构 1、K8S概述和特性 概述&#xff1a; k8s是谷歌在2014年开源的容器化集群管理系统使用k8s进行容器化应用部署使用k8s利于应用扩展k8s目标实施让部…

AcWing3416.时间显示——学习笔记

目录 题目 代码 AC结果 思路 关键步骤 题目 3416. 时间显示 - AcWing题库https://www.acwing.com/problem/content/description/3419/ 代码 import java.util.Scanner;public class Main {public static void main(String[] args){Scanner input new Scanner(System.in…

Rust学习入门--【15】Rust 所有权

系列文章目录 Rust 语言是一种高效、可靠的通用高级语言&#xff0c;效率可以媲美 C / C 。本系列文件记录博主自学Rust的过程。欢迎大家一同学习。 Rust学习入门–【1】引言 Rust学习入门–【2】Rust 开发环境配置 Rust学习入门–【3】Cargo介绍 Rust学习入门–【4】Rust 输…

Maven的安装和配置

Maven的安装 1.1Maven是什么&#xff1f; 是阿帕奇的&#xff0c;就是代替原先手动导入jar包的方式 1.官方介绍 视频&#xff1a;百度百科-验证Maven是一款服务于Java平台的自动化构建工具。Maven 作为 Java 项目管理工具&#xff0c;它不仅可以用作包管理&#xff0c;还有许多…

DIDL4_前向传播与反向传播(模型参数的更新)

前向传播与反向传播前向传播与反向传播的作用前向传播及公式前向传播范例反向传播及公式反向传播范例小结前向传播计算图前向传播与反向传播的作用 在训练神经网络时&#xff0c;前向传播和反向传播相互依赖。 对于前向传播&#xff0c;我们沿着依赖的方向遍历计算图并计算其路…

# AutoSar一文概览

1.什么是AutoSar ​ AUTOSAR全称为“AUTomotive Open System ARchitecture”&#xff0c;译为“汽车开放系统体系结构”&#xff1b;AUTOSAR是由 全球各大汽车整车厂、汽车零部件供应商、汽车电子软件系统公司联合建立的一套标准协议、软件架构。 2.为什么汽车行业要定义一个…

DIDL5_数值稳定性和模型初始化

数值稳定性和模型初始化数值稳定性梯度不稳定的影响推导什么是梯度消失&#xff1f;什么是梯度爆炸&#xff1f;如何解决数值不稳定问题&#xff1f;——参数初始化参数初始化的几种方法默认初始化Xavier初始化小结当神经网络变得很深的时候&#xff0c;数值特别容易不稳定。我…

面试题67. 把字符串转换成整数

题目 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先&#xff0c;该函数会根据需要丢弃无用的开头空格字符&#xff0c;直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时&#xf…

密度峰值聚类算法(DPC)

密度峰值聚类算法目录DPC算法1.1 DPC算法的两个假设1.2 DPC算法的两个重要概念1.3 DPC算法的执行步骤1.4 DPC算法的优缺点matlab代码密度计算函数计算delta寻找聚类中心点聚类算法目录 DPC算法 1.1 DPC算法的两个假设 1&#xff09;类簇中心被类簇中其他密度较低的数据点包围…

kubernetes 教程

K8s 安装kubectl 下载kubectl curl -LO "https://dl.k8s.io/release/**$(**curl -L -s https://dl.k8s.io/release/stable.txt**)**/bin/linux/amd64/kubectl" 安装 sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl 验证 kubectl versi…