本章都是关于使用管理界面构建内容管理工具。 我们将为完全独立于Web前端的管理员视图创建一个模块。 CMS将支持基于Leaf模板并使用Swift代码进行验证的具有可重用表单的列表,创建,更新和删除功能。 模型将被持久化到数据库中,我们将使用中间件来保护管理端点。
管理模块
就像前端一样,管理模块是一个特殊的模块。 这些模块是其他模块的“框架”。 它们提供了主要的布局模板,其他模块可以挂接到这些容器中。 例如,前端具有一个索引模板,该模板由Web前端上的所有页面(例如博客或登录屏幕)使用。 管理模块将为管理页面提供类似的索引模板。 在Admin/Views文件夹中创建一个名为Index.leaf的新文件,其内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| /** * FILE: * Sources/App/Modules/Admin/Views/Index.leaf */ <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="robots" content="noindex"> <title>#(title)</title> <link rel="stylesheet" href="/css/frontend.css"> <link rel="stylesheet" href="/css/admin.css"> <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon"> </head> <body> <header> <a href="/" id="logo"> <img src="/images/logo.png"> <h1>Char's Blog - 管理员</h1> </a> <nav id="navigation"> <a href="/" target="_blank">Site</a> · <a href="/admin">Admin</a> · <a href="/logout">Logout</a> </nav> </header> <main> <div id="main-content"> #import("body") </div> </main> <script src="/javascript/admin.js"></script> </body> </html>
|
主管理模板与前端稍有不同。 第一个变化是机器人有了一个新的meta标签,因为我们不想对管理页面进行索引。 不像任何机器人都可以访问这些机器人,我们会加以保护,但让我们保持这种方式。
我们也在这里链接frontend.css文件,但这可能是常见内容的共享CSS文件。 我们还包括一个新的admin.css样式表,其中将包含特定于管理员的样式。 菜单结构与前端不同,我们在最后添加了一个新的admin.js文件。 请在“公共”文件夹中创建这些新文件。
我们还将需要类似主屏幕的内容管理系统。 让我们在Admin/Views文件夹中的索引视图旁边添加一个新的Home.leaf模板。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
#extend("Admin/Index"): #export("body"): <section class="wrapper"> <h2>#(header)</h2> </section> <section class="wrapper"> <p>#(message)</p> </section> #endexport #endextend
|
现在,创建一个新的AdminController,它可以呈现CMS的主屏幕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
import Vapor struct AdminController { func homeView(req: Request) throws -> EventLoopFuture<View> { let user = try req.auth.require(UserModel.self)
struct Context: Encodable { let title: String let header: String let message: String } let context = Context(title: "myPage - Admin", header: "Hi \(user.email)", message: "welcome to the CMS!") return req.view.render("Admin/Home", context) } }
|
如前所述,管理员视图仅对经过身份验证的用户可用,这就是为什么我们需要从身份验证层要求UserModel的原因。 由于我们将拥有用户数据,因此欢迎您以个性化的消息欢迎已登录的用户。
使用模块目录中新创建的AdminRouter.swift文件连接此管理控制器。 我们可以使用上一章中创建的用户模块中的会话身份验证器中间件。
1 2 3 4 5 6 7 8 9 10
|
import Vapor struct AdminRouter: RouteCollection { let controller = AdminController() func boot(routes: RoutesBuilder) throws { routes.grouped(UserModelSessionAuthenticator()).get("admin", use: self.controller.homeView) } }
|
稍后,您将看到还有其他一些中间件可以从字面上保护受保护的路由,如果用户未通过身份验证,则可以将他们重定向到其他地方。
要完成该模块,我们应该在Admin文件夹中创建一个新的AdminModule.swift文件,并返回路由器实例。
1 2 3 4 5 6 7 8 9
|
import Vapor import Fluent
struct AdminModule: Module { var router: RouteCollection? { AdminRouter() } }
|
我们必须在configure.swift文件中注册这个新模块,以使工作正常。
1 2 3 4 5 6 7 8 9
|
public func configure(_ app: Application) throws { let modules: [Module] = [ UserModule(), FrontendModule(), AdminModule(), BlogModule(), ] }
|
现在我们可以更改Frontend/Home模板,我们应该在此处放置一个链接,以供登录用户使用,以便他们只需单击即可进入管理界面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| /** * FILE: * Sources/App/Modules/Frontend/Views/Home.leaf */
#extend("Frontend/Index"): #export("body"): <section class="wrapper"> <h2>#(header)</h2> </section> <section class="wrapper"> <p>#(message)</p> </section> <section class="wrapper"> #if(email != nil): <p><b>#(email)</b> 已登录.</p> <a href="/admin">Admin</a> · <a href="/logout">Logout</a> #else: <a href="/sign-in">登录</a> #endif </section> #endexport #endextend
|
运行该应用程序,使用默认用户帐户登录,然后单击管理菜单。 现在,我们有了CMS的基础。 这些步骤现在应该已经很熟悉了,最后我们可以继续前进并建立一些实际的内容管理屏幕。