之前寫過一篇vue初始化項目,構建vuex的后台管理項目架子,這個structure-admin-web所擁有的功能
接下來,針對structure-admin-web的不足,進行了補充,開發了具有登陸的structure-admin項目,技術站:主要是node+vue+redis+mysql+es6
歡迎訪問structure-admin源碼:structure-admin
歡迎訪問weekly源碼:weekly
項目地址演示地址:http://weekly.mwcxs.top
- (公司負責人)賬號:testadmin,密碼:123456
- (部門經理)賬號:test,密碼:123456
- (成員)賬號:teststaff,密碼:123456
PS:添加的成員的默認密碼是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 設置查詢緩存
添加數據
模型提供了下列的方法來添加數據:
更新數據
模型提供了下列的方法來更新數據:
- 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 語句,可以通過下面的方法進行:
具體的可以參考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/420.html
2、clone下來項目
git clone https://github.com/saucxs/structure-admin.git
3、分別針對前端vue的structure-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)前端vue的structure-admin-web的啟動
npm run dev
(2)和node后端structure-admin-node的啟動
npm start
8、這樣就可以啟動
(1)登陸頁

(2)寫周報頁面

9、該項目架子搭的周報企業管理系統
在PC端,歡迎訪問:http://weekly.mwcxs.top,
- (公司負責人)賬號:testadmin,密碼:123456
- (部門經理)賬號:test,密碼:123456
- (成員)賬號:teststaff,密碼:123456
