目录
1、添加路由
2、api/admin.js API
增、删、改、查、分页、图片上传
//定义管理员API
import { $get, $post, $setToken } from "../utils/request.js"
import md5 from 'js-md5'
import { $msg_s, $msg_e, $confirm } from '../utils/msg.js'
export let login = async (params) => {
//解构出ckMe
let { ckMe } = params
params.loginPwd = md5(md5(params.loginPwd).split('').reverse().join(''))
let { success, message, token } = await $get('Admin/Login', params)
if (success) {
//sessionStorage缓存数据,浏览器关闭清空
//localStorage缓存数据,手动清除,否则一直存在浏览器中
sessionStorage.setItem('token', token)
$setToken()
$msg_s(message)
//登录成功缓存账号
localStorage.setItem('loginId', params.loginId)
//判断是否需要记住我
if (ckMe) {
//缓存密码
localStorage.setItem('loginPwd', params.loginPwd)
}
} else {
$msg_e(message)
}
return success
}
//自动登录
export let loginAuto = async () => {
let loginId = localStorage.getItem('loginId')
let loginPwd = localStorage.getItem('loginPwd')
if (loginId & loginPwd) {
let params = {
loginId,
loginPwd
}
let { success, token } = await $get('Admin/Login', params)
if (success) {
sessionStorage.setItem('token', token)
$setToken()
return true
} else {
return false
}
} else {
return false
}
}
//查询账户信息
export let list = async (params) => {
let ret = await $get('Admin/List', params)
return ret
}
export let add = async (params) => {
//验证账户信息
if (!params.loginId) {
$msg_e("请输入账号")
return false
} else if (!params.loginPwd) {
$msg_e("请输入密码")
return false
} else if (params.loginPwd.length < 6) {
$msg_e("密码长度不得小于6")
return false
} else if (params.loginPwd != params.loginPwd2) {
$msg_e("两次密码不一致")
return false
} else if (!params.name) {
$msg_e("请输入姓名")
return false
} else if (!params.phone) {
$msg_e("请输入电话")
return false
} else if (!(/^1\d{10}$/.test(params.phone))) {
$msg_e("电话格式错误")
return false
} else if (params.roleId == 0) {
$msg_e("请选个角色")
return false
}
// 密码加密
params.loginPwd = md5(md5(params.loginPwd).split('').reverse().join(''))
let { success, message } = await $post('Admin/Add', params)
if (success) {
$msg_s(message)
} else {
$msg_e(message)
}
return success
}
//更新
export let update = async (params) => {
//验证账户信息
if (!params.name) {
$msg_e("请输入姓名")
return false
} else if (!params.phone) {
$msg_e("请输入电话")
return false
} else if (!(/^1\d{10}$/.test(params.phone))) {
$msg_e("电话格式错误")
return false
} else if (params.roleId == 0) {
$msg_e("请选个角色")
return false
}
let { success, message } = await $post('Admin/Update', params)
if (success) {
$msg_s(message)
} else {
$msg_e(message)
}
return success
}
//删除
export let del = async (params) => {
//提示是否确认删除
await $confirm('确定是否删除')
let { success, message } = await $post('Admin/Delete', params)
if (success) {
$msg_s(message)
} else {
$msg_e(message)
}
return success
}
//根据账号返回一个账户对象
export let getOne = async (params) => {
let r = await $get('Admin/GetOne', params)
return r
}
//重置密码
export let resetPwd = async (params) => {
if (!params.oldLoginPwd) {
$msg_e("请输入原始密码")
return false
} else if (!params.newLoginPwd) {
$msg_e("请输入最新密码")
return false
} else if (!params.newLoginPwd2) {
$msg_e("请输入确认密码")
return false
} else if (params.newLoginPwd != params.newLoginPwd2) {
$msg_e("两次密码不一致")
return false
}
params.oldLoginPwd = md5(md5(params.oldLoginPwd).split('').reverse().join(''))
params.newLoginPwd = md5(md5(params.newLoginPwd).split('').reverse().join(''))
let { success, message } = await $post('Admin/ResetPwd', params)
if (success) {
$msg_s(message)
} else {
$msg_e(message)
}
return success
}
3、账户Admin.vue
<template>
<div class="search">
<span>账号:</span>
<el-select v-model="roleId" size="small">
<el-option v-for="item in roleList" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
</el-select>
<el-button size="small" type="success" @click="loadTable">查询</el-button>
<el-button size="small" type="primary" @click="openDrawer = true">添加</el-button>
</div>
<el-table size="" :data="tableData" style="width: 100%">
<el-table-column prop="id" label="编号" width="100" />
<el-table-column prop="loginId" label="账号" width="100" />
<el-table-column prop="name" label="姓名" width="100" />
<el-table-column prop="phone" label="电话" width="120" />
<!-- <el-table-column prop="photo" label="头像" width="100" /> -->
<el-table-column label="头像" width="100">
<template #default="scope">
<el-image style="width: 60px; height: 60px" :src="admin_photo_base_url + (scope.row.photo || 'default.jpg')"
fit="cover" />
</template>
</el-table-column>
<el-table-column prop="role.roleName" label="角色" width="100" />
<el-table-column fixed="right" label="操作" width="180">
<template #default="scope">
<el-button size="small" type="warning" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="prev, pager, next" :page-size="pageSize" :total="total"
v-model:current-page="pageIndex" />
</div>
<el-drawer v-model="openDrawer" :title="isAdd ? '添加账户' : '修改账户'" size="30%" direction="rtl" :before-close="drawerClose">
<div class="edititem">
<span>头像:</span>
<div>
<el-upload class="avatar-uploader" :action="admin_upload_url" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="formData.photo" :src="admin_photo_base_url + formData.photo" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</div>
</div>
<div class="edititem" v-if="isAdd">
<span>账号:</span>
<div><el-input v-model="formData.loginId" placeholder="请输入账号" /></div>
</div>
<div class="edititem">
<span>姓名:</span>
<div><el-input v-model="formData.name" placeholder="请输入姓名" /></div>
</div>
<div class="edititem" v-if="isAdd">
<span>密码:</span>
<div><el-input type="password" v-model="formData.loginPwd" placeholder="请输入密码" /></div>
</div>
<div class="edititem" v-if="isAdd">
<span>确认密码:</span>
<div><el-input type="password" v-model="formData.loginPwd2" placeholder="请输入确认密码" /></div>
</div>
<div class="edititem">
<span>电话:</span>
<div><el-input v-model="formData.phone" placeholder="请输入电话" /></div>
</div>
<div class="edititem">
<span>角色:</span>
<el-select v-model="formData.roleId" size="small">
<el-option v-for="item in roleList" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
</el-select>
</div>
<div class="item">
<span></span>
<div>
<el-button size="small" type="primary" @click="editForm">{{ isAdd ? '添加' : '修改' }}</el-button>
<el-button size="small" type="default" @click="clearFormData">取消</el-button>
</div>
</div>
</el-drawer>
</template>
<script>
import { list, add, update, del } from '../../api/admin'
import { list as roleList } from '../../api/role'
import { reactive, toRefs, watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
//上传头像地址和查看头像地址
import { admin_upload_url, admin_photo_base_url } from '../../config/conster'
import { $msg_e } from '../../utils/msg'
export default {
name: 'Admin',
setup() {
let data = reactive({
//表格数据
tableData: [],
roleList: [],
roleId: 0,
//当前页
pageIndex: 1,
//每页条数
pageSize: 10,
//总数量
total: 0,
//是否打开抽屉
openDrawer: false,
//表单数据
formData: {
loginId: '',
loginPwd: '',
loginPwd2: '',
name: '',
phone: '',
roleId: '0',
photo: ''
},
//上传账户的地址
admin_upload_url,
//查看账户头像根地址
admin_photo_base_url,
})
//加载角色组信息
let loadRoleList = async () => {
let ret = await roleList()
ret.unshift({ roleId: 0, roleName: '请选择角色' })
data.roleList = ret
}
//调用加载角色数组
loadRoleList()
data.tableData = [{ id: 1, loginId: 'admin', loginPwd: '', name: '李四', phone: '10086', photo: '', role: { roleId: 2, roleName: '普通管理员' } }, { id: 2, loginId: 'admin2', loginPwd: '', name: '张三', phone: '10087', photo: '', role: { roleId: 1, roleName: '管理员' } }]
let loadTable = async () => {
//查询条件
let params = {
roleId: data.roleId,
pageIndex: data.pageIndex,
pageSize: data.pageSize
}
//获取查询结果
let { count, data: adminData, } = await list(params)
data.tableData = adminData
data.total = count
// data.formData = [{'roleId':'1','roleName':'系统管理员'},{'roleId':'2','roleName':'普通管理员'}]
console.log(data.formData)
}
//执行加载表格数据的方法
loadTable()
//监听当前页码是否发生变化
watch(() => data.pageIndex, () => {
//执行加载表格数据的方法
loadTable()
})
//头像上传成功指定函数
let handleAvatarSuccess = (res) => {
let { filename, success } = res
if (success) {
data.formData.phone = filename
}
this.imageUrl = URL.createObjectURL(file.raw)
}
//头像上传之前调用函数
let beforeAvatarUpload = (file) => {
let imgType = ['image/jpeg', 'image/png', 'image/gif']
const isJPG = imgType.includes(file.type)
const islt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
$msg_e('请选择正确的图片格式')
return false
} else if (!islt2M) {
$msg_e('图片大小不能超过2M')
return false
}
return true
}
let editForm = async () => {
let r = false
//判断是执行添加还是修改
if (data.isAdd) {
r = await add(data.formData)
//添加成功清空表单
if (r) {
clearFormData()
}
} else {
r = await update(data.formData)
}
if (r) {
loadTable();
}
}
//清空表单
let clearFormData = () => {
data.formData = {
loginId: '',
loginPwd: '',
loginPwd2: '',
name: '',
phone: '',
roleId: '0',
photo: ''
}
}
//关闭抽屉
let drawerClose = () => {
data.openDrawer = false
add.isAdd = true
clearFormData()
}
//执行修改
let handleEdit = (row) => {
data.formData = { ...row }
data.isAdd = false
data.openDrawer = true
}
//执行删除
let handleDelete = async (row) => {
let { id } = row
let r = await del({ id })
//删除成功,刷新页面
if (r) {
loadTable
}
}
return {
...toRefs(data),
loadTable,
handleAvatarSuccess,
beforeAvatarUpload,
drawerClose,
editForm,
clearFormData,
handleEdit,
handleDelete
}
}
}
</script>
<style lang="scss" scoped>
.avatar-uploader {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 178px;
height: 178px;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader :hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>
4、个人中心 view/Mine.vue
<template>
<div class="box">
<el-image style="width: 100px; height: 100px"
:src="admin_photo_base_url+$store.state.admin.photo||'logo.png'"
:fit="fill" />
</div>
<div class="content">
<p>账号:admin</p>
<p>姓名:admin</p>
<p>电话:18705161482</p>
<p>角色:管理员</p>
<!-- <p>账号:{{$store.state.admin.loginId}}</p>
<p>姓名:{{$store.state.admin.name}}</p>
<p>电话:{{$store.state.admin.phone}}</p>
<p>角色:{{$store.state.admin.roleName}}</p> -->
</div>
</template>
<script>
//导入头像地址
import {admin_photo_base_url} from "../../config/conster"
export default {
name: 'Mine',
setup(){
return {
admin_photo_base_url
}
}
}
</script>
<style lang="scss" scoped>
.box {
display: flex;
.content{
margin-left: 10px;
p{
height: 40px;
}
}
}
</style>
5、重置密码ResetPwd.vue
<template>
<div class="box">
<div class="edititem" >
<span>原始密码:</span>
<div><el-input type="password" v-model="oldLoginPwd" placeholder="请输入原始密码"/></div>
</div>
<div class="edititem" >
<span>最新密码:</span>
<div><el-input type="password" v-model="newLoginPwd" placeholder="请输入最新密码"/></div>
</div>
<div class="edititem">
<span>确认密码:</span>
<div><el-input type="password" v-model="newLoginPwd2" placeholder="请输入确认密码"/></div>
</div>
<div class="edititem">
<span>确认密码:</span>
<div><el-button type="primary" @click="editForm">修改</el-button></div>
<div><el-button type="default" @click="clearFormData">取消</el-button></div>
</div>
</div>
</template>
<script>
import {resetPwd} from '../../api/admin'
import {reactive,toRefs} from 'vue'
import { useStore } from 'vuex'
export default {
name: 'ResetPwd',
setup(){
//获取全局状态管理
let $store = useStore()
let data = reactive({
oldLoginPwd:'',
newLoginPwd:'',
newLoginPwd2:'',
})
let clearFormData=()=>{
data.oldLoginPwd=''
data.newLoginPwd=''
data.newLoginPwd2=''
}
let editForm = async()=>{
data.id = $store.state.admin.admin.id
await resetPwd(data)
}
return {
...toRefs(data),
clearFormData,
editForm
}
}
}
</script>
<style lang="scss" scoped>
.box{
width: 400px;
font-size:16px
}
</style>
6、上传组件和上传方法
//头像上传成功指定函数
let handleAvatarSuccess = (res) => {
let { filename, success } = res
if (success) {
data.formData.phone = filename
}
this.imageUrl = URL.createObjectURL(file.raw)
}
//头像上传之前调用函数
let beforeAvatarUpload = (file) => {
let imgType = ['image/jpeg', 'image/png', 'image/gif']
const isJPG = imgType.includes(file.type)
const islt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
$msg_e('请选择正确的图片格式')
return false
} else if (!islt2M) {
$msg_e('图片大小不能超过2M')
return false
}
return true
}
7、Error404.vue
<template>
<div class="box">
<img src="../assets/404.jpg" @click="$router.push('/')"/>
</div>
</template>
<script>
export default{
name: 'Error404'
}
</script>
<style scoped lang="scss">
.box{
width: 100vw;
height: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
</style>
路由配置
//404
{
path: '/:pathMatch(.*)*',
name: 'Error404',
component: () => import('../views/Error404.vue')
}