后台管控系统架子structure-admin,包含vue前端和thinkjs后端

以前写过一篇vue初始化项目,构建vuex的后台管理项目架子,这个structure-admin-web所拥有的功能html

接下来,针对structure-admin-web的不足,进行了补充,开发了具备登录的structure-admin项目,前端

技术站:主要是node+vue+redis+mysql+es6vue

欢迎访问structure-admin源码:structure-adminnode

同步更新到sau交流学习社区:https://www.mwcxs.top/page/42...mysql

接下来:ios

1、后端服务nodejs,thinjs的redis配置,操做数据库git

2、前端vue+vuex全局路由守卫,axios请求拦截es6

3、项目启动必读github

1、后端服务nodejs,thinjs的redis配置,操做数据库

我使用的是thinkjs3,一个nodejs的框架。web

一、首先介绍登录的控制

逻辑:

(1)已经登录的,直接根据的路由跳到相应页面;

(2)已经登录的,不能跳到登录页面,跳到首页;

(3)没有登录的,输入url必须跳到登录页;

(4)退出系统的,必须回到登录页,状态是未登陆

1.1 thinkjs的redis的配置文件adapter.js

exports.session = {

type: 'redis',
common: {
    cookie: {
        name: 'thinkjs',
        keys: ['werwer', 'werwer'],
        signed: true
    }
},
redis: {
    handle: redisSession,
    host: '127.0.0.1',
    port: 6379,
    password: 'a123456'
}

};
设置的由redis的服务地址host,端口,以及redis的密码,redis的搭建和配置,参考安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目这篇文章。

1.2 在每一次前端请求的路由的时候,都会去redis服务器中去取userInfo的信息

若是为空,返回前端data为空,前端在路由过滤中,跳到登录页,若是有值就正常返回。

async __before() {

let user = await this.session("userInfo");
    if(user) {
        this.user = user;
    } else {
        this.user = '';
    }
}

这个在nodejs的控制器controller里,在每一次前端的请求发送到后端的时候,都会去redis的取userInfo的值,

let user = await this.session("userInfo");

这个userInfo的值也是本身在登录的时候,把登录成功以后的我的信息加入到redis服务中

1.3 在登录成功的时候讲我的信息加到redis服务中

async loginAction() {

let {username, password} = this.post();try {
        let user = await this.model('user').where({
            username,
        }).find();
        if(user.password && user.password == password) {
            // login success
            await this.session('userInfo',{username, userId:user.id});
            return this.success("登录成功");
        } else {
            return this.fail("用户名或密码错误")
        }
    }
    catch(e) {
        console.log(e);
        return this.fail("登陆失败")
    }

这个就是将我的信息加入到redis中

await this.session('userInfo',{username, userId:user.id});

WEB 请求中常常经过 session 来维持会话的,框架经过 think-session 和 Adapter 来支持 session 功能。

二、介绍登出(退出)的控制

async logoutAction() {
        try {
            await this.session(null);
            return this.success("登出成功");
        } catch(e) {
            return this.fail(`登出失败${e}`)
        }
    }

这个就是前端发的请求登出,直接将redis的置空,根据前端路由跳转到登录页,这时候redis的服务中没有值,就不会跳转到其余页面

三、数据库的配置adapter.js

exports.model = {
  type: 'mysql',
  common: {
    logConnect: true,
    logSql: true,
    logger: msg => think.logger.info(msg)
  },
  mysql: {
    handle: mysql,
    database: 'example',
    prefix: 'example_',
    encoding: 'utf8',
    host: '127.0.0.1',
    port: '3306',
    user: 'root',
    password: '123456',
    dateStrings: true
  }
};

common部分是配置是否将sql的语句的操做日志打出来,这样便于咱们在开发的时候的调试和修改bug

四、操做数据库

项目开发中,常常须要操做数据库(如:增删改查等功能),手工拼写 SQL 语句很是麻烦,同时还要注意 SQL 注入等安全问题。为此框架提供了模型功能,方便操做数据库。

Mysql 的 Adapter 为 think-model-mysql,底层基于 mysql 库实现,使用链接池的方式链接数据库,默认链接数为 1。

拿登录的接口来讲明:this.model说明使用封装好的model,find是查找单条数据,在user的这张表中查找username值为前端传来的username的值,返回的值赋给user中。

async loginAction() {
        let {username, password} = this.post();
        try {
            let user = await this.model('user').where({
                username,
            }).find();
            if(user.password && user.password == password) {
                // login success
                await this.session('userInfo',{username, userId:user.id});
                return this.success("登录成功");
            } else {
                return this.fail("用户名或密码错误")
            }
        }
        catch(e) {
            console.log(e);
            return this.fail("登陆失败")
        }

think.Model 基类提供了丰富的方法进行 CRUD 操做,下面来一一介绍。

查询数据

模型提供了多种方法来查询数据,如:

find 查询单条数据
select 查询多条数据
count 查询总条数
countSelect 分页查询数据
max 查询字段的最大值
avg 查询字段的平均值
min 查询字段的最小值
sum 对字段值进行求和
getField 查询指定字段的值
同时模型支持经过下面的方法指定 SQL 语句中的特定条件,如:

where 指定 SQL 语句中的 where 条件
limit / page 指定 SQL 语句中的 limit
field / fieldReverse 指定 SQL 语句中的 field
order 指定 SQL 语句中的 order
group 指定 SQL 语句中的 group
join 指定 SQL 语句中的 join
union 指定 SQL 语句中的 union
having 指定 SQL 语句中的 having
cache 设置查询缓存
添加数据
模型提供了下列的方法来添加数据:

add 添加单条数据
thenAdd where 条件不存在时添加
addMany 添加多条数据
selectAdd 添加子查询的结果数据
更新数据
模型提供了下列的方法来更新数据:

update 更新单条数据
updateMany 更新多条数据
thenUpdate 条件式更新
increment 字段增长值
decrement 字段减小值
删除数据
模型提供了下列的方法来删除数据:

delete 删除数据
用项目的代码举栗子:

(1)查询单条数据,用find(),条件为:工号(usernum)为180909,用户名(username)为saucxs ,而且填写时间(time)为这周的时间范围的时间戳,返回的是对象object

let weekly = await this.model('week').where({
     usernum: '180909', 
   username: 'saucxs', 
   time: {'>': startWeekStamp, '<': endWeekStamp}
 }).find();

解读:model('week')的意思,取得是week的数据表

(2)查询多条数据,用select(),条件:公司id(company_id)为data的数据,返回的是数组array

let department = await this.model('department').where({company_id: 'data'}).select();

(3)查询表中的具体的列数据,用field()

departmentMemberList = await this.model('user').field('id, company_id, company_name, department_id, department_name, email, role, role_name, username, usernum,telephone').where({
          company_id: this.user.company_id,
          role: {'>=': this.user.role}
        }).find();

解读:this.user.company_id取的是登录用户的公司id,{'>=': this.user.role}为比登录用户的角色

(4)分页查询,用page(page, pagesize)和countSelect(),返回的数据是对象

departmentMemberList = await this.model('user').field('id, company_id, company_name, department_id, department_name, email, role, role_name, username, usernum,telephone').where({
          company_id: this.user.company_id,
          role: {'>=': this.user.role}
        }).order("department_id asc , role asc").page(page, pagesize).countSelect();

解读:返回的对象,以下图所示:(count是总条数,currentPage为当前页,data是数据的数组,pageSize为每一页展现几条,totalPages为总共有多少页)

(5)排序,倒序(desc)和正序(asc),用order("参数1 asc,参数2 desc”)

departmentMemberList = await this.model('user').field('id, company_id, company_name, department_id, department_name, email, role, role_name, username, usernum,telephone').where({
          company_id: this.user.company_id,
          role: {'>=': this.user.role}
        }).order("department_id asc , role asc").page(page, pagesize).countSelect();

(6)删除,用delete(),条件用where

await this.model('department').where({company_id, department_id}).delete();

(7)新增,用add(),没有where

await this.model('department').add({
          company_id: this.user.company_id, company_name: this.user.company_name, department_id, department_name
        });

(8)改,用update(),条件where

await this.model('user').where({id}).update({
                usernum, username, telephone, role, role_name,email, company_id, company_name, department_id, department_name
              });

手动执行 SQL 语句
有时候模型包装的方法不能知足全部的状况,这时候须要手工指定 SQL 语句,能够经过下面的方法进行:

query 手写 SQL 语句查询
execute 手写 SQL 语句执行
具体的能够参考thinkJS的官方文档的数据操做这块:https://thinkjs.org/zh-cn/doc...

2、前端vue+vuex全局路由守卫,axios请求拦截

刚才简单的说了一下nodejs的后端启动的服务,封装的接口,而前端调用这个接口使用的是url是:模块名/控制器名/方法名,这个能够在配置文件中修改定义的方法

一、全局路由守卫

全局路由守卫是每一次都会判断是否登录(也就是判断redis服务中是否有值)。已经登录(后端返回的用户权限信息),则判断当前要跳转的路由,用户是否有权限访问,能够考虑在用户登录以后将用户权限把路由过滤一遍生成菜单,菜单保存到vuex中。

/*路由处理*/
router.beforeEach((to, from, next) => {
  let menuId;
  let auditResult;
  let applicationVerifyFlag;
  let key = to.meta.key;
  if (key) {
    store.dispatch("getUserInfo", {}).then(response => {if(!response.data){
        if (to.path !== '/login') {
          return next('/login');
        }
        next();
      }else{
        if (to.path == '/login') {
          return next('/writeWeekly');
        }
        store.commit("USER_INFO", response.data);
        next();
      }
    });
  } else {
   next();
  }
});

根据这个key来判断是否有权限,取得是路由中meta的key的值。

routes: [
    {
      path: '/login',
      name: 'login',
      meta: {
        key: '0'
      },
      component: login
    },
    {
      path: '/',
      name: 'home',
      component: home,
      children: [{
        path: '/writeWeekly',
        name: 'writeWeekly',
        meta: {
          key: '1'
        },
        component: writeWeekly
      }]
    }
  ]

二、axios请求拦截

统一处理全部的http请求和响应的,经过配置http request interceptors为http头部增长Authorization字段,其内容为Token,经过配置http response interceptors,当后端接口返回401 Unauthorized(未受权),让用户从新登陆。

// 开发环境调试用户信息
axios.interceptors.request.use(config => {
    if (process.env.NODE_ENV === 'development') {
      config.headers["username"] = "189090909";
    }
    return config;
});

axios.interceptors.response.use(
  response => {
    let data = response.data;
    console.log(data, 'data');
    if (!data.data) {
      //   登录成功的回调地址
      return data;
    } else {
      return data;
    }
  },
  error => ({
    code: -1,
    msg: "网络异常"
  })
);

对全部的请求进行了封装。

// get请求配置
let getConfig = {
    url: '',
    baseURL: serveUrl,
    headers: {
    'X-Requested-With': 'XMLHttpRequest'
  },
  paramsSerializer(params) {
    return Qs.stringify(params, {
      arrayFormat: 'brackets'
    })
  },
  timeout: 5000
}

// post请求配置
let postConfig = {
    url: '',
    baseURL: serveUrl,
    headers: {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    transformRequest: [function (data) {
      return JSON.stringify(data.params || {})
    }],
    timeout: 5000
}

export {
    serveUrl,
    getConfig,
    postConfig,
  }

3、项目启动必读

一、首先你的环境是nodejs,不会安装配置参考:http://www.mwcxs.top/page/420...

二、clone下来项目

git clone https://github.com/saucxs/structure-admin.git

三、分别针对前端vue的structure-admin-web的文件夹和node后端structure-admin-node,安装相应依赖

npm install

四、安装redis(能够考虑安装RedisDesktopManager)

参考:安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目

五、安装mysql,这个就不赘述

六、修改nodejs的后端的配置文件adapter.js,config.js这两个文件中

adapter.js

exports.cache = {
    type: 'redis',
    common: {
        timeout: 24 * 60 * 60 * 1000 // millisecond
    },
    redis: {
        handle: redisCache,
        host: '127.0.0.1',
        port: 6379,
        password: 'a123456'  //redis安装时候设置的秘密
    }
};
//
//
exports.model = {
  type: 'mysql',
  common: {
    logConnect: true,
    logSql: true,
    logger: msg => think.logger.info(msg)
  },
  mysql: {
    handle: mysql,
    database: 'weekly',
    prefix: 'week_',
    encoding: 'utf8',
    host: '127.0.0.1',   //本地数据库
    port: '3306',     //数据库端口
    user: 'root',    //数据库的用户名
    password: '123456',    //数据库该用户名的密码
    dateStrings: true
  }
};

七、分别对先后端分离的项目启动

(1)前端vue的structure-admin-web的启动

npm run dev

(2)和node后端structure-admin-node的启动

npm start

八、这样就能够启动

(1)登录页

clipboard.png

(2)写周报页面

clipboard.png

structure-admin架子线上地址:http://structure_admin.mwcxs.top
测试帐号:test,密码:123456

九、该架子搭的周报企业管理系统

在PC端,欢迎访问:http://weekly.mwcxs.top

(公司负责人)帐号:testadmin,密码:123456(部门经理)帐号:test,密码:123456(成员)帐号:teststaff,密码:123456

相关文章
相关标签/搜索