vue2的后台管理系统 迁移到 vue3后台管理系统
重构的流程
- 1.新建项目,确定脚手架版本
- 2.项目整体迁移
- 3.重构路由,axios,element-plus等项目所需要的依赖
- 4.迁移组件内容(需要的配置项移步到5目录and6目录)
- 4-1.Login页面
- 4-2. Home页
- 4-3.Students管理内部的页面
- 4-3-1.studentList(学生列表)
- 4-3-2.InfoList(信息列表)
- 4-3-3.InfoLists(信息管理)
- 4-3-4.WorkList(作业列表页)
- 4-3-5.WorkMenu(作业管理页)
- 5.迁移到vue3中所用到的组件
- 5-1.面包屑组件(Breadcrumb)
- 5-2.侧边栏 组件(Menu)
- 5-3.头部组件(Header)
- 5-4.分页组件(pageing)
- 5-5.页尾组件(footer)
- 6.迁移到vue3中所用到的模块
- 6-1.setToken.js模块
- 6-2.table.js模块
- 6-3.vaildata.js正则模块
- 7.总结:
1.新建项目,确定脚手架版本
1-1.新建项目
npm create vite (filename)
1-2.查看脚手架版本是否是3.0.0版本,如果是则安装成功,否则安装失败
2.项目整体迁移
把vue2中所要用到的组件以及文件,图片迁移到vue3的组件内
3.重构路由,axios,element-plus等项目所需要的依赖
3-1.下载依赖可以使用两种方式
3-1-1:将依赖一次性下载完成
npm i axios,element-plus,vue-router,sass-loader,qs,
echarts,font-awesome,vite-aliases
3-1-2:使用那个就下载那个的依赖包
npm i //下载依赖
npm i axios //下载请求
npm i element-plus //下载element-plus
npm i vue-router //下载路由
npm i sass-loader //下载sass
npm i qs //下载qs方法
npm i echarts //下载echarts
npm i font-awesome //下载图标库
npm i vite-aliases //下载@的依赖文件
下载完成移步4目录看修改vue2转换vue3的组件
4.迁移组件内容(需要的配置项移步到5目录and6目录)
4-1.Login页面
<template><div class="login"><el-card class="box-card"><!-- 这里的template只是为了承载插槽 #header--><template #header><div class="clearfix"><span>通用后台管理器</span></div></template><el-form :model="form" status-icon ref="form" label-width="100px" class="demo-ruleForm" :rules="rules"><el-form-item label="用户名" prop="name"><el-input type="text" v-model="form.name" autocomplete="off"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input v-model="form.password"></el-input></el-form-item><el-form-item><el-button type="primary" @click="login('form')">登录</el-button></el-form-item></el-form></el-card></div>
</template><script>
import { login } from "@/api/api.js"
import { nameRule, passRule } from "@/utils/validate.js"
import { setToken } from "@/utils/setToken.js";
export default {name: "Login",data() {return {form: {name: "admins",password: "Dx1212$",},rules: {name: [{ validator: nameRule, required: true, trigger: 'blur' },],password: [{ validator: passRule, required: true, trigger: 'blur' }],}}},methods: {login(form) {this.$refs[form].validate((valid) => {if (valid) {login(this.form).then((res) => {if (res.data.status === 200) {setToken("token", res.data.token);setToken("username", this.form.name);this.$message({ message: res.data.message, type: 'success' });location.href = "/Home"}})} else {// console.error(this.form)}})},},created() {// 记录url地址栏中路由信息// console.log(this.$route.matched)}
};
</script><style lang="scss">
.login {width: 100%;height: 100%;position: absolute;background: url(../assets/bg.jpg);.box-card {width: 450px;margin: 200px auto;background: #65768557;.clearfix {//标题font-size: 34px;color: white;}.el-button {//按钮width: 100%;}.el-form-item__label {color: white;}}
}
</style>
4-2. Home页
<template><div class="home"><!-- 头部 --><Header></Header><!-- 主体部分 --><el-container class="content"><!-- 左侧 --><Menu></Menu><!-- 右侧 --><el-container><el-main><!-- 面包屑 --><Bread></Bread><div class="count"><router-view></router-view></div></el-main><!-- 尾部 --><el-footer><Footer></Footer></el-footer></el-container></el-container></div>
</template><script>
import Header from './common/Header.vue';
import Bread from './common/Breadcrumb.vue';
import Menu from './common/Menu.vue';
import Footer from './common/Footer.vue';
export default {name: 'home',props: {msg: String},components: {Header,Bread,Menu,Footer},created() {console.log(this.$route.matched)}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.home {width: 100%;height: 100%;.content {position: absolute;width: 100%;top: 60px;bottom: 0;.count {margin: 20px 0px;}}
}
</style>
4-3.Students管理内部的页面
4-3-1.studentList(学生列表)
<template><div><!-- 查询 --><el-form :inline="true" :model="formInline" class="demo-form-inline" size="small" align="left"><el-form-item label="姓名"><el-input v-model="formInline.name" placeholder="请输入姓名"></el-input></el-form-item><el-form-item><el-button type="primary" @click="find">查询</el-button></el-form-item><el-form-item><el-button type="primary" @click="reset">重置</el-button></el-form-item></el-form><!-- 表格 --><!--1:0-9 2:10-19 3:20-29 slice(当前页数-1) *每页的条数,当前页数*当前的条数--><el-table v-loading="loading" border :data="compData" style="width: 100%"><el-table-column prop="name" label="姓名" align="center"></el-table-column><el-table-column prop="sex_text" label="性别" align="center"></el-table-column><el-table-column prop="age" label="年龄" align="center"></el-table-column><el-table-column prop="number" label="学号" align="center"></el-table-column><el-table-column prop="class" label="班级号" align="center"></el-table-column><!-- 判断是否入学 --><el-table-column prop="state_text" label="状态" align="center"></el-table-column><el-table-column prop="address" label="地址" align="center"></el-table-column><el-table-column prop="phone" label="联系方式" align="center"></el-table-column><el-table-column label="操作" width="120px" align="center"><!-- 相当于ref --><template slot-scope="scope"><el-button type="primary" size="small" icon="Delete" @click="del(scope.row)"></el-button></template></el-table-column></el-table><!-- 分页 --><el-card><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage":page-sizes="[5, 10, 20, 30, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination></el-card>
</div>
</template><script setup>
import { student, studentDel } from '../../api/api';
import { ref, reactive, computed } from "vue"
import service from '../../api/service';let tableData = reactive([])//表格的总数据
let formInline = reactive({//查询name: ''
})
// console.log("wewe", formInline.name);
let total = ref(0) //总条数
let pageSize = ref(10)//每页显示的数量
let currentPage = ref(1)//当前页
let loading = ref(true)//加载遮罩层
getData()let compData = computed(() => {// console.log(tableData);return tableData.slice((currentPage.value - 1) * pageSize.value,//起点currentPage.value * pageSize.value//终点(数据取在终点的前一个结束))
})function handleSizeChange(val) {//修改每页显示的数量pageSize.value = val;currentPage.value = 1;//每次修改完成之后,回到当前第一页
}
function handleCurrentChange(val) { //修改当前页currentPage.value = val;
}
// 获取数据
function getData(params) {console.log(params);student(params).then((res) => {if (res.data.status === 200) {tableData.length = 0tableData.push(...res.data.data)total.value = res.data.total;tableData.forEach((item) => {// 尽量不要去修改原数据,因为后续的使用会造成影响item.sex === 1 ? (item.sex_text = "男") : (item.sex_text = "女");// 字符串的话要是用== 不可以使用===item.state === "1"?(item.state_text = "已入学") : item.state === "2"?(item.state_text = "未入学") : (item.state_text = "休学中");})loading.value = false}})
}
// 删除
function del(row) {studentDel(row.id).then((res) => {if (res.data.status === 200) {message({ message: "数据删除成功", type: 'success' });// 重新获取数据getData();// console.log(getData())}})
}
// 查询
function find() {//根据姓名显示数据getData(formInline)// console.log(tableData)
}
// 重置
function reset() {formInline = reactive({});getData(formInline.name)
}
</script><style lang="scss" scoped>
.demo-form-inline {padding-left: 10px;
}.el-card {margin-top: 20px;
}
</style>
4-3-2.InfoList(信息列表)
<template><div class="infolist"><!-- 新增按钮 --><el-form :inline="true" class="demo-form-inline" size="small" align="left"><el-form-item><el-button type="primary" @click="assStudent">新增</el-button></el-form-item></el-form><!-- 信息列表 --><el-table :data="compData" border style="width: 100%" v-loading="loading"><el-table-column prop="name" label="姓名" align="center"></el-table-column><el-table-column prop="sex_text" label="性别" align="center"></el-table-column><el-table-column prop="age" label="年龄" align="center"></el-table-column><el-table-column prop="time" label="入学时间" align="center"></el-table-column><el-table-column prop="father" label="父亲" align="center"></el-table-column><el-table-column prop="mather" label="母亲" align="center"></el-table-column><el-table-column prop="phone" label="手机号" align="center"></el-table-column><el-table-column prop="address" label="地址" align="center"></el-table-column><el-table-column label="操作" width="120px" align="center"><!-- 相当于ref --><template #default=scope><el-button type="primary" size="small" :icon="Edit" @click="edit(scope.row)"></el-button><el-button type="primary" size="small" :icon="Delete" @click="del(scope.row)"></el-button></template></el-table-column></el-table><!-- 课堂小练习:完成分页效果,效果详情参考studentList --><el-card><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage":page-sizes="[5, 10, 20, 30, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination></el-card><!-- 复用提示框 --><el-dialog width="450px" :title="state ? '添加学生信息' : '修改学生信息'" :model-value="dialogFormVisible"><el-form :model="form" ref="formRef"><el-form-item label="姓名" prop="name" :label-width="formLabelWidth"><el-input v-model="form.name" autocomplete="off"></el-input></el-form-item><el-form-item label="性别" prop="sex" :label-width="formLabelWidth"><el-radio v-model="form.sex" label="1">男</el-radio><el-radio v-model="form.sex" label="2">女</el-radio></el-form-item><el-form-item label="年龄" prop="age" :label-width="formLabelWidth"><el-input v-model="form.age" autocomplete="off"></el-input></el-form-item><el-form-item label="联系方式" prop="phone" :label-width="formLabelWidth"><el-input v-model="form.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="父亲" prop="father" :label-width="formLabelWidth"><el-input v-model="form.father" autocomplete="off"></el-input></el-form-item><el-form-item label="母亲" prop="mather" :label-width="formLabelWidth"><el-input v-model="form.mather" autocomplete="off"></el-input></el-form-item><el-form-item label="入学时间" prop="time" :label-width="formLabelWidth"><el-date-picker v-model="form.time" type="date" placeholder="选择日期" format="yyyy 年 MM 月 dd 日"value-format="yyyy-MM-dd"></el-date-picker></el-form-item><el-form-item label="家庭住址" prop="address" :label-width="formLabelWidth"><el-input v-model="form.address" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="closeInfo('form')">取 消</el-button><el-button type="primary" @click="sure('form')">确 定</el-button></div></el-dialog>
</div>
</template><script setup>
import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue'
import { getInfo, info, infoDel } from '../../api/api';
import { ref, reactive, computed } from "vue";
import service from '../../api/service';
import { ElMessage, ElMessageBox } from 'element-plus'// export default {
// data() {
// return {
let tableData = reactive([])//信息列表数据
let total = ref(0)//总数
let currentPage = ref(1)//当前页
let pageSize = ref(10)//每页数量/
let state = ref(false)//区分新增还是修改
let dialogFormVisible = ref(false)//判断提示框显示隐藏
let formLabelWidth = ref('80px')//默认宽度
// 对象的setter 可以创建属性,可以去创建属性,再去赋值
// getter 会直接去找该属性,如果没有属性,报错
let form = reactive({name: "",age: "",sex: '1',father: "",mather: "",phone: '',time: "",address: "",id: 1
})
let loading = ref(true)getData()let compData = computed(() => {console.log("erer", compData)return tableData.slice((currentPage.value - 1) * pageSize.value,//起点currentPage.value * pageSize.value//终点(数据取在终点的前一个结束))
})function handleSizeChange(val) {//修改每页显示的数量pageSize.value = val;currentPage.value = 1;//每次修改完成之后,回到当前第一页
}
function handleCurrentChange(val) { //修改当前页currentPage.value = val;
}
// 获取信息列表数据
function getData() {getInfo().then((res) => {console.log(res)if (res.data.status === 200) {tableData.length = 0tableData.push(...res.data.data)total.value = res.data.totalconsole.log(tableData)tableData.forEach((item) => {item.sex === '1' ? (item.sex_text = "男") : (item.sex_text = "女")})loading.value = false}})
}
// 新增数据
function assStudent() {//1.弹出 提示框dialogFormVisible.value = true;// 修改文字state.value = true;let i = 0form = reactive({name: "",age: "",sex: '1',father: "",mather: "",phone: '',time: "",address: "",id: i++})
}
function edit(row) {console.log(row);form = reactive({ ...row });state.value = false;//切换对话框标题dialogFormVisible.value = true
}
const formRef = ref(null)
// 取消按钮
function closeInfo() {formRef.value.resetFields();dialogFormVisible.value = false;
}
// 确定按钮
function sure() {console.log(1111);dialogFormVisible.value = false// 是否复合正则要求formRef.value.validate(valid => {if (valid) {// 判断是新增还是修改if (state.value) {//新增info('post', form).then((res) => {// console.log(form.value, 111);if (res.data.status === 200) {getData()dialogFormVisible.value = false;ElMessage({ type: "success", message: res.data.message })}})} else {//修改info('put', form).then((res) => {if (res.data.status === 200) {getData();dialogFormVisible.value = false;ElMessage({ type: "success", message: res.data.message })}})}}})}
function del(row) {// alert("你确定要删除吗?", "提示", {// confirmButtonText: "确定",// callback: () => {// console.log(111)// infoDel(row.id).then(res => {// if (res.data.status === 200) {// getData()// ElMessage({ type: "success", message: res.data.message })// }// })// }// })ElMessageBox.alert('This is a message', 'Title', {// if you want to disable its autofocus// autofocus: false,confirmButtonText: 'OK',callback: () => {infoDel(row.id).then(res => {if (res.data.status === 200) {getData()ElMessage({ type: "success", message: res.data.message })}})},})
}
</script><style lang="scss" scoped>
.demo-form-inline {padding-left: 10px;
}.el-card {margin-top: 20px;
}
</style>
4-3-3.InfoLists(信息管理)
<template><div class="infolist"><!-- 新增按钮 --><el-form :inline="true" class="demo-form-inline" size="small" align="left"><el-form-item><el-button type="primary" @click="assStudent">新增</el-button></el-form-item></el-form><!-- 信息列表 --><el-table :data="compData" border style="width: 100%" v-loading="loading"><el-table-column prop="name" label="姓名" align="center"></el-table-column><el-table-column prop="sex_text" label="性别" align="center"></el-table-column><el-table-column prop="age" label="年龄" align="center"></el-table-column><el-table-column prop="time" label="入学时间" align="center"></el-table-column><el-table-column prop="father" label="父亲" align="center"></el-table-column><el-table-column prop="mather" label="母亲" align="center"></el-table-column><el-table-column prop="phone" label="手机号" align="center"></el-table-column><el-table-column prop="address" label="地址" align="center"></el-table-column><el-table-column label="操作" width="120px" align="center"><!-- 相当于ref --><template #default=scope><el-button type="primary" size="small" :icon="Edit" @click="edit(scope.row)">dfgh</el-button><el-button type="primary" size="small" :icon="Delete" @click="del(scope.row)"></el-button></template></el-table-column></el-table><!-- 课堂小练习:完成分页效果,效果详情参考studentList --><el-card><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage":page-sizes="[5, 10, 20, 30, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination></el-card><!-- 复用提示框 --><el-dialog width="450px" :title="state ? '添加学生信息' : '修改学生信息'" :model-value="dialogFormVisible"><el-form :model="form" ref="from"><el-form-item label="姓名" prop="name" :label-width="formLabelWidth"><el-input v-model="form.name" autocomplete="off"></el-input></el-form-item><el-form-item label="性别" prop="sex" :label-width="formLabelWidth"><el-radio v-model="form.sex" label="1">男</el-radio><el-radio v-model="form.sex" label="2">女</el-radio></el-form-item><el-form-item label="年龄" prop="age" :label-width="formLabelWidth"><el-input v-model="form.age" autocomplete="off"></el-input></el-form-item><el-form-item label="联系方式" prop="phone" :label-width="formLabelWidth"><el-input v-model="form.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="父亲" prop="father" :label-width="formLabelWidth"><el-input v-model="form.father" autocomplete="off"></el-input></el-form-item><el-form-item label="母亲" prop="mather" :label-width="formLabelWidth"><el-input v-model="form.mather" autocomplete="off"></el-input></el-form-item><el-form-item label="入学时间" prop="time" :label-width="formLabelWidth"><el-date-picker v-model="form.time" type="date" placeholder="选择日期" format="yyyy 年 MM 月 dd 日"value-format="yyyy-MM-dd"></el-date-picker></el-form-item><el-form-item label="家庭住址" prop="address" :label-width="formLabelWidth"><el-input v-model="form.address" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="closeInfo('form')">取 消</el-button><el-button type="primary" @click="sure('form')">确 定</el-button></div></el-dialog>
</div>
</template><script setup>
import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue'
import { info, infoDel } from '../../api/api';
import { getData, changInfo, delData } from '../../utils/table';
import service from '../../api/service';
import { computed, ref, toRef, reactive } from 'vue';
let tableData = reactive([])//信息列表数据
let total = ref(0)//总数
let currentPage = ref(1)//当前页
let pageSize = ref(10)//每页数量
let state = ref(false)//区分新增还是修改
let dialogFormVisible = ref(false)//判断提示框显示隐藏
let formLabelWidth = ref('80px')//默认宽度
// 对象的setter 可以创建属性,可以去创建属性,再去赋值
// getter 会直接去找该属性,如果没有属性,报错
var i = 0
let form = reactive({name: "",age: "",sex: '1',father: "",mather: "",phone: '',time: "",address: "",id: i++
})
let loading = ref(true);
const datas = toRef(tableData)._object
let obj = {datas,total,loading,service
}
getData(obj, '/info');let compData = computed(() => {return tableData.slice((currentPage.value - 1) * pageSize.value,//起点currentPage.value * pageSize.value//终点(数据取在终点的前一个结束))
})
function handleSizeChange(val) {//修改每页显示的数量pageSize.value = val;currentPage.value = 1;//每次修改完成之后,回到当前第一页
}
function handleCurrentChange(val) { //修改当前页currentPage.value = val;
}
// 获取信息列表数据// 新增数据
function assStudent() {// console.log("ghj");//1.弹出 提示框dialogFormVisible.value = true;// 修改文字state.value = true;let i = 0form = reactive({name: "",age: "",sex: '1',father: "",mather: "",phone: '',time: "",address: "",id: i++})
}
function edit(row) {// console.log("121212", row);form.value = reactive({ ...row });state.value = false;//切换对话框标题dialogFormVisible.value = true
}
const from = ref(null)
// 取消按钮
function closeInfo(form) {from.resetFields();dialogFormVisible.value = false;
}
// 确定按钮
function sure() {console.log(11)dialogFormVisible.value = false// 是否复合正则要求let method = '';const datas = toRef(tableData)._objectlet mm = {service,dialogFormVisible,datas,total,loading,service}state.value ? method = "post" : method = 'put';changInfo(mm, method, '/info', form, getData);}
function del(row) {// console.log(11111, row);const datas = toRef(tableData)._objectlet obj3 = {row,service,datas,total,loading,}// console.log(1111, row)delData(obj3, '/info', row.id, getData);
}</script><style lang="scss" scoped>
.demo-form-inline {padding-left: 10px;
}.el-card {margin-top: 20px;
}
</style>
4-3-4.WorkList(作业列表页)
<template><div class="workList"><!-- 信息列表 --><el-table :data="tableData" v-loading="loading" border style="width: 100%"><el-table-column prop="id" label="用户id" align="center"></el-table-column><el-table-column prop="userId_text" label="所属班级" align="center"></el-table-column>6<el-table-column prop="title" label="作业名称" align="center"></el-table-column><el-table-column prop="completed_text" label="完成情况" align="center"></el-table-column></el-table><!-- 分页 --><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page":page-sizes="[10, 20, 30, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination>
</div>
</template><script setup>import service from "../../api/service.js"
import { getTableData } from "@/utils/table.js"
import { ref, reactive } from "vue";
let tableData = reactive([])
let page = ref(1)
let size = ref(10)
let total = ref(0)
let loading = ref(false)
// 通过接口,请求数据
// getTable()
// const datas = tableData
const obj = reactive({service,tableData,total,loading
})
let comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }
getTableData(obj, "/works", { page: page.value, size: size.value }, ["completed", "userId"], comp)
// console.log(getTable())function handleSizeChange(val) {console.log(`每页 ${val} 条`);size.value = valpage.value = 1;let comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }getTableData(obj, "/works", { page: page.value, size: size.value }, ["completed", "userId"], comp)
}
function handleCurrentChange(val) {console.log(`当前页: ${val}`);console.log(page);page.value = vallet comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }getTableData(obj, "/works", { page: page.value, size: size.value }, ["completed", "userId"], comp)
}// computed: {// compData() {// return this.tableData.slice(// (this.page - 1) * this.size,//起点// this.page * this.size//终点(数据取在终点的前一个结束)// )// }// }</script><style lang="scss" scoped></style>
4-3-5.WorkMenu(作业管理页)
<template><div class="workList"><!-- 信息列表 --><el-table :data="tableData" v-loading="loading" border style="width: 100%"><el-table-column prop="id" label="用户id" align="center"></el-table-column><el-table-column prop="userId_text" label="所属班级" align="center"></el-table-column><el-table-column prop="title" label="作业名称" align="center"></el-table-column><el-table-column prop="completed_text" label="完成情况" align="center"></el-table-column></el-table><Page :total="total" :url="url" :obj="obj"></Page>
</div>
</template><script setup>import service from "@/api/service.js"import Page from '../common/Pageing.vue';
import { ref, reactive } from "vue";
// data() {
// return {
let tableData = reactive([])
let total = ref(0)
let loading = ref(true)
let url = ref("/works")let obj = {tableData,total,loading,url,service
}// }// },// mounted() {// // console.log(this.tableData)// }// computed: {// compData() {// return this.tableData.slice(// (this.page - 1) * this.size,//起点// this.page * this.size//终点(数据取在终点的前一个结束)// )// }// }// }
</script><style lang="scss" scoped></style>
5.迁移到vue3中所用到的组件
5-1.面包屑组件(Breadcrumb)
<template><div><el-card><el-breadcrumb separator-class="el-icon-arrow-right"><el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item><!-- 课堂小练习:给各级的面包屑,添加路由跳转的功能 --><el-breadcrumb-item v-for="(item, index) in $route.matched" :ue="item" :key="index":to="{ name: item.name }">{{ item.name }}</el-breadcrumb-item></el-breadcrumb></el-card></div>
</template><script setup>
import { ref } from "vue"
let ue = ref("")
</script><style lang="scss" scoped></style>
5-2.侧边栏 组件(Menu)
<template><div class="menu"><el-aside width="203px"><el-menu router default-active="2" class="el-menu-vertical-demo" background-color="#2578B5"text-color="#fff" active-text-color="#ffd04b"><template v-for="(item, index) in menus"><el-sub-menu :index="index + ''" :key="index" v-if="!item.hidden"><template #title><i :class="item.iconClass" style="margin-right:20px"></i><span>{{ item.name }}</span></template><el-menu-item v-for="(child, index) in item.children" :key="index" :index="child.path"><el-menu-item :index="child.path"><i :class="child.iconClass" style="margin-right:10px"></i>{{ child.name }}</el-menu-item></el-menu-item></el-sub-menu></template></el-menu></el-aside></div>
</template><script setup>
import { useRouter } from 'vue-router';
const router = useRouter();
const menus = router.options.routes;
// 默认展开项
const activePach = router.currentRoute.value.path;</script><style lang="scss" scoped>
.menu {// 谷歌中的滚动条::-webkit-scrollbar {display: none;}.el-aside {height: 100%;.el-menu {height: 100%;.fa {margin-right: 10px;}}.el-submenu .el-menu-item {min-width: 0;}}
}
</style>
5-3.头部组件(Header)
<template><div class="header"><el-header><div class="title">通用管理系统</div><div>{{ name }}</div></el-header></div>
</template><script setup>
import { getToken } from "@/utils/setToken.js";
import { ref, onMounted } from "vue";let name = ref("")name.value = getToken("username")</script><style lang="scss" scoped>
.header {.el-header {background-color: #2578b5;color: white;line-height: 60px;display: flex;justify-content: space-between;.title {width: 200px;font-size: 24px;// background: #2578b5;}}
}
</style>
5-4.分页组件(pageing)
<!-- 这里整个文件是 组件化封装 -->
<template><div><!-- 分页 --><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page":page-sizes="[10, 20, 30, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next, jumper":total="total" :url="url" :obj="obj"></el-pagination>
</div>
</template><script setup>
import { getTableData } from "@/utils/table.js"
import { ref, onMounted } from "vue";
const props = defineProps({"url": String,"total": Number,"obj": Object
})let page = ref(1);
let size = ref(10);console.log(props.obj)
onMounted(() => {// 通过接口,请求数据// getTable()let comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }getTableData(props.obj, props.url, { page: page.value, size: size.value }, ["completed", "userId"], comp)
})function handleSizeChange(val) {// console.log(`每页 ${val} 条`);size.value = val;page.value = 1;let comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }getTableData(props.obj, props.url, { page: page.value, size: size.value }, ["completed", "userId"], comp)
}
function handleCurrentChange(val) {// console.log(`当前页: ${val}`);page.value = vallet comp = { "completed": ["已完成", "未完成"], "suerId": ["猪猪侠一班", "猪猪侠二班", "猪猪侠三班", "猪猪侠四班"] }getTableData(props.obj, props.url, { page: page.value, size: size.value }, ["completed", "userId"], comp)
}</script><style lang="scss" scoped></style>
5-5.页尾组件(footer)
<template><div><el-card>Frontend 2022 Casey</el-card></div>
</template><script setup></script><style lang="scss" scoped></style>
6.迁移到vue3中所用到的模块
6-1.setToken.js模块
export function setToken(tokenKey, tokenValue) {return localStorage.setItem(tokenKey, tokenValue)
}export function getToken(tokenKey) {return localStorage.getItem(tokenKey)
}export function removeToken(tokenKey) {return localStorage.removeItem(tokenKey)
}
6-2.table.js模块
import { ElMessage, ElMessageBox } from "element-plus";
// 这个整个文件是 模块化
// 获取表格数据
export function getData(root, url, params) {// console.log(1112345031E481, root);root.service.get(url, { params: params || {} }).then((res) => {if (res.data.status === 200) {root.datas.length = 0root.datas.push(...res.data.data)root.total.value = res.data.totalroot.datas.forEach((item) => {item.sex === '1' ? (item.sex_text = "男") : (item.sex_text = "女")})root.loading.value = false}}).catch((err) => {throw err;})
}
// 新增和修改的确定按钮封装
import qs from "qs";
export function changInfo(root, method, url, form, callback) {// 判断是新增还是修改// 转换数据类型 后端的数据有问题let data = qs.stringify(form)root.service[method](url, data).then((res) => {if (res.data.status === 200) {callback(root, url);root.dialogFormVisible.value = false;ElMessage({ type: "success", message: res.data.message })}}).catch(err => {// 直接在控制台上弹出错误throw err;})
}
// 删除提示框封装
export function delData(root, url, id, callFun) {ElMessageBox.alert("你确定要删除吗?", "提示", {confirmButtonText: "确定",callback: () => {console.log(root.service.delete(`${url}/${id}`), "2345678");root.service.delete(`${url}/${id}`).then(res => {console.log(11111, res)if (res.data.status === 200) {callFun(root, url)console.log(root, url, 111);ElMessage({ type: "success", message: res.data.message })}})}})}// 作业列表,获取数据的封装
export function getTableData(root, url, params, arr, text_patams) {root.service.get(url, { params: params || {} }).then(res => {// console.log(root);if (res.data.status === 200) {root.tableData.length = 0root.tableData.push(...res.data.data)root.total.value = res.data.total// 外层循环 找到数组中的每一个对象root.tableData.map(item => {// 内层循环 找到每一个对象中需要修改的属性arr.map((aItem, index) => {// console.log(2, item, item[aItem], aItem, index, text_patams.completed[index])if (aItem == "completed") {item[aItem] ? item[aItem + "_text"] = text_patams.completed[index] : item[aItem + "_text"] = text_patams.completed[index + 1]} else {if (item.userId === 1) {item[aItem + "_text"] = "猪猪侠一班"return false} else if (item.userId === 2) {item[aItem + "_text"] = "猪猪侠二班"return false} else if (item.userId === 3) {item[aItem + "_text"] = "猪猪侠三班"return false} else if (item.userId === 4) {item[aItem + "_text"] = "猪猪侠四班"return false} else if (item.userId === 5) {item[aItem + "_text"] = "猪猪侠五班"return false} else if (item.userId === 6) {item[aItem + "_text"] = "猪猪侠六班"return false} else if (item.userId === 7) {item[aItem + "_text"] = "猪猪侠七班"return false} else if (item.userId === 8) {item[aItem + "_text"] = "猪猪侠八班"return false} else if (item.userId === 9) {item[aItem + "_text"] = "猪猪侠九班"return false} else if (item.userId === 10) {item[aItem + "_text"] = "猪猪侠十班"return false}}})})// console.log(root.loading);// root.loadingroot.loading.value = false}}).catch(err => {throw err;})
}
6-3.vaildata.js正则模块
// 用户名匹配
export function nameRule(rule, value, callback) {let reg = /(^[a-zA-Z0-9]{4,10}$)/if (value === '') {callback(new Error("请输入用户名"));} else if (!reg.test(value)) {callback("请输入4-10位的用户名")} else {callback();}
}//密码正则匹配
export function passRule(rule, value, callback) {let reg = /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/if (value === '') {callback(new Error("请输入密码"));} else if (!reg.test(value)) {callback("请输入6-12位带有数字大小写字符以及特殊符号")} else {callback();}
}
7.总结:
以上所属都是vue2迁移到vue3所用到的内容,有何不懂评论区问答!!!
相关文章:
vue2的后台管理系统 迁移到 vue3后台管理系统
重构的流程1.新建项目,确定脚手架版本2.项目整体迁移3.重构路由,axios,element-plus等项目所需要的依赖4.迁移组件内容(需要的配置项移步到5目录and6目录)4-1.Login页面4-2. Home页4-3.Students管理内部的页面4-3-1.studentList(学生列表)4-3-2.InfoList(信息列表)4-3-3.InfoLi…...
2023年美赛F题
关键点1.绿色GDP(GGDP)是否比传统GDP更好好的衡量标准?2.如果GGDP成为经济健康的主要量标准,可能会对环境产生什么影响?3建立一个简单的模型,估计GGDP取代GDP作为经济健康的主要衡量标准,对减缓气候变化产生的影响。4.GGDP取代GDP可能会遇到…...
【数据结构与算法分析】介绍蛮力法以及相关程序案例
文章目录蛮力法之排序选择排序冒泡排序实际应用蛮力法之最近对和凸包问题最近对问题凸包问题蛮力法(brute force),其本质跟咱常说的暴力法是一样的,都是一种简单直接地解决问题的方法,通常直接基于问题的描述和所涉及的概念定义进行求解。 蛮…...
用股票交易量查询接口是怎么查询a股全天总成交量的?
用股票交易量查询接口是怎么查询a股全天总成交量的?今天下班就以通达信给大家讲解一下,通常是在K线图的底部状态栏,可以在日线进行查看a股成交量。在市场栏底部的子图中。 有当天成交的数量。成交量是表示一定的时间内已经成交的中的成交数量…...
求职季哪种 Python 程序员能拿高薪?
本文以Python爬虫、数据分析、后端、数据挖掘、全栈开发、运维开发、高级开发工程师、大数据、机器学习、架构师这10个岗位,从拉勾网上爬取了相应的职位信息和任职要求,并通过数据分析可视化,直观地展示了这10个职位的平均薪资和学历、工作经…...
如何选择好的IB课程学校?
在上海除了拼中考,你还可以走一条更有“选择权”的路——国际化学校! 然而选择学校时,让家长最头痛的事情,莫过于为孩子选择什么样的国际化课程。 今天我们来聊聊IB课程! 三大主流国际课程中,被公认含金量最…...
2023美赛ABCDEF题思路+参考文献+代码
选题建议、ABCDEF题参考文献、ABCDEF题思路(后续更新视频和代码)、D题数据、数据集及处理方式已更新,其他日内更新。下文包含:2023年美国大学生数学建模竞赛(以下简称美赛)A - F题思路解析、选题建议、代码…...
DataEase 制作数据可视化大屏经验分享
前言 DataEase 简介 DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。DataEase 支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表,并可以方便地与他人分享。 更多详细介…...
前端基础-2day
前端基础 这里写目录标题前端基础div和span标签div 标签span标签列表有序列表无序列表自定义列表图片超链接标签表格 table表格合并表单标签表单控键属性div和span标签 div 标签 没有具体的含义,用于划分页面区域,独占一行 快捷键:div{}*3 …...
在线一键JS混淆还原
当今,随着互联网的发展,越来越多的网站开始使用JavaScript来实现动态交互和用户体验。但是,由于JavaScript代码的开放性和易于复制,网站管理员需要采取一些措施来保护他们的代码。这就是JavaScript混淆工具产生的原因。 jsjiami.…...
Java基本语法
目录 一、注释方式 1、单行注释 // 2、多行注释 /*...*/ 3、文档注释 /**....*/ 二、标识符和关键字 三、数据类型 拓展及面试题讲解 1、整数拓展 进制 二进制0b 八进制0 十六进制0x 2、字符拓展 编码Unicode表 2字节 0~65536 3、字符串拓展 4、布尔值拓展 一、注释方式…...
什么表单设计工具能快速提升办公效率?
在信息化快速发展的年代,谁能掌握更先进的技术,谁就能拥有更广阔的发展前景。在以前的办公环境中,传统的表单制作工具占据了主流地位,随着办公自动化的快速发展,传统表单工具的弊端也暴露出来了,采用更先进…...
SystemVerilog——Axi4Lite_To_Localbus
摘要:用SystemVerilog对Axi4转localbus进行编写与仿真 如果需要从PS端对PL进行寄存器的读写操作,从znyq M_AXI_HPM_FPD出来,经过axi_interconnect 模块分出多个通道(不同的地址),经过一个axi_slave模块&am…...
硬件_IMX6ULL的LCD控制器
硬件_IMX6ULL的LCD控制器 文章目录硬件_IMX6ULL的LCD控制器一、 LCD控制器模块介绍1.1 硬件框图1.2 数据传输与处理1.3 时序控制二、 LCD控制器寄存器简介2.1 LCDIF_CTRL寄存器2.2 LCDIF_CTRL1寄存器2.3 LCDIF_TRANSFER_COUNT寄存器2.4 LCDIF_VDCTRL0寄存器2.5 LCDIF_VDCTRL1寄…...
ICLR 2022—你不应该错过的 10 篇论文(下)
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 ICLR 2023已经放榜,但是今天我们先来回顾一下去年的ICLR 2022! ICLR 2022将于2022年 4 月 25 日星期一至 4 月 29 日星期五在线举行(连续第三年!&#x…...
国内外优秀程序员的私域博客大全
文章目录 国内外优秀程序员的私域博客大全**国内的优秀程序员****国外的优秀程序员**结语国内外优秀程序员的私域博客大全 国内的优秀程序员 1、风雪之隅-惠新宸 擅长领域:PHP、PECL等 Laruance惠新宸——国内最有影响力的PHP技术专家,PHP开发组核心成员, Zend顾问, PHP7及…...
【C++ Primer Plus】第六章:分支语句和逻辑运算符
文章目录第六章 分支语句和逻辑运算符6.1 字符函数库cctype6.2 ?:运算符6.3 读取数字的输入6.4 cin的处理过程char类型intdoublechar数组使用char数组来存储输入6.5 写入到文本文件中6.6 读取文本文件6.7 总结第六章 分支语句和逻辑运算符 6.1 字符函数库cctype C从C语言继承…...
堡垒机的主要功能是什么?为什么需要堡垒机?
堡垒机是一种用于管理和控制服务器的工具,其主要功能是为管理人员提供安全、便捷的远程管理和操作方式。为什么需要堡垒机呢?下面我们将详细阐述堡垒机的主要功能和必要性。 一、堡垒机的主要功能: ①、用户认证和授权管理:堡垒机…...
记录spring中Transactional事务注解失效的六个场景
记录spring中Transactional事务注解失效的六个场景 方法内的自调用 原因:通过this内部调用其他带有Transactional注解的方法,是通过this进行调用,并没有通过cglib代理对象进行调用,导致方法未被增强导致无法检测内部事务 解决方…...
【23种设计模式】行为型模式详细介绍(下)
前言 本文为 【23种设计模式】行为型模式 相关内容介绍,下边将对访问者模式,模板模式,策略模式,状态模式,观察者模式,备忘录模式,中介者模式,迭代器模式,解释器模式&…...
dbeaver工具连接达梦数据库
、一 概述 DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发,DBeaver 采用 Eclipse 框架开发,支持插件扩展,并且提供了许多数据库管理工具:ER 图、数据导入/导出、数据库比较、模拟数据生成等࿰…...
比Teambition、Worktile 更适合研发团队的几大工具盘点
Worktile 和 Teambitiom 哪个更好?两个产品各有特点。1.Teambition 优势:操作简单、个人版永不收费、更适合小型团队;2.Teambition 劣势:无法满足中大型团队复杂的项目管理、自定义能力弱、无法与钉钉以外的工具打通等;…...
matlab图像处理常用功能以及函数
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、matlab灰度处理相关二、形态学的一些函数1.腐蚀2.膨胀3.开运算4.闭运算三、其他一些可能会用到的方法1.使用hough进行直线检测2.圆检测3.闭合形状检测4.寻找…...
eBPF 之 ProgramType、AttachType和InputContext
1. ProgramType 定义定义在 include/uapi/linux/bpf.h 文件中,不同 Linux 版本会有变化,以下是 Linux 5.19 版本定义:enum bpf_prog_type {BPF_PROG_TYPE_UNSPEC,BPF_PROG_TYPE_SOCKET_FILTER,BPF_PROG_TYPE_KPROBE,BPF_PROG_TYPE_SCHED_CLS,…...
C++运行时类型识别RTTI
C技能 runtime type identification(RTTI) 运行时类型识别在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。1. 运行时类型转换下面的程序模仿了dynamic_cast<type_id>()类型转化符号,根据每个类的id来判断当前的类型,如果id不匹配…...
idea多时编辑多行-winmac都支持
1背景介绍 idea编辑器非常强大,其中一个功能非常优秀,很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后,可以直接多行编辑。 优点&a…...
BI是报表?BI是可视化?BI到底是什么?
很多企业认为只要买一个前端商业智能BI分析工具就可以解决企业级的商业智能BI所有问题,这个看法实际上也不可行的。可能在最开始分析场景相对简单,对接数据的复杂度不是很高的情况下这类商业智能BI分析工具没有问题。但是在企业的商业智能BI项目建设有一…...
Python基础-数据类型之元组
一、元组的定义 nums (1, 2, 3, 4, 5) 元组是序列的其中一种,每个元素都以逗号分隔,用()包围。 当元组中只有一个元素时,需要在元素后面加逗号分隔,nums (1,),否则括号会被当成运算符 nums (1) print(type(nums…...
大数据面试小抄
项目地址:https://github.com/GTyingzi/BigDATA 该项目是自己在学习大数据过程中整理、总结下来的一份面试小抄。涵盖Hadoop、Spark、Flink、Hive、HBae、Kafka、ES、Zookeeper等。 开源给大家,若感觉不错欢迎star~ 摘取Flink部分如下文章目录FlinkFli…...
Vue:(三十一)Vue封装的过度与动画
上一篇订阅与发布不够过瘾,接着再来一篇,come on!!!作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名写法:过度:元素进入的样式:v-enter&am…...
专门做任务的网站6/百度指数的使用方法
--参考http://www.lanstonwu.com/using-datapump-export-and-import-data/ --参考http://www.cnblogs.com/wbzhao/archive/2012/04/06/2434702.html 一、前期准备 1.以SSH远程登录服务器,找到指定目录下创建数据泵中间文件(.DMP)存放的目录: /*rmdir /ho…...
客户管理系统推荐/谷歌seo引擎优化
在微信公众平台机型服务器配置的时候,下图中的服务必须先在服务端跑起来,后台接口使用java开发。 authenticate控制器接口如下: /*** 验证只接受微信后台的服务请求* 开发者通过检验signature对请求进行校验。* 若确认此次GET请求来…...
遵义网站建设优化公司/互联网行业都有哪些工作
获得微秒级的时间 收藏 Win 下建议如下方式: http://www.vckbase.com/document/viewdoc/?id1301 VC中基于 Windows 的精确定时 中国科学院光电技术研究所 游志宇 在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间&#x…...
app制作网站有哪些 请列举/百度灰色关键词代做
2019独角兽企业重金招聘Python工程师标准>>> 要买新手机了旧手机怎么办?我们可以废物利用下,把旧的手机变成一个远程监控摄像头。这里使用Java创建手机camera客户端和远程服务上的监控界面。 参考原文: Making Android Smart Phon…...
电子商务网站建设开发文档/深圳关键词优化怎么样
本博客记录工程上遇到的常用的却陌生的np用法 1.np.split(分割数组) 1.1 等分数组 In [2]: x np.arange(9)In [3]: x Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])In [8]: np.split(x,3) Out[8]: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7,…...
好的设计师网站有哪些/seo技术网网
对于单页应用,官方提供了vue-router进行路由跳转的处理,本篇主要也是基于其官方文档写作而成。安装基于传统,我更喜欢采用npm包的形式进行安装。npm install vue-router --save当然,官方采用了多种方式进行安装,包括bo…...