├── .eslintignore ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── mixed-live-vue.iml ├── package-lock.json ├── package.json ├── pic ├── bilibili-logo.png ├── image-20210524192657052.png ├── image-20210524193646108.png ├── image-20210524193933924.png ├── image-20210524194048907.png ├── image-20210524194340048.png └── image-20210524194748667.png ├── public ├── favicon.ico ├── iconfont │ ├── demo.css │ ├── demo_index.html │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.js │ ├── iconfont.json │ ├── iconfont.svg │ ├── iconfont.ttf │ ├── iconfont.woff │ └── iconfont.woff2 └── index.html ├── src ├── App.vue ├── api │ ├── UserApi.js │ └── liveList.js ├── assets │ ├── LiveLogo.png │ ├── css │ │ └── style.css │ ├── js │ │ └── lib.js │ └── logo.png ├── components │ ├── Common │ │ ├── BilibiliDanmu.vue │ │ └── RoomList.vue │ ├── Global.vue │ ├── Home.vue │ ├── Index.vue │ ├── LivePage │ │ └── Room.vue │ ├── Login │ │ ├── BindMail.vue │ │ ├── Forget.vue │ │ ├── Login.vue │ │ └── Register.vue │ ├── MainPages │ │ ├── AreaAll.vue │ │ ├── Areas.vue │ │ ├── Follows.vue │ │ ├── PlatformRooms.vue │ │ ├── Platforms.vue │ │ ├── Recommend.vue │ │ ├── Search.vue │ │ └── Tv.vue │ ├── Mobile │ │ ├── ArtPlayerMobile.vue │ │ ├── FollowsMobile.vue │ │ ├── HomeMobile.vue │ │ ├── IndexMobile.vue │ │ ├── RecommendMobile.vue │ │ ├── RoomListMobile.vue │ │ ├── RoomMobile.vue │ │ └── SearchMobile.vue │ └── Test │ │ └── ArtPlayerTest.vue ├── main.js ├── router │ └── index.js └── utils │ ├── exception.js │ └── request.js └── vue.config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | src/assets/js/lib.js -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | ### Vue template 25 | # gitignore template for Vue.js projects 26 | # 27 | # Recommended template: Node.gitignore 28 | 29 | # TODO: where does this rule come from? 30 | docs/_book 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 YJ1211 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![image-20210524192657052](pic/image-20210524192657052.png) 2 | 3 | # JustLive-Web 4 | 5 | :tv:一个整合国内多个直播平台内容的网站,基于vue.js开发。 6 | 7 | 此项目为JustLive Web端💻 8 | 9 | 📱 Android版 [JustLive-Android](https://github.com/guyijie1211/JustLive-Android) 10 | 11 | 后端项目地址 [JustLive-Api](https://github.com/guyijie1211/JustLive-Api) 12 | 13 | QQ交流群:645962588 14 | 15 | 网站页面 👉 [live.yj1211.work](http://live.yj1211.work) 👈 16 | 17 | #### 功能 18 | 19 | ✔ 多平台直播信息获取 20 | 21 | ✔ 关注直播间 22 | 23 | ✔ 弹幕获取 24 | 25 | ✔ 直播间搜索 26 | 27 | 28 | 29 | ## 直播支持 30 | 31 | 虎牙、斗鱼、BILIBILI直播、网易cc(cc暂无清晰度切换) 32 | 33 | 直播源获取参考 [wbt5/real-url](https://github.com/wbt5/real-url) 34 | 35 | 播放器使用 [zhw2590582/ArtPlayer](https://github.com/zhw2590582/ArtPlayer) 36 | 37 | ## 弹幕支持(暂不支持弹幕发送) 38 | 39 | 斗鱼、BILIBILI直播、虎牙 40 | 41 | 斗鱼弹幕协议参考 [斗鱼开放平台](https://open.douyu.com/source/api/63) 42 | 43 | BILIBILI直播弹幕协议参考 [lovelyyoshino/Bilibili-Live-API](https://github.com/lovelyyoshino/Bilibili-Live-API) 44 | 45 | ## 更新记录 46 | **2022/08/11** 因企鹅电竞关站,先已取消支持该直播源 47 | 48 | **2021/07/28** 更换弹幕插件, 优化弹幕体验 49 | 50 | **2021/07/27** 增加企鹅电竞直播源 51 | 52 | **2021/07/09** 测试功能:电视节目直播 53 | 54 | **2021/07/07** 增加直播页面弹幕列表、房间列表和分区列表的动画效果 55 | 56 | **2021/06/29** 修复斗鱼房间人数达到“亿”后导致无法获取房间信息的问题 57 | 58 | **2021/06/28** 增加弹幕屏蔽功能(支持用户等级和弹幕内容屏蔽) 59 | 60 | **2021/06/27** 修复虎牙接口更新导致的问题 61 | 62 | **2021/06/08** 网站升级Https协议 63 | 64 | **2021/06/04** 增加虎牙弹幕获取支持 65 | 66 | 67 | ## 页面 68 | 69 | ![image-20210524193646108](pic/image-20210524193646108.png) 70 | 71 | ![image-20210524194748667](pic/image-20210524194748667.png) 72 | 73 | ![image-20210524193933924](pic/image-20210524193933924.png) 74 | 75 | ![image-20210524194048907](pic/image-20210524194048907.png) 76 | 77 | ![image-20210524194340048](pic/image-20210524194340048.png) 78 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /mixed-live-vue.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mixed-live-vue", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@silvermine/videojs-quality-selector": "^1.2.4", 12 | "@videojs/http-streaming": "^2.5.0", 13 | "artplayer": "^4.6.2", 14 | "artplayer-plugin-danmuku": "^4.4.11", 15 | "artplayer-vue": "^3.5.27", 16 | "axios": "^0.21.1", 17 | "comment-core-library": "^0.11.1", 18 | "compression-webpack-plugin": "^5.0.1", 19 | "core-js": "^3.6.5", 20 | "danmaku": "^2.0.2", 21 | "dns": "^0.2.2", 22 | "douyudm": "^2.0.1", 23 | "dplayer": "^1.26.0", 24 | "element-ui": "^2.14.1", 25 | "events": "^3.3.0", 26 | "flv.js": "^1.6.2", 27 | "hls.js": "^1.3.2", 28 | "huya-danmu": "^2.0.3", 29 | "jquery": "^3.5.1", 30 | "js-md5": "^0.7.3", 31 | "less-loader": "^5.0.0", 32 | "md5": "^2.3.0", 33 | "net": "^1.0.2", 34 | "pako": "^2.0.3", 35 | "qs": "^6.9.6", 36 | "request": "^2.88.2", 37 | "request-promise": "^4.2.6", 38 | "to-arraybuffer": "^1.0.1", 39 | "videojs-contrib-hls": "^5.15.0", 40 | "videojs-flvjs": "^0.2.0", 41 | "videojs-hls-quality-selector": "^1.1.4", 42 | "vue": "^2.6.11", 43 | "vue-lazyload": "^1.3.3", 44 | "vue-router": "^3.4.9", 45 | "vue-video-player": "^5.0.2", 46 | "vuex": "^3.6.0", 47 | "ws": "^7.4.4" 48 | }, 49 | "devDependencies": { 50 | "@vue/cli-plugin-babel": "~4.5.0", 51 | "@vue/cli-plugin-eslint": "~4.5.0", 52 | "@vue/cli-service": "~4.5.0", 53 | "babel-eslint": "^10.1.0", 54 | "css-loader": "^5.0.2", 55 | "douyudm": "^2.0.1", 56 | "eslint": "^6.7.2", 57 | "eslint-plugin-vue": "^6.2.2", 58 | "sass-loader": "^11.0.0", 59 | "ts-loader": "^8.0.16", 60 | "video.js": "^7.10.2", 61 | "vue-template-compiler": "^2.6.11", 62 | "webpack": "^4.0.0", 63 | "webpack-cli": "^4.5.0" 64 | }, 65 | "eslintConfig": { 66 | "root": true, 67 | "env": { 68 | "node": true 69 | }, 70 | "extends": [ 71 | "plugin:vue/essential", 72 | "eslint:recommended" 73 | ], 74 | "parserOptions": { 75 | "parser": "babel-eslint" 76 | }, 77 | "rules": { 78 | "no-unused-vars": "off" 79 | } 80 | }, 81 | "browserslist": [ 82 | "> 1%", 83 | "last 2 versions", 84 | "not dead" 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /pic/bilibili-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/bilibili-logo.png -------------------------------------------------------------------------------- /pic/image-20210524192657052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524192657052.png -------------------------------------------------------------------------------- /pic/image-20210524193646108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524193646108.png -------------------------------------------------------------------------------- /pic/image-20210524193933924.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524193933924.png -------------------------------------------------------------------------------- /pic/image-20210524194048907.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524194048907.png -------------------------------------------------------------------------------- /pic/image-20210524194340048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524194340048.png -------------------------------------------------------------------------------- /pic/image-20210524194748667.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/pic/image-20210524194748667.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/public/favicon.ico -------------------------------------------------------------------------------- /public/iconfont/demo.css: -------------------------------------------------------------------------------- 1 | /* Logo 字体 */ 2 | @font-face { 3 | font-family: "iconfont logo"; 4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); 5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), 6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), 7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), 8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); 9 | } 10 | 11 | .logo { 12 | font-family: "iconfont logo"; 13 | font-size: 160px; 14 | font-style: normal; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | /* tabs */ 20 | .nav-tabs { 21 | position: relative; 22 | } 23 | 24 | .nav-tabs .nav-more { 25 | position: absolute; 26 | right: 0; 27 | bottom: 0; 28 | height: 42px; 29 | line-height: 42px; 30 | color: #666; 31 | } 32 | 33 | #tabs { 34 | border-bottom: 1px solid #eee; 35 | } 36 | 37 | #tabs li { 38 | cursor: pointer; 39 | width: 100px; 40 | height: 40px; 41 | line-height: 40px; 42 | text-align: center; 43 | font-size: 16px; 44 | border-bottom: 2px solid transparent; 45 | position: relative; 46 | z-index: 1; 47 | margin-bottom: -1px; 48 | color: #666; 49 | } 50 | 51 | 52 | #tabs .active { 53 | border-bottom-color: #f00; 54 | color: #222; 55 | } 56 | 57 | .tab-container .content { 58 | display: none; 59 | } 60 | 61 | /* 页面布局 */ 62 | .main { 63 | padding: 30px 100px; 64 | width: 960px; 65 | margin: 0 auto; 66 | } 67 | 68 | .main .logo { 69 | color: #333; 70 | text-align: left; 71 | margin-bottom: 30px; 72 | line-height: 1; 73 | height: 110px; 74 | margin-top: -50px; 75 | overflow: hidden; 76 | *zoom: 1; 77 | } 78 | 79 | .main .logo a { 80 | font-size: 160px; 81 | color: #333; 82 | } 83 | 84 | .helps { 85 | margin-top: 40px; 86 | } 87 | 88 | .helps pre { 89 | padding: 20px; 90 | margin: 10px 0; 91 | border: solid 1px #e7e1cd; 92 | background-color: #fffdef; 93 | overflow: auto; 94 | } 95 | 96 | .icon_lists { 97 | width: 100% !important; 98 | overflow: hidden; 99 | *zoom: 1; 100 | } 101 | 102 | .icon_lists li { 103 | width: 100px; 104 | margin-bottom: 10px; 105 | margin-right: 20px; 106 | text-align: center; 107 | list-style: none !important; 108 | cursor: default; 109 | } 110 | 111 | .icon_lists li .code-name { 112 | line-height: 1.2; 113 | } 114 | 115 | .icon_lists .icon { 116 | display: block; 117 | height: 100px; 118 | line-height: 100px; 119 | font-size: 42px; 120 | margin: 10px auto; 121 | color: #333; 122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear; 123 | -moz-transition: font-size 0.25s linear, width 0.25s linear; 124 | transition: font-size 0.25s linear, width 0.25s linear; 125 | } 126 | 127 | .icon_lists .icon:hover { 128 | font-size: 100px; 129 | } 130 | 131 | .icon_lists .svg-icon { 132 | /* 通过设置 font-size 来改变图标大小 */ 133 | width: 1em; 134 | /* 图标和文字相邻时,垂直对齐 */ 135 | vertical-align: -0.15em; 136 | /* 通过设置 color 来改变 SVG 的颜色/fill */ 137 | fill: currentColor; 138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 139 | normalize.css 中也包含这行 */ 140 | overflow: hidden; 141 | } 142 | 143 | .icon_lists li .name, 144 | .icon_lists li .code-name { 145 | color: #666; 146 | } 147 | 148 | /* markdown 样式 */ 149 | .markdown { 150 | color: #666; 151 | font-size: 14px; 152 | line-height: 1.8; 153 | } 154 | 155 | .highlight { 156 | line-height: 1.5; 157 | } 158 | 159 | .markdown img { 160 | vertical-align: middle; 161 | max-width: 100%; 162 | } 163 | 164 | .markdown h1 { 165 | color: #404040; 166 | font-weight: 500; 167 | line-height: 40px; 168 | margin-bottom: 24px; 169 | } 170 | 171 | .markdown h2, 172 | .markdown h3, 173 | .markdown h4, 174 | .markdown h5, 175 | .markdown h6 { 176 | color: #404040; 177 | margin: 1.6em 0 0.6em 0; 178 | font-weight: 500; 179 | clear: both; 180 | } 181 | 182 | .markdown h1 { 183 | font-size: 28px; 184 | } 185 | 186 | .markdown h2 { 187 | font-size: 22px; 188 | } 189 | 190 | .markdown h3 { 191 | font-size: 16px; 192 | } 193 | 194 | .markdown h4 { 195 | font-size: 14px; 196 | } 197 | 198 | .markdown h5 { 199 | font-size: 12px; 200 | } 201 | 202 | .markdown h6 { 203 | font-size: 12px; 204 | } 205 | 206 | .markdown hr { 207 | height: 1px; 208 | border: 0; 209 | background: #e9e9e9; 210 | margin: 16px 0; 211 | clear: both; 212 | } 213 | 214 | .markdown p { 215 | margin: 1em 0; 216 | } 217 | 218 | .markdown>p, 219 | .markdown>blockquote, 220 | .markdown>.highlight, 221 | .markdown>ol, 222 | .markdown>ul { 223 | width: 80%; 224 | } 225 | 226 | .markdown ul>li { 227 | list-style: circle; 228 | } 229 | 230 | .markdown>ul li, 231 | .markdown blockquote ul>li { 232 | margin-left: 20px; 233 | padding-left: 4px; 234 | } 235 | 236 | .markdown>ul li p, 237 | .markdown>ol li p { 238 | margin: 0.6em 0; 239 | } 240 | 241 | .markdown ol>li { 242 | list-style: decimal; 243 | } 244 | 245 | .markdown>ol li, 246 | .markdown blockquote ol>li { 247 | margin-left: 20px; 248 | padding-left: 4px; 249 | } 250 | 251 | .markdown code { 252 | margin: 0 3px; 253 | padding: 0 5px; 254 | background: #eee; 255 | border-radius: 3px; 256 | } 257 | 258 | .markdown strong, 259 | .markdown b { 260 | font-weight: 600; 261 | } 262 | 263 | .markdown>table { 264 | border-collapse: collapse; 265 | border-spacing: 0px; 266 | empty-cells: show; 267 | border: 1px solid #e9e9e9; 268 | width: 95%; 269 | margin-bottom: 24px; 270 | } 271 | 272 | .markdown>table th { 273 | white-space: nowrap; 274 | color: #333; 275 | font-weight: 600; 276 | } 277 | 278 | .markdown>table th, 279 | .markdown>table td { 280 | border: 1px solid #e9e9e9; 281 | padding: 8px 16px; 282 | text-align: left; 283 | } 284 | 285 | .markdown>table th { 286 | background: #F7F7F7; 287 | } 288 | 289 | .markdown blockquote { 290 | font-size: 90%; 291 | color: #999; 292 | border-left: 4px solid #e9e9e9; 293 | padding-left: 0.8em; 294 | margin: 1em 0; 295 | } 296 | 297 | .markdown blockquote p { 298 | margin: 0; 299 | } 300 | 301 | .markdown .anchor { 302 | opacity: 0; 303 | transition: opacity 0.3s ease; 304 | margin-left: 8px; 305 | } 306 | 307 | .markdown .waiting { 308 | color: #ccc; 309 | } 310 | 311 | .markdown h1:hover .anchor, 312 | .markdown h2:hover .anchor, 313 | .markdown h3:hover .anchor, 314 | .markdown h4:hover .anchor, 315 | .markdown h5:hover .anchor, 316 | .markdown h6:hover .anchor { 317 | opacity: 1; 318 | display: inline-block; 319 | } 320 | 321 | .markdown>br, 322 | .markdown>p>br { 323 | clear: both; 324 | } 325 | 326 | 327 | .hljs { 328 | display: block; 329 | background: white; 330 | padding: 0.5em; 331 | color: #333333; 332 | overflow-x: auto; 333 | } 334 | 335 | .hljs-comment, 336 | .hljs-meta { 337 | color: #969896; 338 | } 339 | 340 | .hljs-string, 341 | .hljs-variable, 342 | .hljs-template-variable, 343 | .hljs-strong, 344 | .hljs-emphasis, 345 | .hljs-quote { 346 | color: #df5000; 347 | } 348 | 349 | .hljs-keyword, 350 | .hljs-selector-tag, 351 | .hljs-type { 352 | color: #a71d5d; 353 | } 354 | 355 | .hljs-literal, 356 | .hljs-symbol, 357 | .hljs-bullet, 358 | .hljs-attribute { 359 | color: #0086b3; 360 | } 361 | 362 | .hljs-section, 363 | .hljs-name { 364 | color: #63a35c; 365 | } 366 | 367 | .hljs-tag { 368 | color: #333333; 369 | } 370 | 371 | .hljs-title, 372 | .hljs-attr, 373 | .hljs-selector-id, 374 | .hljs-selector-class, 375 | .hljs-selector-attr, 376 | .hljs-selector-pseudo { 377 | color: #795da3; 378 | } 379 | 380 | .hljs-addition { 381 | color: #55a532; 382 | background-color: #eaffea; 383 | } 384 | 385 | .hljs-deletion { 386 | color: #bd2c00; 387 | background-color: #ffecec; 388 | } 389 | 390 | .hljs-link { 391 | text-decoration: underline; 392 | } 393 | 394 | /* 代码高亮 */ 395 | /* PrismJS 1.15.0 396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ 397 | /** 398 | * prism.js default theme for JavaScript, CSS and HTML 399 | * Based on dabblet (http://dabblet.com) 400 | * @author Lea Verou 401 | */ 402 | code[class*="language-"], 403 | pre[class*="language-"] { 404 | color: black; 405 | background: none; 406 | text-shadow: 0 1px white; 407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 408 | text-align: left; 409 | white-space: pre; 410 | word-spacing: normal; 411 | word-break: normal; 412 | word-wrap: normal; 413 | line-height: 1.5; 414 | 415 | -moz-tab-size: 4; 416 | -o-tab-size: 4; 417 | tab-size: 4; 418 | 419 | -webkit-hyphens: none; 420 | -moz-hyphens: none; 421 | -ms-hyphens: none; 422 | hyphens: none; 423 | } 424 | 425 | pre[class*="language-"]::-moz-selection, 426 | pre[class*="language-"] ::-moz-selection, 427 | code[class*="language-"]::-moz-selection, 428 | code[class*="language-"] ::-moz-selection { 429 | text-shadow: none; 430 | background: #b3d4fc; 431 | } 432 | 433 | pre[class*="language-"]::selection, 434 | pre[class*="language-"] ::selection, 435 | code[class*="language-"]::selection, 436 | code[class*="language-"] ::selection { 437 | text-shadow: none; 438 | background: #b3d4fc; 439 | } 440 | 441 | @media print { 442 | 443 | code[class*="language-"], 444 | pre[class*="language-"] { 445 | text-shadow: none; 446 | } 447 | } 448 | 449 | /* Code blocks */ 450 | pre[class*="language-"] { 451 | padding: 1em; 452 | margin: .5em 0; 453 | overflow: auto; 454 | } 455 | 456 | :not(pre)>code[class*="language-"], 457 | pre[class*="language-"] { 458 | background: #f5f2f0; 459 | } 460 | 461 | /* Inline code */ 462 | :not(pre)>code[class*="language-"] { 463 | padding: .1em; 464 | border-radius: .3em; 465 | white-space: normal; 466 | } 467 | 468 | .token.comment, 469 | .token.prolog, 470 | .token.doctype, 471 | .token.cdata { 472 | color: slategray; 473 | } 474 | 475 | .token.punctuation { 476 | color: #999; 477 | } 478 | 479 | .namespace { 480 | opacity: .7; 481 | } 482 | 483 | .token.property, 484 | .token.tag, 485 | .token.boolean, 486 | .token.number, 487 | .token.constant, 488 | .token.symbol, 489 | .token.deleted { 490 | color: #905; 491 | } 492 | 493 | .token.selector, 494 | .token.attr-name, 495 | .token.string, 496 | .token.char, 497 | .token.builtin, 498 | .token.inserted { 499 | color: #690; 500 | } 501 | 502 | .token.operator, 503 | .token.entity, 504 | .token.url, 505 | .language-css .token.string, 506 | .style .token.string { 507 | color: #9a6e3a; 508 | background: hsla(0, 0%, 100%, .5); 509 | } 510 | 511 | .token.atrule, 512 | .token.attr-value, 513 | .token.keyword { 514 | color: #07a; 515 | } 516 | 517 | .token.function, 518 | .token.class-name { 519 | color: #DD4A68; 520 | } 521 | 522 | .token.regex, 523 | .token.important, 524 | .token.variable { 525 | color: #e90; 526 | } 527 | 528 | .token.important, 529 | .token.bold { 530 | font-weight: bold; 531 | } 532 | 533 | .token.italic { 534 | font-style: italic; 535 | } 536 | 537 | .token.entity { 538 | cursor: help; 539 | } 540 | -------------------------------------------------------------------------------- /public/iconfont/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "iconfont"; /* Project id 2329939 */ 3 | src: url('iconfont.woff2?t=1627443085066') format('woff2'), 4 | url('iconfont.woff?t=1627443085066') format('woff'), 5 | url('iconfont.ttf?t=1627443085066') format('truetype'); 6 | } 7 | 8 | .iconfont { 9 | font-family: "iconfont" !important; 10 | font-size: 16px; 11 | font-style: normal; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | .icon-bofangqi-danmuzitida:before { 17 | content: "\e6a2"; 18 | } 19 | 20 | .icon-danmukaiqi:before { 21 | content: "\e613"; 22 | } 23 | 24 | .icon-danmuguanbi:before { 25 | content: "\e614"; 26 | } 27 | 28 | .icon-bofangqi-danmuguan:before { 29 | content: "\e696"; 30 | } 31 | 32 | .icon-bofangqi-danmukai:before { 33 | content: "\e697"; 34 | } 35 | 36 | .icon-tv:before { 37 | content: "\e64b"; 38 | } 39 | 40 | .icon-dianshi1:before { 41 | content: "\e68b"; 42 | } 43 | 44 | .icon-dianshi2:before { 45 | content: "\e68c"; 46 | } 47 | 48 | .icon-dianshi3:before { 49 | content: "\e795"; 50 | } 51 | 52 | .icon-dianshi4:before { 53 | content: "\e707"; 54 | } 55 | 56 | .icon-dianshi:before { 57 | content: "\e636"; 58 | } 59 | 60 | .icon-add:before { 61 | content: "\e664"; 62 | } 63 | 64 | .icon-add-circle:before { 65 | content: "\e665"; 66 | } 67 | 68 | .icon-adjust:before { 69 | content: "\e666"; 70 | } 71 | 72 | .icon-arrow-down:before { 73 | content: "\e667"; 74 | } 75 | 76 | .icon-ashbin:before { 77 | content: "\e668"; 78 | } 79 | 80 | .icon-arrow-right:before { 81 | content: "\e669"; 82 | } 83 | 84 | .icon-browse:before { 85 | content: "\e66a"; 86 | } 87 | 88 | .icon-bottom:before { 89 | content: "\e66b"; 90 | } 91 | 92 | .icon-bad:before { 93 | content: "\e66c"; 94 | } 95 | 96 | .icon-arrow-double-left:before { 97 | content: "\e66f"; 98 | } 99 | 100 | .icon-arrow-left-circle:before { 101 | content: "\e670"; 102 | } 103 | 104 | .icon-arrow-double-right:before { 105 | content: "\e671"; 106 | } 107 | 108 | .icon-close:before { 109 | content: "\e672"; 110 | } 111 | 112 | .icon-check-item:before { 113 | content: "\e673"; 114 | } 115 | 116 | .icon-comment:before { 117 | content: "\e674"; 118 | } 119 | 120 | .icon-complete:before { 121 | content: "\e675"; 122 | } 123 | 124 | .icon-direction-right:before { 125 | content: "\e676"; 126 | } 127 | 128 | .icon-direction-up:before { 129 | content: "\e677"; 130 | } 131 | 132 | .icon-direction-left:before { 133 | content: "\e678"; 134 | } 135 | 136 | .icon-download:before { 137 | content: "\e679"; 138 | } 139 | 140 | .icon-elipsis:before { 141 | content: "\e67a"; 142 | } 143 | 144 | .icon-edit:before { 145 | content: "\e67b"; 146 | } 147 | 148 | .icon-eye-close:before { 149 | content: "\e67c"; 150 | } 151 | 152 | .icon-email:before { 153 | content: "\e67d"; 154 | } 155 | 156 | .icon-favorite:before { 157 | content: "\e67e"; 158 | } 159 | 160 | .icon-fabulous:before { 161 | content: "\e67f"; 162 | } 163 | 164 | .icon-good:before { 165 | content: "\e680"; 166 | } 167 | 168 | .icon-home:before { 169 | content: "\e681"; 170 | } 171 | 172 | .icon-link:before { 173 | content: "\e682"; 174 | } 175 | 176 | .icon-fullscreen-expand:before { 177 | content: "\e683"; 178 | } 179 | 180 | .icon-menu:before { 181 | content: "\e684"; 182 | } 183 | 184 | .icon-modular:before { 185 | content: "\e685"; 186 | } 187 | 188 | .icon-refresh:before { 189 | content: "\e686"; 190 | } 191 | 192 | .icon-picture:before { 193 | content: "\e687"; 194 | } 195 | 196 | .icon-search:before { 197 | content: "\e688"; 198 | } 199 | 200 | .icon-sign-out:before { 201 | content: "\e689"; 202 | } 203 | 204 | .icon-setting:before { 205 | content: "\e68a"; 206 | } 207 | 208 | .icon-shoucang1:before { 209 | content: "\e633"; 210 | } 211 | 212 | .icon-fenlei:before { 213 | content: "\e66e"; 214 | } 215 | 216 | .icon-fenlei2:before { 217 | content: "\e609"; 218 | } 219 | 220 | .icon-zhuye:before { 221 | content: "\e635"; 222 | } 223 | 224 | .icon-icon--:before { 225 | content: "\e70c"; 226 | } 227 | 228 | .icon-shoucang:before { 229 | content: "\e626"; 230 | } 231 | 232 | .icon-remen:before { 233 | content: "\e62f"; 234 | } 235 | 236 | .icon-zuosvg:before { 237 | content: "\e601"; 238 | } 239 | 240 | .icon-yousvg:before { 241 | content: "\e602"; 242 | } 243 | 244 | .icon-sousuo:before { 245 | content: "\e615"; 246 | } 247 | 248 | .icon-shangpinfenlei:before { 249 | content: "\e634"; 250 | } 251 | 252 | .icon-liuyan:before { 253 | content: "\e638"; 254 | } 255 | 256 | .icon-fenlei1:before { 257 | content: "\e639"; 258 | } 259 | 260 | .icon-shoucang0:before { 261 | content: "\e66d"; 262 | } 263 | 264 | -------------------------------------------------------------------------------- /public/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/public/iconfont/iconfont.eot -------------------------------------------------------------------------------- /public/iconfont/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2329939", 3 | "name": "mixed-live", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "2154862", 10 | "name": "播放器-弹幕字体(大)_44", 11 | "font_class": "bofangqi-danmuzitida", 12 | "unicode": "e6a2", 13 | "unicode_decimal": 59042 14 | }, 15 | { 16 | "icon_id": "23129875", 17 | "name": "弹幕开启", 18 | "font_class": "danmukaiqi", 19 | "unicode": "e613", 20 | "unicode_decimal": 58899 21 | }, 22 | { 23 | "icon_id": "23129876", 24 | "name": "弹幕关闭", 25 | "font_class": "danmuguanbi", 26 | "unicode": "e614", 27 | "unicode_decimal": 58900 28 | }, 29 | { 30 | "icon_id": "2154820", 31 | "name": "播放器-弹幕(关)_44", 32 | "font_class": "bofangqi-danmuguan", 33 | "unicode": "e696", 34 | "unicode_decimal": 59030 35 | }, 36 | { 37 | "icon_id": "2154821", 38 | "name": "播放器-弹幕(开)_44", 39 | "font_class": "bofangqi-danmukai", 40 | "unicode": "e697", 41 | "unicode_decimal": 59031 42 | }, 43 | { 44 | "icon_id": "1800702", 45 | "name": "电视机", 46 | "font_class": "tv", 47 | "unicode": "e64b", 48 | "unicode_decimal": 58955 49 | }, 50 | { 51 | "icon_id": "2271246", 52 | "name": "电视", 53 | "font_class": "dianshi1", 54 | "unicode": "e68b", 55 | "unicode_decimal": 59019 56 | }, 57 | { 58 | "icon_id": "2271315", 59 | "name": "电视", 60 | "font_class": "dianshi2", 61 | "unicode": "e68c", 62 | "unicode_decimal": 59020 63 | }, 64 | { 65 | "icon_id": "4294105", 66 | "name": "电视", 67 | "font_class": "dianshi3", 68 | "unicode": "e795", 69 | "unicode_decimal": 59285 70 | }, 71 | { 72 | "icon_id": "4933254", 73 | "name": "电视", 74 | "font_class": "dianshi4", 75 | "unicode": "e707", 76 | "unicode_decimal": 59143 77 | }, 78 | { 79 | "icon_id": "5045511", 80 | "name": "电视", 81 | "font_class": "dianshi", 82 | "unicode": "e636", 83 | "unicode_decimal": 58934 84 | }, 85 | { 86 | "icon_id": "15838424", 87 | "name": "add", 88 | "font_class": "add", 89 | "unicode": "e664", 90 | "unicode_decimal": 58980 91 | }, 92 | { 93 | "icon_id": "15838425", 94 | "name": "add-circle", 95 | "font_class": "add-circle", 96 | "unicode": "e665", 97 | "unicode_decimal": 58981 98 | }, 99 | { 100 | "icon_id": "15838426", 101 | "name": "adjust", 102 | "font_class": "adjust", 103 | "unicode": "e666", 104 | "unicode_decimal": 58982 105 | }, 106 | { 107 | "icon_id": "15838429", 108 | "name": "arrow-down", 109 | "font_class": "arrow-down", 110 | "unicode": "e667", 111 | "unicode_decimal": 58983 112 | }, 113 | { 114 | "icon_id": "15838430", 115 | "name": "ashbin", 116 | "font_class": "ashbin", 117 | "unicode": "e668", 118 | "unicode_decimal": 58984 119 | }, 120 | { 121 | "icon_id": "15838431", 122 | "name": "arrow-right", 123 | "font_class": "arrow-right", 124 | "unicode": "e669", 125 | "unicode_decimal": 58985 126 | }, 127 | { 128 | "icon_id": "15838432", 129 | "name": "browse", 130 | "font_class": "browse", 131 | "unicode": "e66a", 132 | "unicode_decimal": 58986 133 | }, 134 | { 135 | "icon_id": "15838433", 136 | "name": "bottom", 137 | "font_class": "bottom", 138 | "unicode": "e66b", 139 | "unicode_decimal": 58987 140 | }, 141 | { 142 | "icon_id": "15838435", 143 | "name": "bad", 144 | "font_class": "bad", 145 | "unicode": "e66c", 146 | "unicode_decimal": 58988 147 | }, 148 | { 149 | "icon_id": "15838436", 150 | "name": "arrow-double-left", 151 | "font_class": "arrow-double-left", 152 | "unicode": "e66f", 153 | "unicode_decimal": 58991 154 | }, 155 | { 156 | "icon_id": "15838437", 157 | "name": "arrow-left-circle", 158 | "font_class": "arrow-left-circle", 159 | "unicode": "e670", 160 | "unicode_decimal": 58992 161 | }, 162 | { 163 | "icon_id": "15838438", 164 | "name": "arrow-double-right", 165 | "font_class": "arrow-double-right", 166 | "unicode": "e671", 167 | "unicode_decimal": 58993 168 | }, 169 | { 170 | "icon_id": "15838444", 171 | "name": "close", 172 | "font_class": "close", 173 | "unicode": "e672", 174 | "unicode_decimal": 58994 175 | }, 176 | { 177 | "icon_id": "15838445", 178 | "name": "check-item", 179 | "font_class": "check-item", 180 | "unicode": "e673", 181 | "unicode_decimal": 58995 182 | }, 183 | { 184 | "icon_id": "15838447", 185 | "name": "comment", 186 | "font_class": "comment", 187 | "unicode": "e674", 188 | "unicode_decimal": 58996 189 | }, 190 | { 191 | "icon_id": "15838450", 192 | "name": "complete", 193 | "font_class": "complete", 194 | "unicode": "e675", 195 | "unicode_decimal": 58997 196 | }, 197 | { 198 | "icon_id": "15838460", 199 | "name": "direction-right", 200 | "font_class": "direction-right", 201 | "unicode": "e676", 202 | "unicode_decimal": 58998 203 | }, 204 | { 205 | "icon_id": "15838461", 206 | "name": "direction-up", 207 | "font_class": "direction-up", 208 | "unicode": "e677", 209 | "unicode_decimal": 58999 210 | }, 211 | { 212 | "icon_id": "15838463", 213 | "name": "direction-left", 214 | "font_class": "direction-left", 215 | "unicode": "e678", 216 | "unicode_decimal": 59000 217 | }, 218 | { 219 | "icon_id": "15838464", 220 | "name": "download", 221 | "font_class": "download", 222 | "unicode": "e679", 223 | "unicode_decimal": 59001 224 | }, 225 | { 226 | "icon_id": "15838467", 227 | "name": "elipsis", 228 | "font_class": "elipsis", 229 | "unicode": "e67a", 230 | "unicode_decimal": 59002 231 | }, 232 | { 233 | "icon_id": "15838470", 234 | "name": "edit", 235 | "font_class": "edit", 236 | "unicode": "e67b", 237 | "unicode_decimal": 59003 238 | }, 239 | { 240 | "icon_id": "15838471", 241 | "name": "eye-close", 242 | "font_class": "eye-close", 243 | "unicode": "e67c", 244 | "unicode_decimal": 59004 245 | }, 246 | { 247 | "icon_id": "15838472", 248 | "name": "email", 249 | "font_class": "email", 250 | "unicode": "e67d", 251 | "unicode_decimal": 59005 252 | }, 253 | { 254 | "icon_id": "15838474", 255 | "name": "favorite", 256 | "font_class": "favorite", 257 | "unicode": "e67e", 258 | "unicode_decimal": 59006 259 | }, 260 | { 261 | "icon_id": "15838479", 262 | "name": "fabulous", 263 | "font_class": "fabulous", 264 | "unicode": "e67f", 265 | "unicode_decimal": 59007 266 | }, 267 | { 268 | "icon_id": "15838483", 269 | "name": "good", 270 | "font_class": "good", 271 | "unicode": "e680", 272 | "unicode_decimal": 59008 273 | }, 274 | { 275 | "icon_id": "15838485", 276 | "name": "home", 277 | "font_class": "home", 278 | "unicode": "e681", 279 | "unicode_decimal": 59009 280 | }, 281 | { 282 | "icon_id": "15838493", 283 | "name": "link", 284 | "font_class": "link", 285 | "unicode": "e682", 286 | "unicode_decimal": 59010 287 | }, 288 | { 289 | "icon_id": "15838498", 290 | "name": "fullscreen-expand", 291 | "font_class": "fullscreen-expand", 292 | "unicode": "e683", 293 | "unicode_decimal": 59011 294 | }, 295 | { 296 | "icon_id": "15838501", 297 | "name": "menu", 298 | "font_class": "menu", 299 | "unicode": "e684", 300 | "unicode_decimal": 59012 301 | }, 302 | { 303 | "icon_id": "15838505", 304 | "name": "modular", 305 | "font_class": "modular", 306 | "unicode": "e685", 307 | "unicode_decimal": 59013 308 | }, 309 | { 310 | "icon_id": "15838519", 311 | "name": "refresh", 312 | "font_class": "refresh", 313 | "unicode": "e686", 314 | "unicode_decimal": 59014 315 | }, 316 | { 317 | "icon_id": "15838521", 318 | "name": "picture", 319 | "font_class": "picture", 320 | "unicode": "e687", 321 | "unicode_decimal": 59015 322 | }, 323 | { 324 | "icon_id": "15838525", 325 | "name": "search", 326 | "font_class": "search", 327 | "unicode": "e688", 328 | "unicode_decimal": 59016 329 | }, 330 | { 331 | "icon_id": "15838529", 332 | "name": "sign-out", 333 | "font_class": "sign-out", 334 | "unicode": "e689", 335 | "unicode_decimal": 59017 336 | }, 337 | { 338 | "icon_id": "15838535", 339 | "name": "setting", 340 | "font_class": "setting", 341 | "unicode": "e68a", 342 | "unicode_decimal": 59018 343 | }, 344 | { 345 | "icon_id": "9810495", 346 | "name": "收藏", 347 | "font_class": "shoucang1", 348 | "unicode": "e633", 349 | "unicode_decimal": 58931 350 | }, 351 | { 352 | "icon_id": "444567", 353 | "name": "分类", 354 | "font_class": "fenlei", 355 | "unicode": "e66e", 356 | "unicode_decimal": 58990 357 | }, 358 | { 359 | "icon_id": "519400", 360 | "name": "分类", 361 | "font_class": "fenlei2", 362 | "unicode": "e609", 363 | "unicode_decimal": 58889 364 | }, 365 | { 366 | "icon_id": "604660", 367 | "name": "主页", 368 | "font_class": "zhuye", 369 | "unicode": "e635", 370 | "unicode_decimal": 58933 371 | }, 372 | { 373 | "icon_id": "3216052", 374 | "name": "分类", 375 | "font_class": "icon--", 376 | "unicode": "e70c", 377 | "unicode_decimal": 59148 378 | }, 379 | { 380 | "icon_id": "887931", 381 | "name": "收藏", 382 | "font_class": "shoucang", 383 | "unicode": "e626", 384 | "unicode_decimal": 58918 385 | }, 386 | { 387 | "icon_id": "1217795", 388 | "name": "热门", 389 | "font_class": "remen", 390 | "unicode": "e62f", 391 | "unicode_decimal": 58927 392 | }, 393 | { 394 | "icon_id": "1201814", 395 | "name": " iocn- left", 396 | "font_class": "zuosvg", 397 | "unicode": "e601", 398 | "unicode_decimal": 58881 399 | }, 400 | { 401 | "icon_id": "1201889", 402 | "name": "iocn-right", 403 | "font_class": "yousvg", 404 | "unicode": "e602", 405 | "unicode_decimal": 58882 406 | }, 407 | { 408 | "icon_id": "1208162", 409 | "name": "搜索", 410 | "font_class": "sousuo", 411 | "unicode": "e615", 412 | "unicode_decimal": 58901 413 | }, 414 | { 415 | "icon_id": "1221713", 416 | "name": "商品分类", 417 | "font_class": "shangpinfenlei", 418 | "unicode": "e634", 419 | "unicode_decimal": 58932 420 | }, 421 | { 422 | "icon_id": "1227534", 423 | "name": "留言", 424 | "font_class": "liuyan", 425 | "unicode": "e638", 426 | "unicode_decimal": 58936 427 | }, 428 | { 429 | "icon_id": "1227535", 430 | "name": "分类1", 431 | "font_class": "fenlei1", 432 | "unicode": "e639", 433 | "unicode_decimal": 58937 434 | }, 435 | { 436 | "icon_id": "1300178", 437 | "name": "收藏0", 438 | "font_class": "shoucang0", 439 | "unicode": "e66d", 440 | "unicode_decimal": 58989 441 | } 442 | ] 443 | } 444 | -------------------------------------------------------------------------------- /public/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/public/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /public/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/public/iconfont/iconfont.woff -------------------------------------------------------------------------------- /public/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/public/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | JustLive 25 | 26 | 27 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 51 | 52 | -------------------------------------------------------------------------------- /src/api/UserApi.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs' 3 | 4 | export const userApi = (username, password) => 5 | request({ 6 | url: '/api/login', 7 | method: 'post', 8 | data: qs.stringify({ 9 | username, 10 | password, 11 | }) 12 | }) 13 | export const registerUser = (username, nickname, password, mail) => 14 | request({ 15 | url: '/api/register', 16 | method: 'POST', 17 | data: qs.stringify({ 18 | username, 19 | nickname, 20 | password, 21 | mail 22 | }) 23 | }) 24 | export const follow = (platform, roomId, uid) => 25 | request({ 26 | url: '/api/live/follow', 27 | method: 'GET', 28 | params: { 29 | platform: platform, 30 | roomId: roomId, 31 | uid: uid, 32 | } 33 | }) 34 | export const unFollow = (platform, roomId, uid) => 35 | request({ 36 | url: '/api/live/unFollow', 37 | method: 'GET', 38 | params: { 39 | platform: platform, 40 | roomId: roomId, 41 | uid: uid, 42 | } 43 | }) 44 | export const changeUserInfo = (userInfo) => 45 | request({ 46 | url: '/api/live/changeUserInfo', 47 | method: 'POST', 48 | data: userInfo 49 | }) 50 | export const changePassword = (userName, oldPassword, newPassword) => 51 | request({ 52 | url: '/api/live/changePassword', 53 | method: 'GET', 54 | params: { 55 | userName: userName, 56 | oldPassword: oldPassword, 57 | newPassword: newPassword, 58 | } 59 | }) 60 | export const changePasswordByMail = (mail, newPassword) => 61 | request({ 62 | url: '/api/live/changePasswordByMail', 63 | method: 'GET', 64 | params: { 65 | mail: mail, 66 | newPassword: newPassword 67 | } 68 | }) 69 | export const sendMail = (mail, code, action) => 70 | request({ 71 | url: '/api/live/sendMail', 72 | method: 'GET', 73 | params: { 74 | mail: mail, 75 | code: code, 76 | action: action 77 | } 78 | }) 79 | export const bindMail = (userName, mail) => 80 | request({ 81 | url: '/api/live/bindMail', 82 | method: 'GET', 83 | params: { 84 | userName: userName, 85 | mail: mail 86 | } 87 | }) 88 | export const getBindMail = (uid) => 89 | request({ 90 | url: '/api/live/getBindMail', 91 | method: 'GET', 92 | params: { 93 | uid: uid 94 | } 95 | }) -------------------------------------------------------------------------------- /src/api/liveList.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export const getRecommend = (page, size) => 4 | request({ 5 | url: '/api/live/getRecommend', 6 | method: 'GET', 7 | params: { 8 | page: page, 9 | size: size, 10 | } 11 | }) 12 | 13 | export const getRealUrl = (platform, roomId) => 14 | request({ 15 | url: '/api/live/getRealUrl', 16 | method: 'GET', 17 | params: { 18 | platform: platform, 19 | roomId: roomId, 20 | } 21 | }) 22 | 23 | export const getHuyaInfo = (roomId) => 24 | request({ 25 | url: '/api/live/getHuyaInfo', 26 | method: 'GET', 27 | params: { 28 | roomId: roomId, 29 | } 30 | }) 31 | 32 | export const getRealUrlMultiSource = (platform, roomId) => 33 | request({ 34 | url: '/api/live/getRealUrlMultiSource', 35 | method: 'GET', 36 | params: { 37 | platform: platform, 38 | roomId: roomId, 39 | } 40 | }) 41 | 42 | export const getRoomInfo = (uid, platform, roomId) => 43 | request({ 44 | url: '/api/live/getRoomInfo', 45 | method: 'GET', 46 | params: { 47 | uid: uid, 48 | platform: platform, 49 | roomId: roomId, 50 | } 51 | }) 52 | 53 | export const getRoomsOn = (uid) => 54 | request({ 55 | url: '/api/live/getRoomsOn', 56 | method: 'GET', 57 | params: { 58 | uid: uid, 59 | } 60 | }) 61 | 62 | export const getRecommendByPlatform = (platform, page, size) => 63 | request({ 64 | url: '/api/live/getRecommendByPlatform', 65 | method: 'GET', 66 | params: { 67 | platform: platform, 68 | page: page, 69 | size: size, 70 | } 71 | }) 72 | 73 | export const getAllSupportPlatforms = () => 74 | request({ 75 | url: '/api/live/getAllSupportPlatforms', 76 | method: 'GET' 77 | }) 78 | 79 | export const getAreas = (platform) => 80 | request({ 81 | url: '/api/live/getAreas', 82 | method: 'GET', 83 | params: { 84 | platform: platform, 85 | } 86 | }) 87 | 88 | export const getRecommendByPlatformArea = (platform, area, page, size) => 89 | request({ 90 | url: '/api/live/getRecommendByPlatformArea', 91 | method: 'GET', 92 | params: { 93 | platform: platform, 94 | area: area, 95 | page: page, 96 | size: size, 97 | } 98 | }) 99 | 100 | export const getAllAreas = () => 101 | request({ 102 | url: '/api/live/getAllAreas', 103 | method: 'GET', 104 | }) 105 | 106 | export const getSearch = (platform, keyWords, uid) => 107 | request({ 108 | url: '/api/live/search', 109 | method: 'GET', 110 | params: { 111 | platform: platform, 112 | keyWords: keyWords, 113 | uid: uid, 114 | } 115 | }) 116 | 117 | export const getRecommendByAreaAll = (areaType, area, page) => 118 | request({ 119 | url: '/api/live/getRecommendByAreaAll', 120 | method: 'GET', 121 | params: { 122 | areaType: areaType, 123 | area: area, 124 | page: page, 125 | } 126 | }) 127 | 128 | export const getTv = () => 129 | request({ 130 | url: '/api/live/getTv', 131 | method: 'GET', 132 | }) 133 | export const getApp = () => 134 | request({ 135 | url: '/api/live/versionUpdate', 136 | method: 'GET', 137 | }) 138 | 139 | -------------------------------------------------------------------------------- /src/assets/LiveLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/src/assets/LiveLogo.png -------------------------------------------------------------------------------- /src/assets/css/style.css: -------------------------------------------------------------------------------- 1 | .abp { 2 | position: relative; 3 | } 4 | 5 | .abp .container { 6 | border: 0; 7 | bottom: 0; 8 | display: block; 9 | left: 0; 10 | margin: 0; 11 | overflow: hidden; 12 | position: absolute; 13 | right: 0; 14 | top: 0; 15 | touch-callout: none; 16 | -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 17 | transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 18 | -webkit-user-select: none; 19 | -moz-user-select: none; 20 | -ms-user-select: none; 21 | user-select: none; 22 | z-index: 9999; 23 | } 24 | 25 | .abp .container .cmt { 26 | color: #fff; 27 | font-family: SimHei, SimSun, Heiti, "MS Mincho", "Meiryo", "Microsoft YaHei", monospace; 28 | font-size: 25px; 29 | letter-spacing: 0; 30 | line-height: 100%; 31 | margin: 0; 32 | padding: 3px 0 0 0; 33 | position: absolute; 34 | text-decoration: none; 35 | text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; 36 | -webkit-text-size-adjust: none; 37 | -ms-text-size-adjust: none; 38 | text-size-adjust: none; 39 | -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 40 | transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 41 | -webkit-transform-origin: 0% 0%; 42 | -ms-transform-origin: 0% 0%; 43 | transform-origin: 0% 0%; 44 | white-space: pre; 45 | word-break: keep-all; 46 | } 47 | 48 | .abp .container .cmt.no-shadow { 49 | text-shadow: none; 50 | } 51 | 52 | .abp .container .cmt.reverse-shadow { 53 | text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white; 54 | } 55 | 56 | .abp .container .cmt.css-optimize { 57 | will-change: transform; 58 | } 59 | 60 | /** Aliases for Chinese named fonts because they don't work on *nix **/ 61 | @font-face{ 62 | font-family: '\9ED1\4F53'; 63 | src:local('SimHei'); 64 | } 65 | 66 | @font-face{ 67 | font-family: '\5B8B\4F53'; 68 | src:local('SimSun'); 69 | } 70 | 71 | @font-face{ 72 | font-family: '\534E\6587\6977\4F53'; 73 | src:local('SimKai'); 74 | } 75 | 76 | @font-face{ 77 | font-family: '\5E7C\5706'; 78 | src:local('YouYuan'); 79 | } 80 | 81 | @font-face{ 82 | font-family: '\5FAE\8F6F\96C5\9ED1'; 83 | src:local('Microsoft YaHei'); 84 | } 85 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyijie1211/JustLive-Web/0cf767657cfb73124629a6858b054751ccd69634/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/Common/BilibiliDanmu.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 103 | 104 | -------------------------------------------------------------------------------- /src/components/Common/RoomList.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 106 | 107 | 251 | -------------------------------------------------------------------------------- /src/components/Global.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 56 | 168 | 169 | 170 | 276 | -------------------------------------------------------------------------------- /src/components/Login/BindMail.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 204 | 205 | 224 | 225 | -------------------------------------------------------------------------------- /src/components/Login/Forget.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 222 | 223 | 242 | 243 | -------------------------------------------------------------------------------- /src/components/Login/Login.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 115 | 116 | 171 | -------------------------------------------------------------------------------- /src/components/Login/Register.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 138 | 139 | 158 | 159 | -------------------------------------------------------------------------------- /src/components/MainPages/AreaAll.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 68 | 69 | 89 | -------------------------------------------------------------------------------- /src/components/MainPages/Areas.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 104 | 105 | 181 | -------------------------------------------------------------------------------- /src/components/MainPages/Follows.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 125 | 126 | 174 | -------------------------------------------------------------------------------- /src/components/MainPages/PlatformRooms.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 155 | 156 | 213 | -------------------------------------------------------------------------------- /src/components/MainPages/Platforms.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 52 | 53 | 106 | -------------------------------------------------------------------------------- /src/components/MainPages/Recommend.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 73 | 74 | 96 | -------------------------------------------------------------------------------- /src/components/MainPages/Search.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 152 | 153 | 301 | -------------------------------------------------------------------------------- /src/components/MainPages/Tv.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 59 | 60 | -------------------------------------------------------------------------------- /src/components/Mobile/ArtPlayerMobile.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 412 | 413 | 420 | 421 | 426 | -------------------------------------------------------------------------------- /src/components/Mobile/FollowsMobile.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 125 | 126 | 169 | -------------------------------------------------------------------------------- /src/components/Mobile/HomeMobile.vue: -------------------------------------------------------------------------------- 1 | 34 | 140 | 141 | 142 | 212 | -------------------------------------------------------------------------------- /src/components/Mobile/RecommendMobile.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 73 | 74 | 96 | -------------------------------------------------------------------------------- /src/components/Mobile/RoomListMobile.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 99 | 100 | 227 | -------------------------------------------------------------------------------- /src/components/Mobile/SearchMobile.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 142 | 143 | 288 | -------------------------------------------------------------------------------- /src/components/Test/ArtPlayerTest.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 488 | 489 | 496 | 497 | 502 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui'; 3 | import 'element-ui/lib/theme-chalk/index.css'; 4 | import App from './App.vue' 5 | import router from './router' 6 | import '../public/iconfont/iconfont.css' 7 | 8 | Vue.config.productionTip = false; 9 | 10 | var axios = require('axios'); 11 | // axios.defaults.baseURL = '/api'; 12 | 13 | Vue.prototype.$axios = axios; 14 | 15 | Vue.use(ElementUI); 16 | 17 | 18 | new Vue({ 19 | el: '#app', 20 | router, 21 | render: h => h(App) 22 | }); 23 | 24 | router.beforeEach((to, from, next) => { 25 | /* 路由发生变化修改页面title */ 26 | document.title = "JustLive" 27 | next() 28 | }) 29 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from "@/components/Home"; 4 | import Room from "@/components/LivePage/Room"; 5 | import Search from "@/components/MainPages/Search"; 6 | import Recommend from "@/components/MainPages/Recommend"; 7 | import Index from "@/components/Index"; 8 | import Follows from "@/components/MainPages/Follows"; 9 | import Platforms from "@/components/MainPages/Platforms"; 10 | import PlatformRooms from "@/components/MainPages/PlatformRooms"; 11 | import Areas from "@/components/MainPages/Areas"; 12 | import AreaAll from "@/components/MainPages/AreaAll"; 13 | import Tv from "@/components/MainPages/Tv"; 14 | import ArtPlayerTest from "@/components/Test/ArtPlayerTest"; 15 | import RoomMobile from "../components/Mobile/RoomMobile"; 16 | import IndexMobile from "../components/Mobile/IndexMobile"; 17 | import HomeMobile from "../components/Mobile/HomeMobile"; 18 | import RecommendMobile from "../components/Mobile/RecommendMobile"; 19 | import FollowsMobile from "../components/Mobile/FollowsMobile"; 20 | import SearchMobile from "@/components/Mobile/SearchMobile.vue"; 21 | 22 | // 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题 23 | const originalPush = Router.prototype.push 24 | Router.prototype.push = function push(location) { 25 | return originalPush.call(this, location).catch(err => err) 26 | } 27 | 28 | Vue.use(Router) 29 | 30 | const router = new Router({ 31 | mode: 'history', 32 | // base: '/live/', 33 | routes:[ 34 | { 35 | path:'/', 36 | redirect:'/index/home/recommend' 37 | }, 38 | { 39 | path:'/mobile', 40 | redirect:'/mobile/index/home/recommend' 41 | }, 42 | { 43 | path: '/index', 44 | name: '播放测试', 45 | component: Index, 46 | redirect: '/index/home/recommend', 47 | children: [ 48 | { 49 | path: '/index/home', 50 | name: '主页', 51 | component: Home, 52 | children: [ 53 | { 54 | path: '/index/home/recommend', 55 | name: '直播推荐', 56 | component: Recommend 57 | }, 58 | { 59 | path: '/index/home/follows', 60 | name: 'follows', 61 | component: Follows 62 | }, 63 | { 64 | path: '/index/home/platforms', 65 | name: 'platforms', 66 | component: Platforms 67 | }, 68 | { 69 | path: '/index/home/areas', 70 | name: 'areas', 71 | component: Areas 72 | }, 73 | { 74 | path: '/index/home/areasAll', 75 | name: 'areaAll', 76 | component: AreaAll 77 | }, 78 | { 79 | path: '/index/home/tv', 80 | name: 'tv', 81 | component: Tv 82 | }, 83 | { 84 | path: '/index/home/:platform', 85 | name: 'platformRoom', 86 | component: PlatformRooms 87 | }, 88 | 89 | ] 90 | }, 91 | { 92 | path: "/index/liveRoom", 93 | name: "liveRoom", 94 | component: Room 95 | }, 96 | { 97 | path: "/index/search", 98 | name: "search", 99 | component: Search 100 | }, 101 | ] 102 | 103 | }, 104 | // 移动端 105 | { 106 | path: '/mobile/index', 107 | name: '移动端', 108 | component: IndexMobile, 109 | redirect: '/mobile/index/home/recommend', 110 | children: [ 111 | { 112 | path: '/mobile/index/home', 113 | name: '主页移动端', 114 | component: HomeMobile, 115 | children: [ 116 | { 117 | path: '/mobile/index/home/recommend', 118 | name: '直播推荐移动端', 119 | component: RecommendMobile 120 | }, 121 | { 122 | path: '/mobile/index/home/follows', 123 | name: 'follows移动端', 124 | component: FollowsMobile 125 | }, 126 | { 127 | path: '/mobile/index/home/platforms', 128 | name: 'platforms移动端', 129 | component: Platforms 130 | }, 131 | { 132 | path: '/mobile/index/home/areas', 133 | name: 'areas移动端', 134 | component: Areas 135 | }, 136 | { 137 | path: '/mobile/index/home/areasAll', 138 | name: 'areaAll移动端', 139 | component: AreaAll 140 | }, 141 | { 142 | path: '/mobile/index/home/tv', 143 | name: 'tv移动端', 144 | component: Tv 145 | }, 146 | { 147 | path: '/mobile/index/home/:platform', 148 | name: 'platformRoom移动端', 149 | component: PlatformRooms 150 | }, 151 | 152 | ] 153 | }, 154 | { 155 | path: "/mobile/index/liveRoom", 156 | name: "liveRoomMobile", 157 | component: RoomMobile 158 | }, 159 | { 160 | path: "/mobile/index/search", 161 | name: "searchMobile", 162 | component: SearchMobile 163 | }, 164 | ] 165 | 166 | }, 167 | { 168 | path: '/test', 169 | name: 'test', 170 | component: ArtPlayerTest 171 | }, 172 | ] 173 | }) 174 | 175 | export default router 176 | -------------------------------------------------------------------------------- /src/utils/exception.js: -------------------------------------------------------------------------------- 1 | export function outputError(source, error) { 2 | console.log(error.response ? error.response : error.message) 3 | source.$message({ 4 | showClose: true, 5 | message: '出错了,请按F12查看浏览器日志。', 6 | type: 'error' 7 | }) 8 | } -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { 3 | Message, 4 | } from 'element-ui' 5 | import router from '../router/index.js' //注意路径与文件名 6 | 7 | const service = axios.create({ 8 | // baseURL: 'https://yj1211.work/', // api 的 base_url 9 | timeout: 50000 // request timeout 10 | }) 11 | 12 | // 请求拦截 设置统一header 13 | service.interceptors.request.use( 14 | config => { 15 | if (localStorage.eleToken) { 16 | config.headers.Authorization = localStorage.eleToken 17 | } 18 | return config 19 | }, 20 | error => { 21 | return Promise.reject(error) 22 | } 23 | ) 24 | 25 | // 响应拦截 401 token过期处理 26 | service.interceptors.response.use( 27 | response => { 28 | 29 | return response 30 | }, 31 | error => { 32 | // 错误提醒 33 | // Message.error(error.response.data) 34 | 35 | const { status } = error.response 36 | if (status === 400) { 37 | Message.error('token值无效,请重新登录') 38 | // 清除token 39 | localStorage.removeItem('eleToken') 40 | 41 | // 页面跳转 42 | router.push('/Login') 43 | } 44 | 45 | return Promise.reject(error) 46 | } 47 | ) 48 | 49 | export default service 50 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require("webpack") 2 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 3 | const productionGzipExtensions = ['js', 'css'] 4 | const Timestamp = new Date().getTime(); 5 | 6 | module.exports = { 7 | configureWebpack: { 8 | plugins: [ 9 | new webpack.ProvidePlugin({ 10 | $:"jquery", 11 | jQuery:"jquery", 12 | "windows.jQuery":"jquery" 13 | }), 14 | // 下面是下载的插件的配置 15 | new CompressionWebpackPlugin({ 16 | algorithm: 'gzip', 17 | test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), 18 | threshold: 10240, 19 | minRatio: 0.8 20 | }), 21 | new webpack.optimize.LimitChunkCountPlugin({ 22 | maxChunks: 5, 23 | minChunkSize: 100 24 | }) 25 | ], 26 | output: { // 输出重构 打包编译后的 文件名称 【模块名称.版本号.时间戳】 27 | filename: `[name].${Timestamp}.js`, 28 | chunkFilename: `[name].${Timestamp}.js` 29 | }, 30 | }, 31 | // publicPath: './', 32 | devServer: { 33 | open: true, //是否自动弹出浏览器页面 34 | host: "localhost", 35 | port: '8080', 36 | https: false, 37 | hotOnly: false , 38 | proxy: { 39 | '/api': { 40 | target: 'http://yj1211.work:8013/', //API服务器的地址(由于此处我nodejs后台用了路由,所以+了api),正常不加 41 | // target: 'http://localhost:8013/', 42 | ws: true, //代理websockets 43 | changeOrigin: true, // 虚拟的站点需要更管origin 44 | pathRewrite: { //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc' 45 | '^/api': '/api' 46 | } 47 | }, 48 | }, 49 | } 50 | } 51 | --------------------------------------------------------------------------------