因为一部遮天,我用三种语言实现了腾讯国漫评分系统(三):后台接口和修仙大成篇

前言

"仙路尽头谁为峰,一见无始道成空。"

2013年初读遮天,十年后遮天的动漫正式上线。依稀记得高中记忆力"三十年河东三十年河西"的萧炎和独断万古的荒天帝。不知道当年经典绝伦的小说,如今改成动漫口碑如何。

于是就打开腾讯视频看看评分,每个视频都要点开才能看到评分和介绍。随即就萌生了用技术整合国漫评分内容的想法。最后历经一周,完成了一个简单的评分展示系统。

上一篇文章写的是腾讯国漫数据获取的部分,这篇文章主要写的是使用vue生态构建前端的部分。

静态展示:

动态展示:

三. 后台接口

从上面的前端设计来看,因为也没有搜索之类的设计,所以只需要一个接口获取MySQL中的评分信息就可以了。后台接口我这里就选择Java的springboot + Mybatis来做一个数据查询接口。前台请求就是axios

springboot

已经两三年没有写过后台接口了,写的时候有点生疏感。

1. 数据源

使用的阿里Druid,来定义数据源。

使用 @Value 来读取application.properties中的数据库配置信息。

2. mapper

定义了两个mapper,一个是分页查询,使用评分排序;另一个就是count统计。

java 复制代码
@Mapper
public interface CartoonMapper {
    @Select("select * from cartoon order by score desc limit #{start}, #{num};")
    List<CartoonDomain> listCartoon(int start, int num);

    @Select("select count(*) from cartoon")
    int countCartoon();
}

其中CartoonDomain是和数据库的cartoon的ORM实体类。

3. service

然后实现service,来调用mapper中的dao。

java 复制代码
@Service
public class CartoonService {
    @Autowired
    private CartoonMapper cartoonMapper;

    public List<CartoonDomain> listCartoon10(int start, int num) {
        List<CartoonDomain> cartoonList= cartoonMapper.listCartoon(start, num);
        return cartoonList;
    }

    public int countCartoon() {
        int count = cartoonMapper.countCartoon();
        return count;
    }
}

4. controller

就实现了一个controller。

java 复制代码
@RequestMapping("cartoon")
@RestController
public class CartoonController {
    @Autowired
    private CartoonService cartoonService;

    @RequestMapping(value="/listCartoon", method= RequestMethod.POST)
    public HashMap<String, Object> getCartoon(@RequestBody Params params) {
        int num = 10;
        List<CartoonDomain> cartoonList = cartoonService.listCartoon(params.getPage() * 10, num);
        int count = cartoonService.countCartoon();
        HashMap<String, Object> map = new HashMap<>();
        map.put("count", count);
        map.put("data", cartoonList);
        return map;
    }
}

使用 @RequestBody 限定前端传入一个json格式的参数在getCartoon() 中,定义了一个Params实体类来接收参数,这个类中只有一个page字段,用来实现mapper中的分页,这里num指定了每页10个。

使用 @RestController限定返回值为json,第一层json是count和data字段,data字段里面存放的是国漫数据的list。

启动springboot程序,使用Http Client进行请求测试:

可以看到已经请求到了目标数据。接下来就是在前端来实现请求模块。

前端:axios

首先就是安装axios

封装axios工具

在src/utils目录中封装一个请求工具类axios.ts

JavaScript 复制代码
import axios from "axios";
import {AxiosRequestConfig} from "axios";

export function createAxios(baseURL: string, axiosConfig: AxiosRequestConfig) {
  const Axios = axios.create({
    baseURL: baseURL,
    headers: {
      "Content-Type": "application/json;charset=UTF-8"
    },
    responseType: 'json'
  })
  return  Axios(axiosConfig)
}

使用axios的create 封装了一个createAxios() 方法,构建了一个模板化的创建Axios实例的工具。我们只要传入baseURL和请求配置axiosConfig就可以直接发起请求。

实现请求api

然后在src下新建一个api目录,在api中新增cartoon.ts用来封装请求。

javascript 复制代码
import {createAxios} from "@/utils/axios";

const baseURL = "http://localhost:8080/cartoon_web/"
export function getCartoonList(page: number) {
  const data = {
    'page': page
  }
  return createAxios(
    baseURL,
    {url: 'cartoon/listCartoon', method: 'post', data: data}
  )
}

实现了getCartoonList 方法来调用springboot定义的接口,通过createAxios() 方法,然后将url、method和data以字典形式传入axiosConfig,然后发起请求。

调用api

接下来就是调用getCartoonList请求后获取数据。在哪里获取数据,因为数据是渲染在carousel、title的组件上的,所以可以在他们的父组件进行请求,即布局组件。

javascript 复制代码
import {onBeforeMount} from 'vue'
import {getCartoonList} from "@/api/cartoon/cartoon";

onBeforeMount(() => {
  getCartoonList(0).then((res) => {
    console.log(res.data)
  })
})

天下武功,唯快不破。在onBeforeMount 生命周期函数发起请求,请求之后使用then回调函数来处理响应数据,这里先简单的打印一下,看看数据。

刷新页面,控制台跨域错误,导致无法请求数据。

返回springboot的应用,在controller的getCartoon方法上,添加 @CrossOrigin注解允许跨域。

再次刷新页面,看控制台,已经输出请求数据。

和之前使用Http Client测试请求的的数据是一样的。接下来就是如何处理数据渲染到各个组件上了。

处理响应数据

因为是多个组件都会用到响应数据做渲染,所以要像之前写过的路由动态加载一样,将这些数据放到pinia作为全局状态变量。这里就在之前实现carousel同步的pinia状态useCarousel中进行新增。

之前预留了cartoonData字段就是用来存储data信息的,同时有新增了4个字段。

maxPage表示最多能向后台请求多少次数据,这个可以根据后台返回的count计算得到。

currentPage表示当前请求的是第几页数据,从0开始,如果 = maxPage则从0开始重新获取。

maxIndex是表示轮播图轮播图最多可以播放到的index,到达时则请求下一页的数据。

currentIndex表示当前幻灯片的缩影,从0开始,如果 = maxIndex则发起请求

在layout布局组件中,发起数据请求,根据count 计算出总页数(从0开始),然后赋值给maxPage

这样就将请求的第一页数据,放到了cartoonData共享变量中,然后就是渲染数据,先将图片渲染到carousel组件,这里有两个carousel,渲染方式都一样,所以这里只挑一个写。

渲染carousel

carousel主要是图片,这里要注意的一定就是img的src属性,必须要用require来加载图片。

在layout中获取了第一页数据,那么后面如何获取后面的数据,这个就在carousel中实现,在轮播图中有一个change事件,当切换图片时,就会自动调用此方法,所以思路就是当轮播到第10张图片时,就进行下一页请求。

typescript 复制代码
function change(current: number, pre: number) {
    const maxIndex = carouselStore.state.maxIndex
    if (current == maxIndex) {
      let currentPage = carouselStore.state.currentPage + 1
      if (currentPage > carouselStore.state.maxPage) {
         currentPage = 0
      }
      getCartoonList(currentPage).then((res) => {
        carouselStore.setCartoonData(res.data['data'])
        carouselStore.state.currentPage = currentPage
      })
    }
    carouselStore.state.currentIndex = current
  }

current 指的是翻转后图片的索引,从0开始。若current等于状态变量中的maxIndex ,则进行请求,但前提当前请求页数currentPage 不能大于maxPage,否则就置为0请求第一页数据。

控制台可以看到读取了新一页的数据。

渲染score.vue

然后就是对评分组件的渲染。

主要工作就是替换template中文字部分,在渲染进度条的时候,使用了customColors的颜色。

javascript 复制代码
const customColors = [
    {color: '#f56c6c', percentage: 20},
    {color: '#e6a23c', percentage: 40},
    {color: '#5cb87a', percentage: 60},
    {color: '#1989fa', percentage: 80},
    {color: '#6f7ad3', percentage: 100},
  ]

查看渲染后的网页。

可以看到score和description随着轮播图切换也实时渲染数据。

渲染description.vue

对描述组件的渲染。

这里就是纯纯的对文本部分进行替换。

渲染title.vue

这个title的渲染按理说难度也没多大,主要是在 <el-rate> 的v-model绑定评分数据时,本来想直接绑定研究了一阵子,后来就直接用watch监控变量。

像name是直接渲染,tags是做了一个为空不展示的处理,score需要单独的处理。

javascript 复制代码
const carouselStore = useCarousel()
const score = ref(0.0)

watch(() => carouselStore.state.currentIndex, () => {
  score.value = parseFloat(carouselStore.state.cartoonData[carouselStore.state.currentIndex]?.score)
})

watch(() => carouselStore.state.cartoonData, () => {
  score.value = parseFloat(carouselStore.state.cartoonData[0]?.score)
})

对score进行了两部分的处理,一是currentIndex改变,即轮播图片切换时,需要修改,但是这样第一个的评分就显示不了,所以再对cartoonData进行监控,每次请求数据都会修改。

这样,一个腾讯国漫评分页面就完成了。

结语

这就是我基于python、Java和vue写的一个简单的评分展示系统,虽然很简单,但也将数据采集、数据清洗、后台开发、前端设计融合了起来。前端是我的短板,在很多地方就纠结了很久,不过经历这一次的实践之后也有一丝丝成长。

相关推荐
一孤程18 分钟前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒20 分钟前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai1 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript
Hyyy2 小时前
很多Desktop都在上的Computer Use是什么
前端·llm
慢功夫2 小时前
开篇:VS Code 为什么不是一个普通 React App
前端·visual studio code
你挚爱的强哥2 小时前
Vue2 实现 1.5s 十连击监听(连续点击若干次),封装通用可复用点击检测工具,不用 data!Vue 封装通用连击监听方法,支持自定义时长与点击次数
前端·javascript·vue.js
程序员张32 小时前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
CaffeinePro2 小时前
FastAPI数据库集成SQLAlchemy异步ORM全方案
后端·fastapi
小旭Coding2 小时前
凌晨告警轰炸!Go 服务协程只增不减,内存持续暴涨直至 OOM
后端
半个落月2 小时前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端