基于上一篇中的开发基本上实现了登录注册,通过token拿数据等一些登录涉及到的功能开发,基本上后端的功能已全部完成,可以看下上一篇实现全栈收银系统(Node+Vue)(上)的分享。 今天我们需要进行实现的功能包前端页面的编写和开发
创建在node-app项目(即在node项目里面)
vue create client
安装命令 npm install concurrently
将Vue项目执行运行的命令添加 "start": "npm run serve"
在node项目中配置成,我们只需要执行 npm run dev
就能让后台跟前台都运行起来
在路由页面中
{ path: '*', name: '/404', component: NotFound }, 复制代码
请求拦截
axios.interceptors.request.use(config => { return config; },error => { return Promise.reject(error); }) 复制代码
响应拦截
axios.interceptors.response.use(response => { return response; }, error => { Message.error(erroe.response.data); return Promise.reject(error); }) 复制代码
记得 export default axios
main.js中配置 Vue.prototype.$axios = axios;
npm install jet-decode
jwt_decode(token)
const type = { SET_AUTHENTICATION: "SET_AUTHENTICATION", //判断是否认证通过 (自定义的type名称) SET_USER: 'SET_USER', } const mutations ={ [type.SET_AUTHENTICATION](state,isAuthentication) { if(isAuthentication) state.isAuthentication = isAuthentication; else state.isAuthentication = false; }, [type.SET_USER](state,user) { if(user) state.user = user; else state.user = {}; }, } const actions = { //异步操作 setAuthentication: ({commit},isAuthentication) => { commit(type.SET_AUTHENTICATION,isAuthentication); }, setUser:({commit},user) => { commit(type.SET_USER,user); }, } 复制代码
登录操作
// 解析token const decode = jwt_decode(token); // 存储数据 this.$store.dispatch("setAuthentication", !this.isEmpty(decode)); this.$store.dispatch("setUser", decode); 复制代码
获取相应的头像,名字,等级我们可以在登录的时候通过解析tonken获取到的信息赋值,由于我们登录的时候将解析的tonken存入vuex中,故我们可以进行取值
token信息
获取tonken信息<span>{{user.name}}</span> computed: { user() { return this.$store.getters.user; } } 复制代码
操作跟我们token过期操作雷同,需要清除相应的token数据,将状态更改为false ,故我们可以通过vuex中为退出设置个方法调用即可
//vuex const actions = { //退出登录清除状态 clearCurrentState:({commit}) => { commit(type.SET_AUTHENTICATION,false); commit(type.SET_USER,null) } } // HeadNav logout() { localStorage.removeItem('eleToken'); //设置vuex store this.$store.dispatch('clearCurrentState'); //跳转 this.$router.push('/login'); } 复制代码
参考element中的table自定义列模板 ,此处的数据遍历按照文档中的走相应的更改字段即可
此处实现是雷同的,共用同个弹窗组件,其中涉及到父子组件之间的相互传值。 新建出dialog自定义内容,此处技术点
// 由父组件的数据传入进行接收 props: { dialog: Object, form: Object }, // 提交表单以后将数据传回去给父组件 (此处的提交写法是表单额提交写法) onSubmit(form) { this.$refs[form].validate(valid => { if (valid) { //表单数据验证完成之后,提交数据; const url = this.dialog.option == "add" ? "add" : `edit/${this.form.id}`; this.$axios.post(`/api/profile/${url}`, this.form).then(res => { // 操作成功 this.dialog.show = true; this.$emit("update"); }); } }); } 复制代码
添加的时候,我们通过点击父页面改变自定义的数组数据,让子组件显示,通过提交数据传回给父组件,update
刷新父组件当前列表重新请求,继而关闭弹窗。
在此处中我们对不同操作相应的data数据都要做处理,编辑的时候,我们对from中的数据进行赋值操作,添加的时候清空数据
<!-- 弹框页面 --> <DialogFound :dialog='dialog' :form='form' @update="getProfile"></DialogFound> data() { //这些数据是自定义的数据,包括表单信息,控制子组件的数组数据 dialog: { show: false, title: "", option: "edit" }, form: { type: "", describe: "", income: "", expend: "", cash: "", remark: "", id: "" }, }, methods: { //刷新数据 getProfile() { // 获取表格数据 this.$axios("/api/profile").then(res => { // this.tableData = res.data; this.allTableData = res.data; this.filterTableData = res.data; // 设置分页数据 this.setPaginations(); }); }, } 复制代码
element自带了方法,我们只需要获取拿了进行使用就行了
onDeleteMoney(row, index) { // 删除 this.$axios.delete(`/api/profile/delete/${row._id}`).then(res => { console.log(JSON.stringify(res)); this.$message("删除成功"); this.getProfile(); }); }, 复制代码
模板参考element的分页,根据分页我们需要自定义的数组数据进行收集赋值
paginations: { page_index: 1, // 当前位于哪页 total: 0, // 总数 page_size: 5, // 1页显示多少条 page_sizes: [5, 10, 15, 20], //每页显示多少条 layout: "total, sizes, prev, pager, next, jumper" // 翻页属性 }, 复制代码
我们需要再第一次数据加载的时候获取到全部的数组数据allTableData
,设置一个空数组,将储存 过滤后的数组数据
setPaginations() { // 总页数 this.paginations.total = this.allTableData.length; this.paginations.page_index = 1; this.paginations.page_size = 5; // 设置默认分页数据 //此处便将总的数据进行遍历,根据设置的初始值,将返回为true的数据储存在空数组中 this.tableData = this.allTableData.filter((item, index) => { console.log(index < this.paginations.page_size); return index < this.paginations.page_size; //return index < page_size; 根据切换的页数进行过滤 }); console.log( this.tableData ) }, 复制代码
实现切换页数进行数据的改变
handleCurrentChange(page) { // 当前页 let sortnum = this.paginations.page_size * (page - 1); let table = this.allTableData.filter((item, index) => { return index >= sortnum; }); // 设置默认分页数据 this.tableData = table.filter((item, index) => { return index < this.paginations.page_size; }); //第二种的实现 // let tables = []; // for(let i=index;i<nums;i++) { // if(this.allTableData[i]) { // tables.push(this.allTableData[i]); // } // this.tableData = tables // } }, 复制代码
时间的筛选中,我们需要重新定义一个新的全部数据的数组,通过获取两个时间段的时间格式后进行比较赋值到计算分页的数组当中,重新再执行分页的初始化函数
onScreeoutMoney() { // 筛选 if (!this.search_data.startTime || !this.search_data.endTime) { this.$message({ type: "warning", message: "请选择时间区间" }); this.getProfile(); return; } const stime = this.search_data.startTime.getTime(); //开始时间 const etime = this.search_data.endTime.getTime(); //结束时间 this.allTableData = this.filterTableData.filter(item => { let date = new Date(item.date); let time = date.getTime(); return time >= stime && time <= etime; }); // 分页数据 this.setPaginations(); } }, 复制代码
最终实现了vue+node实现的后台系统
代码已上传github,请给star,后续继续更新,多谢支持