六、后台管理端【商家信息】页面逻辑
6.1 用户登录逻辑
核心逻辑: 登录成功后存储Token、 获取用户信息、 有用户信息 ? 跳转首页 : 跳转上传商家信息页
vue
<script>
export default {
methods: {
// 登录
async login() {
this.loading = true
try {
const { data } = await loginApi(userInfo)
// 保存token
setToken(data)
// 获取用户信息
const { data: info } = await getShopInfoApi()
this.$message.success('登录成功')
this.loading = false
// 判断是否有用户信息
if (!info) {
next('/modify-info')
} else {
next('/dashboard')
}
} catch (error) {
this.loading = false
}
}
}
}
</script>
6.2 上传商家信息页
src/views/settings/modify-info.vue
核心逻辑: 收集商家信息
, 图片上传
, 提交商家信息
- 收集商家信息
vue
<template>
<!-- 店铺名称 -->
<div class="image-view-title">
<div class="image-list">店铺名称</div>
<el-input v-model="formInput.name" placeholder="请输入店铺名称"></el-input>
</div>
<!-- 店铺地址 -->
<div class="image-view-title">
<div class="image-list">店铺地址</div>
<el-input v-model="formInput.address" type="text" placeholder="请输入店铺地址"></el-input>
</div>
<!-- 店铺logo -->
<div class="image-view-title">
<div class="image-list">店铺logo</div>
<el-input v-model="formInput.logo" placeholder="请输入Logo"></el-input>
</div>
<!-- 提交 -->
<div class="image-button">
<el-button type="success" size="medium" @click="submitForm" :loading="loading">提交</el-button>
</div>
</template>
<script>
export default {
data() {
return {
formInput: {
name: '',
address: '',
logo: ''
},
loading: false
}
},
}
</script>
- 上传图片
vue
<template>
<el-upload
class="avatar-uploader"
:action="actions"
:headers="{ authorization: 'Bearer ' + token }"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="formInput.logo" :src="formInput.logo" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</template>
<script>
export default {
methods: {
handleAvatarSuccess(res, file) {
this.formInput.logo = res.data
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG、PNG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
}
}
}
</script>
- 提交商家信息
js
async submitForm() {
this.loading = true
const requestApi = addShopInfoApi
try {
await requestApi(this.formInput)
this.$message.success('操作成功')
this.loading = false
// 新增则跳转首页 修改则返回信息页
this.$router.push(this.shopInfo ? '/settings' : '/')
} catch (error) {
this.loading = false
}
}
6.3 路由验证文件
核心逻辑: 未登录用户禁止进入主页, 未设置商家信息禁止进入主页, 进入后拉取商家信息
修改登录逻辑 将登录逻辑改写到vuex中
store/index.js
js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
modules: { user },
getters: {
shopName: state => state.user.shopInfo?.name,
token: state => state.user.token
}
})
store/module/user.js
修改登录逻辑
, 获取商家信息方法
, 用户退出登录方法
js
// 用户模块(商家)
import { loginApi } from "@/api/auth"
import { getShopInfoApi } from "@/api/merchant-info"
import { getToken, removeToken, setToken } from "@/utils/auth"
const defaultState = () => ({
token: getToken(),
shopInfo: null
})
const mutations = {
SET_TOKEN (state, token) {
state.token = token
},
SET_INFO (state, info) {
state.shopInfo = info
}
}
const actions = {
// 登录
async login({ commit, dispatch }, userInfo) {
const { data } = await loginApi(userInfo)
setToken(data)
commit('SET_TOKEN', data)
},
// 获取商家信息
async getShopInfo ({ commit }) {
const { data } = await getShopInfoApi()
commit('SET_INFO', data)
return data
},
// 退出登录
logout({ commit }) {
removeToken()
commit('SET_TOKEN', '')
commit('SET_INFO', '')
}
}
const getters = {}
export default {
namespaced: true,
state: defaultState(),
mutations,
actions,
getters
}
views/login.vue
js
// 登录
async login() {
this.loading = true
try {
await this.$store.dispatch('user/login', this.formInput)
this.$message.success('登录成功')
this.loading = false
this.$router.push('/dashboard')
} catch (error) {
this.loading = false
}
}
permission.js 核心代码
js
// 路由前置守卫
router.beforeEach(async (to, from, next) => {
console.log('路由进入前')
// 开启加载进度条
NProgress.start()
// 设置页面标题
document.title = getPageTitle(to.meta.title)
// 判断用户是否登录? -> 登录 放行 -> 未登录 跳转登录页面
// 1. 取出token值【登录凭证】
const token = store.getters.token
// 2. 判断是否有token
if (token) {
// 3. 验证是否有商家信息【商家信息页 不需要验证】
if (store.getters.shopName || to.path === '/modify-info') {
// 4. 有商家信息
next()
} else {
try {
// 5. 无商家信息 重新拉取商家信息
const info = await store.dispatch('user/getShopInfo')
// 6. 拉取后还是无商家信息【跳转商家信息页】
if (!info) {
next('/modify-info')
} else {
next()
}
} catch (error) {
// 5. 拉取信息失败
store.dispatch('user/logout')
next('/login')
}
}
} else {
// 3. 无token 判断当前页面是否为登录【直接放行 / 跳转登录】
if (to.path === '/login') {
next()
} else {
next('/login')
}
}
// 关闭加载进度条
NProgress.done()
})
6.4 商家信息页
商家信息页 主要为展示页面 展示商家信息
核心逻辑: 通过vuex拉取信息
跳转修改商家信息页
6.5 修改商家信息页
需要的逻辑: 返回上一页
渲染商家信息
提交商家信息修改
- 返回上一页: 判断是否有商家信息 有则显示返回上一页
vue
<p @click="$router.push('/settings')" v-if="shopInfo">返回上一页</p>
- 渲染商家信息: 从vuex拉取商家信息 有则渲染到
formInput
中
js
computed: {
...mapState('user', ['shopInfo', 'token']),
title() {
return this.shopInfo ? '修改店铺信息' : '设置店铺信息'
}
},
mounted() {
// 判断是否为信息
if (this.shopInfo.name) {
this.formInput = { ...this.shopInfo }
}
}
- 提交商家信息修改: 判断
shopInfo
是否有值 ? 修改 : 设置