后端SpringBoot+前端Vue前后端分离的项目(二)

前言:完成一个列表,实现表头的切换,字段的筛选,排序,分页功能。

目录

一、数据库表的设计

​编辑二、后端实现

环境配置

model层

mapper层

service层

service层单元测试

controller层

三、前端实现

interface接口

接口api层

主体代码

效果展示


一、数据库表的设计

二、后端实现

环境配置

引入mybatis-plus依赖

java 复制代码
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

model层

java 复制代码
package com.mrjj.java.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("merchandise_details")
public class MerchandiseDetails {
    @TableId(type= IdType.AUTO)
    public int id;
    public String salesPlatform;
    public String merchandiseName;
    public int freightCharge;
    public String notes;
}

mapper层

java 复制代码
package com.mrjj.java.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mrjj.java.model.MerchandiseDetails;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MerchandiseDetailsMapper extends BaseMapper<MerchandiseDetails> {
}

service层

MerchandiseDetailsService文件

java 复制代码
package com.mrjj.java.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.mrjj.java.model.MerchandiseDetails;

public interface MerchandiseDetailsService extends IService<MerchandiseDetails> {
}
java 复制代码
package com.mrjj.java.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mrjj.java.mapper.MerchandiseDetailsMapper;
import com.mrjj.java.model.MerchandiseDetails;
import com.mrjj.java.service.MerchandiseDetailsService;
import org.springframework.stereotype.Service;

@Service("MerchandiseDetailsService")
public class MerchandiseDetailsServiceImpl extends ServiceImpl<MerchandiseDetailsMapper, MerchandiseDetails> implements MerchandiseDetailsService {
}

service层单元测试

java 复制代码
package com.mrjj.java.service;

import com.mrjj.java.model.MerchandiseDetails;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@SpringBootTest
@Transactional
public class MerchandiseDetailsServiceTest {
    @Resource
    MerchandiseDetailsService merchandiseDetailsService;

    @Test
    public void getAll() {
        List<MerchandiseDetails> list = merchandiseDetailsService.list();
        System.out.println(list);

    }

    @Test
    public void update() {
        MerchandiseDetails change = new MerchandiseDetails(30, "淘宝", "天堂伞", 16, "质量好");
        merchandiseDetailsService.updateById(change);
    }
}

controller层

java 复制代码
package com.mrjj.java.controller;

import com.mrjj.java.model.MerchandiseDetails;
import com.mrjj.java.model.Result;
import com.mrjj.java.service.MerchandiseDetailsService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/MerchandiseDetails")
public class MerchandiseDetailsController {
    @Resource
    MerchandiseDetailsService merchandiseDetailsService;

    @GetMapping
    public Result<List<MerchandiseDetails>> listMerchandiseDetails() {
        return Result.success(merchandiseDetailsService.list());
    }

    @PutMapping
    public Result updateMerchandiseDetails(@RequestBody MerchandiseDetails merchandiseDetails) {
        boolean result = merchandiseDetailsService.updateById(merchandiseDetails);
        if (result) {
            return Result.success("更新商品详细信息成功!");
        } else {
            return Result.fail(210, "更新商品详细信息失败", merchandiseDetails);
        }

    }
}

三、前端实现

interface接口

javascript 复制代码
export interface MerchandiseDetails {
    id: number;
    salesPlatform: string;
    merchandiseName: string;
    freightCharge: number;
    notes: string;
}

接口api层

javascript 复制代码
import request from '../request'
import axios, { type AxiosPromise } from 'axios'
import type { MerchandiseDetails } from '@/types/merchandises_details/types'
const instance = axios.create({
    baseURL: '/merchandiseDetails',
    timeout: 30000,
    headers: { 'Content-Type': 'application/json;charset=utf-8' }
  })
  export default instance

export function listMerchandiseDetailsApi(): AxiosPromise<MerchandiseDetails[]> {
  return request({
    url: '/merchandiseDetails',
    method: 'get',
  })
}

export function updateMerchandiseDetailsApi(data: MerchandiseDetails) {
  return request({
    url: '/merchandiseDetails',
    method: 'put',
    data: data,
  })
}

主要代码

java 复制代码
<template>
<main>
  <el-dialog title="修改商品名称" v-model="isUpdateName">
    <el-input v-model="changeRow.merchandiseName" size="default" clearable></el-input>
    <template #footer>
      <span>
        <el-button @click="isUpdateName = false">取消</el-button>
        <el-button type="primary" @click="updateMerchandiseName">确认</el-button>
      </span>
    </template>
  </el-dialog>
  <el-row>
    <el-col :span="12" :offset="0"> 
  <el-radio-group v-model="filterType" size="default">
    <el-radio-button label="all">全部</el-radio-button>
    <el-radio-button label="京东" />
    <el-radio-button label="唯品会" />
    <el-radio-button label="淘宝" />
    <el-radio-button label="亚马逊" />
    <el-radio-button label="拼多多" />
    <el-radio-button label="当当" />
    <el-radio-button label="天猫" />
  </el-radio-group>

    </el-col>
    <el-col >
      <el-input
        v-model="searchText"
        placeholder="请输入内容进行搜索"
        size="default"
        clearable
        :suffix-icon="Search"
        ><template #prepend
          ><el-button type="primary" size="default" :icon="Search"></el-button>
        </template>
      </el-input>
    </el-col>
  </el-row>

  <el-table :data="showMerchandiseList" style="width: 50%" height="540" border stripe>
    <el-table-column label="商品名称" fixed prop="merchandiseName" width="200px" />
    <el-table-column label="销售平台" prop="salesPlatform" width="100px" />
    <el-table-column label="邮费" prop="freightCharge" width="100px" />
    <el-table-column label="详细信息" prop="notes" width="200px" />
    <el-table-column label="操作" width="200px">
      <template #default="{ row }">
        <el-button
          type="primary"
          size="default"
          @click="
            isUpdateName = true;
            changeRow = { ...row };
          "
          >修改商品名称</el-button
        ></template
      >
    </el-table-column>
  </el-table>
  <el-pagination
    background
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="[10, 20, 50]"
    layout="total, prev,sizes, pager, next,jumper"
    :total="filterMerchandiseList.length"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />
  </main>
</template>
<script setup lang="ts">
import { MerchandiseName } from '../types/merchandises_details/types'
import { listMerchandiseDetailsApi, updateMerchandiseDetailsApi } from '../api/merchandise_details'
import { computed, onMounted, ref } from 'vue'
import { Search } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
let merchandiseDetailsList = ref<MerchandiseName[]>([])
let filterMerchandiseList = computed(() => {
  let platformMerchandise = merchandiseDetailsList.value
    .filter((key) => {
      return filterType.value === 'all' || key.salesPlatform === filterType.value
    })
    .filter((merchandise) => {
      return (
        merchandise.merchandiseName.indexOf(searchText.value) !== -1 ||
        merchandise.notes.indexOf(searchText.value) !== -1
      )
    })
  return platformMerchandise
})
onMounted(() => {
  ListMerchandiseDetails()
})

const searchText = ref('')
const filterType = ref('all')

let changeRow = ref<MerchandiseName>()
let isUpdateName = ref(false)

let currentPage = ref(1)
let pageSize = ref(10)

let showMerchandiseList = computed(() => {
  let startIndex = (currentPage.value - 1) * pageSize.value
  let endIndex = currentPage.value * pageSize.value - 1
  let index = -1
  let currentPageData = filterMerchandiseList.value.filter((merchandiseName) => {
    index += 1
    return index <= endIndex && index >= startIndex
  })
  return currentPageData
})

function ListMerchandiseDetails() {
  listMerchandiseDetailsApi().then(({ data }) => {
    merchandiseDetailsList.value = data
  })
}
function updateMerchandiseName() {
  // ElMessage.info(JSON.stringify(changeRow.value))
  isUpdateName.value = false
  updateMerchandiseDetailsApi(changeRow.value!).then(({ data }) => {
    ElMessage.success(data)
    ListMerchandiseDetails()
  })
}
function handleSizeChange(size: number) {
  console.log('当前页面大小是:', size)
  pageSize.value = size
}
const handleCurrentChange = (page: number) => {
  console.log('当前的页数是:', page)
  currentPage.value = page
}
</script>

<style scoped>
.el-input{
width: 30%;
}
</style>

效果展示

固定表头,每页展示50条数据,分页功能

搜索功能

过滤+搜索功能

修改商品名称

数据库merchandise_name字段值发生改变

相关推荐
Mintopia10 分钟前
🧠 可定制化 AIGC:Web 用户个性化模型训练的技术门槛正在塌缩!
前端·人工智能·trae
JarvanMo31 分钟前
Flutter CI/CD 完整指南:从 Bitbucket Pipelines 到 Play Store 自动化部署
前端
查老师34 分钟前
就为这一个简单的 Bug,我搭上了整整一个工作日
后端·程序员
JarvanMo38 分钟前
Flutter3.38 带来了什么
前端
倚栏听风雨1 小时前
React中useCallback
前端
不说别的就是很菜1 小时前
【前端面试】前端工程化篇
前端·面试·职场和发展
亿元程序员1 小时前
微信小游戏包体限制4M,一个字体就11.24M,怎么玩?
前端
涔溪1 小时前
vue中预览pdf文件
前端·vue.js·pdf
绝无仅有1 小时前
大厂某里电商平台的面试及技术问题解析
后端·面试·架构
天若有情6731 小时前
从零实现轻量级C++ Web框架:SimpleHttpServer入门指南
开发语言·前端·c++·后端·mvc·web应用