├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── package.json ├── public ├── favicon.ico ├── index.html └── swiper.min.js ├── src ├── App.vue ├── api │ ├── actor.js │ ├── api.js │ ├── article.js │ ├── award.js │ ├── common.js │ ├── movie.js │ ├── review.js │ ├── role.js │ ├── serial.js │ ├── user.js │ └── video.js ├── assets │ ├── iconfont │ │ ├── iconfont.css │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── images │ │ ├── honour-cup.png │ │ └── logo.png │ └── styles │ │ ├── common.css │ │ ├── cropper.min.css │ │ ├── index.css │ │ ├── reset.css │ │ ├── swiper.min.css │ │ └── variables.scss ├── components │ ├── Actor │ │ ├── ActorItem │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── ActorRow │ │ │ ├── index.js │ │ │ └── index.vue │ ├── App │ │ └── FooterInfo │ │ │ ├── index.js │ │ │ └── index.vue │ ├── Article │ │ └── ArticleItem │ │ │ ├── index.js │ │ │ └── index.vue │ ├── Basic │ │ └── BasicItem.vue │ ├── BottomBar.vue │ ├── Header │ │ ├── HeaderBar │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── HeaderScrollBar │ │ │ ├── index.js │ │ │ └── index.vue │ ├── ImageGroup │ │ ├── index.js │ │ └── index.vue │ ├── ImageUpload │ │ ├── index.js │ │ └── src │ │ │ ├── CropImage.vue │ │ │ └── index.vue │ ├── MPanel │ │ ├── index.js │ │ └── index.vue │ ├── Movie │ │ ├── MovieCard │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── MovieItem │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── MovieRow │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── Skeleton │ │ │ ├── index.js │ │ │ └── index.vue │ ├── NoData │ │ ├── index.js │ │ └── index.vue │ ├── Page │ │ ├── index.js │ │ └── index.vue │ ├── Photo │ │ ├── PhotoGroup │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── PhotoSwiper │ │ │ ├── index.js │ │ │ └── index.vue │ ├── Player │ │ ├── PlayerProgress.vue │ │ └── index.vue │ ├── Report │ │ ├── index.js │ │ └── src │ │ │ └── report.vue │ ├── Review │ │ └── ReviewItem │ │ │ ├── index.js │ │ │ └── index.vue │ ├── Role │ │ ├── RoleItem │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── RoleRow │ │ │ ├── index.js │ │ │ └── index.vue │ ├── Skeleton │ │ ├── index.js │ │ └── index.vue │ ├── TabSwitch │ │ ├── index.js │ │ └── index.vue │ ├── Tool │ │ ├── ToolBar │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── UserCollection │ │ │ ├── index.js │ │ │ └── index.vue │ │ └── UserLike │ │ │ ├── index.js │ │ │ └── index.vue │ └── Video │ │ ├── VideoItem │ │ ├── index.js │ │ └── index.vue │ │ └── VideoRow │ │ ├── index.js │ │ └── index.vue ├── config.js ├── directive │ └── infinite-scroll │ │ ├── index.js │ │ └── infinite-scroll.js ├── filters │ └── index.js ├── http │ └── index.js ├── main.js ├── mixins │ ├── getInfiniteData.js │ └── preventScroll.js ├── router │ ├── actor.js │ ├── article.js │ ├── award.js │ ├── index.js │ ├── main.js │ ├── movie.js │ ├── profile.js │ ├── role.js │ └── video.js ├── store │ ├── index.js │ └── modules │ │ ├── actor.js │ │ ├── movie.js │ │ └── user.js ├── util │ ├── color.js │ └── index.js └── views │ ├── 404.vue │ ├── Layout.vue │ ├── account │ ├── components │ │ └── CaptchaModal.vue │ ├── forget.vue │ ├── login.vue │ └── register.vue │ ├── actor │ ├── award │ │ ├── components │ │ │ └── AwardItem.vue │ │ └── index.vue │ ├── detail │ │ ├── components │ │ │ ├── ActorAward.vue │ │ │ ├── ActorCount.vue │ │ │ └── Skeleton.vue │ │ ├── index.vue │ │ └── information.vue │ ├── role │ │ └── index.vue │ └── works │ │ └── index.vue │ ├── article │ └── detail │ │ ├── components │ │ └── Skeleton.vue │ │ └── index.vue │ ├── award │ ├── detail │ │ ├── components │ │ │ └── AwardInfo.vue │ │ ├── index.vue │ │ └── info.vue │ ├── index │ │ └── index.vue │ └── session │ │ ├── components │ │ └── Skeleton.vue │ │ └── index.vue │ ├── comment │ ├── components │ │ ├── CommentBar.vue │ │ ├── CommentEditor.vue │ │ ├── CommentItem.vue │ │ ├── CommentSkeleton.vue │ │ └── CommentTool.vue │ └── index.vue │ ├── demo.vue │ ├── home │ ├── components │ │ ├── HeaderBar.vue │ │ ├── HomeMenu.vue │ │ ├── HomeSwiper.vue │ │ └── Skeleton.vue │ └── index.vue │ ├── movie │ ├── coming.vue │ ├── detail │ │ ├── article │ │ │ └── index.vue │ │ ├── award │ │ │ ├── components │ │ │ │ └── AwardItem.vue │ │ │ └── index.vue │ │ ├── cast │ │ │ ├── components │ │ │ │ └── CastPanel.vue │ │ │ └── index.vue │ │ ├── company │ │ │ └── index.vue │ │ ├── dialogue │ │ │ └── index.vue │ │ ├── index │ │ │ ├── components │ │ │ │ ├── MovieAward.vue │ │ │ │ ├── MovieBar.vue │ │ │ │ ├── MovieExtra.vue │ │ │ │ ├── MovieInfo.vue │ │ │ │ ├── MovieRating.vue │ │ │ │ ├── PhotoWall.vue │ │ │ │ ├── SerialRow.vue │ │ │ │ └── Skeleton.vue │ │ │ ├── detail.vue │ │ │ ├── favorite.vue │ │ │ └── index.vue │ │ ├── knowledge │ │ │ └── index.vue │ │ ├── level │ │ │ └── index.vue │ │ ├── pubdate │ │ │ └── index.vue │ │ ├── rating │ │ │ ├── components │ │ │ │ ├── RateDetail.vue │ │ │ │ └── RateTrend.vue │ │ │ ├── create.vue │ │ │ └── index.vue │ │ ├── review │ │ │ └── index.vue │ │ ├── role │ │ │ └── index.vue │ │ ├── serial │ │ │ ├── components │ │ │ │ └── SerialItem.vue │ │ │ └── index.vue │ │ └── video │ │ │ └── index.vue │ ├── index │ │ ├── components │ │ │ ├── MenuSkeleton.vue │ │ │ ├── MovieRow.vue │ │ │ ├── MovieSkeleton.vue │ │ │ ├── NavGroup.vue │ │ │ └── NavList.vue │ │ └── index.vue │ ├── serial │ │ └── detail │ │ │ ├── components │ │ │ └── SerialInfo.vue │ │ │ └── index.vue │ ├── theater.vue │ ├── today.vue │ └── top.vue │ ├── offline.vue │ ├── photo │ ├── components │ │ └── PhotoItem.vue │ └── index.vue │ ├── profile │ ├── aboutus │ │ ├── author.vue │ │ └── project.vue │ ├── changelog │ │ └── index.vue │ ├── collection │ │ ├── actor │ │ │ └── index.vue │ │ ├── review │ │ │ └── index.vue │ │ ├── role │ │ │ └── index.vue │ │ └── video │ │ │ └── index.vue │ ├── favorite │ │ ├── create │ │ │ └── index.vue │ │ ├── detail │ │ │ ├── components │ │ │ │ └── FavoriteInfo.vue │ │ │ └── index.vue │ │ ├── edit │ │ │ └── index.vue │ │ └── index │ │ │ └── index.vue │ ├── feedback │ │ └── index.vue │ ├── index │ │ ├── components │ │ │ ├── MineCell.vue │ │ │ ├── MineInfo.vue │ │ │ └── MineMenu.vue │ │ └── index.vue │ ├── information │ │ └── index.vue │ └── setting │ │ └── index.vue │ ├── review │ └── detail │ │ ├── components │ │ ├── Skeleton.vue │ │ └── ToolVote.vue │ │ └── index.vue │ ├── role │ ├── actor │ │ └── index.vue │ ├── detail │ │ ├── components │ │ │ ├── RoleCount.vue │ │ │ └── Skeleton.vue │ │ ├── index.vue │ │ └── information.vue │ └── movie │ │ └── index.vue │ ├── search │ ├── components │ │ ├── SearchBar.vue │ │ ├── SearchHistory.vue │ │ ├── SearchMenu.vue │ │ └── SearchResult.vue │ └── index.vue │ └── video │ ├── detail │ ├── components │ │ ├── MVideo.vue │ │ ├── Skeleton.vue │ │ ├── VideoInfo.vue │ │ ├── VideoItem.vue │ │ └── VideoRow.vue │ └── index.vue │ └── index │ ├── components │ ├── VideoCard.vue │ └── VideoListSkeleton.vue │ └── index.vue └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /html 4 | /dist 5 | html.zip 6 | 7 | # local env files 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | 16 | package-lock.json 17 | 18 | # Editor directories and files 19 | .idea 20 | .vscode 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 慕影网 2 | 3 | ## Vue 实现的影视评分类网站 4 | 5 | 一个基于 `vue` 实现的移动端影视评分网站,涉及 `60+` 个页面,`70+` 个接口,包含注册登录、个人中心、影视信息、影人信息、相册、评分等多个功能。 6 | 本项目会长期更新。 7 | 8 | ## 演示 9 | 演示地址:[https://test-h5.ixook.com](https://test-h5.ixook.com) 10 | 11 | 接口文档:[https://doc.ixook.com](https://doc.ixook.com/doc/movie-mobile-test/api?api=readme) 12 | 13 | 开发文档:[https://h5-doc.ixook.com](https://h5-doc.ixook.com) 14 | 15 | 16 | ## 脑图 17 | ![慕影H5.png](https://note-file.ixook.com/FqtgheEZr7IgaYEHyGwBQ-M1ipBV) 18 | 19 | ## 技术栈 20 | - `vue2.6` 21 | - `vuex` 22 | - `vue-router` 23 | - `vue-cli` 24 | - `sass` 25 | - `axios.js` [基于 promise 的 HTTP 库](https://www.kancloud.cn/yunye/axios/234845) 26 | - `iconfont` [阿里字体图标库](https://www.iconfont.cn/) 27 | - `mind-ui-vue` [个人为本项目制作的`vue`移动端组件库](https://mind-ui-vue.ixook.com/docs) 28 | - `lib-flexible` [移动端自适应方案](https://github.com/amfe/lib-flexible) 29 | - `cropperjs` [图片裁剪](https://github.com/fengyuanchen/cropperjs) 30 | - `echarts` [百度图表插件](https://echarts.apache.org/zh/index.html) 31 | - `swiper` [图片轮播/预览插件](https://www.swiper.com.cn) 32 | - `vue-lazyload` [图片懒加载插件](https://github.com/hilongjw/vue-lazyload) 33 | 34 | 35 | ## 安装 36 | ``` 37 | npm install 38 | ``` 39 | 40 | ## 开发环境启动 41 | ``` 42 | npm run serve 43 | ``` 44 | 45 | ## 打包编译 46 | ``` 47 | npm run build 48 | ``` 49 | 50 | ## 联系作者 51 | 如有问题可以提 `issue` 或者加入qq群: `577133021` 进行反馈 52 | 53 | 作者主页地址:[https://ixook.com](https://ixook.com) 54 | 55 | 56 | ## License 57 | GPL 58 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "muying-h5", 3 | "version": "0.1.2", 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 | "axios": "^0.19.2", 12 | "core-js": "^3.21.1", 13 | "cropperjs": "^1.5.12", 14 | "echarts": "^5.3.1", 15 | "lib-flexible": "^0.3.2", 16 | "mind-ui-vue": "^1.0.3", 17 | "qiniu-js": "^3.4.0", 18 | "spark-md5": "^3.0.2", 19 | "swiper": "^8.1.0", 20 | "vue": "^2.6.14", 21 | "vue-lazyload": "^1.3.3", 22 | "vue-router": "^3.5.3", 23 | "vuex": "^3.6.2" 24 | }, 25 | "devDependencies": { 26 | "@vue/cli-plugin-babel": "~4.3.0", 27 | "@vue/cli-plugin-eslint": "~4.3.0", 28 | "@vue/cli-plugin-router": "~4.3.0", 29 | "@vue/cli-plugin-vuex": "~4.3.0", 30 | "@vue/cli-service": "~4.3.0", 31 | "babel-eslint": "^10.1.0", 32 | "eslint": "^6.7.2", 33 | "eslint-plugin-vue": "^6.2.2", 34 | "px2rem-loader": "^0.1.9", 35 | "sass": "^1.30.0", 36 | "sass-loader": "^10.1.0", 37 | "css-loader": "^5.2.7", 38 | "vue-style-loader": "^4.1.3", 39 | "vue-template-compiler": "^2.6.14" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 慕影网 11 | 12 | 13 | 26 | 27 | 28 | 29 | 33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/api/actor.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 影人相关 4 | export const getActor = (id) => http.get(`/actors/${id}`); // 获取影人信息 5 | export const getActorAwards = (id) => http.get(`/actors/${id}/awards`); // 获取影人奖项 6 | export const getActorPhotos = (id, params) => http.get(`/actors/${id}/photos`, params); // 获取影人相册 7 | export const getActorWorks = (id, params) => http.get(`/actors/${id}/works`, params); // 获取影人参演作品 8 | export const getActorRoles = (id, params) => http.get(`/actors/${id}/roles`, params); // 获取影人饰演角色 9 | -------------------------------------------------------------------------------- /src/api/api.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index'; 2 | 3 | export const getCover = () => http.get('movie/cover'); // 今日封面 4 | export const getIndex = () => http.get('index'); // 首页聚合接口 5 | 6 | export const getCategories = () => http.get("/categories"); // 影视分类 7 | export const getMovieTheater = (params) => http.get('movie/theater', params); // 正在热映 8 | export const getMovieComing = (params) => http.get('movie/coming', params); // 即将上映 9 | export const getMovieTop = (params) => http.get('movie/top', params); // TOP 100 10 | export const getMovieToday = (params) => http.get('movie/today', params); // 历史上的今日上映影片 11 | -------------------------------------------------------------------------------- /src/api/article.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 文章相关 4 | export const getArticle = (id) => http.get(`/articles/${id}`); // 文章详情 5 | -------------------------------------------------------------------------------- /src/api/award.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | export const getAwards = () => http.get(`/awards`); // 奖项列表 4 | export const getAward = (name) => http.get(`/awards/${name}`); // 奖项详情 5 | export const getAwardSession = (name, session) => http.get(`/awards/${name}/${session}`); // 奖项届详情 -------------------------------------------------------------------------------- /src/api/common.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | export const getVersion = () => http.get("/version") // 获取版本号 4 | export const getQiniuUpToken = params => http.get("/qiniu/uptoken", params) // 七牛文件上传token 5 | 6 | export const getCaptcha = () => http.get("/captcha") // 获取图片验证码 7 | export const createPhoneCode = (params) => http.get("/code", params) // 获取手机验证码 8 | export const checkPhoneCode = (params) => http.post("/code", params) // 校验手机验证码 9 | 10 | export const search = (params) => http.get("/search", params); // 搜索 11 | 12 | // 获取评论 13 | export const getComments = (type, id, params) => http.get(`/${type}/${id}/comments`, params); 14 | export const createComment = (type, id, params) => http.post(`/${type}/${id}/comments`, params); 15 | export const deleteComment = (id) => http.delete(`/comments/${id}`); 16 | 17 | 18 | 19 | // 举报 20 | export const getReport = (params) => http.get(`/reports`, params); 21 | export const createReport = (params) => http.post(`/reports`, params); -------------------------------------------------------------------------------- /src/api/movie.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 影视相关接口 4 | export const getMovies = (params) => http.get(`/movies`, params); // 影视列表 5 | export const getMovie = (id) => http.get(`/movies/${id}`); // 影视详情 6 | export const getMovieCast = (id) => http.get(`/movies/${id}/cast`); // 影视演员 7 | export const getMovieRoles = (id, params) => http.get(`/movies/${id}/roles`, params); // 影视角色 8 | export const getMoviePhotos = (id, params) => http.get(`/movies/${id}/photos`, params); // 影视相册 9 | export const getMovieVideos = (id, params) => http.get(`/movies/${id}/videos`, params); // 影视视频 10 | export const getMovieComments = (id, params) => http.get(`/movies/${id}/comments`, params); // 影视评分 11 | export const getMovieReviews = (id, params) => http.get(`/movies/${id}/reviews`, params); // 影视长评 12 | export const getMovieLevels = (id, params) => http.get(`/movies/${id}/levels`, params); // 引导等级 13 | export const getMoviePubdates = (id, params) => http.get(`/movies/${id}/pubdates`, params); // 上映日期 14 | export const getMovieAwards = (id) => http.get(`/movies/${id}/awards`); // 获得奖项 15 | export const getMovieKnowledges = (id, params) => http.get(`/movies/${id}/knowledges`, params); // 幕后知识 16 | export const getMovieDialogues = (id, params) => http.get(`/movies/${id}/dialogues`, params); // 经典台词 17 | export const getMovieCompanies = (id) => http.get(`/movies/${id}/companies`); // 关联公司 18 | export const getMovieArticles = (id, params) => http.get(`/movies/${id}/articles`, params); // 文章资讯 19 | export const getMovieSerials = (id, params) => http.get(`/movies/${id}/serials`, params); // 所属系列 20 | export const getMovieRatings = (id) => http.get(`/movies/${id}/ratings`); // 评分详情 -------------------------------------------------------------------------------- /src/api/review.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 影评相关接口 4 | export const getReview = (id) => http.get(`/reviews/${id}`); // 影评详情 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/api/role.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 角色相关接口 4 | export const getRole = (id) => http.get(`/roles/${id}`); // 角色详情 5 | export const getRolePhotos = (id, params) => http.get(`/roles/${id}/photos`, params); // 角色相册 6 | export const getRoleMovies = (id, params) => http.get(`/roles/${id}/movies`, params); // 角色影视 7 | export const getRoleActors = (id, params) => http.get(`/roles/${id}/actors`, params); // 角色影人 -------------------------------------------------------------------------------- /src/api/serial.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 系列相关接口 4 | export const getSerials = (params) => http.get(`/serials`, params); // 系列列表 5 | export const getSerialMovies = (id, params) => http.get(`/serials/${id}/movies`, params); // 系列影视 6 | -------------------------------------------------------------------------------- /src/api/user.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | // 账号 4 | export const register = (params) => http.post(`/register`, params); // 注册 5 | export const getUserToken = (params) => http.post(`/login`, params); // 登录获取token 6 | export const getUserInfo = (params) => http.get(`/user`, params); // 登录用户信息 7 | export const updateUserInfo = (params) => http.put(`/user`, params); // 更新用户信息 8 | export const checkAccount = (params) => http.post(`/account`, params); // 校验手机号是否存在 9 | export const updateUserPassword = (params) => http.put(`/user/password`, params); // 更新用户密码 10 | 11 | 12 | 13 | // 影视收藏 14 | export const getUserFavorites = (params) => http.get(`/user/favorites`, params); // 收藏夹列表 15 | export const getUserFavorite = (id, params) => http.get(`/user/favorites/${id}`, params); // 收藏夹详情 16 | export const createUserFavorite = (params) => http.post(`/user/favorites`, params); // 新建收藏夹 17 | export const updateUserFavorite = (id, params) => http.put(`/user/favorites/${id}`, params); // 更新收藏夹 18 | export const deleteUserFavorite = (id) => http.delete(`/user/favorites/${id}`); // 删除收藏夹 19 | export const deleteUserFavoriteMovies = (id, union_id) => http.delete(`/user/favorites/${id}/movies/${union_id}`); // 删除收藏夹下影视 20 | 21 | export const getUserFavoriteMovies = (id, params) => http.get(`/user/favorites/${id}/movies`, params); // 收藏夹下影视 22 | export const updateUserMovieFavorite = (id, params) => http.put(`/user/movies/${id}/favorites`, params); // 更新影视所属收藏夹 23 | 24 | 25 | // 用户评分 26 | export const createUserMovieRating = (id, params) => http.post(`/user/movies/${id}/rating`, params) // 用户评分 27 | export const userMovieWish = (id, params) => http.post(`/user/movies/${id}/wish`, params) // 用户想看 28 | 29 | // 用户反馈 30 | export const createFeedback = (params) => http.post(`/feedback`, params) 31 | 32 | 33 | /** 34 | * @desc 用户收藏 35 | * */ 36 | 37 | // 收藏统计 38 | export const getUserCollectionCount = () => http.get(`/user/collections/count`); 39 | 40 | 41 | /** 42 | * @desc 收藏 43 | * type 被收藏资源 可选值为 actors reviews roles videos 44 | * @return array 45 | */ 46 | export const getUserCollection = (type) => http.get(`/user/collections/${type}`); 47 | export const createCollection = (type, id) => http.post(`/user/${type}/${id}/collections`); 48 | export const deleteCollection = (type, id) => http.delete(`/user/${type}/${id}/collections`); 49 | 50 | // 投票,赞同与反对 51 | export const createReviewVote = (id, params) => http.post(`/reviews/${id}/voters`, params); 52 | 53 | // 评论喜欢 54 | export const createCommentLike = (id) => http.post(`/comments/${id}/like`); 55 | export const deleteCommentLike = (id) => http.delete(`/comments/${id}/like`); 56 | 57 | 58 | /** 59 | * @desc 点赞 60 | * type 被点赞的资源 可选值为 videos photos 61 | * @return array 62 | */ 63 | // 喜欢 64 | export const createLike = (type, id) => http.post(`/${type}/${id}/like`); 65 | export const deleteLike = (type, id) => http.delete(`/${type}/${id}/like`); 66 | -------------------------------------------------------------------------------- /src/api/video.js: -------------------------------------------------------------------------------- 1 | import http from '@/http/index' 2 | 3 | export const getVideos = (params) => http.get('/videos', params); // 获取视频列表 4 | export const getVideo = (id) => http.get(`/videos/${id}`); // 获取视频详情 5 | -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/src/assets/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/src/assets/iconfont/iconfont.woff -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/src/assets/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/images/honour-cup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/src/assets/images/honour-cup.png -------------------------------------------------------------------------------- /src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NameLi/muying-h5/48c42bc32638fe871265e42c85c2a026133d5ece/src/assets/images/logo.png -------------------------------------------------------------------------------- /src/assets/styles/common.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif; 3 | -webkit-font-smoothing: antialiased; 4 | -moz-osx-font-smoothing: grayscale; 5 | color: #303133; 6 | font-size: 14px; 7 | } 8 | 9 | body { 10 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 11 | } 12 | 13 | .border, .border_top, .border_right, .border_bottom, .border_left { 14 | position: relative; 15 | } 16 | 17 | .border::before { 18 | display: block; 19 | content: ""; 20 | position: absolute; 21 | left: 0; 22 | top: 0; 23 | border: 1px solid #dedede; 24 | transform-origin: 0 0; 25 | box-sizing: border-box; 26 | border-radius: 6px; 27 | } 28 | 29 | .border_top::before, .border_right::before, .border_bottom::before, .border_left::before { 30 | display: block; 31 | content: ""; 32 | position: absolute; 33 | background: #dedede; 34 | } 35 | 36 | .border_top::before { 37 | left: 0; 38 | top: 0; 39 | width: 100%; 40 | height: 1px; 41 | } 42 | 43 | .border_left::before { 44 | left: 0; 45 | top: 0; 46 | bottom: 0; 47 | width: 1px; 48 | height: 100%; 49 | } 50 | 51 | 52 | .border_right::before { 53 | right: 0; 54 | top: 0; 55 | bottom: 0; 56 | width: 1px; 57 | height: 100%; 58 | } 59 | 60 | .border_bottom::before { 61 | left: 0; 62 | bottom: 0; 63 | width: 100%; 64 | height: 1px; 65 | } 66 | 67 | @media screen and (-webkit-min-device-pixel-ratio: 2) { 68 | .border::before { 69 | width: 200%; 70 | height: 200%; 71 | transform: scale(0.5); 72 | } 73 | 74 | .border_top::before, .border_bottom::before { 75 | transform: scaleY(0.5); 76 | } 77 | 78 | .border_left::before, .border_right::before { 79 | transform: scaleX(0.5); 80 | } 81 | } 82 | 83 | @media screen and (-webkit-min-device-pixel-ratio: 3) { 84 | .border::before { 85 | width: 300%; 86 | height: 300%; 87 | transform: scale(0.33333); 88 | } 89 | 90 | .border_top::before, .border_bottom::before { 91 | transform: scaleY(0.33333); 92 | } 93 | 94 | .border_left::before, .border_right::before { 95 | transform: scaleX(0.33333); 96 | } 97 | } 98 | 99 | @media (max-width: 800px) { 100 | ::-webkit-scrollbar { 101 | display: none; 102 | } 103 | } 104 | 105 | .ellipsis { 106 | overflow: hidden; 107 | text-overflow: ellipsis; 108 | white-space: nowrap; 109 | } 110 | 111 | .hidden { 112 | display: none; 113 | } 114 | 115 | .overflow-hidden { 116 | overflow: hidden; 117 | } -------------------------------------------------------------------------------- /src/assets/styles/index.css: -------------------------------------------------------------------------------- 1 | @import url(./reset.css); 2 | @import url(./common.css); 3 | @import url(./cropper.min.css); 4 | @import url(./swiper.min.css); 5 | @import url(../iconfont/iconfont.css); -------------------------------------------------------------------------------- /src/assets/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* 2 | css 初始化 3 | 2017.4.20 4 | */ 5 | body, ul, ol, li, h1, h2, h3, h4, h5, h6, p, form, th, dd, dl, fieldset, legend, input, textarea, select {margin: 0;padding: 0;} 6 | 7 | ul, ol { list-style:none; } 8 | 9 | a {text-decoration:none;} 10 | h1, h2, h3, h4, h5, h6 {font-weight: normal;} 11 | address, em {font-style:normal} 12 | li {list-style:none} 13 | img {border:0; vertical-align:middle} 14 | table {border-collapse:collapse; border-spacing:0} 15 | p {word-wrap:break-word} 16 | input{outline:none} -------------------------------------------------------------------------------- /src/assets/styles/variables.scss: -------------------------------------------------------------------------------- 1 | $color-theme: #e54847; -------------------------------------------------------------------------------- /src/components/Actor/ActorItem/index.js: -------------------------------------------------------------------------------- 1 | import ActorItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(ActorItem.name, ActorItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Actor/ActorItem/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 48 | 49 | 99 | -------------------------------------------------------------------------------- /src/components/Actor/ActorRow/index.js: -------------------------------------------------------------------------------- 1 | import ActorRow from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(ActorRow.name, ActorRow); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Actor/ActorRow/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 38 | 39 | 74 | -------------------------------------------------------------------------------- /src/components/App/FooterInfo/index.js: -------------------------------------------------------------------------------- 1 | import FooterInfo from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(FooterInfo.name, FooterInfo); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/App/FooterInfo/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | -------------------------------------------------------------------------------- /src/components/Article/ArticleItem/index.js: -------------------------------------------------------------------------------- 1 | import VideoItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(VideoItem.name, VideoItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Basic/BasicItem.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | 27 | 53 | -------------------------------------------------------------------------------- /src/components/Header/HeaderBar/index.js: -------------------------------------------------------------------------------- 1 | import HeaderBar from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(HeaderBar.name, HeaderBar); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Header/HeaderScrollBar/index.js: -------------------------------------------------------------------------------- 1 | import Component from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(Component.name, Component); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/ImageGroup/index.js: -------------------------------------------------------------------------------- 1 | import ImageGroup from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(ImageGroup.name, ImageGroup); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/ImageGroup/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 43 | 44 | -------------------------------------------------------------------------------- /src/components/ImageUpload/index.js: -------------------------------------------------------------------------------- 1 | import ImageUploadComponent from './src/index.vue'; 2 | 3 | const ImageUpload = { 4 | install: function (Vue) { 5 | Vue.component('ImageUpload', ImageUploadComponent) 6 | } 7 | } 8 | 9 | export default ImageUpload; -------------------------------------------------------------------------------- /src/components/MPanel/index.js: -------------------------------------------------------------------------------- 1 | import MPanel from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(MPanel.name, MPanel); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/MPanel/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 57 | 58 | -------------------------------------------------------------------------------- /src/components/Movie/MovieCard/index.js: -------------------------------------------------------------------------------- 1 | import MovieCard from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(MovieCard.name, MovieCard); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Movie/MovieCard/index.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 44 | 45 | -------------------------------------------------------------------------------- /src/components/Movie/MovieItem/index.js: -------------------------------------------------------------------------------- 1 | import MovieItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(MovieItem.name, MovieItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Movie/MovieRow/index.js: -------------------------------------------------------------------------------- 1 | import MovieRow from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(MovieRow.name, MovieRow); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Movie/Skeleton/index.js: -------------------------------------------------------------------------------- 1 | import Component from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(Component.name, Component); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Movie/Skeleton/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 32 | 33 | 82 | -------------------------------------------------------------------------------- /src/components/NoData/index.js: -------------------------------------------------------------------------------- 1 | import NoData from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(NoData.name, NoData); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/NoData/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 41 | 42 | 54 | -------------------------------------------------------------------------------- /src/components/Page/index.js: -------------------------------------------------------------------------------- 1 | import Page from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(Page.name, Page); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Photo/PhotoGroup/index.js: -------------------------------------------------------------------------------- 1 | import PhotoGroup from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(PhotoGroup.name, PhotoGroup); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Photo/PhotoGroup/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/Photo/PhotoSwiper/index.js: -------------------------------------------------------------------------------- 1 | import PhotoSwiper from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(PhotoSwiper.name, PhotoSwiper); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Report/index.js: -------------------------------------------------------------------------------- 1 | import Report from './src/report.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(Report.name, Report); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Review/ReviewItem/index.js: -------------------------------------------------------------------------------- 1 | import ReviewItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(ReviewItem.name, ReviewItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Review/ReviewItem/index.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 45 | 46 | 96 | -------------------------------------------------------------------------------- /src/components/Role/RoleItem/index.js: -------------------------------------------------------------------------------- 1 | import RoleItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(RoleItem.name, RoleItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Role/RoleItem/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 49 | 50 | 106 | -------------------------------------------------------------------------------- /src/components/Role/RoleRow/index.js: -------------------------------------------------------------------------------- 1 | import RoleRow from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(RoleRow.name, RoleRow); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Role/RoleRow/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 28 | 29 | 64 | -------------------------------------------------------------------------------- /src/components/Skeleton/index.js: -------------------------------------------------------------------------------- 1 | import Skeleton from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(Skeleton.name, Skeleton); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Skeleton/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/TabSwitch/index.js: -------------------------------------------------------------------------------- 1 | import TabSwitch from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(TabSwitch.name, TabSwitch); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/TabSwitch/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 54 | 55 | 103 | -------------------------------------------------------------------------------- /src/components/Tool/ToolBar/index.js: -------------------------------------------------------------------------------- 1 | import ToolBar from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(ToolBar.name, ToolBar); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Tool/UserCollection/index.js: -------------------------------------------------------------------------------- 1 | import UserCollection from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(UserCollection.name, UserCollection); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Tool/UserCollection/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /src/components/Tool/UserLike/index.js: -------------------------------------------------------------------------------- 1 | import UserLike from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(UserLike.name, UserLike); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Tool/UserLike/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/Video/VideoItem/index.js: -------------------------------------------------------------------------------- 1 | import VideoItem from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(VideoItem.name, VideoItem); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Video/VideoRow/index.js: -------------------------------------------------------------------------------- 1 | import VideoRow from './index.vue'; 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.component(VideoRow.name, VideoRow); 6 | } 7 | }; -------------------------------------------------------------------------------- /src/components/Video/VideoRow/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | export const HOST = '//test-h5-api.ixook.com'; 2 | export const FILE_DOMAIN = "https://img.ixook.com" 3 | 4 | export const APP_NAME = '慕影网'; 5 | export const DEVELOPER = '冰糖雪梨'; 6 | export const VERSION = '0.1 alpha'; -------------------------------------------------------------------------------- /src/directive/infinite-scroll/index.js: -------------------------------------------------------------------------------- 1 | import infiniteScroll from './infinite-scroll' 2 | 3 | export default { 4 | install(Vue) { 5 | Vue.directive('infinite-scroll', infiniteScroll) 6 | } 7 | } -------------------------------------------------------------------------------- /src/filters/index.js: -------------------------------------------------------------------------------- 1 | import { dateBefore, timeFormat } from '@/util/index' 2 | 3 | 4 | export { dateBefore, timeFormat }; -------------------------------------------------------------------------------- /src/http/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import store from '@/store' 3 | import router from '@/router' 4 | import { HOST } from '@/config' 5 | import { Toast } from 'mind-ui-vue' 6 | 7 | // axios 配置 8 | axios.defaults.timeout = 20000 9 | axios.defaults.baseURL = HOST 10 | axios.defaults.headers['Content-Type'] = 'application/json;charset=UTF-8' 11 | 12 | 13 | // 请求时的拦截 14 | axios.interceptors.request.use(config => { 15 | if (store.state.user.token) { 16 | config.headers['Authorization'] = 'Bearer ' + store.state.user.token 17 | } 18 | return config 19 | }, function (error) { 20 | return Promise.reject(error) 21 | }) 22 | 23 | // 返回值 24 | axios.interceptors.response.use(res => { 25 | if (res.status === 200) { 26 | 27 | if (res.data.code >= 400) { 28 | Toast({ 29 | position: 'top', 30 | message: res.data.message 31 | }) 32 | } 33 | 34 | return res.data 35 | } 36 | 37 | return { 38 | code: res.status_code, 39 | message: res.message, 40 | data: {} 41 | } 42 | 43 | }, error => { 44 | 45 | if (String(error).includes('timeout')) { 46 | Toast('网络请求超时') 47 | } else if (String(error).includes('Network Error')) { 48 | // Toast('网络异常') 49 | 50 | router.push({ 51 | path: '/offline' 52 | }) 53 | 54 | } else if (error.response) { 55 | const { status, statusText } = error.response 56 | 57 | // 未登录 58 | if (status === 401) { 59 | 60 | // 清空 61 | store.commit("user/SET_USER", null); 62 | store.commit("user/SET_TOKEN", ""); 63 | localStorage.removeItem("user"); 64 | localStorage.removeItem("token"); 65 | 66 | if (!['Login', 'Profile', 'Register', 'NotFound', 'Forget'].includes(router.currentRoute.name)) { 67 | router.push({ 68 | path: '/login', 69 | query: { redirect: router.currentRoute.fullPath } 70 | }) 71 | } 72 | 73 | return error.response.data 74 | } 75 | 76 | Toast(status + '' + statusText) 77 | } 78 | 79 | return { 80 | 'code': 400, 81 | 'messsage': 'error' 82 | } 83 | }) 84 | 85 | 86 | export default { 87 | get(url, params) { 88 | return axios({ 89 | method: 'get', 90 | url, 91 | params 92 | }) 93 | }, 94 | 95 | post(url, data) { 96 | return axios({ 97 | method: 'post', 98 | url, 99 | data 100 | }) 101 | }, 102 | 103 | patch(url, data) { 104 | return axios({ 105 | method: 'patch', 106 | url, 107 | data 108 | }) 109 | }, 110 | 111 | put(url, data) { 112 | return axios({ 113 | method: 'put', 114 | url, 115 | data 116 | }) 117 | }, 118 | 119 | delete(url, data) { 120 | return axios({ 121 | method: 'delete', 122 | url, 123 | data 124 | }) 125 | } 126 | } -------------------------------------------------------------------------------- /src/mixins/getInfiniteData.js: -------------------------------------------------------------------------------- 1 | export const getInfiniteData = { 2 | data() { 3 | return { 4 | loading: false, 5 | noData: false, 6 | noMoreData: false, 7 | isError: false, 8 | list: [], 9 | total: 0, 10 | page: 1, 11 | per_page: 20, 12 | form: {}, 13 | }; 14 | }, 15 | 16 | computed: { 17 | isShowSkeleton() { 18 | return this.loading && this.page === 1; 19 | }, 20 | }, 21 | 22 | mounted() { 23 | this.loadMore(); 24 | }, 25 | 26 | methods: { 27 | async getData(fn, ...args) { 28 | 29 | if (this.isError) return; 30 | 31 | if (this.noMoreData && this.page === 1 && this.list.length === 0) { 32 | this.noMoreData = false; 33 | } 34 | 35 | if (this.loading || this.noMoreData) return; 36 | 37 | this.loading = true; 38 | 39 | let params = { 40 | page: this.page, 41 | per_page: this.per_page, 42 | ...this.form 43 | }; 44 | 45 | const { code, data, total } = await fn(...args, params); 46 | 47 | if (code === 200) { 48 | // 是否无数据 49 | if (this.page === 1 && data.length === 0) { 50 | this.noData = true; 51 | } else { 52 | this.noData = false; 53 | } 54 | 55 | this.isError = false; 56 | 57 | this.page++; 58 | 59 | this.list.push(...data); 60 | this.total = total || 0 61 | 62 | if (data.length < this.per_page) { 63 | this.noMoreData = true; 64 | } 65 | } else { 66 | this.isError = true; 67 | } 68 | 69 | this.$nextTick(() => { 70 | this.loading = false; 71 | }); 72 | }, 73 | }, 74 | } -------------------------------------------------------------------------------- /src/mixins/preventScroll.js: -------------------------------------------------------------------------------- 1 | export const preventScroll = { 2 | mounted() { 3 | this.$preventScroll(true); 4 | }, 5 | 6 | beforeDestroy() { 7 | this.$preventScroll(false); 8 | }, 9 | } -------------------------------------------------------------------------------- /src/router/actor.js: -------------------------------------------------------------------------------- 1 | 2 | // 影人路由表 3 | export default [ 4 | { 5 | path: '/actors/:id', 6 | props: true, 7 | name: "Actor", 8 | component: () => import('@/views/actor/detail'), 9 | children: [ 10 | { 11 | path: '/actors/:id/information', 12 | props: true, 13 | name: "ActorDetail", 14 | component: () => import('@/views/actor/detail/information') 15 | }, 16 | { 17 | path: '/actors/:id/awards', 18 | props: true, 19 | name: "ActorAwards", 20 | component: () => import('@/views/actor/award/index') 21 | }, 22 | { 23 | path: '/actors/:id/works', 24 | props: true, 25 | name: "ActorWorks", 26 | component: () => import('@/views/actor/works/index') 27 | }, 28 | { 29 | path: '/actors/:id/roles', 30 | props: true, 31 | name: "ActorRoles", 32 | component: () => import('@/views/actor/role/index') 33 | }, 34 | ] 35 | }, 36 | ] -------------------------------------------------------------------------------- /src/router/article.js: -------------------------------------------------------------------------------- 1 | 2 | // 文章路由 3 | export default [ 4 | // { 5 | // path: '/articles', 6 | // name: "Articles", 7 | // component: () => import('@/views/article/index') 8 | // }, 9 | { 10 | path: '/articles/:id', 11 | props: true, 12 | name: "Article", 13 | component: () => import('@/views/article/detail/index'), 14 | children: [ 15 | { 16 | path: '/articles/:id/comments', 17 | props: true, 18 | name: "ArticleComments", 19 | component: () => import('@/views/comment/index') 20 | }, 21 | ] 22 | }, 23 | ] -------------------------------------------------------------------------------- /src/router/award.js: -------------------------------------------------------------------------------- 1 | 2 | // 奖项路由 3 | export default [ 4 | { 5 | path: '/awards', 6 | name: "Awards", 7 | component: () => import('@/views/award/index/index') 8 | }, 9 | { 10 | path: '/awards/:name', 11 | props: true, 12 | name: "Award", 13 | component: () => import('@/views/award/detail/index'), 14 | children: [ 15 | { 16 | path: '/awards/:name/detail', 17 | name: "AwardDetail", 18 | props: true, 19 | component: () => import('@/views/award/detail/info') 20 | }, 21 | ] 22 | }, 23 | { 24 | path: '/awards/:name/:session', 25 | props: true, 26 | name: "AwardSession", 27 | component: () => import('@/views/award/session/index') 28 | }, 29 | ] -------------------------------------------------------------------------------- /src/router/main.js: -------------------------------------------------------------------------------- 1 | 2 | // 基础路由 3 | export default [ 4 | { 5 | path: '/', 6 | component: () => import('@/views/Layout'), 7 | children: [ 8 | { 9 | path: '/home', 10 | name: "Home", 11 | meta: { scrollY: 0 }, 12 | component: () => import('@/views/home/index') 13 | }, 14 | { 15 | path: '/movies', 16 | name: "Movies", 17 | meta: { scrollY: 0 }, 18 | component: () => import('@/views/movie/index/index') 19 | }, 20 | { 21 | path: '/videos', 22 | name: "Videos", 23 | meta: { scrollY: 0 }, 24 | component: () => import('@/views/video/index/index') 25 | }, 26 | { 27 | path: '/profile', 28 | name: "Profile", 29 | meta: { scrollY: 0 }, 30 | component: () => import('@/views/profile/index/index'), 31 | children: [ 32 | { 33 | path: '/profile/information', 34 | name: "ProfileInformation", 35 | component: () => import('@/views/profile/information/index') 36 | }, 37 | { 38 | path: '/profile/feedback', 39 | name: "Feedback", 40 | component: () => import('@/views/profile/feedback') 41 | }, 42 | { 43 | path: '/profile/changelog', 44 | name: "ChangeLog", 45 | component: () => import('@/views/profile/changelog') 46 | }, 47 | { 48 | path: '/profile/author', 49 | name: "AboutAuthor", 50 | component: () => import('@/views/profile/aboutus/author') 51 | }, 52 | { 53 | path: '/profile/project', 54 | name: "AboutProject", 55 | component: () => import('@/views/profile/aboutus/project') 56 | }, 57 | { 58 | path: '/profile/setting', 59 | name: "Setting", 60 | component: () => import('@/views/profile/setting/index') 61 | }, 62 | ] 63 | }, 64 | ] 65 | }, 66 | ] -------------------------------------------------------------------------------- /src/router/profile.js: -------------------------------------------------------------------------------- 1 | 2 | // 个人中心 3 | export default [ 4 | { 5 | path: '/profile/favorites', 6 | name: "ProfileFavorites", 7 | component: () => import('@/views/profile/favorite/index'), 8 | children: [ 9 | { 10 | path: '/profile/favorites/create', 11 | props: true, 12 | name: "ProfileFavoriteCreate", 13 | component: () => import('@/views/profile/favorite/create/index') 14 | }, 15 | ] 16 | }, 17 | // { 18 | // path: '/profile/favorites/create', 19 | // props: true, 20 | // name: "ProfileFavoriteCreate", 21 | // component: () => import('@/views/profile/favorite/create/index') 22 | // }, 23 | { 24 | path: '/profile/favorites/:id', 25 | props: true, 26 | name: "ProfileFavorite", 27 | component: () => import('@/views/profile/favorite/detail'), 28 | children: [ 29 | { 30 | path: '/profile/favorites/:id/edit', 31 | props: true, 32 | name: "profileFavoriteEdit", 33 | component: () => import('@/views/profile/favorite/edit/index') 34 | }, 35 | ] 36 | }, 37 | 38 | { 39 | path: '/profile/actors', 40 | name: "ProfileActors", 41 | component: () => import('@/views/profile/collection/actor') 42 | }, 43 | { 44 | path: '/profile/roles', 45 | name: "ProfileRoles", 46 | component: () => import('@/views/profile/collection/role') 47 | }, 48 | { 49 | path: '/profile/reviews', 50 | name: "ProfileReviews", 51 | component: () => import('@/views/profile/collection/review') 52 | }, 53 | { 54 | path: '/profile/videos', 55 | name: "ProfileVideos", 56 | component: () => import('@/views/profile/collection/video') 57 | }, 58 | ] -------------------------------------------------------------------------------- /src/router/role.js: -------------------------------------------------------------------------------- 1 | 2 | // 角色路由表 3 | export default [ 4 | { 5 | path: '/roles/:id', 6 | props: true, 7 | name: "Role", 8 | component: () => import('@/views/role/detail'), 9 | children: [ 10 | { 11 | path: '/roles/:id/information', 12 | props: true, 13 | name: "RoleDetail", 14 | component: () => import('@/views/role/detail/information') 15 | }, 16 | { 17 | path: '/roles/:id/movies', 18 | props: true, 19 | name: 'RoleMovies', 20 | component: () => import('@/views/role/movie/index') 21 | }, 22 | { 23 | path: '/roles/:id/actors', 24 | props: true, 25 | name: 'RoleActors', 26 | component: () => import('@/views/role/actor/index') 27 | }, 28 | ] 29 | }, 30 | ] -------------------------------------------------------------------------------- /src/router/video.js: -------------------------------------------------------------------------------- 1 | 2 | // 视频路由 3 | export default [ 4 | { 5 | path: '/videos/:id', 6 | props: true, 7 | name: "Video", 8 | component: () => import('@/views/video/detail/index'), 9 | children: [ 10 | { 11 | path: '/videos/:id/comments', 12 | props: true, 13 | name: "VideoComments", 14 | component: () => import('@/views/comment'), 15 | } 16 | ] 17 | }, 18 | ] -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import user from './modules/user' 5 | import movie from './modules/movie' 6 | import actor from './modules/actor' 7 | Vue.use(Vuex) 8 | 9 | export default new Vuex.Store({ 10 | modules: { 11 | user, 12 | movie, 13 | actor 14 | } 15 | }) -------------------------------------------------------------------------------- /src/store/modules/actor.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | actor: localStorage.getItem('actor') ? JSON.parse(localStorage.getItem('actor')) : {}, 3 | } 4 | 5 | const getters = { 6 | getActor: state => state.actor, 7 | } 8 | 9 | const mutations = { 10 | SET_ACTOR: (state, actor) => { 11 | state.actor = actor 12 | localStorage.setItem('actor', JSON.stringify(actor)) 13 | }, 14 | } 15 | 16 | export default { 17 | namespaced: false, 18 | state, 19 | mutations, 20 | getters 21 | } 22 | -------------------------------------------------------------------------------- /src/store/modules/movie.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | movie: localStorage.getItem('movie') ? JSON.parse(localStorage.getItem('movie')) : {}, 3 | } 4 | 5 | const getters = { 6 | getMovie: state => state.movie, 7 | } 8 | 9 | const mutations = { 10 | SET_MOVIE: (state, movie) => { 11 | state.movie = movie 12 | localStorage.setItem('movie', JSON.stringify(movie)) 13 | }, 14 | } 15 | 16 | export default { 17 | namespaced: false, 18 | state, 19 | mutations, 20 | getters 21 | } 22 | -------------------------------------------------------------------------------- /src/store/modules/user.js: -------------------------------------------------------------------------------- 1 | import { register, getUserToken, getUserInfo } from '@/api/user' 2 | 3 | const state = { 4 | token: localStorage.getItem('token') || '', 5 | user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : null, 6 | } 7 | 8 | const getters = { 9 | getUser: state => state.user, 10 | getToken: state => state.token 11 | } 12 | 13 | const mutations = { 14 | // 身份token 15 | SET_TOKEN: (state, token) => { 16 | state.token = token 17 | localStorage.setItem('token', token) 18 | }, 19 | // 用户信息 20 | SET_USER: (state, user) => { 21 | state.user = user 22 | localStorage.setItem('user', JSON.stringify(user)) 23 | }, 24 | } 25 | 26 | const actions = { 27 | // user register 28 | async register({ commit }, form) { 29 | const { account, password, code } = form 30 | 31 | const res = await register({ account, password, code }) 32 | 33 | if (res.code === 200) { 34 | commit('SET_TOKEN', res.data.token) 35 | } 36 | return res 37 | }, 38 | 39 | // user login 40 | async login({ commit }, form) { 41 | const { account, password } = form 42 | 43 | const res = await getUserToken({ account, password }) 44 | 45 | if (res.code === 200) { 46 | commit('SET_TOKEN', res.data.token) 47 | } 48 | return res 49 | }, 50 | 51 | // get user info 52 | async getInfo({ commit }) { 53 | 54 | const res = await getUserInfo(); 55 | 56 | if (res.code === 200) { 57 | commit('SET_USER', res.data) 58 | } 59 | 60 | return res 61 | } 62 | } 63 | 64 | export default { 65 | namespaced: true, 66 | state, 67 | mutations, 68 | actions, 69 | getters 70 | } 71 | -------------------------------------------------------------------------------- /src/util/color.js: -------------------------------------------------------------------------------- 1 | export const colorToRgba = function (color, alpha) { 2 | // 16进制颜色值的正则 3 | let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; 4 | 5 | // 把颜色值变成小写 6 | color = color.toLowerCase(); 7 | 8 | if (reg.test(color)) { 9 | // 如果只有三位的值,需变成六位,如:#fff => #ffffff 10 | 11 | if (color.length === 4) { 12 | let colorNew = "#"; 13 | for (let i = 1; i < 4; i += 1) { 14 | colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1)); 15 | } 16 | color = colorNew; 17 | } 18 | 19 | // 处理六位的颜色值,转为RGB 20 | let colorChange = []; 21 | for (let i = 1; i < 7; i += 2) { 22 | colorChange.push(parseInt("0x" + color.slice(i, i + 2))); 23 | } 24 | return `RGB(${colorChange.join(",")}, ${alpha})`; 25 | } else { 26 | return color; 27 | } 28 | }; -------------------------------------------------------------------------------- /src/util/index.js: -------------------------------------------------------------------------------- 1 | export const debounce = (func, wait = 200) => { 2 | let timeout; 3 | return function (event) { 4 | clearTimeout(timeout); 5 | timeout = setTimeout(() => { 6 | func.call(this, event); 7 | }, wait); 8 | }; 9 | } 10 | 11 | 12 | export const throttle = (cb, wait = 1000 / 60) => { 13 | let last = 0; 14 | return function () { 15 | var now = new Date().getTime();; 16 | if (now - last > wait) { 17 | cb.call(this); 18 | last = new Date().getTime();; 19 | } 20 | } 21 | } 22 | 23 | // 格式化时间 将秒数转为 00:00 格式 24 | export const timeFormat = sec => { 25 | let min = 0; 26 | min = Math.floor(sec / 60); // 分 27 | min < 10 && (min = '0' + min); // 补零 28 | sec = Math.floor(sec % 60); // 秒 29 | sec < 10 && (sec = '0' + sec); // 补零 30 | 31 | return (min || '00') + ":" + sec; 32 | } 33 | 34 | 35 | export const dateBefore = (datatime) => { 36 | let dateTimeStamp = new Date(datatime).getTime() 37 | 38 | let minute = 1000 * 60; 39 | let hour = minute * 60; 40 | let day = hour * 24; 41 | 42 | let month = day * 30; 43 | let year = month * 12; 44 | let now = new Date().getTime(); 45 | let diffValue = now - dateTimeStamp; 46 | let result = "" 47 | 48 | if (diffValue < 0) { 49 | return; 50 | } 51 | 52 | let monthC = diffValue / month; 53 | let weekC = diffValue / (7 * day); 54 | let dayC = diffValue / day; 55 | let hourC = diffValue / hour; 56 | let minC = diffValue / minute; 57 | let yearC = diffValue / year; 58 | 59 | if (yearC >= 1) { 60 | return "" + parseInt(yearC) + "年前"; 61 | } 62 | if (monthC >= 1) { 63 | result = "" + parseInt(monthC) + "月前"; 64 | } else if (weekC >= 1) { 65 | result = "" + parseInt(weekC) + "周前"; 66 | } else if (dayC >= 1) { 67 | result = "" + parseInt(dayC) + "天前"; 68 | } else if (hourC >= 1) { 69 | result = "" + parseInt(hourC) + "小时前"; 70 | } else if (minC >= 1) { 71 | result = "" + parseInt(minC) + "分钟前"; 72 | } else { 73 | result = "刚刚"; 74 | } 75 | 76 | return result; 77 | } 78 | 79 | export const preventScroll = function (prevent = true) { 80 | if (prevent) { 81 | document.body.classList.add("overflow-hidden"); 82 | } else { 83 | document.body.classList.remove("overflow-hidden"); 84 | } 85 | } -------------------------------------------------------------------------------- /src/views/404.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /src/views/Layout.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/views/actor/award/components/AwardItem.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 50 | 51 | -------------------------------------------------------------------------------- /src/views/actor/award/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /src/views/actor/detail/components/ActorAward.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | 32 | -------------------------------------------------------------------------------- /src/views/actor/detail/components/ActorCount.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 30 | 31 | -------------------------------------------------------------------------------- /src/views/actor/detail/components/Skeleton.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 38 | 39 | -------------------------------------------------------------------------------- /src/views/actor/detail/information.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 43 | 44 | 50 | -------------------------------------------------------------------------------- /src/views/actor/role/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 54 | 55 | 73 | -------------------------------------------------------------------------------- /src/views/actor/works/index.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 88 | 89 | 129 | -------------------------------------------------------------------------------- /src/views/article/detail/components/Skeleton.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /src/views/award/detail/components/AwardInfo.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/award/detail/index.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 69 | 70 | -------------------------------------------------------------------------------- /src/views/award/detail/info.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 52 | 53 | 54 | 62 | -------------------------------------------------------------------------------- /src/views/award/index/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 57 | 58 | -------------------------------------------------------------------------------- /src/views/award/session/components/Skeleton.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | -------------------------------------------------------------------------------- /src/views/comment/components/CommentBar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 60 | 61 | -------------------------------------------------------------------------------- /src/views/comment/components/CommentSkeleton.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | -------------------------------------------------------------------------------- /src/views/comment/components/CommentTool.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 108 | 109 | -------------------------------------------------------------------------------- /src/views/demo.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | 24 | -------------------------------------------------------------------------------- /src/views/home/components/HomeMenu.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /src/views/home/components/Skeleton.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/movie/coming.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 69 | 70 | -------------------------------------------------------------------------------- /src/views/movie/detail/article/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 35 | 36 | -------------------------------------------------------------------------------- /src/views/movie/detail/award/components/AwardItem.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 39 | 40 | -------------------------------------------------------------------------------- /src/views/movie/detail/award/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /src/views/movie/detail/cast/components/CastPanel.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 39 | 40 | -------------------------------------------------------------------------------- /src/views/movie/detail/cast/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /src/views/movie/detail/company/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 55 | 56 | -------------------------------------------------------------------------------- /src/views/movie/detail/dialogue/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 38 | 39 | -------------------------------------------------------------------------------- /src/views/movie/detail/index/components/MovieAward.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 53 | 54 | -------------------------------------------------------------------------------- /src/views/movie/detail/index/components/MovieExtra.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 65 | 66 | -------------------------------------------------------------------------------- /src/views/movie/detail/index/components/PhotoWall.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /src/views/movie/detail/index/components/SerialRow.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 33 | 34 | 63 | -------------------------------------------------------------------------------- /src/views/movie/detail/knowledge/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 38 | 39 | -------------------------------------------------------------------------------- /src/views/movie/detail/level/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 33 | 34 | -------------------------------------------------------------------------------- /src/views/movie/detail/pubdate/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 32 | 33 | -------------------------------------------------------------------------------- /src/views/movie/detail/rating/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 73 | 74 | -------------------------------------------------------------------------------- /src/views/movie/detail/review/index.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 70 | 71 | -------------------------------------------------------------------------------- /src/views/movie/detail/role/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /src/views/movie/detail/serial/components/SerialItem.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 35 | 36 | -------------------------------------------------------------------------------- /src/views/movie/detail/serial/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /src/views/movie/detail/video/index.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 86 | 87 | -------------------------------------------------------------------------------- /src/views/movie/index/components/MenuSkeleton.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /src/views/movie/index/components/MovieRow.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 32 | 33 | 85 | -------------------------------------------------------------------------------- /src/views/movie/index/components/MovieSkeleton.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /src/views/movie/index/components/NavList.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/movie/index/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /src/views/movie/serial/detail/components/SerialInfo.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | 27 | -------------------------------------------------------------------------------- /src/views/movie/serial/detail/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 53 | 54 | 60 | -------------------------------------------------------------------------------- /src/views/movie/theater.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | 32 | -------------------------------------------------------------------------------- /src/views/movie/today.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 63 | 64 | -------------------------------------------------------------------------------- /src/views/movie/top.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 37 | 38 | -------------------------------------------------------------------------------- /src/views/offline.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 46 | 47 | -------------------------------------------------------------------------------- /src/views/photo/components/PhotoItem.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 16 | 17 | -------------------------------------------------------------------------------- /src/views/profile/aboutus/author.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | -------------------------------------------------------------------------------- /src/views/profile/aboutus/project.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /src/views/profile/changelog/index.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 59 | 60 | -------------------------------------------------------------------------------- /src/views/profile/collection/actor/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /src/views/profile/collection/review/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 37 | 38 | -------------------------------------------------------------------------------- /src/views/profile/collection/role/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /src/views/profile/collection/video/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 33 | 34 | -------------------------------------------------------------------------------- /src/views/profile/feedback/index.vue: -------------------------------------------------------------------------------- 1 |