小程序入门项目
一、项目界面
二、搭建工程
2.1 父工程
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hmx</groupId>
<artifactId>miniprogram-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>miniprogram-api</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<packaging>pom</packaging>
<!--管理依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
<dependency>
<groupId>com.yungouos.pay</groupId>
<artifactId>yungouos-pay-sdk</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-ecs</artifactId>
<version>4.17.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2 搭建api工程
2.2.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>miniprogram-parent</artifactId>
<groupId>com.hmx</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>miniprogram-api</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 参数校验框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.yungouos.pay</groupId>
<artifactId>yungouos-pay-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-ecs</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.2 配置
application.yml
spring:
profiles:
active: dev #由于涉及到一些隐私配置,所以运行使用local环境,查看配置使用的dev配置
server:
servlet:
context-path: /miniApi
application-dev.yml
spring:
servlet:
multipart:
max-request-size: 100MB
max-file-size: 100MB
datasource:
url: jdbc:mysql://localhost:3306/miniprogram?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
host: localhost
database: 0
port: 6379
password:
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
timeout: 20000ms
application:
name: miniprogram
server:
port: 5000
oss:
endpoint: 'oss-cn-beijing.aliyuncs.com'
accessKeyId: ''
accessKeySecret: ''
bucketName: 'hmx123'
wxpay:
mchid: '商家id'
key: '支付key'
wxmini:
appid: '11'
secret: '22'
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.hmx.courseware.pojo
global-config:
db-config:
table-prefix: cw_
2.2.3 启动类+mybatisplus配置
@SpringBootApplication
public class MiniProgramApplication {
public static void main(String[] args) {
SpringApplication.run(MiniProgramApplication.class,args);
}
}
@Configuration
@MapperScan("com.hmx.miniprogram.mapper")
public class MybatisPlusConfig {
//分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
三、首页 课件列表
注意
前端utils/common.js中 有阿里oss的图片 前缀,改成自己的
3.1 接口说明
接口url:/cwApi/courseware/list
请求方式: get
请求参数:
名称 | 类型 | 描述 |
---|---|---|
start | int | 当前页 从1开始 |
返回数据:
// http://localhost:5000/cwApi/courseware/list?start=1
{
"code": 0,
"message": "操作成功!",
"data": {
"pageNum": 1,
"pageSize": 10,
"totalPage": 1,
"total": 4,
"list": [
{
"id": 1,
"name": "JAVA核心面试知识整理",
"price": 0.99,
"count": 1,
"url": null,
"cover": "/courseware/cover/java_hexin.png",
"createTime": "2021-02-18 13:55:11",
"carouselUrl": "/courseware/carousel/1.jpg",
"isCarousel": 1
},
{
"id": 4,
"name": "2021Java面试题大全",
"price": 0.99,
"count": 0,
"url": null,
"cover": "/courseware/cover/java_ms.png",
"createTime": "2021-02-18 13:55:11",
"carouselUrl": "/courseware/carousel/2.jpg",
"isCarousel": 2
},
{
"id": 20,
"name": "深入理解MySQL核心技术",
"price": 0.99,
"count": 0,
"url": null,
"cover": "/courseware/cover/mysql.jpg",
"createTime": "2021-02-20 21:56:14",
"carouselUrl": "/courseware/carousel/3.jpg",
"isCarousel": 3
},
{
"id": 21,
"name": "软件设计师考点精炼",
"price": 0.99,
"count": 0,
"url": null,
"cover": "/courseware/cover/ruan.jpg",
"createTime": "2021-08-07 17:57:52",
"carouselUrl": "",
"isCarousel": 0
}
]
}
}
package com.hmx.miniprogram.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @program: miniprogram-parent
* @description:
* @author: hmx
* @create: 2021-08-23 12:56
**/
@Data
public class Courseware implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@NotNull(message = "姓名不能为空")
private String name;
@NotNull(message = "价格不能为空")
private BigDecimal price;
@Min(value = 0, message = "购买量不能小于0")
private Integer count;
@NotNull(message = "课件地址不能为空")
private String url;
@NotNull(message = "封面不能为空")
private String cover;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
private String carouselUrl;
private Integer isCarousel;
}
3.2 Controller
package com.hmx.miniprogram.controller;
import com.hmx.miniprogram.common.Result;
import com.hmx.miniprogram.service.CoursewareService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @program: miniprogram-parent
* @description:
* @author: hmx
* @create: 2021-08-23 12:58
**/
@RestController
@RequestMapping("courseware")
public class CoursewareController {
@Autowired
private CoursewareService coursewareService;
@GetMapping("list")
public Result list(@RequestParam Integer start) {
//业务逻辑交给service处理
coursewareService.list(start);
}
}
3.3 Service
package com.hmx.miniprogram.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmx.miniprogram.common.CommonPage;
import com.hmx.miniprogram.common.Result;
import com.hmx.miniprogram.mapper.CoursewareMapper;
import com.hmx.miniprogram.pojo.Courseware;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* @program: miniprogram-parent
* @description:
* @author: hmx
* @create: 2021-08-23 13:02
**/
@Service
public class CoursewareService {
@Resource
private CoursewareMapper coursewareMapper;
public Result list(Integer start){
/**
* 1. 用mybatis plus的分页功能 查询
* 2. 返回 IPage 对象,转换为CommonPage即可
*/
Page<Courseware> page = new Page<>(start, 10);
Page<Courseware> coursewarePage = coursewareMapper.selectPage(page,new LambdaQueryWrapper<>());
CommonPage<Courseware> coursewareCommonPage = CommonPage.restPage(coursewarePage);
//url 得赋值为Null
List<Courseware> collect = coursewareCommonPage.getList().stream().peek(courseware -> courseware.setUrl(null)).collect(Collectors.toList());
coursewareCommonPage.setList(collect);
return Result.SUCCESS(coursewareCommonPage);
}
}
3.4 Mapper
package com.hmx.miniprogram.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hmx.miniprogram.pojo.Courseware;
/**
* @program: miniprogram-parent
* @description:
* @author: hmx
* @create: 2021-08-23 13:19
**/
public interface CoursewareMapper extends BaseMapper<Courseware> {
}
3.5 统一返回对象
import com.hmx.miniprogram.common.ResultCode;
import lombok.Data;
/**
* 统一响应结果集
*/
@Data
public class Result<T> {
//操作代码
Integer code;
//提示信息
String message;
//结果数据
T data;
public Result() {
}
public Result(ResultCode resultCode) {
this.code = resultCode.code();
this.message = resultCode.message();
}
public Result(ResultCode resultCode, T data) {
this.code = resultCode.code();
this.message = resultCode.message();
this.data = data;
}
public Result(String message) {
this.message = message;
}
public static Result SUCCESS() {
return new Result(ResultCode.SUCCESS);
}
public static <T> Result SUCCESS(T data) {
return new Result(ResultCode.SUCCESS, data);
}
public static Result FAIL() {
return new Result(ResultCode.FAIL);
}
public static Result FAIL(String message) {
return new Result(message);
}
}
package com.hmx.miniprogram.common;
/**
* 通用响应状态
*/
public enum ResultCode {
/* 成功状态码 */
SUCCESS(0, "操作成功!"),
/* 错误状态码 */
FAIL(-1, "操作失败!"),
/* 参数错误:10001-19999 */
PARAM_IS_INVALID(10001, "参数无效"),
PARAM_IS_BLANK(10002, "参数为空"),
PARAM_TYPE_BIND_ERROR(10003, "参数格式错误"),
PARAM_NOT_COMPLETE(10004, "参数缺失"),
/* 用户错误:20001-29999*/
USER_NOT_LOGGED_IN(20001, "用户未登录,请先登录"),
USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
USER_NOT_EXIST(20004, "用户不存在"),
USER_HAS_EXISTED(20005, "用户已存在"),
/* 业务错误:30001-39999 */
BUSINESS_GROUP_NO_ALLOWED_DEL(30001, "应用分组已经被应用使用,不能删除"),
BUSINESS_THEME_NO_ALLOWED_DEL(30002, "主题已经被用户使用,不能删除"),
BUSINESS_THEME_NO_ALLOWED_DISABLE(30003, "主题已经被用户使用,不能停用"),
BUSINESS_THEME_DEFAULT_NO_ALLOWED_DEL(30004, "默认主题,不能删除"),
BUSINESS_THEME_NO_ALLOWED_UPDATE(30005, "主题已经被用户使用,不能修改图片信息"),
BUSINESS_IS_TOP(30040, "已经到最顶部"),
BUSINESS_IS_BOTTOM(30041, "已经到最底部"),
BUSINESS_NAME_EXISTED(30051, "名称已存在"),
/* 系统错误:40001-49999 */
SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
UPLOAD_ERROR(40002, "系统异常,上传文件失败"),
FILE_MAX_SIZE_OVERFLOW(40003, "上传尺寸过大"),
FILE_ACCEPT_NOT_SUPPORT(40004, "上传文件格式不支持"),
SET_UP_AT_LEAST_ONE_ADMIN(40005, "至少指定一个管理员"),
URL_INVALID(40006, "地址不合法"),
LINK_AND_LOGOUT_NO_MATCH(40006, "主页地址和注销地址IP不一致"),
IP_AND_PORT_EXISTED(40007, "当前IP和端口已经被占中"),
LINK_IS_REQUIRED(40008, "生成第三方token认证信息: 主页地址不能为空,请完善信息"),
ONLY_ROOT_DEPARTMENT(40009, "组织机构只能存在一个根机构"),
DEPART_CODE_EXISTED(40010, "组织机构编码已存在"),
DEPART_CONTAINS_USERS(40011, "该机构下是存在用户,不允许删除"),
DEPART_CONTAINS_SON(40012, "该机构下是存在子级机构,不允许删除"),
DEPART_PARENT_IS_SELF(40013, "选择的父机构不能为本身"),
DICT_EXIST_DEPEND(40014, "该字典数据存在详情依赖,不允许删除"),
DICT_DETAIL_LOCK(40015, "该字典数据被锁定,不允许修改或删除"),
DEPART_CODE_EXISTED_WITH_ARGS(40016, "组织机构编码【{0}】系统已存在"),
/* 数据错误:50001-599999 */
RESULT_DATA_NONE(50001, "数据未找到"),
DATA_IS_WRONG(50002, "数据有误"),
DATA_ALREADY_EXISTED(50003, "数据已存在"),
AUTH_CODE_ERROR(50004, "验证码错误"),
/* 接口错误:60001-69999 */
INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),
INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),
/* 权限错误:70001-79999 */
PERMISSION_UNAUTHENTICATED(70001, "此操作需要登陆系统!"),
PERMISSION_UNAUTHORISE(70002, "权限不足,无权操作!"),
PERMISSION_EXPIRE(70003, "登录状态过期!"),
PERMISSION_TOKEN_EXPIRED(70004, "token已过期"),
PERMISSION_LIMIT(70005, "访问次数受限制"),
PERMISSION_TOKEN_INVALID(70006, "无效token"),
PERMISSION_SIGNATURE_ERROR(70007, "签名失败"),
PERMISSION_VIP(70000, "权限不足,此影片需要大会员,请开通大会员");
//操作代码
int code;
//提示信息
String message;
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
public int code() {
return code;
}
public String message() {
return message;
}
public void setCode(int code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.hmx.miniprogram.common;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data;
import org.springframework.data.domain.Page;
import java.util.List;
/**
* 分页数据封装类
*/
@Data
public class CommonPage<T> {
private Integer pageNum;
private Integer pageSize;
private Integer totalPage;
private Long total;
private List<T> list;
public static <T>CommonPage<T> restPage(IPage<T> list){
CommonPage<T> result = new CommonPage<>();
result.setList(list.getRecords());
result.setTotal(list.getTotal());
result.setPageSize((int) list.getSize());
result.setTotalPage((int) list.getPages());
result.setPageNum((int) list.getCurrent());
return result;
}
/**
* 将SpringData分页后的list转为分页信息
*/
public static <T> CommonPage<T> restPage(Page<T> pageInfo) {
CommonPage<T> result = new CommonPage<T>();
result.setTotalPage(pageInfo.getTotalPages());
result.setPageNum(pageInfo.getNumber());
result.setPageSize(pageInfo.getSize());
result.setTotal(pageInfo.getTotalElements());
result.setList(pageInfo.getContent());
return result;
}
}
3. 首页轮播图
3.1 接口说明
接口url:/cwApi/courseware/getCarousel
请求方式: get
请求参数:
名称 | 类型 | 描述 |
---|---|---|
返回数据:
// http://localhost:5000/cwApi/courseware/getCarousel
{
"code": 0,
"message": "操作成功!",
"data": [
{
"id": 1,
"name": null,
"price": null,
"count": null,
"url": null,
"cover": null,
"createTime": null,
"carouselUrl": "/courseware/carousel/1.jpg",
"isCarousel": null
},
{
"id": 4,
"name": null,
"price": null,
"count": null,
"url": null,
"cover": null,
"createTime": null,
"carouselUrl": "/courseware/carousel/2.jpg",
"isCarousel": null
},
{
"id": 20,
"name": null,
"price": null,
"count": null,
"url": null,
"cover": null,
"createTime": null,
"carouselUrl": "/courseware/carousel/3.jpg",
"isCarousel": null
}
]
}
3.2 Controller
@GetMapping("/getCarousel")
public Result getCarousel() {
return coursewareService.getCarousel();
}
3.3 Service
public Result getCarousel() {
LambdaQueryWrapper<Courseware> queryWrapper = Wrappers.<Courseware>lambdaQuery().gt(Courseware::getIsCarousel, 0).orderByAsc(Courseware::getIsCarousel);
queryWrapper.select(Courseware::getId,Courseware::getCarouselUrl);
List<Courseware> coursewareList = coursewareMapper.selectList(queryWrapper);
return Result.SUCCESS(coursewareList);
}