家政服务平台后台管理系统
前言
该文记录博主做项目时的大致流程和遇到的问题及如何解决。
视图:基于vue框架,大量运用ElementUI组件;
数据:从云服务器上通过若干接口传输到项目。
综合运用了项目依赖【dependencies】axios,element-ui,vue,vue-router,vuex
本文是基于其中一个小模块-顾客模块,展开来说的
第一步-项目部署:
有以下三种方法:
- 部署到自己的云服务器上
- 部署到本地
- 直接调用别人已经部署好的接口
这里以部署本地为例(简):
第一步:在Navicat中新建数据库并导入sql文件,设置该数据库的权限等;
第二步:在终端中运行java文件【此时后台数据已经就位】;
第三步:打开vue-admin-template-master半成品框架,执行cnpm install命令完成初始化项目;
第四步:npm run dev跑项目
...
第二步-修改框架
刚到手的框架内的数据基本都是为使用者提供指南的数据,所以我们要将不用的数据/用不到的数据修改或删除。
修改基路径
.env.development
.env.production
两个文件中将原VUE_APP_BASE_API注释掉,替换成不是的接口基路径(修改完需要重启项目才会生效)
# VUE_APP_BASE_API = ‘/prod-api’
VUE_APP_BASE_API = ‘http:/localhost:端口号’
对于登录
登录模块流程
登录总结:
第一步index.vue中发送一个登录表单loginForm至状态机中的login方法
【框架的优越性:只调用一个方法->自己内部逻辑中访问了多个文件夹(方便后期维护项目,大大减少了修改的工作量)】
第二步login方法拿到token,并将token设置到全局
第三步在request方法中拿到token,并设置到请求头
第四步在response方法中判断状态码,若成功200返回成功对象
第五步push方法跳转至'/'
下面是代码:
登录方法handleLogin中对refs中的loginForm表单数据valid进行了校验,
校验中使用了状态机store的dispatch方法,该状态机存在于/src/store/moduler/user.js
调用了状态机中的login方法,
// @/views/login/index.vue
handleLogin() {
// 对refs中名为loginForm的表单进行了校验,校验的值valid
this.$refs.loginForm.validate(valid => {
if (valid) {
// 模态框加载
this.loading = true
// 使用了状态机store中user的login方法
// 该状态机存在于/src/store/moduler/user.js
console.log(this.loginForm)
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ path: this.redirect || '/' })
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
向后台提交的数据username、password、type都会被捕捉到this.loginForm
而状态机会从中解构数据
login({ commit }, userInfo) {
const { username, password, type } = userInfo...
状态机中login方法来自@/api/user
// @/api/user.js
import request from '@/utils/request'
// 默认到处三个方法
export function login(data) {
return request({
url: '/user/login',
method: 'post',
data
})
}
export function getInfo(token) {
return request({
url: '/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/user/logout',
method: 'post'
})
}
login方法中返回的request方法来自@/utils/request
在request中// 全局最初写后台访问请求的各种方法,
请求拦截/响应拦截
请求拦截中判断是否含有token若有则在请求头部添加属性值Authorization=TOKEN
响应拦截中根据不同的状态码response.data.status做出不同提示信息
当状态码为200时返回response.data
// @/utils/request
service.interceptors.request.use(
config => {
// do something before request is sent
// 判断请求中是否有token
if (store.getters.token) {
// let each request carry token
// ['Authorization'] is a custom headers key
// please modify it according to the actual situation
// 请求头中添加一条属性值
config.headers['Authorization'] = getToken()
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
service.interceptors.response.use(...)
登录页面预览:
对于顾客模块
一、 修改侧边栏一个路由@/router/index.js
当路由配置好后发现右边内容区域,是顶格显示:
选中css样式然后在VScode中点击Search图标,粘贴找到对应css修改
二、布局
第一件事:打开要参考的原型或网站查看布局
【在main.js中可以将ElementUI的样式设置为中文/英文】
load方法:将数据导入
在分页区域问题:/customer/query方法传参page,pageSize需要的类型是query类型(而默认json字符串)
这是就需要导入qs,在查询字符串之前qs.stringify(this,params)进行数据转换为查询字符串
三、增删改查
点击新增/修改时出现模态框,点击删除时获取当前行id
【外键:用户下单,订单还未完成,不可删除】
详情按钮:页面跳转
在方法中通过this.$router.push() - 路由跳转
跳转过去后,有返回按钮
Element中的页头样式
跳转时,携带参数row
传【handleDetails方法中】 - this.$router.push({ path: 'customerDetails', query: { row }})
收【created生命周期函数中】 - this.$route.query.row
详情页面 - ElementUI的Card组件
在@/router/index.js中配置路由,并且在views目录下创建路径
// 顾客端
{
path: '/customer',
// 是否侧边栏显示
component: Layout,
// 重定向到/customer/index
redirect: '/customer/index',
name: 'Customer',
meta: { title: '顾客管理', icon: 'example' },
children: [
{
// 默认路径
path: 'customer',
name: 'Customer',
// 组件路径
// 法一:views修改原文件|法二:在views目录下重新创建一个customer|法三:在@/下创建pages自己定义路径
component: () => import('@/views/customer/index'),
meta: { title: '顾客管理', icon: 'table' }
},
{
path: 'customerDetails',
name: 'CustomerDetails',
// 将顾客看详情隐藏
hidden: true,
component: () => import('@/views/customer/customerDetails'),
meta: { title: '顾客详情', icon: 'tree' }
}
]
},
页面如下:
在customer/index.vue中大致分为:上方按钮搜索区域、中间表格区域、下方分页区域
这些框架都可以在ElementUI中找到,我们只需要修改其中的数据/参数即可
最后显示的页面布局如下:
在index.vue中导入request方法,并且调用post/get方法进行数据的加载
load() {
request.post('/customer/query', qs.stringify(this.params)).then((res) => {
this.tableData = res.data
})
新增/修改模态框
// 新增操作
add() {
this.title = '新增顾客'
this.dialogFormVisible = true
},
// onSubmit新增模态框中提交按钮
onSubmit() {
request.post('/customer/saveOrUpdate', qs.stringify(this.form)).then((res) => {
this.$message({
message: res.message,
type: 'success'
})
// 关闭模态框
this.dialogFormVisible = false
// 刷新数据
this.load()
})
},
customerDetails.vue页面(点击【详情】按钮跳转页面)同理,布局如下:
上方的标签页tabs可以在ElementUI中找到。
其中遇到的问题,时间戳转换:
formatDate(row, column, cellValue, index) {
if (cellValue === null || cellValue === '') return ''
// 时间戳为10位需*1000,如果为13位的话不需乘1000。
const date = new Date(parseInt(cellValue))
const Y = date.getFullYear() + '-'
const M = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) + '-' : date.getMonth() + 1 + '-'
const D = date.getDate() < 10 ? '0' + date.getDate() + ' ' : date.getDate() + ' '
const h = date.getHours() < 10 ? '0' + date.getHours() + ':' : date.getHours() + ':'
const m = date.getMinutes() < 10 ? '0' + date.getMinutes() + ':' : date.getMinutes() + ':'
const s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return Y + M + D + h + m + s
}
<span class="cusDetails">注册时间: </span>{{ formatDate(null, null, info.registerTime, null) }}<br>
遇到了如下浏览器错误:
大致意思为本应传入的数据为数组类型,而传入了对象。。。
data() {
return {
info: {},
addressInfo: [],
commentInfo: {},
orderInfo: {},
// 基本信息默认
activeName: 'first',
// load方法传参id
id: ''
}
},
错误原因就是上方代码中的addressInfo类型,应该将 addressInfo: {}改为 addressInfo: [],错误则消失了。
下面是页头的返回按钮方法:
// 页头返回键
goBack() {
// console.log('go back')
// 返回上一次
this.$router.go(-1)
},
总结:在Element-UI中,我们除了自己要用什么就搬什么之外,还要熟悉其中标签中的属性/方法,这些东西可以让我们事半功倍!说到这,最主要还是要熟悉。