初学nodejs+express,打造cms系统(4)
前面已经改造了基础模块,下面到了页面制作环节。先前的脚手架已经支持ejs了,在views文件夹里出现了测试ejs,下面基本上是锻炼自己仿写能力了。
【routes/api.js】
var express = require('express'); var router = express.Router(); var base = require('../function/base'); base.use(['config','fun','db_mysql']); var db=base.db_mysql; db.init(base.config.mysql); base.db=db; base.$config=base.db.select_one("select * from config where tag='config'"); router.use('/', function(req, res, next) { base.use('req_res',{req:req,res:res}); var req_res=base.req_res; var $ac=base.fun.str(req.query["action"]); var $model=base.fun.str(req.query["model"]); base.$model=$model; if($model=='') { //首页 res.send('404'); return; }else{ if($ac=='') { //默认为功能首页 $ac='index'; } //get view层(view层里绑定具体哪一个view) var api_path=`../api/${$model}`; console.log(api_path); var api_action=require(api_path); api_action.init(base,$model,$ac);//装载 try{ var this_type=typeof(api_action.action[$ac]); }catch(e){ var this_type=''; } if(this_type=='undefined') { //部分无关紧要的页面效果 res.send('404'); }else{ api_action.action[$ac](); } // return; } }); module.exports = router;
先有个管理view的路由,然后通过先前的routes/admin.js,api_action.action[$ac]();对应admin/admin/${model}.js进行行为控制
即views/login.ejs - > admin/admin/login.js 一一对应着开发
【views/login.ejs】
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link href="assets/images/favicon.ico" rel="icon"> <title><%= title %></title> <link rel="stylesheet" href="assets/libs/layui/css/layui.css"/> <link rel="stylesheet" href="assets/module/admin.css?v=318"/> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body class="layui-layout-body"> <div class="layui-layout layui-layout-admin"> <!-- 头部 --> <div class="layui-header"> <div class="layui-logo"> <img src="assets/images/logo.png"/> <cite> EasyWeb iframe</cite> </div> <ul class="layui-nav layui-layout-left"> <li class="layui-nav-item" lay-unselect> <a ew-event="flexible" title="侧边伸缩"><i class="layui-icon layui-icon-shrink-right"></i></a> </li> <li class="layui-nav-item" lay-unselect> <a ew-event="refresh" title="刷新"><i class="layui-icon layui-icon-refresh-3"></i></a> </li> </ul> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item" lay-unselect> <a ew-event="message" title="消息"> <i class="layui-icon layui-icon-notice"></i> <span class="layui-badge-dot"></span> </a> </li> <li class="layui-nav-item" lay-unselect> <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a> </li> <li class="layui-nav-item layui-hide-xs" lay-unselect> <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a> </li> <li class="layui-nav-item layui-hide-xs" lay-unselect> <a ew-event="lockScreen" title="锁屏"><i class="layui-icon layui-icon-password"></i></a> </li> <li class="layui-nav-item" lay-unselect> <a> <img src="assets/images/head.jpg" class="layui-nav-img"> <cite>管理员</cite> </a> <dl class="layui-nav-child"> <dd lay-unselect><a ew-href="page/template/user-info.html">个人中心</a></dd> <dd lay-unselect><a ew-event="psw">修改密码</a></dd> <hr> <dd lay-unselect><a ew-event="logout" data-url="page/template/login/login.html">退出</a></dd> </dl> </li> <li class="layui-nav-item" lay-unselect> <a ew-event="theme" title="主题"><i class="layui-icon layui-icon-more-vertical"></i></a> </li> </ul> </div> <!-- 侧边栏 --> <div class="layui-side"> <div class="layui-side-scroll"> <ul class="layui-nav layui-nav-tree arrow2" lay-filter="admin-side-nav" lay-shrink="_all"> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-home"></i> <cite>Dashboard</cite></a> <dl class="layui-nav-child"> <dd><a lay-href="page/console/workplace.html">工作台</a></dd> <dd><a lay-href="page/console/console.html">控制台</a></dd> <dd><a lay-href="page/console/dashboard.html">分析页</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-set"></i> <cite>系统管理</cite></a> <dl class="layui-nav-child"> <dd><a lay-href="page/system/user.html">用户管理</a></dd> <dd><a lay-href="page/system/role.html">角色管理</a></dd> <dd><a lay-href="page/system/authorities.html">权限管理</a></dd> <dd><a lay-href="page/system/dictionary.html">字典管理</a></dd> <dd><a lay-href="page/system/organization.html">机构管理</a></dd> <dd><a lay-href="page/system/login-record.html">登录日志</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-template"></i> <cite>模板页面</cite></a> <dl class="layui-nav-child"> <dd> <a>表单页</a> <dl class="layui-nav-child"> <dd><a lay-href="page/template/form/form-basic.html">基础表单</a></dd> <dd><a lay-href="page/template/form/form-advance.html">复杂表单</a></dd> <dd><a lay-href="page/template/form/form-step.html">分步表单</a></dd> </dl> </dd> <dd> <a>列表页</a> <dl class="layui-nav-child"> <dd><a lay-href="page/template/table/table-basic.html">数据表格</a></dd> <dd><a lay-href="page/template/table/table-advance.html">复杂表格</a></dd> <dd><a lay-href="page/template/table/table-img.html">图片表格</a></dd> <dd><a lay-href="page/template/table/table-card.html">卡片列表</a></dd> </dl> </dd> <dd> <a>错误页</a> <dl class="layui-nav-child"> <dd><a lay-href="page/template/error/error-500.html">500</a></dd> <dd><a lay-href="page/template/error/error-404.html">404</a></dd> <dd><a lay-href="page/template/error/error-403.html">403</a></dd> </dl> </dd> <dd> <a>登录页</a> <dl class="layui-nav-child"> <dd><a href="page/template/login/login.html" target="_blank">登录页</a></dd> <dd><a href="page/template/login/reg.html" target="_blank">注册页</a></dd> <dd><a href="page/template/login/forget.html" target="_blank">忘记密码</a></dd> </dl> </dd> <dd><a lay-href="page/template/user-info.html">个人中心</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-component"></i> <cite>扩展组件</cite></a> <dl class="layui-nav-child"> <dd> <a>常用组件</a> <dl class="layui-nav-child"> <dd><a lay-href="page/plugin/basic/dialog.html">弹窗扩展</a></dd> <dd><a lay-href="page/plugin/basic/dropdown.html">下拉菜单</a></dd> <dd><a lay-href="page/plugin/basic/notice.html">消息通知</a></dd> <dd><a lay-href="page/plugin/basic/tagsInput.html">标签输入</a></dd> <dd><a lay-href="page/plugin/basic/cascader.html">级联选择</a></dd> <dd><a lay-href="page/plugin/basic/steps.html">步骤条</a></dd> </dl> </dd> <dd> <a>进阶组件</a> <dl class="layui-nav-child"> <dd><a lay-href="page/plugin/advance/printer.html">打印插件</a></dd> <dd><a lay-href="page/plugin/advance/split.html">分割面板</a></dd> <dd><a lay-href="page/plugin/advance/formX.html">表单扩展</a></dd> <dd><a lay-href="page/plugin/advance/tableX.html">表格扩展</a></dd> <dd><a lay-href="page/plugin/advance/dataGrid.html">数据列表</a></dd> <dd><a lay-href="page/plugin/advance/contextMenu.html">鼠标右键</a></dd> </dl> </dd> <dd> <a>其他组件</a> <dl class="layui-nav-child"> <dd><a lay-href="page/plugin/other/circleProgress.html">圆形进度条</a></dd> <dd><a lay-href="page/plugin/other/editor.html">富文本编辑</a></dd> <dd><a lay-href="page/plugin/other/mousewheel.html">鼠标滚轮</a></dd> <dd><a lay-href="page/plugin/other/other.html">更多组件</a></dd> </dl> </dd> <dd><a lay-href="page/plugin/more.html">更多扩展</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-app"></i> <cite>经典实例</cite></a> <dl class="layui-nav-child"> <dd><a lay-href="page/example/dialog.html">弹窗实例</a></dd> <dd><a lay-href="page/example/course.html">课程管理</a></dd> <dd><a lay-href="page/example/calendar.html">排课管理</a></dd> <dd><a lay-href="page/example/question.html">添加试题</a></dd> <dd><a lay-href="page/example/file.html">文件管理</a></dd> <dd><a lay-href="page/example/table-crud.html">表格CRUD</a></dd> <dd><a href="page/example/side-more.html" target="_blank">多系统模式</a></dd> <dd><a href="page/example/side-ajax.html" target="_blank">Ajax侧边栏</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-release"></i> <cite>LayUI组件</cite></a> <dl class="layui-nav-child"> <dd><a lay-href="page/plugin/other/layui.html">组件演示</a></dd> <dd><a lay-href="https://www.layui.com/doc/element/button.html#use">layui文档</a></dd> <dd><a lay-href="https://layer.layui.com/">layer弹窗</a></dd> <dd><a lay-href="https://www.layui.com/laydate/">laydate日期</a></dd> </dl> </li> <li class="layui-nav-item"> <a><i class="layui-icon layui-icon-unlink"></i> <cite>多级菜单</cite></a> <dl class="layui-nav-child"> <dd><a>二级菜单</a></dd> <dd> <a>二级菜单</a> <dl class="layui-nav-child"> <dd><a lay-href="javascript:layer.msg('Hello!');">三级菜单</a></dd> <dd> <a>三级菜单</a> <dl class="layui-nav-child"> <dd><a lay-href="javascript:;">四级菜单</a></dd> <dd> <a>四级菜单</a> <dl class="layui-nav-child"> <dd><a>五级菜单</a></dd> <dd> <a lay-href="https://baidu.com">百度一下</a> </dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </li> <li class="layui-nav-item"> <a lay-href="//baidu.com"><i class="layui-icon layui-icon-unlink"></i> <cite>一级菜单</cite></a> </li> </ul> </div> </div> <!-- 主体部分 --> <div class="layui-body"></div> <!-- 底部 --> <div class="layui-footer layui-text"> copyright © 2020 <a href="http://easyweb.vip" target="_blank">easyweb.vip</a> all rights reserved. <span class="pull-right">Version 3.1.8</span> </div> </div> <!-- 加载动画 --> <div class="page-loading"> <div class="ball-loader"> <span></span><span></span><span></span><span></span> </div> </div> <!-- js部分 --> <script type="text/javascript" src="./assets/libs/layui/layui.js"></script> <script type="text/javascript" src="./assets/js/common.js?v=318"></script> <script> layui.use(['index'], function () { var $ = layui.jquery; var index = layui.index; // 默认加载主页 index.loadHome({ menuPath: 'page/console/workplace.html', menuName: '<i class="layui-icon layui-icon-home"></i>' }); }); </script> </body> </html>
前端代码简单参考一下,这个是模板化的,不是前后端分离,现在很少用了。但是我的低代码模式可以巧妙的用这种模版化的,效果比较佳,尤其适合我们小公司做敏捷开发。开发一些小系统。
【admin/admin/login.js】
//api库 var api={ init(base,$model){ this.action.base=base; this.action.$model=$model; this.action.req_res=base.req_res; this.action.res=base.req_res.res; this.action.req=base.req_res.req; this.action.db=base.db; this.action.admin=base.admin; this.action.fun=base.fun; } ,action:{ logincp(){ var me=this; console.log('logincp'); var username=me.fun.str(me.req.body.username); var password=me.fun.str(me.req.body.password); if(username.length<3) { var json={success:false,msg:'用户名输入长度太短'}; me.res.json(json); return; } if(password.length<3) { var json={success:false,msg:'密码输入长度太短'}; me.res.json(json); return; } var check_sql=`select * from admin where admin_username='${username}' `; var check_info=me.db.select_one(check_sql); if(me.fun.str(check_info['admin_username'])=='') { var json={success:false,msg:'用户不存在'}; me.res.json(json); return; } if(me.fun.str(check_info['admin_password'])!=password) { var json={success:false,msg:'密码错误'}; me.res.json(json); return; } if(me.fun.str(check_info['used'])==0) { var json={success:false,msg:'帐号已被禁用'}; me.res.json(json); return; } //成功 me.req_res.admin_logingo(username); me.res.json({success:true,msg:'登录成功'}); return; } ,loginout(){ var me=this; console.log('loginout'); me.req_res.admin_loginout(); me.res.json({success:true,msg:'退出登录成功'}); return; } } }; module.exports = api;
这里有一个细节,我们action=add打开的是模版页面,action=save可能就是一个接口。
,add(){ var me=this; console.log('add'); me.base.$tpl.info={}; me.res.render(`admin/${me.$model}/${me.$model}_add`, { base: me.base,$tpl:me.base.$tpl,$model:me.$model,$ac:me.$ac }); return; }
,save(){ var me=this; console.log('save'); me.fun.addlog(`ADMIN model:${me.$model} action:${me.$ac}`); var this_id=me.fun.str(me.req.body.id); var sqlstr=me.fun.str(me.req.body.field); var notin=['id','ID','field']; if(this_id=='') { var sqlarr=me.db.myinsertsql(me.req,sqlstr,notin,"post"); var sql1=sqlarr[0]; var sql2=sqlarr[1]; var sql=`insert into ${this.table} (${sql1}) values (${sql2})`; }else{ var sqlarr=me.db.myupsql(me.req,sqlstr,notin,"post"); var sqlx=sqlarr[0]; var sql=`update ${this.table} set ${sqlx} where id ='${this_id}'`; } me.fun.addlog(sql); var r=me.db.dosql(sql); if(r) { var output={success:true,msg:'操作成功'}; }else{ var output={success:false,msg:'操作失败'}; } me.fun.addlog(JSON.stringify(output)); me.res.json(output); return; }
好了,后面的工作就是写页面、写接口。由于数据库改成同步了,增删改查,跟PHP无比接近了。
后面差不多就是上传、数据导入导出等特别功能要专门研究了。