后台管理开发文档
in JavaDevelop with 0 comment

后台管理开发文档

in JavaDevelop with 0 comment

1 后端项目创建

1.1 结构如图所示

在这里插入图片描述

1.2 项目demo测试

在这里插入图片描述

2. 前端环境搭建

2.1 VUE项目运行测试

2.1.1 运行项目

在这里插入图片描述

2.1.2 启动APP展现项目

在这里插入图片描述

2.1.3 关闭编码格式校验

在这里插入图片描述

2.1.4 删除默认样式

在这里插入图片描述

2.1.5 删除默认路由

在这里插入图片描述

2.1.6 删除默认Hello组件

在这里插入图片描述

3. 用户登陆模块创建

3.1 登陆准备

3.1.1 创建文件

在这里插入图片描述

3.1.2 编辑路由文件

1).编辑路由文件
在这里插入图片描述
2).指定路由占位符
在这里插入图片描述
3).路由测试
在这里插入图片描述

3.1.3 设定默认路径跳转

当用户访问 根目录时,要求重定向到登陆组件
在这里插入图片描述

3.1.4 导入静态资源文件

将课前资料中的文件导入项目中
在这里插入图片描述

3.1.5 用户访问测试

在这里插入图片描述

3.2 用户数据验证

1).定义表单校验规则
在这里插入图片描述
2).定义校验规则JS
在这里插入图片描述
3).效果展现
在这里插入图片描述

3.3 表单数据重置

3.3.1 业务需求说明

当点击重置表单按钮时 应该清空数据
在这里插入图片描述

3.3.2 实现重置

在这里插入图片描述

3.4 登录预校验

3.4.1 elementUI API

当用户输入数据之后,需要对数据进行校验.当数据有效时 才能提交数据.
在这里插入图片描述

3.4.2 编辑登录按钮的JS

在这里插入图片描述

3.5 导入Axios组件

3.5.1 导入axios组件

说明:在main.js中添加如下代码

/* 导入axios包 */
import axios from 'axios'
/* 设定axios的请求根目录 */
axios.defaults.baseURL = 'http://localhost:8091/'
/* 向vue对象中添加全局对象 以后发送ajax请求使用$http对象 */
Vue.prototype.$http = axios

3.6 用户登录

3.6.1 发送Ajax请求

在这里插入图片描述

3.6.2 编辑UserController

在这里插入图片描述

3.6.3 编辑UserService

在这里插入图片描述

3.6.4 返回值类型

	{"status":200,"msg":"服务器调用成功!","data":"1e893a97634847b3a8b499b173bea620"}

3.7 保存用户信息

3.7.1 业务说明

说明: 当用户登陆成功之后,将token保存到客户端中的sessionStorage中. 因为用户的其他操作都必须保证用户已经登录之后才能操作. 所以通过SessionStorage保存用户的token记录 表示已经登陆.

3.7.2 编辑页面JS

在这里插入图片描述

3.7.3 浏览器效果展现

在这里插入图片描述

3.8 跳转Home页面

3.8.1 编辑路由

在这里插入图片描述

3.8.2 页面效果展现

在这里插入图片描述

3.9 路由导航守卫

3.9.1 业务说明

当用户没有登录时,不可以访问其他页面 如果sessionStorage中没有token数据,则表示没有登录 用该拦截,跳转到登录页面.

3.9.2路由守卫语法

编辑router的index.js

//设置路由导航守卫
//关于参数说明:
  //1. to 将要访问的路径
  //2. from 从哪个路径跳转来的
  //3. next 是一个函数   next() 表示放行  next("/login") 强制跳转
router.beforeEach((to,from,next) => {
    //1.当用户访问登录页面,则直接放行 如果不需要执行后续操作 执行return
    if(to.path === '/login') return next()
    //2.当用户访问其他页面 需要校验是否有token
    let token = window.sessionStorage.getItem('token')
    //如果数据为null  则访问登录页面
    if(!token)  return next('/login')
    //如果数据不为null 则放行
    next()
})

在这里插入图片描述

3.10 用户退出操作

3.10.1 业务说明

当用户点击退出按钮时,应该删除sessionStorage中的token信息. 并且访问登录页面

3.10.2 用户退出操作

在这里插入图片描述

4. 用户首页布局

4.1 ElementUI 页面布局介绍

4.1.1 页面HTML

在这里插入图片描述
页面效果:
在这里插入图片描述

4.2 实现左侧菜单获取

4.2.1编辑Home.vue

在这里插入图片描述

4.2.2 编辑RightsController

在这里插入图片描述

4.2.3 编辑RightsService

package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.RightsMapper;
import com.jt.pojo.Rights;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 刘昱江
 * 时间 2021/5/12
 */
@Service
public class RightsServiceImpl implements RightsService{

    @Autowired
    private RightsMapper rightsMapper;


    @Override
    public List<Rights> getRightsList() {
        //1.查询所有的一级菜单
        QueryWrapper<Rights> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", 0);
        List<Rights> oneList = rightsMapper.selectList(queryWrapper);
        //2.根据一级查询二级菜单
        for (Rights oneRights : oneList){
            //查询二级菜单
            QueryWrapper<Rights> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("parent_id", oneRights.getId());
            List<Rights> twoList = rightsMapper.selectList(queryWrapper2);
            oneRights.setChildren(twoList);
        }
        return oneList;
}
}

4.2.4 页面效果展现

在这里插入图片描述

4.3 菜单栏介绍

4.3.1 导航菜单样式

在这里插入图片描述

4.3.2 菜单属性介绍

在这里插入图片描述

4.3.3 子菜单跳转

属性介绍:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
在这里插入图片描述
定义子组件请求路径
在这里插入图片描述

4.3.4 欢迎页面展现

说明: 添加welcome页面
在这里插入图片描述
定义路由组件: 实现默认跳转
在这里插入图片描述
在这里插入图片描述

5 用户模块实现

5.1 实现用户页面跳转

5.1.1 创建user模块

在这里插入图片描述

5.1.2 定义用户路由

在这里插入图片描述

5.2 面包屑导航

5.2.1 官网Demo

在这里插入图片描述

5.2.2 定义面包屑

 <!-- 1.定义面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>

在这里插入图片描述

5.3 定义卡片视图

5.3.1 官网API

在这里插入图片描述

5.3.2 定义卡片视图

    <!-- 2.定义卡片视图 -->
    <el-card class="box-card">
       <h1>我是一个卡片视图</h1>
    </el-card>

在这里插入图片描述

5.4 定义输入框

5.4.1 官网API

在这里插入图片描述

5.4.2 定义栅格

使用栅格是为了固定内容的大小 el-row 表示一行 :span=24 一行最多24个 代表宽度
在这里插入图片描述
在这里插入图片描述

5.4.2 编辑页面

<!-- 2.定义卡片视图 -->
    <el-card class="box-card">

       <!-- 3.定义栅格的一行 :gutter="20"定义行间距   :span="9" 占位符  -->
       <el-row :gutter="20">
         <el-col :span="9">
            <!-- 3.定义搜索框 -->
            <el-input placeholder="请输入内容">
                <el-button slot="append" icon="el-icon-search"></el-button>
            </el-input>
         </el-col>
         <el-col :span="4">
            <!-- 定义添加按钮-->
            <el-button type="primary">添加用户</el-button>
         </el-col>
       </el-row>
    </el-card>

5.4.3 页面效果

在这里插入图片描述

5.5 实现用户列表查询

5.5.1 业务接口

在这里插入图片描述

5.5.2 定义PageResult对象

在这里插入图片描述

5.5.3 编辑UserController

在这里插入图片描述

5.5.4 编辑UserService

在这里插入图片描述

5.5.5 编辑MybatisPlus 配置类

官网API:
在这里插入图片描述

package com.jt.config;

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

/**
 * @author 刘昱江
 * 时间 2021/5/13
 */
@Configuration
public class MybatisPlusConfig {

    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MARIADB));
        return interceptor;
    }
}

5.6 实现用户列表显示VUE页面

5.6.1 获取用户数据

<script>
  export default {
    data(){
      return {
        queryInfo: {
          query: '',
          pageNum: 1,
          pageSize: 5
        },
        //为了后续操作 定义数据在外边
        userList: [],
        total: 0
      }
    },
    methods: {
      async getUserList(){
        const {data: result} = await this.$http.get('/user/list',{
           params: this.queryInfo
        })
        if(result.status !== 200) return this.$message.error("用户列表查询失败")
        this.userList = result.data.rows
        this.total = result.data.total
      }
    },
    //利用钩子函数实现数据查询
    mounted(){
      this.getUserList()
    }
  }
</script>

5.6.2 表格数据API

在这里插入图片描述

5.6.2 编辑页面

在这里插入图片描述

5.6.3 页面效果

在这里插入图片描述

5.6.4 状态信息

在这里插入图片描述
作用域插槽: slot-scope=“scope”
在这里插入图片描述

5.6.5 编辑按钮

在这里插入图片描述

5.6.6 效果展现

在这里插入图片描述

5.7 实现用户列表分页

5.7.1 官方API

在这里插入图片描述

5.7.2 复制分页JS

 <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="currentPage4"
      :page-sizes="[100, 200, 300, 400]"
      :page-size="100"
      layout="total, sizes, prev, pager, next, jumper"
      :total="400">
    </el-pagination>

5.7.3 编辑分页操作

在这里插入图片描述
编辑页面JS
在这里插入图片描述
效果展现
在这里插入图片描述

5.8 用户状态修改

5.8.1 修改事件触发

在switch中 通过change事件可以实现数据的修改
在这里插入图片描述

5.8.2 编辑Vue页面

通过回调函数和作用域插槽 实现数据传递
在这里插入图片描述

5.8.3 编辑页面JS

在这里插入图片描述

5.8.4 编辑UserController

在这里插入图片描述

5.8.5 编辑UserService

在这里插入图片描述

5.9 用户搜索按钮实现

5.9.1 业务说明

当用户点击按钮之后,将数据绑定到查询对象中,重新获取列表数据即可.
在这里插入图片描述

5.9.2 编辑Vue页面

在这里插入图片描述

5.9.3 Input输入框清空操作

说明: 当用户输入成功之后,可以通过清空属性 已写数据 实现查询全部的功能
在这里插入图片描述
清空事件: 当用户调用clearable之后,调用clear事件
在这里插入图片描述
触发页面JS
在这里插入图片描述

5.10 添加用户功能实现

5.9.1 绘制新增表单对话框

1).绘制Dialog对话框
在这里插入图片描述

5.9.2 编辑页面HTML

<!-- 编辑用户新增对话框 visible.sync 控制对话框的显示-->
    <el-dialog title="添加用户" :visible.sync="dialogVisible" width="50%">

      <!-- 定义用户提交表单数据-->
      <el-form :model="addUserModel" :rules="rules" ref="addUserRef" label-width="100px" class="demo-ruleForm">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addUserModel.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="addUserModel.password" type="password"></el-input>
        </el-form-item>
        <el-form-item label="密码确认" prop="password2">
          <el-input v-model="addUserModel.password2" type="password"></el-input>
        </el-form-item>
        <el-form-item label="电话" prop="phone">
          <el-input v-model="addUserModel.phone"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addUserModel.email"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>

5.9.3 校验邮箱/手机正则/密码校验

//校验邮箱规则 rule校验规则   value校验的数据   callback回调函数
      const checkEmail = (rule, value, callback) => {
        //定义邮箱的正则表达式  JS中用/来表示正则表达式的开始和结束
        const emailRege = /^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$/
        //正则表达式语法校验  test(xx) 校验成功 返回true  校验失败返回false
        if (emailRege.test(value)) {
          //表示邮箱合法 正确返回
          return callback()
        }
        callback(new Error('请填写正确的邮箱地址'))
      }

      //校验手机号的邮箱规则
      const checkPhone = (rule, value, callback) => {

        //定义校验手机号的正则语法
        const phoneRege = /^1[34578][0-9]{9}$/
        if (phoneRege.test(value)) {

          return callback()
        }
        callback(new Error('请填写正确的手机号'))

      }

      const checkPassword = (rule, value, callback) => {
        if(this.addUserModel.password !== value) return callback(new Error('2次密码输入不一致'))
        //否则校验成功
        callback()
      }

使用校验规则
在这里插入图片描述

5.11 重置表单数据

5.11.1 重置事件 close

在这里插入图片描述

5.11.2 编辑页面VUE

在这里插入图片描述
在这里插入图片描述

5.12 实现用户新增

5.12.1 编辑页面html

在这里插入图片描述

5.12.2 编辑UserController

在这里插入图片描述

5.12.3 编辑UserService

在这里插入图片描述

5.12.4 自动填充API说明

在这里插入图片描述
在这里插入图片描述

5.12.5 配置自动填充配置类

在这里插入图片描述
页面效果:
在这里插入图片描述

5.13 用户修改数据回显

5.13.1 绘制修改Dialog页面

<!-- 定义修改页面 -->
    <el-dialog title="修改用户" :visible.sync="updateDialogVisible" width="50%">
      <!-- 定义用户提交表单数据-->
      <el-form :model="updateUserModel" :rules="rules" ref="updateUserRef" label-width="100px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="updateUserModel.username"  disabled ></el-input>
        </el-form-item>
        <el-form-item label="电话" prop="phone">
          <el-input v-model="updateUserModel.phone"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="updateUserModel.email"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="updateDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="updateDialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>

5.13.2 根据ID获取数据

	async updateUserBtn(user){
        this.updateDialogVisible = true
        const {data: result} = await this.$http.get("/user/"+user.id)
        if(result.status !== 200) return this.$message.error("用户查询失败")
        this.updateUserModel = result.data
      }

5.13.3 编辑UserController

在这里插入图片描述

5.13.4 编辑UserService

在这里插入图片描述

5.14 重置修改页面

5.14.1 官网API

在这里插入图片描述

5.14.2 编辑JS

在这里插入图片描述
在这里插入图片描述

5.15 用户修改提交

5.15.1 表单数据预校验

在这里插入图片描述

5.15.2 编辑UserController

在这里插入图片描述

5.15.3 编辑UserService

在这里插入图片描述

5.16 用户删除

5.16.1 消息提示框

在这里插入图片描述

5.16.2 编辑页面JS

在这里插入图片描述

5.16.3 编辑UserController

在这里插入图片描述

5.16.4 编辑UserService

在这里插入图片描述

5.16.5 页面效果展现

在这里插入图片描述

6. 商品分类功能实现

6.1 商品分类列表展现

6.1.1 编辑页面JS

在这里插入图片描述

6.1.2 编辑后台Controller

在这里插入图片描述

6.1.3 编辑后台Service

 @Override
    public List<ItemCat> findItemCatList(Integer type) {
        //获取数据
        Map<Integer,List<ItemCat>> map = getItemCatMap();
        return findChildrenList(null,type,map);
    }

    public List<ItemCat> findChildrenList(Integer id,Integer type, Map<Integer,List<ItemCat>> map){
        if(id==null) id = 0;
        List<ItemCat> itemCatList = map.get(id);

        if(type == 1){
            return itemCatList;
        }
        if(itemCatList == null){
            return null;
        }
        for (ItemCat itemCat: itemCatList){
            if(itemCat.getLevel()<type){
                List<ItemCat> childrenList = findChildrenList(itemCat.getId(),type,map);
                itemCat.setChildren(childrenList);
            }
        }
        return itemCatList;
    }

    public Map<Integer,List<ItemCat>> getItemCatMap(){
        List<ItemCat> itemCatList = itemCatMapper.selectList(null);
        Map<Integer,List<ItemCat>> map = new HashMap<>();
        for(ItemCat itemCat : itemCatList){
            Integer parentId = itemCat.getParentId();
            if(map.containsKey(parentId)){
                map.get(parentId).add(itemCat);
            }else{
                List<ItemCat> list = new ArrayList<>();
                list.add(itemCat);
                map.put(parentId, list);
            }
        }
        return map;
    }


	方式2:
	 @Override
    public List<ItemCat> findItemCatList(Integer type) {
        Map<Integer,List<ItemCat>> map = getItemCatMap();
        if(type == 1) return map.get(0);
        if(type == 2) return findTwoItemCatList(map);
        return findThreeItemCatList(map);
    }


    public List<ItemCat> findTwoItemCatList(Map<Integer,List<ItemCat>> map){
        //1.获取一级商品分类
        List<ItemCat> oneList = map.get(0);
        //2.根据一级查询二级
        for(ItemCat itemCat : oneList){
            List<ItemCat> twoList = map.get(itemCat.getId());
            itemCat.setChildren(twoList);
        }
        return oneList;
    }

    private List<ItemCat> findThreeItemCatList(Map<Integer,List<ItemCat>> map) {
        List<ItemCat> twoList = findTwoItemCatList(map);
        for (ItemCat itemCat : twoList){    //1级菜单
            if(itemCat.getChildren() !=null){
                for(ItemCat itemCat2 :itemCat.getChildren()){
                    List<ItemCat> threeList = map.get(itemCat2.getId());
                    itemCat2.setChildren(threeList);
                }
            }
        }
        return twoList;
    }

    public Map<Integer,List<ItemCat>> getItemCatMap(){
        List<ItemCat> itemCatList = itemCatMapper.selectList(null);
        Map<Integer,List<ItemCat>> map = new HashMap<>();
        for(ItemCat itemCat : itemCatList){
            Integer parentId = itemCat.getParentId();
            if(map.containsKey(parentId)){
                map.get(parentId).add(itemCat);
            }else{
                List<ItemCat> list = new ArrayList<>();
                list.add(itemCat);
                map.put(parentId, list);
            }
        }
        return map;
    }

6.1.4 页面效果展现

在这里插入图片描述

6.2 商品分类状态实现

6.2.1 编辑页面VUE

在这里插入图片描述

6.2.2 编辑ItemCatController

在这里插入图片描述

6.2.3 编辑ItemCatService

在这里插入图片描述

6.3 商品分类新增

6.3.1 编辑页面JS

在这里插入图片描述

6.3.2 编辑ItemCatController

在这里插入图片描述

6.3.3 编辑ItemCatService

在这里插入图片描述

6.4 商品分类修改

6.4.1 页面JS展现

在这里插入图片描述

6.4.2 编辑ItemCatController

在这里插入图片描述

6.4.3 编辑ItemCatService

在这里插入图片描述

6.5 商品分类删除

6.5.1 编辑页面JS

在这里插入图片描述

6.5.2 编辑ItemCatController

在这里插入图片描述

6.5.3 编辑ItemCatService

 @Override
    public void deleteItemCat(ItemCat itemCat) {
        if(itemCat.getLevel() == 3){
            itemCatMapper.deleteById(itemCat.getId());
            return;
        }

        if(itemCat.getLevel() == 2){
            itemCatMapper.delete(new QueryWrapper<>(itemCat).eq("parent_id", itemCat.getId()));
            itemCatMapper.deleteById(itemCat.getId());
        }

        if(itemCat.getLevel() == 1){
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("parent_id", itemCat.getId());
            List<ItemCat> list2 = itemCatMapper.selectList(queryWrapper);
            for (ItemCat itemCat2 : list2){
                QueryWrapper<ItemCat> queryWrapperTemp = new QueryWrapper<>();
                queryWrapperTemp.eq("parent_id", itemCat2.getId());
                itemCatMapper.delete(queryWrapperTemp);
                itemCatMapper.deleteById(itemCat2.getId());
            }
            itemCatMapper.deleteById(itemCat.getId());
        }
    }

7 商品分类参数列表实现

7.1 商品分类参数列表

7.1.1 编辑ItemCatParam

在这里插入图片描述

7.1.2 编辑itemCatParamController

在这里插入图片描述

7.1.3 编辑itemCatParamService

在这里插入图片描述

7.1.4 页面效果展现

在这里插入图片描述

7.2 新增分类参数

7.2.1 编辑VUE页面

1).商品分类参数新增页面
在这里插入图片描述
2).新增商品分类参数
在这里插入图片描述

7.2.2 编辑ItemCatParamController

在这里插入图片描述

7.2.3 编辑ItemCatParamService

在这里插入图片描述

7.3 商品分类参数删除

7.3.1 编辑页面VUE

1).编辑页面JS
在这里插入图片描述
2).删除JS
在这里插入图片描述

7.3.2 编辑ItemCatParamController

在这里插入图片描述

7.3.2 编辑ItemCatParamService

在这里插入图片描述

7.4 商品分类参数修改

7.4.1 编辑页面JS

在这里插入图片描述

7.4.2 编辑Controller

在这里插入图片描述

7.4.3 编辑Service

在这里插入图片描述

8.商品模块实现

8.1 商品列表展现

8.1.1 编辑页面VUE

在这里插入图片描述

8.1.2 编辑ItemController

在这里插入图片描述

8.1.3 编辑ItemService

在这里插入图片描述

8.2 修改商品状态

8.2.1 编辑页面VUE

在这里插入图片描述

8.2.2 编辑ItemController

在这里插入图片描述

8.2.3 编辑ItemService

在这里插入图片描述

8.3 删除商品

8.3.1 编辑页面VUE

在这里插入图片描述

8.3.2 编辑ItemController

在这里插入图片描述

8.3.3 编辑ItemService

在这里插入图片描述

8.4 文件上传操作

8.4.1 文件上传页面

1).文件上传操作
在这里插入图片描述

8.4.2 编辑FileController

在这里插入图片描述

8.4.2 编辑properties配置文件

#配置windows服务器路径
image.localPathDir=D:/JT_IMAGE
#配置Linux服务器路径
#image.localPathDir=/usr/local/src/images
image.localUrlPath=http://image.jt.com

8.4.3 编辑FileService

@Service
@PropertySource("classpath:/properties/image.properties")
public class FileServiceImpl implements FileService{

    //为属性动态赋值 注解@Value
    @Value("${image.localPathDir}")
    private String localPathDir;        // = "D:/JT_IMAGE";
    @Value("${image.localUrlPath}")
    private String localUrlPath;        // = "http://image.jt.com";


    //1.参数  ~~~已知条件
    //2.干什么 ~~~ 实现文件上传
    //3.返回值: void ImageVO 有效返回

    /**
     * 文件上传案例实现
     * 1.如何保证前端是上传的数据是有效的!!
     *      1.1 校验文件的名称检查是否为图片
     *      1.2 校验是否为恶意程序.
     * @param file
     * @return
     */
    @Override
    public ImageVO upload(MultipartFile file) throws IOException {
        //1.1校验是否为图片类型  abc.jpg ABC.JPG 文件大小写
        String fileName = file.getOriginalFilename();
        //将所有的文件名称转化为小写
        fileName = fileName.toLowerCase();
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
            return null;
        }
        //1.2 校验图片类型是否为木马
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if(width == 0 || height == 0 ){
                return null;
            }
        }catch (Exception e){
            return null;
        }

        //2. 目录结构
        //2.1 实现分目录存储...  可以以时间维度进行分隔 /yyyy/MM/dd/
        String datePath =
                new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
        //2.2 进行目录的拼接  "D:/JT_IMAGE/2021/11/11";
        String localDir = localPathDir + datePath;
        //2.3 需要创建目录
        File dirFile = new File(localDir);
        if(!dirFile.exists()){
            dirFile.mkdirs();
        }

        //3.文件名称重复  采用UUID防止文件重名 uuid.jpg
        String uuid = UUID.randomUUID().toString()
                        .replace("-", "");
        //fileName = abc.jpg
        String fileType =
                fileName.substring(fileName.lastIndexOf("."));
        String realFileName = uuid + fileType;

        //c:jt_image/2021/11/11/uuid.jpg
        String filePathAll = localDir + realFileName;
        //实现文件上传
        File realFile = new File(filePathAll);
        file.transferTo(realFile);

        //封装ImageVO对象  //2021/11/11/uuid.jpg 图片路径
        String virtualPath = datePath + realFileName;
        //封装虚拟URl地址  http://image.jt.com/2021/11/11/uuid.jpg
        String urlPath = localUrlPath + virtualPath;
        return new ImageVO(virtualPath,urlPath,realFileName);
    }
    }

8.4.4 成功之后的回调

在这里插入图片描述

8.5 商品新增

8.5.1 编辑vue 页面

在这里插入图片描述

8.5.2 编辑ItemController

在这里插入图片描述

8.5.3 编辑ItemService

 /**
     * 实现三张表入库 商品表/商品详情表/商品参数表
     * @param itemVO
     */
    @Transactional
    @Override
    public void saveItem(ItemVO itemVO){
        //1.入库商品表
        Item item = itemVO.getItem();
        item.setStatus(true);    //默认启用状态
        //要求入库之后返回主键
        //MP如果设定了主键自增则会自动的实现数据回显
        itemMapper.insert(item);

        //2.入库商品详情
        ItemDesc itemDesc = itemVO.getItemDesc();
        itemDesc.setId(item.getId());
        itemDescMapper.insert(itemDesc);

        //3.入库商品参数
        //1.一个商品应该有自己的单独的参数. 动态参数/静态属性 KYE-VLAUE [key:value,key2:value2]
        ItemParam itemParam = itemVO.getItemParam();
        ItemParamVO[] dynamic = itemParam.getDynamicArray();
        ItemParamVO[] staticParam  = itemParam.getStaticArray();
        try {
            //将页面传递的数据转化为JSON,之后数据库保存
            String dynamicJSON = MAPPER.writeValueAsString(dynamic);
            String staticJSON = MAPPER.writeValueAsString(staticParam);
            //封装商品参数信息
            itemParam.setDynamicArgs(dynamicJSON)
                     .setStaticArgs(staticJSON)
                     .setId(item.getId());
            //实现入库操作
            itemParamMapper.insert(itemParam);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            //如果程序执行报错 则抛出异常
            throw new RuntimeException(e);
        }
    }