基于Spring Boot的电脑商城管理系统—商品管理模块
1、pom文件和application.yml配置文件和mvc配置
pom文件
<?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.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--项目信息-->
<groupId>com.chengxu</groupId>
<artifactId>computerMall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>computerMall</name>
<description>Demo project for Spring Boot</description>
<!--jdk版本-->
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--thymeleaf依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!--mysql数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok依赖-->
<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>
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 阿里巴巴数据源启动器-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 热部署依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- java持久化API spring data-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--jquery依赖-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
<!-- bootstrap依赖-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<!-- redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.7.RELEASE</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork><!--必须添加这个配置-->
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件
spring:
#数据源配置
datasource:
#url: jdbc:mysql://localhost:3306/shoppingmall?serverTimezone=UTC
url: jdbc:mysql://localhost:3306/mall?serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
#配置第三方数据源
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
min-idle: 10
max-active: 100
redis:
database: 0 #选择数据库
host: 127.0.0.1 #主机地址
port: 6379 #端口号
password:
jedis:
pool:
max-active: 8 # 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool 的状态为exhausted(耗尽)
max-idle: 10 # 连接池中的最大空闲连接,默认值也是8。
min-idle: 2 # 连接池中的最小空闲连接,默认值也是0。
max-wait: -1 # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接 抛出JedisConnectionException
#配置国际化文件基础名
messages:
basename: i18n.login
jpa:
hibernate: ##数据表生成策略使用hibernate
ddl-auto: update #更新或创建表
show-sql: true #显示SQL语句
#关闭缓存,页面热处理
thymeleaf:
cache: false
#端口号
server:
port: 8080
mybatis:
#开启驼峰命名匹配
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.chengxu.computermall.entity
#用户头像,商品图片的存放位置,可以自定义位置
user:
file:
commodityImages: D:/ideaProject/computerMall/src/main/resources/static/commodityImages/
headPortraitImages: D:/ideaProject/computerMall/src/main/resources/static/headPortraitImages/
MVC配置类MyMvcConfig
package com.chengxu.computermall.config;
/*import com.chengxu.config.LoginHandlerInterceptor;
import com.chengxu.config.LoginHandlerInterceptor;*/
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: 程旭
* @date: 2021/7/5
* MVC扩展
*/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Value("${user.file.commodityImages}")
private String commodityImages;//图片路径
@Value(("${user.file.headPortraitImages}"))
private String headPortraitImages;//头像路径
//添加视图控制器
//ViewControllerRegistry:注册视图控制
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// WebMvcConfigurer.super.addViewControllers(registry);
// 设置重定向
registry.addViewController("/admin/login").setViewName("/admin/adminLogin");
/*registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");*/
registry.addViewController("/login").setViewName("login");
registry.addViewController("/register").setViewName("register");
}
//添加拦截器
//InterceptorRegistry注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//WebMvcConfigurer.super.addInterceptors(registry);
//LoginHandlerInterceptor:注册拦截器处理器
//addPathPatterns("/**"):添加要拦截的路径/**表示拦截所有
//excludePathPatterns:要排除的路径 /webjars/**,/asserts/**这两个是静态资源所在位置,否则无法进行页面渲染
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/admin/**")
.excludePathPatterns("/commodityImages/**","/asserts/**","/webjars/**","/admin/login","/favicon.ico",
"/admin/bg/**","/admin/toLogin","/echarts/**","/headPortraitImages/**","/layui/**","/admin/verifyCode");
registry.addInterceptor(new MemberLoginHandlerInterceptor()).addPathPatterns("/member/**")
.excludePathPatterns("/member/toLogin","/member/index/*","/member/memberOutLogin","/member/memberRegister");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//映射图片保存地址
registry.addResourceHandler("/commodityImages/**").addResourceLocations("file:D:\\ideaProject\\computerMall\\src\\main\\resources\\static\\commodityImages\\");
registry.addResourceHandler("/headPortraitImages/**").addResourceLocations("file:D:\\ideaProject\\computerMall\\src\\main\\resources\\static\\headPortraitImages\\");
}
}
2、实体类
2.1、商品表实体类(Commodity)
创建entity文件夹,用于存放实体类,因为使用了lombok工具,所以不用对实体类中的属性进行封装,省去了get和set方法,pom文件中已经加入了lombok依赖
idea可以在file–>Settings–>Plugins–>搜索lombok,安装插件
使用SpringData注解@Entity,@Table映射数据表
package com.chengxu.computermall.entity;
import com.chengxu.computermall.utils.DateTimeUtils;
import lombok.AllArgsConstructor;
import lombok.Cleanup;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
/**
* @author: 程旭
* @date: 2022/2/13
* 商品表实体类
*/
@Entity//表明此类为实体类
@Table(name = "t_commodity")//对应的数据表
@DynamicUpdate//该注解确保Hibernate只更新实体中修改的列
@Data//封装所有属性,不用再创建get,set方法了。lombok工具的注解
@AllArgsConstructor//全参的构造方法,lombok工具的注解
@NoArgsConstructor//无参的构造方法,lombok工具的注解
public class Commodity {
@Id//主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键自增
private Long commodityId;//编号
@Column
private String commodityPicture;//图片
@Column
private String xiangqing; //详情图
@Column
private String guige;//规格
@Column
private String name;//商品名
@Column
private String kindName;//种类
@Column
private String brandName;//品牌
@Column
private String sellPrice;//售价
@Column
private String inPrice;//进价
@Column
private Long stock;//库存
@Column
private String createDate= DateTimeUtils.getStrDate();//创建日期
@Column
private String isPutaway="off";//是否上架,默认下架
@Column
private String description;//商品描述
}
2.2 商品种类实体(Kind)
package com.chengxu.computermall.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author: 程旭
* @date: 2022/2/18
* 商品类型
*/
@Entity
@Table(name = "t_kind")
@DynamicUpdate//该注解确保Hibernate只更新实体中修改的列
@Data//封装所有属性,不用再创建get,set方法了。lombok工具的注解
@AllArgsConstructor//全参的构造方法,lombok工具的注解
@NoArgsConstructor//无参的构造方法,lombok工具的注解
public class Kind implements Serializable {
@Id//主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增
private Long kindId;//种类id
@Column
private Long fatherId;//父id
@Column
private String kindName;//种类名
@Column
private String leaf;
@Column
private String delstatus;
}
2.3商品库存(Sku)
package com.chengxu.computermall.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
/**
* @author: 程旭
* @date: 2022/4/26
* 库存
*/
@Entity//表明此类为实体类
@Table(name = "t_sku")//对应的数据表
@DynamicUpdate
@Data//封装所有属性,不用再创建get,set方法了。lombok工具的注解
@AllArgsConstructor//全参的构造方法,lombok工具的注解
@NoArgsConstructor//无参的构造方法,lombok工具的注解
public class Sku {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long skuId;
@Column
private Long commodityId;//商品编号
@Column
private Double skuSellPrice;//售价
@Column
private Double skuInPrice;//进价
@Column
private Long skuStock;//库存
@Column
private String skuName;
}
3、数据访问层
这里使用了Mybatis和SpringData两种框架结合,也可以使用MyBatispuls,SpringData封装了基础的数据操作的CRUD方法不用再手动去写了,但是有些复杂的数据操作还是要手动写sql,SpringData的底层是用的hibernate,我只学了Mybatis所以手动写sql还是用的MybatisO(∩_∩)O
3.1、CommotityMapper 商品接口
package com.chengxu.computermall.mapper;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.model.PageResult;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* @author: 程旭
* @date: 2021/6/21
* 商品
*/
@Mapper
public interface CommotityMapper {
/**
* 分页排序查询
*
* @return
*/
// @Select("SELECT * from t_commodity order by commodity_id ASC limit #{pageNum},#{pageSize};")
public List<Commodity> findAllCommodity(Map<String ,Object> param);
@Select("select * from t_commodity where is_putaway='on' order by commodity_id desc")
public List<Commodity> findAllDesc();
/**
* 计数
* @return
*/
//@Select("SELECT count(commodity_id) from t_commodity")
public int findCommodityCount(Map<String ,Object> param);
/**
* 商品是否存在
* @param name
* @return
*/
@Select("select count(*) from t_commodity where name=#{name}")
public int findCommodityIsExist(String name);
//查询根据种类,品牌,商品名查询
public List<Commodity> findCommodityByKindAndBrandAndName();
/**
* 插入
* @param commodity
* @return
*/
public Long insertCommodity(Commodity commodity);
}
commoditymapper映射文件
代码:
<?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.chengxu.computermall.mapper.CommotityMapper">
<!-- sql片段-->
<sql id="search_where">
<where>
<if test="commodity.brandName!=null and commodity.brandName!='' ">
brand_name like '%${commodity.brandName}%'
</if>
<if test=" commodity.kindName!=null and commodity.kindName!=''">
and kind_name like '%${commodity.kindName}%'
</if>
<if test="commodity.name!=null and commodity.name!=''">
and name like '%${commodity.name}%'
</if>
</where>
</sql>
<!-- 插入-->
<insert id="insertCommodity" parameterType="Commodity" useGeneratedKeys="true" keyProperty="commodityId">
INSERT INTO t_commodity(commodity_picture,create_date,in_price,is_putaway,name,sell_price,stock,description,brand_name,kind_name,guige,xiangqing)
VALUES(#{commodityPicture},#{createDate},#{inPrice},#{isPutaway},#{name},#{sellPrice},#{stock},#{description},#{brandName},#{kindName},#{guige},#{xiangqing});
</insert>
<select id="findCommodityCount" parameterType="map" resultType="int">
select count(*) from t_commodity
<include refid="search_where"></include>
</select>
<!-- 查询所有-->
<select id="findAllCommodity" parameterType="map" resultType="commodity">
select *
from t_commodity
<include refid="search_where"></include>
order by commodity_id desc limit #{start},#{pageSize};
</select>
<select id="findCommodityByKindAndBrandAndName" resultType="com.chengxu.computermall.entity.Commodity"></select>
</mapper>
springdata访问层接口放在repository文件夹
package com.chengxu.computermall.repository;
import com.chengxu.computermall.entity.Commodity;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/2/15
* 商品的Jpa仓库
*/
@Repository
public interface CommodityRepository extends JpaRepository<Commodity,Long> {
//根据商品名查询
public List<Commodity> findByName(String name);
public List<Commodity> findByBrandNameContains(String name);
//根据商品id查询
public Commodity findByCommodityId(Long commodityId);
//根据id删除,批量删除
@Modifying
@Transactional
@Query("delete from Commodity s where s.commodityId in (:ids) ")
void deleteCommodityById(@Param("ids") List<Long> ids);
public List<Commodity> findByKindNameAndBrandName(String kindName,String brandName);
}
3.2商品种类接口KindMapper和KindRepository和KindMapper.xml
package com.chengxu.computermall.mapper;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.entity.Kind;
import com.chengxu.computermall.model.PageResult;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* @author: 程旭
* @date: 2022/2/22
*/
@Mapper
public interface KindMapper {
public List<Kind> findAll(Map<String ,Object> param);
@Select("select * from t_kind where kind_name=#{kindName}")
public Kind findByKindName(String kindName);
public int findKindCount(Map<String, Object> param);
public List<Kind> findAllKindChild(Map<String, Object> param);
}
package com.chengxu.computermall.repository;
import com.chengxu.computermall.entity.Kind;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/2/19
* 商品种类接口jps仓库
*/
@Repository
public interface KindRepository extends JpaRepository<Kind,Long> {
//没有父id的
public List<Kind> findByFatherIdIsNull();
//根据父id查询
public List<Kind> findByFatherId(Long fatherId);
public Kind findByKindId(Long kindId);
public List<Kind> findByKindName(String kindName);
public List<Kind> findByKindNameAndAndFatherId(String kindName,Long fatherId);
//查询子类
public List<Kind> findByFatherIdIsNotNull();
}
<?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.chengxu.computermall.mapper.KindMapper">
<sql id="search_where">
<where>
<if test="kind.fatherId!=null ">
father_id = '${kind.fatherId}'
</if>
<if test="kind.fatherId==null ">
father_id is null
</if>
</where>
</sql>
<select id="findKindCount" parameterType="map" resultType="int">
select count(*) from t_kind
<include refid="search_where"></include>
</select>
<!-- 查询所有-->
<select id="findAll" parameterType="map" resultType="kind">
select *
from t_kind
<include refid="search_where"></include>
limit #{start},#{pageSize};
</select>
<select id="findAllKindChild" parameterType="map" resultType="kind">
select *
from t_kind
<include refid="search_where"></include>
limit #{start},#{pageSize};
</select>
</mapper>
3.3商品库存接口SkuRepository
package com.chengxu.computermall.repository;
import com.chengxu.computermall.entity.Sku;
import org.apache.catalina.LifecycleState;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/4/29
*/
@Repository
public interface SkuRepository extends JpaRepository<Sku,Long> {
//根据id查询
public Sku findBySkuId(Long id);
//根据商品id查询规格
public List<Sku> findByCommodityId(Long commodityId);
@Modifying
@Transactional
@Query("delete from Sku s where s.commodityId =:ids ")
void deleteSkuByCommodityId(@Param("ids") Long ids);
@Modifying
@Transactional
@Query("delete from Sku s where s.commodityId in (:ids) ")
void deleteSkuById(@Param("ids") List<Long> ids);
}
4、业务层接口(service层)
** 4.1、CommodityService接口代码:**
package com.chengxu.computermall.service;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.model.PageResult;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/2/15
* 商品接口
*/
public interface CommodityService {
//分页查询
public PageResult<Commodity> findAllCommodity(Commodity commodity,int pageNum, int pageSize);
//查询商品是否存在
public int findCommodityIsExist(String name);
//根据名称查询商品
public List<Commodity> findCommodityByName(String name);
//保存商品
public void save(Commodity commodity);
//插入
public Long insert(Commodity commodity);
//根据id查询商品
public Commodity findByCommodityId(Long commodityId);
//根据id删除商品
public void deleteCommodityById(Long commodityId);
//批量删除
public void deleAllById(List<Long> commodityIds);
}
编写接口实现类之前,可以先自定义一个数据模板,用于封装查询到的数据
创建model文件夹,用于存放数据模板
PageResult类查询结果分页模板
package com.chengxu.computermall.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/2/15
* 表格数据的结果模板
*/
@Data//get,set方法
@AllArgsConstructor//全参的构造函数
@NoArgsConstructor//无参的构造函数
public class PageResult<T> {
private int code;//0表示成功,1表示失败
private String msg;//错误信息
private int count;//总记录数:3000000
private List<T> data;//数据
}
实现类CommodityServiceImpl
package com.chengxu.computermall.serviceImpl;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.mapper.CommotityMapper;
import com.chengxu.computermall.model.PageResult;
import com.chengxu.computermall.repository.CommodityRepository;
import com.chengxu.computermall.service.CommodityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: 程旭
* @date: 2022/2/16
*/
@Service
public class CommodityServiceImpl implements CommodityService {
@Autowired
private CommodityRepository commodityRepository;
@Autowired
private CommotityMapper commotityMapper;
/**
* 分页查询
* @param pageNum:当前页
* @param pageSize:每页多少数据
* @return
*/
@Override
public PageResult<Commodity> findAllCommodity(Commodity commodity,int pageNum, int pageSize){
/* //排序规则:按照id升序
Sort.Order order=new Sort.Order(Sort.Direction.ASC,"commodityId");
Sort sort=Sort.by(order);
//创建分页规则
Pageable pageable= PageRequest.of(pageNum,pageSize,sort);
//查询所有商品
Page<Commodity> list = commodityRepository.findAll(pageable);*/
//通过getContent()方法将Page对象转为list对象
Map<String ,Object> param=new HashMap<>();
param.put("commodity",commodity);
param.put("start",(pageNum-1)*pageSize);
param.put("pageSize",pageSize);
List<Commodity> list=commotityMapper.findAllCommodity( param);
int count=commotityMapper.findCommodityCount(param);
PageResult<Commodity> commodityPageResult=new PageResult<Commodity>(0,"",count,list);
return commodityPageResult;
}
/**
* 查询商品名是否存在
* @param name
* @return
*/
@Override
public int findCommodityIsExist(String name) {
return commotityMapper.findCommodityIsExist(name);
}
@Override
public List<Commodity> findCommodityByName(String name) {
//根据名称查询
List<Commodity> commodityList=commodityRepository.findByName(name);
return commodityList;
}
/**
* 保存商品
* @param commodity
*/
@Override
public void save(Commodity commodity) {
commodityRepository.save(commodity);
}
/**
* 插入
* @param commodity
* @return 返回id
*/
@Override
public Long insert(Commodity commodity) {
//插入或会将id放入comodity对象
commotityMapper.insertCommodity(commodity);
//通过get方法获取id
long id =commodity.getCommodityId();
return id;
}
/**
* 根据商品id查询
* @param commodityId
* @return
*/
@Override
public Commodity findByCommodityId(Long commodityId) {
return commodityRepository.findByCommodityId(commodityId);
}
/**
* 商品根据id删除
* @param commodityId
*/
@Override
public void deleteCommodityById(Long commodityId) {
//删除
commodityRepository.deleteById(commodityId);
}
@Transactional
@Override
public void deleAllById(List<Long> commodityIds) {
commodityRepository.deleteCommodityById(commodityIds);
}
}
4.2、KindService接口与实现类
package com.chengxu.computermall.service;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.entity.Kind;
import com.chengxu.computermall.model.PageResult;
import java.util.List;
/**
* @author: 程旭
* @date: 2022/2/19
* 种类接口
*/
public interface KindService {
//查询种类
public List<Kind> findFatherIdByIsNull();
//根据父id查询品牌
public List<Kind> findBrandByFatherId(Long fatherId);
//根据id查询
public Kind findbyId(Long kindId);
public List<Kind> findByKindName(String kindName);
public Kind findByKindNameOne(String kindName);
public void save(Kind kind);
//分页查询
public PageResult<Kind> findAllKind(Kind kind, int pageNum, int pageSize);
public void deleKindById(Long kindId);
public void deleAllById(List<Long> delList);
public PageResult<Kind> findAllKindChild(Kind kind, int page, int limit, Long fatherId);
public List<Kind> findByKindNameAndFatherId(String kindName, Long fatherId);
}
package com.chengxu.computermall.serviceImpl;
import com.chengxu.computermall.entity.Kind;
import com.chengxu.computermall.mapper.KindMapper;
import com.chengxu.computermall.model.PageResult;
import com.chengxu.computermall.repository.KindRepository;
import com.chengxu.computermall.service.KindService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: 程旭
* @date: 2022/2/19
* 商品种类实现类
*/
@Service
public class KindServiceImpl implements KindService {
@Autowired
private KindRepository kindRepository;
@Autowired
private KindMapper kindMapper;
@Override
public List<Kind> findFatherIdByIsNull() {
List<Kind> kindList= kindRepository.findByFatherIdIsNull();
return kindList;
}
/**
* 根据父id查询
* @param fatherId
* @return
*/
@Override
public List<Kind> findBrandByFatherId(Long fatherId) {
List<Kind> kindList=kindRepository.findByFatherId(fatherId);
return kindList;
}
//根据id查询
@Override
public Kind findbyId(Long kindId) {
Kind kind=kindRepository.findByKindId(kindId);
return kind;
}
// 根据名称查询
@Override
public List<Kind> findByKindName(String kindName) {
List<Kind> kind=kindRepository.findByKindName(kindName);
return kind;
}
@Override
public Kind findByKindNameOne(String kindName) {
Kind kind=kindMapper.findByKindName(kindName);
return kind;
}
@Override
public void save(Kind kind) {
kindRepository.save(kind);
}
/**
* 分页查询
* @param pageNum:当前页
* @param pageSize:每页多少数据
* @return
*/
@Override
public PageResult<Kind> findAllKind(Kind kind,int pageNum, int pageSize){
//通过getContent()方法将Page对象转为list对象
Map<String ,Object> param=new HashMap<>();
param.put("kind",kind);
param.put("start",(pageNum-1)*pageSize);
param.put("pageSize",pageSize);
List<Kind> list=kindMapper.findAll( param);
int count=kindMapper.findKindCount(param);
PageResult<Kind> kindPageResult=new PageResult<Kind>(0,"",count,list);
return kindPageResult;
}
@Override
public void deleKindById(Long kindId) {
kindRepository.deleteById(kindId);
}
@Override
public void deleAllById(List<Long> delList) {
kindRepository.deleteAllByIdInBatch(delList);
}
@Override
public PageResult<Kind> findAllKindChild(Kind kind, int pageNum, int pageSize, Long fatherId) {
//通过getContent()方法将Page对象转为list对象
Map<String ,Object> param=new HashMap<>();
kind.setFatherId(fatherId);
param.put("kind",kind);
param.put("start",(pageNum-1)*pageSize);
param.put("pageSize",pageSize);
param.put("fatherId",fatherId);
List<Kind> list=kindMapper.findAllKindChild( param);
int count=kindMapper.findKindCount(param);
PageResult<Kind> kindPageResult=new PageResult<Kind>(0,"",count,list);
return kindPageResult;
}
@Override
public List<Kind> findByKindNameAndFatherId(String kindName, Long fatherId) {
List<Kind> kindList=kindRepository.findByKindNameAndAndFatherId(kindName,fatherId);
return kindList;
}
}
5、Controller层
package com.chengxu.computermall.controller.admin.commodity;
import com.chengxu.computermall.entity.Commodity;
import com.chengxu.computermall.entity.Kind;
import com.chengxu.computermall.entity.Sku;
import com.chengxu.computermall.model.PageResult;
import com.chengxu.computermall.repository.SkuRepository;
import com.chengxu.computermall.service.CommodityService;
import com.chengxu.computermall.service.KindService;
import com.chengxu.computermall.utils.LoggerUtil;
import com.chengxu.computermall.utils.UpaloadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author: 程旭
* @date: 2022/2/15
* 管理商品的控制器
*/
@Controller
public class CommodityListController {
@Autowired
private CommodityService commodityService;
@Autowired
private KindService kindService;
@Value("${user.file.commodityImages}")
private String uploadPath;
@Autowired
private SkuRepository skuRepository;
/**
* 跳转到商品列表
* @return:要跳转的页面所在路径
*/
@GetMapping("/admin/commodityList")
public String commodityList(Model model){
List<Kind> kindList= kindService.findFatherIdByIsNull();
model.addAttribute("kindList",kindList);
return "admin/commodity/commodityList";
}
/**
* 获取商品表格数据
* @return
* page:layui表格自动携带参数,从1开始
* limit:layui表格自动携带的参数,每页的数据量
*/
@GetMapping("/admin/commodityData")
@ResponseBody
public PageResult<Commodity> commodityData(Commodity commodity,int page,int limit){
// System.out.println(commodity.getBrandName()+commodity.getKindName()+commodity.getName());
Long kindId=null;
Long brandId=null;
if (commodity.getKindName()!=null&&!"".equals(commodity.getKindName())){
kindId=Long.parseLong(commodity.getKindName());
}
if (commodity.getBrandName()!=null&&!"".equals(commodity.getBrandName())){
brandId=Long.parseLong(commodity.getBrandName());
}
Kind kind=kindService.findbyId(kindId);
//查询品牌名
Kind brand=kindService.findbyId(brandId);
if (kind!=null){
commodity.setKindName(kind.getKindName());
}else {
commodity.setKindName("");
}
if (brand!=null){
commodity.setBrandName(brand.getKindName());
}else {
commodity.setBrandName("");
}
//Pageable对象的PageRequest.of(pageNum,pageSize,sort);方法的pageNum是从0开始
PageResult<Commodity> result=commodityService.findAllCommodity(commodity,page,limit);
return result;
}
/**
* 跳转到添加商品页面
* @return
*/
@GetMapping("/admin/commodityAdd")
public String commodityAdd(Model model){
List<Kind> kindList= kindService.findFatherIdByIsNull();
model.addAttribute("kindList",kindList);
return "admin/commodity/commodityAdd";
}
/**
* 商品添加
* @param commodity
* @param kindId
* @param brandId
* @param skuName
* @param sellPrice
* @param inPrice
* @param stock
* @return
*/
@PostMapping("/admin/commodityAdd")
@ResponseBody//返回请求,不是跳转页面
public Map commodityAdd(Commodity commodity, Long kindId, Long brandId,
@RequestParam("skuName") String[] skuName,
@RequestParam("skuSellPrice") Double[] sellPrice,
@RequestParam("skuInPrice") Double[] inPrice,
@RequestParam("skuStock")Long[] stock){
String maxSellPrice;//最大售价
String minSellPrice;//最小售价
String maxInPrice;//最大进价
String minInPrice;//最小进价
Long sumStock;//总库存
//数组转列表
List<Long> stocklist=Arrays.asList(stock);
//列表转对象
LongSummaryStatistics stats = stocklist.stream().mapToLong((x) -> x).summaryStatistics();
//调用方法
maxSellPrice=String.valueOf((double)Collections.max(Arrays.asList(sellPrice)));
minSellPrice=String.valueOf((double)Collections.min(Arrays.asList(sellPrice)));
maxInPrice=String.valueOf((double)Collections.max(Arrays.asList(inPrice)));
minInPrice=String.valueOf((double)Collections.min(Arrays.asList(inPrice)));
sumStock=stats.getSum();
System.out.println(maxSellPrice+minSellPrice+maxInPrice+minInPrice+sumStock);
Map<String,Object>map =new HashMap<>();
//查询种类名
if (commodity.getName()==null||"".equals(commodity.getName())){
map.put("msg",2);//商品不能为空
return map;
}
kindId=Long.parseLong(commodity.getKindName());
brandId=Long.parseLong(commodity.getBrandName());
Kind kind=kindService.findbyId(kindId);
//查询品牌名
Kind brand=kindService.findbyId(brandId);
commodity.setBrandName(brand.getKindName());
commodity.setKindName(kind.getKindName());
//去除商品中的空格
String name=commodity.getName().replace(" ","");
//根据商品名判断商品是否存在
int i=commodityService.findCommodityIsExist(name);
if (i>0){//商品存在返回
map.put("msg",1);//1表示失败
return map;
}else if (name==null||"".equals(name)){
map.put("msg",2);//商品不能为空
return map;
}else {
// commodityService.save(commodity);
commodity.setInPrice(minInPrice+'~'+maxInPrice);//进价
commodity.setSellPrice(minSellPrice+'~'+maxSellPrice);
commodity.setStock(sumStock);
//插入数据后返回商品id
Long commodityId=commodityService.insert(commodity);
for (int j = 0; j < skuName.length; j++) {
Sku sku=new Sku();//创建规格对象
sku.setCommodityId(commodityId);//商品id
sku.setSkuSellPrice(sellPrice[j]);//售价
sku.setSkuName(skuName[j]);//规格名
sku.setSkuStock(stock[j]);//库存
sku.setSkuInPrice(inPrice[j]);//进价
//保存
skuRepository.save(sku);
}
}
map.put("msg",0);//0表示成功
return map;//map会被自动解析为json格式
}
/**
* 商品图片上传
*/
@ResponseBody
@PostMapping( "admin/commodityUploadFile")
public Map<String, Object> uploadFile(HttpServletRequest servletRequest, @RequestParam("file") MultipartFile file)
throws IOException {
Map<String, Object> res = new HashMap<>();
// 如果文件内容不为空,则写入上传路径
/*if (!file.isEmpty()) {
// 上传文件路径
String UploadPath = uploadPath;
//取得原文件名字
String fileName = file.getOriginalFilename();
//取得文件扩展名
String suffix = fileName.substring(fileName.lastIndexOf("."));
//提取系统时间作为新文件名
String prefix = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime());
//保存路径
// 上传文件名
String filename = prefix+suffix;
//创建文件
File filepath = new File(UploadPath, filename);
// 判断路径是否存在,没有创建
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 将上传文件保存到一个目标文档中
File file1 = new File(UploadPath + File.separator + filename);
file.transferTo(file1);
// 返回的是一个url对象,图片名称
res.put("url", filename);
return res;
} else {
res.put("url","");
return res;
}*/
String filename;//文件名
//调用上传文件方法
filename= UpaloadUtils.uploadPicture(uploadPath,file);
res.put("url", filename);
return res;
}
/**
* 商品查看
*/
@GetMapping("/admin/commodityLook/{commodityId}")
public String commodityLook(@PathVariable("commodityId") Long commodityId,Model model){
//根据id查询商品
Commodity commodity=commodityService.findByCommodityId(commodityId);
if (commodity.getXiangqing()!=null&&!"".equals(commodity.getXiangqing())){
//将详情图片的地址转换为数组
String[] xiangqing=commodity.getXiangqing().split(",");
//去除数组中的空值,并将数据加入列表
List<String > list= Arrays.stream(xiangqing).filter(s -> !"".equals(s)).collect(Collectors.toList());
model.addAttribute("xiangqingList",list);
}else {
model.addAttribute("xiangqingList",null);
}
//根据商品id查询规格
List<Sku> skuList=skuRepository.findByCommodityId(commodityId);
model.addAttribute("skuList",skuList);
//将商品存放到model对象
model.addAttribute("commodity",commodity);
return "admin/commodity/commodityLook";
}
/**
* 根据商品id删除
*/
@DeleteMapping("/admin/commodityDelete/{commodityId}")
@ResponseBody
public Map commodityDelete(@PathVariable("commodityId")Long commodityId){
Map<String,Object> map=new HashMap<>();
//调用删除方法
commodityService.deleteCommodityById(commodityId);
//同时删除对应的sku
skuRepository.deleteSkuByCommodityId(commodityId);
//返回信息
map.put("msg",0);
return map;
}
//批量删除
@PostMapping("/admin/commodityDelAll")
@ResponseBody
public Map commodityDelAll(String commodityId){
Map<String,Object>map=new HashMap<>();
List<Long> delList = new ArrayList<>();
String[] strs = commodityId.split(",");
System.out.println(strs);
for (String str : strs) {
delList.add(Long.parseLong(str));
}
LoggerUtil.info(delList.toString());
//同时删除对应的规格
skuRepository.deleteSkuById(delList);
commodityService.deleAllById(delList);//删除所有
map.put("msg",0);
return map;
}
/**
* 前往编辑页面
* @return
* commodityId:商品id
*/
@GetMapping("/admin/commodityEdit")
public String commodityEdit(Long commodityId,Model model){
//根据id查询
Commodity commodity=commodityService.findByCommodityId(commodityId);
//存入model对象
model.addAttribute("commodity",commodity);
//查新类别
Kind kind=kindService.findByKindNameOne(commodity.getKindName());
//查询所有种类
List<Kind> kindList= kindService.findFatherIdByIsNull();
//该种类下所有品牌
List<Kind> brandList=null;
if (kind!=null){
brandList=kindService.findBrandByFatherId(kind.getKindId());
}
if (commodity.getXiangqing()!=null&&!"".equals(commodity.getXiangqing())){
//将详情图片的地址转换为数组
String[] xiangqing=commodity.getXiangqing().split(",");
//去除数组中的空值,并将数据加入列表
List<String > list= Arrays.stream(xiangqing).filter(s -> !"".equals(s)).collect(Collectors.toList());
model.addAttribute("xiangqingList",list);
}else {
model.addAttribute("xiangqingList",null);
}
//根据商品id查询规格
List<Sku> skuList=skuRepository.findByCommodityId(commodityId);
model.addAttribute("skuList",skuList);
model.addAttribute("kindList",kindList);
model.addAttribute("brandList",brandList);
//跳转编辑页面
return "admin/commodity/commodityEdit";
}
/**
* 保存编辑后的信息
* @param commodity
* @return
*/
@PostMapping("/admin/commodityEdit")
@ResponseBody//返回请求,不是跳转页面
public Map commodityEdit(Commodity commodity,Long kindId,Long brandId,
@RequestParam("skuId") Long[] skuId,
@RequestParam("skuName")String[] skuName,
@RequestParam("skuSellPrice")Double[] skuSellPrice,
@RequestParam("skuInPrice")Double[] skuInPrice,
@RequestParam("skuStock")Long[] skuStock){
String maxSellPrice;//最大售价
String minSellPrice;//最小售价
String maxInPrice;//最大进价
String minInPrice;//最小进价
Long sumStock;//总库存
//数组转列表
List<Long> stocklist=Arrays.asList(skuStock);
//列表转对象
LongSummaryStatistics stats = stocklist.stream().mapToLong((x) -> x).summaryStatistics();
//调用方法
maxSellPrice=String.valueOf((double)Collections.max(Arrays.asList(skuSellPrice)));
minSellPrice=String.valueOf((double)Collections.min(Arrays.asList(skuSellPrice)));
maxInPrice=String.valueOf((double)Collections.max(Arrays.asList(skuInPrice)));
minInPrice=String.valueOf((double)Collections.min(Arrays.asList(skuInPrice)));
sumStock=stats.getSum();
//查询种类名
kindId=Long.parseLong(commodity.getKindName());
brandId=Long.parseLong(commodity.getBrandName());
Kind kind=kindService.findbyId(kindId);
//查询品牌名
Kind brand=kindService.findbyId(brandId);
Map<String,Object>map =new HashMap<>();
commodity.setBrandName(brand.getKindName());
commodity.setKindName(kind.getKindName());
//去除商品中的空格
String name=commodity.getName().replaceAll(" ","");
if ("".equals(name)||name==null){
map.put("msg",2);//2表示商品存在
return map;
}
List<Commodity> commodityList=commodityService.findCommodityByName(commodity.getName());
if (commodityList.size()>1){//如果商品名有两个,则商品重复
map.put("msg",1);//0表示成功,1表示已存在
return map;//map会被自动解析为json格式
}else if (commodityList.size()==1){//如果商品名有了
Commodity commodity1=commodityList.get(0);
if (commodity1.getCommodityId()==commodity.getCommodityId()){//并且已经存在的商品和现在修改的商品id相同
//保存信息
commodity.setInPrice(minInPrice+'~'+maxInPrice);//进价
commodity.setSellPrice(minSellPrice+'~'+maxSellPrice);
commodity.setStock(sumStock);
commodityService.save(commodity);
//保存规格
for (int j = 0; j < skuId.length; j++) {
if (skuId[j]!=-1){
Sku sku=new Sku();//创建规格对象
sku.setSkuId(skuId[j]);
sku.setCommodityId(commodity.getCommodityId());//商品id
sku.setSkuSellPrice(skuSellPrice[j]);//售价
sku.setSkuName(skuName[j]);//规格名
sku.setSkuStock(skuStock[j]);//库存
sku.setSkuInPrice(skuInPrice[j]);//进价
skuRepository.save(sku);
}else if (skuId[j]==-1){
Sku sku=new Sku();//创建规格对象
sku.setCommodityId(commodity.getCommodityId());//商品id
sku.setSkuSellPrice(skuSellPrice[j]);//售价
sku.setSkuName(skuName[j]);//规格名
sku.setSkuStock(skuStock[j]);//库存
sku.setSkuInPrice(skuInPrice[j]);//进价
skuRepository.save(sku);
}
}
map.put("msg",0);//0表示成功
return map;//map会被自动解析为json格式
}else {//已有商品和正在编辑商品不是同一个商品
map.put("msg",1);//0表示成功,1表示已存在
return map;//map会被自动解析为json格式
}
}else {
//保存信息
commodity.setInPrice(minInPrice+'~'+maxInPrice);//进价
commodity.setSellPrice(minSellPrice+'~'+maxSellPrice);
commodity.setStock(sumStock);
commodityService.save(commodity);
//保存规格
for (int j = 0; j < skuId.length; j++) {
if (skuId[j]!=-1){
Sku sku=new Sku();//创建规格对象
sku.setSkuId(skuId[j]);
sku.setCommodityId(commodity.getCommodityId());//商品id
sku.setSkuSellPrice(skuSellPrice[j]);//售价
sku.setSkuName(skuName[j]);//规格名
sku.setSkuStock(skuStock[j]);//库存
sku.setSkuInPrice(skuInPrice[j]);//进价
skuRepository.save(sku);
}else if (skuId[j]==-1){
Sku sku=new Sku();//创建规格对象
sku.setCommodityId(commodity.getCommodityId());//商品id
sku.setSkuSellPrice(skuSellPrice[j]);//售价
sku.setSkuName(skuName[j]);//规格名
sku.setSkuStock(skuStock[j]);//库存
sku.setSkuInPrice(skuInPrice[j]);//进价
skuRepository.save(sku);
}
//保存
}
map.put("msg",0);//0表示成功
return map;//map会被自动解析为json格式
}
}
}
6、前端页面显示
在resources文件夹下创建templates文件夹,用于存放前端页面
在resources下的static文件夹放入layui的文件
商品列表页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>商城后台管理系统</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
<script>
//JS
layui.use(['element', 'layer', 'util'], function () {
var element = layui.element
, layer = layui.layer
, util = layui.util
, $ = layui.$;
//头部事件
util.event('lay-header-event', {
//左侧菜单事件
menuLeft: function (othis) {
layer.msg('展开左侧菜单的操作', {icon: 0});
}
, menuRight: function () {
layer.open({
type: 1
, title: '更多'
, content: '<div style="padding: 15px;">处理右侧面板的操作</div>'
, area: ['260px', '100%']
, offset: 'rt' //右上角
, anim: 5
, shadeClose: true
, scrollbar: false
});
}
});
});
</script>
<style>
/* 移动端 */
@media screen and (max-width: 768px) {
.layui-layout-admin .layui-layout-left,
.layui-layout-admin .layui-body,
.layui-layout-admin .layui-footer {
left: 0;
}
.layui-layout-admin .layui-side {
left: -300px;
}
}
.layui-table-cell {
height: auto;
line-height: 28px;
}
</style>
<style>
.layui-input{
border: #122b40 2px solid;
}
</style>
</head>
<body style="background-color: #e8e8e8">
<form class="layui-form" action="" id="commodityForm" style="margin-top: 10px;margin-left: 15px;">
<div class="layui-form-item">
<div class="layui-input-inline">
<select name="kindId" id="kindId" lay-filter="classify">
<option value="" selected="">请选择类型</option>
<option th:if="${kindList}!=null" th:each="kind:${kindList}" th:value="${kind.getKindId()}"
th:text="${kind.getKindName()}"></option>
</select>
</div>
<div class="layui-input-inline" id="brand">
<select name="brandId"id="brandId">
<option value="">请选品牌</option>
</select>
</div>
<div class="layui-input-inline">
<input type="text" id="name" name="name" placeholder="请输入商品名" class="layui-input">
</div>
<div class="layui-input-inline">
<button type="button" onclick="doSearch()" class="layui-btn" lay-submit="" lay-filter="demo1">搜索
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<table class="layui-hide" id="test" lay-filter="test"></table>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<!-- <button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>-->
<button class="layui-btn layui-btn-sm" lay-event="getCheckLength">获取选中数目</button>
<!-- <button class="layui-btn layui-btn-sm" lay-event="isAll">验证是否全选</button>-->
<button class="layui-btn layui-btn-sm" lay-event="add">添加商品</button>
<button class="layui-btn layui-btn-sm" lay-event="delAll">批量删除</button>
</div>
</script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
<script>
var $form;
var $;
var table;
layui.use(['table','jquery','form', 'layer','laydate'], function () {//加载表格模块
$ = layui.jquery;
$form = $('form');
var form = layui.form,
laydate = layui.laydate,
layer = layui.layer;
table = layui.table;//获取内置的table对象
form.on('select(classify)',function (data) {
//监听到了下拉框选择的选项,传递过来
// console.log(data);//在控制台输出信息
var fatherId = data.value;
// console.log(classfies);
//再利用ajax将数据传到后端,来获取到对应下拉框选项而出现的值
$.ajax({
type:"post",
url:"/admin/commodityBrand",//前往获取商品的品牌
data:{"fatherId":fatherId},
dataType:"json",
success:function (data) {
//console.log(data.brandList)
//对应的值传回,拼出html下拉框语句
var tmp='<option value="">请选择品牌</option>';
for (var d=0; d<data.brandList.length;d++){
console.log(data.brandList[d].kindName)
tmp +='<option value="'+data.brandList[d].kindId+'">'+data.brandList[d].kindName+'</option>';
}
$("#brandId").html(tmp);
form.render();
},error:function () {
layer.alert('请求失败');
}
});
})
table.render({//进行表格渲染
elem: '#test'//要渲染的表格id
, url: '/admin/commodityData'
, toolbar: '#toolbarDemo'//表格的工具条
, title: '商品数据表'
, totalRow: false//合计关闭
,id:'commodityTable'
, cols: [//
[
{type: 'checkbox'}
, {field: 'commodityId', title: 'ID', sort: true,}
, {
field: 'commodityPicture', title: '商品图片', templet: function (d) {
return '<div><img src="/commodityImages/' + d.commodityPicture + '"' +
'></div>'
}
}
, {field: 'name', title: '商品名', align: 'center'}
, {field: 'kindName', title: '类型', width: 80, align: 'center'}
, {field: 'brandName', title: '品牌', width: 80, align: 'center'}
, {field: 'sellPrice', title: '售价', width: 80, align: 'center', sort: true, totalRow: false}
, {field: 'inPrice', title: '进价', width: 80, align: 'center', sort: true, totalRow: false}
, {field: 'stock', title: '库存', width: 80, align: 'center', sort: true, totalRow: false}
, {field: 'createDate', title: '日期', align: 'center'}
, {field: 'isPutaway', title: '状态', width: 80, align: 'center'}
, {field: 'description', title: '描述',}
, {title: '操作', toolbar: '#barDemo',}
]
]
//,page: true//是否分页
//设置分页属性
, page: {
layout: ['prev', 'page', 'next', 'count', 'limit', 'refresh', 'skip']//自定义布局顺序
, limit: 10 //初始 每页几条数据
, limits: [10, 20, 30, 40, 50, 80, 100] //可以选择的 每页几条数据
, groups: 10 //最多几个跳页按钮
, first: true //不显示首页
, last: true //不显示尾页
}
});
//工具栏事件
table.on('toolbar(test)', function (obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'getCheckData':
var data = checkStatus.data;
layer.alert(JSON.stringify(data));
break;
case 'getCheckLength':
var data = checkStatus.data;
layer.msg('选中了:' + data.length + ' 个');
break;
case 'isAll':
layer.msg(checkStatus.isAll ? '全选' : '未全选')
break;
case 'add':
parent.layer.open({
type: 2,//2表示跳转页面
offset: 'auto',
title: '添加商品',
content: '/admin/commodityAdd',//页面路径
area: ['1000px', '600px'],//宽高
btn: '关闭全部',
btnAlign: 'c',
yes: function () {
table.reload('test');
parent.layer.closeAll()
}
})
break;
case 'delAll':
var data = checkStatus.data;
console.log("sss"+JSON.stringify(data))
let commodityId = "";
if (data.length > 0) {
for (var i in data) {
commodityId += data[i].commodityId + ",";
}
console.log(commodityId);
layer.confirm('确定删除选中的商品?', {icon: 3, title: '提示信息'}, function (index) {
$.ajax({
url:'/admin/commodityDelAll',
data:{"commodityId":commodityId},
type:'post',
dataType: 'json',
success:function (data){
if (data.msg==0){
layer.alert("删除成功",function (){
window.location.reload();
})
}
},
error:function (){
}
})
})
} else {
layer.msg("请选择需要删除的商品");
}
};
});
//触发行双击事件
table.on('rowDouble(test)', function (obj) {
parent.layer.open({
type: 2,//2表示跳转页面
offset: 'auto',
title: '商品查看',
content: '/admin/commodityLook/' + obj.data.commodityId,//页面路径
area: ['1000px', '600px'],//宽高
btn: '关闭全部',
btnAlign: 'c',
yes: function () {
parent.layer.closeAll()
}
})
});
//工具条事件
table.on('tool(test)', function (obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值",表格id
var commodityId = obj.data.commodityId; //获得当前行id
console.log(commodityId)
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
if (layEvent === 'del') { //删除
layer.confirm('真的删除行么', function (index) {
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
layer.close(index);
//向服务端发送删除指令
console.log("执行")
$.ajax({
url: "/admin/commodityDelete/" + commodityId,
type: "delete",
dataType: "json",
success: function (data) {
if (data.msg == 0) {
table.reload('test');
layer.alert("删除成功")
}
},
error: function () {
layer.alert("删除失败")
}
})
});
} else if (layEvent === 'edit') { //编辑
parent.layer.open({
type: 2,//2表示跳转页面
offset: 'auto',
title: '编辑',
content: '/admin/commodityEdit?commodityId=' + commodityId,//页面路径
area: ['1000px', '600px'],//宽高
btn: '关闭全部',
btnAlign: 'c',
yes: function () {
parent.layer.closeAll()
}
})
}
});
});
//搜索
function doSearch(){
//附加搜索条件
var brandName=$("#brandId").val();
var kindName=$("#kindId").val();
var name=$("#name").val();
table.reload('commodityTable', {
where: {//附加额外参数
brandName:brandName,
kindName:kindName,
name:name
} //设定异步数据接口的额外参数
//,height: 300
});
}
</script>
</body>
</html>
商品添加页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>商品添加</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
</head>
<body>
<form class="layui-form layui-form-pane" action="" id="commodityForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-inline">
<input type="text" name="name" lay-verify="required" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux"><span id="commodityMsg" style="color: red"
hidden="hidden">*商品已存在</span></div>
</div>
</div>
<!-- <div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品售价</label>
<div class="layui-input-inline">
<input type="number" name="sellPrice" min="0" lay-verify="required" class="layui-input" placeholder="0">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">商品进价</label>
<div class="layui-input-inline">
<input type="number" name="inPrice" min="0" lay-verify="required" class="layui-input" placeholder="0">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">数量</label>
<div class="layui-input-inline">
<input type="number" name="stock" min="0" placeholder="0" lay-verify="required" class="layui-input">
</div>
</div>
</div>-->
<!-- <div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">验证日期</label>
<div class="layui-input-inline">
<input type="text" name="createDate" id="date" lay-verify="date" placeholder="yyyy-MM-dd"
autocomplete="off" class="layui-input">
</div>
</div>
</div>-->
<div class="layui-form-item">
<label class="layui-form-label">商品类型</label>
<div class="layui-input-inline">
<select name="kindName" id="kindId" lay-filter="classify">
<option value="" selected="">请选择类型</option>
<option th:if="${kindList}!=null" th:each="kind:${kindList}" th:value="${kind.getKindId()}"
th:text="${kind.getKindName()}"></option>
</select>
</div>
<div class="layui-input-inline">
<select name="brandName" id="brandId">
<option value="">请选品牌</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux"></div>
</div>
<!--商品规格-->
<div class="layui-form-item">
<label class="layui-form-label">商品规格</label>
<div style="margin-left: 10px;margin-bottom: 10px;" class="layui-input-block" id="addSkuBtn">
<div class="layui-input-inline">
<button type="button" onclick="addSku()" class="layui-btn">添加规格</button>
</div>
</div>
<!-- 规格内容-->
</div>
<!--/商品规格-->
<div class="layui-form-item">
<label class="layui-form-label">照片</label>
<div class="layui-input-block">
<!-- 上传按钮 -->
<button type="button" class="layui-btn" id="uploadPic">
上传图片
</button>
<!-- 隐藏的input -->
<input type="hidden" id="commodityPicture" name="commodityPicture"/>
<input type="hidden" id="xiangqing" name="xiangqing"/>
<!-- 预览区域 -->
<div id="imgDiv" class="layui-upload-list" style="display: none;">
<div class="image-container" id="container'+index+'">
<img class="layui-upload-img" width="500px" height="400px" id="demo1" name="msg"/>
<p id="demoText"></p>
</div>
<div style="width: 500px;">
<div class="layui-progress layui-progress-big" lay-showpercent="yes" lay-filter="demo">
<div class="layui-progress-bar" lay-percent=""></div>
</div>
<div class="delete-css " style="padding-top: 10px;">
<button id="upload_img" class="layui-btn layui-btn-sm layui-btn-primary">
<i class="layui-icon"></i>
</button>
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">展示图</label>
<!-- 展示图一-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang1">
<p id="xiang1Text"></p>
</div>
<button type="button" class="layui-btn" id="test1">展示图1</button>
</div>
<!-- 展示图二-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang2">
<p id="xiang2Text"></p>
</div>
<button type="button" class="layui-btn" id="test2">展示图2</button>
</div>
<!-- 展示图三-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang3">
<p id="xiang3Text"></p>
</div>
<button type="button" class="layui-btn" id="test3">展示图3</button>
</div>
</div>
<!-- 规格-->
<!-- <div class="layui-form-item">-->
<!-- <label class="layui-form-label">规格</label>-->
<!-- <div class=" layui-input-inline" >-->
<!-- <input style="padding-right: 60px" type="text" class="layui-input layui-input-inline">-->
<!-- <button style="position: absolute;right: 0px" type="button" class=" delguige layui-btn layui-btn-primary layui-btn-md"><i class="layui-icon"></i></button>-->
<!-- </div>-->
<!-- </div>-->
<div class="layui-form-item">
<label class="layui-form-label">是否上架</label>
<div class="layui-input-block">
<input type="checkbox" checked="" name="isPutaway" lay-skin="switch" lay-filter="switchTest"
lay-text="是|否">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">
<textarea name="description" placeholder="请输入内容" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" onclick="doSave()" class="layui-btn" lay-submit="" lay-filter="demo1">立即提交
</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</div>
</form>
<script>
var $;
var layer;//弹出层对象
layui.use(['form', 'layedit', 'laydate', 'upload', 'element'], function () {
var form = layui.form
, layedit = layui.layedit
, laydate = layui.laydate;
$ = layui.jquery;
layer = layui.layer;
var upload = layui.upload;
var element = layui.element
//展示图1
var uploadtest1 = upload.render({
elem: '#test1'
, url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
, before: function (obj) {
//预读本地文件示例,不支持ie8
obj.preview(function (index, file, result) {
$('#xiang1').attr('src', result); //图片链接(base64)
});
}
, done: function (res) {
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing").attr("value", $("#xiangqing").val() + ',' + res.url);
} else {
return layer.msg('上传失败');
}
}
, error: function () {
//演示失败状态,并实现重传
var demoText = $('#xiang1Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function () {
uploadtest1.upload();
});
}
});
//展示图2
var uploadtest2 = upload.render({
elem: '#test2'
, url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
, before: function (obj) {
//预读本地文件示例,不支持ie8
obj.preview(function (index, file, result) {
$('#xiang2').attr('src', result); //图片链接(base64)
});
}
, done: function (res) {
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing").attr("value", $("#xiangqing").val() + ',' + res.url);
} else {
return layer.msg('上传失败');
}
}
, error: function () {
//演示失败状态,并实现重传
var demoText = $('#xiang1Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function () {
uploadtest2.upload();
});
}
});
//展示图3
var uploadtest3 = upload.render({
elem: '#test3'
, url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
, before: function (obj) {
//预读本地文件示例,不支持ie8
obj.preview(function (index, file, result) {
$('#xiang3').attr('src', result); //图片链接(base64)
});
}
, done: function (res) {
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing").attr("value", $("#xiangqing").val() + ',' + res.url);
} else {
return layer.msg('上传失败');
}
}
, error: function () {
//演示失败状态,并实现重传
var demoText = $('#xiang3Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function () {
uploadtest3.upload();
});
}
//进度条
,
});
form.on('select(classify)', function (data) {
//监听到了下拉框选择的选项,传递过来
// console.log(data);//在控制台输出信息
var fatherId = data.value;
// console.log(classfies);
//再利用ajax将数据传到后端,来获取到对应下拉框选项而出现的值
$.ajax({
type: "post",
url: "/admin/commodityBrand",//前往获取商品的品牌
data: {"fatherId": fatherId},
dataType: "json",
success: function (data) {
//console.log(data.brandList)
//对应的值传回,拼出html下拉框语句
var tmp = '<option value="">请选择品牌</option>';
for (var d = 0; d < data.brandList.length; d++) {
console.log(data.brandList[d].kindName)
tmp += '<option value="' + data.brandList[d].kindId + '">' + data.brandList[d].kindName + '</option>';
}
$("#brandId").html(tmp);
form.render();
}, error: function () {
layer.alert('请求失败');
}
});
})
var uploadListIns = upload.render({
elem: '#uploadPic', //绑定元素
url: '/admin/commodityUploadFile', //上传接口
before: function (obj) {
//预读本地文件示例,不支持ie8
obj.preview(function (index, file, result) {
$('#demo1').attr('src', result); //图片链接(base64)
//删除某图片
$("#upload_img").bind('click', function () {
delete files[index];
$("#container" + index).remove();
var demoText = $('#demoText');
demoText.html('');
});
element.progress('demo', '0%'); //进度条复位
layer.msg('上传中', {icon: 16, time: 0});
});
},
done: function (res) {
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#commodityPicture").attr("value", res.url);
$("#imgDiv").css("display", "")// 显示图片框
} else {
return layer.msg('上传失败');
}
},
error: function () {
//演示失败状态,并实现重传
var demoText = $('#demoText');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function () {
uploadListIns.upload();
});
}
//进度条
, progress: function (n, elem, e) {
element.progress('demo', n + '%'); //可配合 layui 进度条元素使用
if (n == 100) {
layer.msg('上传完毕', {icon: 1});
}
}
});
//日期
laydate.render({
elem: '#date'
});
//创建一个编辑器
var editIndex = layedit.build('LAY_demo_editor');
//监听指定开关
form.on('switch(switchTest)', function (data) {
/*layer.msg('开关checked:'+ (this.checked ? 'true' : 'false') {
offset: '6px',*/
});
});
function tianjiaguige() {
$("#guigebtn").prepend("<div class=\" layui-input-inline\" >\n" +
" <input style=\"padding-right: 60px\" type=\"text\" class=\"layui-input layui-input-inline\"> <button style=\"position: absolute;right: 0px\" type=\"button\" class=\" delguige layui-btn layui-btn-primary layui-btn-md\"><i class=\"layui-icon\"></i></button>\n" +
" </div>");//通过insertBefore插入guigebtn前面
}
function doSave() {
// var skuName =document.getElementsByName("skuName")
let formData = $("#commodityForm").serialize();//获取表单数据
$.ajax({
url: "/admin/commodityAdd",
type: "post",
data: formData,
dataType: "json",
success: function (data) {
if (data.msg == 0) {
layer.alert("添加成功", {
yes: function () {
parent.layer.closeAll();
}
})
} else if (data.msg == 2) {
$("#commodityMsg").removeAttr("hidden")
$("#commodityMsg").attr("value", "商品名不能为空")
} else if (data.msg == 1) {
$("#commodityMsg").removeAttr("hidden")
}
},
error: function () {
layer.msg("添加失败")
}
})
}
//添加规格
function addSku() {
$("#addSkuBtn").append(" " +
"<div id='guige' class=\"layui-form-item\" style=\"margin-top: 10px;\">\n" +
" <div style=\"margin-left: 100px;\" class=\"layui-input-inline\">\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"text\" name=\"skuName\" lay-verify=\"required\" class=\"layui-input\" placeholder=\"规格名称\">\n" +
" </div>\n" +
" </div>\n" +
" <div class=\"layui-inline\">\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"number\" name=\"skuSellPrice\" min=\"0\" lay-verify=\"required\" class=\"layui-input\"\n" +
" placeholder=\"售价\">\n" +
" </div>\n" +
" </div>\n" +
"\n" +
" <div class=\"layui-inline \">\n" +
"\n" +
" <div class=\"layui-input-inline\" >\n" +
" <input type=\"number\" name=\"skuInPrice\" min=\"0\" lay-verify=\"required\" class=\"layui-input\"\n" +
" placeholder=\"进价\">\n" +
" </div>\n" +
" </div>\n" +
" <div class=\"layui-inline\">\n" +
"\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"number\" name=\"skuStock\" min=\"0\" placeholder=\"库存\" lay-verify=\"required\"\n" +
" class=\"layui-input\">\n" +
" <button id='aaa' οnclick='delSku(this)' value='1' style='position: absolute;right: -45px;top: 5px' type=\"button\" class=\"layui-btn layui-btn-sm layui-btn-danger\"><i class=\"layui-icon\"></i></button>\n" +
" </div>\n" +
" </div>\n" +
" </div>"
);
}
//删除规格
function delSku(obj) {
console.log("获取复元素"+$(obj).parent().parent().parent().remove())
}
</script>
</body>
</html>
商品编辑页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>商品编辑</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
<style>
.layui-input{
border: #122b40 2px solid;
}
</style>
</head>
<body>
<form class="layui-form" action="" id="commodityForm" >
<div class="layui-form-item" hidden>
<div class="layui-inline">
<label class="layui-form-label">商品id</label>
<div class="layui-input-inline">
<input type="number" name="commodityId" lay-verify="required" class="layui-input" th:value="${commodity.getCommodityId()}">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-inline">
<input type="text" name="name" lay-verify="required" class="layui-input" th:value="${commodity.getName()}">
</div>
<div class="layui-form-mid layui-word-aux"><span id="commodityMsg" style="color: red"
hidden="hidden">*商品已存在</span></div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品售价</label>
<div class="layui-input-inline">
<input type="text" name="sellPrice" lay-verify="required" class="layui-input" th:value="${commodity.getSellPrice()}">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">商品进价</label>
<div class="layui-input-inline">
<input type="text" name="inPrice" lay-verify="required" class="layui-input" th:value="${commodity.getInPrice()}">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">数量</label>
<div class="layui-input-inline">
<input type="number" name="stock" min="0" lay-verify="required" class="layui-input" th:value="${commodity.getStock()}">
</div>
</div>
</div>
<!-- <div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">验证日期</label>
<div class="layui-input-inline">
<input type="text" name="createDate" id="date" lay-verify="date" placeholder="yyyy-MM-dd"
autocomplete="off" class="layui-input" th:value="${commodity.getCreateDate()}">
</div>
</div>
</div>-->
<div class="layui-form-item">
<label class="layui-form-label">商品类型</label>
<div class="layui-input-inline">
<select name="kindName" id="kindId" lay-filter="classify">
<option value="" th:if="${commodity.getKindName()==null}" >请选择类型</option>
<option th:selected="${kind.getKindName()==commodity.getKindName()}" th:if="${kindList}!=null" th:each="kind:${kindList}" th:value="${kind.getKindId()}"
th:text="${kind.getKindName()}"></option>
</select>
</div>
<div class="layui-input-inline" id="brand">
<select name="brandName"id="brandId">
<option th:if="${brandList==null}" value="">请选择品牌</option>
<option th:selected="${brand.getKindName()==commodity.getKindName()}" th:if="${brandList}!=null" th:each="brand:${brandList}" th:value="${brand.getKindId()}"
th:text="${brand.getKindName()}"></option>
</select>
</div>
</div>
<!-- 商品规格-->
<div class="layui-form-item">
<label class="layui-form-label">商品规格</label>
<div th:if="${skuList!=null}" style="margin-left: 10px;margin-bottom: 10px;" class="layui-input-block" id="addSkuBtn">
<div class="layui-input-inline">
<button type="button" onclick="addSku()" class="layui-btn">添加规格</button>
</div>
<div th:each="sku:${skuList}" id="guige" class="layui-form-item" style="margin-top: 10px;margin-left: 10%; border: #e8e8e8 1px solid;width: 85%">
<input id="skuId" name="skuId" th:value="${sku.getSkuId()}" hidden="hidden">
<div style="margin-left: 0px;" class="layui-inline" >
<label class="layui-form-label" >规格</label>
<div class="layui-input-inline">
<input type="text" name="skuName" lay-verify="required" class="layui-input" th:value="${sku.getSkuName()}" placeholder="规格名称">
</div>
</div>
<div class="layui-inline" style="margin-left: -80px">
<label class="layui-form-label" >售价</label>
<div class="layui-input-inline" >
<input type="number" name="skuSellPrice" min="0" lay-verify="required" class="layui-input" th:value="${sku.getSkuSellPrice()}" placeholder="售价">
</div>
</div>
<div class="layui-inline " style="margin-left: -80px">
<label class="layui-form-label" >进价</label>
<div class="layui-input-inline" >
<input type="number" name="skuInPrice" min="0" lay-verify="required" class="layui-input" th:value="${sku.getSkuInPrice()}" placeholder="进价">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" >库存</label>
<div class="layui-input-inline" >
<input type="number" name="skuStock" min="0" th:value="${sku.getSkuStock()}" placeholder="库存" lay-verify="required" class="layui-input">
<button id="aaa" th:onclick="|javascript:delSku('${sku.skuId}',this,'${commodity.getCommodityId()}')|" value="1"
style="position: absolute;right: -45px;top: 5px" type="button"
class="layui-btn layui-btn-sm layui-btn-danger">
<i class="layui-icon"></i></button>
</div>
</div>
</div>
</div>
<!-- 规格内容-->
</div>
<div class="layui-form-item">
<label class="layui-form-label">照片</label>
<div class="layui-input-block">
<!-- 上传按钮 -->
<button type="button" class="layui-btn" id="uploadPic">
上传图片
</button>
<!-- 隐藏的input -->
<input type="hidden" id="commodityPicture" th:value="${commodity.getCommodityPicture()}" name="commodityPicture"/>
<input type="hidden" id="xiangqing" th:value="${commodity.getXiangqing()}" name="xiangqing"/>
<input th:if="${xiangqingList!=null}" th:each="xList,xIndex:${xiangqingList}" type="hidden" th:id="'xiangqing'+${xIndex.index+1}" th:value="${xList}" />
<input th:if="${xiangqingList==null}" type="hidden" id="xiangqing1" />
<input th:if="${xiangqingList==null}" type="hidden" id="xiangqing2" />
<input th:if="${xiangqingList==null}" type="hidden" id="xiangqing3" />
<!-- 预览区域 -->
<div id="imgDiv" class="layui-upload-list" >
<div class="image-container" id="container'+index+'">
<img th:src="'/commodityImages/'+${commodity.getCommodityPicture()}" class="layui-upload-img" width="500px" height="400px" id="demo1" name="msg"/>
<p id="demoText"></p>
</div>
<div style="width: 500px;">
<div class="layui-progress layui-progress-big" lay-showpercent="yes" lay-filter="demo">
<div class="layui-progress-bar" lay-percent=""></div>
</div>
<div class="delete-css " style="padding-top: 10px;">
<button id="upload_img" class="layui-btn layui-btn-sm layui-btn-primary">
<i class="layui-icon"></i>
</button>
</div>
</div>
</div>
</div>
<div th:if="${xiangqingList!=null}" class="layui-form-item">
<label class="layui-form-label">展示图</label>
<!-- 展示图一-->
<div th:each="list,start:${xiangqingList}" class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img th:src="'/commodityImages/'+${list}"style="border: 2px solid black" width="100" height="100" class="layui-upload-img" th:id="'xiang'+${start.index+1}">
<p th:id="'xiang'+${start.index+1}+'Text'"></p>
</div>
<button type="button" class="layui-btn" th:id="'test'+${start.index+1}" th:text="'展示图'+${start.index+1}"></button>
</div>
</div>
<!-- 没有展示图则显示默认-->
<div th:if="${xiangqingList==null}" class="layui-form-item">
<label class="layui-form-label">展示图</label>
<!-- 展示图一-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang1">
<p id="xiang1Text"></p>
</div>
<button type="button" class="layui-btn" id="test1" >展示图1</button>
</div>
<!-- 展示图二-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang2">
<p id="xiang2Text"></p>
</div>
<button type="button" class="layui-btn" id="test2">展示图2</button>
</div>
<!-- 展示图三-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang3">
<p id="xiang3Text"></p>
</div>
<button type="button" class="layui-btn" id="test3">展示图3</button>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否上架</label>
<div class="layui-input-block">
<input type="checkbox" th:checked="${commodity.getIsPutaway()=='off'?false:true}" name="isPutaway" lay-skin="switch" lay-filter="switchTest"
lay-text="是|否">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">
<textarea th:text="${commodity.getDescription()}" name="description" placeholder="请输入内容" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" onclick="doSave()" class="layui-btn" lay-submit="" lay-filter="demo1">立即提交
</button>
</div>
</div>
</div>
</form>
<script>
var $;
var layer;//弹出层对象
layui.use(['form', 'layedit', 'laydate', 'upload', 'element','jquery'], function () {
var form = layui.form
, layedit = layui.layedit
, laydate = layui.laydate;
$ = layui.jquery;
layer = layui.layer;
var upload = layui.upload;
var element = layui.element;
//展示图1
var uploadtest1 = upload.render({
elem: '#test1'
,url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
,before: function(obj){
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result){
$('#xiang1').attr('src', result); //图片链接(base64)
});
}
,done: function(res){
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing1").attr("value", res.url);
} else {
return layer.msg('上传失败');
}
}
,error: function(){
//演示失败状态,并实现重传
var demoText = $('#xiang1Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function(){
uploadtest1.upload();
});
}
});
//展示图2
var uploadtest2 = upload.render({
elem: '#test2'
,url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
,before: function(obj){
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result){
$('#xiang2').attr('src', result); //图片链接(base64)
});
}
,done: function(res){
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing2").attr("value", res.url);
} else {
return layer.msg('上传失败');
}
}
,error: function(){
//演示失败状态,并实现重传
var demoText = $('#xiang1Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function(){
uploadtest2.upload();
});
}
});
//展示图3
var uploadtest3 = upload.render({
elem: '#test3'
,url: '/admin/commodityUploadFile' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
,before: function(obj){
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result){
$('#xiang3').attr('src', result); //图片链接(base64)
});
}
,done: function(res){
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#xiangqing3").attr("value", res.url);
} else {
return layer.msg('上传失败');
}
}
,error: function(){
//演示失败状态,并实现重传
var demoText = $('#xiang3Text');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function(){
uploadtest3.upload();
});
}
//进度条
,
});
form.on('select(classify)',function (data) {
//监听到了下拉框选择的选项,传递过来
// console.log(data);//在控制台输出信息
var fatherId = data.value;
// console.log(classfies);
//再利用ajax将数据传到后端,来获取到对应下拉框选项而出现的值
$.ajax({
type:"post",
url:"/admin/commodityBrand",//前往获取商品的品牌
data:{"fatherId":fatherId},
dataType:"json",
success:function (data) {
//console.log(data.brandList)
//对应的值传回,拼出html下拉框语句
var tmp='<option value="">请选择品牌</option>';
for (var d=0; d<data.brandList.length;d++){
console.log(data.brandList[d].kindName)
tmp +='<option value="'+data.brandList[d].kindId+'">'+data.brandList[d].kindName+'</option>';
}
$("#brandId").html(tmp);
form.render();
},error:function () {
layer.alert('请求失败');
}
});
})
var uploadListIns = upload.render({
elem: '#uploadPic', //绑定元素
url: '/admin/commodityUploadFile', //上传接口
before: function (obj) {
//预读本地文件示例,不支持ie8
obj.preview(function (index, file, result) {
$('#demo1').attr('src', result); //图片链接(base64)
//删除某图片
$("#upload_img").bind('click', function () {
delete files[index];
$("#container" + index).remove();
var demoText = $('#demoText');
demoText.html('');
});
element.progress('demo', '0%'); //进度条复位
layer.msg('上传中', {icon: 16, time: 0});
});
},
done: function (res) {
//如果上传失败
if (res != "") {
//上传成功
layer.alert("上传成功" + res.url);
$("#commodityPicture").attr("value", res.url);
$("#imgDiv").css("display", "")// 显示图片框
} else {
return layer.msg('上传失败');
}
},
error: function () {
//演示失败状态,并实现重传
var demoText = $('#demoText');
demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>');
demoText.find('.demo-reload').on('click', function () {
uploadListIns.upload();
});
}
//进度条
,progress: function(n, elem, e){
element.progress('demo', n + '%'); //可配合 layui 进度条元素使用
if(n == 100){
layer.msg('上传完毕', {icon: 1});
}
}
});
//日期
laydate.render({
elem: '#date'
});
});
function doSave() {
let x=$("#xiangqing1").val()+','+$("#xiangqing2").val()+','+$("#xiangqing3").val()
$("#xiangqing").attr("value",x)
let formData = $("#commodityForm").serialize();//获取表单数据
$.ajax({
url: "/admin/commodityEdit",
type: "post",
data: formData,
dataType: "json",
success: function (data) {
if (data.msg == 0) {
layer.alert("编辑成功", {
yes: function () {
//parent.location.href="/admin/commodityList"
parent.layer.closeAll();
}
})
} else if (data.msg==2){
$("#commodityMsg").removeAttr("hidden")
$("#commodityMsg").attr("value","商品名不能为空")
}else if (data.msg==1){
$("#commodityMsg").removeAttr("hidden")
}
},
error: function () {
layer.msg("编辑失败")
}
})
}
//添加规格
function addSku() {
$("#addSkuBtn").append(" " +
"<div id='guige' class=\"layui-form-item\" style=\"margin-top: 10px;\">\n" +
"<input id=\"skuId\" name=\"skuId\" value=\"-1\" hidden=\"hidden\">"+
" <div style=\"margin-left: 100px;\" class=\"layui-input-inline\">\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"text\" name=\"skuName\" lay-verify=\"required\" class=\"layui-input\" placeholder=\"规格名称\">\n" +
" </div>\n" +
" </div>\n" +
" <div class=\"layui-inline\">\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"number\" name=\"skuSellPrice\" min=\"0\" lay-verify=\"required\" class=\"layui-input\"\n" +
" placeholder=\"售价\">\n" +
" </div>\n" +
" </div>\n" +
"\n" +
" <div class=\"layui-inline \">\n" +
"\n" +
" <div class=\"layui-input-inline\" >\n" +
" <input type=\"number\" name=\"skuInPrice\" min=\"0\" lay-verify=\"required\" class=\"layui-input\"\n" +
" placeholder=\"进价\">\n" +
" </div>\n" +
" </div>\n" +
" <div class=\"layui-inline\">\n" +
"\n" +
" <div class=\"layui-input-inline\">\n" +
" <input type=\"number\" name=\"skuStock\" min=\"0\" placeholder=\"库存\" lay-verify=\"required\"\n" +
" class=\"layui-input\">\n" +
" <button οnclick='delsku2(this)' style='position: absolute;right: -45px;top: 5px' type=\"button\" class=\"layui-btn layui-btn-sm layui-btn-danger\"><i class=\"layui-icon\"></i></button>\n" +
" </div>\n" +
" </div>\n" +
" </div>"
);
}
//删除规格
function delSku(skuId,obj,commodityId) {
console.log("规格id"+skuId)
$.ajax({
url:'/admin/skuDelete/'+skuId+'/'+commodityId,
dataType:"json",
success:function (data){
layer.msg('data.resource');
if (data.resource==200){
$(obj).parent().parent().parent().remove();
layer.msg('删除完成');
parent.layer.closeAll()
parent.layer.open({
type: 2,//2表示跳转页面
offset: 'auto',
title: '编辑',
content: '/admin/commodityEdit?commodityId=' + commodityId,//页面路径
area: ['1000px', '600px'],//宽高
btn: '关闭全部',
btnAlign: 'c',
yes: function () {
parent.layer.closeAll()
}
})
}else {
layer.msg('删除失败');
}
},
error:function (){
layer.msg('操作失败');
}
})
}
function delsku2(obj){
$(obj).parent().parent().parent().remove();
}
</script>
</body>
</html>
商品查看页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>商品查看</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
<style>
.layui-input{
border: #122b40 2px solid;
}
</style>
</head>
<body >
<form class="layui-form" action="" id="commodityForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-inline">
<input type="text" name="name" lay-verify="required" class="layui-input" th:value="${commodity.getName()}">
</div>
<div class="layui-form-mid layui-word-aux"><span id="commodityMsg" style="color: red"
hidden="hidden">*商品已存在</span></div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">商品售价</label>
<div class="layui-input-inline">
<input type="text" name="sellPrice" lay-verify="required" class="layui-input" th:value="${commodity.getSellPrice()}">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">商品进价</label>
<div class="layui-input-inline">
<input type="text" name="inPrice" lay-verify="required" class="layui-input" th:value="${commodity.getInPrice()}">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">数量</label>
<div class="layui-input-inline">
<input type="number" name="stock" min="0" lay-verify="required" class="layui-input" th:value="${commodity.getStock()}">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">验证日期</label>
<div class="layui-input-inline">
<input type="text" name="createDate" id="date" lay-verify="date" placeholder="yyyy-MM-dd"
autocomplete="off" class="layui-input" th:value="${commodity.getCreateDate()}">
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品类型</label>
<div class="layui-input-inline">
<select name="kindName">
<option th:if="${commodity.getKindName()==null}" value="" selected="">请选择类型</option>
<option th:if="${commodity.getKindName()!=null}" th:text="${commodity.getKindName()}" value="" selected="">请选择类型</option>
</select>
</div>
<div class="layui-input-inline">
<select name="brandName" id="brandId">
<option th:if="${commodity.getBrandName()==null}" value="">请选品牌</option>
<option th:if="${commodity.getBrandName()!=null}" th:text="${commodity.getBrandName()}" value="">请选品牌</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux"></div>
</div>
<!-- 商品规格-->
<div class="layui-form-item">
<label class="layui-form-label">商品规格</label>
<div th:if="${skuList!=null}" style="margin-left: 10px;margin-bottom: 10px;" class="layui-input-block" id="addSkuBtn">
<!-- <div class="layui-input-inline">
<button type="button" οnclick="addSku()" class="layui-btn">添加规格</button>
</div>-->
<div th:each="sku:${skuList}" id="guige" class="layui-form-item" style="margin-top: 10px;margin-left: 10%; border: #e8e8e8 1px solid;width: 85%">
<input id="skuID" th:value="${sku.getSkuId()}" hidden="hidden">
<div style="margin-left: 0px;" class="layui-inline" >
<label class="layui-form-label" >规格</label>
<div class="layui-input-inline">
<input type="text" name="skuName" lay-verify="required" class="layui-input" th:value="${sku.getSkuName()}" placeholder="规格名称">
</div>
</div>
<div class="layui-inline" style="margin-left: -80px">
<label class="layui-form-label" >售价</label>
<div class="layui-input-inline" >
<input type="number" name="skuSellPrice" min="0" lay-verify="required" class="layui-input" th:value="${sku.getSkuSellPrice()}" placeholder="售价">
</div>
</div>
<div class="layui-inline " style="margin-left: -80px">
<label class="layui-form-label" >进价</label>
<div class="layui-input-inline" >
<input type="number" name="skuInPrice" min="0" lay-verify="required" class="layui-input" th:value="${sku.getSkuInPrice()}" placeholder="进价">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" >库存</label>
<div class="layui-input-inline" >
<input type="number" name="skuStock" min="0" th:value="${sku.getSkuStock()}" placeholder="库存" lay-verify="required" class="layui-input">
<!-- <button id="aaa" οnclick="delSku(this)" value="1"
style="position: absolute;right: -45px;top: 5px" type="button"
class="layui-btn layui-btn-sm layui-btn-danger">
<i class="layui-icon"></i></button>-->
</div>
</div>
</div>
</div>
<!-- 规格内容-->
</div>
<div class="layui-form-item">
<label class="layui-form-label">照片</label>
<div class="layui-input-block">
<!-- 预览区域 -->
<div id="imgDiv" class="layui-upload-list">
<div class="image-container" id="container'+index+'">
<img th:src="'/commodityImages/'+${commodity.getCommodityPicture()}" class="layui-upload-img" width="500px" height="400px" id="demo1" name="msg"/>
</div>
</div>
</div>
<div th:if="${xiangqingList!=null}" class="layui-form-item">
<label class="layui-form-label">展示图</label>
<!-- 展示图一-->
<div th:each="list,start:${xiangqingList}" class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img th:src="'/commodityImages/'+${list}"style="border: 2px solid black" width="100" height="100" class="layui-upload-img" th:id="'xiang'+${start.index+1}">
<p th:id="'xiang'+${start.index+1}+'Text'"></p>
</div>
<button type="button" class="layui-btn" id="test1" th:text="'展示图'+${start.index+1}"></button>
</div>
</div>
<!-- 没有展示图则显示默认-->
<div th:if="${xiangqingList==null}" class="layui-form-item">
<label class="layui-form-label">展示图</label>
<!-- 展示图一-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang1">
<p id="xiangText"></p>
</div>
<button type="button" class="layui-btn" id="test" >展示图1</button>
</div>
<!-- 展示图二-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang2">
<p id="xiang2Text"></p>
</div>
<button type="button" class="layui-btn" id="test2">展示图2</button>
</div>
<!-- 展示图三-->
<div class="layui-upload layui-input-inline">
<div style="width: 95px;">
</div>
<div class="layui-upload-list">
<img style="border: 2px solid black" width="100" height="100" class="layui-upload-img" id="xiang3">
<p id="xiang3Text"></p>
</div>
<button type="button" class="layui-btn" id="test3">展示图3</button>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否上架</label>
<div class="layui-input-block">
<input type="checkbox" th:checked="${commodity.getIsPutaway()=='off'?false:true}" name="isPutaway" lay-skin="switch" lay-filter="switchTest"
lay-text="是|否">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">
<textarea th:text="${commodity.getDescription()}" name="description" placeholder="请输入内容" class="layui-textarea"></textarea>
</div>
</div>
</div>
</form>
<script>
var $;
var layer;//弹出层对象
layui.use(['form', 'layedit', 'laydate', 'upload', 'element'], function () {
var form = layui.form
, layedit = layui.layedit
, laydate = layui.laydate;
$ = layui.jquery;
layer = layui.layer;
});
</script>
</body>
</html>