前言:当我们要搭建一个后台管理系统时,选择一个简洁易用的模板是至关重要的。在本文中,我们将介绍如何使用 Vite、Vue 3 和 Ant Design Vue 来搭建一个简洁、通用且易扩展的后台管理系统模板。小编之前其实写过一个后台管理系统的相关文章,感兴趣的掘友们可以先去简单看一下,链接就放在下面了,至于为什么又要写一个新的同质的后台管理系统,emmmmm....,其实是上一篇我不满意,之前第三方库选用的是element,编码体验差强人意,这次就选了antd,而且也没配置eslint和prettier,后期的代码看起来乱成一锅粥了都,正好最近有项目要用,我就干脆重写一个了,废话不多说,我们直接步入正题吧。
一. 项目搭建:
1.1 创建项目
npm create vite@latest 项目名称
1.2 安装初始配置和运行项目:
1.3 打开后如果效果如下,说明项目创建好了:
1.4 接下来通过VS Code对项目基本配置进行修改,如下图所示:
1.4.1:按需修改eslint代码检查规则:
1.4.2:安装必要插件:
1.4.3: ESLint 和 Prettier 配合使用:prettier官方提供了一款工具 eslint-config-prettier ,这个工具其实禁用掉了一些不必要的以及和Prettier相冲突的ESLint规则。此外,我们还需要安装如下依赖:
npm install --save-dev eslint-config-prettier
npm install --save-dev eslint-plugin-prettier
npm install --save-dev prettier
1.5:安装axios 和 antd
npm install axios
npm install ant-design-vue@next --save
antd推荐配置:
创建axios实例并进行相关配置(axios二次封装),比如开发环境跨域配置或者请求、响应拦截器等等
二. 项目基本结构搭建:
2.1: 创建必要文件夹并配置路由
2.2: layout容器的具体实现:
2.3: Home主页面的具体实现:
2.4: 登录页实现:
2.4: 角色管理页实现:这里小编就简单介绍一下吧,这个页面的代码也贴在下面了
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 搜索表单 -->
<!-- <usersearch /> -->
<a-form
:label-col="{ xl: 7, lg: 5, md: 7, sm: 4 }"
:wrapper-col="{ xl: 17, lg: 19, md: 17, sm: 20 }"
>
<a-row :gutter="8">
<a-col :xl="6" :lg="12" :md="12" :sm="24" :xs="24">
<a-form-item label="用户账号">
<a-input v-model:value.trim="form.roleName" placeholder="请输入用户账号" allow-clear
><template #suffix> <UserOutlined style="color: #ccc" /> </template
></a-input>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="12" :md="12" :sm="24" :xs="24">
<a-form-item class="ele-text-right" :wrapper-col="{ span: 24 }">
<a-space>
<a-button style="background-color: #5cc750" type="primary" @click="searchUsers"
>查询</a-button
>
<!-- <a-button>重置</a-button> -->
</a-space>
</a-form-item>
</a-col>
</a-row>
</a-form>
<!-- 数据操作 -->
<!-- <a-space style="margin-bottom: 10px">
<a-button style="background-color: #5cc750" type="primary" class="ele-btn-icon">
<template #icon>
<plus-outlined />
</template>
<span>新建</span>
</a-button>
<a-button danger type="primary" class="ele-btn-icon">
<template #icon>
<delete-outlined />
</template>
<span>删除</span>
</a-button>
</a-space> -->
<!-- 表格 -->
<a-table
:pagination="pagination"
@change="handleTableChange"
bordered
row-key="userId"
:dataSource="dataSource"
:columns="columns"
:scroll="{ x: 1000 }"
>
<template #headerCell="{ column }">
<template v-if="column.key === 'checkbox'">
<a-checkbox />
</template>
<template v-if="column.key === 'username'">
<UserOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'phone'">
<WhatsAppOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'sexName'">
<ManOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'roles'">
<UserSwitchOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'createTime'">
<HistoryOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'status'">
<PieChartOutlined style="margin-right: 5px" />{{ column.title }}
</template>
<template v-if="column.key === 'action'">
<SettingOutlined style="margin-right: 5px" />{{ column.title }}
</template>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'checkbox'">
<a-checkbox />
</template>
<template v-if="column.key === 'nickname'">
<!-- <router-link :to="'/system/user/details?id=' + record.userId">
</router-link> -->
<div style="color: #1677ff">{{ record.nickname }}</div>
</template>
<template v-else-if="column.key === 'roles'">
<a-tag v-for="item in record.roles" :key="item.roleId" color="blue">
{{ item.roleName }}
</a-tag>
</template>
<template v-else-if="column.key === 'status'">
<a-switch
:checked="record.status === 0"
@change="(checked) => editStatus(checked, record)"
/>
</template>
<template v-else-if="column.key === 'action'">
<a-space>
<!-- <a>修改</a>
<a-divider type="vertical" />
<a>重置密码</a> -->
<!-- <a-divider type="vertical" /> -->
<a-popconfirm
placement="topRight"
@confirm="handleDelUser(record)"
title="确定要删除此用户吗?"
ok-text="是"
cancel-text="否"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</a-table>
</a-card>
</div>
</template>
<script setup>
import { ref, onMounted, reactive } from 'vue'
import { getUserAPI, delUserAPI, queryUserAPI } from '@/apis/user.js'
import {
UserOutlined,
WhatsAppOutlined,
ManOutlined,
UserSwitchOutlined,
HistoryOutlined,
SettingOutlined,
PieChartOutlined
} from '@ant-design/icons-vue'
// import usersearch from './components/usersearch.vue'
import { message } from 'ant-design-vue'
// 查询用户相关
const form = ref({
roleName: '',
comments: ''
})
const queryData = ref({
username: '',
role: null
})
const searchUsers = async () => {
console.log('form: ', form.value)
queryData.value.username = form.value.roleName
console.log('queryParams', queryData.value)
const { username } = queryData.value
console.log('username', username)
const res = await queryUserAPI(queryData.value)
console.log('query', res)
dataSource.value = res?.data || []
if (!dataSource.value.length) {
console.log('无符合条件的数据')
dataSource.value = data.value
message.error('抱歉!没有符合条件的数据')
} else {
message.success('查询成功!')
dataSource.value = res.data
}
}
// 表格数据
const dataSource = ref([])
//获取用户列表数据并格式化字段
const data = ref([])
onMounted(async () => {
const res = await getUserAPI()
console.log('userList: ', res)
data.value = res.data
data.value = data.value.map((item, index) => {
index++
return { ...item, index }
})
dataSource.value = data.value
})
// 表格列配置
const columns = ref([
// {
// key: 'checkbox',
// width: 48,
// align: 'center'
// },
{
key: 'index',
width: 70,
align: 'center',
dataIndex: 'index',
title: '编号'
},
{
title: '用户账号',
dataIndex: 'username',
sorter: true,
showSorterTooltip: false,
align: 'center',
key: 'username'
},
// {
// title: '手机号',
// dataIndex: 'phone',
// sorter: true,
// showSorterTooltip: false,
// align: 'center',
// key: 'phone'
// },
// {
// title: '性别',
// dataIndex: 'sexName',
// width: 100,
// align: 'center',
// key: 'sexName'
// },
// {
// title: '角色',
// key: 'roles',
// align: 'center'
// },
// {
// title: '创建时间',
// dataIndex: 'createTime',
// sorter: true,
// showSorterTooltip: false,
// ellipsis: true,
// align: 'center',
// key: 'createTime'
// },
// {
// title: '状态',
// key: 'status',
// dataIndex: 'status',
// width: 100,
// align: 'center'
// },
{
title: '操作',
key: 'action',
width: 220,
align: 'center'
}
])
//删除指定用户
const handleDelUser = async (record) => {
console.log('del', record.username)
const res = await delUserAPI(record.username)
//删除失败测试
// const res = await delUserAPI('zs')
console.log('delUser: ', res)
if (res.response?.status && res.response.status != 200) {
message.error(res.response.data.data)
return
} else {
message.success(res.data)
//更新数据
const res1 = await getUserAPI()
console.log('userList: ', res1)
dataSource.value = res1.data
dataSource.value = dataSource.value.map((item, index) => {
index++
return { ...item, index }
})
return
}
}
//修改用户状态
//对于每页数据的管理
let pagination = reactive({
total: dataSource.value.length,
current: 1,
pageSize: 5,
showSizeChanger: true,
pageSizeOptions: ['5', '4', '3'],
showQuickJumper: true
})
// 对每页数据显示的交互
let handleTableChange = (pagina) => {
console.log('pagination.current 第几页', pagina.current) //第几页
console.log('pagina.pageSize 一页多少 ', pagina.pageSize) //一页多少
pagination.current = pagina.current
pagination.pageSize = pagina.pageSize
}
</script>