您的位置:首页 > Web前端 > Vue.js

vue,vuex的后台管理项目架子structure-admin,后端服务nodejs,前端vue页面

2018-09-18 20:14 2915 查看
之前写过一篇vue初始化项目,构建vuex的后台管理项目架子,这个structure-admin-web所拥有的功能

1、vuex来实现状态管理

2、静态页面,未引入后端服务

3、组件是用的是element-ui

4、页面布局是上左右,左右布局使用的弹性和布局flex,左边定宽,右边计算宽度

5、左右的滚动条是相互独立的,去掉body上的滚动条

6、没有业务代码,仅仅是一个静态的vuex的架子

说明:之前使用左侧menu的fixed布局,发现element-ui的弹窗组件不能正常显示,考虑换成flex布局


接下来,针对structure-admin-web的不足,进行了补充,开发了具有登陆的structure-admin项目,技术站:主要是node+vue+redis+mysql+es6

欢迎访问github源码:https://github.com/saucxs/structure-admin

项目地址演示地址:http://120.27.109.67:8089/#/departmentManage,测试的账号:test,密码:123456

接下来:

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

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

三、项目启动必读

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

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

1、首先介绍登陆的控制

逻辑:

(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 功能。

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

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


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

3、数据库的配置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

4、操作数据库

项目开发中,经常需要操作数据库(如:增删改查等功能),手工拼写 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/3.0/relation_model.html

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

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

1、全局路由守卫

全局路由守卫是每一次都会判断是否登陆(也就是判断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
}]
}
]


2、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,
}


三、项目启动必读

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

2、clone下来项目

git clone https://github.com/saucxs/structure-admin.git[/code] 
3、分别针对前端vuestructure-admin-web的文件夹和node后端structure-admin-node,安装相应依赖

npm install


4、安装redis(可以考虑安装RedisDesktopManager)

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

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

6、修改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
}
};


7、分别对前后端分离的项目启动

(1)前端vuestructure-admin-web的启动

npm run dev


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

npm start


8、这样就可以启动

(1)登陆页



(2)写周报页面



9、欢迎fork和start该项目

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

不懂的地方可以提issue,欢迎提出来共同探讨

10、该项目架子搭的周报企业管理系统

在PC端,欢迎访问:http://120.27.109.67:8089/#/departmentManage,这个账号和密码,给出一个测试的,账号:test,密码:123456
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐