如何将一个后台管理模板移植到 Grails 中?
假设我们有了一个后台管理WEB模板,例如 startbootstrap-admin-2。
我们需要可以用它来制作一个管理后台,可以这样做。
制作 layout 页面
将 startbootstrap-sb-admin-2-gh-pages git 项目检出后,可以看到下面的目录结构。
css\
img\
js\
node_modules\
scss\
vendor\
.browserslistrc
.gitignore
.travis.yml
404.html
blank.html
buttons.html
cards.html
charts.html
forgot-password.html
gulpfile.js
index.html
LICENSE
login.html
package.json
package-lock.json
README.md
register.html
tables.html
utilities-animation.html
utilities-border.html
utilities-color.html
utilities-other.html
我们只需要将 index.html 文件拷贝为 grails 项目的 views/layout/sb_main.gsp ,后续会修改 sb_main.gsp 的内容。
准备资源文件
再将 vendors/ 目录复制为 grails 项目的 assets/libs 目录,后续会删除不必要的文件。
将 模板项目/js 下的文件复制到 grails项目的 assets/javascripts 目录下。
将 模板项目/css 下的文件复制到 grails项目的 assets/stylesheets 目录下。
将 模板项目/img 下的文件复制到 grails项目的 assets/images 目录下。
清理资源文件目录
这里我就得到如下的 libs 目录结构:
├─bootstrap
│ ├─js
│ └─scss
│ ├─mixins
│ ├─utilities
│ └─vendor
├─chart.js
├─datatables
├─fontawesome-free
│ ├─css
│ ├─js
│ ├─less
│ ├─scss
│ ├─sprites
│ ├─svgs
│ │ ├─brands
│ │ ├─regular
│ │ └─solid
│ └─webfonts
├─jquery
└─jquery-easing
现在我们来删除不用的文件。
首先所有的 less、scss 目录都可以删除。
bootstrap 目录也可以删除,因为可以改用 grails 自带的 bootstrap4.3 文件。
然后删除 .min.js,.min.css 文件,因为 asset-pipeline 会为我们在打包的时候创建。
删除 *.map 文件,因为 asset-pipeline 会为我们在打包的时候创建。
对于 fontawesome-free 要特殊处理,因为该目录下文件众多,都是用不上的。
先删除 svgs 目录,这个目录下有1700+多个文件,并且不需要。删除 scss、less 目录,上面提到过。删除 js 和 css 目录下的 brands*, regular*, solids* 文件,因为 all 里面都包含了。剩下的文件是:
all.js
conflict-detection.js
fontawesome.js
v4-shims.js
清理完文件、目录后,资源准备环节就告一个段落了。
修改 sb_main.gsp 中引用资源的写法
link 标签
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
改为
<asset:link href="fontawesome-free/css/all.css" rel="stylesheet" type="text/css"/>
注意这里的区别:
- grails 的 asset-pipeline plugin 会自动在 assets/ 子目录下查找文件,所以,不需要写 assets/ 下的一级子目录如 stylesheets、libs 等。
- 要写结束标签 “/>”,而不是 body 为空的 xml 标签。
<a></a>
就是一个 body 为空的 xml 标签,要写成<a/>
才行。
stylesheet 标签
<link href="css/sb-admin-2.min.css" rel="stylesheet">
改为
<asset:stylesheet src="sb-admin-2.css"/>
javascript 标签
<script src="vendor/jquery/jquery.min.js"></script>
改为
<asset:javascript src="jquery-3.3.1.min.js" />
img 标签
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;" src="img/undraw_posting_photo.svg" alt="">
改为
<asset:image class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;" src="undraw_posting_photo.svg" alt="" />
改到这里,页面模板就能正常显示了,但还没有将内容部分留出来,所有页面显示的内容都是一样的,下面我们需要添加 layout 的内容区域设置。
给layout文件添加布局指令
有三个布局指令,告诉 grails 布局文件中哪部分是 header、哪部分是 title、哪部分是要插入的正文。
三个指令分别是:
<g:layoutTitle default="金案源"/>
<g:layoutHead/>
<g:layoutBody/>
下面直接给出最终结果,大家一看就明白了。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title>
<g:layoutTitle default="在线象棋商城"/>
</title>
<!-- Custom fonts for this template-->
<asset:link href="fontawesome-free/css/all.css" rel="stylesheet" type="text/css"/>
<asset:stylesheet src="fonts.css"/>
<!-- Custom styles for this template-->
<asset:stylesheet src="sb-admin-2.css"/>
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<g:render template="/layouts/sidebar" />
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<g:render template="/layouts/topbar" />
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<g:layoutBody/>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright © ${companyName} 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">准备退出吗?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">想退出登录请选择下面的 "退出" 按钮。</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">取消</button>
<a class="btn btn-primary" href="login.html">退出</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<asset:javascript src="jquery-3.3.1.min.js" />
<asset:javascript src="bootstrap.bundle.js"/>
<!-- Core plugin JavaScript-->
<asset:javascript src="jquery-easing/jquery.easing.js" />
<!-- Custom scripts for all pages-->
<asset:javascript src="sb-admin-2.js"/>
<!-- Page level plugins -->
<asset:javascript src="chart.js/Chart.js"/>
<!-- Page level custom scripts -->
<asset:javascript src="demo/chart-area-demo.js"/>
<asset:javascript src="demo/chart-pie-demo.js"/>
</body>
</html>
具体页面的写法
如 views/index.gsp 页面,套用 layout 的写法如下:
<!doctype html>
<html>
<head>
<meta name="layout" content="sb_main"/>
<title>Welcome to Grails</title>
</head>
<body>
这里的内容会被插入到 <g:layoutBody/> 处。
</body>
刷新一下页面,就能看到最终效果了。
完毕。