springboot项目实战-销售管理系统-产品管理
发布时间
阅读量:
阅读量
接着前面的内容,贴出代码
数据库
drop table if exists ap_product;
CREATE TABLE `ap_product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(50) DEFAULT NULL COMMENT '产品名称',
`code` varchar(50) DEFAULT NULL COMMENT '产品编码',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`supplier` varchar(200) DEFAULT NULL COMMENT '供应商',
`note` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '备注',
`product_unit` varchar(20) DEFAULT NULL COMMENT '产品单位',
`is_deleted` tinyint default 0 comment '是否删除,0正常,1删除',
PRIMARY KEY (`id`) ) COMMENT='产品表';
insert into ap_product(name,supplier) values ('继电器','广东得利电器');
insert into ap_product(name,supplier) values ('断开器','深圳南山电器');
springboot后端
product.java
package com.shrimpking.pojo;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/** * <p>
* 产品表
* </p>
* * @author shrimpking
* @since 2023-11-20
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("ap_product")
@ApiModel(value="Product对象", description="产品表")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "产品名称")
private String name;
@ApiModelProperty(value = "产品编码")
private String code;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "供应商")
private String supplier;
@ApiModelProperty(value = "备注")
private String note;
@ApiModelProperty(value = "产品单位")
private String productUnit;
@TableLogic
@ApiModelProperty(value = "是否删除,0正常,1删除")
private Integer isDeleted;
}
productmapper.java
package com.shrimpking.mapper;
import com.shrimpking.pojo.Product;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/** * <p>
* 产品表 Mapper 接口
* </p>
* * @author shrimpking
* @since 2023-11-20
*/
public interface ProductMapper extends BaseMapper<Product> {
}
productMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shrimpking.mapper.ProductMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.shrimpking.pojo.Product">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="code" property="code" />
<result column="create_time" property="createTime" />
<result column="supplier" property="supplier" />
<result column="note" property="note" />
<result column="product_unit" property="productUnit" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, code, create_time, supplier, note, product_unit
</sql>
</mapper>
productService.java
package com.shrimpking.service;
import com.shrimpking.pojo.Product;
import com.baomidou.mybatisplus.extension.service.IService;
/** * <p>
* 产品表 服务类
* </p>
* * @author shrimpking
* @since 2023-11-20
*/
public interface ProductService extends IService<Product> {
}
productServiceImpl.java
package com.shrimpking.service.impl;
import com.shrimpking.pojo.Product;
import com.shrimpking.mapper.ProductMapper;
import com.shrimpking.service.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/** * <p>
* 产品表 服务实现类
* </p>
* * @author shrimpking
* @since 2023-11-20
*/
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
}
productController.java
package com.shrimpking.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shrimpking.pojo.Customer;
import com.shrimpking.pojo.Product;
import com.shrimpking.req.CustomerParams;
import com.shrimpking.req.ProductParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/** * <p>
* 产品表 前端控制器
* </p>
* * @author shrimpking
* @since 2023-11-20
*/
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/listPage")
public Result listPage(ProductParams productParams){
IPage<Product> page = new Page<>(productParams.getCurrentPage(), productParams.getPageSize());
LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(productParams.getName()), Product::getName, productParams.getName());
queryWrapper.like(StringUtils.isNotBlank(productParams.getSupplier()),Product::getSupplier,productParams.getSupplier());
IPage<Product> resultPage = this.productService.page(page, queryWrapper);
return Result.success(resultPage);
}
@PostMapping("/save")
public Result save(@RequestBody Product product){
LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Product::getName,product.getName());
int count = this.productService.count(queryWrapper);
if(count > 0){ return Result.fail("此商品已存在");}
boolean save = this.productService.save(product);
if(!save) { return Result.fail("保存失败");}
return Result.success("保存成功");
}
@PostMapping("/update")
public Result update(@RequestBody Product product){
LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Product::getName,product.getName());
Product one = this.productService.getOne(queryWrapper);
if(one != null && !one.getId().equals(product.getId())){
return Result.fail("此商品已存在");
}
boolean update = this.productService.updateById(product);
if(!update){ return Result.fail("更新失败");}
return Result.success("更新成功");
}
@DeleteMapping("/delete/{id}")
public Result delete(@PathVariable("id") Long productId){
if(ObjectUtil.isNull(productId)){
return Result.fail("未选择商品,无法删除");
}
boolean remove = this.productService.removeById(productId);
if(!remove) { return Result.fail("删除失败");}
return Result.success("删除成功");
}
@GetMapping("/list")
public Result list(){
List<Product> list = this.productService.list();
return Result.success(list);
}
}
productPrams.java
package com.shrimpking.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
/** * Created by IntelliJ IDEA.
* * @Author : Shrimpking
* @create 2023/11/21 15:59
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class ProductParams extends QueryParams
{
private String name;
private String supplier;
}
vue前端
router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: '/login',
},
{
path: '/login',
name:'LoginView',
component: ()=> import('@/views/LoginView.vue'),
},
{
path: '/home',
name: 'HomeView',
redirect: '/index',
component: ()=> import('@/views/HomeView.vue'),
children:[
{
path: '/index',
name: 'IndexView',
component: ()=> import('@/views/IndexView.vue'),
meta: {
title: '首页'
}
},
{
path: '/user',
name: 'UserView',
component: ()=> import('@/views/User/UserView.vue'),
meta: {
title: '用户信息'
}
},
{
path: '/customer',
name: 'CustomerView',
component: ()=> import('@/views/Customer/CustomerView.vue'),
meta: {
title: '客户信息'
}
},
{
path: '/follow',
name: 'CustomerFollow',
component: ()=> import('@/views/Customer/CustomerFollow.vue'),
meta: {
title: '客户跟进'
}
},
{
path: '/product',
name: 'ProductView',
component: ()=> import('@/views/Product/ProductView.vue'),
meta: {
title: '产品信息'
}
},
{
path: '/order',
name: 'OrderView',
component: ()=> import('@/views/Order/OrderView.vue'),
meta: {
title: '订单信息'
}
},
{
path: '/orderDetail',
name: 'OrderDetail',
component: ()=> import('@/views/Order/OrderDetail.vue'),
meta: {
title: '订单明细'
}
},
{
path: '/target',
name: 'TargetView',
component: ()=> import('@/views/Target/TargetView.vue'),
meta: {
title: '订单目标'
}
},
{
path: '/todo',
name: 'TodoList',
component: ()=> import('@/views/Todo/TodoList.vue'),
meta: {
title: '待办事项'
}
},
]
}
]
const router = new VueRouter({
routes
})
//路由错误时,解决问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject);
return originalPush.call(this, location).catch(err => err)
};
//白名单
const IGNORE_URLS = ['/login'];
//前置守卫
router.beforeEach((to, from, next) => {
//在白名单中,放行
if(IGNORE_URLS.includes(to.path)){
next();
}
//获取用户
let admin = JSON.parse(window.localStorage.getItem('access-admin'));
if(!admin && !IGNORE_URLS.includes(to.path)){
//没有登录 ,没有在白名单中,跳转登录
return next('/login');
}
next();
});
export default router
product.vue
<template>
<div class="user-area">
<el-card show="always" class="search">
<el-row>
<el-form :inline="true">
<el-form-item>
<el-input
v-model="searchForm.name"
placeholder="输入产品名称搜索"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable></el-input>
</el-form-item>
<el-form-item>
<el-input
v-model="searchForm.supplier"
placeholder="输入供应商搜索"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-toilet-paper" @click="doClean">清空</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-plus" @click="addBtn">新增</el-button>
</el-form-item>
</el-form>
</el-row>
</el-card>
<div class="data-table">
<el-table
:data="tableData"
border
:height="tableHeight"
style="width: 100%">
<el-table-column
prop="id"
label="ID">
</el-table-column>
<el-table-column
prop="name"
label="产品名称"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="code"
label="产品编码"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="supplier"
label="供应商"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="note"
label="备注"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="productUnit"
label="产品单位"
show-overflow-tooltip>
</el-table-column>
<el-table-column label="操作" width="300px;">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="data-page">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="searchForm.currentPage"
:page-sizes="[2, 5, 10, 50]"
:page-size="searchForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<!-- 新增对话框 -->
<div>
<el-dialog
:title="dialogTitle"
:visible.sync="addDialogVisible"
:close-on-click-modal="false"
width="50%"
:before-close="handleClose">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="80px"
label-position="left"
class="demo-ruleForm">
<el-row>
<el-col :span="10" :offset="1">
<el-form-item label="产品名称" prop="name">
<el-input v-model="ruleForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="产品编码" prop="code">
<el-input v-model="ruleForm.code" clearable></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="ruleForm.createTime"
type="date"
style="width: 100%;"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="10" :offset="1">
<el-form-item label="供应商" prop="supplier">
<el-input v-model="ruleForm.supplier" clearable></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="ruleForm.note" clearable></el-input>
</el-form-item>
<el-form-item label="产品单位" prop="productUnit" >
<el-input v-model="ruleForm.productUnit" clearable></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogReset" v-if="dialogTitle==='新增产品'">重 置</el-button>
<el-button type="primary" @click="dialogSubmit">确 定</el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "ProductView",
data(){
return {
//对话框标题
dialogTitle: '',
//对话框可见
addDialogVisible: false,
//搜索区域
searchForm: {
name:'',
supplier:'',
currentPage:1,
pageSize:5,
},
//总记录数
total:0,
//表格数据
tableData:[],
//表格高度
tableHeight:0,
//新增表单
ruleForm: {
name: '',
code: '',
createTime: '',
supplier: '',
note: '',
productUnit: '',
},
rules: {
name: [
{ required: true, message: '请输入产品名称', trigger: 'blur' },
],
code: [
{ required: true, message: '请输入产品编码', trigger: 'blur' },
],
createTime: [
{ required: true, message: '请选择创建时间', trigger: 'change' },
],
supplier: [
{ required: true, message: '请输入供应商', trigger: 'blur' },
],
productUnit: [
{ required: true, message: '请输入产品单位', trigger: 'blur' },
],
}
}
},
methods: {
//删除
handleDelete(row){
this.$confirm(`您确定要删除【${ row.name }】吗?`,'删除提示',{
confirmButtonText:'删除',
cancelButtonText:'取消',
type: 'warning'
}).then(()=>{
request.delete('/product/delete/' + row.id)
.then(res=>{
if(res.code === 200){
this.$message.success(res.msg);
this.doSearch();
}else {
this.$message.error(res.msg);
this.doSearch();
}
});
}).catch(_=>{
this.$message.warning("已取消删除");
})
},
//编辑
handleEdit(row){
//深度拷贝
let obj = JSON.parse(JSON.stringify(row));
this.ruleForm = obj;
this.dialogTitle = '编辑产品';
this.addDialogVisible = true;
},
//新增
addBtn(){
this.ruleForm = {};
this.dialogTitle = '新增产品';
this.addDialogVisible = true;
},
//对话框提交
dialogSubmit(){
this.$refs.ruleForm.validate((valid)=>{
if(valid){
request.post(this.ruleForm.id ? '/product/update':'/product/save',this.ruleForm)
.then(res=>{
if(res.code === 200){
this.$message.success(res.msg);
this.handleClose();
this.doSearch();
}else {
this.$message.error(res.msg);
this.doSearch();
}
})
}
})
},
//对话框重置
dialogReset(){
this.$refs.ruleForm.resetFields();
this.ruleForm = {};
},
//对话框关闭
handleClose(){
this.dialogReset();
this.addDialogVisible = false;
},
//清空
doClean(){
this.searchForm.name = '';
this.searchForm.supplier = '';
this.doSearch();
},
//搜索
doSearch(){
this.searchForm.currentPage = 1;
this.getData();
},
//获取数据
getData(){
request.get("/product/listPage",{
params: this.searchForm
}).then(res=>{
if(res.code === 200){
//console.log(res);
this.tableData = res.data.records;
this.searchForm.currentPage = res.data.current;
this.searchForm.pageSize = res.data.size;
this.total = res.data.total;
}else {
this.$message.error("获取数据失败!");
}
})
},
handleSizeChange(val){
this.searchForm.pageSize = val;
this.searchForm.currentPage = 1;
this.getData();
},
handleCurrentChange(val){
this.searchForm.currentPage = val;
this.getData();
}
},
created(){
//计算表格高度
this.$nextTick(()=>{
this.tableHeight = window.innerHeight - 275;
});
//获取数据
this.getData();
}
}
</script>
<style lang="scss" scoped>
.user-area{
width: 100%;
height: 100%;
margin-top: 15px;
.search{
}
.data-table{
margin-top: 15px;
}
.data-page{
text-align: left;
margin-top: 5px;
}
}
</style>
全部评论 (0)
还没有任何评论哟~
