文章目录

  • 一、环境准备
  • 二、前端构建
    • 2.1 页面绘制
      • 2.1.1 网站框架`App.vue`
      • 2.1.2 前台观影/电影首页`Movie.vue`
      • 2.1.3 前台观影/播放电影`Player.vue`
      • 2.1.4 数据查询/电影筛选`MovieQuery.vue`
      • 2.1.5 数据查询/评分细查`RatingQuery.vue`
      • 2.1.6 数据查询/可视化数据`Charts.vue`
    • 2.2 相关配置
      • 2.2.1 项目配置`main.js`
      • 2.2.2 路由配置`router/index.js`
  • 三、相关博客

一、环境准备

  首先准备好node环境并安装好vue,在存储项目的目录下使用命令vue init webpack movie-web,然后一路enter,等待片刻便可以初始化一个名为movie-webVue 2项目。

  进入Vue项目主目录,依次调用如下命令安装第三方组件:

npm install element-ui -S
npm install echarts@4.9.0
npm install vue-router
npm install axios

二、前端构建

2.1 页面绘制
2.1.1 网站框架App.vue
<template><div id="app"><el-header id="header" height="60px"><div id="title"><span id="big-title">uQiYi</span><span id="small-title">v1.0.1</span></div><div id="userinfo"><span id="user-name">Hello, Chiak1</span></div></el-header><el-container><el-aside width="20%"><el-menu default-active="1"><el-submenu index="1"><template slot="title">前台观影</template><el-menu-item index="movie" @click="goTo('/movie')">电影首页</el-menu-item><el-menu-item index="rating" @click="goTo('/player')">播放电影</el-menu-item></el-submenu><el-submenu index="2"><template slot="title">数据查询</template><el-menu-item index="movie_query" @click="goTo('/movie_query')">电影筛选</el-menu-item><el-menu-item index="rating_query" @click="goTo('/rating_query')">评分细查</el-menu-item><el-menu-item index="charts" @click="goTo('/charts')">可视化数据</el-menu-item></el-submenu><el-submenu index="3"><template slot="title">用户中心</template><el-menu-item index="userinfo">用户信息</el-menu-item></el-submenu></el-menu></el-aside><el-main><router-view></router-view></el-main></el-container></div>
</template><script>
export default {name: 'App',methods: {goTo (url) {this.$router.replace(url)}}
}
</script><style scoped>
#app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}#header {height: 10%;background-color: #67C23A;position: absolute;top: 0px;left: 0px;right: 0px;
}#title {position: absolute;top: 10px;left: 50px;
}#big-title {font-size: 30px;color: white;
}#small-title {padding-left: 10px;font-size: 14px;color: white;
}#userinfo {position: absolute;top: 18px;right: 50px;
}#user-name {font-size: 20px;color: white;
}span {font-size: 14px;
}
</style>
2.1.2 前台观影/电影首页Movie.vue
/* eslint-disable */
<template><div><div class="block"><span style="color: green; font-size: 20px; font-weight: bold">猜你喜欢</span><el-carousel :interval="3000" type="card" height="300px" style="padding-top: 10px"><el-carousel-item v-for="poster in this.posters" :key="poster"><el-image :src="poster" fit="cover" style="width: 210px; height: 300px"></el-image></el-carousel-item></el-carousel><el-table stripe :data="recommend" height="300px" style="width: 650px; position: absolute; left: 5%"><el-table-column label="电影ID" prop="movieId"></el-table-column><el-table-column label="电影名" prop="title"></el-table-column><el-table-column label="平均评分" prop="avgRating"></el-table-column></el-table></div><div id="box2"><span style="color: green">最近热播 Hot(10s 更新一次)</span><el-table stripe :data="hot" v-loading="loading" height="650px"><el-table-column type="index"></el-table-column><el-table-column label="电影ID" prop="movieId"></el-table-column><el-table-column label="电影名" prop="title"></el-table-column><el-table-column label="播放次数" prop="count"></el-table-column></el-table></div></div>
</template><script>
import axios from 'axios'
export default {name: 'Movie',data () {return {timer: null,posters: [],// 示例数据movies: {1: {movieId: 1, title: "你的名字", avgRating: 4.82},2: {movieId: 2, title: "超凡蜘蛛侠", avgRating: 4.3},3: {movieId: 3, title: "毒液:致命守护者", avgRating: 4.44},4: {movieId: 4, title: "硬汉", avgRating: 3.98},5: {movieId: 5, title: "不明身份", avgRating: 3.99},6: {movieId: 6, title: "天下无贼", avgRating: 4.52},7: {movieId: 7, title: "蝙蝠侠:黑暗骑士", avgRating: 4.51},8: {movieId: 8, title: "釜山行", avgRating: 4.03},9: {movieId: 9, title: "寂静岭", avgRating: 3.87},10: {movieId: 10, title: "我是传奇", avgRating: 3.92},11: {movieId: 11, title: "泰坦尼克", avgRating: 4.91},12: {movieId: 12, title: "翻译疑云", avgRating: 3.69},13: {movieId: 13, title: "禁闭岛", avgRating: 4.61},14: {movieId: 14, title: "绣春刀", avgRating: 3.98}},recommend: [],hot: []}},created () {var posterNames = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]for (var i = 0; i < 5; i++) {var id = parseInt(Math.random() * posterNames.length)this.posters.push(require("@/assets/" + posterNames[id] + ".jpeg"))this.recommend.push(this.movies[posterNames[id]])posterNames.splice(id, 1)}this.init()},beforeDestroy () {clearInterval(this.timer)this.timer = null},methods: {init () {this.timer = setInterval(() => {axios.post('/movie/hot').then((res) => {if (res.data) {this.hot = res.data} else {this.$message("查询数据失败")this.hot = []}})}, 10000)}}
}
</script><style scoped>
.block {width: 50%;position: absolute;top: 10%;left: 20%
}#box2 {width: 25%;position: absolute;top: 10%;left: 72%;
}
</style>
2.1.3 前台观影/播放电影Player.vue
/* eslint-disable */
<template><div><div id="box1"><el-input v-model="movieId" placeholder="电影ID" style="width: 150px"></el-input><el-button type="success" plain @click="play()">播放电影</el-button><el-button type="danger" plain @click="clear()">取消播放</el-button></div><div id="box2"><video width="800px" height="500px" controls autoplay><source :src="movie" type="video/mp4">您的浏览器不支持 video 标签。</video></div><div id="box3"><el-rate v-model="rating" :colors="colors"></el-rate><el-input v-model="userId" placeholder="用户ID" style="width: 150px"></el-input><el-button type="success" plain @click="rate()">确认评分</el-button></div></div>
</template><script>
import axios from 'axios'
export default {name: 'Player',data () {return {movieId: null,movie: null,rating: null,userId: null,colors: ['#99A9BF', '#F7BA2A', '#FF9900']}},methods: {play () {this.movie = require("@/assets/video/" + this.movieId + ".mp4")},clear () {this.movie = nullthis.movieId = nullthis.rating = nullthis.userId = null},rate () {axios.post('/player/rate', {"userId": this.userId, "movieId": this.movieId, "rating": this.rating})this.$message("评分成功")this.clear()}}
}
</script><style scoped>
#box1 {width: 40%;height: 100px;position: absolute;top: 12%;left: 15%;
}#box2 {position: absolute;left: 30%;bottom: 10%;
}#box3 {width: 40%;height: 100px;position: absolute;top: 10%;right: 5%;
}
</style>
2.1.4 数据查询/电影筛选MovieQuery.vue
/* eslint-disable */
<template><div><div id="box1"><el-input v-model="minAvgRating" placeholder="平均分≥" style="width: 150px"></el-input><el-input v-model="minCount" placeholder="评分次数≥" style="width: 150px; padding-right: 20px"></el-input><el-switch v-model="useCount" active-text="评分次数" inactive-text="平均分"></el-switch><el-button type="primary" plain @click="query()" style="margin-left: 30px">查询结果</el-button><el-button type="danger" plain @click="clear()">清除查询</el-button></div><div id="box2"><el-table stripe :data="movieList" v-loading="loading" height="550px"><el-table-column type="index"></el-table-column><el-table-column label="电影ID" prop="movieId"></el-table-column><el-table-column label="电影名" prop="title"></el-table-column><el-table-column label="电影题材" prop="genres"></el-table-column><el-table-column label="平均评分" prop="avgRating"></el-table-column><el-table-column label="评分次数" prop="count"></el-table-column></el-table></div></div>
</template><script>
import axios from 'axios'
export default {name: 'MovieQuery',data () {return {minAvgRating: null,minCount: null,useCount: null,movieList: [],loading: false}},methods: {query () {if (this.loading) {this.$message('当前有查询正在进行,请稍后')} else {this.loading = trueaxios.post('/movie_query/query', {minAvgRating: this.minAvgRating, minCount: this.minCount, useCount: this.useCount}).then((res) => {if (res.data && this.loading) {this.movieList = res.datathis.$message('查询成功')} else {this.$message('查询失败')}this.loading = false})}},clear () {this.minAvgRating = nullthis.minCount = nullthis.useCount = nullthis.movieList = []this.loading = false}}
}
</script><style scoped>
#adv {height: 20%;width: 79.62%;position: absolute;top: 7.3%;left: 20.38%;
}#box1 {width: 70%;height: 100px;position: relative;top: 10%;
}
</style>
2.1.5 数据查询/评分细查RatingQuery.vue
/* eslint-disable */
<template><div><div id="box1"><el-input v-model="movieId" placeholder="电影ID" @change="searchRating()" style="width: 150px" clearable></el-input><el-input v-model="avgRating" placeholder="平均评分" style="width: 150px" label="平均分" readonly="true"></el-input><el-button type="danger" plain @click="clear()">清除数据</el-button></div><div id="box2"><el-table stripe :data="ratingList" v-loading="loading" height="550px"><el-table-column type="index"></el-table-column><el-table-column label="电影ID" prop="movieId"></el-table-column><el-table-column label="电影名" prop="title"></el-table-column><el-table-column label="用户ID" prop="userId"></el-table-column><el-table-column label="用户评分" prop="rating"></el-table-column></el-table></div></div>
</template><script>
import axios from 'axios'
export default {name: 'RatingQuery',data () {return {movieId: null,avgRating: null,ratingList: [],loading: false}},methods: {searchRating () {if (this.movieId) {if (this.loading) {this.$message('当前有查询正在进行,请稍后')} else {this.loading = trueaxios.post('/rating_query/query', {movieId: this.movieId}).then((res) => {if (res.data && this.loading) {this.ratingList = res.datavar sum = 0var count = 0for (var i in this.ratingList) {sum += this.ratingList[i].ratingcount += 1}this.avgRating = (sum / count).toFixed(2)this.$message('查询成功')} else {this.$message('查询失败')}this.loading = false})}}},clear () {this.movieId = nullthis.avgRating = nullthis.ratingList = []this.loading = false}}
}
</script><style scoped>
#box1 {width: 40%;height: 100px;position: relative;top: 10%;
}
</style>
2.1.6 数据查询/可视化数据Charts.vue
/* eslint-disable */
<template><div><el-tabs v-model="active" type="border-card" @tab-click="handleClick" style="height: 700px"><el-tab-pane label="信息概览" name="A" style="height: 630px; width: 1070px;"><div id="chart1"></div><div id="chart2"></div><div id="chart3"></div><div id="chart4"></div></el-tab-pane><el-tab-pane label="电影数据" name="B" style="height: 630px; width: 1070px;"><div id="chart5"></div><div id="chart6"></div><div id="chart7"></div></el-tab-pane></el-tabs></div>
</template><script>
import axios from 'axios'
import * as echarts from 'echarts'
export default {name: 'Charts',data () {return {timer: null,active: "A",chart1x: [],chart1y: [],chart2data: [],chart3x: [],chart3y: [],chart4x: [],chart4y: [],chart5x: [],chart5y: [],chart6x: [],chart6y: [],chart7data: []}},created () {this.init()},beforeDestroy () {clearInterval(this.timer)this.timer = null},methods: {init () {this.timer = setInterval(() => {axios.post('/charts/query').then((res) => {if (res.data) {this.chart1x = res.data.chart1.xconsole.log(this.chart1x)this.chart1y = res.data.chart1.ythis.chart2data = res.data.chart2.datathis.chart3x = res.data.chart3.xthis.chart3y = res.data.chart3.ythis.chart4x = res.data.chart4.xthis.chart4y = res.data.chart4.ythis.chart5x = res.data.chart5.xthis.chart5y = res.data.chart5.ythis.chart6x = res.data.chart6.xthis.chart6y = res.data.chart6.ythis.chart7data = res.data.chart7.datathis.drawLine()} else {this.$message("查询数据失败")}})}, 1000)},drawLine () {var chart1 = echarts.init(document.getElementById('chart1'))chart1.setOption({title: {text: '评分分布'},color: ['#67C23A'],tooltip: {},xAxis: {type: 'category',boundaryGap: false,data: this.chart1x},yAxis: {},series: [{name: '电影评分',type: 'bar',data: this.chart1y}]})var chart2 = echarts.init(document.getElementById('chart2'))chart2.setOption({tooltip: {trigger: 'item'},legend: {top: '5%',left: 'center'},series: [{name: '评分分布',type: 'pie',radius: ['40%', '70%'],avoidLabelOverlap: false,itemStyle: {borderRadius: 10,borderColor: '#fff',borderWidth: 2},label: {show: false,position: 'center'},emphasis: {label: {show: true,fontSize: '40',fontWeight: 'bold'}},labelLine: {show: false},data: this.chart2data}]})var chart3 = echarts.init(document.getElementById('chart3'))chart3.setOption({title: {text: '每 10s 平台电影评分次数'},color: ['#67C23A'],tooltip: {},xAxis: {type: 'category',boundaryGap: false,data: this.chart3x},yAxis: {type: 'value'},series: [{name: '评分次数',type: 'line',data: this.chart3y,smooth: true}]})var chart4 = echarts.init(document.getElementById('chart4'))chart4.setOption({title: {text: '平台电影评分总次数'},color: ['#67C23A'],tooltip: {},xAxis: {type: 'category',boundaryGap: false,data: this.chart4x},yAxis: {type: 'value'},series: [{name: '评分次数',type: 'line',data: this.chart4y,smooth: true}]})var chart5 = echarts.init(document.getElementById('chart5'))chart5.setOption({title: {text: '电影评分 Top5'},color: ['#67C23A'],tooltip: {},xAxis: {type: 'category',boundaryGap: false,data: this.chart5x},yAxis: {},series: [{name: '电影评分',type: 'bar',data: this.chart5y}]})var chart6 = echarts.init(document.getElementById('chart6'))chart6.setOption({title: {text: '评分次数 Top5'},color: ['#67C23A'],tooltip: {},xAxis: {type: 'category',boundaryGap: false,data: this.chart6x},yAxis: {},series: [{name: '电影评分',type: 'bar',data: this.chart6y}]})var chart7 = echarts.init(document.getElementById('chart7'))chart7.setOption({legend: {top: 'bottom'},tooltip: {},series: [{name: '评分次数',type: 'pie',radius: [50, 250],center: ['50%', '50%'],roseType: 'area',itemStyle: {borderRadius: 8},data: this.chart7data}]})}}
}
</script><style scoped>
#chart1 {width: 300px;height: 300px;position: absolute;top: 20px;left: 40px;
}#chart2 {width: 300px;height: 300px;position: absolute;top: 340px;left: 40px;
}#chart3 {width: 600px;height: 300px;position: absolute;top: 20px;left: 380px;
}#chart4 {width: 600px;height: 300px;position: absolute;top: 340px;left: 380px;
}#chart5 {width: 300px;height: 300px;position: absolute;top: 20px;left: 40px;
}#chart6 {width: 300px;height: 300px;position: absolute;top: 340px;left: 40px;
}#chart7 {width: 650px;height: 600px;position: absolute;top: 20px;left: 400px;
}
</style>
2.2 相关配置
2.2.1 项目配置main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import Vue from 'vue'
import App from './App'
import VueResource from 'vue-resource'
import router from './router'Vue.use(VueResource)
Vue.use(ElementUI)
Vue.config.productionTip = false
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8001'/* eslint-disable no-new */
new Vue({el: '#app',router,components: { App },template: '<App/>'
})
2.2.2 路由配置router/index.js

  初始化的Vue项目中并不包含路由,所以需要手动在src目录下创建文件夹router,然后在router下创建配置文件index.js如下:

import Vue from 'vue'
import Router from 'vue-router'
import Movie from '@/components/Movie'
import Player from '@/components/Player'
import MovieQuery from '@/components/MovieQuery'
import RatingQuery from '@/components/RatingQuery'
import Charts from '@/components/Charts'Vue.use(Router)export default new Router({routes: [{path: '/',redirect: '/movie'},{path: '/movie',name: 'Movie',component: Movie},{path: '/player',name: 'Player',component: Player},{path: '/movie_query',name: 'MovieQuery',component: MovieQuery},{path: '/rating_query',name: 'RatingQuery',component: RatingQuery},{path: '/charts',name: 'Charts',component: Charts}]
})

三、相关博客

  • 基于Flink的电影数据实时统计平台(一):项目展示
  • 基于Flink的电影数据实时统计平台(二):项目结构
  • 基于Flink的电影数据实时统计平台(四):后端项目构建与数据准备
  • 基于Flink的电影数据实时统计平台(五):流计算业务实现
  • 基于Flink的电影数据实时统计平台(六):后端业务实现

基于Flink的电影数据实时统计平台(三):前端构建相关推荐

  1. 基于Flink的电影数据实时统计平台(一):项目展示

    文章目录 一.项目介绍 二.项目演示 2.1 前端观影/电影首页 2.2 前端观影/播放电影 2.3 数据查询/电影筛选 2.4 数据查询/评分细查 2.5 数据查询/可视化数据 三.相关博客 一.项 ...

  2. Flink原理解析50篇(四)-基于 Flink CDC 打通数据实时入湖

    在构建实时数仓的过程中,如何快速.正确的同步业务数据是最先面临的问题,本文主要讨论一下如何使用实时处理引擎Flink和数据湖Apache Iceberg两种技术,来解决业务数据实时入湖相关的问题. 0 ...

  3. 基于Flink CDC打通数据实时入湖

    作者 | 数据社       责编 | 欧阳姝黎 在构建实时数仓的过程中,如何快速.正确的同步业务数据是最先面临的问题,本文主要讨论一下如何使用实时处理引擎 Flink 和数据湖 Apache Ice ...

  4. Flink从入门到精通100篇(十九)-基于 Flink 的大规模准实时数据分析平台的建设实践

    前言 如何基于 Flink 搭建大规模准实时数据分析平台?在 Flink Forward Asia 2019 上,来自 Lyft 公司实时数据平台的徐赢博士和计算数据平台的高立博士分享了 Lyft 基 ...

  5. 基于Flink百亿数据实时去重

    基于传统的Set方法去重,以及弊端 去重处理方法: 需要一个全局 set集合来维护历史所有数据的主键.当处理新日志时,需要拿到当前日志的主键与历史数据的 set 集合按照规则进行比较,若 set集合中 ...

  6. 基于Flink的个人装扮商城群体用户画像与数据实时统计系统(六)-需求集C实现

    文章目录 一.需求集C有什么? 二.模拟生成用户购买商品的信息 三.需求集C实现 一.需求集C有什么? 所有需求link:基于Flink的个人装扮商城群体用户画像与数据实时统计系统(二)-项目介绍与需 ...

  7. 基于Flink的高可靠实时ETL系统

    GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)是长期关注互联网技术与架构的高可用架构技术社区和msup推出的,面向架构师.技术负责人及高端技术从业人员的年度 ...

  8. 基于 Flink 的超大规模在线实时反欺诈系统的建设与实践

    在大数据时代,金融科技公司通常借助消费数据来综合评估用户的信用和还款能力.这个过程中,某些中介机构会搜集大量的号并进行"养号"工作,即在一年周期里让这些号形成正常的消费.通讯记录, ...

  9. 基于Flink的超大规模在线实时反欺诈系统的建设与实践

    作者:关贺宇 在大数据时代,金融科技公司通常借助消费数据来综合评估用户的信用和还款能力.这个过程中,某些中介机构会搜集大量的号并进行"养号"工作,即在一年周期里让这些号形成正常的消 ...

最新文章

  1. Pandownload惊喜复活!下载速度惊人!
  2. 二十六、二叉树--查找指定节点
  3. 【云周刊】第178期:阿里云以生态联盟推动全球市场,牵手Bolloré集团全球合作...
  4. UA MATH566 统计理论1 充分统计量例题答案3
  5. 一棵树,怎么就平衡了(图解AVL+实现)
  6. C++ :学习(类、指针)
  7. Plitch for the final Feb 16
  8. go redis 序列化_求求你不要手写Redis缓存
  9. IIS服务器证书的导入 IIS 5、IIS 6、IIS 7
  10. 修改文件属性与权限(鸟哥linux私房菜)
  11. 谷粒学院【网上教育】总结
  12. Crystal Reports 2008|Crystal Reports 2008破解版下载
  13. 2017华为面试算法题小结
  14. 灵活使用CSS内联样式
  15. 微信公众平台、微信开放平台、微信商户平台的区别
  16. OSChina 周五乱弹 —— 为什么程序媛那么少?
  17. 如何评价微软在数据中心使用FPGA代替传统CPU的做法?
  18. python打字机效果_打字效果动画的4种实现方法(超简单)
  19. 锐化pdf文件(图片形式)
  20. 一文多图搞懂KITTI检测数据集下载使用(附网盘链接)

热门文章

  1. 交通运输部办公厅关于印发推进智慧交通发展行动计划(2017-2020年)的通知
  2. Mono Develop脚本编辑器介绍
  3. 万字博客带你了解Spring Framework 的全貌
  4. 当前时间转换为yy-mm-dd hh:mm:ss格式
  5. vim快捷键之复制(yy)+粘贴(p)+删除(dd)+撤销(u)+恢复(ctrl + r)大法
  6. Unity3d 中Legacy动画系统-剑圣的动画
  7. 针对mysql 5.7.20 数据恢复
  8. 最新最全面的Spring详解(一)——Spring概述与IOC容器
  9. python和苹果_苹果手机评论情感分析(附python源码和评论数据)
  10. node安装教程详解