快速搭建SpringBoot3+Vue3管理系统
- 前端项目搭建(默认开发环境:node20,Jdk17)
- 创建项目并下载依赖--执行以下命令
前端项目搭建(默认开发环境:node20,Jdk17)
创建项目并下载依赖–执行以下命令
- 创建项目
yarn create vite admin-vue --template
2.下载依赖(也可按需下载)
yarn add echarts --save
yarn add vue-router --save
yarn add element-plus --save
yarn add axios --save
yarn add sass--save
3.导入IDEA
4.配置快速启动
也可以在终端中使用命令启动,如下:
5.配置Axios
在src目录下新建axios目录,并创建request.js文件
import axios from 'axios'
const request = axios.create({timeout: 20000,baseURL: 'http://127.0.0.1:8080',
})
export default request
6.配置路由
在src目录下新建axios目录,并创建router.js文件
import {createRouter,createWebHashHistory} from "vue-router";
// 在router.js文件中创建路由实例对象
const router=createRouter({history:createWebHashHistory(),routes:[//路由规则]
})
// 输出实例对象
export default router;
7.挂载ElementPlus和路由
在main.js中挂载
import { createApp } from 'vue'
import './style.css'
// 导入element-plu
import ElementPlus from 'element-plus'
// 导入路由
import router from './router/router.js'
// 导入css样式
import 'element-plus/dist/index.css'
import App from './App.vue'
// 挂载element-plu和router
createApp(App).use(ElementPlus).use(router).mount('#app')
8.绝对路径配置
在vite.config.js中配置绝对路径别名–@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
// https://vite.dev/config/
export default defineConfig({plugins: [vue()],// 绝对路径别名resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})
8.创建布局组件
8.1 顶部水平导航
<script setup>
import {onMounted, ref} from "vue";
import router from "@/router/router.js";
// 图片地址
const url=ref("/element-plus-logo.svg")
// 将用户信息从浏览器缓存中取出
const user=ref(JSON.parse(localStorage.getItem('xm-user') || '{}'))
// 退出登录
const logout=()=>{localStorage.removeItem('xm-user');router.push("/login");
}
</script><template><!-- 顶部导航栏--><el-menurouterclass="el-menu-demo"mode="horizontal"text-color="grey"background-color="white":ellipsis="false"><el-menu-item index="1"><el-image style="width: 100px; height: 100px" :src="url" />|商品信息管理系统</el-menu-item><el-menu-item index="/">首页</el-menu-item><el-menu-item index="/TeachingCenter"><span>教学中心</span></el-menu-item><el-menu-item index="/TeachingCenter"><span>教学资源</span></el-menu-item><el-menu-item index="/Goods"><span>商品信息管理</span></el-menu-item><el-menu-item index="/TeachingCenter"><span>教学实践</span></el-menu-item><el-menu-item index="/TeachingCenter"><span>问答社区</span></el-menu-item><el-sub-menu index="10" v-if="user.id"><template #title><img :src="user.avatar" width="40px" height="40px" style="border-radius: 50%;margin-right: 5px" />{{ user.name }}</template><el-menu-item index="/manage/personal">个人中心</el-menu-item><el-menu-item index="10-2">修改密码</el-menu-item><el-menu-item index="10-3" @click="logout">退出登录</el-menu-item></el-sub-menu><el-menu-item index="/login" v-else><el-button type="primary" round>登录</el-button></el-menu-item></el-menu>
</template><style scoped>
.el-menu--horizontal > .el-menu-item:nth-child(1) {margin-right: auto;
}
</style>
8.2 侧边导航栏
<script setup>import {Goods, House, Promotion, User,Avatar} from "@element-plus/icons-vue";
</script><template><!-- 侧边导航栏--><el-aside width="200px" ><el-menu default-active="1" style="min-height: 100%;overflow-x: hidden;"class="el-menu"background-color="white"text-color="grey"router><!-- <div style="height: 60px; line-height: 60px; text-align: center;"><img src="../assets/logo.png" alt="" style="width: 20px;position: relative; top: 5px;margin-right: 5px;"><b style="color: white;">后台管理系统</b></div>--><el-menu-item index="/manage/index" ><el-icon><House /></el-icon>主页</el-menu-item><el-menu-item index="/manage/goods"><el-icon><Goods /></el-icon><span>商品信息管理</span></el-menu-item><el-sub-menu index="2"><template #title><el-icon><User /></el-icon>用户管理</template><el-menu-item ><el-icon><User /></el-icon>用户信息</el-menu-item><el-menu-item index="/manage/admin"><el-icon><Avatar /></el-icon><span>管理员信息</span></el-menu-item></el-sub-menu><el-menu-item ><el-icon><Promotion /></el-icon>订单管理</el-menu-item></el-menu></el-aside>
</template><style scoped>
.el-menu{height: 100vh;
}
</style>
8.3 底部导航栏
<script setup></script><template><p alog-group="copy">©2024 商品信息管理系统<a rel="noopener" href="//www.baidu.com/duty/">使用必读</a><a rel="noopener" href="https://tieba.baidu.com/tb/eula.html">协议</a><a href="https://tieba.baidu.com/tb/cms/tieba-fe/tieba_promise.html">隐私政策</a><a rel="noopener" href="//tieba.baidu.com/hermes/feedback">投诉反馈</a>信息网络传播视听节目许可证 0110516 违法和不良信息举报电话:400-921-5119<a rel="noopener" href="http://net.china.cn/chinese/index.htm" target="_blank"><img src="//tb2.bdstatic.com/tb/static-common/img/net_7a8d27a.png" width="20"></a><a rel="noopener" href="http://www.bj.cyberpolice.cn/index.htm" target="_blank"><img title="首都网络110报警服务" src="//tb2.bdstatic.com/tb/static-common/img/110_97c9232.png" width="20"></a></p>
</template><style scoped></style>
9.创建整体布局,引用子组件
<script setup>
// 注册子组件
import Header from "@/components/Header.vue";
import Footer from "@/components/Footer.vue";
import Aside from "@/components/Aside.vue";
import {ref} from "vue";
import {useRouter} from "vue-router";
// 获取全局路由
const router=useRouter();
// 判断是否登录
// 将用户信息从浏览器缓存中取出
const user=ref(JSON.parse(localStorage.getItem('xm-user') || '{}'))
if (user.value.name==null){//如果没有数据router.push("/login");
}
</script><template><!-- container布局 --><div class="common-layout"><el-container><!-- 顶部导航栏--><el-header><Header></Header></el-header><el-container><!-- 侧边导航栏--><el-aside width="200px"><Aside></Aside></el-aside><el-container><!-- 内容显示区域--><el-main><!-- 路由视图--><router-view></router-view></el-main><!-- 底部导航栏--><el-footer><Footer></Footer></el-footer></el-container></el-container></el-container></div>
</template><style scoped></style>
10.创建商品信息组件:Goods.vue
<script setup>
import {onMounted, ref} from "vue";
import request from "../../axios/request.js";
import {ElMessage, ElMessageBox} from "element-plus";
import {Delete,Edit,Message,Search,Plus,House,User,Promotion,Goods,Download,UploadFilled
} from "@element-plus/icons-vue";const list = ref([])
// 查询条件
const name = ref("")
// 模态框是否显示
const dialogVisible = ref(false);
// 商品的信息
const goods = ref({id: "",name: "",price: "",intro: "",amount: "",goodsType: "",imgurl: "",remark: "未上架"
})// 表单校验规则
const rules = {name: [{required: true, message: "请输入名称", trigger: "blur"}],price: [{required: true, message: "请输入价格", trigger: "blur"}],intro: [{required: true, message: "请输入简介", trigger: "blur"}],amount: [{required: true, message: "请输入库存", trigger: "blur"}],goodsType: [{required: true, message: "请选择类别", trigger: "blur"}],remark: [{required: true, message: "请选择状态", trigger: "blur"}]
}// 表单引用
const goodsForm = ref();
// 分页参数
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)// 保存选中的数据
const multipleSelection = ref([])// 查询商品信息
const getList = () => {request({url: '/goods/page',method: 'get',params: {page: pageNum.value,limit: pageSize.value,goodsName: name.value,}}).then((res) => {// console.log(res)list.value = res.data.data;total.value = res.data.count;// name.value=""})
}// 改变每页数据量
const handleSizeChange = (pSize) => {// console.log(pSize+`items per page`)pageSize.value = pSize;getList()
}
// 改变当前页
const handleCurrentChange = (pNum) => {// console.log(`current page: `+pNum)pageNum.value = pNum;getList()
}
// 根据id删除
const del = (id) => {// console.log(id)ElMessageBox.confirm('是否确认删除?','Warning',{confirmButtonText: 'OK',cancelButtonText: 'Cancel',type: 'warning',}).then(() => {request({url: '/goods/del',method: 'get',params: {id: id}}).then(res => {if (res.data.code == 200) {ElMessage({type: 'success',message: '删除成功!',})} else {ElMessage({type: 'error',message: '删除失败!',})}getList()})}).catch(() => {ElMessage({type: 'warning',message: '取消删除!',})})
}// 搜索
const search = () => {getList()
}// 新增
const add = () => {dialogVisible.value = true
}
// 数据提交
const save = () => {
// 校验表单是否合法goodsForm.value.validate((flag, err) => {if (flag) {//验证通过request({url: '/goods/save',method: 'post',data: goods.value}).then(res => {getList()goods.value = ""dialogVisible.value = falseElMessage({type: 'success',message: '保存成功',})})} else {ElMessage({type: 'error',message: '验证没通过!',})}})
}
// 修改
const edit = (item) => {// 深拷贝const newObj = Object.assign({}, item)dialogVisible.value = truegoods.value = newObj
}
// 获取已选择的数据
const handleSelectionChange = (val) => {// console.log(val)multipleSelection.value = val;
}
// 批量删除
const delBatch = () => {
// 获取需要删除的数据的id--数组let ids = multipleSelection.value.map(item => item.id);// console.log("ids",ids)if (ids.length != 0) {ElMessageBox.confirm('是否确认删除?','Warning',{confirmButtonText: 'OK',cancelButtonText: 'Cancel',type: 'warning',}).then(() => {request({url: '/goods/delBatch',method: 'post',data: ids}).then(res => {ElMessage({type: 'success',message: '删除成功!',})getList()// console.log(res)})}).catch(() => {ElMessage({type: 'warning',message: '取消删除!',})})} else {ElMessage({type: 'error',message: '请先选择数据!'})}
}
// 导入成功后重新加载数据
const handleExcelImportSuccess = () => {getList();ElMessage({type: 'success',message: '上传成功!',})
}// 导出数据
const exp = () => {window.open(`http://192.168.31.242:8080/goods/export`)
}// excle导入前验证-->文件类别、文件大小
const cheackExcle = (rawFile) => {// console.log(rawFile.size)// 获取文件后缀let testmsg = rawFile.name.substring(rawFile.name.lastIndexOf('.') + 1)if (testmsg !== 'xlsx') {ElMessage.error('只能上传后缀为.xlsx的excle文件')return false} else if (rawFile.size / 1024 / 1024 > 2) {ElMessage.error('文件大小不能超过2M')return false}return true
}// 图片上传之前的钩子--》判断文件是否是图片、图片大小是否符合要求
const beforeAvatarUpload = (rawFile) => {console.log("类型:", rawFile.type)console.log(rawFile.type !== 'image/png');// 获取文件后缀let testmsg = rawFile.name.substring(rawFile.name.lastIndexOf('.') + 1)console.log("后缀:", testmsg)// 判断文件类型const extension = testmsg === 'jpg' || testmsg === 'png' || testmsg === 'jpeg' || testmsg === 'gif'if (!extension) {//不符合要求ElMessage.error('图片必须是jpg/jpeg/png格式!')return false}// 校验文件大小if (rawFile.size / 1024 / 1024 > 2) {ElMessage.error('图片大小不能超过2MB!')return false}return true
}
// 图片上传后的钩子函数-->回写图片地址
const handleAvatarSuccess = (res) => {console.log(res)goods.value.imgurl = res.msg
}//生命周期函数
onMounted(() => {getList();
})
</script><template><!-- 数据表格--><el-form-item label="名称" style="margin-top: 20px"><el-input v-model="name" style="width: 200px" placeholder="请输入商品名称"></el-input><el-button type="primary" :icon="Search" style="margin-left: 10px" @click="search">搜索</el-button><el-button type="primary" :icon="Plus" style="margin-left: 10px" @click="add">新增</el-button><el-button type="danger" :icon="Delete" style="margin-left: 10px" @click="delBatch">批量删除</el-button><el-upload :action="'http://' + '192.168.31.242:8080/goods/import'":show-file-list="false"accept="xlsx":before-upload="cheackExcle":on-success="handleExcelImportSuccess"style="display: inline-block"><el-button type="primary" style="margin-left: 10px" :icon="UploadFilled">导入</el-button></el-upload><el-button type="warning" style="margin-left: 10px" :icon="Download" @click="exp">导出</el-button></el-form-item><el-table :data="list" width="100%" stripe @selection-change="handleSelectionChange"><el-table-column type="selection" width="55"/><el-table-column type="index" label="序号" width="80" :index="1"></el-table-column><!-- <el-table-column prop="id" label="ID"></el-table-column>--><el-table-column prop="name" label="商品名称"></el-table-column><el-table-column prop="price" label="单价"></el-table-column><el-table-column prop="intro" label="简介" width="100" show-overflow-tooltip></el-table-column><el-table-column prop="amount" label="库存"></el-table-column><el-table-column prop="goodsType" label="类别"></el-table-column><el-table-column prop="remark" label="状态"></el-table-column><el-table-column label="图片" width="120"><template #default="scope"><el-image style="width: 100px; height: 80px; padding: 5px;" :src="scope.row.imgurl" :zoom-rate="1.2":max-scale="7" :min-scale="0.2" :preview-src-list="[scope.row.imgurl]" :preview-teleported="true"/></template></el-table-column><el-table-column label="操作" width="300" fixed="right"><template #default="scope"><el-button type="primary" :icon="Edit" @click="edit(scope.row)">修改</el-button><el-button type="danger" :icon="Delete" @click="del(scope.row.id)">删除</el-button></template></el-table-column></el-table>
<!-- 数据分页--><div style="padding: 10px"><el-paginationv-model:current-page="pageNum"v-model:page-size="pageSize":page-sizes="[10, 20, 30, 40]"size="large"backgroundlayout="total, sizes, prev, pager, next, jumper":total="total"@size-change="handleSizeChange"@current-change="handleCurrentChange"/></div><!--模态框--><el-dialogv-model="dialogVisible":title="goods.id ? '修改商品' : '新增商品'"width="500"ref="goodsForm"><el-form :model="goods" :rules="rules" ref="goodsForm"><el-form-item label="商品名称" prop="name"><el-input v-model="goods.name" autocomplete="off"/></el-form-item><el-form-item label="商品单价" prop="price"><el-input v-model="goods.price" autocomplete="off"/></el-form-item><el-form-item label="商品简介" prop="intro"><el-input v-model="goods.intro" autocomplete="off"/></el-form-item><el-form-item label="商品库存" prop="amount"><el-input v-model="goods.amount" autocomplete="off"/></el-form-item><el-form-item label="商品类别" prop="goodsType"><el-select v-model="goods.goodsType" placeholder="请选择商品类别"><el-option label="手机" value="手机"/><el-option label="电脑" value="电脑"/><el-option label="水果" value="水果"/></el-select></el-form-item><!-- 单选框--><el-form-item label="状态" prop="remark"><el-radio-group v-model="goods.remark"><el-radio value="上架">上架</el-radio><el-radio value="未上架">未上架</el-radio></el-radio-group></el-form-item><!-- 图片上传--><el-form-item label="商品图片"><el-uploadclass="avatar-uploader":action="'http://' + '192.168.31.242:8080/files/upload'":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="goods.imgurl" :src="goods.imgurl" class="avatar" style="width: 300px"/><el-icon v-else class="avatar-uploader-icon"><Plus/></el-icon></el-upload></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="save">提交</el-button></div></template></el-dialog>
</template><style scoped>
.avatar-uploader .el-upload {border: 1px dashed var(--el-border-color);border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;transition: var(--el-transition-duration-fast);
}.avatar-uploader .el-upload: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>
11.创建首页组件:Index.vue
<script setup>
import { reactive, onMounted,ref} from 'vue'
import { Memo } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import request from "@/axios/request.js";// 格式化日期时间
const formattedDate=()=>{const date = new Date();const year = date.getFullYear();const month = (date.getMonth() + 1).toString().padStart(2, '0');const day = date.getDate().toString().padStart(2, '0');const hour = date.getHours().toString().padStart(2, '0');const minute = date.getMinutes().toString().padStart(2, '0');const second = date.getSeconds().toString().padStart(2, '0');const formattedDate = `${year}-${month}-${day} ${hour}:${minute}:${second}`;console.log(formattedDate);return formattedDate;}
let date=formattedDate();
const loginInfo=ref({loginTime: date,loginPlace: "云南-昆明"
})
const data = reactive({user: JSON.parse(localStorage.getItem('xm-user') || '{}'),noticeData: []
})// 查询公告信息
const getNoticeList = () => {request({url: '/notice/page',method: 'get',params: {page: 1,limit: 4,}}).then((res) => {// console.log(res)data.noticeData = res.data.data;})
}// 商品数量
const total=ref(0)
// 将用户信息从浏览器缓存中取出
const user=ref(JSON.parse(localStorage.getItem('xm-user') || '{}'))
// 查询商品信息
const getList = () => {request({url: '/goods/page',method: 'get',params: {page: 1,limit: 10,goodsName: name.value,}}).then((res) => {// console.log(res)// list.value = res.data.data;total.value = res.data.count;console.log(total.value)// name.value=""})
}
// 图表1:月度销售额
const initCharts1 = () => {const myChart = echarts.init(document.getElementById('salesVolume'))myChart.setOption({color: ['#1493fa'],title: { text: '2024年月度销售额' },xAxis: {data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],name: '月份',axisLabel: {interval: 0},},yAxis: {name: '单位(千万元)',},grid: {left: '3%',right: '8%',bottom: '5%',containLabel: true,},legend: {},series: [{data: [6, 7, 8.5, 8, 9, 10, 13, 12, 10, 16, 15, 14],type: 'line',name: '销售额',smooth: true,label: {show: true,position: 'top',}}]})// 图表自适应大小window.onresize = () => {myChart.resize()}
}
// 图表2:2024年订单数量
const initCharts2 = () => {const myChart = echarts.init(document.getElementById('orderQuantity'))myChart.setOption({title: { text: '2024年订单数量' },color: ['#1493fa'],grid: {left: '3%',right: '8%',bottom: '3%',containLabel: true,},xAxis: {type: 'category',data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],name: '月份',// 类目轴中在 boundaryGap 为 true 的时候有效,可以保证刻度线和标签对齐axisTick: {alignWithLabel: true,},axisLabel: {interval: 0,rotate: 45 // 设置刻度标签旋转角度为45度},},legend: {},yAxis: {name: '单位(个)',},series: [{data: [400, 450, 300, 230, 250, 300, 400, 350, 160, 350, 380, 400],type: 'bar',barWidth: '60%',name: '订单总数',label: {show: true,position: 'top',}}]})// 图表自适应大小window.onresize = () => {myChart.resize()}
}//生命周期函数
onMounted(() => {getList();getNoticeList()// 初始化图表initCharts1()initCharts2()
})
</script><template><el-row :gutter="20"><!-- 登录信息--><el-col :span="6"><el-card class="box-card">
<!-- <el-card class="box-card"><template #header><div class="card-header"><img :src="user.avatar" style="width: 40px; height: 40px;">
<!– <el-avatar class="avatar" src="@/assets/img.png" shape="square" :size="40"> </el-avatar>–><span style="font-size: 24px;">{{ user.name }} </span></div></template><div class="info"><p>登录时间:{{ loginInfo.loginTime }}</p><p>登录地点:{{ loginInfo.loginPlace }}</p></div></el-card>--><div style="display: flex"><div class="card" style="flex: 50%; height: 400px;width: 200px"><div style="font-weight: bold; font-size: 18px; padding: 10px 0 30px 10px">系统公告</div><el-timeline style="max-width: 600px"><el-timeline-itemv-for="(item, index) in data.noticeData":key="index":timestamp="item.time">{{ item.title }}</el-timeline-item></el-timeline></div><div style="flex: 50%"></div></div></el-card></el-col><!-- 单月统计信息展示 --><el-col :span="18" ><el-card class="box-card"><template #header><div class="card-header">6月统计信息</div></template><div class="info" style="height: 340px"><el-row :gutter="24"><!-- 商品数量 --><el-col :span="8"><div class="card-container"><div class="card-left-container" style="background-color: #EEAD0E;"><el-icon :size="90"><Memo /></el-icon></div><div class="card-right-container"><p class="number">{{ total }}</p><p>商品数量(个)</p></div></div></el-col><!-- 商品分类数量 --><el-col :span="8"><div class="card-container"><div class="card-left-container" style="background-color: #AB82FF;"><el-icon :size="90"><Memo /></el-icon></div><div class="card-right-container"><p class="number">20</p><p>商品分类数量(个)</p></div></div></el-col><!-- 用户访问次数 --><el-col :span="8"><div class="card-container"><div class="card-left-container" style=" background-color: #63B8FF;"><el-icon :size="90"><Memo /></el-icon></div><div class="card-right-container"><p class="number">121</p><p>用户访问次数(次)</p></div></div></el-col></el-row></div></el-card></el-col></el-row><!-- 图表区域 --><el-row :gutter="20" style="margin-top: 10px"><el-col :span="12"><!-- 通过折线图展示2024年月度销售额 --><el-card class="box-card"><div id="salesVolume" style="width: auto; height:400px;"></div></el-card></el-col><el-col :span="12"><!-- 通过柱状图展示2024年订单数量 --><el-card class="box-card"><div id="orderQuantity" style="width: auto; height:400px;"></div></el-card></el-col></el-row>
</template><style scoped></style>
12.创建登录组件:Login.vue
<script setup>
import {ref} from "vue";
import {User,Lock} from "@element-plus/icons-vue";
import request from "@/axios/request.js";
import router from "@/router/router.js";
import {ElMessage} from "element-plus";
import {useRouter} from "vue-router";
// const router=useRouter()const user=ref({username:"",password:"",role:""
})
const rules={username:[{required:true,message:"请输入用户名",trigger:"blur"}],password:[{required:true,message:"请输入密码",trigger:"blur"}],role:[{required:true,message:"请选择角色",trigger:"blur"}]
}
// 表单引用
const formRef=ref()
// 登录验证
const login=()=>{formRef.value.validate((flag)=>{if(flag){request({url:"/login",method:"post",data:user.value}).then(res => {console.log(res)if (res.data.code==200){ElMessage.success("登录成功!")// 将用户信息保存到浏览器缓存中localStorage.setItem('xm-user', JSON.stringify(res.data.data))// 跳转首页router.push("/manage/index")}else {ElMessage.error(res.data.msg)}})}})
}</script><template><div class="login-container"><div class="login-box"><div style="font-weight: bold; font-size: 24px; text-align: center; margin-bottom: 30px; color: #1450aa">欢 迎 登 录</div><el-form ref="formRef" :model="user" :rules="rules"><el-form-item prop="username"><el-input :prefix-icon="User" size="large" v-model="user.username" placeholder="请输入账号"></el-input></el-form-item><el-form-item prop="password"><el-input show-password :prefix-icon="Lock" size="large" v-model="user.password" placeholder="请输入密码"></el-input></el-form-item><el-form-item prop="role"><el-select size="large" v-model="user.role" placeholder="请选择角色"><el-option value="ADMIN" label="管理员"></el-option></el-select></el-form-item><el-form-item><el-button size="large" type="primary" style="width: 100%" @click="login">登 录</el-button></el-form-item><div style="text-align: right">还没有账号?请 <router-link to="/register"><b style="color: dodgerblue">注册</b></router-link></div></el-form></div></div>
</template><style scoped>
.login-container {height: 100vh;overflow: hidden;display: flex;justify-content: center;align-items: center;background: linear-gradient(to top, #7f7fd5, #86a8e7, #91eae4);
}
.login-box {width: 350px;padding: 30px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);background-color: rgba(255, 255, 255, 0.5);
}
</style>
13.添加路由规则–router.js
import {createRouter,createWebHashHistory} from "vue-router";
// 在router.js文件中创建路由实例对象
const router=createRouter({history:createWebHashHistory(),routes:[//路由规则{path:"/",redirect:"/login"},{path:"/manage",component:()=>import('@/views/Manage.vue'),children:[//子路由{path:"index",component:()=>import('@/views/manage/Index.vue')},{path:"goods",component:()=>import('@/views/manage/Goods.vue')},{path:"admin",component:()=>import('@/views/manage/Admin.vue')},{path:"personal",component:()=>import('@/views/manage/Personal.vue')},{path:"password",component:()=>import('@/views/manage/Password.vue')},{path:"notice",component:()=>import('@/views/manage/Notice.vue')},]},{path:"/login",component:()=>import('@/views/Login.vue')},{path:"/404",component:()=>import('@/views/404.vue')},{path:"/register",component:()=>import('@/views/Register.vue')},{path: '/:pathMatch(.*)', redirect: '/404' }]
})
// 输出实例对象
export default router;
效果图:
首页:
商品信息管理:
完整项目可以从资源下载