idea + vue3 + mybatis + springBoot3前后端分离实现对一张表的增删改查(前端,从项目搭建到调用后端所有接口)

项目地址Admin/zwy_manager_up_v1

1.前端项目

1.1项目创建

1.1.1使用cmd创建vue项目

在文件资源管理器中打开你想创建位置路径

npm create vue@latest

选择只选择Route

依次执行以下命令

访问搭建好的vue项目

1.1.2瘦身vue项目

idea打开该项目,项目原始结构如下

瘦身后的项目结构

修改3个文件添加1个文件

名称:App.vue

位置:src/App.vue

<template>
 <RouterView/>
</template>

名称:main.js

位置:src/main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(router)

app.mount('#app')

名称:HelloWorld.vue

位置:src/views/HelloWorld.vue

<template>
  <div>
    <h1>Hello World</h1>
  </div>
</template>
<script setup>

</script>

名称:index.js

位置:src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'hello',
      component: () => import('../views/HelloWorld.vue'),
    },

  ],
})

export default router

1.1.3集成element-plus

下载element-plus依赖

npm install element-plus@ 

package-lock.json或package.json或node_modules查看是否引入

配置element-plus

位置:src/main.js

名称:main.js

 import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
  app.use(ElementPlus)

测试element-plus是否配置好

新建视图

位置:src/views/Button.vue

名称:Button.vue

<template>
  <div>
    <el-button type="primary" @click="handleClick">按钮</el-button>
  </div>
</template>
<script setup>

</script>

添加路由

位置:src/router/index.js

名称:index.js

    {
      path: '/button',
      name: 'button',
      component: () => import('../views/Button.vue'),
    }

访问该视图

1.2视图搭建

一共有4个,404.vue,manager.vue,employeeOp.vue,home.vue

其中manager.vue(employeeOp.vue,home.vue) 是嵌套关系

404.vue是路由守卫

1.2.1 全局映入icon

位置:src/main.js

名称:main.js

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        app.component(key, component)
    }

1.2.2导入所需要的图片和样式

位置:src/assets/global.css

名称:global.css


.card {

    margin-top: 20px;
    margin-left: 10px;
    padding: 10px;
    width: calc(100% - 40px);
    background-color: #ffffff;
    border: 1px solid #e4e7ed;
    border-radius: 4px;
    color: #303133;

}

位置:src/assets/img.png

名称:img.png

位置:/assets/404.png

名称:404.png

1.2.3视图文件编写

位置:src/view/employeeDataOp.vue

名称:employeeDataOp.vue

<template>
  <div >
<!--    第一项 搜索框和重置按钮-->
    <div class="card">
      <el-input v-model="searchName" placeholder="请输入员工姓名" style="width: 200px;margin-right: 5px;" suffix-icon="Search"/>
      <el-button type="primary">搜索</el-button>
      <el-button type="warning">重置</el-button>
    </div>

<!--    第二项 常用操作 批量删除 添加员工-->
    <div class="card">
      <el-button type="primary">新建员工</el-button>
      <el-button type="danger">批量删除</el-button>
    </div>

<!--    第三项 员工数据表格-->
    <div class="card">
     <el-table :data = "data.tableData" height="400" style="width: 100%;border: #7a7575 solid 1px">
       <el-table-column prop="id" label="编号" />
       <el-table-column prop="name" label="姓名" />
       <el-table-column prop="gender" label="性别" />
       <el-table-column prop="title" label="职位" />
       <el-table-column prop="birthday" label="出生日期"/>

     </el-table>
    </div>

<!--    第四项 分页组件-->
    <div class="card">
      <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="400"

      />
    </div>
  </div>
</template>
<script setup>

import {reactive} from "vue";

const data =  reactive({
  tableData: [
    {
      id:1,
      name:'张三',
      gender:'男',
      title:'高级工程师',
      birthday:'1985-01-01'
    },

  ],


})
</script>

位置:src/veiws/home.vue

名称:home.vue

<template>
  <div>
    员工管理系统首页
  </div>
</template>
<script setup>

</script>

位置:src/veiws/manager.vue

名称:manager.vue

<template>
  <div>
<!--    顶部信息栏(logo 系统名 用户头像 用户名)开始 -->
    <div style="height: 40px;background-color: aqua;display:flex;align-items:center;
">
      <img src="../assets/img.png" style="width: 40px;margin-left: 20px">
      <span style="margin-left: 10px;font-size: 20px;font-family: 新宋体;color: white">员工管理系统</span>
      <div style="flex:1"></div>

      <el-avatar  src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"/>
      <span style="margin-left: 10px;margin-right:10px;font-size: 20px;font-family: 新宋体;color: white">泳</span>

    </div>
    <!--    顶部信息栏(logo 系统名 用户头像 用户名)结束 -->

<!--    body部分开始-->
    <div style="display: flex">
<!--    左边导航栏开始-->
      <div style="width: 140px;height: calc(100vh - 40px);border-right: #cdcdcd solid 1px">
        <el-menu
            router>
          <el-menu-item index="/manager/home" >
            <el-icon>
              <HomeFilled />
            </el-icon>
              <span>首页</span>
          </el-menu-item>
          <el-menu-item index="/manager/employeeDataOp">
            <el-icon><User /></el-icon>
              <span>员工管理</span>
          </el-menu-item>
        </el-menu>

      </div>
<!--    左边导航栏结束-->

<!--    右边数据域开始-->
      <div style="width: calc(100% - 140px)">
        <RouterView/>
      </div>
<!--    右边数据域结束-->
    </div>
<!--    body部分结束-->





  </div>
</template>
<script setup>

</script>

位置:src/view/404.vue

名称:404.vue


<template>

    <div class="card" style="display:flex;align-items:center;">
      <img src="@/assets/404.png" style="width: 100%;">
      </div>
  <div style="margin-top: 20px;">
    <div style="text-align: center;">
      <el-button type="primary" @click="backLatestPage">返回上一页</el-button>
    </div>
  </div>


</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const backLatestPage = () => {
  router.go(-1)
}

</script>

1.2.4路由修改

位置:src/router/index.js

名称:index.js

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'hello',
      component: () => import('../views/HelloWorld.vue'),
    },
    {
      path: '/button',
      name: 'button',
      component: () => import('../views/Button.vue'),
    },
    {
      path:'/manager',
      name:'manager',
      component:()=>import('../views/Manager.vue'),
      children:[
        {
          path:'/manager/employeeDataOp',
          name:'employeeDataOp',
          meta:{title:'员工数据操作'},
          component:()=>import('../views/employeeDataOp.vue')
        },
          {
            path:'/manager/home',
            name:'home',
            meta:{title:'首页'},
            component:()=>import('../views/home.vue')
          }
      ]
    },
    {
      path:'/404',
      name:'404',
      meta:{title:'404'},
      component:()=>import('../views/404.vue')

    },
    {
      path:'/:pathMatch(.*)*',
      redirect:'/404',

    }

  ],
})
router.beforeEach((to,from,next)=>{
    document.title=to.meta.title;
    next()
})

export default router

1.2.4静态界面展示

1.3接口调用

1.3.1安装axios(发请求的工具)

 npm install axios@latest

1.3.2编写request.js文件(处理请求)

位置:src/utils/request.js

const request  =  axios.create({
    baseURL:'http://localhost:9999',//后台接口地址
    timeout:5000 //请求超时设置
})

//request 拦截器
// 可以自请求发送前对请求做一些处理
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    return config
},error => {
    return Promise.reject(error)

});
//可以在接口响应后统一处理结果
request.interceptors.response.use(
    response =>{
        let res = response.data;
    //     兼容服务器端返回的字符串数据
        if(typeof res === 'string') {
            res = res ?   JSON.parse(res) : res
        }
        return res;
    },
    error => {
        if(error.response.status === 404){
            ElMessage.error('服务器未找到该接口')
        }else if(error.response.status === 500){
            ElMessage.error('服务器内部错误')
        }else{
            console.error(error.message)
        }
        return Promise.reject(error)
    }
)
export default request

1.3.3修改employeeDataOp.vue

位置:src/views/employeeDataOp.vue

<template>
  <div >
<!--    第一项 搜索框和重置按钮-->
    <div class="card">
      <el-input v-model="data.searchName" placeholder="请输入员工姓名" style="width: 200px;margin-right: 5px;" suffix-icon="Search"/>
      <el-button type="primary" @click="loadData()">搜索</el-button>
      <el-button type="warning" @click="reset()">重置</el-button>
    </div>

<!--    第二项 常用操作 批量删除 添加员工-->
    <div class="card">
      <el-button type="primary" @click="switchAddDialog">新建员工</el-button>
      <el-button type="danger" @click="deleteBatchMessageBox">批量删除</el-button>
    </div>

<!--    第三项 员工数据表格-->
    <div class="card">
     <el-table @selectionChange="handleSelectionChange" :data = "data.tableData" height="400" style="width: 100%;border: #7a7575 solid 1px">
       <el-table-column type="selection" width="55" />
       <el-table-column prop="id" label="编号" />
       <el-table-column prop="name" label="姓名" />
       <el-table-column prop="gender" label="性别" />
       <el-table-column prop="title" label="职位" />
       <el-table-column prop="birthday" label="出生日期"/>
       <el-table-column fixed="right" label="操作" width="120">
         <template #default="scope">
           <el-button  type="primary"  @click="editRow(scope.row)" circle>
             <el-icon><Edit /></el-icon>
           </el-button>
           <el-button  type="danger" @click="deleteMessageBox(scope.row)" circle>
             <el-icon><Delete /></el-icon>
           </el-button>
         </template>
       </el-table-column>

     </el-table>
    </div>

<!--    第四项 分页组件-->
    <div class="card">
      <el-pagination

          v-model:current-page="data.currentPage"
          v-model:page-size="data.pageSize"
          @current-change="loadData"
          @size-change="loadData"
          :page-sizes="[10, 20, 50, 100]"

          layout="total, sizes, prev, pager, next, jumper"
          v-model:total="data.total"

      />
    </div>
    <el-dialog
        v-model="data.AddDialogVisible"
        title="新建员工"
        width="300"
        align-center
    >
      <el-input v-model="data.employee.name" style="width: 240px;margin-bottom: 20px;" placeholder="请输入名称"></el-input>
      <el-radio-group v-model="data.employee.gender" style="width: 240px;margin-bottom: 20px;">
        <el-radio value="男" size="large" border>男</el-radio>
        <el-radio value="女" size="large" border>女</el-radio>
      </el-radio-group>
      <el-input v-model="data.employee.title" style="width: 240px;margin-bottom: 20px;" placeholder="请输入职称"></el-input>


        <el-date-picker
            v-model="data.employee.birthday"
            type="date"
            placeholder="选择出生日期"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"

        />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="switchAddDialog">取消</el-button>
          <el-button type="primary" @click="save()">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>

import {reactive,ref} from "vue";
import request from "@/utils/request.js";

import {ElMessage,ElMessageBox} from "element-plus";

const res = ref();
const data =  reactive({
  AddDialogVisible:false,
  tableData: [
  ],
  currentPage:1,
  pageSize:5,
  searchName:'',
  employee:{
    id:0,
    name:'',
    gender:'',
    title:'',
    birthday:''
  },
  ids:[]

})
const loadData = () => {


  const loadAll = () =>{

        request.get('employee/selectPage', {
          params: {
            pageNum: data.currentPage,
            pageSize: data.pageSize,
          }
        }).then(res=> {
          data.tableData = res.data.list;
          data.total = res.data.total;

          console.log(res.data.list)
        })
      }
      const loadByName = () =>{
        request.post('employee/findByName',{
            name:data.searchName,
        },{  params: {
                pageNum: data.currentPage,
                pageSize: data.pageSize,
              }}).then(res=>{
          data.tableData = res.data.list;
          data.total = res.data.total;
          console.log(res.data.list)
        })
        }
  data.searchName ? loadByName() :loadAll()
}
loadData();
const reset = () =>{
  data.searchName = '';
  loadData();
}
const switchAddDialog = () =>{
  data.AddDialogVisible = data.AddDialogVisible ? false : true;
}
const editRow = (row) =>{
  data.employee = row;
  switchAddDialog();
  //深拷贝,解决就算取消修改,数据还是被修改了的问题
  data.employee = JSON.parse(JSON.stringify(row));

}
const save = () =>{
  const update = () =>{
    request.put('employee/modify',data.employee).then(res=>{
      console.log(res);
      if(res.code === '200'){
        ElMessage.success('添加成功');
        loadData();
        switchAddDialog();
      }else {
        ElMessage.error(res.code + '/n' + res.msg);
      }
    })
  }
  const add = () =>{
    request.post('employee/add',data.employee).then(res=>{
      console.log(res);
      if(res.code === '200'){
        ElMessage.success('添加成功');
        loadData();
        switchAddDialog();
      }else {
        ElMessage.error(res.code + '/n' + res.msg);
      }
    })
  }
  data.employee.id != 0 ? update() : add();
}
const deleteOne = (row) =>{
  request.delete(`employee/deleteById/${row.id}`).then(res=>{
    if(res.code === '200'){
      ElMessage.success('删除成功');
      loadData();
    }else {
      ElMessage.error(res.code + '/n' + res.msg);
    }
  })
}
const handleSelectionChange = (rows) =>{
  data.ids = rows.map(row => row.id);
  console.log(data.ids);
}
const deleteBatch = () =>{
  request.delete(`employee/deleteBatch`,{data:data.ids}).then(res=>{
    if(res.code === '200'){
      ElMessage.success('批量删除成功');
      loadData();
    }else {
      ElMessage.error(res.code + '/n' + res.msg);
    }

  })
}
const deleteMessageBox = (row) =>{
  ElMessageBox.confirm('此操作将永久删除该信息, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'danger',
  }).then(() => {
    deleteOne(row);
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除',
    });
  });
}
const deleteBatchMessageBox = () =>{
  if(data.ids.length === 0){
    ElMessage.error('请选择要删除的数据');
    return;
  }
  ElMessageBox.confirm('此操作将永久删除该信息, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'danger',
  }).then(() => {
    deleteBatch();
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除',
    });
  });
}
</script>

我来解释也哈这个视图,

静态内容方面

分为四个部分对应代码四个<div>

第一个是搜索框

第二个是一些基础操作

第三个是表格

第四个是分页组件

还有一个对话框作用是添加或修改员工信息点击新建按钮这个对话框显示对应代码<el_dialog>标签

还有一个消息框当,进行删除操作时候提供一个缓冲,以免误删对应const deleteMassageBox,deleteBatchMassageBox.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值