KKSU
2023-12-20 36f45aa751f88dbb1b09ca01cc9559f716d97e8c
富文本框输入版本变化
19 files modified
18 files added
1973 ■■■■■ changed files
src/main/java/cc/mrbird/febs/common/utils/AppContants.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsCategoryController.java 43 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsController.java 30 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ApiMallAppController.java 58 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsCategoryController.java 32 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsController.java 32 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiAddOrderDto.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiAddOrderItemDto.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiMallAppMemberInfoDto.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiMallGoodsQueryDto.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallAppMember.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallGoods.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCategory.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallAppMemberMapper.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallGoodsCategoryMapper.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallGoodsMapper.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IAdminMallGoodsCategoryService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IAdminMallGoodsService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IApiMallAppService.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IApiMallGoodsCategoryService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsCategoryService.java 106 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java 34 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallAppServiceImpl.java 104 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallGoodsCategoryServiceImpl.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiMallAppMemberInfoVo.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiMallGoodsListVo.java 34 ●●●●● patch | view | raw | blame | history
src/main/resources/application-test.yml 2 ●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallAppMemberMapper.xml 24 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallGoodsCategoryMapper.xml 34 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallGoodsMapper.xml 54 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/goods/goodsAppAddNew.html 234 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/goods/goodsAppList.html 229 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/goods/goodsAppUpdateNew.html 280 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/product/categoryAppAdd.html 130 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/product/categoryAppList.html 174 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/product/categoryAppUpdate.html 149 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/utils/AppContants.java
@@ -17,6 +17,12 @@
     * app用户登陆redis前缀
     */
    public static final String APP_LOGIN_PREFIX = "app_";
    public static final String SY_APP_LOGIN_PREFIX = "sy_app_";
    /**
     * 是否是收银APP类目 1:是
     */
    public static final Integer IS_APP_CATEGORY = 1;
    public static final Integer IS_APP_GOODS = 1;
    public static final String XCX_LOGIN_PREFIX = "xcx_";
    public static final String XCX_LOGIN_PHONE_PREFIX = "xcx_p";
src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsCategoryController.java
@@ -4,6 +4,7 @@
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.mall.entity.MallGoodsCategory;
import cc.mrbird.febs.mall.service.IAdminMallGoodsCategoryService;
import cc.mrbird.febs.mall.service.IApiMallGoodsCategoryService;
@@ -51,6 +52,11 @@
        return new FebsResponse().success().data(mallGoodsCategoryService.findAllCategoryList());
    }
    @GetMapping(value = "/categoryAppTree")
    public FebsResponse categoryAppTree() {
        return new FebsResponse().success().data(mallGoodsCategoryService.findAllAppCategoryList());
    }
    /**
     * 商品分类-选择
     */
@@ -96,5 +102,42 @@
        return goodsCategoryService.delCategary(id);
    }
    /**
     * APP商品分类列表
     * @param mallGoodsCategory
     * @param request
     * @return
     */
    @GetMapping("categoryAppList")
    public FebsResponse categoryAppList(MallGoodsCategory mallGoodsCategory, QueryRequest request) {
        mallGoodsCategory.setIsApp(AppContants.IS_APP_CATEGORY);
        Map<String, Object> data = getDataTable(goodsCategoryService.getCategoryList(mallGoodsCategory, request));
        return new FebsResponse().success().data(data);
    }
    /**
     * 商品分类-新增
     */
    @PostMapping("addAppCategory")
    @ControllerEndpoint(operation = " 商品分类-新增", exceptionMessage = "操作失败")
    public FebsResponse addAppCategory(@Valid MallGoodsCategory mallGoodsCategory) {
        return goodsCategoryService.addAppCategory(mallGoodsCategory);
    }
    /**
     * 商品分类-编辑
     */
    @PostMapping("updateAppCategory")
    @ControllerEndpoint(operation = " 商品分类-编辑", exceptionMessage = "操作失败")
    public FebsResponse updateAppCategory(@Valid MallGoodsCategory mallGoodsCategory) {
        return goodsCategoryService.updateAppCategory(mallGoodsCategory);
    }
    /**
     * 商品分类-删除
     */
    @GetMapping("delAppCategary/{id}")
    @ControllerEndpoint(operation = " 商品分类-删除", exceptionMessage = "操作失败")
    public FebsResponse delAppCategary(@NotNull(message = "{required}") @PathVariable Long id) {
        return goodsCategoryService.delAppCategary(id);
    }
}
src/main/java/cc/mrbird/febs/mall/controller/AdminMallGoodsController.java
@@ -96,6 +96,36 @@
        return new FebsResponse().success().data(data);
    }
    /**
     * app商品列表
     * @param mallGoods
     * @param request
     * @return
     */
    @GetMapping("goodsAppList")
    public FebsResponse goodsAppList(MallGoods mallGoods, QueryRequest request) {
        Map<String, Object> data = getDataTable(adminMallGoodsService.getAppCategoryListInPage(mallGoods, request));
        return new FebsResponse().success().data(data);
    }
    /**
     * app商品-新增
     */
    @PostMapping("addMallAppGoods")
    @ControllerEndpoint(operation = " 商品-新增", exceptionMessage = "新增失败")
    public FebsResponse addMallAppGoods(@RequestBody @Valid AddMallGoodsDto addMallGoodsDto) {
        return adminMallGoodsService.addMallAppGoods(addMallGoodsDto);
    }
    /**
     * app商品-编辑
     */
    @PostMapping("updateAppMallGoods")
    @ControllerEndpoint(operation = "商品-编辑", exceptionMessage = "操作失败")
    public FebsResponse updateAppMallGoods(@RequestBody @Valid MallGoodsUpdateDto mallGoodsUpdateDto) {
        return adminMallGoodsService.updateAppMallGoods(mallGoodsUpdateDto);
    }
    /**
     * 商品-新增
     */
src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java
@@ -3,6 +3,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.service.IApiMallAppService;
import cc.mrbird.febs.mall.service.IApiMallMemberService;
import cc.mrbird.febs.pay.model.WxGenerateQrCodeDto;
import cc.mrbird.febs.pay.service.IXcxPayService;
@@ -39,6 +40,7 @@
public class ApiLoginController {
    private final IApiMallMemberService memberService;
    private final IApiMallAppService mallAppService;
    private final IXcxPayService iXcxPayService;
    private final RedisUtils redisUtils;
@@ -56,6 +58,13 @@
    }
    @ApiOperation(value = "app账号密码登录接口", notes = "app账号密码登录接口")
    @PostMapping(value = "/appToLogin")
    public FebsResponse appToLogin(@RequestBody LoginDto loginDto) {
        return mallAppService.appToLogin(loginDto);
    }
    @ApiOperation(value = "忘记/修改密码", notes = "忘记/修改密码")
    @PostMapping(value = "/forgetPwd")
    public FebsResponse forgetPwd(@RequestBody ForgetPwdDto forgetPwdDto) {
src/main/java/cc/mrbird/febs/mall/controller/ApiMallAppController.java
New file
@@ -0,0 +1,58 @@
package cc.mrbird.febs.mall.controller;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.service.IApiMallAppService;
import cc.mrbird.febs.mall.service.IApiMallGoodsCategoryService;
import cc.mrbird.febs.mall.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@Slf4j
@CrossOrigin("*")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api/syApp")
@Api(value = "ApiMallAppController", tags = "收银APP")
public class ApiMallAppController {
    private final IApiMallAppService mallAppService;
    @ApiOperation(value = "根据手机尾号查询用户信息", notes = "根据手机尾号查询用户信息")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMallAppMemberInfoVo.class)
    })
    @PostMapping(value = "/appMemberInfo")
    public FebsResponse appMemberInfo(@RequestBody ApiMallAppMemberInfoDto apiMallAppMemberInfoDto) {
        return mallAppService.appMemberInfo(apiMallAppMemberInfoDto);
    }
    @ApiOperation(value = "获取商品分类", notes = "获取商品分类")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = MallGoodsCategoryVo.class)
    })
    @GetMapping(value = "/findAllCategoryList")
    public FebsResponse findAllCategoryList() {
        return mallAppService.findAllCategoryList();
    }
    @ApiOperation(value = "获取分类下的商城商品", notes = "获取分类下的商城商品")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMallGoodsListVo.class)
    })
    @PostMapping(value = "/goodsListNoPage")
    public FebsResponse goodsListNoPage(@RequestBody ApiMallGoodsQueryDto queryDto) {
        return mallAppService.findMallGoodsListNoPage(queryDto);
    }
    @ApiOperation(value = "创建订单", notes = "创建订单")
    @PostMapping(value = "/createAppOrder")
    public FebsResponse createAppOrder(@RequestBody ApiAddOrderDto addOrderDto) {
        return mallAppService.createAppOrder(addOrderDto);
    }
}
src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsCategoryController.java
@@ -57,4 +57,36 @@
        model.addAttribute("goodsCategoryVo", data);
        return FebsUtil.view("modules/product/categoryUpdate");
    }
    /**
     * App商品分类列表
     * @return
     */
    @GetMapping("categoryAppList")
    @RequiresPermissions("categoryAppList:view")
    public String categoryAppList() {
        return FebsUtil.view("modules/product/categoryAppList");
    }
    /**
     * 商品分类-新增
     * @return
     */
    @GetMapping("categoryAppAdd")
    @RequiresPermissions("categoryAppAdd:add")
    public String categoryAppAdd() {
        return FebsUtil.view("modules/product/categoryAppAdd");
    }
    /**
     * 商品分类-详情
     * @param id
     * @param model
     * @return
     */
    @GetMapping("categoryAppUpdate/{id}")
    @RequiresPermissions("categoryAppUpdate:update")
    public String categoryAppUpdate(@PathVariable long id, Model model) {
        AdminMallGoodsCategoryVo data = mallGoodsCategoryService.getMallGoodsCategoryInfoById(id);
        model.addAttribute("goodsCategoryVo", data);
        return FebsUtil.view("modules/product/categoryAppUpdate");
    }
}
src/main/java/cc/mrbird/febs/mall/controller/ViewMallGoodsController.java
@@ -46,6 +46,38 @@
    }
    /**
     * app商品列表
     * @return
     */
    @GetMapping("goodsAppList")
    @RequiresPermissions("goodsAppList:view")
    public String goodsAppList() {
        return FebsUtil.view("modules/goods/goodsAppList");
    }
    /**
     * app商品-新增
     * @return
     */
    @GetMapping("goodsAppAddNew")
    @RequiresPermissions("goodsAppAddNew:add")
    public String goodsAppAddNew() {
        return FebsUtil.view("modules/goods/goodsAppAddNew");
    }
    /**
     * app商品-编辑-详情
     * @param id
     * @param model
     * @return
     */
    @GetMapping("goodsAppUpdateNew/{id}")
    @RequiresPermissions("goodsAppUpdateNew:update")
    public String goodsAppUpdateNew(@PathVariable long id, Model model) {
        MallGoods data = mallGoodsService.selectGoodsById(id);
        model.addAttribute("goodsInfo", data);
        return FebsUtil.view("modules/goods/goodsAppUpdateNew");
    }
    /**
     * 商品-新增
     * @return
     */
src/main/java/cc/mrbird/febs/mall/dto/ApiAddOrderDto.java
New file
@@ -0,0 +1,19 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "ApiAddOrderDto", description = "新增订单接口参数接收类")
public class ApiAddOrderDto {
    @ApiModelProperty(value = "订单结算方式 1:普通结算 2:会员结算", example = "1")
    private Integer type;
    @ApiModelProperty(value = "商品明细")
    private List<ApiAddOrderItemDto> items;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiAddOrderItemDto.java
New file
@@ -0,0 +1,21 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiAddOrderItemDto", description = "新增订单明细参数接收类")
public class ApiAddOrderItemDto {
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "skuID", example = "1")
    private Long skuId;
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "数量", example = "2")
    private Integer cnt;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiMallAppMemberInfoDto.java
New file
@@ -0,0 +1,17 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiMallAppMemberInfoDto", description = "参数接收类")
public class ApiMallAppMemberInfoDto {
    @NotNull(message = "电话号码不能为空")
    @ApiModelProperty(value = "电话号码,支持尾号查询", example = "3560")
    private String phone;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiMallGoodsQueryDto.java
New file
@@ -0,0 +1,14 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiMallGoodsQueryDto", description = "商城商品参数接收类")
public class ApiMallGoodsQueryDto {
    @ApiModelProperty(value = "分类ID")
    private Long categoryId;
}
src/main/java/cc/mrbird/febs/mall/entity/MallAppMember.java
New file
@@ -0,0 +1,15 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
//app用户表
@Data
@TableName("mall_app_member")
public class MallAppMember  extends BaseEntity {
    private String account;
    private String password;
}
src/main/java/cc/mrbird/febs/mall/entity/MallGoods.java
@@ -31,6 +31,7 @@
    private String goodsDetails;
    private Integer isSale;
    private Integer isApp;
    /**
     * 上架
src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCategory.java
@@ -23,5 +23,7 @@
    private String image;
    private Integer indexNum;
    // 是否是收银APP类目 1:是 否则为小程序类别
    private Integer isApp;
}
src/main/java/cc/mrbird/febs/mall/mapper/MallAppMemberMapper.java
New file
@@ -0,0 +1,18 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.dto.ApiMallAppMemberInfoDto;
import cc.mrbird.febs.mall.entity.MallAppMember;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.vo.ApiMallAppMemberInfoVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MallAppMemberMapper extends BaseMapper<MallAppMember> {
    MallAppMember selectByAccountAndPassword(@Param("account") String account, @Param("password") String password);
    List<ApiMallAppMemberInfoVo> selectMemberInfoLikePhone(@Param("phone")String phone);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallGoodsCategoryMapper.java
@@ -21,6 +21,8 @@
    List<MallGoodsCategoryVo> selectAllCategoryList();
    List<MallGoodsCategoryVo> selectAllAppCategoryList();
    List<MallGoodsCategory> selectCategoryListByParentId(@Param("id") Long id);
    List<MallGoodsCategory> selectRecommendCategoryList();
@@ -32,4 +34,6 @@
    List<MallGoodsCategory> selectChildCategaryById(@Param("id")Long id);
    List<AdminMallGoodsCategoryTreeVo> getAllCategorys();
    List<MallGoodsCategoryVo> selectAllCategoryListByIsApp(@Param("isApp")Integer isAppCategory);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallGoodsMapper.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.dto.ApiMallGoodsQueryDto;
import cc.mrbird.febs.mall.dto.MallGoodsQueryDto;
import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
import cc.mrbird.febs.mall.entity.MallGoods;
@@ -22,6 +23,8 @@
    MallGoods selectGoodsDetailById(@Param("id") Long id);
    IPage<AdminMallGoodsVo> selectMallGoodsInPage(Page<AdminMallGoodsVo> page, @Param("record")MallGoods mallGoods);
    IPage<AdminMallGoodsVo> selectMallAppGoodsInPage(Page<AdminMallGoodsVo> page, @Param("record")MallGoods mallGoods);
    Integer selectMallGoodsCountByGoodsName(@Param("goodsName")String goodsName);
@@ -55,4 +58,5 @@
    List<MallGoodsListVo> selectMallGoodsListQueryNoPage(@Param("record")MallGoodsQueryDto queryDto);
    List<ApiMallGoodsListVo> selectMallGoodsListQueryNoPageIsApp(@Param("record") ApiMallGoodsQueryDto queryDto);
}
src/main/java/cc/mrbird/febs/mall/service/IAdminMallGoodsCategoryService.java
@@ -17,6 +17,8 @@
    FebsResponse addCategory(MallGoodsCategory mallGoodsCategory);
    FebsResponse addAppCategory(MallGoodsCategory mallGoodsCategory);
    List<MallGoodsCategory> getCategorys(MallGoodsCategory mallGoodsCategory);
    AdminMallGoodsCategoryVo getMallGoodsCategoryInfoById(long id);
@@ -24,8 +26,10 @@
    List<AdminMallGoodsCategoryTreeVo> getParentCategorys();
    FebsResponse updateCategory(MallGoodsCategory mallGoodsCategory);
    FebsResponse updateAppCategory(MallGoodsCategory mallGoodsCategory);
    FebsResponse delCategary(Long id);
    FebsResponse delAppCategary(Long id);
    List<AdminMallGoodsCategoryTreeVo> getAllCategorys();
}
src/main/java/cc/mrbird/febs/mall/service/IAdminMallGoodsService.java
@@ -16,8 +16,11 @@
public interface IAdminMallGoodsService extends IService<MallGoods> {
    IPage<AdminMallGoodsVo> getCategoryListInPage(MallGoods mallGoods, QueryRequest request);
    IPage<AdminMallGoodsVo> getAppCategoryListInPage(MallGoods mallGoods, QueryRequest request);
    FebsResponse addMallGoods(AddMallGoodsDto addMallGoodsDto);
    FebsResponse addMallAppGoods(AddMallGoodsDto addMallGoodsDto);
    FebsResponse upMallGoods(Long id);
@@ -32,6 +35,7 @@
    MallGoods selectGoodsById(long id);
    FebsResponse updateMallGoods(MallGoodsUpdateDto mallGoodsUpdateDto);
    FebsResponse updateAppMallGoods(MallGoodsUpdateDto mallGoodsUpdateDto);
    List<AdminMallGoodsTreeVo> getAllGoodsTree();
src/main/java/cc/mrbird/febs/mall/service/IApiMallAppService.java
New file
@@ -0,0 +1,19 @@
package cc.mrbird.febs.mall.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.MallAppMember;
import com.baomidou.mybatisplus.extension.service.IService;
public interface IApiMallAppService extends IService<MallAppMember> {
    FebsResponse appToLogin(LoginDto loginDto);
    FebsResponse appMemberInfo(ApiMallAppMemberInfoDto apiMallAppMemberInfoDto);
    FebsResponse findAllCategoryList();
    FebsResponse findMallGoodsListNoPage(ApiMallGoodsQueryDto queryDto);
    FebsResponse createAppOrder(ApiAddOrderDto addOrderDto);
}
src/main/java/cc/mrbird/febs/mall/service/IApiMallGoodsCategoryService.java
@@ -10,6 +10,8 @@
    List<MallGoodsCategoryVo> findAllCategoryList();
    List<MallGoodsCategoryVo> findAllAppCategoryList();
    List<MallGoodsCategory> findChildCategoryListById(Long id);
    List<MallGoodsCategory> findRecommendCategory();
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsCategoryService.java
@@ -2,6 +2,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.mall.entity.MallGoods;
import cc.mrbird.febs.mall.entity.MallGoodsCategory;
import cc.mrbird.febs.mall.mapper.MallGoodsCategoryMapper;
@@ -77,6 +78,46 @@
    }
    @Override
    public FebsResponse addAppCategory(MallGoodsCategory mallGoodsCategory) {
        String name = mallGoodsCategory.getName();
        if(StrUtil.isEmpty(name)){
            return new FebsResponse().fail().message("分类名称不能为空");
        }
        List<MallGoodsCategory> categorys = mallGoodsCategoryMapper.selectCategoryByName(name);
        if(CollUtil.isNotEmpty(categorys)){
            return new FebsResponse().fail().message("分类名称不能重复");
        }
//        Long parentIdParam = mallGoodsCategory.getParentId() == null ? 0L:mallGoodsCategory.getParentId();
//        Integer isRecommendParam = mallGoodsCategory.getIsRecommend();
//        if(parentIdParam > 0 && isRecommendParam == 1){
//            return new FebsResponse().fail().message("子分类不能选择【是否推荐】为【是】");
//        }
        MallGoodsCategory goodsCategory = new MallGoodsCategory();
        goodsCategory.setName(name);
        goodsCategory.setIsApp(AppContants.IS_APP_CATEGORY);
        goodsCategory.setImage(mallGoodsCategory.getImage());
        goodsCategory.setIndexNum(mallGoodsCategory.getIndexNum());
//        if(ObjectUtil.isNotEmpty(mallGoodsCategory.getParentId())){
//            Long parentId = mallGoodsCategory.getParentId();
//            MallGoodsCategory mallGoodsCategoryParent = mallGoodsCategoryMapper.selectById(parentId);
//            goodsCategory.setParentId(mallGoodsCategory.getParentId());
//            if(StrUtil.isNotEmpty(mallGoodsCategoryParent.getParentIds())){
//                goodsCategory.setParentIds(mallGoodsCategoryParent.getParentIds()+","+mallGoodsCategory.getParentId()+",");
//            }else{
//                goodsCategory.setParentIds(mallGoodsCategory.getParentId()+",");
//            }
//            goodsCategory.setIsRecommend(0);
//        }else{
//            goodsCategory.setParentId(0L);
//            goodsCategory.setIsRecommend(mallGoodsCategory.getIsRecommend());
//        }
        mallGoodsCategoryMapper.insert(goodsCategory);
        return new FebsResponse().success();
    }
    @Override
    public List<MallGoodsCategory> getCategorys(MallGoodsCategory mallGoodsCategory) {
        List<MallGoodsCategory> mallGoodsCategorys = mallGoodsCategoryMapper.getCategorys();
        return mallGoodsCategorys;
@@ -130,6 +171,42 @@
    }
    @Override
    public FebsResponse updateAppCategory(MallGoodsCategory mallGoodsCategoryParam) {
        String name = mallGoodsCategoryParam.getName();
        if(StrUtil.isEmpty(name)){
            return new FebsResponse().fail().message("名称不能为空");
        }
//        Long parentIdParam = mallGoodsCategoryParam.getParentId() == null ? 0L:mallGoodsCategoryParam.getParentId();
//        Integer isRecommendParam = mallGoodsCategoryParam.getIsRecommend();
//        if(parentIdParam > 0 && isRecommendParam == 1){
//            return new FebsResponse().fail().message("子分类不能选择【是否推荐】为【是】");
//        }
        Long id = mallGoodsCategoryParam.getId();
        MallGoodsCategory mallGoodsCategory = mallGoodsCategoryMapper.selectById(id);
        mallGoodsCategory.setName(mallGoodsCategoryParam.getName());
        mallGoodsCategory.setImage(mallGoodsCategoryParam.getImage());
        mallGoodsCategory.setIndexNum(mallGoodsCategoryParam.getIndexNum());
//        if(ObjectUtil.isNotEmpty(mallGoodsCategoryParam.getParentId())){
//            Long parentId = mallGoodsCategoryParam.getParentId();
//            MallGoodsCategory mallGoodsCategoryParent = mallGoodsCategoryMapper.selectById(parentId);
//            mallGoodsCategory.setParentId(mallGoodsCategoryParam.getParentId());
//            if(StrUtil.isNotEmpty(mallGoodsCategoryParent.getParentIds())){
//                mallGoodsCategory.setParentIds(mallGoodsCategoryParent.getParentIds()+","+mallGoodsCategory.getParentId()+",");
//            }else{
//                mallGoodsCategory.setParentIds(mallGoodsCategory.getParentId()+",");
//            }
//            mallGoodsCategory.setIsRecommend(0);
//        }else{
//            mallGoodsCategory.setParentId(0L);
//            mallGoodsCategory.setIsRecommend(mallGoodsCategoryParam.getIsRecommend());
//        }
        mallGoodsCategoryMapper.updateById(mallGoodsCategory);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse delCategary(Long id) {
        MallGoodsCategory mallGoodsCategory = mallGoodsCategoryMapper.selectById(id);
        if(ObjectUtil.isEmpty(mallGoodsCategory)){
@@ -159,6 +236,35 @@
    }
    @Override
    public FebsResponse delAppCategary(Long id) {
        MallGoodsCategory mallGoodsCategory = mallGoodsCategoryMapper.selectById(id);
        if(ObjectUtil.isEmpty(mallGoodsCategory)){
            return new FebsResponse().fail().message("系统繁忙,请刷新页面重试");
        }
        List<MallGoodsCategory> childCategarys = mallGoodsCategoryMapper.selectChildCategaryById(id);
        if(CollUtil.isNotEmpty(childCategarys)){
            for(MallGoodsCategory childCategary : childCategarys){
                Long childCategaryId = childCategary.getId();
                List<MallGoods> mallChildGoods = mallGoodsMapper.selectMallGoodsByCategaryId(childCategaryId);
                if(CollUtil.isNotEmpty(mallChildGoods)){
                    return new FebsResponse().fail().message("该分类下的子类【"+childCategary.getName()+"】还有商品,请先删除商品或者修改商品分类");
                }
            }
        }
        if(CollUtil.isNotEmpty(childCategarys)){
            return new FebsResponse().fail().message("该分类下还有子类,请先删除子类");
        }
        List<MallGoods> mallGoods = mallGoodsMapper.selectMallGoodsByCategaryId(id);
        if(CollUtil.isNotEmpty(mallGoods)){
            return new FebsResponse().fail().message("该分类下还有商品,请先删除商品或者修改商品分类");
        }
        mallGoodsCategoryMapper.deleteById(mallGoodsCategory);
        return new FebsResponse().success();
    }
    @Override
    public List<AdminMallGoodsCategoryTreeVo> getAllCategorys() {
        List<AdminMallGoodsCategoryTreeVo> adminMallGoodsCategoryTreeVos = mallGoodsCategoryMapper.getAllCategorys();
        return adminMallGoodsCategoryTreeVos;
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java
@@ -2,6 +2,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.mall.conversion.MallGoodsConversion;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.*;
@@ -44,6 +45,13 @@
    public IPage<AdminMallGoodsVo> getCategoryListInPage(MallGoods mallGoods, QueryRequest request) {
        Page<AdminMallGoodsVo> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<AdminMallGoodsVo> adminMallGoodsVos = this.baseMapper.selectMallGoodsInPage(page, mallGoods);
        return adminMallGoodsVos;
    }
    @Override
    public IPage<AdminMallGoodsVo> getAppCategoryListInPage(MallGoods mallGoods, QueryRequest request) {
        Page<AdminMallGoodsVo> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<AdminMallGoodsVo> adminMallGoodsVos = this.baseMapper.selectMallAppGoodsInPage(page, mallGoods);
        return adminMallGoodsVos;
    }
@@ -194,6 +202,23 @@
        }
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    @Transactional
    public FebsResponse addMallAppGoods(AddMallGoodsDto addMallGoodsDto) {
        String goodsNo = addMallGoodsDto.getGoodsNo();
        Integer mallGoodsByGoodsNo = mallGoodsMapper.selectMallGoodsCountByGoodsNo(goodsNo);
        if (mallGoodsByGoodsNo > 0) {
            return new FebsResponse().fail().message("商品编号不能重复");
        }
        //新增商品
        MallGoods mallGoods = MallGoodsConversion.INSTANCE.dtoToEntity(addMallGoodsDto);
        mallGoods.setIsSale(MallGoods.ISSALE_STATUS_DISABLED);
        mallGoods.setIsApp(AppContants.IS_APP_GOODS);
        mallGoodsMapper.insert(mallGoods);
        return new FebsResponse().success().message("添加成功");
    }
    @Override
@@ -470,6 +495,15 @@
    }
    @Override
    public FebsResponse updateAppMallGoods(MallGoodsUpdateDto mallGoodsUpdateDto) {
        //新增商品
        MallGoods mallGoods = mallGoodsMapper.selectById(mallGoodsUpdateDto.getId());
        BeanUtil.copyProperties(mallGoodsUpdateDto, mallGoods);
        mallGoodsMapper.updateById(mallGoods);
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    public List<AdminMallGoodsTreeVo> getAllGoodsTree() {
        return mallGoodsMapper.getAllGoodsTree();
    }
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallAppServiceImpl.java
New file
@@ -0,0 +1,104 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.MallAppMember;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.mapper.MallAppMemberMapper;
import cc.mrbird.febs.mall.mapper.MallGoodsCategoryMapper;
import cc.mrbird.febs.mall.mapper.MallGoodsMapper;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.mall.service.IApiMallAppService;
import cc.mrbird.febs.mall.vo.ApiMallAppMemberInfoVo;
import cc.mrbird.febs.mall.vo.ApiMallGoodsListVo;
import cc.mrbird.febs.mall.vo.MallGoodsCategoryVo;
import cc.mrbird.febs.mall.vo.MallGoodsListVo;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiMallAppServiceImpl  extends ServiceImpl<MallAppMemberMapper, MallAppMember> implements IApiMallAppService {
    private final RedisUtils redisUtils;
    private final MallMemberMapper mallMemberMapper;
    private final MallGoodsCategoryMapper mallGoodsCategoryMapper;
    private final MallGoodsMapper mallGoodsMapper;
    @Override
    public FebsResponse appToLogin(LoginDto loginDto) {
        String md5Pwd = SecureUtil.md5(loginDto.getPassword());
        MallMember mallMember = mallMemberMapper.selectInfoByAccountAndPwd(loginDto.getAccount(), md5Pwd);
        if (mallMember == null) {
            throw new FebsException("用户不存在或账号密码错误");
        }
        String redisKey = AppContants.SY_APP_LOGIN_PREFIX + mallMember.getId();
        String existToken = redisUtils.getString(redisKey);
        if (StrUtil.isNotBlank(existToken)) {
            Object o = redisUtils.get(existToken);
            if (ObjectUtil.isNotEmpty(o)) {
                redisUtils.del(existToken);
            }
        }
        String token = IdUtil.simpleUUID();
        redisUtils.set(token, JSONObject.toJSONString(mallMember));
        redisUtils.set(redisKey, token);
        Map<String, Object> authInfo = new HashMap<>();
        authInfo.put("token", token);
        authInfo.put("rasToken", generateAsaToken(token));
        return new FebsResponse().success().data(authInfo);
    }
    @Override
    public FebsResponse appMemberInfo(ApiMallAppMemberInfoDto apiMallAppMemberInfoDto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        List<ApiMallAppMemberInfoVo> mallMembers = this.baseMapper.selectMemberInfoLikePhone(apiMallAppMemberInfoDto.getPhone());
        return new FebsResponse().success().data(mallMembers);
    }
    @Override
    public FebsResponse findAllCategoryList() {
        List<MallGoodsCategoryVo> mallGoodsCategoryVos = mallGoodsCategoryMapper.selectAllCategoryListByIsApp(AppContants.IS_APP_CATEGORY);
        return new FebsResponse().success().data(mallGoodsCategoryVos);
    }
    @Override
    public FebsResponse findMallGoodsListNoPage(ApiMallGoodsQueryDto queryDto) {
        List<ApiMallGoodsListVo> mallGoodsListVos = mallGoodsMapper.selectMallGoodsListQueryNoPageIsApp(queryDto);
        return new FebsResponse().success().data(mallGoodsListVos);
    }
    @Override
    public FebsResponse createAppOrder(ApiAddOrderDto addOrderDto) {
//        return new FebsResponse().success().data(orderId).message("创建订单成功");
        return new FebsResponse().success().message("创建订单成功");
    }
    public String generateAsaToken(String token) {
        RSA rsa = new RSA(null, AppContants.PUBLIC_KEY);
        return rsa.encryptBase64(token + "_" + System.currentTimeMillis(), KeyType.PublicKey);
    }
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallGoodsCategoryServiceImpl.java
@@ -27,6 +27,11 @@
    }
    @Override
    public List<MallGoodsCategoryVo> findAllAppCategoryList() {
        return this.baseMapper.selectAllAppCategoryList();
    }
    @Override
    public List<MallGoodsCategory> findChildCategoryListById(Long id) {
        return this.baseMapper.selectCategoryListByParentId(id);
    }
src/main/java/cc/mrbird/febs/mall/vo/ApiMallAppMemberInfoVo.java
New file
@@ -0,0 +1,26 @@
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiMallAppMemberInfoVo", description = "返回参数类")
public class ApiMallAppMemberInfoVo {
    @ApiModelProperty(value = "头像")
    private String avatar;
    @ApiModelProperty(value = "昵称")
    private String nickname;
    @ApiModelProperty(value = "电话号码")
    private String phone;
    @ApiModelProperty(value = "余额")
    private String balance;
    @ApiModelProperty(value = "积分")
    private String score;
}
src/main/java/cc/mrbird/febs/mall/vo/ApiMallGoodsListVo.java
New file
@@ -0,0 +1,34 @@
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
@ApiModel(value = "ApiMallGoodsListVo", description = "商城商品列表")
public class ApiMallGoodsListVo {
    @ApiModelProperty(value = "id")
    private Long id;
    @ApiModelProperty(value = "商品名称")
    private String goodsName;
    @ApiModelProperty(value = "主图")
    private String thumb;
    @ApiModelProperty(value = "原价")
    private String originalPrice;
    @ApiModelProperty(value = "现价")
    private String presentPrice;
    @ApiModelProperty(value = "1:按数量计价 2:按重量计价")
    private String unit;
    @ApiModelProperty(value = "积分")
    private BigDecimal score;
}
src/main/resources/application-test.yml
@@ -30,7 +30,7 @@
    # Redis服务器地址
    host: 120.27.238.55
    # Redis服务器连接端口
    port: 6379
    port: 6479
    # Redis 密码
    password: d3y6dsdl;f.327
    lettuce:
src/main/resources/mapper/modules/MallAppMemberMapper.xml
New file
@@ -0,0 +1,24 @@
<?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="cc.mrbird.febs.mall.mapper.MallAppMemberMapper">
    <select id="selectByAccountAndPassword" resultType="cc.mrbird.febs.mall.entity.MallAppMember">
        select * from mall_app_member
        where
            account = #{account}
            and password = #{password}
    </select>
    <select id="selectMemberInfoLikePhone" resultType="cc.mrbird.febs.mall.vo.ApiMallAppMemberInfoVo">
        select
            a.avatar phone,
            a.name nickname,
            a.phone phone,
            IFNULL(b.balance,0) balance,
            IFNULL(b.score,0) score
        from mall_member a
        left join mall_member_wallet b on a.id = b.member_id
        where
            a.phone like concat('%',  #{phone})
    </select>
</mapper>
src/main/resources/mapper/modules/MallGoodsCategoryMapper.xml
@@ -11,6 +11,9 @@
                <if test="record.name!=null and record.name!=''">
                    and m.name like concat('%',  #{record.name},'%')
                </if>
                <if test="record.isApp != null and record.isApp != ''">
                    and m.is_app = #{record.isApp}
                </if>
            </if>
        </where>
        order by m.parent_id,m.index_num asc
@@ -49,6 +52,16 @@
        from mall_goods_category a
          left join mall_goods_category b on a.id=b.parent_id
        where a.parent_id = 0
          and a.is_app is NULL
        order by a.index_num asc
    </select>
    <select id="selectAllAppCategoryList" resultMap="mallGoodsCategoryVoMap">
        select
            a.id,
            a.name
        from mall_goods_category a
        where a.is_app = 1
        order by a.index_num asc
    </select>
@@ -60,7 +73,9 @@
    <select id="selectRecommendCategoryList" resultType="cc.mrbird.febs.mall.entity.MallGoodsCategory">
        select * from mall_goods_category
        where parent_id=0 and is_recommend = 1
        where parent_id=0
          and is_recommend = 1
          and is_app is NULL
        order by index_num asc
    </select>
@@ -81,4 +96,21 @@
    <select id="getAllCategorys" resultType="cc.mrbird.febs.mall.vo.AdminMallGoodsCategoryTreeVo">
        SELECT m.id parentId,m.name name  FROM mall_goods_category m ;
    </select>
    <select id="selectAllCategoryListByIsApp" resultMap="mallGoodsCategoryVoMap">
        select
            a.id,
            a.name,
            a.image,
            a.parent_id,
            b.id child_id,
            b.name child_name,
            b.parent_id child_parent_id
        from mall_goods_category a
                 left join mall_goods_category b on a.id=b.parent_id
        where a.parent_id = 0
        and a.is_app = #{isApp}
        order by a.index_num asc
    </select>
</mapper>
src/main/resources/mapper/modules/MallGoodsMapper.xml
@@ -81,6 +81,7 @@
                 left join mall_goods_category c on a.category_id=c.id
            <where>
                a.is_sale=1
                and a.is_app is null
                <if test="record != null">
                    <if test="record.isHot != null and record.isHot != ''">
                        and a.is_hot = #{record.isHot}
@@ -146,12 +147,41 @@
        left join mall_goods_category b on b.id = a.category_id
        left join mall_goods_sku c on c.goods_id = a.id
        <where>
            a.is_app is null
            <if test="record != null">
                <if test="record.goodsName != null and record.goodsName != ''">
                    and a.goods_name like CONCAT('%', CONCAT(#{record.goodsName}, '%'))
                </if>
                <if test="record.goodsType != null and record.goodsType != ''">
                    and a.goods_type=#{record.goodsType}
                </if>
            </if>
        </where>
        group by a.id
        order by a.created_time desc
    </select>
    <select id="selectMallAppGoodsInPage" resultType="cc.mrbird.febs.mall.vo.AdminMallGoodsVo">
        select
        a.id,
        a.goods_name,
        a.goods_no,
        a.unit,
        a.thumb,
        a.is_sale,
        a.original_price,
        a.present_price,
        a.score,
        a.volume saleVolume,
        b.name categaryName,
        a.stock
        from mall_goods a
        left join mall_goods_category b on b.id = a.category_id
        <where>
            a.is_app = 1
            <if test="record != null">
                <if test="record.goodsName != null and record.goodsName != ''">
                    and a.goods_name like CONCAT('%', CONCAT(#{record.goodsName}, '%'))
                </if>
            </if>
        </where>
@@ -298,6 +328,8 @@
        left join mall_goods_category c on a.category_id=c.id
        <where>
            a.is_sale=1
            and
            a.is_app is null
            <if test="record != null">
                <if test="record.isHot != null and record.isHot != ''">
                    and a.is_hot = #{record.isHot}
@@ -341,4 +373,26 @@
        </if>
    </select>
    <select id="selectMallGoodsListQueryNoPageIsApp" resultType="cc.mrbird.febs.mall.vo.ApiMallGoodsListVo">
        select
            a.id,
            a.goods_name,
            a.thumb,
            a.original_price,
            a.present_price,
            a.unit,
            a.score
        from mall_goods a
        left join mall_goods_category c on a.category_id=c.id
        <where>
            <if test="record != null">
                <if test="record.categoryId != null and record.categoryId != ''">
                    and (c.id = #{record.categoryId} or c.parent_id=#{record.categoryId})
                </if>
            </if>
        </where>
        group by a.id
        order by a.id desc
    </select>
</mapper>
src/main/resources/templates/febs/views/modules/goods/goodsAppAddNew.html
New file
@@ -0,0 +1,234 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-goods-app-add" lay-title="新增APP商品">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-fluid" id="goods-app-add">
            <form class="layui-form" action="" lay-filter="goods-app-add-form">
                <div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
                    <ul class="layui-tab-title">
                        <li class="layui-this">基础信息</li>
                    </ul>
                    <div class="layui-tab-content">
                        <div class="layui-tab-item layui-show">
                            <blockquote class="layui-elem-quote blue-border">基本信息设置</blockquote>
                            <div class="layui-row layui-col-space10 layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品名称:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="goodsName" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品编号:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="goodsNo" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品分类:</label>
                                    <div class="layui-input-block">
                                        <div id="goods-category"></div>
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">单位</label>
                                    <div class="layui-input-block">
                                        <select name="unit">
                                            <option value="1">按数量</option>
                                            <option value="2">按重量</option>
                                        </select>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">原价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="originalPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">现价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="presentPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
<!--                                        <div class="layui-form-mid layui-word-aux">现价设置为0进入零撸专区</div>-->
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">成本价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="costPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">库存:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="stock"  lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">销量:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="volume"  lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <label class="layui-form-label febs-form-item-require">缩略图:</label>
                                <div class="layui-input-block">
                                    <div class="layui-upload">
                                        <button type="button" class="layui-btn layui-btn-normal layui-btn" id="test2">上传</button>
                                        <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                                            <div class="layui-upload-list" id="demo2"></div>
                                        </blockquote>
<!--                                        <div class="layui-word-aux">双击图片删除</div>-->
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
<!--                            <div class="layui-form-item febs-hide">-->
                                <label class="layui-form-label">缩略图链接:</label>
                                <div class="layui-input-block">
                                    <input type="text" id="thumb" lay-verify="required" name="thumb" autocomplete="off" class="layui-input" readonly>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="layui-form-item febs-hide">
                    <button class="layui-btn" lay-submit="" lay-filter="goods-app-add-form-submit" id="submit">保存</button>
                </div>
            </form>
        </div>
        </div>
    </div>
</div>
<style>
    .blue-border {
        border-left-color: #2db7f5;
        font-size: 18px;
    }
    .layui-table-cell {
        height:auto;
    }
    .layui-upload-list {
        margin: 0 !important;
    }
    .multi-images {
        margin: 0 5px !important;
    }
</style>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delSku">删除</button>
    </div>
</script>
<script type="text/html" id="tableImgUpload">
    <div class="layui-upload">
        <button type="button" class="layui-btn layui-btn-normal layui-btn-xs sku-img" id="skuImg{{d.index}}">上传</button></br>
        <img class="layui-upload-img" id="imageUrls{{d.index}}" style="width: 100px; display:none;" src="{{d.skuImage}}" >
        <input type="text" id="skuImage{{d.index}}" name="skuImage{{d.index}}" autocomplete="off" value="{{d.skuImage}}" class="layui-input febs-hide">
    </div>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','dropdown', 'laydate', 'layedit', 'upload', 'element', 'table', 'xmSelect'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            layer = layui.layer,
            table = layui.table,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            $view = $('#goods-app-add'),
            layedit = layui.layedit,
            upload = layui.upload,
            validate = layui.validate,
            element = layui.element;
        form.render();
        formSelects.render();
        var category = xmSelect.render({
            el: '#goods-category',
            language: 'zn',
            prop : {
                value : 'id',
                children : 'child'
            },
            iconfont: {
                parent: 'hidden',
            },
            radio: true,
            clickClose: true,
            tree: {
                show: true,
                //非严格模式
                strict: false,
            },
            data: []
        })
        febs.get(ctx + 'admin/goodsCategory/categoryAppTree', null, function(res) {
            category.update({
                data : res.data,
                autoRow: true,
            });
        })
        //图片上传
        upload.render({
            elem: '#test2'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,multiple: true
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    if ($("#thumb").val()) {
                        $('#demo2').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">')
                    } else {
                        $('#demo2').append('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">')
                    }
                });
            }
            ,done: function(res){
                $("#thumb").val(res.data.src);
            }
        });
        form.on('submit(goods-app-add-form-submit)', function (data) {
            data.field.goodsType = 1;
            data.field.categoryId = category.getValue('valueStr');
            $.ajax({
                'url':ctx + 'admin/goods/addMallAppGoods',
                'type':'post',
                'dataType':'json',
                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
                'traditional': true,//ajax传递数组必须添加属性
                'data':JSON.stringify(data.field),
                'success':function (data) {
                    if(data.code==200){
                        layer.closeAll();
                        febs.alert.success(data.message);
                        $('#febs-app-goods').find('#reset').click();
                    }else{
                        febs.alert.warn(data.message);
                    }
                },
                'error':function () {
                    febs.alert.warn('服务器繁忙');
                }
            })
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/goods/goodsAppList.html
New file
@@ -0,0 +1,229 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-app-goods" lay-title="APP商品列表">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="user-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md10">
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <div class="layui-input-inline">
                                            <input type="text" placeholder="名称" name="goodsName" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
                                    新增
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="appGoodsTable" lay-data="{id: 'appGoodsTable'}"></table>
                    <style type="text/css">
                        .layui-table-cell{
                            text-align:center;
                            height: auto;
                            white-space: nowrap; /*文本不会换行,在同一行显示*/
                            overflow: hidden; /*超出隐藏*/
                            text-overflow: ellipsis; /*省略号显示*/
                        }
                        .layui-table img{
                            max-width:100px
                        }
                    </style>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
    <span shiro:lacksPermission="user:view,user:update,user:delete">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    <a lay-event="edit" shiro:hasPermission="user:update"><i
            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
</script>
<script type="text/html" id="upOrDownSwitch">
    {{# if(d.isSale === 1) { }}
    <input type="checkbox" value={{d.id}} lay-text="上架|下架" checked lay-skin="switch" lay-filter="upOrDownSwitch">
    {{# } else { }}
    <input type="checkbox" value={{d.id}} lay-text="上架|下架" lay-skin="switch" lay-filter="upOrDownSwitch">
    {{# } }}
</script>
<style>
    .layui-form-onswitch {
        background-color: #5FB878 !important;
    }
</style>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            $view = $('#febs-app-goods'),
            $query = $view.find('#query'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            $add = $view.find('#add'),
            sortObject = {field: 'phone', type: null},
            tableIns;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(appGoodsTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'downGoods') {
                febs.modal.confirm('下架', '确认下架该商品?', function () {
                    downGoods(data.id);
                });
            }
            if (layEvent === 'upGoods') {
                febs.modal.confirm('上架', '确认上架该商品?', function () {
                    upGoods(data.id);
                });
            }
            if (layEvent === 'delGoods') {
                febs.modal.confirm('删除', '确认删除该商品?', function () {
                    delGoods(data.id);
                });
            }
            if (layEvent === 'goodsAppUpdate') {
                febs.modal.open('编辑', 'modules/goods/goodsAppUpdateNew/' + data.id, {
                    btn: ['提交', '取消'],
                    area:['100%','100%'],
                    yes: function (index, layero) {
                        $('#febs-app-update').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
            if (layEvent === 'seeImgThumb') {
                var t = $view.find('#seeImgThumb'+data.id+'');
                //页面层
                layer.open({
                    type: 1,
                    title: "图片",
                    skin: 'layui-layer-rim', //加上边框
                    area: ['80%', '80%'], //宽高
                    shadeClose: true, //开启遮罩关闭
                    end: function (index, layero) {
                        return false;
                    },
                    content: '<div style="text-align:center"><img src="' + $(t).attr('src') + '" /></div>'
                });
            }
        });
        function downGoods(id) {
            febs.get(ctx + 'admin/goods/downMallGoods/' + id, null, function () {
                febs.alert.success('下架成功');
                $query.click();
            });
        }
        function delGoods(id) {
            febs.get(ctx + 'admin/goods/delMallGoods/' + id, null, function () {
                febs.alert.success('删除成功');
                $query.click();
            });
        }
        function upGoods(id) {
            febs.get(ctx + 'admin/goods/upMallGoods/' + id, null, function () {
                febs.alert.success('上架成功');
                $query.click();
            });
        }
        // 查询按钮
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        // 刷新按钮
        $reset.on('click', function () {
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        $add.on('click', function () {
            febs.modal.open('新增商品', 'modules/goods/goodsAppAddNew/', {
                btn: ['提交', '取消'],
                area:['100%','100%'],
                yes: function (index, layero) {
                    $('#febs-goods-app-add').find('#submit').trigger('click');
                },
                btn2: function () {
                    layer.closeAll();
                }
            });
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'appGoodsTable',
                url: ctx + 'admin/goods/goodsAppList',
                cols: [[
                    {field: 'goodsNo', title: '商品编号', minWidth: 100,align:'left'},
                    {field: 'goodsName', title: '商品名称', minWidth: 140,align:'left'},
                    {field: 'thumb', title: '缩略图',
                        templet: function (d) {
                            return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.thumb+'" alt=""></a>';
                        }, minWidth: 150,align:'center'},
                    {field: 'categaryName', title: '分类', minWidth: 140,align:'left'},
                    {field: 'isSale', title: '是否上架', templet: '#upOrDownSwitch', minWidth: 100,align:'center'},
                    {field: 'presentPrice', title: '现价', minWidth: 100,align:'left'},
                    {field: 'originalPrice', title: '原价', minWidth: 100,align:'left'},
                    {field: 'stock', title: '商品库存', minWidth: 100,align:'left'},
                    {field: 'saleVolume', title: '商品销量', minWidth: 100,align:'left'},
                    {title: '操作',
                        templet: function (d) {
                            if (d.isSale === 1) {
                                return '';
                            }else{
                                return  '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="goodsAppUpdate" shiro:hasPermission="user:update">编辑</button>'
                                    + '<button class="layui-btn layui-btn-normal layui-btn-xs febs-bg-red" lay-event="delGoods" shiro:hasPermission="user:update">删除</button>'
                            }
                        },minWidth: 160,align:'center'}
                ]]
            });
        }
        form.on('switch(upOrDownSwitch)', function (data) {
            if (data.elem.checked) {
                upGoods(data.value);
            } else {
                downGoods(data.value);
            }
        })
        // 获取查询参数
        function getQueryParams() {
            return {
                goodsName: $searchForm.find('input[name="goodsName"]').val().trim(),
            };
        }
    })
</script>
src/main/resources/templates/febs/views/modules/goods/goodsAppUpdateNew.html
New file
@@ -0,0 +1,280 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-app-update" lay-title="编辑商品">
    <div class="layui-row febs-container">
        <div class="layui-col-md12"><div class="layui-fluid" id="goods-app-update">
            <form class="layui-form" action="" lay-filter="goods-app-update-form">
                <div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
                    <ul class="layui-tab-title">
                        <li class="layui-this">基础信息</li>
                    </ul>
                    <input type="text" name="id"
                           placeholder="" autoComplete="off" class="layui-input febs-hide">
                    <div class="layui-tab-content">
                        <div class="layui-tab-item layui-show">
                            <blockquote class="layui-elem-quote blue-border">基本信息设置</blockquote>
                            <div class="layui-row layui-col-space10 layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品名称:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="goodsName" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品编号:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="goodsNo" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">商品分类:</label>
                                    <div class="layui-input-block">
                                        <div id="goods-category"></div>
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">单位</label>
                                    <div class="layui-input-block">
                                        <select name="unit">
                                            <option value="1">按数量</option>
                                            <option value="2">按重量</option>
                                        </select>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">原价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="originalPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">现价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="presentPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                        <!--                                        <div class="layui-form-mid layui-word-aux">现价设置为0进入零撸专区</div>-->
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">成本价:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="costPrice" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">库存:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="stock"  lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                                <div class="layui-col-lg6">
                                    <label class="layui-form-label febs-form-item-require">销量:</label>
                                    <div class="layui-input-block">
                                        <input type="text" name="volume"  lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <label class="layui-form-label febs-form-item-require">缩略图:</label>
                                <div class="layui-input-block">
                                    <div class="layui-upload">
                                        <button type="button" class="layui-btn layui-btn-normal layui-btn" id="test2">上传</button>
                                        <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                                            <div class="layui-upload-list" id="demo2"></div>
                                        </blockquote>
                                        <!--                                        <div class="layui-word-aux">双击图片删除</div>-->
                                    </div>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <!--                            <div class="layui-form-item febs-hide">-->
                                <label class="layui-form-label">缩略图链接:</label>
                                <div class="layui-input-block">
                                    <input type="text" id="thumb" lay-verify="required" name="thumb" autocomplete="off" class="layui-input" readonly>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="layui-form-item febs-hide" style="text-align:center">
                    <button class="layui-btn" lay-submit="" lay-filter="goods-app-update-form-submit"
                            id="submit">
                    </button>
                </div>
            </form>
        </div>
        </div>
    </div>
</div>
<style>
    .blue-border {
        border-left-color: #2db7f5;
        font-size: 18px;
    }
    .layui-table-cell {
        height: auto;
    }
    .layui-upload-list {
        margin: 0 !important;
    }
    .multi-images {
        margin: 0 5px !important;
    }
</style>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delSku">删除</button>
    </div>
</script>
<script type="text/html" id="tableImgUpload">
    <div class="layui-upload">
        <button type="button" class="layui-btn layui-btn-normal layui-btn-xs sku-img" id="skuImg{{d.index}}">上传
        </button>
        </br>
        <img class="layui-upload-img" id="imageUrls{{d.index}}" style="width: 100px; display:none;"
             src="{{d.skuImage}}">
        <input type="text" id="skuImage{{d.index}}" name="skuImage{{d.index}}" autoComplete="off" value="{{d.skuImage}}"
               class="layui-input febs-hide">
    </div>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'dropdown', 'laydate', 'layedit', 'upload', 'element', 'table', 'xmSelect'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            layer = layui.layer,
            table = layui.table,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            goodsInfo = [[${goodsInfo}]],
            $view = $('#goods-app-update'),
            layedit = layui.layedit,
            upload = layui.upload,
            validate = layui.validate,
            element = layui.element;
        form.render();
        formSelects.render();
        var category = xmSelect.render({
            el: '#goods-category',
            language: 'zn',
            prop : {
                value : 'id',
                children : 'child'
            },
            iconfont: {
                parent: 'hidden',
            },
            radio: true,
            clickClose: true,
            tree: {
                show: true,
                //非严格模式
                strict: false,
            },
            data: []
        })
        febs.get(ctx + 'admin/goodsCategory/categoryAppTree', null, function(res) {
            category.update({
                data : res.data,
                autoRow: true,
            });
            initValue();
        })
        //图片上传
        upload.render({
            elem: '#test2'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,multiple: true
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    if ($("#thumb").val()) {
                        $('#demo2').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">')
                    } else {
                        $('#demo2').append('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">')
                    }
                });
            }
            ,done: function(res){
                $("#thumb").val(res.data.src);
            }
        });
        function initValue() {
            form.val("goods-app-update-form", {
                "id": goodsInfo.id,
                "goodsName": goodsInfo.goodsName,
                "goodsNo": goodsInfo.goodsNo,
                "unit": goodsInfo.unit,
                "stock": goodsInfo.stock,
                "volume": goodsInfo.volume,
                "originalPrice": goodsInfo.originalPrice,
                "presentPrice": goodsInfo.presentPrice,
                "costPrice": goodsInfo.costPrice,
                "thumb": goodsInfo.thumb
            });
            var arr = [];
            arr.push(goodsInfo.categoryId)
            category.setValue(arr);
            $('#demo2').append('<img src="' + goodsInfo.thumb + '" alt="" class="layui-upload-img single-image" style="width: 130px">')
        }
        form.on('submit(goods-app-update-form-submit)', function (data) {
            data.field.categoryId = category.getValue('valueStr');
            $.ajax({
                'url': ctx + 'admin/goods/updateAppMallGoods',
                'type': 'post',
                'dataType': 'json',
                'headers': {'Content-Type': 'application/json;charset=utf-8'}, //接口json格式
                'traditional': true,//ajax传递数组必须添加属性
                'data': JSON.stringify(data.field),
                'success': function (data) {
                    if (data.code == 200) {
                        layer.closeAll();
                        febs.alert.success(data.message);
                        $('#febs-app-goods').find('#reset').click();
                    } else {
                        febs.alert.warn(data.message);
                    }
                },
                'error': function () {
                    febs.alert.warn('服务器繁忙');
                }
            })
            return false;
        });
        form.on('select(goods-type-select)', function (data) {
            $('.tc-set').each(function () {
                if (data.value == 2) {
                    $(this).show();
                } else {
                    $(this).hide();
                }
            })
        });
    });
</script>
src/main/resources/templates/febs/views/modules/product/categoryAppAdd.html
New file
@@ -0,0 +1,130 @@
<style>
    #categary-app-add {
        padding: 20px 25px 25px 0;
    }
    #categary-app-add .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #categary-app-add #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #categary-app-add .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #categary-app-add img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="categary-app-add">
    <form class="layui-form" action="" lay-filter="categary-app-add-form">
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">名称:</label>
            <div class="layui-input-block">
                <input type="text" name="name"
                       lay-verify="required" autocomplete="off" class="layui-input" >
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--                <label class="layui-form-label">父类:</label>-->
<!--                <div class="layui-input-inline">-->
<!--                    <select name="parentId" class="categary-app-add-category">-->
<!--                        <option value="">请选择</option>-->
<!--                    </select>-->
<!--                </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">图片:</label>
            <div class="layui-upload">
                <button type="button" class="layui-btn" id="test1">上传图片</button>
                <div class="layui-input-block">
                    <div class="layui-upload-list">
                        <img class="layui-upload-img" id="imageUrls" width="100%" >
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label ">图片链接:</label>
            <div class="layui-input-block">
                <input type="text" id="imageUrl" lay-verify="required" name="image" class="layui-input" readonly>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">排序:</label>
            <div class="layui-input-block">
                <input type="number" name="indexNum"
                       lay-verify="indexNum" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="categary-app-add-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate','upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            member = [[${member}]],
            $view = $('#categary-app-add'),
            upload = layui.upload,
            validate = layui.validate;
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        formSelects.render();
        //普通图片上传
        var uploadInst = upload.render({
            elem: '#test1'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    $('#imageUrls').attr('src', result); //图片链接(base64)
                });
            }
            ,done: function(res){
                febs.alert.success(res.data.src);
                $("#imageUrl").val(res.data.src);
            }
        });
        //(下拉框)
        // $.get(ctx + 'admin/goodsCategory/categorys/tree', function (data) {
        //     for (var k in data)
        //     {
        //         $(".categary-app-add-category").append("<option value='" + data[k].parentId + "'>" + data[k].name + "</option>");
        //     }
        //     layui.use('form', function () {
        //         var form = layui.form;
        //         form.render();
        //     });
        // });
        form.on('submit(categary-app-add-form-submit)', function (data) {
            febs.post(ctx + 'admin/goodsCategory/addAppCategory', data.field, function () {
                layer.closeAll();
                febs.alert.success('新增成功');
                $('#febs-app-category').find('#reset').click();
            });
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/product/categoryAppList.html
New file
@@ -0,0 +1,174 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-app-category" lay-title="APP商品分类">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="user-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md10">
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <div class="layui-input-inline">
                                            <input type="text" placeholder="名称" name="name" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
                                    新增
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="appCategoryTable" lay-data="{id: 'appCategoryTable'}"></table>
                    <style type="text/css">
                        .layui-table-cell{
                            text-align:center;
                            height: auto;
                            white-space: normal;
                        }
                        .layui-table img{
                            max-width:100px
                        }
                    </style>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
    <span shiro:lacksPermission="user:view,user:update,user:delete">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    <a lay-event="edit" shiro:hasPermission="user:update"><i
            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            $view = $('#febs-app-category'),
            $query = $view.find('#query'),
            $add = $view.find('#add'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'phone', type: null},
            tableIns;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(appCategoryTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'see') {
                febs.modal.open('编辑', 'modules/product/categoryAppUpdate/' + data.id, {
                    btn: ['提交', '取消'],
                    yes: function (index, layero) {
                        $('#categary-app-update').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
            if (layEvent === 'delCategary') {
                febs.modal.confirm('删除', '确认删除?', function () {
                    delCategary(data.id);
                });
            }
            if (layEvent === 'seeImges') {
                var t = $view.find('#seeImges'+data.id+'');
                //页面层
                layer.open({
                    type: 1,
                    title: "图片",
                    skin: 'layui-layer-rim', //加上边框
                    area: ['80%', '80%'], //宽高
                    shadeClose: true, //开启遮罩关闭
                    end: function (index, layero) {
                        return false;
                    },
                    content: '<div style="text-align:center"><img src="' + $(t).attr('src') + '" /></div>'
                });
            }
        });
        function delCategary(id) {
            febs.get(ctx + 'admin/goodsCategory/delAppCategary/' + id, null, function () {
                febs.alert.success('操作成功');
                $query.click();
            });
        }
        // 查询按钮
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        // 刷新按钮
        $reset.on('click', function () {
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        $add.on('click', function () {
            febs.modal.open('新增', 'modules/product/categoryAppAdd/', {
                btn: ['提交', '取消'],
                yes: function (index, layero) {
                    $('#categary-app-add').find('#submit').trigger('click');
                },
                btn2: function () {
                    layer.closeAll();
                }
            });
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'appCategoryTable',
                url: ctx + 'admin/goodsCategory/categoryAppList',
                cols: [[
                    {field: 'name', title: '名称', minWidth: 150,align:'left'},
                    {field: 'image', title: '图片',
                        templet: function (d) {
                            return '<a lay-event="seeImges"><img id="seeImges'+d.id+'" src="'+d.image+'" alt=""></a>';
                        }, minWidth: 100,align:'center'},
                    {field: 'indexNum', title: '排序', minWidth: 150,align:'left'},
                    {title: '操作',
                        templet: function (d) {
                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="see" shiro:hasPermission="user:update">编辑</button>'
                            +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="delCategary" shiro:hasPermission="user:update">删除</button>'
                        },minWidth: 300,align:'center'}
                ]]
            });
        }
        // 获取查询参数
        function getQueryParams() {
            return {
                name: $searchForm.find('input[name="name"]').val().trim(),
            };
        }
    })
</script>
src/main/resources/templates/febs/views/modules/product/categoryAppUpdate.html
New file
@@ -0,0 +1,149 @@
<style>
    #categary-app-update {
        padding: 20px 25px 25px 0;
    }
    #categary-app-update .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #categary-app-update #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #categary-app-update .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #categary-app-update img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="categary-app-update">
    <form class="layui-form" action="" lay-filter="categary-app-update-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">id:</label>
            <div class="layui-input-block">
                <input type="text" name="id" data-th-value="${goodsCategoryVo.id}">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">名称:</label>
            <div class="layui-input-block">
                <input type="text" name="name"
                       lay-verify="name" autocomplete="off" class="layui-input" >
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--            <label class="layui-form-label">父类:</label>-->
<!--            <div class="layui-input-inline">-->
<!--                <select name="parentId" class="categary-app-update-category" id="categarySelect">-->
<!--                    <option value="">请选择</option>-->
<!--                </select>-->
<!--            </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label">图片:</label>
            <div class="layui-upload">
                <button type="button" class="layui-btn" id="test1">上传图片</button>
                <div class="layui-input-block">
                    <div class="layui-upload-list">
                        <img class="layui-upload-img" id="imageUrls" width="100%" >
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">图片链接:</label>
            <div class="layui-input-block">
                <input type="text" id="imageUrl" name="image" class="layui-input" readonly>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">排序:</label>
            <div class="layui-input-block">
                <input type="number" name="indexNum"
                       lay-verify="indexNum" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="categary-app-update-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate','upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            goodsCategoryVo = [[${goodsCategoryVo}]],
            $view = $('#categary-app-update'),
            upload = layui.upload,
            validate = layui.validate;
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        formSelects.render();
        //普通图片上传
        var uploadInst = upload.render({
            elem: '#test1'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    $('#imageUrls').attr('src', result); //图片链接(base64)
                });
            }
            ,done: function(res){
                febs.alert.success(res.data.src);
                $("#imageUrl").val(res.data.src);
            }
        });
        //(下拉框)
        // $.get(ctx + 'admin/goodsCategory/categorys/tree', function (data) {
        //     for (var k in data)
        //     {
        //         $(".categary-app-update-category").append("<option value='" + data[k].parentId + "'>" + data[k].name + "</option>");
        //     }
        //     layui.use('form', function () {
        //         var form = layui.form;
        //         $("#categarySelect").val(goodsCategoryVo.parentId)
        //         form.render();
        //     });
        // });
        initUserValue();
        function initUserValue() {
            $('#imageUrls').attr('src', goodsCategoryVo.image);
            form.val("categary-app-update-form", {
                "id": goodsCategoryVo.id,
                "name": goodsCategoryVo.name,
                // "parentId": goodsCategoryVo.parentId,
                "image": goodsCategoryVo.image,
                "indexNum": goodsCategoryVo.indexNum
            });
        }
        form.on('submit(categary-app-update-form-submit)', function (data) {
            febs.post(ctx + 'admin/goodsCategory/updateAppCategory', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-app-category').find('#reset').click();
            });
            return false;
        });
    });
</script>