学成在线第三天

基础信息管理

数据字典:
昨天的大家也看到了这里完全没有显示
在这里插入图片描述

在这里插入图片描述
在开发中我们会遇到两种情况:

  • 开发中有些变量信息,其内容固定,并在多个地方使用。面对多变的需求,这些变量可能会有所调整。
  • 在用户界面中显示下拉框菜单里的数据,一般不会写死,需要进行统一管理。
  • 在学成在线项目中,数据状态,数据类型等都是使用数据字段对比展示的。在页面初始化的时候,会从服务端获取数据字段内容,并存储到前端缓存。

具体实现:

需要数据库表:
在这里插入图片描述
YAPI接口文档:
在这里插入图片描述
在这里插入图片描述
代码展示
首先使用mybatis-plus代码生成器,生成模块结构
在这里插入图片描述
具体结构:
在这里插入图片描述
web代码:

package com.xuecheng.basic.controller;

import com.xuecheng.commons.model.vo.ResponseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xuecheng.basic.service.DictionaryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <p>
 * 数据字典前端控制器
 * </p>
 *
 * @author itheima
 */
@Slf4j
@RestController
@RequestMapping("/dictionary")
public class DictionaryController {

    @Autowired
    private DictionaryService dictionaryService;

    //查询所有数据字典
    @GetMapping
    public ResponseResult findAllDictionary(){
    return dictionaryService.findAllDictionary();
    }
    //根据code查询数据字典
    @GetMapping("/{code}")
    public ResponseResult findCode(@PathVariable("code") String code){
        return dictionaryService.findCode(code);
    }
}

serverImpl层:

package com.xuecheng.basic.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.basic.domain.Dictionary;
import com.xuecheng.basic.mappers.DictionaryMapper;
import com.xuecheng.basic.service.DictionaryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.vo.DictionaryVo;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.web.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-30
 */
@Service
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, Dictionary> implements DictionaryService {

    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private DictionaryMapper dictionaryMapper;
    @Override
    public ResponseResult findAllDictionary() {
        List<Dictionary> list = dictionaryService.list();
        List<DictionaryVo> vos = BeanHelper.copyWithCollection(list, DictionaryVo.class);
        return ResponseResult.okResult(vos);

    }

    @Override
    public ResponseResult findCode(String code) {
        LambdaQueryWrapper<Dictionary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dictionary::getCode,code);
        Dictionary one = dictionaryMapper.selectOne(wrapper);
        if (BeanUtil.isEmpty(one)){
            throw new BusinessException(ErrorCode.NOTFOUND);
        }
        DictionaryVo vo = BeanHelper.copyProperties(one, DictionaryVo.class);
        return ResponseResult.okResult(vo);
    }
}

效果展示:
在这里插入图片描述
添加课程中的数据字典:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要的表:
在这里插入图片描述
YAPI接口文档;在这里插入图片描述
在这里插入图片描述

这个课程分类功能就有点点难度,他是一个嵌套三级结构,具体如下图:
在这里插入图片描述
根据图片我们可以知道这三级结构是根据id,相联系

具体的json格式;


[
  {
    "courseCategoryId": "1",
    "name": "根结点",
    "label": "根结点",
    "parentid": "0",
    "isShow": 1,
    "orderby": 1,
    "isLeaf": 0,
    "categoryTreeNodes": [
      {
        "id": "1-1",
        "name": "前端开发",
        "label": "前端开发",
        "parentid": "1",
        "isShow": 1,
        "orderby": 1,
        "isLeaf": 0,
        "categoryTreeNodes": [
          {
            "id": "1-1-1",
            "name": "HTML/CSS",
            "label": "HTML/CSS",
            "parentid": "1-1",
            "isShow": 1,
            "orderby": 1,
            "isLeaf": 1,
            "categoryTreeNodes": null
          },
          ..........
        ]
      },
      ..........
    ]
  }
]

VO对象:

package com.xuecheng.commons.model.vo;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * <p>
 * 课程分类
 * </p>
 *
 * @author itcast
 */
@Data
public class CategoryVo implements Serializable {
    
    private String id;

    //分类名称
    private String name;

    //分类标签默认和名称一样
    private String label;

    //父结点id(第一级的父节点是0,自关联字段id)
    private String parentid;

    //是否显示
    private Integer isShow;

    //排序字段
    private Integer orderby;

    //是否叶子
    private Integer isLeaf;

    //课程分类子节点数据
    private List<CategoryVo> categoryTreeNodes;
}

web层:

package com.xuecheng.basic.controller;

import com.xuecheng.commons.model.vo.ResponseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xuecheng.basic.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <p>
 * 课程分类前端控制器
 * </p>
 *
 * @author itheima
 */
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {

    @Autowired
    private CategoryService  categoryService;

    //获取分类信息
    @GetMapping("/tree-nodes")
    public ResponseResult findCategory(){
       return categoryService.findCategory();
    }
}

serviceImpl层:

package com.xuecheng.basic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.basic.domain.Category;
import com.xuecheng.basic.mappers.CategoryMapper;
import com.xuecheng.basic.service.CategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.commons.model.vo.CategoryVo;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.commons.utils.BeanHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 课程分类 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-30
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;
    @Override
    public ResponseResult findCategory() {

        //先查询一级
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentid,"0");
        Category category = categoryMapper.selectOne(wrapper);
        CategoryVo categoryVo = BeanHelper.copyProperties(category, CategoryVo.class);
        //再根据id查询二级
        LambdaQueryWrapper<Category> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(Category::getParentid,category.getId());
        List<Category> categories = this.list(wrapper1);//id=1-1,1-10 .....
        List<CategoryVo> twos = BeanHelper.copyWithCollection(categories, CategoryVo.class);
        categoryVo.setCategoryTreeNodes(twos);
        //根据二级id查询三级 id=1-1-1.....
        for (CategoryVo c : twos) {
        LambdaQueryWrapper<Category> wrapper2 = new LambdaQueryWrapper<>();
           wrapper2.eq(Category::getParentid,c.getId());
            List<Category> list = this.list(wrapper2);
            List<CategoryVo> categoryVos = BeanHelper.copyWithCollection(list, CategoryVo.class);
            c.setCategoryTreeNodes(categoryVos);
        }
      return ResponseResult.okResult(categoryVo);
    }
}

效果展示:
在这里插入图片描述
静态文件的存储
在这里插入图片描述
静态文件的上传,本人在瑞吉外卖中使用的是阿里云OSS,但在本项目中我们介绍一个新的分布式文件存储系统——>MinIO,如果你要问我OSS跟MinIo哪个好,那我只能说肯定花钱的比免费的好
MinIo:官网文档

首先我们需要查看虚拟机是否已启动MinIo。
在这里插入图片描述
启动成功后直接访问: http://192.168.136.150:9000
创建一个新的问价夹
在这里插入图片描述
注意:这里我们需要将buckets的权限改为public
在这里插入图片描述
在 xc-content-service导入依赖

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>7.1.0</version>
</dependency>

入门练习:

public class MinioTest {

    private String ak = "";//申请的账号
    private String sk = "";//申请的密码
    private String endPoint= "http://192.168.136.150:9000";
    private String bucket = "xuecheng";//桶名
    private String domain ="http://192.168.136.150:9000";


    @Test
    public void testUpload() throws Exception {

        FileInputStream inputStream = new FileInputStream("D:\\2.jpg");
        String filename = "2.jpg";

        //1、初始化client对象
        MinioClient client = MinioClient
                .builder()
                .credentials(ak, sk)
                .endpoint(endPoint)
                .build();
        //2、配置上传的请求地址
        String filePath = "/images/"+
                DateTime.now().toString("yyyy/MM/dd/") +
                UUID.randomUUID().toString() + filename;

        //3、文件上传
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .object(filePath)
                .contentType("image/jpg")
                .bucket(bucket)
                .stream(inputStream, inputStream.available(), -1)
                .build();
        
        client.putObject(putObjectArgs);
        
        //4、获取请求地址
        String urlPath = domain +"/" + bucket + filePath;
        System.out.println(urlPath);
    }
}

这里可能在会出现点小错误:
在这里插入图片描述
我们需要在虚拟机中输入命令:

#安装ntpdate工具
yum -y install ntp ntpdate
#自动同步时间
ntpdate ntp.ubuntu.com

项目集成:
首先我们需要在yml文件在配置:

minio:
<!--注册的账号密码-->
  accessKey: 
  secretKey: 
  bucket: xuecheng-zixue
  endpoint: http://192.168.136.150:9000
  domain: http://192.168.136.150:9000

在这里插入图片描述

package com.xuecheng.content.config.minio;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {
    @Autowired
    private MinIoProperties prop;

    @Bean
    public MinioClient minioClient(){
        return MinioClient
                .builder()
                .credentials(prop.getAccessKey(),prop.getSecretKey())
                .endpoint(prop.getEndpoint())
                .build();
    }
}
package com.xuecheng.content.config.minio;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.io.Serializable;

@ConfigurationProperties(prefix = "minio")
@Configuration
@Data
public class MinIoProperties implements Serializable {
    private String accessKey;
    private String secretKey;
    private String bucket;
    private String endpoint;
    private String domain;
}

集成测试

@SpringBootTest
@RunWith(SpringRunner.class)//这句话必须加,不加获取不到yml的值
public class MinioTest {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioProperties properties;

    @Test
    public void testUpload() throws Exception {
        //1、指定文件
        FileInputStream inputStream = new FileInputStream("D:\\2.jpg");
        String filename = "2.jpg";
        //2、指定文件上传的位置和文件名称   /images/2022/07/17/uuid +filename
        String filepath = "/images/"+new SimpleDateFormat("yyyy/MM/dd/")
                .format(new Date()) +
                UUID.randomUUID().toString()+filename;
        //3、构造PutObjectArgs参数,并发送请求
        PutObjectArgs objectArgs = PutObjectArgs.builder()
              .contentType("image/jpg") //文件类型
              .stream(inputStream, inputStream.available(), -1) //文件流
              .bucket(properties.getBucket()) //存储空间
              .object(filepath) //文件
              .build();
        minioClient.putObject(objectArgs);
        //5、拼接访问地址
        String urlPath = properties.getDomain() +"/" + properties.getBucket() + filepath;
        System.out.println(urlPath);
    }
}

在这里插入图片描述
课程图片上传:

YAPI接口:
在这里插入图片描述
在这里插入图片描述
代码展示:

web层:

    //上传课程封面图片
    @PostMapping("/upload")
    public ResponseResult upload(MultipartFile uploadFile) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
     return courseBaseService.upload(uploadFile);
    }

servceImpl层:

   @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinIoProperties minIoProperties;
    @Override
    public ResponseResult upload(MultipartFile uploadFile) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        String filename = uploadFile.getOriginalFilename();
        InputStream inputStream = uploadFile.getInputStream();
        //指定文件上传的位置和文件名称
        String filePath="/images/"+new SimpleDateFormat("yyyy/MM-dd/")
                .format(new Date())+ UUID.randomUUID().toString()+filename;
        //3、构造PutObjectArgs参数,并发送请求
        PutObjectArgs objectArgs = PutObjectArgs.builder()
                .contentType("image/jpg") //文件类型
                .stream(inputStream, inputStream.available(), -1) //文件流
                .bucket(minIoProperties.getBucket()) //存储空间
                .object(filePath) //文件
                .build();
        minioClient.putObject(objectArgs);

       String imagesURl= minIoProperties.getDomain()+"/"+minIoProperties.getBucket()+ filePath;
               return ResponseResult.okResult(imagesURl);
    }

效果展示
在这里插入图片描述

在这里插入图片描述
保存课程信息:

课程发布的业务流程:
在这里插入图片描述
课程基础信息在内容管理中会有状态的显示,课程状态为 5 个状态,分别为:

​ 课程初始化,未提交:202002

​ 已提交,待审核:202003

​ 审核通过:202004

​ 审核未通过:202001

​ 已发布:202005

​ 已下架:202006

在这里插入图片描述

YAPI文档接口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码展示:

web层:

  //保存课程
    @PostMapping
    public ResponseResult saveCourse(@RequestBody CourseBaseDto courseBaseDto){
     return courseBaseService.saveCourse(courseBaseDto);
    }

serviceImpl层:

    @Override
    public ResponseResult saveCourse(CourseBaseDto courseBaseDto) {

        CourseBase courseBase = BeanHelper.copyProperties(courseBaseDto, CourseBase.class);
        //补全信息
        courseBase.setStatus(CommonConstants.USING_FLAG);
        courseBase.setCompanyId(AuthInfoHolder.getCompanyId());
        courseBase.setCompanyName(AuthInfoHolder.getAuthInfo().getCompanyName());
        courseBase.setAuditStatus(CourseConstants.AUDIT_UNPAST_STATUS);
        courseBase.setCreateDate(new Date());
        courseBase.setPlanNum(0);//默认章节
        int i = courseBaseMapper.insert(courseBase);
        if (i==0){
            throw  new BusinessException(ErrorCode.ADDEERROR);
        }
        HashMap<String, Long> map = new HashMap<>();
        map.put("courseBaseId",courseBase.getId());
        return ResponseResult.okResult(map);
    }

效果展示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

根据课程id查询课程

当我们点击编辑,会进入到编辑界面,这要进行数据的回显
在这里插入图片描述

YAPI接口文档:
在这里插入图片描述
在这里插入图片描述
需要的VO对象:

package com.xuecheng.commons.model.vo;

import lombok.Data;

import java.math.BigDecimal;
import java.util.Date;

@Data
public class CourseBaseVo {

    private Long id;

    /**
     * 机构ID
     */
    private Long companyId;

    /**
     * 机构名称
     */
    private String companyName;

    /**
     * 课程名称
     */
    private String name;

    /**
     * 适用人群
     */
    private String users;

    /**
     * 课程标签
     */
    private String tags;

    /**
     * 大分类
     */
    private String mt;

    /**
     * 课程大类名称
     */
    private String mtName;

    /**
     * 小分类
     */
    private String st;

    /**
     * 课程小类名称
     */
    private String stName;

    /**
     * 课程等级
     */
    private String grade;

    /**
     * 教育模式(common普通,record 录播,live直播等)
     */
    private String teachmode;

    /**
     * 课程介绍
     */
    private String description;

    /**
     * 课程图片
     */
    private String pic;

    /**
     * 创建时间
     */
    private Date createDate;

    /**
     * 审核状态
     */
    private String auditStatus;

    /**
     * 审核意见
     */
    private String auditMind;

    /**
     * 审核时间
     */
    private Date auditDate;

    /**
     * 是否删除:1为未删除,0为删除
     */
    private Integer status;

    /**
     * 课程发布标识
     */
    private Long coursePubId;

    private Integer planNum;

    private String charge;

    private BigDecimal price;
}

代码展示:
在这里插入图片描述

web层:

  //根据课程id查询课程
    @GetMapping("/{courseBaseId}")
    public ResponseResult findCourseById(@PathVariable("courseBaseId") Long courseBaseId) {
        return courseBaseService.findCourseById(courseBaseId);
    }

serviceImpl层:

   @Override
    public ResponseResult findCourseById(Long courseBaseId) {
        CourseBase courseBase = courseBaseMapper.selectById(courseBaseId);
        if (BeanUtil.isEmpty(courseBase)){
            throw new BusinessException(ErrorCode.COMPANYERROR);
        }
        CourseBaseVo vo = BeanHelper.copyProperties(courseBase, CourseBaseVo.class);
        return ResponseResult.okResult(vo);
    }

效果展示:
在这里插入图片描述

修改课程信息

进行完信息的回显后,就行信息的修改保存功能
在这里插入图片描述

YAPI文档接口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示:

需要的实体:
在这里插入图片描述
实体:
带 ++++ 号的都是dto没有的,其中dto.id==courseBase.companyId

package com.xuecheng.content.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;

/**
 * <p>
 * 课程基本信息
 * </p>
 *
 * @author itheima
 * @since 2022-07-27
 */
@Getter
@Setter
@TableName("tb_course_base")
public class CourseBase implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 机构ID
     */
    private Long companyId;

    /**
     * 机构名称 ++++++++++++++++
     */
    private String companyName;

    /**
     * 课程名称
     */
    private String name;

    /**
     * 适用人群
     */
    private String users;

    /**
     * 课程标签
     */
    private String tags;

    /**
     * 大分类
     */
    private String mt;

    /**
     * 课程大类名称++++++++++++
     */
    private String mtName;

    /**
     * 小分类
     */
    private String st;

    /**
     * 课程小类名称+++++++++++
     */
    private String stName;

    /**
     * 课程等级
     */
    private String grade;

    /**
     * 教育模式(common普通,record 录播,live直播等)
     */
    private String teachmode;

    /**
     * 课程介绍
     */
    private String description;

    /**
     * 课程图片
     */
    private String pic;

    /**
     * 审核状态++++++++++
     */
    private String auditStatus;

    /**
     * 审核意见+++++++++++++
     */
    private String auditMind;

    /**
     * 是否删除:1为未删除,0为删除++++++++++++
     */
    private Integer status;

    /**
     * 课程发布标识+++++++++++++++++
     */
    private Long coursePubId;

    /**
     * 是否收费
     */
    private String charge;

    /**
     * 单价
     */
    private BigDecimal price;

    /**
     * 创建时间+++++++++++++++
     */
    private Date createDate;

    /**
     * 审核时间+++++++++++++
     */
    private Date auditDate;
//++++++++++++++++++
    private Integer planNum;


}

web层:

   //修改课程
     @PutMapping
    public ResponseResult updateCourse(@RequestBody CourseBaseDto dto){
         return courseBaseService.updateCourse(dto);
     }

serviceImpl层:

    @Override
    public ResponseResult updateCourse(CourseBaseDto dto) {
        CourseBase courseBase = this.getById(dto.getId());
        //判断合法
        if (courseBase == null){
            throw new BusinessException(ErrorCode.UPDATEEERROR);
        }
        //判断状态
        String auditStatus = courseBase.getAuditStatus();
        if (StrUtil.equals(auditStatus,CourseConstants.AUDIT_COMMIT_STATUS) ||               StrUtil.equals(auditStatus,CourseConstants.AUDIT_PASTED_STATUS)||
                StrUtil.equals(auditStatus,AUDIT_PUBLISHED_STATUS)
        ){
            throw new BusinessException(ErrorCode.DATAERROR);
        }
        CourseBase base = BeanHelper.copyProperties(dto, CourseBase.class);
        int i = courseBaseMapper.updateById(base);
        if (i == 0){
            throw new BusinessException(ErrorCode.ADDEERROR);
        }
        HashMap<String, Long> map = new HashMap<>();
        map.put("courseBaseId",dto.getId());
        return ResponseResult.okResult(map);
    }
}

效果展示:
在这里插入图片描述
在这里插入图片描述
注意:这里有404很正常,还有一个功能没做,看看数据库有没有更新就好了
在这里插入图片描述
好了今天的任务完成

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

皇家小黄

创作不易!!!!

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

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

打赏作者

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

抵扣说明:

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

余额充值