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 = 0
            tableData.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 = 0
            tableData.push(...res.data.data)
            total.value = res.data.total
            console.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 = 0
    form = 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 = 0
    form = 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)._object
    let 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)._object

    let 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 = val
    page.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 = val
    let 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 = val
    let 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 = 0
                root.datas.push(...res.data.data)
                root.total.value = res.data.total
                root.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 = 0
            root.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.loading
            root.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所用到的内容,有何不懂评论区问答!!!

你可能感兴趣的:(项目,vue.js,javascript,前端)