SpringBoot+BootStrap+Thymeleaf制作简单的员工管理系统(1)

本文介绍了如何在Thymeleaf中实现页面的头部和侧边栏的复用,将它们作为公共部分抽取到common.html中,并展示了如何通过th:fragment和th:replace属性进行引用。同时,详细解释了登录验证后在顶部栏显示用户名,以及如何根据页面路由点亮侧边栏相应链接的方法。内容涉及HTML、Thymeleaf、Spring MVC和后端数据交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇博客已经介绍了登录页,接下来是主页dashboard.html,主页的侧边栏和顶部导航栏可以提取出来作为公共部分,放在templates/common路径下,命名为common.html:

<!--顶部栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow" th:fragment="topbar">
    <a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">[[${session.username}]]</a>
    <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" href="#">Sign out</a>
        </li>
    </ul>
</nav>

<!--侧边栏-->
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse" th:fragment="sidebar(active)">
    <div class="sidebar-sticky pt-3">
        <ul class="nav flex-column">
            <li class="nav-item">
                <a th:class="${active=='main'?'nav-link active':'nav-link'}" href="/main">
                    <span data-feather="home"></span>
                    首页
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">
                    <span data-feather="file"></span>
                    Orders
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">
                    <span data-feather="shopping-cart"></span>
                    Products
                </a>
            </li>
            <li class="nav-item">
                <a th:class="${active=='list'?'nav-link active':'nav-link'}" href="/emps">
                    <span data-feather="users"></span>
                    员工管理
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">
                    <span data-feather="bar-chart-2"></span>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">
                    <span data-feather="layers"></span>
                    Integrations
                </a>
            </li>
        </ul>   
    </div>
</nav>

两个nav标签都带有th:fragment属性,属性值可随意取,表示该标签被复用时的名字,在其他地方使用th:replace即可引用该导航栏。顶部栏中的第一个a标签里的文本取为session的username属性,即将用户名显示在左上角,session中的username属性在后台登录校验成功后进行设置:

@RequestMapping("/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password,
                    Model model, HttpSession session) {
    if (用户名密码校验方法) {
        session.setAttribute("username", username);
        return "redirect:/main.html";
    } else {
        model.addAttribute("msg", "用户名或者密码错误");
        return "index";
    }
}

侧边栏里每个a标签的属性class里可设置是否为active,如果active表示该项被点亮,如下图所示:

 为了实现点击某个选项,该选项被点亮的功能,需要在每个选项的class里设置条件:th:class="${条件?'nav-link active':'nav-link'}",其中active表示被点亮,条件由传入的参数决定,这里的参数名为active。如果点击首页,则传入active应为main,如果点击员工管理,则传入active应为list。因为其他选项暂时用不到,所以只设置首页和员工管理这两个选项。下面是首页dashboard.html:

<nav th:replace="~{common/common::topbar}"></nav>

<div class="container-fluid">
  <div class="row">
    <nav th:replace="~{common/common::sidebar(active='main')}"></nav>

    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
      <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
        <h1 class="h2">Dashboard</h1>
        <div class="btn-toolbar mb-2 mb-md-0">
          <div class="btn-group mr-2">
            <button type="button" class="btn btn-sm btn-outline-secondary">Share</button>
            <button type="button" class="btn btn-sm btn-outline-secondary">Export</button>
          </div>
          <button type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle">
            <span data-feather="calendar"></span>
            This week
          </button>
        </div>
      </div>

      <canvas class="my-4 w-100" id="myChart" width="900" height="380"></canvas>

      <h2>Section title</h2>
      
    </main>
  </div>
</div>

其中,为了复用common.html中的代码,比如复用侧边栏,使用th:replace="~{common/common::sidebar(active='main')}",其中的~是thymeleaf中复用代码专用的符号,第一个common是目录名,第二个common.html的文件名,::后面的sidebar是th:fragment的值,还传入了参数active = 'main',以便点亮侧边栏的首页,后面的员工页也是类似的。

在common.html中,侧边栏的首页a标签的th:href属性值为“@{/main},表示点击跳转到首页,后台代码在覆写了的addViewControllers方法中:

registry.addViewController("/main").setViewName("dashboard");

侧边栏的员工管理a标签的th:href属性值为“@{/emps},表示点击跳转到员工页,后台代码在EmployeeController类中,其中查询了所有的员工信息,放在emps属性中,用于前台遍历:

@RequestMapping("/emps")
public String getAllEmployees(Model model) {
    model.addAttribute("emps", employeeDao.getAllEmployees());
    return "emps/list";
}

list.html如下:

<nav th:replace="~{common/common::topbar}"></nav>
    <div class="container-fluid">
      <div class="row ">
        <nav th:replace="~{common/common::sidebar(active='list')}"></nav>
        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
          <div class="row mt-3">
            <div class="col">
              <h2>员工管理</h2>
            </div>
            <!-- align-self-center使其垂直居中  -->
            <div class="col align-self-center">
              <a class="btn btn-sm btn-success" th:href="@{/toAdd}">添加员工</a>
            </div>
          </div>
          <div class="table-responsive mt-3">
            <table class="table table-striped table-sm">
              <thead>
                <tr>
                  <th>编号</th>
                  <th>名字</th>
                  <th>年龄</th>
                  <th>部门</th>
                  <th>性别</th>
                  <th>生日</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody>
              <tr th:each="emp:${emps}">
                <td>[[${emp.getId()}]]</td>
                <td>[[${emp.getName()}]]</td>
                <td>[[${emp.getAge()}]]</td>
                <td>[[${emp.getDepartment().getName()}]]</td>
                <td>[[${emp.getSex()==0?'女':'男'}]]</td>
                <td>[[${#dates.format(emp.getBirthday(),'yyyy-MM-dd')}]]</td>
                <td>
                  <!--   注意a标签链接的restful风格传参方式    -->
                  <a class="btn btn-sm btn-primary" th:href="@{'/toUpdate/' + ${emp.getId()}}">编辑</a>
                  <a class="btn btn-sm btn-danger" th:href="@{'/delete/' + ${emp.getId()}}">删除</a>
                </td>
              </tr>
              </tbody>
            </table>
          </div>
        </main>
      </div>
    </div>

该页面中还有添加员工、更新员工、删除员工的按钮,用于后续功能。表格取数据注意性别及出生日期两个字段,性别存储形式为0和1,因此前台展示时需要使用thymeleaf的三目运算符,而日期需要转化为自定义的'yyyy-MM-dd'的形式,使用#dates工具类的format方法实现。另外还需注意图中的垂直居中的方式:class属性中带有align-self-center即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值