前端vue+后端springboot+mybatisplus(仓库管理系统完整版)

112 篇文章 0 订阅
40 篇文章 0 订阅

新建项目

新建springboot项目,内建vue模块

 

 

 mysql数据库

drop table if exists d_user;
create table d_user(
	id int auto_increment primary key comment '主键',
	user_no varchar(20) not null comment '账号',
	user_name varchar(100) not null comment '名字',
	password varchar(30) not null comment '密码',
	age int null comment '年龄',
	sex int null comment '性别,1男,2女',
	phone varchar(30) null comment '电话',
	role_id int not null comment '角色id,0超级管理员,1管理员,2用户',
	is_valid varchar(4) default 'Y' null comment '是否有效,Y有效,N无效' 
) comment '用户表';

insert into d_user(user_no,user_name,password,age,sex,phone,role_id) 
values ('sa','超级管理员','1234',99,1,'13312345678',0); 
insert into d_user(user_no,user_name,password,age,sex,phone,role_id) 
values ('admin','管理员','1234',88,1,'13412345678',1); 
insert into d_user(user_no,user_name,password,age,sex,phone,role_id) 
values ('user1','用户1','1234',18,2,'13512345678',2); 

drop table if exists d_menu;
create table d_menu(
	id int(11) not null primary key comment 'ID',
	menu_code varchar(8) default null comment '菜单编码',
	menu_name varchar(20) default null comment '菜单名字',
	menu_level varchar(2) default null comment '菜单级别',
	menu_parentcode varchar(8) default null comment '菜单的父级code',
	menu_index varchar(20) default null comment '菜单点击的触发函数',
	menu_right varchar(8) default null comment '权限,0超级管理员,1管理员,2用户,可以使用逗号组合',
	menu_component varchar(200) default null comment '组件名称',
	menu_icon varchar(100) default null comment '菜单图标'
) comment '菜单表';

insert into d_menu values(1,'001','管理员管理','1',null,'Admin','0','Admin.vue','el-icon-s-custom');
insert into d_menu values(2,'002','用户管理','1',null,'User','0,1','User.vue','el-icon-user-solid');
insert into d_menu values(3,'003','仓库管理','1',null,'Storage','0,1','Storage.vue','el-icon-s-cooperation');
insert into d_menu values(4,'004','商品分类管理','1',null,'GoodsType','0,1','GoodsType.vue','el-icon-s-help');
insert into d_menu values(5,'005','商品管理','1',null,'Goods','0,1,2','Goods.vue','el-icon-s-marketing');
insert into d_menu values(6,'006','出入库管理','1',null,'Record','0,1,2','Record.vue','el-icon-s-platform');

drop table if exists d_storage;
create table d_storage(
	id int(11) not null auto_increment primary key comment 'ID',
	storage_name varchar(100) not null comment '仓库名称',
	remark varchar(1000) default null comment '备注'
) comment '仓库表';

insert into d_storage values (null,'食品库','存放食品的');
insert into d_storage values (null,'枪械库','存放枪支的');
insert into d_storage values (null,'服装库','存放服装的');
insert into d_storage values (null,'鞋品库','存放鞋类的');

drop table if exists d_goodsType;
create table d_goodsType(
	id int(11) not null auto_increment primary key comment 'ID',
	type_name varchar(100) not null comment '商品分类名称',
	remark varchar(1000) default null comment '备注'
) comment '商品分类';

insert into d_goodsType values(null,'长裤','');
insert into d_goodsType values(null,'上衣','');
insert into d_goodsType values(null,'风衣','');
insert into d_goodsType values(null,'连衣裙','');
insert into d_goodsType values(null,'短裙','');
insert into d_goodsType values(null,'百褶裙','');
insert into d_goodsType values(null,'石榴裙','');
insert into d_goodsType values(null,'手枪','');
insert into d_goodsType values(null,'步枪','');

drop table if exists d_goods;
create table d_goods(
	id int(11) not null auto_increment primary key comment 'ID',
	goods_name varchar(100) not null comment '商品名',
	storage_id int(11) not null comment '仓库id',
	goods_type int(11) not null comment '分类名id',
	count int(11) not null comment '数量',
	remark varchar(1000) default null comment '备注'
) comment '商品表';


insert into d_goods(goods_name,storage_id,goods_type,count) values('爱马仕包包',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('酷奇手包',1,1,5);
insert into d_goods(goods_name,storage_id,goods_type,count) values('弹力裤',2,2,100);
insert into d_goods(goods_name,storage_id,goods_type,count) values('碎花百褶裙',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('爱马仕',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('爱包包',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('仕包包',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('仕包',1,1,10);
insert into d_goods(goods_name,storage_id,goods_type,count) values('爱包',1,1,10);

drop table if exists d_record;
create table d_record(
	id int(11) not null auto_increment primary key comment '主键',
	goods int(11) not null comment '商品id',
	user_id int(11) default null comment '取货人,补货人',
	admin_id int(11) default null comment '操作人',
	count int(11) not null comment '数量',
	create_time datetime default CURRENT_TIMESTAMP comment '操作时间',
	remark varchar(1000) default null comment '备注'
) comment '出入库记录表';

insert into d_record(goods,user_id,admin_id,count) values(1,3,1,10);
insert into d_record(goods,user_id,admin_id,count) values(1,3,1,-10);
insert into d_record(goods,user_id,admin_id,count) values(1,3,1,20);

springboot后端

配置文件

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.shrimpking</groupId>
    <artifactId>msy-storage-app02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>msy-storage-app02</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>spring-boot-starter-swagger</artifactId>
            <version>1.5.1.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

server.port=8089
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=UTC
spring.datasource.username=root
spring.datasource.password=mysql123
#默认日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.type-aliases-package=com.shrimpking.pojo

实体类

user.java

package com.shrimpking.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 用户表
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-10
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "账号")
    private String userNo;

    @ApiModelProperty(value = "名字")
    private String userName;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "性别,1男,2女")
    private Integer sex;

    @ApiModelProperty(value = "电话")
    private String phone;

    @ApiModelProperty(value = "角色id,0超级管理员,1管理员,2用户")
    private Integer roleId;

    @ApiModelProperty(value = "是否有效,Y有效,N无效")
    private String isValid;


}

storage.java

package com.shrimpking.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 仓库表
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_storage")
@ApiModel(value="Storage对象", description="仓库表")
public class Storage implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "仓库名称")
    private String storageName;

    @ApiModelProperty(value = "备注")
    private String remark;


}

recordres.java

package com.shrimpking.pojo;

import lombok.Data;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/8/12 21:03
 * record连表查询返回结果集
 */
@Data
public class RecordRes extends Record
{
    private String userName;
    private String adminName;
    private String goodsName;
    private String storageName;
    private String typeName;
}

record.java

package com.shrimpking.pojo;

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 io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 出入库记录表
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_record")
@ApiModel(value="Record对象", description="出入库记录表")
public class Record implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "商品id")
    private Integer goods;

    @ApiModelProperty(value = "取货人,补货人")
    private Integer userId;

    @ApiModelProperty(value = "操作人")
    private Integer adminId;

    @ApiModelProperty(value = "数量")
    private Integer count;

    @ApiModelProperty(value = "操作时间")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "备注")
    private String remark;


}

menu.java

package com.shrimpking.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 菜单表
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-11
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_menu")
@ApiModel(value="Menu对象", description="菜单表")
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "ID")
    private Integer id;

    @ApiModelProperty(value = "菜单编码")
    private String menuCode;

    @ApiModelProperty(value = "菜单名字")
    private String menuName;

    @ApiModelProperty(value = "菜单级别")
    private String menuLevel;

    @ApiModelProperty(value = "菜单的父级code")
    private String menuParentcode;

    @ApiModelProperty(value = "菜单点击的触发函数")
    private String menuIndex;

    @ApiModelProperty(value = "权限,0超级管理员,1管理员,2用户,可以使用逗号组合")
    private String menuRight;

    @ApiModelProperty(value = "组件名称")
    private String menuComponent;

    @ApiModelProperty(value = "菜单图标")
    private String menuIcon;


}

goodsType.java

package com.shrimpking.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 商品分类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_goodstype")
@ApiModel(value="Goodstype对象", description="商品分类")
public class Goodstype implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "商品分类名称")
    private String typeName;

    @ApiModelProperty(value = "备注")
    private String remark;


}

goods.java

package com.shrimpking.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 商品表
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("d_goods")
@ApiModel(value="Goods对象", description="商品表")
public class Goods implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "商品名")
    private String goodsName;

    @ApiModelProperty(value = "仓库id")
    private Integer storageId;

    @ApiModelProperty(value = "分类名id")
    private Integer goodsType;

    @ApiModelProperty(value = "数量")
    private Integer count;

    @ApiModelProperty(value = "备注")
    private String remark;


}

mapper接口层

usermapper.java

package com.shrimpking.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * <p>
 * 用户表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-10
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {

    IPage pageC(IPage<User> page);

    IPage pageC2(IPage<User> page, @Param(Constants.WRAPPER) Wrapper wrapper);

}

storagemapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Storage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 仓库表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Mapper
public interface StorageMapper extends BaseMapper<Storage> {

}

recordmapper.java

package com.shrimpking.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.shrimpking.pojo.Record;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * <p>
 * 出入库记录表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Mapper
public interface RecordMapper extends BaseMapper<Record> {

    IPage pageC(IPage<Record> page,@Param(Constants.WRAPPER) Wrapper wrapper);
}

menumapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Menu;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 菜单表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-11
 */
@Mapper
public interface MenuMapper extends BaseMapper<Menu> {

}

goodstypemapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Goodstype;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 商品分类 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Mapper
public interface GoodstypeMapper extends BaseMapper<Goodstype> {

}

goodsmapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Goods;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 商品表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Mapper
public interface GoodsMapper extends BaseMapper<Goods> {

}

mapperXML

usermapper.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.UserMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.User">
        <id column="id" property="id" />
        <result column="user_no" property="userNo" />
        <result column="user_name" property="userName" />
        <result column="password" property="password" />
        <result column="age" property="age" />
        <result column="sex" property="sex" />
        <result column="phone" property="phone" />
        <result column="role_id" property="roleId" />
        <result column="is_valid" property="isValid" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, user_no, user_name, password, age, sex, phone, role_id, is_valid
    </sql>

    <select id="pageC" resultType="user">
        select * from d_user
    </select>

    <select id="pageC2" resultType="user">
        select * from d_user ${ew.customSqlSegment}
    </select>
</mapper>

storagemapper.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.StorageMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Storage">
        <id column="id" property="id" />
        <result column="storage_name" property="storageName" />
        <result column="remark" property="remark" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, storage_name, remark
    </sql>

</mapper>

recordmapper.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.RecordMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Record">
        <id column="id" property="id" />
        <result column="goods" property="goods" />
        <result column="user_id" property="userId" />
        <result column="admin_id" property="adminId" />
        <result column="count" property="count" />
        <result column="create_time" property="createTime" />
        <result column="remark" property="remark" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, goods, user_id, admin_id, count, create_time, remark
    </sql>

    <select id="pageC" resultType="recordRes">
        select
        a.*,
        b.goods_name as goodsName,
        c.storage_name as storageName,
        d.type_name as typeName,
        (select u.user_name from d_user u where u.id=a.user_id) userName,
        (select u.user_name from d_user u where u.id=a.admin_id) adminName
        from
        d_record a,
        d_goods b,
        d_storage c,
        d_goodstype d
        ${ew.customSqlSegment}
    </select>

</mapper>

menumapper.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.MenuMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Menu">
        <id column="id" property="id" />
        <result column="menu_code" property="menuCode" />
        <result column="menu_name" property="menuName" />
        <result column="menu_level" property="menuLevel" />
        <result column="menu_parentcode" property="menuParentcode" />
        <result column="menu_index" property="menuIndex" />
        <result column="menu_right" property="menuRight" />
        <result column="menu_component" property="menuComponent" />
        <result column="menu_icon" property="menuIcon" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, menu_code, menu_name, menu_level, menu_parentcode, menu_index, menu_right, menu_component, menu_icon
    </sql>

</mapper>

goodstypemapper.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.GoodstypeMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Goodstype">
        <id column="id" property="id" />
        <result column="type_name" property="typeName" />
        <result column="remark" property="remark" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, type_name, remark
    </sql>

</mapper>

goodsmapper.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.GoodsMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Goods">
        <id column="id" property="id" />
        <result column="goods_name" property="goodsName" />
        <result column="sotrage_id" property="sotrageId" />
        <result column="goods_type" property="goodsType" />
        <result column="count" property="count" />
        <result column="remark" property="remark" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, goods_name, sotrage_id, goods_type, count, remark
    </sql>

</mapper>

service层

userservice.java

package com.shrimpking.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 用户表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-10
 */
public interface UserService extends IService<User> {

    IPage pageC(IPage<User> page);

    IPage pageC2(IPage<User> page, Wrapper wrapper);
}

storageService.java

package com.shrimpking.service;

import com.shrimpking.pojo.Storage;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 仓库表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
public interface StorageService extends IService<Storage> {

}

recordservice.java

package com.shrimpking.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Record;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 出入库记录表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
public interface RecordService extends IService<Record> {

    IPage pageC(IPage<Record> page, Wrapper wrapper);
}

menuService.java

package com.shrimpking.service;

import com.shrimpking.pojo.Menu;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 菜单表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-11
 */
public interface MenuService extends IService<Menu> {

}

goodstypeService.java

package com.shrimpking.service;

import com.shrimpking.pojo.Goodstype;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 商品分类 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
public interface GoodstypeService extends IService<Goodstype> {

}

goodsService.java

package com.shrimpking.service;

import com.shrimpking.pojo.Goods;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 商品表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
public interface GoodsService extends IService<Goods> {

}

serviceImpl

userServiceImpl.java

package com.shrimpking.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.User;
import com.shrimpking.mapper.UserMapper;
import com.shrimpking.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-10
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public IPage pageC(IPage<User> page)
    {
        return userMapper.pageC(page);
    }

    @Override
    public IPage pageC2(IPage<User> page, Wrapper wrapper)
    {
        return userMapper.pageC2(page,wrapper);

    }
}

storageserviceImpl.java

package com.shrimpking.service.impl;

import com.shrimpking.pojo.Storage;
import com.shrimpking.mapper.StorageMapper;
import com.shrimpking.service.StorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 仓库表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Service
public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> implements StorageService {

}

recordServiceImpl.java

package com.shrimpking.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Record;
import com.shrimpking.mapper.RecordMapper;
import com.shrimpking.service.RecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 出入库记录表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Service
public class RecordServiceImpl extends ServiceImpl<RecordMapper, Record> implements RecordService {

    @Autowired
    private RecordMapper recordMapper;

    @Override
    public IPage pageC(IPage<Record> page, Wrapper wrapper)
    {
        return recordMapper.pageC(page,wrapper);
    }
}

menuServiceImpl.java

package com.shrimpking.service.impl;

import com.shrimpking.pojo.Menu;
import com.shrimpking.mapper.MenuMapper;
import com.shrimpking.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-11
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

}

goodsTypeServiceImpl.java

package com.shrimpking.service.impl;

import com.shrimpking.pojo.Goodstype;
import com.shrimpking.mapper.GoodstypeMapper;
import com.shrimpking.service.GoodstypeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 商品分类 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Service
public class GoodstypeServiceImpl extends ServiceImpl<GoodstypeMapper, Goodstype> implements GoodstypeService {

}

goodsServiceImpl.java

package com.shrimpking.service.impl;

import com.shrimpking.pojo.Goods;
import com.shrimpking.mapper.GoodsMapper;
import com.shrimpking.service.GoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {

}

controller层

usercontroller.java

package com.shrimpking.controller;


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.common.QueryPageParam;
import com.shrimpking.common.Result;
import com.shrimpking.pojo.User;
import com.shrimpking.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-10
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    //新增
    @PostMapping("/save")
    public Result save(@RequestBody User user)
    {
        return userService.save(user) ? Result.success(): Result.fail();
    }

    //修改
    @PostMapping("/update")
    public Result update(@RequestBody User user)
    {
        return userService.updateById(user) ? Result.success() : Result.fail();
    }

    //新增或修改
    @PostMapping("/saveOrUpdate")
    public boolean saveOrUpdate(@RequestBody User user){
        return userService.saveOrUpdate(user);
    }

    //删除
    @GetMapping("/delete")
    public Result delete(@RequestParam String id)
    {
        return userService.removeById(id) ? Result.success(): Result.fail();
    }


    //根据账号,查询唯一
    @GetMapping("/findByUserNo")
    public Result findByUserNo(@RequestParam String userNo)
    {
        System.out.println(userNo);
        List<User> list = userService.lambdaQuery().eq(User::getUserNo, userNo).list();
        return list.size() > 0 ? Result.success(list) : Result.fail();
    }

    //
    @GetMapping("/list")
    public Result getList()
    {
        List<User> list = userService.list();
        return Result.success(list,(long)list.size());
    }

    //查询,模糊查询
    @PostMapping("/listP")
    public Result listP(@RequestBody  User user)
    {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(user.getUserName()))
        {
            lambdaQueryWrapper.like(User::getUserName,user.getUserName());
            //lambdaQueryWrapper.eq(User::getUserName,user.getUserName());
        }
        return Result.success(userService.list(lambdaQueryWrapper));
    }

    //入参封装
    @PostMapping("/listP2")
    public List<User> listP2(@RequestBody QueryPageParam query)
    {
        System.out.println(query);
        System.out.println("pageSize=" + query.getPageSize());
        System.out.println("pageNum = " + query.getPageNum());
        HashMap param = query.getParam();
        System.out.println(param.get("name"));

        return  null;
    }

    //使用mybatis默认分页类
    @PostMapping("/listPage")
    public Result listPage(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<User> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //System.out.println(query);
        String name = (String) query.getParam().get("name");
        String sex = (String) query.getParam().get("sex");
        String roleId = (String) query.getParam().get("roleId");

        if(StringUtils.isNotBlank(name) && !"null".equals(name))
        {
            wrapper.like(User::getUserName,name);
        }
        if(StringUtils.isNotBlank(sex))
        {
            wrapper.eq(User::getSex,sex);

        }
        if(StringUtils.isNotBlank(roleId))
        {
            wrapper.eq(User::getRoleId,roleId);
        }
        //获取分页结果
        IPage result = userService.page(page,wrapper);
        //System.out.println(result.getTotal());
        return Result.success(result.getRecords(),result.getTotal());
    }

    //自定义sql的分页实现
    @PostMapping("/listPage2")
    public List listPage2(@RequestBody QueryPageParam query)
    {
        Page<User> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());

        IPage result = userService.pageC(page);
        return result.getRecords();
    }

    //自定义sql的分页实现,可以有sql条件
    @PostMapping("/listPage3")
    public List listPage3(@RequestBody QueryPageParam query)
    {
        Page<User> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(User::getUserName,query.getParam().get("name"));

        IPage result = userService.pageC2(page,wrapper);

        return result.getRecords();
    }


    @PostMapping("/listPage4")
    public Result listPage4(@RequestBody QueryPageParam query)
    {
        Page<User> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(User::getUserName,query.getParam().get("name"));

        IPage res = userService.page(page,wrapper);
        return Result.success(res.getRecords(),res.getTotal());

    }

    //登录
    @PostMapping("/login")
    public Result login(@RequestBody User user)
    {
        List<User> list = userService.lambdaQuery().eq(User::getUserNo, user.getUserNo())
                .eq(User::getPassword, user.getPassword()).list();

        return list.size() > 0 ? Result.success(list.get(0)) : Result.fail();
    }

}

storageController.java

package com.shrimpking.controller;


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.common.QueryPageParam;
import com.shrimpking.common.Result;
import com.shrimpking.pojo.Storage;
import com.shrimpking.pojo.User;
import com.shrimpking.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 仓库表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@RestController
@RequestMapping("/storage")
public class StorageController {

    @Autowired
    private StorageService storageService;

    //增加
    @PostMapping("/save")
    public Result save(@RequestBody Storage storage)
    {
        return storageService.save(storage) ? Result.success() : Result.fail();
    }

    //更新
    @PostMapping("/update")
    public Result update(@RequestBody Storage storage)
    {
        return storageService.updateById(storage) ? Result.success() : Result.fail();
    }

    //删除
    @GetMapping("/delete")
    public Result delete(@RequestParam String id)
    {
        return storageService.removeById(id) ? Result.success() : Result.fail();
    }

    //使用mybatis默认分页类
    @PostMapping("/listPage")
    public Result listPage(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<Storage> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        LambdaQueryWrapper<Storage> wrapper = new LambdaQueryWrapper<>();
        String name = (String) query.getParam().get("name");

        if(StringUtils.isNotBlank(name) && !"null".equals(name))
        {
            wrapper.like(Storage::getStorageName,name);
        }
        //获取分页结果
        IPage result = storageService.page(page, wrapper);
        return Result.success(result.getRecords(),result.getTotal());
    }

    //根据仓库名,查询唯一
    @GetMapping("/findByName")
    public Result findByName(@RequestParam String name)
    {
        List<Storage> list = storageService.lambdaQuery().eq(Storage::getStorageName, name).list();
        return list.size() > 0 ? Result.success(list) : Result.fail();
    }

    @GetMapping("/list")
    public Result getList()
    {
        List<Storage> list = storageService.list();
        return Result.success(list,(long)list.size());
    }
}


recordController.java

package com.shrimpking.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.common.QueryPageParam;
import com.shrimpking.common.Result;
import com.shrimpking.pojo.Goods;
import com.shrimpking.pojo.Record;
import com.shrimpking.pojo.User;
import com.shrimpking.service.GoodsService;
import com.shrimpking.service.RecordService;
import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 * <p>
 * 出入库记录表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@RestController
@RequestMapping("/record")
public class RecordController {


    @Autowired
    private RecordService recordService;

    @Autowired
    private GoodsService goodsService;

    @PostMapping("/save")
    public Result save(@RequestBody Record record){
        Goods g1 = goodsService.getById(record.getGoods());
        int n = record.getCount();
        int newCount = g1.getCount() + n;
        g1.setCount(newCount);
        boolean flag = goodsService.updateById(g1);
        return recordService.save(record) ? Result.success():Result.fail();

    }

    //使用mybatis默认分页类
    @PostMapping("/listPage")
    public Result listPage(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<Record> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        LambdaQueryWrapper<Record> wrapper = new LambdaQueryWrapper<>();
        String goods = (String) query.getParam().get("goods");
        //String sex = (String) query.getParam().get("sex");
        //String roleId = (String) query.getParam().get("roleId");

        if(StringUtils.isNotBlank(goods) && !"null".equals(goods))
        {
            wrapper.like(Record::getGoods,goods);
        }
        //获取分页结果
        IPage result = recordService.page(page, wrapper);
        return Result.success(result.getRecords(),result.getTotal());
    }

    //使用自定义sql
    @PostMapping("/listPageC")
    public Result listPageC(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<Record> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        QueryWrapper<Record> wrapper = new QueryWrapper<>();
        wrapper.apply(" a.goods = b.id and c.id = b.storage_id and b.goods_type = d.id ");
        String goods = (String) query.getParam().get("goods");
        String storage = (String) query.getParam().get("storage");
        String goodsType = (String) query.getParam().get("goodsType");
        String roleId = (String) query.getParam().get("roleId");
        String userId = (String) query.getParam().get("userId");

        if(StringUtils.isNotBlank(goods) && !"null".equals(goods))
        {
            wrapper.like("b.goods_name",goods);
        }
        if(StringUtils.isNotBlank(storage) && !"null".equals(storage))
        {
            wrapper.eq("c.id",storage);
        }
        if(StringUtils.isNotBlank(goodsType) && !"null".equals(goodsType))
        {
            wrapper.like("d.id",goodsType);
        }
        if("2".equals(roleId))
        {
            wrapper.eq("a.user_id",userId);
        }
        //获取分页结果
        IPage result = recordService.pageC(page, wrapper);
        return Result.success(result.getRecords(),result.getTotal());
    }
}

menucontroller.java

package com.shrimpking.controller;


import com.shrimpking.common.Result;
import com.shrimpking.pojo.Menu;
import com.shrimpking.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 菜单表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-11
 */
@RestController
@RequestMapping("/menu")
public class MenuController {

    @Autowired
    private MenuService menuService;

    @GetMapping("/list")
    public Result getList(@RequestParam String roleId)
    {
        List<Menu> list = menuService.lambdaQuery().like(Menu::getMenuRight, roleId).list();
        return Result.success(list);
    }
}

goodsTypecontroller.java

package com.shrimpking.controller;


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.common.QueryPageParam;
import com.shrimpking.common.Result;
import com.shrimpking.pojo.Goodstype;
import com.shrimpking.service.GoodstypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 商品分类 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@RestController
@RequestMapping("/goodstype")
public class GoodstypeController {

    @Autowired
    private GoodstypeService goodstypeService;

    //增加
    @PostMapping("/save")
    public Result save(@RequestBody Goodstype goodstype)
    {
        return goodstypeService.save(goodstype) ? Result.success() : Result.fail();
    }

    //更新
    @PostMapping("/update")
    public Result update(@RequestBody Goodstype goodstype)
    {
        return goodstypeService.updateById(goodstype) ? Result.success() : Result.fail();
    }

    //删除
    @GetMapping("/delete")
    public Result delete(@RequestParam String id)
    {
        return goodstypeService.removeById(id) ? Result.success() : Result.fail();
    }

    //使用mybatis默认分页类
    @PostMapping("/listPage")
    public Result listPage(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<Goodstype> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        LambdaQueryWrapper<Goodstype> wrapper = new LambdaQueryWrapper<>();
        String name = (String) query.getParam().get("name");

        if(StringUtils.isNotBlank(name) && !"null".equals(name))
        {
            wrapper.like(Goodstype::getTypeName,name);
        }
        //获取分页结果
        IPage result = goodstypeService.page(page, wrapper);
        return Result.success(result.getRecords(),result.getTotal());
    }

    //根据分类名,查询唯一
    @GetMapping("/findByName")
    public Result findByName(@RequestParam String name)
    {
        List<Goodstype> list = goodstypeService.lambdaQuery().eq(Goodstype::getTypeName, name).list();
        return list.size() > 0 ? Result.success(list) : Result.fail();
    }

    @GetMapping("/list")
    public Result getList()
    {
        List<Goodstype> list = goodstypeService.list();
        return Result.success(list,(long)list.size());
    }
}

goodscontroller.java

package com.shrimpking.controller;


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.common.QueryPageParam;
import com.shrimpking.common.Result;
import com.shrimpking.pojo.Goods;
import com.shrimpking.pojo.Goodstype;
import com.shrimpking.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 商品表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-08-12
 */
@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    //增加
    @PostMapping("/save")
    public Result save(@RequestBody Goods goods)
    {
        return goodsService.save(goods) ? Result.success() : Result.fail();
    }

    //更新
    @PostMapping("/update")
    public Result update(@RequestBody Goods goods)
    {
        return goodsService.updateById(goods) ? Result.success() : Result.fail();
    }

    //删除
    @GetMapping("/delete")
    public Result delete(@RequestParam String id)
    {
        return goodsService.removeById(id) ? Result.success() : Result.fail();
    }

    //使用mybatis默认分页类
    @PostMapping("/listPage")
    public Result listPage(@RequestBody QueryPageParam query)
    {
        //分页类
        Page<Goods> page = new Page<>();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());
        //查询条件
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        String name = (String) query.getParam().get("name");
        String storage = (String) query.getParam().get("storage");
        String goodsType = (String) query.getParam().get("goodsType");

        if(StringUtils.isNotBlank(name) && !"null".equals(name))
        {
            wrapper.like(Goods::getGoodsName,name);
        }
        if(StringUtils.isNotBlank(storage))
        {
            wrapper.eq(Goods::getStorageId,storage);
        }
        if(StringUtils.isNotBlank(goodsType))
        {
            wrapper.eq(Goods::getGoodsType,goodsType);
        }
        //获取分页结果
        IPage result = goodsService.page(page, wrapper);
        return Result.success(result.getRecords(),result.getTotal());
    }

    //根据商品名,查询唯一
    @GetMapping("/findByName")
    public Result findByName(@RequestParam String name)
    {
        List<Goods> list = goodsService.lambdaQuery().eq(Goods::getGoodsName, name).list();
        return list.size() > 0 ? Result.success(list) : Result.fail();
    }
}

配置类

mybatisplusConfig.java

package com.shrimpking.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author user1
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

corsConfig.java

package com.shrimpking.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 案例 一
@Configuration
public class CorsConfig implements WebMvcConfigurer
{
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //放行哪些原始域
                .allowedOriginPatterns("*")
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

公共类

queryPageParam.java

package com.shrimpking.common;

import lombok.Data;

import java.util.HashMap;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/8/10 16:28
 * 入参封装
 */
@Data
public class QueryPageParam
{
    //常量
    private static int PAGE_SIZE = 20;
    private static int PAGE_NUM = 1;

    private Integer pageSize = PAGE_SIZE;
    private Integer pageNum = PAGE_NUM;
    private HashMap param = new HashMap();

}

result.java

package com.shrimpking.common;

import lombok.Data;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/8/10 18:31
 * 封装返回结果类
 */
@Data
public class Result
{
    //编码 200 400
    private Integer code;
    //成功 失败
    private String msg;
    //总记录数
    private Long total;
    //数据
    private Object data;


    /**
     * 成功时返回
     * @param data
     * @param total
     * @return
     */
    public static Result success(Object data,Long total)
    {
        return result(200,"成功",total,data);
    }


    /**
     * 成功时返回
     * @return
     */
    public static Result success()
    {
        return result(200,"成功",-1L,null);
    }

    /**
     * 成功时返回
     * @param data
     * @return
     */
    public static Result success(Object data)
    {
        return result(200,"成功",-1L,data);
    }

    /**
     * 失败时返回
     * @return
     */
    public static Result fail()
    {
        return result(400,"失败",0L,null);
    }

    /**
     *
     * @param code
     * @param msg
     * @param total
     * @param data
     * @return
     */
    private static Result result(Integer code,String msg,long total,Object data)
    {
        Result res = new Result();
        res.setData(data);
        res.setMsg(msg);
        res.setCode(code);
        res.setTotal(total);
        return res;
    }


}

vue前端

main.js

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@/styles/common.css'
import axios from "axios";
import router from "@/router";
import store from '@/store'


Vue.prototype.$axios = axios;
Vue.prototype.$httpUrl = 'http://localhost:8089';

Vue.use(ElementUI, { size: 'small'});
Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
  router,
  store
}).$mount('#app');

app.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App',
  data(){
    return {
      user: JSON.parse(sessionStorage.getItem("currentUser")) //当前用户
    }
  },
  watch:{
    '$store.state.menu':{
      handler(val,old){
        if(!old && this.user && this.user.userNo){
          this.$store.commit('setRouter',val);
        }
      },
      immediate:true
    }
  }
}
</script>

<style>

</style>

views

login.vue

<template>
    <div class="login-body">
        <div class="login-div">
            <div class="login-content">
                <h1 class="login-title">用户登录</h1>
                <el-form :model="loginForm" label-width="100px"
                    :rules="rules" ref="loginForm">
                    <el-form-item label="账号" prop="userNo">
                        <el-input style="" type="text" v-model="loginForm.userNo"
                            autocomplete="off"></el-input>
                    </el-form-item>
                    <el-form-item label="密码" prop="password">
                        <el-input style="" type="password" v-model="loginForm.password"
                            show-password autocomplete="off" @keyup.enter.native="confirm"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="confirm" :disabled="confirm_disabled">登 录</el-button>
                    </el-form-item>
                </el-form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "LoginPage",
        data(){
            return {
                confirm_disabled:false,
                loginForm:{
                    userNo:'',
                    password:''
                },
                rules:{
                    userNo:[
                        { required:true, message:'请输入账号', trigger:'blur'},
                    ],
                    password: [
                        { required: true, message: '请输入密码', trigger: 'blur'}
                    ]
                }
            }
        },
        methods:{
            confirm(){
                this.confirm_disabled = true;
                this.$refs.loginForm.validate((valid) => {
                    //valid成功为true,失败为false
                    if(valid){
                        //去后台验证用户名密码
                        this.$axios.post( this.$httpUrl + '/user/login',this.loginForm)
                            .then( res => {
                                if(res.data.code === 200){
                                    //存储服务器
                                    sessionStorage.setItem("currentUser",JSON.stringify(res.data.data));
                                    //跳转主页
                                    this.$router.push('/Index');
                                }else {
                                    this.confirm_disabled = false;
                                    this.$message.error("校验失败,用户名或密码错误");
                                    return false;
                                }

                            });
                    }else {
                        this.confirm_disabled = false;
                        this.$message.error("校验失败");
                        return false;
                    }
                });
            }
        }
    }
</script>

<style scoped>

    .login-body{
        position: absolute;
        width: 100%;
        height: 100%;
        background-color: #b3c0d1;
    }

    .login-div{
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -200px;
        margin-left: -250px;
        width: 450px;
        height: 330px;
        background-color: #ffffff;
        border-radius: 5%;
    }

    .login-title{
        margin: 20px 0;
        text-align: center;
    }

    .login-content{
        width: 400px;
        height: 250px;
        position: absolute;
        top: 25px;
        left: 25px;
    }
</style>

common.css

*{
    padding: 0;
    margin: 0;
}

store

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import router,{ resetRouter } from "@/router";
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex);

function addNewRouter(menuList) {
    //console.log(menuList);
    let routes = router.options.routes;
    routes.forEach(item => {
        if(item.path === "/Index"){
            menuList.forEach( menu => {
                let childRoute = {
                    path:'/' + menu.menuIndex,
                    name: menu.menuName,
                    meta:{
                        title: menu.menuName
                    },
                    component: ()=>import('@/components/' + menu.menuComponent)
                };
                //console.log(childRoute);
                item.children.push(childRoute);
            });
        }
    });
    //路由表先清空,再添加
    resetRouter();
    router.addRoutes(routes);
}

const store = new Vuex.Store({
    state:{
        menu:[]
    },
    mutations:{
        setMenu(state,menuList){
            state.menu = menuList;
            addNewRouter(menuList);
        },
        setRouter(state,menuList){
            addNewRouter(menuList);
        }
    },
    getters:{
        getMenu(state){
            return state.menu;
        }
    },
    plugins:[createPersistedState()]

});

export default store;

router

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from "@/views/Login";
import Index from "@/components/Index";
import Home from "@/components/Home";
Vue.use(VueRouter);

const router = new VueRouter({
   routes:[
       {
           path:'/',
           name:'login',
           component: Login
       },
       {
           path: '/Index',
           name: 'index',
           component: Index,
           redirect:'/Home',
           children:[
               {
                   path:'/Home',
                   name:'home',
                   meta:{
                       title:'首页'
                   },
                   component: Home
               }
           ]
       }
   ],
    mode:'history'
});

//重置路由,清空
export function resetRouter() {
    router.matcher = new VueRouter({
        mode: 'history',
        routes: []
    }).matcher
}

//home页,再次进入时发生冲突
const VueRouterPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push (to) {
    return VueRouterPush.call(this,to).catch(err => err)
};

export default router;

components

user.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="userName"
                      placeholder="请输入名字"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="sex" placeholder="请选择性别" style="margin-left:10px;width:300px;">
                <el-option
                        v-for="item in sexList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add">新增</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="userNo" label="账号">
            </el-table-column>
            <el-table-column prop="userName" label="名字">
            </el-table-column>
            <el-table-column prop="age" label="年龄">
            </el-table-column>
            <el-table-column prop="sex" label="性别">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.sex === 1 ? 'primary' : 'success'"
                            disable-transitions>{{scope.row.sex === 1 ? '男' : '女'}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="roleId" label="角色">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.roleId === 0 ? 'danger' : (scope.row.roleId === 1 ? 'primary' : 'success')"
                            disable-transitions>{{scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户')}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="phone" label="电话">
            </el-table-column>
            <el-table-column prop="operate" label="操作">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增用户"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="账号" prop="userNo">
                    <el-col :span="20">
                        <el-input v-model="form.userNo"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="名字" prop="userName">
                    <el-col :span="20">
                        <el-input v-model="form.userName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="密码" prop="password">
                    <el-col :span="20">
                        <el-input v-model="form.password"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="年龄" prop="age">
                    <el-col :span="20">
                        <el-input v-model="form.age"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="性别">
                    <el-radio-group v-model="form.sex">
                        <el-radio label="1">男</el-radio>
                        <el-radio label="2">女</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="电话" prop="phone">
                    <el-col :span="20">
                        <el-input v-model="form.phone"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: "UserPage",
        data() {
            //判断年龄
            let checkAge = (rule, value, callback) => {
                if(value > 150){
                    callback(new Error('年龄输入过大'));
                }else{
                    callback();
                }
            };

            //验证账号唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证账号
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/user/findByUserNo?userNo=' + this.form.userNo).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('账号已经存在'));
                    }
                })
            };
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                userName:'', //查询名字输入框
                sex:'', //查询选择性别
                sexList:[
                    { value:'1',label:'男'},
                    { value:'2',label:'女'}
                ],  //性别下拉框绑定
                dialogVisible: false, //模态输入框是否显示
                form:{
                    id:'',
                    userNo:'',
                    userName:'',
                    password:'',
                    age:'',
                    phone:'',
                    sex:'1',
                    roleId:'2'
                }, //表单中的输入项
                //验证规则
                rules: {
                    userNo: [
                        { required: true, message: '请输入账号', trigger: 'blur' },
                        { min: 1, max: 15, message: '长度在 1 到 15 个字符', trigger: 'blur' },
                        { validator: checkDuplicate ,trigger:'blur'}
                    ],
                    userName: [
                        { required: true, message: '请输入名字', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' }
                    ],
                    password: [
                        { required: true, message: '请输入密码', trigger: 'blur' }
                    ],
                    age: [
                        { required: true, message: '请输入年龄', trigger: 'blur' },
                        { min:1, max:3, message: '年龄在1到3位数之间',trigger: 'blur'},
                        { validator: checkAge ,trigger:'blur'}
                    ],
                    phone: [
                        { required: true, message: '请输入电话', trigger: 'blur' },
                        { pattern:/^1[3|4|5|6|7|8|9][0-9]\d{8}/, message: '手机号码格式不正确', trigger: 'blur'}
                    ]
                }
            }
        },
        methods:{
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/user/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.userNo = row.userNo;
                    this.form.userName = row.userName;
                    this.form.password = row.password;
                    this.form.age = row.age +''; //数字转字符,才显示
                    this.form.phone = row.phone;
                    this.form.sex = row.sex + '';
                    this.form.roleId = row.roleId;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/user/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/user/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam(){
                this.userName = '';
                this.sex = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/user/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/user/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.userName, //查询的名字
                        sex: this.sex,  //查询性别
                        roleId:'2' //角色id
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

storage.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="storageName"
                      placeholder="请输入仓库名"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add">新增</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="storageName" label="仓库名">
            </el-table-column>
            <el-table-column prop="remark" label="备注">
            </el-table-column>
            <el-table-column prop="operate" label="操作">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增仓库"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="仓库名" prop="storageName">
                    <el-col :span="20">
                        <el-input v-model="form.storageName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="备注">
                    <el-col :span="20">
                        <el-input type="textarea" v-model="form.remark" :rows="5"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: "StoragePage",
        data() {
            //验证仓库名唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证账号
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/storage/findByName?name=' + this.form.storageName).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('仓库已经存在'));
                    }
                })
            };
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                storageName:'', //查询输入框
                dialogVisible: false, //模态输入框是否显示
                form:{
                    id:'',
                    storageName:'',
                    remark:''
                }, //表单中的输入项
                //验证规则
                rules: {
                    storageName: [
                        { required: true, message: '请输入仓库名', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' },
                        { validator: checkDuplicate, trigger:'blur'}
                    ]
                }
            }
        },
        methods:{
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/storage/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.storageName = row.storageName;
                    this.form.remark = row.remark;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/storage/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/storage/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam(){
                this.storageName = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/storage/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/storage/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.storageName, //查询的名字
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

selectuser.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="userName"
                      placeholder="请输入名字"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="sex" placeholder="请选择性别" style="margin-left:10px;width:300px;">
                <el-option
                        v-for="item in sexList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border
                  highlight-current-row
                  @current-change="handleCurrentRowChange">
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="userNo" label="账号">
            </el-table-column>
            <el-table-column prop="userName" label="名字">
            </el-table-column>
            <el-table-column prop="age" label="年龄">
            </el-table-column>
            <el-table-column prop="sex" label="性别">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.sex === 1 ? 'primary' : 'success'"
                            disable-transitions>{{scope.row.sex === 1 ? '男' : '女'}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="roleId" label="角色">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.roleId === 0 ? 'danger' : (scope.row.roleId === 1 ? 'primary' : 'success')"
                            disable-transitions>{{scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户')}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="phone" label="电话">
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
    </div>
</template>

<script>

    export default {
        name: "UserPage",
        data() {
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                userName:'', //查询名字输入框
                sex:'', //查询选择性别
                sexList:[
                    { value:'1',label:'男'},
                    { value:'2',label:'女'}
                ] //性别下拉框绑定
            }
        },
        methods:{
            //选择的那一行
            handleCurrentRowChange(row){
                this.$emit('selectDoneUser',row)
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //重置按钮
            resetParam(){
                this.userName = '';
                this.sex = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/user/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.userName, //查询的名字
                        sex: this.sex,  //查询性别
                        roleId:'2' //角色id
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

record.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="goods"
                      placeholder="请输入商品名"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="storage" placeholder="请选择仓库" style="margin-left:10px;">
                <el-option
                        v-for="item in storageData"
                        :key="item.id"
                        :label="item.storageName"
                        :value="item.id">
                </el-option>
            </el-select>
            <el-select v-model="goodsType" placeholder="请选择分类" style="margin-left:10px;">
                <el-option
                        v-for="item in goodsTypeData"
                        :key="item.id"
                        :label="item.typeName"
                        :value="item.id">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="goodsName" label="商品名">
            </el-table-column>
            <el-table-column prop="storageName" label="仓库名">
            </el-table-column>
            <el-table-column prop="typeName" label="分类名">
            </el-table-column>
            <el-table-column prop="userName" label="经办人">
            </el-table-column>
            <el-table-column prop="adminName" label="操作人">
            </el-table-column>
            <el-table-column prop="count" label="数量">
            </el-table-column>
            <el-table-column prop="createTime" label="操作时间">
            </el-table-column>
            <el-table-column prop="remark" label="备注">
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
    </div>
</template>

<script>

    export default {
        name: "RecordPage",
        data() {
            return {
                user: JSON.parse(sessionStorage.getItem("currentUser")), //当前用户
                tableData: [], //列表数据
                userData: [], //用户数据
                storageData:[], //仓库列表
                goodsTypeData:[], //商品分类列表
                pageNum: 1, //当前页码
                pageSize: 10, //每页数量
                total: 0, //总记录数
                goods: '', //查询输入框
                storage:'', //查询
                goodsType:'', //查询
                dialogVisible: false, //模态输入框是否显示
                form: {
                    id: '',
                    goods: '',
                    count: 0,
                    remark: ''
                }, //表单中的输入项
                //验证规则
                rules: {
                    goods: [
                        {required: true, message: '请输入商品名', trigger: 'blur'},
                        {min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur'},
                    ],
                    count: [
                        {required: true, message: '请输入数量', trigger: 'blur'},
                    ]
                }
            }
        },
        methods: {
            //格式化表格中
            formatUser(row) {
                let temp = this.userData.find(item => {
                    return item.id === row.userId
                });

                return temp && temp.userName;
            },
            formatAdmin(row) {
                let temp = this.userData.find(item => {
                    return item.id === row.adminId
                });

                return temp && temp.userName;
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doSave() {
                this.$axios.post(this.$httpUrl + '/xx/save', this.form).then(res => {
                    //console.log(res);
                    if (res.data.code === 200) {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    } else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save() {
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if (this.form.id) {
                            //修改,保存
                            this.doUpdate();
                        } else {
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add() {
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() => {
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam() {
                this.goods = '';
                this.storage = '';
                this.goodsType = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet() {
                this.$axios.get(this.$httpUrl + '/record/listPage').then(res => {
                    //console.log(res);
                    if (res.data.code === 200) {
                        this.tableData = res.data.data;
                    } else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost() {
                this.$axios.post(this.$httpUrl + '/record/listPageC', {
                    pageSize: this.pageSize,
                    pageNum: this.pageNum,
                    param: {
                        goods: this.goods, //查询的名字
                        storage: this.storage + '', //仓库
                        goodsType: this.goodsType + '', // 分类
                        roleId: this.user.roleId + '', //角色
                        userId: this.user.id + ''  //  用户id
                    }
                }).then(res => {
                    console.log(res);
                    if (res.data.code === 200) {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    } else {
                        alert('获取数据失败');
                    }
                })
            },
            loadUser() {
                this.$axios.get(this.$httpUrl + '/user/list').then(res => {
                    //console.log(res);
                    if (res.data.code === 200) {
                        //列表数据
                        this.userData = res.data.data;
                    } else {
                        alert('获取数据失败');
                    }
                })
            },
            loadStorage(){
                this.$axios.get( this.$httpUrl + '/storage/list').then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.storageData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            loadGoodsType(){
                this.$axios.get( this.$httpUrl + '/goodstype/list').then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.goodsTypeData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            this.loadUser();
            this.loadStorage();
            this.loadGoodsType();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

main.vue

<template>
    <div>
        <div style="margin-bottom: 10px;">
            <el-input v-model="userName"
                      placeholder="请输入名字"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="sex" placeholder="请选择性别" style="margin-left:10px;width:300px;">
                <el-option
                        v-for="item in sexList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add">新增</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="userNo" label="账号">
            </el-table-column>
            <el-table-column prop="userName" label="名字">
            </el-table-column>
            <el-table-column prop="age" label="年龄">
            </el-table-column>
            <el-table-column prop="sex" label="性别">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.sex === 1 ? 'primary' : 'success'"
                            disable-transitions>{{scope.row.sex === 1 ? '男' : '女'}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="roleId" label="角色">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.roleId === 0 ? 'danger' : (scope.row.roleId === 1 ? 'primary' : 'success')"
                            disable-transitions>{{scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户')}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="phone" label="电话">
            </el-table-column>
            <el-table-column prop="operate" label="操作">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增用户"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="账号" prop="userNo">
                    <el-col :span="20">
                        <el-input v-model="form.userNo"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="名字" prop="userName">
                    <el-col :span="20">
                        <el-input v-model="form.userName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="密码" prop="password">
                    <el-col :span="20">
                        <el-input v-model="form.password"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="年龄" prop="age">
                    <el-col :span="20">
                        <el-input v-model="form.age"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="性别">
                    <el-radio-group v-model="form.sex">
                        <el-radio label="1">男</el-radio>
                        <el-radio label="2">女</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="电话" prop="phone">
                    <el-col :span="20">
                        <el-input v-model="form.phone"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: "MainPart",
        data() {
            //判断年龄
            let checkAge = (rule, value, callback) => {
                if(value > 150){
                    callback(new Error('年龄输入过大'));
                }else{
                    callback();
                }
            };

            //验证账号唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证账号
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/user/findByUserNo?userNo=' + this.form.userNo).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('账号已经存在'));
                    }
                })
            };
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                userName:'', //查询名字输入框
                sex:'', //查询选择性别
                sexList:[
                    { value:'1',label:'男'},
                    { value:'2',label:'女'}
                ],  //性别下拉框绑定
                dialogVisible: false, //模态输入框是否显示
                form:{
                    id:'',
                    userNo:'',
                    userName:'',
                    password:'',
                    age:'',
                    phone:'',
                    sex:'1',
                    roleId:'2'
                }, //表单中的输入项
                //验证规则
                rules: {
                    userNo: [
                        { required: true, message: '请输入账号', trigger: 'blur' },
                        { min: 1, max: 15, message: '长度在 1 到 15 个字符', trigger: 'blur' },
                        { validator: checkDuplicate ,trigger:'blur'}
                    ],
                    userName: [
                        { required: true, message: '请输入名字', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' }
                    ],
                    password: [
                        { required: true, message: '请输入密码', trigger: 'blur' }
                    ],
                    age: [
                        { required: true, message: '请输入年龄', trigger: 'blur' },
                        { min:1, max:3, message: '年龄在1到3位数之间',trigger: 'blur'},
                        { validator: checkAge ,trigger:'blur'}
                    ],
                    phone: [
                        { required: true, message: '请输入电话', trigger: 'blur' },
                        { pattern:/^1[3|4|5|6|7|8|9][0-9]\d{8}/, message: '手机号码格式不正确', trigger: 'blur'}
                    ]
                }
            }
        },
        methods:{
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/user/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.userNo = row.userNo;
                    this.form.userName = row.userName;
                    this.form.password = row.password;
                    this.form.age = row.age +''; //数字转字符,才显示
                    this.form.phone = row.phone;
                    this.form.sex = row.sex + '';
                    this.form.roleId = row.roleId;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/user/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/user/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                });
            },
            //重置按钮
            resetParam(){
                this.userName = '';
                this.sex = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/user/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/user/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.userName, //查询的名字
                        sex: this.sex  //查询性别
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

index.vue

<template>
    <div style="width:100%;height: 100vh;">
        <el-container style="height: 100%; border: 1px solid #eee">
            <el-aside :width="asideWidth" style="background-color: rgb(238, 241, 246);height: 100%;margin-left: -1px;">
                <Aside :isCollapse="isCollapse"></Aside>
            </el-aside>

            <el-container style="width:100%;height:100%;">
                <el-header style="text-align: right; font-size: 12px;width: 100%;border-bottom: 1px solid #cccccc;">
                    <Header @doCollapse="handleCollapse" :icon="icon"></Header>
                </el-header>
                <el-main>
                    <router-view></router-view>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>

<script>
    import Aside from "@/components/Aside";
    import Header from "@/components/Header";
    export default {
        name: "IndexPage",
        data(){
          return {
              isCollapse: false,
              asideWidth: '200px',
              icon:'el-icon-s-fold'
          }
        },
        components:{
            Aside,
            Header
        },
        methods:{
            //折叠左侧菜单栏
            handleCollapse(){
                this.isCollapse = !this.isCollapse;
                //折叠菜单栏时,也缩放宽度
                this.asideWidth = this.isCollapse ? '64px' : '200px';
                this.icon = this.isCollapse ? 'el-icon-s-unfold':'el-icon-s-fold';
            }
        }
    }
</script>

<style scoped>
    .el-header {
        #background-color: #B3C0D1;
        color: #333;
        line-height: 60px;
    }

    .el-aside {
        color: #333;
    }

    .el-main{
        padding: 0;
    }
</style>

home.vue

<template>
    <div style="background-color: #eaebea;width: 100%;height: 100%;">
        <h1 style="font-size:30px;text-align: center;padding-top: 50px;padding-bottom: 40px;">欢迎你 &lt;{{ user.userName }} &gt;</h1>
        <el-descriptions title="个人中心" :column="2" size="40" border>
            <el-descriptions-item>
                <template slot="label">
                    <i class="el-icon-s-custom"></i>
                    账号
                </template>
                {{ user.userNo }}
            </el-descriptions-item>
            <el-descriptions-item>
                <template slot="label">
                    <i class="el-icon-mobile-phone"></i>
                    电话
                </template>
                {{ user.phone }}
            </el-descriptions-item>
            <el-descriptions-item>
                <template slot="label">
                    <i class="el-icon-location-outline"></i>
                    性别
                </template>
                <el-tag :type="user.sex === 1 ? 'primary':'success'" disable-transitions>
                    <i :class="user.sex === 1 ? 'el-icon-male':'el-icon-female'"></i>
                    {{user.sex === 1 ? '男': '女'}}
                </el-tag>
            </el-descriptions-item>
            <el-descriptions-item>
                <template slot="label">
                    <i class="el-icon-tickets"></i>
                    角色
                </template>
                <el-tag type="success" disable-transtions>
                    {{ user.roleId === 0 ? '超级管理员':(user.roleId === 1? '管理员':'用户')}}
                </el-tag>
            </el-descriptions-item>
        </el-descriptions>


    </div>
</template>

<script>
    export default {
        name: "HomePage",
        data(){
            return {
                user:{}
            }
        },
        computed:{

        },
        methods:{
            init(){
                this.user = JSON.parse(sessionStorage.getItem("currentUser"))
            }
        },
        created(){
            this.init();
        }
    }
</script>

<style scoped>

</style>

header.vue

<template>
    <div style="display: flex;line-height: 60px;">
        <div @click="collapse" style="cursor: pointer;">
            <i :class="icon" style="font-size:20px;"></i>
        </div>
        <div style="flex: 1;text-align: center;font-size: 34px;">
            <span>模拟仓库管理系统</span>
        </div>
        <el-dropdown>
            <span>{{ user.userName }}</span>
            <i class="el-icon-arrow-down" style="margin-right: 15px;margin-left:5px;"></i>
            <el-dropdown-menu slot="dropdown">
                <el-dropdown-item @click.native="toUser">个人中心</el-dropdown-item>
                <el-dropdown-item @click.native="logout">退出</el-dropdown-item>
            </el-dropdown-menu>
        </el-dropdown>
    </div>
</template>

<script>
    export default {
        name: "HeaderPart",
        data(){
          return {
              user: JSON.parse(sessionStorage.getItem("currentUser"))
          }
        },
        props:{
          icon: String
        },
        methods:{
            toUser(){
               //console.log('to_user');
                this.$router.push('/Home');
            },
            logout(){
                //console.log("logout");
                this.$confirm('您确定要退出系统吗?','提示',{
                    confirmButtonText:'退出', //
                    type:'warning',
                    center:true //文字居中
                }).then(()=>{
                    //退出
                    this.$message({
                        message:'退出系统成功!',
                        type:'success'
                    });
                    //清空
                    sessionStorage.clear();
                    //跳转登录页
                    this.$router.push("/");
                }).catch(()=>{
                    this.$message({
                        message:'已取消退出登录!',
                        type:'info'
                    });
                });

            },
            //折叠左侧菜单栏
            collapse(){
                this.$emit('doCollapse');
            }
        }
    }
</script>

<style scoped>

</style>

goodsType.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="typeName"
                      placeholder="请输入分类名称"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add">新增</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="typeName" label="分类名">
            </el-table-column>
            <el-table-column prop="remark" label="备注">
            </el-table-column>
            <el-table-column prop="operate" label="操作">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增分类"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="分类名称" prop="typeName">
                    <el-col :span="20">
                        <el-input v-model="form.typeName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="备注">
                    <el-col :span="20">
                        <el-input type="textarea" v-model="form.remark" :rows="5"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: "GoodsType",
        data() {
            //验证分类名唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/goodstype/findByName?name=' + this.form.typeName).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('分类名称已经存在'));
                    }
                })
            };
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                typeName:'', //查询输入框
                dialogVisible: false, //模态输入框是否显示
                form:{
                    id:'',
                    typeName:'',
                    remark:''
                }, //表单中的输入项
                //验证规则
                rules: {
                    typeName: [
                        { required: true, message: '请输入分类名', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' },
                        { validator: checkDuplicate, trigger:'blur'}
                    ]
                }
            }
        },
        methods:{
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/goodstype/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.typeName = row.typeName;
                    this.form.remark = row.remark;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/goodstype/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/goodstype/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam(){
                this.typeName = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/goodstype/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/goodstype/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.typeName, //查询的名字
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

goods.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="goodsName"
                      placeholder="请输入商品名"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="storage" placeholder="请选择仓库" style="margin-left:10px;">
                <el-option
                        v-for="item in storageData"
                        :key="item.id"
                        :label="item.storageName"
                        :value="item.id">
                </el-option>
            </el-select>
            <el-select v-model="goodsType" placeholder="请选择分类" style="margin-left:10px;">
                <el-option
                        v-for="item in goodsTypeData"
                        :key="item.id"
                        :label="item.typeName"
                        :value="item.id">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add" v-if="user.roleId !=2">新增</el-button>
            <el-button type="success" @click="inGoods" v-if="user.roleId !=2">入库</el-button>
            <el-button type="success" @click="outGoods" v-if="user.roleId !=2">出库</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border
                  highlight-current-row
                  @current-change="handleCurrentRowChange">
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="goodsName" label="商品名">
            </el-table-column>
            <el-table-column prop="storageId" label="仓库" :formatter="formatStorage">
            </el-table-column>
            <el-table-column prop="goodsType" label="商品分类" :formatter="formatGoodsType">
            </el-table-column>
            <el-table-column prop="count" label="数量">
            </el-table-column>
            <el-table-column prop="remark" label="备注">
            </el-table-column>
            <el-table-column prop="operate" label="操作" v-if="user.roleId !=2">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增商品"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="商品名称" prop="goodsName">
                    <el-col :span="20">
                        <el-input v-model="form.goodsName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="仓库" prop="storageId">
                    <el-col :span="20">
                        <el-select v-model="form.storageId" placeholder="请选择仓库">
                            <el-option
                                    v-for="item in storageData"
                                    :key="item.id"
                                    :label="item.storageName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-col>
                </el-form-item>
                <el-form-item label="商品分类" prop="goodsType">
                    <el-col :span="20">
                        <el-select v-model="form.goodsType" placeholder="请选择分类">
                            <el-option
                                    v-for="item in goodsTypeData"
                                    :key="item.id"
                                    :label="item.typeName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-col>
                </el-form-item>
                <el-form-item label="数量" prop="count">
                    <el-col :span="20">
                        <el-input v-model="form.count"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="备注">
                    <el-col :span="20">
                        <el-input type="textarea" v-model="form.remark" :rows="5"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>

        <el-dialog
                title="出入库"
                :visible.sync="inDialogVisible"
                width="30%"
                :before-close="handleInClose"
                center>
            <el-dialog
                    width="65%"
                    title="选择用户"
                    :visible.sync="innerVisible"
                    append-to-body>
                <select-user @selectDoneUser="selectDoneUser"></select-user>
                <span slot="footer" class="dialog-footer">
                    <el-button @click="innerVisible = false">取 消</el-button>
                    <el-button type="primary" @click="confirmUser">确定</el-button>
                </span>
            </el-dialog>
            <el-form ref="formIn" :rules="rulesIn"  :model="formIn" label-width="80px">
                <el-form-item label="商品名称">
                    <el-col :span="20">
                        <el-input v-model="formIn.goodsName" readonly></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="经办人">
                    <el-col :span="20">
                        <el-input v-model="formIn.userName" readonly @click.native="selectUser"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="数量" prop="count">
                    <el-col :span="20">
                        <el-input v-model="formIn.count"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="备注">
                    <el-col :span="20">
                        <el-input type="textarea" v-model="formIn.remark" :rows="5"></el-input>
                    </el-col>
                </el-form-item>

            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="inDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="saveIn">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
    import SelectUser from "@/components/SelectUser";
    export default {
        name: "GoodsPage",
        components:{
            SelectUser
        },
        data() {

            let checkCount = (rule, value, callback) => {
                if(value > 9999){
                    callback(new Error('数量输入过大'));
                }else {
                    callback();
                }
            };

            //验证商品名唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/goods/findByName?name=' + this.form.goodsName).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('商品名称已经存在'));
                    }
                })
            };
            return {
                user: JSON.parse(sessionStorage.getItem("currentUser")), //当前登录用户
                tableData: [], //列表数据
                storageData:[], //仓库列表
                goodsTypeData:[], //商品分类列表
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                goodsName:'', //查询输入框
                storage:'', //查询下拉框仓库
                goodsType:'', //查询下拉框分类
                dialogVisible: false, //模态输入框是否显示
                inDialogVisible: false, // 入库对话框
                outDialogVisible: false, //出库对话框
                currentRow: null, //当前行
                innerVisible: false, //内层对话框
                tempUser:{},
                form:{
                    id:'',
                    goodsName:'',
                    storageId:'',
                    goodsType:'',
                    count:0,
                    remark:''
                }, //表单中的输入项
                formIn:{
                    goods:'',
                    goodsName:'',
                    userId:'3',
                    userName:'',
                    adminId:'',
                    count: '',
                    remark:''
                },
                formOut:{
                    goods:'',
                    goodsName:'',
                    userId:'3',
                    adminId:'',
                    count: '',
                    remark:''
                },
                //验证规则
                rulesIn:{

                },
                //验证规则
                rules: {
                    goodsName: [
                        { required: true, message: '请输入商品名', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' },
                        { validator: checkDuplicate, trigger:'blur'}
                    ],
                    storageId: [
                        { required: true, message: '请选择仓库', trigger: 'blur' },
                    ],
                    goodsType: [
                        { required: true, message: '请选择分类名', trigger: 'blur' },
                    ],
                    count: [
                        { required: true, message: '请输入数量', trigger: 'blur' },
                        { pattern:/^([1-9][0-9]*){1,4}/, message: '数量必须为正数', trigger: 'blur'},
                        { validator: checkCount,trigger: 'blur'}
                    ]
                }
            }
        },
        methods:{
            //监听,选择完毕用户
            selectDoneUser(row){
                //传给临时用户保存
                this.tempUser = row;
            },
            //内层选择用户对话框,确定按钮
            confirmUser(){
                this.formIn.userId = this.tempUser.id;
                this.formIn.userName = this.tempUser.userName;
                this.innerVisible = false;
            },
            selectUser(){
                this.innerVisible = true;
            },
            handleCurrentRowChange(val) {
                this.currentRow = val;
            },
            //入库保存
            saveIn(){
                this.$axios.post( this.$httpUrl + '/record/save',this.formIn).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '入库成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.inDialogVisible = false;
                        this.loadPost();
                        this.resetInForm();
                    }else {
                        this.$message.error('入库失败');
                    }
                });
            },
            //入库关闭
            handleInClose() {
                this.inDialogVisible = false;
            },
            //重置入库表单
            resetInForm() {
                this.$refs.formIn.resetFields();
            },
            //重置出库表单
            resetOutForm() {
                this.$refs.formOut.resetFields();
            },
            //入库按钮
            inGoods(){
                if(this.currentRow == null || !this.currentRow.id){
                    this.$message({
                       type:'warning',
                       message:'请选择一行'
                    });
                    return;
                }
                this.inDialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetInForm();
                });

                this.formIn.goods = this.currentRow.id;
                this.formIn.goodsName = this.currentRow.goodsName;
                this.formIn.adminId = this.user.id;


            },
            //出库按钮
            outGoods(){
                this.outDialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetOutForm();
                });
            },
            //格式化表格中的分类列
            formatGoodsType(row){
                let temp = this.goodsTypeData.find( item => {
                    return item.id === row.goodsType
                });
                return temp && temp.typeName;
            },
            //格式化表格中仓库列
            formatStorage(row){
                let temp = this.storageData.find( item => {
                    return item.id === row.storageId
                });

                return temp && temp.storageName;
            },
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/goods/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.goodsName = row.goodsName;
                    this.form.storageId = row.storageId;
                    this.form.goodsType = row.goodsType;
                    this.form.count = row.count;
                    this.form.remark = row.remark;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/goods/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/goods/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam(){
                this.goodsName = '';
                this.storage = '';
                this.goodsType = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/goods/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/goods/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.goodsName, //查询的名字
                        storage: this.storage + '', //查询的仓库
                        goodsType: this.goodsType + '', //查询的分类
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            loadStorage(){
                this.$axios.get( this.$httpUrl + '/storage/list').then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.storageData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            loadGoodsType(){
                this.$axios.get( this.$httpUrl + '/goodstype/list').then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.goodsTypeData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadStorage();
            this.loadGoodsType();
            this.loadPost();

        }
    }
</script>

<style scoped>

</style>

aside.vue

<template>
    <el-menu
            background-color="#545c64"
            text-color="#fff"
            active-text-color="#ffd04b"
            style="height: 100%;"
            default-active="/home"
            :collapse="isCollapse"
            :collapse-transition="false"
            router >
        <el-menu-item index="/home">
            <i class="el-icon-s-home"></i>
            <span slot="title">首页</span>
        </el-menu-item>
        <el-menu-item :index="'/' + item.menuIndex"  v-for="(item,index) in menu" :key="index">
            <i :class="item.menuIcon"></i>
            <span slot="title">{{item.menuName}}</span>
        </el-menu-item>
    </el-menu>
</template>

<script>
    export default {
        name: "AsidePart",
        data(){
            return {
                user: {},
                menu:[]
            }
        },
        //折叠左侧菜单栏
        props:{
            isCollapse: Boolean
        },
        methods:{
          loadMenu(){
              //console.log(this.user.roleId);
              this.$axios.get(this.$httpUrl + '/menu/list?roleId=' + this.user.roleId+'').then(res => {
                  //console.log(res);
                  this.menu = res.data.data;
                  this.$store.commit('setMenu',this.menu);
              })
          },
            init(){
                this.user = JSON.parse(sessionStorage.getItem("currentUser"))
            }
        },
        created(){
            this.init();
            this.loadMenu();
        }
    }
</script>

<style scoped>

</style>

admin.vue

<template>
    <div style="padding-top: 5px;">
        <div style="margin-bottom: 10px;">
            <el-input v-model="userName"
                      placeholder="请输入名字"
                      style="width:300px;"
                      suffix-icon="el-icon-search"
                      @keyup.enter.native="loadPost"></el-input>
            <el-select v-model="sex" placeholder="请选择性别" style="margin-left:10px;width:300px;">
                <el-option
                        v-for="item in sexList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
            <el-button type="primary" style="margin-left: 5px;" @click="loadPost">查询</el-button>
            <el-button type="success" style="margin-left: 5px;" @click="resetParam">重置</el-button>
            <el-button type="success" @click="add">新增</el-button>
        </div>
        <el-table :data="tableData" style="height: 100%;"
                  :header-cell-style="{background:'#92b5b6', color:'#221e1d'}"
                  border>
            <el-table-column prop="id" label="ID" >
            </el-table-column>
            <el-table-column prop="userNo" label="账号">
            </el-table-column>
            <el-table-column prop="userName" label="名字">
            </el-table-column>
            <el-table-column prop="age" label="年龄">
            </el-table-column>
            <el-table-column prop="sex" label="性别">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.sex === 1 ? 'primary' : 'success'"
                            disable-transitions>{{scope.row.sex === 1 ? '男' : '女'}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="roleId" label="角色">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.roleId === 0 ? 'danger' : (scope.row.roleId === 1 ? 'primary' : 'success')"
                            disable-transitions>{{scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户')}}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="phone" label="电话">
            </el-table-column>
            <el-table-column prop="operate" label="操作">
                <template slot-scope="scope">
                    <el-button type="success" @click="update(scope.row)" style="margin-right:10px;">编辑</el-button>
                    <el-popconfirm title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <el-button type="danger" slot="reference">删除</el-button>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[1, 2, 10, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
        <el-dialog
                title="新增用户"
                :visible.sync="dialogVisible"
                width="30%"
                :before-close="handleClose"
                center>
            <el-form ref="form" :rules="rules"  :model="form" label-width="80px">
                <el-form-item label="账号" prop="userNo">
                    <el-col :span="20">
                        <el-input v-model="form.userNo"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="名字" prop="userName">
                    <el-col :span="20">
                        <el-input v-model="form.userName"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="密码" prop="password">
                    <el-col :span="20">
                        <el-input v-model="form.password"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="年龄" prop="age">
                    <el-col :span="20">
                        <el-input v-model="form.age"></el-input>
                    </el-col>
                </el-form-item>
                <el-form-item label="性别">
                    <el-radio-group v-model="form.sex">
                        <el-radio label="1">男</el-radio>
                        <el-radio label="2">女</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="电话" prop="phone">
                    <el-col :span="20">
                        <el-input v-model="form.phone"></el-input>
                    </el-col>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="save">保 存</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: "AdminPage",
        data() {
            //判断年龄
            let checkAge = (rule, value, callback) => {
                if(value > 150){
                    callback(new Error('年龄输入过大'));
                }else{
                    callback();
                }
            };

            //验证账号唯一性
            let checkDuplicate = (rule, value, callback) => {
                //修改时,不验证账号
                if(this.form.id){
                    return callback();
                }
                this.$axios.get(this.$httpUrl + '/user/findByUserNo?userNo=' + this.form.userNo).then( res=> {
                    //console.log(res);
                    if(res.data.code !==200){
                        callback();
                    }else{
                        callback(new Error('账号已经存在'));
                    }
                })
            };
            return {
                tableData: [], //列表数据
                pageNum:1, //当前页码
                pageSize:10, //每页数量
                total:0, //总记录数
                userName:'', //查询名字输入框
                sex:'', //查询选择性别
                sexList:[
                    { value:'1',label:'男'},
                    { value:'2',label:'女'}
                ],  //性别下拉框绑定
                dialogVisible: false, //模态输入框是否显示
                form:{
                    id:'',
                    userNo:'',
                    userName:'',
                    password:'',
                    age:'',
                    phone:'',
                    sex:'1',
                    roleId:'1'
                }, //表单中的输入项
                //验证规则
                rules: {
                    userNo: [
                        { required: true, message: '请输入账号', trigger: 'blur' },
                        { min: 1, max: 15, message: '长度在 1 到 15 个字符', trigger: 'blur' },
                        { validator: checkDuplicate ,trigger:'blur'}
                    ],
                    userName: [
                        { required: true, message: '请输入名字', trigger: 'blur' },
                        { min: 1, max: 20, message: '长度在 1 到20 个字符', trigger: 'blur' }
                    ],
                    password: [
                        { required: true, message: '请输入密码', trigger: 'blur' }
                    ],
                    age: [
                        { required: true, message: '请输入年龄', trigger: 'blur' },
                        { min:1, max:3, message: '年龄在1到3位数之间',trigger: 'blur'},
                        { validator: checkAge ,trigger:'blur'}
                    ],
                    phone: [
                        { required: true, message: '请输入电话', trigger: 'blur' },
                        { pattern:/^1[3|4|5|6|7|8|9][0-9]\d{8}/, message: '手机号码格式不正确', trigger: 'blur'}
                    ]
                }
            }
        },
        methods:{
            //删除按钮
            handleDelete(id){
                this.$axios.get( this.$httpUrl + '/user/delete?id=' + id).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        this.loadPost();
                    }else {
                        this.$message.error('删除失败');
                    }
                });
            },
            //修改按钮
            update(row){
                //console.log(row);
                //赋值到表单
                //显示对话框
                this.dialogVisible = true;
                //异步赋值
                this.$nextTick( ()=> {
                    this.form.id = row.id;
                    this.form.userNo = row.userNo;
                    this.form.userName = row.userName;
                    this.form.password = row.password;
                    this.form.age = row.age +''; //数字转字符,才显示
                    this.form.phone = row.phone;
                    this.form.sex = row.sex + '';
                    this.form.roleId = row.roleId;
                });
            },
            //重置新增表单
            resetForm() {
                this.$refs.form.resetFields();
            },
            doUpdate(){
                this.$axios.post( this.$httpUrl + '/user/update',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '更新成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('更新失败');
                    }
                });
            },
            doSave(){
                this.$axios.post( this.$httpUrl + '/user/save',this.form).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.$message({
                            message: '新增成功',
                            type: 'success'
                        });
                        //关闭对话框
                        this.dialogVisible = false;
                        this.loadPost();
                    }else {
                        this.$message.error('新增失败');
                    }
                });
            },
            //保存数据
            save(){
                //保存之前,先验证
                this.$refs.form.validate((valid) => {
                    //通过验证
                    if (valid) {
                        if(this.form.id){
                            //修改,保存
                            this.doUpdate();
                        }else{
                            //新增,保存
                            this.doSave();
                        }
                    } else {
                        //验证未通过
                        return false;
                    }
                });
            },
            //新增对话框关闭按钮
            handleClose() {
                this.dialogVisible = false;
            },
            //新增按钮
            add(){
                this.dialogVisible = true;
                //打开新增窗口时,将之前的内容清除
                this.$nextTick(() =>{
                    this.resetForm();
                    this.form.id = '';
                });
            },
            //重置按钮
            resetParam(){
                this.userName = '';
                this.sex = '';
                this.loadPost();
            },
            //每页数量发生变化
            handleSizeChange(val) {
                //console.log(`每页 ${val} 条`);
                this.pageNum = 1;
                this.pageSize = val;
                this.loadPost();
            },
            //当前页码发生变化
            handleCurrentChange(val) {
                //console.log(`当前页: ${val}`);
                this.pageNum = val;
                this.loadPost();
            },
            //get方式加载数据
            loadGet(){
                this.$axios.get( this.$httpUrl +'/user/listPage').then (res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        this.tableData = res.data.data;
                    }else {
                        alert('获取数据失败');
                    }
                })
            },
            //post方式加载数据
            loadPost(){
                this.$axios.post( this.$httpUrl + '/user/listPage',{
                    pageSize: this.pageSize,
                    pageNum : this.pageNum,
                    param:{
                        name: this.userName, //查询的名字
                        sex: this.sex,  //查询性别
                        roleId:'1' //角色id
                    }
                }).then(res => {
                    //console.log(res);
                    if(res.data.code ===200)
                    {
                        //列表数据
                        this.tableData = res.data.data;
                        //总记录数
                        this.total = res.data.total;
                    }else {
                        alert('获取数据失败');
                    }
                })
            }
        },
        created(){
            //this.loadGet();
            this.loadPost();
        }
    }
</script>

<style scoped>

</style>

package.json

{
  "name": "storage-web",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^1.4.0",
    "core-js": "^3.8.3",
    "element-ui": "^2.15.13",
    "vue": "^2.6.14",
    "vue-router": "^3.6.5",
    "vuex": "^3.6.2",
    "vuex-persistedstate": "^4.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vue/cli-plugin-babel": "^5.0.0",
    "@vue/cli-plugin-eslint": "^5.0.0",
    "@vue/cli-service": "^5.0.0",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3",
    "vue-template-compiler": "^2.6.14"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "@babel/eslint-parser"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

测试

登录

 

 首页

 管理员管理

 用户管理

 仓库管理

 商品分类管理

 商品管理

 出入库管理

 注销

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虾米大王

有你的支持,我会更有动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值