├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── images
├── article.gif
├── book.gif
├── home.gif
├── me.gif
├── pin-detail.gif
├── pin.gif
├── search.gif
├── test.jpg
├── topics.gif
├── user.gif
├── 微信图片_20200306204705.jpg
├── 微信图片_20200309110857.jpg
├── 微信图片_20200327193455.jpg
├── 微信图片_20200327230420.jpg
├── 微信图片_20200328120726.jpg
├── 微信图片_20200328120821.jpg
├── 微信图片_20200328152341.jpg
├── 微信图片_20200328211854.jpg
├── 微信图片_20200329194915.jpg
├── 微信图片_20200330234326.jpg
├── 微信图片_20200331130952.jpg
├── 微信图片_20200331174417.jpg
├── 微信图片_20200331190849.jpg
├── 微信图片_20200331222139.jpg
├── 微信图片_20200401163936.jpg
├── 微信图片_20200401221547.jpg
├── 微信图片_20200402114039.jpg
└── 微信图片_20200408215158.jpg
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── api
│ ├── auth.js
│ ├── book.js
│ ├── collection.js
│ ├── common.js
│ ├── entry.js
│ ├── home.js
│ ├── pins.js
│ ├── post.js
│ ├── search.js
│ ├── topic.js
│ └── user.js
├── assets
│ └── css
│ │ ├── article.styl
│ │ ├── common.styl
│ │ ├── normalize.styl
│ │ └── variable.styl
├── common
│ ├── cache.js
│ ├── config.js
│ ├── const.js
│ └── store.js
├── components
│ ├── book-entry
│ │ └── index.vue
│ ├── book-section-entry
│ │ └── index.vue
│ ├── collection-item
│ │ └── index.vue
│ ├── comment
│ │ └── index.vue
│ ├── fold-text
│ │ └── index.vue
│ ├── l-article-entry
│ │ └── index.vue
│ ├── l-pin-entry
│ │ └── index.vue
│ ├── link-view
│ │ └── index.vue
│ ├── loading
│ │ ├── image
│ │ │ └── loading.gif
│ │ └── index.vue
│ ├── m-article-entry
│ │ └── index.vue
│ ├── m-author
│ │ └── index.vue
│ ├── m-header
│ │ └── index.vue
│ ├── message
│ │ ├── index.js
│ │ └── src
│ │ │ └── index.vue
│ ├── native-scroll
│ │ └── index.vue
│ ├── nav-tab
│ │ └── index.vue
│ ├── need-login
│ │ └── index.vue
│ ├── pin-info
│ │ └── index.vue
│ ├── refresh
│ │ ├── image
│ │ │ └── refresh.gif
│ │ └── index.vue
│ ├── router-transition
│ │ └── index.vue
│ ├── s-article-entry
│ │ └── index.vue
│ ├── s-author
│ │ └── index.vue
│ ├── s-header
│ │ └── index.vue
│ ├── s-pin-entry
│ │ └── index.vue
│ ├── scroll
│ │ └── index.vue
│ ├── search-box
│ │ └── index.vue
│ ├── switch
│ │ └── index.vue
│ ├── tab
│ │ └── index.vue
│ ├── tag-item
│ │ └── index.vue
│ ├── tag
│ │ └── index.vue
│ ├── three-op
│ │ └── index.vue
│ └── topic-item
│ │ └── index.vue
├── fliter
│ └── index.js
├── layout
│ ├── footer
│ │ └── index.vue
│ └── index.vue
├── main.js
├── mixins
│ └── index.js
├── plugin
│ └── router-transition
│ │ ├── constant.js
│ │ ├── index.js
│ │ ├── index.vue
│ │ └── util.js
├── router
│ ├── home.js
│ ├── index.js
│ ├── pins.js
│ ├── topic.js
│ └── user.js
├── store
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── mutation-types.js
│ ├── mutations.js
│ └── state.js
├── util
│ ├── index.js
│ └── request.js
└── views
│ ├── about
│ └── index.vue
│ ├── book
│ └── index.vue
│ ├── books
│ ├── index.vue
│ └── pages
│ │ └── book-entry-list
│ │ └── index.vue
│ ├── collection-set
│ └── index.vue
│ ├── collection
│ └── index.vue
│ ├── feedback
│ └── index.vue
│ ├── home
│ ├── index.vue
│ └── pages
│ │ ├── home-article-list
│ │ └── index.vue
│ │ └── home-following
│ │ └── index.vue
│ ├── login
│ └── index.vue
│ ├── me
│ └── index.vue
│ ├── my-like
│ └── index.vue
│ ├── my-purchased-book
│ └── index.vue
│ ├── pin
│ └── index.vue
│ ├── pins
│ ├── index.vue
│ └── pages
│ │ ├── pin-following
│ │ └── index.vue
│ │ └── pins-entry-list
│ │ └── index.vue
│ ├── post
│ └── index.vue
│ ├── recommendation-author
│ ├── index.vue
│ └── pages
│ │ └── recommend-author-list
│ │ └── index.vue
│ ├── search
│ ├── index.vue
│ └── pages
│ │ └── search-result
│ │ └── index.vue
│ ├── section-detail
│ ├── components
│ │ └── section-content
│ │ │ └── index.vue
│ └── index.vue
│ ├── set-psd
│ └── index.vue
│ ├── setting
│ └── index.vue
│ ├── sousou
│ └── index.vue
│ ├── special-show-edit
│ └── index.vue
│ ├── tag-manage
│ └── index.vue
│ ├── topic-attender
│ └── index.vue
│ ├── topic
│ ├── index.vue
│ └── pages
│ │ └── topic-pin-list
│ │ └── index.vue
│ ├── topics
│ └── index.vue
│ ├── user-like
│ └── index.vue
│ ├── user-read-history
│ └── index.vue
│ ├── user-tag
│ └── index.vue
│ └── user
│ ├── index.vue
│ └── pages
│ ├── user-activity
│ └── index.vue
│ ├── user-more
│ └── index.vue
│ ├── user-pin
│ └── index.vue
│ ├── user-post
│ └── index.vue
│ └── user-share
│ └── index.vue
├── vue.config.js
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue仿照掘金客户端App开发Web版掘金App
2 |
3 | ## 运行
4 |
5 | ```
6 | git clone https://github.com/sanfengliao/vue-juejin.git
7 |
8 | cd vue-juejin
9 |
10 | npm install
11 |
12 | # serve with hot reload at localhost:8080
13 | npm run serve
14 |
15 | # build juejin application for production
16 | npm run build
17 | ```
18 | ## 正文
19 | ### 介绍
20 | 该项目是~~抄袭~~仿照掘金客户端使用Vue开发的WebApp。里面所有的API均来自官方Android。页面基本上和掘金App差不多,不过由于里面的一些图片本菜使用的是阿里的iconfont,因此会和掘金App上面的图片有点不一样,但是整体的功能和掘金App还是差不多的。
21 |
22 | 该项目源码已经开源在~~gayhub~~github, [点击可查看源码](https://github.com/sanfengliao/vue-juejin),希望各位掘友大大给个star
23 |
24 | ### 效果图
25 | (前面一大波长gif来袭)
26 |
27 | (如果图片显示不出,请访问[原文链接](https://juejin.im/post/5e98441df265da47ef2f3720))
28 |
29 | * 首页
30 |
31 | 
32 |
33 | * 沸点
34 |
35 | 
36 |
37 | * 搜索
38 |
39 | 
40 |
41 | * 小册
42 |
43 | 
44 |
45 | * 我的
46 |
47 | 
48 |
49 | * 用户主页
50 |
51 | 
52 |
53 | * 话题主页
54 |
55 | 
56 |
57 | * 文章详情
58 |
59 | 
60 |
61 | * 沸点详情
62 |
63 | 
64 | ### 完成度
65 | 本来以为仿照App实现的话应该很快就可以全部昨晚,可做起来才发现APP 里面的东西实在是不少(有一些是本菜实在做不了,比如支付),包括页面和交互,要完全照抄实现确实需要一些时间和精力,UI 之类的都是简单测量+肉眼调试实现的,下面列出页面和交互的完成度,这里应该只是列出了绝大部分。未列出、未实现的后续会根据时间、精力来实现。
66 | 实际完成度请以代码为主
67 | - [x] 启动页 不做
68 | - [x] 登录、未登录跳转和页面数据刷新(逻辑还不够眼睛)
69 | - [x] 上拉加载、下拉锁芯
70 | - [x] HOME 完成
71 | - [x] TAB切换
72 | - [x] TAB编辑
73 | - [x] 关注的作者发布的文章
74 | - [x] 点赞
75 | - [x] 沸点
76 | - [x] TAB切换
77 | - [x] TAB编辑
78 | - [x] 关注的作者发布的动态
79 | - [x] 点赞
80 | - [x] 沸点详情
81 | - [x] 搜索 完成
82 | - [x] 按照综合、文章、用户、标签搜索
83 | - [ ] 小册
84 | - [x] 小册列表
85 | - [x] 小册详情
86 | - [x] 小册章节详情
87 | - [ ] 购买小册 (臣妾做不到啊)
88 | - [ ] 我的
89 | - [x] 个人主页
90 | - [ ] 编辑
91 | - [x] 活动
92 | - [x] 原创文章
93 | - [x] 沸点
94 | - [x] 收藏集
95 | - [x] 收藏集详情页
96 | - [x] 喜欢的文章
97 | - [x] 关注的标签
98 | - [ ] 标签详情页
99 | - [ ] 消息中心
100 | - [x] 赞过的文章和沸点
101 | - [x] 收藏集
102 | - [x] 创建的
103 | - [x] 已关注的
104 | - [x] 已购小册 (不知道有没有问题)
105 | - [x] 阅读过的文章
106 | - [x] 标签管理
107 | - [x] 已关注标签
108 | - [x] 所有标签
109 | - [x] 推荐标签
110 | - [x] 所有标签
111 | - [x] 关注标签
112 | - [ ] 夜间模式
113 | - [ ] 设置 完成一些
114 | - [x] 修改密码
115 | - [ ] 登录页
116 | - [x] 作者榜
117 | - [x] 用户主页
118 | - [x] 关注
119 | - [x] 活动
120 | - [x] 原创文章
121 | - [x] 沸点
122 | - [x] 收藏集
123 | - [x] 收藏集详情页
124 | - [x] 关注收藏集
125 | - [x] 收藏集文章列表
126 | - [x] 喜欢的文章
127 | - [x] 关注的标签
128 | - [ ] 标签详情页
129 | - [ ] 话题榜
130 | - [x] 更多话题
131 | - [ ] 已关注话题
132 | - [x] 话题详情
133 | - [x] 关注话
134 | - [ ] 文章详情页
135 | - [x] 文章内容
136 | - [x] 显示评论
137 | - [x] 文章作者其他系列文章
138 | - [x] 关注作者
139 | - [ ] 收藏文章、分享文章
140 | - [ ] 评论
141 | - [ ] 其他
142 | - [ ] 沸点详情页
143 | - [x] 文章内容
144 | - [x] 显示评论
145 | - [x] 推荐沸点
146 | - [x] 关注作者
147 | - [ ] 分享沸点
148 | - [ ] 评论
149 | - [ ] 其他
150 | - [ ] ...
151 | 应该还有一些完成的没有列举出来,大家clone下来跑一遍试试吧 [点击此下载源码](https://github.com/sanfengliao/vue-juejin.git)
152 | #### 交互完成度
153 | 评论、留言、关注、添加到收藏集、发表沸点等暂时均没有实现,因为 APP 里面的东西实在是不少......
154 |
155 | - [ ] 评论
156 | - [ ] 留言
157 | - [ ] 未完待续部分...
158 | ### 后续
159 | 1. 话说掘金的 API 域名(二级)真是多啊,使用webpack-dev-server的proxy配置代理都让node报`possible EventEmiter memory leak deteceted`的警告了。
160 | 2. 富文本部分是直接拷贝掘金web官网的富文本样式
161 | 3. 有些页面的显示还不够丝滑,后续需要改进
162 | 4. 认真的看效果图的话,可以看出某些页面还是有一些bug的,
163 | 5. 关于页面切换动画似乎还不够连贯,不知道是代码的问题(绝对是代码的问题),还是浏览器的问题
164 | 6. 登录的token好像有一些问题,在两个app登录同一个账号不会报token异常,但是在该项目中在两个浏览器中登录会出问题。
165 | 7. html节点的font-size设置太小了,因此有些忘记设计font-size的元素可能会显示不出文字。
166 | 8. 后续会不停的完善该项目,把一些能够开发的功能都开发出来,希望各位朋友们多多支持。
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [["@vue/cli-plugin-babel/preset", {useBuiltIns: "entry"}]]
3 | };
4 |
--------------------------------------------------------------------------------
/images/article.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/article.gif
--------------------------------------------------------------------------------
/images/book.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/book.gif
--------------------------------------------------------------------------------
/images/home.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/home.gif
--------------------------------------------------------------------------------
/images/me.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/me.gif
--------------------------------------------------------------------------------
/images/pin-detail.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/pin-detail.gif
--------------------------------------------------------------------------------
/images/pin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/pin.gif
--------------------------------------------------------------------------------
/images/search.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/search.gif
--------------------------------------------------------------------------------
/images/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/test.jpg
--------------------------------------------------------------------------------
/images/topics.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/topics.gif
--------------------------------------------------------------------------------
/images/user.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/user.gif
--------------------------------------------------------------------------------
/images/微信图片_20200306204705.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200306204705.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200309110857.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200309110857.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200327193455.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200327193455.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200327230420.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200327230420.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200328120726.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200328120726.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200328120821.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200328120821.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200328152341.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200328152341.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200328211854.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200328211854.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200329194915.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200329194915.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200330234326.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200330234326.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200331130952.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200331130952.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200331174417.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200331174417.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200331190849.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200331190849.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200331222139.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200331222139.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200401163936.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200401163936.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200401221547.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200401221547.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200402114039.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200402114039.jpg
--------------------------------------------------------------------------------
/images/微信图片_20200408215158.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/images/微信图片_20200408215158.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-juejin",
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 | "axios": "^0.19.2",
12 | "better-scroll": "^1.15.2",
13 | "core-js": "^3.6.4",
14 | "qs": "^6.9.3",
15 | "swiper": "^5.3.6",
16 | "vue": "^2.6.11",
17 | "vue-awesome-swiper": "^4.1.0",
18 | "vue-router": "^3.1.5",
19 | "vuex": "^3.1.2"
20 | },
21 | "devDependencies": {
22 | "@vue/cli-plugin-babel": "~4.2.0",
23 | "@vue/cli-plugin-eslint": "~4.2.0",
24 | "@vue/cli-plugin-router": "~4.2.0",
25 | "@vue/cli-plugin-vuex": "~4.2.0",
26 | "@vue/cli-service": "~4.2.0",
27 | "@vue/eslint-config-prettier": "^6.0.0",
28 | "babel-eslint": "^10.0.3",
29 | "eslint": "^6.7.2",
30 | "eslint-plugin-prettier": "^3.1.1",
31 | "eslint-plugin-vue": "^6.1.2",
32 | "prettier": "^1.19.1",
33 | "stylus": "^0.54.7",
34 | "stylus-loader": "^3.0.2",
35 | "vue-template-compiler": "^2.6.11"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | <%= htmlWebpackPlugin.options.title %>
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
43 |
44 |
--------------------------------------------------------------------------------
/src/api/auth.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import store from '../store'
3 | import { client_id, device_id } from '../common/config'
4 |
5 | /**
6 | * 登录功能
7 | * @param {string} username
8 | * @param {string} password
9 | * @param {string} loginType
10 | */
11 | export const login = (username, password, loginType) => {
12 | console.log('login')
13 | let data = `user=${username}&psd=${password}&src=android&login_type=${loginType}&client_id=${client_id}&device_id=${device_id}&state=state&token=${store.state.token}`
14 | return request.post('/auth-center/v1/login',data, {
15 | headers: {
16 | 'Content-Type': 'application/x-www-form-urlencoded'
17 | }
18 | }).then(res => res.data)
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/api/book.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { commonParams } from './common'
3 | import store from '../store'
4 | const state = store.state
5 | /**
6 | * 获取小册
7 | * @param {number} pageNum
8 | */
9 | export const getBooks = (pageNum=1) => {
10 | // TODO 添加token
11 | return request({
12 | method: 'GET',
13 | url: '/xiaoce-timeline/v1/getListByLastTime',
14 | params: {
15 | pageNum,
16 | token: state.token,
17 | uid: state.uid,
18 | ...commonParams,
19 | }
20 | }).then(res => res.data)
21 | }
22 | /**
23 | *
24 | * @param {number} pageNum
25 | */
26 | export const getMyBooks = (pageNum=1) => {
27 | // TODO 添加token
28 | return request({
29 | method: 'GET',
30 | url: '/xiaoce-cache/v1/userBuyList',
31 | params: {
32 | pageNum,
33 | token: state.token,
34 | uid: state.uid,
35 | ...commonParams
36 | }
37 | }).then(res => res.data)
38 | }
39 |
40 |
41 | export const getBookDetail = (id) => {
42 | return request({
43 | method: 'GET',
44 | url: '/xiaoce-cache/v1/get',
45 | params: {
46 | id,
47 | token: state.token,
48 | uid: state.uid,
49 | ...commonParams
50 | }
51 | }).then(res => res.data)
52 | }
53 |
54 | /**
55 | *
56 | * @param {string} id
57 | */
58 | export const getBookSectionDetail = (sectionId) => {
59 | // TODO 添加token
60 | return request({
61 | method: 'GET',
62 | url: '/xiaoce-cache/v1/getSection',
63 | params: {
64 | sectionId,
65 | token: state.token,
66 | uid: state.uid,
67 | ...commonParams
68 | }
69 | }).then(res => res.data)
70 | }
71 |
72 | /**
73 | *
74 | * @param {string} id
75 | */
76 | export const getBookSections = (id) => {
77 | // TODO 添加token
78 | return request({
79 | method: 'GET',
80 | url: '/xiaoce-cache/v1/getListSection',
81 | params: {
82 | id,
83 | token: state.token,
84 | uid: state.uid,
85 | ...commonParams
86 | }
87 | }).then(res => res.data)
88 | }
89 | /**
90 | *
91 | * @param {string} id
92 | * @param {number} pageNum
93 | * @param {number} pageSize
94 | */
95 | export const getListBuy = (id, pageNum=1, pageSize=20) => {
96 | // TODO 添加token
97 | return request({
98 | method: 'GET',
99 | url: '/xiaoce-cache/v1/getListBuy',
100 | params: {
101 | id,
102 | pageNum,
103 | pageSize,
104 | token: state.token,
105 | uid: state.uid,
106 | ...commonParams
107 | }
108 | }).then(res => res.data)
109 | }
--------------------------------------------------------------------------------
/src/api/collection.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { commonParams } from './common'
3 | import store from '../store'
4 | const state = store.state
5 |
6 | /**
7 | *
8 | * @param {string} targetUserId
9 | * @param {number} page
10 | */
11 | export const getUserCollectionSet = (targetUserId, page=0) => {
12 | return request({
13 | method: 'GET',
14 | url: '/collection-set/v1/getUserCollectionSet',
15 | params: {
16 | src: commonParams.src,
17 | clientId: commonParams.client_id,
18 | token: state.token,
19 | userId: state.uid,
20 | targetUserId,
21 | page
22 | }
23 | }).then(res => res.data)
24 | }
25 |
26 | export const getFollowedCollectionSet = (targetUserId, page=0, pageSize=30) => {
27 | return request({
28 | method: 'GET',
29 | url: '/collection-set/v1/getFollowedCollectionSet',
30 | params: {
31 | src: commonParams.src,
32 | clientId: commonParams.client_id,
33 | token: state.token,
34 | userId: state.uid,
35 | targetUserId,
36 | page,
37 | pageSize
38 | }
39 | }).then(res => res.data)
40 | }
41 |
42 | export const getCollectionSetInfo = (csId) => {
43 | return request({
44 | method: 'GET',
45 | url: '/collection-set/v1/getCollectionSetInfo',
46 | params: {
47 | csId,
48 | src: commonParams.src,
49 | clientId: commonParams.client_id,
50 | userId: state.uid,
51 | token: state.token
52 | }
53 | }).then(res => res.data)
54 | }
55 |
56 | export const getCollectionSetEntries = (csId, page, rankType='new') => {
57 | return request({
58 | method:'GET',
59 | url: '/collection-set/v1/getCollectionSetEntries',
60 | params: {
61 | page,
62 | csId,
63 | rankType,
64 | src: commonParams.src,
65 | clientId: commonParams.client_id,
66 | userId: state.uid,
67 | token: state.token
68 | }
69 | }).then(res => res.data)
70 | }
71 |
72 | export const followCollection = (csId) => {
73 | return request({
74 | method: 'PUT',
75 | url: '/collection-set/v1/follow',
76 | params: {
77 | csId,
78 | userId: state.uid,
79 | token: state.token,
80 | clientId: commonParams.client_id,
81 | src: commonParams.src
82 | }
83 | }).then(res => res.data)
84 | }
85 |
86 | export const unFollowCollection = (csId) => {
87 | return request({
88 | method: 'PUT',
89 | url: '/collection-set/v1/unfollow',
90 | params: {
91 | csId,
92 | userId: state.uid,
93 | token: state.token,
94 | clientId: commonParams.client_id,
95 | src: commonParams.src
96 | }
97 | }).then(res => res.data)
98 | }
--------------------------------------------------------------------------------
/src/api/common.js:
--------------------------------------------------------------------------------
1 | import store from '../store'
2 | import { device_id, client_id } from '../common/config'
3 | export const commonParams = {
4 | device_id,
5 | client_id,
6 | src: 'android'
7 | }
--------------------------------------------------------------------------------
/src/api/entry.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { commonParams } from './common'
3 | import store from '../store'
4 | import qs from 'qs'
5 | const state = store.state
6 |
7 | export const getEntryByIds = (entryIds) => {
8 | return request({
9 | method: 'GET',
10 | url: '/timeline-merger/v1/get_entry_by_ids',
11 | params: {
12 | entryIds,
13 | ...commonParams,
14 | token: state.token
15 | }
16 | }).then(res => res.data)
17 | }
18 |
19 | export const likeEntry = (entryId) => {
20 | return request.put(`/user-like/v1/user/like/entry/${entryId}`, qs.stringify({
21 | uid: store.state.uid,
22 | token: store.state.token,
23 | device_id: commonParams.device_id,
24 | src: commonParams.src
25 | }),{
26 | headers: {
27 | 'X-Juejin-Client': commonParams.client_id,
28 | 'X-Juejin-Src': 'web',
29 | 'X-Juejin-Token': store.state.token,
30 | 'X-Juejin-Uid': store.state.uid,
31 | 'Content-Type': 'application/x-www-form-urlencoded'
32 | }
33 | }).then(res => res.data)
34 | // return request({
35 | // method: 'PUT',
36 | // url: `/user-like/v1/user/like/entry/${entryId}`,
37 | // headers: {
38 | // 'X-Juejin-Client': commonParams.client_id,
39 | // 'X-Juejin-Src': 'web',
40 | // 'X-Juejin-Token': store.state.token,
41 | // 'X-Juejin-Uid': store.state.uid
42 | // }
43 | // }).then(res => res.data)
44 | }
--------------------------------------------------------------------------------
/src/api/home.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { apiUrl, } from '../common/config'
3 |
4 | import { commonParams } from './common'
5 | import store from '../store'
6 | const state = store.state
7 |
8 | /**
9 | * 获取文章列表
10 | * @param {object} data
11 | */
12 | export const query = (data) => {
13 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, data).then(res => {
14 | return res.data
15 | })
16 | }
17 |
18 | /**
19 | * 获取标签
20 | * @param {string} category
21 | */
22 | export const queryTag = (category) => {
23 | return request.post(apiUrl.WEB_HOME_REQUEST_URL, {
24 | operationName: "",
25 | query: "",
26 | variables: {category, limit: 15},
27 | extensions: {query: {id: "801e22bdc908798e1c828ba6b71a9fd9"}}
28 | }).then(res => {
29 | return res.data
30 | })
31 | }
32 |
33 | /**
34 | * 获取首页文章列表
35 | * @param {string} after
36 | */
37 | export const getRecommendedArticle = (after='') => {
38 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
39 | variables: {
40 | after,
41 | platformCode: '2',
42 | positionCodes: [2, 3],
43 | tags: []
44 | },
45 | extensions: {
46 | query: {
47 | id: 'f948b4528c56f0d2ceaff0be67b0809d'
48 | }
49 | }
50 | }).then(res => {
51 | return res.data
52 | })
53 | }
54 |
55 | /**
56 | * 获取热门文章列表
57 | * @param {string} after
58 | * @param {string} order
59 | */
60 | export const getHotArticle = (after='', order='THREE_DAYS_HOTTEST') => {
61 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
62 | variables: {
63 | after,
64 | order,
65 | "first": 30
66 | },
67 | "extensions": {
68 | "query": {
69 | "id": "f30157ca93f83fc7ff860ed0fb45599e"
70 | }
71 | }
72 | }).then(res => {
73 | return res.data
74 | })
75 | }
76 | /**
77 | * 获取文章列表
78 | * @param {string} category
79 | * @param {string[]} tags
80 | * @param {string} before
81 | * @param {number} limit
82 | */
83 | export const getEntryByTimeline = (category, tags=[], after='', limit=20) => {
84 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
85 | variables: {
86 | after,
87 | category,
88 | tags,
89 | },
90 | extensions: {
91 | query: {
92 | id: '242a289e6ba916aa4f3ceae00a4225d3'
93 | }
94 | }
95 | }).then(res => {
96 | return res.data
97 | })
98 | }
99 |
100 | /**
101 | *
102 | * @param {string} category
103 | * @param {number} limit
104 | * @param {string} period
105 | */
106 | export const getEntryByPeriod = (category, before='', limit=20, period='3day') => {
107 | return request({
108 | method: 'get',
109 | url: '/timeline-merger/v1/get_entry_by_period',
110 | params: {
111 | category,
112 | limit,
113 | period,
114 | before,
115 | token: state.token,
116 | uid: state.uid,
117 | ...commonParams
118 | }
119 | }).then(res => {
120 | return res.data
121 | })
122 | }
123 |
124 |
125 | export const getFollowingUserArticle = (after) => {
126 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
127 | variables: {
128 | after,
129 | feedType: "ARTICLE",
130 | afterPosition: "5e8fba2cef23ab3a04e4ee2b"
131 | },
132 | extensions: {
133 | query: {
134 | id: "05d2b2b04536aceb593531ec832d6b22"
135 | }
136 | },
137 |
138 | }).then(res => res.data)
139 | }
140 |
141 | /**
142 | *
143 | * @param {string[]} exclude
144 | */
145 | export const getRecommendedUser = (exclude=[]) => {
146 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
147 | variables: {
148 | excluded: []
149 | },
150 | extensions: {
151 | query: {
152 | id: "dc4406d13ccf186ca585b47f14e902b4"
153 | }
154 | }
155 | }).then(res => res.data)
156 | }
157 |
--------------------------------------------------------------------------------
/src/api/pins.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { apiUrl } from '../common/config'
3 | import store from '../store'
4 | import { commonParams } from './common'
5 |
6 | const state = store.state
7 |
8 | /**
9 | * 获取沸点推荐
10 | */
11 | export const getHotRecommendList = () => {
12 | return request({
13 | method: 'GET',
14 | url: '/short-msg/v1/getHotRecommendList',
15 | params: {
16 | token: state.token,
17 | uid: state.uid,
18 | ...commonParams
19 | }
20 | }).then(res => {
21 | return res.data
22 | })
23 | }
24 |
25 | /**
26 | * 获取主题
27 | * @param {string} topicId
28 | * @param {number} page
29 | * @param {number} pageSize
30 | * @param {string} sortType
31 | */
32 | export const getTopicList = (topicId, page=0, pageSize=20, sortType='rank') => {
33 | return request({
34 | method: 'GET',
35 | url: '/short-msg/v1/pinList/topic',
36 | params: {
37 | topicId,
38 | page,
39 | pageSize,
40 | sortType,
41 | token: state.token,
42 | uid: state.uid,
43 | ...commonParams
44 | }
45 | }).then(res => {
46 | return res.data
47 | })
48 | }
49 |
50 | /**
51 | * 获取沸点推荐列表
52 | * @param {string} after
53 | */
54 | export const getRecommendedFeed = (after='') => {
55 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
56 | "variables": {
57 | after,
58 | "afterPosition": ""
59 | },
60 | "extensions": {
61 | "query": {
62 | "id": "e3e03965a15cf246cf7cc3944086843b"
63 | }
64 | }
65 | }).then(res => res.data)
66 | }
67 |
68 | /**
69 | * 获取热门列表
70 | * @param {string} after
71 | */
72 | export const getPopularPinList = (after='') => {
73 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
74 | "variables": {
75 | after,
76 | "first": 20
77 | },
78 | "extensions": {
79 | "query": {
80 | "id": "1b6b07b2ffcdc06c43114d79ca131afa"
81 | }
82 | }
83 | }).then(res => res.data)
84 | }
85 |
86 | /**
87 | * 获取沸点评论
88 | * @param {string} id
89 | * @param {number} pageNum
90 | * @param {number} pageSize
91 | * @param {string} rankType
92 | */
93 | export const getPinComments = (id, pageNum=0, pageSize=20, rankType='new') => {
94 | return request({
95 | method: 'GET',
96 | url: `/hot-topic-comment-wrapper/v1/comments/${id}`,
97 | params: {
98 | pageNum,
99 | pageSize,
100 | rankType,
101 | token: state.token,
102 | uid: state.uid,
103 | ...commonParams
104 |
105 | }
106 | }).then(res => res.data)
107 | }
108 |
109 | // TODO 请求参数加上token
110 | /**
111 | *
112 | * @param {string} id
113 | */
114 | export const getPinById = (id) => {
115 | return request({
116 | method: 'GET',
117 | url: '/short-msg/v1/getByID',
118 | params: {
119 | msgId: id,
120 | token: state.token,
121 | uid: state.uid,
122 | ...commonParams
123 | }
124 | }).then(res => res.data)
125 | }
126 |
127 | export const getFollowingUserActivities = (after) => {
128 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
129 | variables: {
130 | after,
131 | feedType: "MAIN"
132 | },
133 | extensions: {
134 | query: {
135 | id: "05d2b2b04536aceb593531ec832d6b22"
136 | }
137 | }
138 | }).then(res => res.data)
139 | }
140 |
141 | /**
142 | *
143 | * @param {string[]} exclude
144 | */
145 | export const getRecommendedUser = (exclude=[], limit=8) => {
146 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
147 | variables: {
148 | excluded: JSON.stringify(exclude),
149 | limit,
150 | },
151 | extensions: {
152 | query: {
153 | id: "038909ed3577b0925031b01b445819a0"
154 | }
155 | }
156 | }).then(res => res.data)
157 | }
158 |
159 | export const likePin = (msgId) => {
160 | return request({
161 | method: 'GET',
162 | url: '/short-msg/v1/like',
163 | params: {
164 | msgId,
165 | uid: store.state.uid,
166 | token: store.state.token,
167 | ...commonParams
168 | }
169 | }).then(res => res.data)
170 | }
171 |
172 | export const unlikePin = (msgId) => {
173 | return request({
174 | method: 'GET',
175 | url: '/short-msg/v1/unlike',
176 | params: {
177 | msgId,
178 | uid: store.state.uid,
179 | token: store.state.token,
180 | ...commonParams
181 | }
182 | }).then(res => res.data)
183 | }
--------------------------------------------------------------------------------
/src/api/post.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import store from '../store'
3 |
4 | import { commonParams } from './common'
5 | const state = store.state
6 |
7 | export const getEntryView = (entryId) => {
8 | return request({
9 | method: 'GET',
10 | url: '/entry-view/v1/getEntryView',
11 | params: {
12 | entryId,
13 | token: state.token,
14 | uid: state.uid,
15 | ...commonParams,
16 | // src: commonParams.src
17 | }
18 | }).then(res => {
19 | return res.data
20 | })
21 | }
22 |
23 | export const getEntryByEntryIds = (entryIds) => {
24 | return request({
25 | method: 'GET',
26 | url: '/timeline-merger/v1/get_entry_by_ids',
27 | params: {
28 | entryIds,
29 | token: state.token,
30 | uid: state.uid,
31 | ...commonParams
32 | // src: commonParams.src
33 | }
34 | }).then(res => res.data)
35 | }
36 |
37 | export const getRelatedEntry = (entryId, limit=4) => {
38 | return request({
39 | method: 'GET',
40 | url: '/timeline-merger/v1/get_related_entry',
41 | params: {
42 | entryId,
43 | limit,
44 | token: state.token,
45 | uid: state.uid,
46 | ...commonParams
47 | // src: commonParams.src
48 | }
49 | }).then(res => res.data)
50 | }
51 |
52 | export const getComments = (id, createdAt='', rankType='new') => {
53 | return request({
54 | method: 'GET',
55 | url: `/comment-wrapper-ms/v2/comments/entry/${id}`,
56 | params: {
57 | createdAt,
58 | rankType,
59 | // token: state.token,
60 | // uid: state.uid,
61 | // ...commonParams
62 | src: commonParams.src
63 | }
64 | }).then(res => res.data)
65 | }
--------------------------------------------------------------------------------
/src/api/search.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { apiUrl } from '../common/config'
3 | import { commonParams } from './common'
4 | import store from '../store'
5 | const state = store.state
6 |
7 |
8 | // TODO 添加token
9 | /**
10 | * 获取banner
11 | */
12 | export const getEventBanner = () => {
13 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
14 | variables: {
15 | platformCode: 2,
16 | positionCodes: [4]
17 | },
18 | extensions: {
19 | query: {
20 | id: "1623ab25980fadf6bae12e10fc0af1e8"
21 | }
22 | }
23 | }).then(res => res.data)
24 | }
25 |
26 | // TODO 添加uid和token
27 | /**
28 | *
29 | * @param {string} before
30 | */
31 | export const getEntryByRank = (before) => {
32 | return request({
33 | method: 'GET',
34 | url: '/timeline-merger/v1/get_entry_by_rank',
35 | params: {
36 | before,
37 | limit: 30,
38 | src: commonParams.src,
39 | token: state.token,
40 | uid: state.uid,
41 | ...commonParams
42 | }
43 | }).then(res => res.data)
44 | }
45 |
46 | /**
47 | *
48 | * @param {string} query
49 | * @param {string} type
50 | * @param {string} after
51 | */
52 | export const search = (query, type, after='') => {
53 | return request.post(apiUrl.ANDROID_HOME_REQUEST_URL, {
54 | variables: {
55 | after,
56 | type: type.toUpperCase(),
57 | query
58 | },
59 | extensions: {
60 | query: {
61 | id: "caee4ea8b64f5860b8867564230e905f"
62 | }
63 | }
64 | }).then(res => res.data)
65 | }
--------------------------------------------------------------------------------
/src/api/topic.js:
--------------------------------------------------------------------------------
1 | import request from '../util/request'
2 | import { apiUrl } from '../common/config'
3 | import { commonParams } from './common'
4 | import store from '../store'
5 | import qs from 'qs'
6 |
7 | export const getTopicInfo = (topicId) => {
8 | return request({
9 | method: 'GET',
10 | url: `/short-msg/v1/topic/${topicId}`,
11 | params: {
12 | uid: store.state.uid,
13 | token: store.state.token,
14 | src: commonParams.src,
15 | device_id: commonParams.device_id
16 | }
17 | }).then(res => res.data)
18 | }
19 |
20 | export const getTopicPinList = (topicId, sortType='rank', page=0, pageSize=20) => {
21 | return request({
22 | method: 'GET',
23 | url: `/short-msg/v1/pinList/topic`,
24 | params: {
25 | topicId,
26 | sortType,
27 | page,
28 | pageSize,
29 | uid: store.state.uid,
30 | token: store.state.token,
31 | ...commonParams
32 | }
33 | }).then(res => res.data)
34 | }
35 |
36 | export const getTopicAttender = (topicId, page=0, pageSize=20) => {
37 | return request({
38 | method: 'GET',
39 | url: '/short-msg/v1/topic/attenders',
40 | params: {
41 | topicId,
42 | page,
43 | pageSize,
44 | uid: store.state.uid,
45 | token: store.state.token,
46 | ...commonParams
47 | }
48 | }).then(res => res.data)
49 | }
50 |
51 | /**
52 | *
53 | * @param {string} sortType
54 | * @param {number} page
55 | * @param {number} pageSize
56 | */
57 | export const getTopicList = (sortType='hot', page=0, pageSize=20) => {
58 | return request({
59 | method: 'GET',
60 | url: '/short-msg/v1/topicList',
61 | params: {
62 | ...commonParams,
63 | uid: store.state.uid,
64 | token: store.state.token,
65 | sortType,
66 | page,
67 | pageSize
68 | }
69 | }).then( res => res.data)
70 | }
71 |
72 | /**
73 | *
74 | * @param {string} topicIds
75 | */
76 | export const followTopic = (topicIds) => {
77 | return request.post('/short-msg/v1/topic/follow',qs.stringify({
78 | topicIds,
79 | ...commonParams,
80 | uid: store.state.uid,
81 | token: store.state.token
82 | }), {
83 | headers: {
84 | 'Content-Type':' application/x-www-form-urlencoded'
85 | }
86 | }).then(res => res.data)
87 | }
--------------------------------------------------------------------------------
/src/assets/css/common.styl:
--------------------------------------------------------------------------------
1 |
2 | .con {
3 | padding: 0 20*$unit;
4 | background: #fff;
5 | }
6 |
7 | .scroll-with-no-bar {
8 | overflow: scroll
9 | }
10 |
11 | .scroll-with-no-bar::-webkit-scrollbar {
12 | display: none
13 | }
14 |
15 | .page-content {
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | .page-section {
21 | flex: 1;
22 | height: 0;
23 | }
24 |
25 | .slide-enter, .slide-leave-to{
26 |
27 | transform: translateY(100%);
28 | z-index: 1;
29 | }
30 |
31 | .border-top-1px {
32 | position: relative;
33 | }
34 |
35 | .touch-active:active {
36 | background: #dcdbdb !important;
37 | }
38 |
39 | .follow {
40 | padding: 14*$unit 0;
41 | width: 150*$unit;
42 | border: 1px #6cbd45 solid;
43 | text-align: center;
44 | color: #6cbd45;
45 | font-size: 26*$unit;
46 | border-radius: 5*$unit;
47 | }
48 | .edit-btn {
49 | padding: 14*$unit 35*$unit;
50 | /* width: 140*$unit; */
51 | border: 1px #007fff solid;
52 | color: #007fff;
53 | font-size: 26*$unit;
54 | border-radius: 5*$unit;
55 | }
56 | .follow.active {
57 | background: #6cbd45;
58 | border: none;
59 | color: #fff;
60 | }
61 | .follow .iconfont{
62 | padding: 0;
63 | margin-right: 10*$unit;
64 | font-size: 26*$unit;
65 | }
66 |
67 | .border-top-1px::after {
68 | content: ' ';
69 | width: 100%;
70 | height: 1px;
71 | background: #edeeef;
72 | position: absolute;
73 | left: 0;
74 | top: 0;
75 | overflow: hidden;
76 | /* border-bottom: 1px solid #71777c; */
77 | transform-origin: left bottom;
78 | }
79 |
80 | .border-bottom-1px {
81 | position: relative;
82 | }
83 |
84 | .border-bottom-1px::after {
85 | content: ' ';
86 | width: 100%;
87 | height: 1px;
88 | background: #edeeef;
89 | position: absolute;
90 | left: 0;
91 | bottom: 0;
92 | overflow: hidden;
93 | /* border-bottom: 1px solid #71777c; */
94 | transform-origin: left bottom;
95 | }
96 |
97 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
98 | .border-bottom-1px::after {
99 | -webkit-transform: scaleY(.7);
100 | transform: scaleY(.7);
101 | }
102 | .border-top-1px::after {
103 | -webkit-transform: scaleY(.7);
104 | transform: scaleY(.7);
105 | }
106 | }
107 |
108 | @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {
109 | .border-bottom-1px::after {
110 | -webkit-transform: scaleY(.5);
111 | transform: scaleY(.5);
112 | }
113 | .border-top-1px::after {
114 | -webkit-transform: scaleY(.7);
115 | transform: scaleY(.7);
116 | }
117 | }
118 |
119 | @media only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) {
120 | .border-bottom-1px ::after {
121 | -webkit-transform: scaleY(.33);
122 | transform: scaleY(.33);
123 | }
124 | .border-top-1px::after {
125 | -webkit-transform: scaleY(.7);
126 | transform: scaleY(.7);
127 | }
128 | }
--------------------------------------------------------------------------------
/src/assets/css/variable.styl:
--------------------------------------------------------------------------------
1 | $gray-color=#f4f5f5
2 | $primary-color=#0180ff
3 | $border-color=#edeeef
4 | $text-color=#666
5 | $title-color=#2e3135
6 | $gray-text-color=#909090
7 | $primary-text-color=#007fff
8 | $active-color=#dcdbdb
9 | $primary-green-color=#6cbd45
10 | $article-content-color=#5c6066
11 | $unit=1/32rem
12 |
--------------------------------------------------------------------------------
/src/common/cache.js:
--------------------------------------------------------------------------------
1 | const cache = {
2 | /**
3 | *
4 | * @param {string} key
5 | * @param {any} value
6 | */
7 | set(key, value) {
8 | cache[key] = value
9 | },
10 | /**
11 | *
12 | * @param {string} key
13 | * @param {any} value
14 | */
15 | get(key) {
16 | return cache[key]
17 | }
18 | }
19 |
20 | export default cache
--------------------------------------------------------------------------------
/src/common/config.js:
--------------------------------------------------------------------------------
1 | import store from './store'
2 | import { HOME_ROUTE_KEY, PIN_ROUTE_KEY, HOME_ROUTE_INDEX_KEY, PIN_ROUTE_INDEX_KEY } from './const'
3 | import { generateDeviceId } from '../util'
4 |
5 | export let defaultHomeRoutes = [{
6 | path: '/home/following',
7 | title: '关注'
8 | },{
9 | path: '/home/recommended',
10 | title: '推荐',
11 | },{
12 | path: '/home/hot',
13 | title: '热榜'
14 | },
15 | ]
16 |
17 | export let homeRoutes = store.get(HOME_ROUTE_KEY, [{
18 | path: '/home/backend',
19 | title: '后端',
20 | show: false
21 | }, {
22 | path: '/home/frontend',
23 | title: '前端',
24 | show: false
25 | }, {
26 | path: '/home/android',
27 | title: 'Android',
28 | show: false
29 | }, {
30 | path: '/home/ios',
31 | title: 'IOS',
32 | show: false
33 | }, {
34 | path: '/home/ai',
35 | title: '人工智能',
36 | show: false
37 | }, {
38 | path: '/home/freebie',
39 | title: '开发工具',
40 | show: false
41 | }, {
42 | path: '/home/career',
43 | title: '代码人生',
44 | show: false
45 | }, {
46 | path: '/home/article',
47 | title: '阅读',
48 | show: false
49 | }
50 | ])
51 |
52 | export const homeRouteIndex = store.get(HOME_ROUTE_INDEX_KEY, {
53 | '/home/following': -2,
54 | '/home/recommended': -1,
55 | '/home/hot': 0,
56 | '/home/backend': 1,
57 | '/home/frontend': 2,
58 | '/home/android': 3,
59 | '/home/ios': 4,
60 | '/home/ai': 5,
61 | '/home/freebie': 6,
62 | '/home/career': 7,
63 | '/home/article': 8,
64 | })
65 |
66 |
67 | export const pinRouteIndex = store.get(PIN_ROUTE_INDEX_KEY, {
68 | '/pins/following': -2,
69 | '/pins/recommended': -1,
70 | '/pins/hot': -0,
71 | '/pins/topic/5c09ea2b092dcb42c740fe73': 1,
72 | '/pins/topic/5abb61e1092dcb4620ca3322': 2,
73 | '/pins/topic/5c106be9092dcb2cc5de7257': 3,
74 | '/pins/topic/5b514af1092dcb61bd72800d': 4,
75 | '/pins/topic/5abb67d2092dcb4620ca3324': 5,
76 | '/pins/topic/5c46a17f092dcb4737217152': 6,
77 | })
78 |
79 | export let defaultPinsRoutes = [
80 | {
81 | path: '/pins/following',
82 | title: '关注'
83 | },
84 | {
85 | path: '/pins/recommended',
86 | title: '推荐'
87 | },{
88 | path: '/pins/hot',
89 | title: '热门'
90 | }
91 | ]
92 |
93 | export let pinsRoutes = store.get(PIN_ROUTE_KEY, [{
94 | path: '/pins/topic/5c09ea2b092dcb42c740fe73',
95 | title: '开源推荐',
96 | show: true
97 | },{
98 | path: '/pins/topic/5abb61e1092dcb4620ca3322',
99 | title: '内推招聘',
100 | show: true,
101 | },{
102 | path: '/pins/topic/5abcaa67092dcb4620ca335c',
103 | title: '掘金相亲',
104 | show: true,
105 | },{
106 | path: '/pins/topic/5c106be9092dcb2cc5de7257',
107 | title: '上班摸鱼',
108 | show: true,
109 | },{
110 | path: '/pins/topic/5b514af1092dcb61bd72800d',
111 | title: '应用安利',
112 | show: true,
113 | }, {
114 | path: '/pins/topic/5abb67d2092dcb4620ca3324',
115 | title: '开发工具',
116 | show: true
117 | }, {
118 | path: '/pins/topic/5c46a17f092dcb4737217152',
119 | title: 'New资讯',
120 | show: true
121 | }]
122 | )
123 |
124 | export const apiUrl = {
125 | ANDROID_HOME_REQUEST_URL: 'https://android-api.juejin.im/graphql',
126 | WEB_HOME_REQUEST_URL: 'https://web-api.juejin.im/query'
127 | }
128 |
129 | export const pinsRouteType = {
130 | RECOMMENDED: 'RECOMMENDED',
131 | HOT: 'HOT',
132 | TOPIC: 'TOPIC'
133 | }
134 |
135 | export const routeTypes = {
136 | HOME_CATEGORY: 'home_category',
137 | HOME_RECOMMEND: 'home_recommend',
138 | HOME_HOT: 'home_hot',
139 | }
140 |
141 |
142 | export const device_id = generateDeviceId()
143 | export const client_id = device_id
--------------------------------------------------------------------------------
/src/common/const.js:
--------------------------------------------------------------------------------
1 | export const HOME_ROUTE_KEY = '__HOME_ROUTES__'
2 | export const PIN_ROUTE_KEY = '__PIN_ROUTE_KEY__'
3 | export const TOKEN_KEY = '__TOKEN__'
4 | export const UID_KEY = '__UID_KEY__'
5 | export const IS_LOGIN_KEY = '__IS_LOGIN__'
6 | export const HOME_ROUTE_INDEX_KEY = '_HOME_ROUTE_INDEX_KEY_'
7 | export const PIN_ROUTE_INDEX_KEY = '_PIN_ROUTE_INDEX_KEY_'
--------------------------------------------------------------------------------
/src/common/store.js:
--------------------------------------------------------------------------------
1 | const store = {
2 | get(key, defaultValue) {
3 | return JSON.parse(localStorage.getItem(key)) || defaultValue
4 | },
5 | set(key, value) {
6 | localStorage.setItem(key, JSON.stringify(value))
7 | }
8 | }
9 |
10 | export default store
--------------------------------------------------------------------------------
/src/components/book-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
{{book.title}}
10 |
11 |
{{book.userData.username}}
12 |
![]()
13 |
14 |
15 | {{book.lastSectionCount}}小节 · {{book.buyCount}}人已购买
16 |
17 |
18 |
19 |
20 |
¥{{book.price}}
21 |
22 |
23 |
24 |
25 |
26 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/book-section-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{index}}
4 |
5 |
{{section.title}}
6 |
7 | 阅读时长: {{section.contentSize | readTime }}
8 | {{section.pv}}次学习
9 |
10 |
11 |
12 |
13 | 试读
14 |
15 |
16 |

17 |
18 |
19 |
20 |
21 |
22 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/collection-item/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{collection.title}}
6 |
7 | {{collection.entryCount}}篇 ·
8 | {{collection.followCount}}关注 ·
9 | {{collection.user.username}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/comment/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
50 |
51 |
52 |
76 |
77 |
--------------------------------------------------------------------------------
/src/components/fold-text/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 | {{text}}
11 |
12 |
13 |
{{isFold ? '展开全文' : '收起'}}
14 |
15 |
16 |
17 |
64 |
65 |
--------------------------------------------------------------------------------
/src/components/l-article-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 | 专栏
13 |
14 |
{{article.title}}
15 |
16 |
17 |
18 | {{article.content}}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
59 |
60 |
--------------------------------------------------------------------------------
/src/components/l-pin-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
52 |
53 |
--------------------------------------------------------------------------------
/src/components/link-view/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{urlTitle}}
5 |
{{linkDomain}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
--------------------------------------------------------------------------------
/src/components/loading/image/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/src/components/loading/image/loading.gif
--------------------------------------------------------------------------------
/src/components/loading/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/m-article-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
21 |
22 | {{article.title}}
23 |
24 |
25 | {{article.content}}
26 |
27 |
28 |
29 |
30 |
31 |
41 |
42 |
43 |
44 |
67 |
68 |
--------------------------------------------------------------------------------
/src/components/m-author/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
{{author.username}}
11 |
![]()
12 |
13 |
14 | {{author.jobTitle}}
15 | @ {{author.company}}
16 | · {{dateDis}}
17 |
18 |
{{author.description}}
19 |
20 |
21 |
22 |
23 | 已关注
24 |
25 |
26 |
27 | 关注
28 |
29 |
30 |
31 |
32 |
33 |
72 |
73 |
--------------------------------------------------------------------------------
/src/components/m-header/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/message/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue' // 引入 Vue
2 | import MessageMain from './src' // 引入上边定义好的 message 模板
3 | const MessageBox = Vue.extend(MessageMain) // 使用 Vue.extend 来创建一个构造器
4 | let instance // instance 变量用来保存实例
5 | let timer = null // timer 变量用来保存定时器
6 | // 定义一个 function, 参数为 options, 默认为一个对象
7 | const Message = function(options = {}) {
8 | // 如果当前处在服务器端, 则直接返回
9 | if(Vue.prototype.$isServer) return
10 | // 如果当前定时器已开启, 说明页面上已经有一个 message-box 了, 则不能再继续创建新的 message-box
11 | if(timer) return
12 | // 对 options 做处理, 如果直接传入 string, 则使其保存在 options 的 message 属性上
13 | if(typeof options === 'string') {
14 | options = {
15 | message: options
16 | }
17 | }
18 | // 初始化实例, 并将 options 作为新的 data 传入, Vue 会将 options 合并到原有的 data 上, 覆盖原有的默认值, 但是, 在 options 中没有设置的是不会被改变的
19 | instance = new MessageBox({
20 | data: options
21 | })
22 | // 调用 $mount 方法, 将当前实例渲染为真实 DOM, 生成 $el,, 如果不执行这一步, 将拿不到 $el 的值, 但是不指定 DOM 节点接管当前实例
23 | instance.vm = instance.$mount()
24 | // 使用原生 JS 的 API 将当前实例的真实 DOM 追加到 body 中
25 | document.body.appendChild(instance.vm.$el)
26 | // 实例上的 vm 就是我们的 Vue 组件, 所以我们可以通过 vm 访问到当前实例中的所有属性
27 | // 将 visible 设置为 true, 即显示当前 message-box
28 | instance.vm.visible = true
29 | // 开启定时器
30 | timer = setTimeout(() => {
31 | // 在时间结束后将当前实例手动卸载
32 | instance.vm.visible = false
33 | // 使用原生 API 将当前实例生成的 DOM 节点在真实的 DOM 树中删除
34 | setTimeout(() => {
35 | instance.vm.$destroy()
36 | instance.vm.$el.parentNode.removeChild(instance.vm.$el)
37 | timer = null
38 | }, 500)
39 |
40 | // 清除定时器
41 | }, instance.vm.duration)
42 | // 定时器的时间使用 vm 中定义的时间
43 | return instance.vm
44 | }
45 | // 最终抛出一个对象, 对象上我们可以使用 install 来扩展 Vue 的插件
46 | // 当我们的对象上有 install 方法的时候, 它接收第一个参数为 Vue,
47 | // 我这里为了方便使用, 还在当前抛出的对象上定义了一个 message 方法, 为了方便在 axios 的拦截器中使用
48 | export default {
49 | message: Message,
50 | install(Vue) {
51 | Vue.prototype.$message = Message
52 | Vue.message = Message
53 | }
54 | }
--------------------------------------------------------------------------------
/src/components/message/src/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{message}}
6 |
7 |
8 |
9 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/native-scroll/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
72 |
73 |
--------------------------------------------------------------------------------
/src/components/nav-tab/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | {{item.title}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
82 |
83 |
--------------------------------------------------------------------------------
/src/components/need-login/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{title}}
8 |
9 |
10 | 登录/注册
11 |
12 |
13 |
14 |
15 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/pin-info/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 | {{pin.topic.title}}
19 |
20 |
21 |
22 |
23 |
24 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/refresh/image/refresh.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanfengliao/vue-juejin/c9c3c1cd310e2c83a1ffc7103cf74d5906890f08/src/components/refresh/image/refresh.gif
--------------------------------------------------------------------------------
/src/components/refresh/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/router-transition/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
33 |
34 |
--------------------------------------------------------------------------------
/src/components/s-article-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{article.title}}
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/s-author/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
{{author.username}}
10 |
![]()
11 |
12 |
13 |
14 | 已关注
15 |
16 |
17 |
18 | 关注
19 |
20 |
21 |
22 |
23 |
42 |
43 |
--------------------------------------------------------------------------------
/src/components/s-header/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/s-pin-entry/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 荐
6 | 热
7 | {{pin.content}}
8 |
9 |
10 |
11 |
12 | {{pin.user.username}}
13 | {{pin.likedCount}} 赞 · {{pin.commentCount}} 评论
14 |
15 |
16 |
17 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/scroll/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
138 |
139 |
--------------------------------------------------------------------------------
/src/components/search-box/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
15 |
52 |
53 |
--------------------------------------------------------------------------------
/src/components/switch/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
36 |
37 |
--------------------------------------------------------------------------------
/src/components/tab/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
39 |
40 |
--------------------------------------------------------------------------------
/src/components/tag-item/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{tag.title}}
6 |
7 | {{tag.subscribersCount}}人关注
8 | ·
9 | {{tag.entryCount}}篇文章
10 |
11 |
12 |
13 |
14 |
15 | 关注
16 |
17 |
18 |
19 |
20 |
21 |
33 |
34 |
--------------------------------------------------------------------------------
/src/components/tag/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{text}}
4 |
5 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/three-op/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{likeCount > 0 ? likeCount : '点赞'}}
6 |
7 |
8 |
9 | {{commentCount > 0 ? commentCount : '评论'}}
10 |
11 |
12 |
13 | 分享
14 |
15 |
16 |
17 |
18 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/topic-item/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
{{topic.title}}
8 |
9 | {{topic.followersCount}} 关注者
10 | ·
11 | {{topic.msgsCount}} 沸点
12 |
13 |
14 |
17 |
18 |
19 |
20 |
41 |
42 |
--------------------------------------------------------------------------------
/src/fliter/index.js:
--------------------------------------------------------------------------------
1 | export const dateDis = date => {
2 | let stime = new Date(date).getTime()
3 | let etime = Date.now()
4 | let dtime = etime - stime
5 | let year = Math.floor(dtime / (24 * 3600 * 1000 * 365))
6 | if (year > 0) {
7 | return year + '年前'
8 | }
9 | let days = Math.floor(dtime / (24 * 3600 * 1000))
10 | if (days > 0) {
11 | return days + '天前'
12 | }
13 | let hours = Math.floor(dtime / (3600 * 1000))
14 | if (hours > 0) {
15 | return hours + '小时前'
16 | }
17 | let minutes = Math.floor(dtime / (60 * 1000))
18 | if (minutes > 5) {
19 | return minutes + '分钟前'
20 | }
21 | return '刚刚'
22 | }
23 |
24 | const backgroundImages = [
25 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-1.636691c.svg',
26 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-2.f597b88.svg',
27 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-3.e108c68.svg',
28 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-4.2c3fafd.svg',
29 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-5.f8d5198.svg',
30 | 'https://b-gold-cdn.xitu.io/v3/static/img/lv-6.74bd93a.svg'
31 | ]
32 |
33 | export const levelImage = index => {
34 | return backgroundImages[index - 1]
35 | }
--------------------------------------------------------------------------------
/src/layout/footer/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
45 |
46 |
--------------------------------------------------------------------------------
/src/layout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue"
2 | import App from "./App.vue"
3 | import router from "./router"
4 | import store from "./store"
5 | import routerTransition from './plugin/router-transition'
6 | // import RouterTransition from './plugin/router-transition/index.vue'
7 | // import RouterTransition from './components/router-transition'
8 | import Message from './components/message'
9 |
10 | import './assets/css/normalize.styl'
11 | import './assets/css/common.styl'
12 | import { dateDis, levelImage } from './fliter'
13 | import VueAwesomeSwiper from 'vue-awesome-swiper'
14 |
15 | // import style
16 | import 'swiper/css/swiper.css'
17 | import './assets/css/article.styl'
18 |
19 | // function resize() {
20 | // let clientWidth = document.documentElement.clientWidth
21 | // let fontSize = 16 * clientWidth / 375
22 | // document.documentElement.style.fontSize = fontSize + 'px'
23 | // }
24 |
25 | console.log(navigator.userAgent)
26 |
27 |
28 | Vue.use(VueAwesomeSwiper)
29 | Vue.use(Message)
30 | Vue.config.productionTip = false
31 |
32 | Vue.use(routerTransition, {
33 | router
34 | })
35 |
36 | Vue.filter('dateDis', dateDis)
37 | Vue.filter('levelImage', levelImage)
38 |
39 | new Vue({
40 | router,
41 | store,
42 | render: h => h(App)
43 | }).$mount("#app")
44 |
45 |
--------------------------------------------------------------------------------
/src/mixins/index.js:
--------------------------------------------------------------------------------
1 | export const keepAliveMixin = {
2 | created() {
3 | this.$store.dispatch('addKeepAlive', this.$options.name)
4 | },
5 | methods: {
6 | goBackAndRemoveKeepAlive() {
7 | this.$store.dispatch('removeKeepAlive', this.$options.name)
8 | this.$router.goBack()
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/plugin/router-transition/constant.js:
--------------------------------------------------------------------------------
1 | export const transitionType = {
2 | PUSH: 'push',
3 | COVER: 'cover'
4 | }
5 |
6 | export const directionType = {
7 | TOP_TO_BOTTOM: 'top-to-bottom',
8 | BOTTOM_TO_TOP: 'bottom-to-top',
9 | LEFT_TO_RIGHT: 'left-to-right',
10 | RIGHT_TO_LEFT: 'right-to-left'
11 | }
--------------------------------------------------------------------------------
/src/plugin/router-transition/index.js:
--------------------------------------------------------------------------------
1 | import RouterTransition from './index.vue'
2 | export default {
3 | /**
4 | *
5 | * @param {Vue} Vue
6 | * @param {} options
7 | */
8 | install(Vue, options) {
9 | let { routeIndex } = options
10 | Vue.prototype.$routeIndex = routeIndex
11 | Vue.component('router-transition', RouterTransition)
12 |
13 | },
14 | }
--------------------------------------------------------------------------------
/src/plugin/router-transition/util.js:
--------------------------------------------------------------------------------
1 | export const isDef = (o) => {
2 | return o!== undefined && o !== null
3 | }
--------------------------------------------------------------------------------
/src/router/home.js:
--------------------------------------------------------------------------------
1 | import HomeArticleList from '../views/home/pages/home-article-list'
2 | import HomeFollowing from '../views/home/pages/home-following'
3 | import { homeRoutes as _homeRoutes, routeTypes} from '../common/config'
4 |
5 | const routeMap = {
6 | '/home/backend': {
7 | props: {
8 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
9 | categoryId: '5562b419e4b00c57d9b94ae2',
10 | hasTags: true
11 | },
12 | path: '/home/backend',
13 | name: '后端',
14 | component: HomeArticleList,
15 | meta: {
16 | routeType: routeTypes.HOME_CATEGORY
17 | }
18 | },
19 | '/home/frontend': {
20 | props: {
21 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
22 | categoryId: '5562b415e4b00c57d9b94ac8',
23 | hasTags: true
24 | },
25 | path: '/home/frontend',
26 | name: '前端',
27 | component: HomeArticleList,
28 | meta: {
29 | routeType: routeTypes.HOME_CATEGORY
30 | }
31 | },
32 | '/home/android': {
33 | props: {
34 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
35 | categoryId: '5562b410e4b00c57d9b94a92',
36 | hasTags: true
37 | },
38 | path: '/home/android',
39 | name: 'Android',
40 | component: HomeArticleList,
41 | meta: {
42 | routeType: routeTypes.HOME_CATEGORY
43 | }
44 | },
45 | '/home/ios': {
46 | props: {
47 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
48 | categoryId: '5562b405e4b00c57d9b94a41',
49 | hasTags: true
50 | },
51 | path: '/home/ios',
52 | name: 'IOS',
53 | component: HomeArticleList,
54 | meta: {
55 | routeType: routeTypes.HOME_CATEGORY
56 | }
57 | },
58 | '/home/ai': {
59 | props: {
60 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
61 | categoryId: '57be7c18128fe1005fa902de',
62 | hasTags: true
63 | },
64 | path: '/home/ai',
65 | name: '人工智能',
66 | component: HomeArticleList,
67 | meta: {
68 | routeType: routeTypes.HOME_CATEGORY
69 | }
70 | },
71 | '/home/freebie': {
72 | props: {
73 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
74 | categoryId: '5562b422e4b00c57d9b94b53',
75 | hasTags: true
76 | },
77 | path: '/home/freebie',
78 | name: '开发工具',
79 | component: HomeArticleList,
80 | meta: {
81 | routeType: routeTypes.HOME_CATEGORY
82 | }
83 | },
84 | '/home/career': {
85 | props: {
86 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
87 | categoryId: '5c9c7cca1b117f3c60fee548',
88 | hasTags: true
89 | },
90 | path: '/home/career',
91 | name: '代码人生',
92 | component: HomeArticleList,
93 | meta: {
94 | routeType: routeTypes.HOME_CATEGORY
95 | }
96 | },
97 | '/home/article': {
98 | props: {
99 | queryId: '242a289e6ba916aa4f3ceae00a4225d3',
100 | categoryId: '5562b428e4b00c57d9b94b9d',
101 | hasTags: true
102 | },
103 | path: '/home/article',
104 | name: '阅读',
105 | component: HomeArticleList,
106 | meta: {
107 | routeType: routeTypes.HOME_CATEGORY
108 | }
109 | }
110 | }
111 |
112 | export const homeRoutes = [
113 | {
114 | name: '关注',
115 | path: '/home/following',
116 | component: HomeFollowing
117 | },
118 | {
119 | props: {
120 | queryId: 'f948b4528c56f0d2ceaff0be67b0809d'
121 | },
122 | name: '推荐',
123 | path: '/home/recommended',
124 | component: HomeArticleList,
125 | meta: {
126 | routeType: routeTypes.HOME_RECOMMEND
127 | }
128 | },{
129 | props: {
130 | queryId: 'f30157ca93f83fc7ff860ed0fb45599e',
131 | sort: 'THREE_DAYS_HOTTEST',
132 | sortTags:[{
133 | tagId: 'THREE_DAYS_HOTTEST',
134 | title: '三天内'
135 | }, {
136 | tagId: 'WEEKLY_HOTTEST',
137 | title: '七天内'
138 | }, {
139 | tagId: 'MONTHLY_HOTTEST',
140 | title: '30天内'
141 | }, {
142 | tagId: 'HOTTEST',
143 | title: '全部'
144 | }]
145 | },
146 | name: '热榜',
147 | path: '/home/hot',
148 | component: HomeArticleList,
149 | meta: {
150 | routeType: routeTypes.HOME_HOT
151 | }
152 | }
153 | ]
154 |
155 | for (let item of _homeRoutes) {
156 | homeRoutes.push(routeMap[item.path])
157 | }
158 |
--------------------------------------------------------------------------------
/src/router/pins.js:
--------------------------------------------------------------------------------
1 | import PinsEntryList from '../views/pins/pages/pins-entry-list'
2 | import PinFollowing from '../views/pins/pages/pin-following'
3 | import { pinsRouteType } from '../common/config'
4 |
5 | export const pinsRoutes = [{
6 | name: 'pins-following',
7 | path: '/pins/following',
8 | component: PinFollowing
9 | },{
10 | name: 'pins-recommended',
11 | path: '/pins/recommended',
12 | component: PinsEntryList,
13 | meta: {
14 | type: pinsRouteType.RECOMMENDED
15 | }
16 | }, {
17 | name: 'pins-hot',
18 | path: '/pins/hot',
19 | component: PinsEntryList,
20 | meta: {
21 | type: pinsRouteType.HOT,
22 | }
23 | },{
24 | path: '/pins/topic/:id',
25 | component: PinsEntryList,
26 | meta: {
27 | type: pinsRouteType.TOPIC
28 | }
29 | }]
--------------------------------------------------------------------------------
/src/router/topic.js:
--------------------------------------------------------------------------------
1 | import TopicPinList from '../views/topic/pages/topic-pin-list'
2 |
3 | export const topicRoutes = [{
4 | name: 'topic-pin-list',
5 | path: ':type',
6 | component: TopicPinList
7 | }]
--------------------------------------------------------------------------------
/src/router/user.js:
--------------------------------------------------------------------------------
1 | import UserActivity from '../views/user/pages/user-activity'
2 | import UserPost from '../views/user/pages/user-post'
3 | import UserPin from '../views/user/pages/user-pin'
4 | import UserShare from '../views/user/pages/user-share'
5 | import UserMore from '../views/user/pages/user-more'
6 | import { ROUTE_INDEX } from '../common/const'
7 | export const userRoutes = [
8 | {
9 | name: 'user-activity',
10 | path: 'activies',
11 | component: UserActivity
12 | },
13 | {
14 | name: 'user-post',
15 | path: 'posts',
16 | component: UserPost
17 | },
18 | {
19 | name: 'user-pin',
20 | path: 'pins',
21 | component: UserPin
22 | },
23 | {
24 | name: 'user-share',
25 | path: 'shares',
26 | component: UserShare,
27 | },
28 | {
29 | name: 'user-more',
30 | path: 'more',
31 | component: UserMore,
32 | },
33 | ]
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import * as types from './mutation-types'
2 |
3 | import { HOME_ROUTE_KEY, PIN_ROUTE_KEY, TOKEN_KEY, UID_KEY, IS_LOGIN_KEY, HOME_ROUTE_INDEX_KEY, PIN_ROUTE_INDEX_KEY } from '../common/const'
4 | import { login } from '../api/auth'
5 |
6 | import Message from '../components/message'
7 | import store from '../common/store'
8 |
9 | export const setRouteTransition = ({commit}, value) => {
10 | commit(types.SET_ROUTE_TRANSITION, value)
11 | }
12 |
13 | export const userLogin = async ({ commit },{username, password, loginType}) => {
14 | let data = await login(username, password, loginType)
15 |
16 | if (data.s !== 1) {
17 | Message.message(data.m)
18 | return false
19 | }
20 | let { token , user_id } = data.d
21 | commit(types.SET_TOKEN, token)
22 | commit(types.SET_UID, user_id)
23 | commit(types.SET_IS_LOGIN, true)
24 | localStorage.setItem(TOKEN_KEY, token)
25 | localStorage.setItem(UID_KEY, user_id)
26 | localStorage.setItem(IS_LOGIN_KEY, true)
27 | return true
28 | }
29 |
30 | export const userLogout = ({ commit }) => {
31 | commit(types.SET_IS_LOGIN, false)
32 | localStorage.setItem(IS_LOGIN_KEY, false)
33 | }
34 |
35 | export const addKeepAlive = ({commit,state}, componentName) => {
36 | let { keepAliveArr } = state
37 | if (keepAliveArr.indexOf(componentName) === -1) {
38 | keepAliveArr.push(componentName)
39 | commit(types.SET_KEEP_ALIVE_ARR, keepAliveArr)
40 | }
41 | }
42 |
43 | export const removeKeepAlive = ({commit, state}, componentName) => {
44 | let { keepAliveArr } = state
45 | let index = keepAliveArr.indexOf(componentName)
46 | if (index !== -1) {
47 | keepAliveArr.splice(index, 1)
48 | commit(types.SET_KEEP_ALIVE_ARR, keepAliveArr)
49 | }
50 | }
51 |
52 |
53 | export const setHomeRoutes = ({commit}, homeRoutes) => {
54 | // store.set(HOME_ROUTE_KEY, homeRoutes)
55 | commit(types.SET_HOME_ROUTES, homeRoutes)
56 | store.set(HOME_ROUTE_KEY, homeRoutes)
57 | }
58 |
59 |
60 | export const setPinRoutes = ({commit}, pinRoutes) => {
61 | // store.set(PIN_ROUTE_KEY, pinRoutes)
62 | commit(types.SET_PINS_ROUTES, pinRoutes)
63 | store.set(PIN_ROUTE_KEY, pinRoutes)
64 | }
65 |
66 | export const setQuery = ({ commit }, query) => {
67 | commit(types.SET_QUERY, query)
68 | }
69 |
70 |
71 | export const setHomeRouteIndex = ({commit, state}, routeIndex) => {
72 | let { homeRouteIndex } = state
73 | homeRouteIndex = Object.assign(homeRouteIndex, routeIndex)
74 | commit(types.SET_HOME_ROUTE_INDEX, homeRouteIndex)
75 | store.set(HOME_ROUTE_INDEX_KEY, homeRouteIndex)
76 | }
77 |
78 | export const setPinRouteIndex = ({commit, state}, routeIndex) => {
79 | let { pinRouteIndex } = state
80 | pinRouteIndex = Object.assign(pinRouteIndex, routeIndex)
81 | commit(types.SET_PIN_ROUTE_INDEX, pinRouteIndex)
82 | store.set(PIN_ROUTE_INDEX_KEY, pinRouteIndex)
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export const routeTransition = state => state.routeTransition
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue"
2 | import Vuex from "vuex"
3 |
4 | Vue.use(Vuex)
5 | import * as actions from './actions'
6 | import * as getters from './getters'
7 | import mutations from './mutations'
8 | import state from './state'
9 | export default new Vuex.Store({
10 | actions,
11 | getters,
12 | mutations,
13 | state
14 | })
15 |
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const SET_ROUTE_TRANSITION = 'set_route_transition'
2 | export const SET_HOME_ROUTES = 'set_home_routes'
3 | export const SET_PINS_ROUTES = 'set_pins_routes'
4 | export const SET_TOKEN = 'set_token'
5 | export const SET_UID = 'set_uid'
6 | export const SET_IS_LOGIN = 'set_is_login'
7 | export const SET_KEEP_ALIVE_ARR = 'set_keep_alive_arr'
8 | export const SET_QUERY = 'set_query'
9 | export const SET_HOME_ROUTE_INDEX = 'set_home_route_index'
10 | export const SET_PIN_ROUTE_INDEX = 'set_pin_route_index'
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import * as types from './mutation-types'
2 | const mutations = {
3 | [types.SET_ROUTE_TRANSITION](state, routeTransition) {
4 | state.routeTransition = routeTransition
5 | },
6 | [types.SET_HOME_ROUTES](state, homeRoutes) {
7 | state.homeRoutes = homeRoutes
8 | },
9 | [types.SET_PINS_ROUTES](state, pinsRoutes) {
10 | state.pinsRoutes = pinsRoutes
11 | },
12 | [types.SET_TOKEN](state, token) {
13 | state.token = token
14 | },
15 | [types.SET_UID](state, uid) {
16 | state.uid = uid
17 | },
18 | [types.SET_IS_LOGIN](state, isLogin) {
19 | state.isLogin = isLogin
20 | },
21 | [types.SET_KEEP_ALIVE_ARR](state, arr) {
22 | state.keepAliveArr = arr
23 | },
24 | [types.SET_QUERY](state, query) {
25 | state.query = query
26 | },
27 | [types.SET_HOME_ROUTE_INDEX](state, homeRouteIndex) {
28 | state.homeRouteIndex = homeRouteIndex
29 | },
30 | [types.SET_PIN_ROUTE_INDEX](state, pinRouteIndex) {
31 | state.pinRouteIndex = pinRouteIndex
32 | }
33 | }
34 |
35 | export default mutations
--------------------------------------------------------------------------------
/src/store/state.js:
--------------------------------------------------------------------------------
1 | import { homeRoutes,pinsRoutes, homeRouteIndex, pinRouteIndex } from '../common/config'
2 | import { TOKEN_KEY, UID_KEY, IS_LOGIN_KEY } from '../common/const'
3 |
4 | const state = {
5 | routeTransition: true,
6 | defaultAvatar: 'https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg',
7 | homeRoutes,
8 | pinsRoutes,
9 | homeRouteIndex,
10 | pinRouteIndex,
11 | token: localStorage.getItem(TOKEN_KEY) || '',
12 | uid: localStorage.getItem(UID_KEY) || '',
13 | isLogin: JSON.parse(localStorage.getItem(IS_LOGIN_KEY)) || false,
14 | keepAliveArr: ['layout'],
15 | query: ''
16 | }
17 |
18 | export default state
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 从数组中随机抽取n个
3 | * @param {Array} arr
4 | * @param {number} n
5 | * @returns
6 | */
7 | export const randomSelect = (arr, n) => {
8 | let _arr = arr.slice()
9 | let result = []
10 | if (n >= _arr.length) {
11 | return _arr
12 | }
13 | let len = _arr.length
14 | for (let i = 0; i < n; ++i) {
15 | let index = Math.floor(Math.random() * (len - i))
16 | result.push(_arr[index])
17 | let temp = _arr[index]
18 | _arr[index] = _arr[len - 1 - i]
19 | _arr[len - 1 - i] = temp
20 | }
21 | return result
22 | }
23 |
24 | /**
25 | *
26 | * @param {string} url
27 | */
28 | export const getUrlParams = (url) => {
29 | let queryString = url.split('?')[1]
30 | if (queryString) {
31 | let kvs = queryString.split('&')
32 | if (kvs.length > 0) {
33 | let params = {}
34 | for (let item of kvs) {
35 | let [k, v] = item.split('=')
36 | params[k] = v
37 | }
38 | return params
39 | }
40 | }
41 |
42 | }
43 |
44 | /**
45 | *
46 | * @param {Function} fn
47 | * @param {number} delay
48 | */
49 | export const throttle = function(fn, delay=500) {
50 | let last = 0
51 | return function(...args) {
52 | if (Date.now() - last >= delay) {
53 | fn.apply(this, args)
54 | last = Date.now()
55 | }
56 | }
57 | }
58 |
59 | export function generateDeviceId() {
60 | let deviceId = localStorage.getItem('_device_id_')
61 | if (!deviceId) {
62 | deviceId = Math.random().toString().slice(2, 6)
63 | let deviceId = localStorage.setItem('_device_id_', deviceId)
64 | }
65 | return deviceId
66 | }
--------------------------------------------------------------------------------
/src/util/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import store from '../store'
3 | import { device_id, client_id } from '../common/config'
4 |
5 |
6 | const service = axios.create({
7 | timeout: 5000
8 | })
9 |
10 | service.interceptors.request.use(
11 | config => {
12 | config.headers['X-Agent'] = 'Juejin/xiaomi/Redmi Note 7 Pro Android/9 Juejin/Android/5.9.3',
13 | config.headers['X-Juejin-Src'] = 'android'
14 | // let { token, uid } = store.state
15 | // config.headers['X-Juejin-Uid'] = state.uid
16 | // config.headers['X-Juejin-Token'] = state.token
17 | // config.headers['X-Token'] = state.token
18 | const state = store.state
19 | config.headers['X-Legacy-Token'] = state.token
20 | config.headers['X-Legacy-Uid'] = state.uid
21 | config.headers['X-Juejin-Client'] = client_id
22 | config.headers['X-Legacy-Device-Id'] = device_id
23 | return config
24 | }
25 | )
26 | service.interceptors.response.use(res=>{
27 | return res
28 | }, err=> {
29 | return err.response
30 | })
31 |
32 | export default service
--------------------------------------------------------------------------------
/src/views/about/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
声明
9 |
该Web应用完全为第三方开发者开发,仅用于学习交流,禁止用于其他用途。
10 |
11 |
12 |
代码已开源
13 |
14 |
15 |
16 |
17 |
18 |
求大佬给个star
19 |
{{githubAddress}}
20 |
21 |
22 |
23 |
24 |
25 |
联系方式
26 |
27 |
28 |
29 |
30 |
31 |
通过GitHub反馈
32 |
{{githubHome}}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
通过Email反馈
41 |
{{email}}
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
通过QQ反馈
50 |
{{qq}}
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
75 |
76 |
--------------------------------------------------------------------------------
/src/views/books/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
56 |
57 |
--------------------------------------------------------------------------------
/src/views/books/pages/book-entry-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
79 |
80 |
--------------------------------------------------------------------------------
/src/views/collection-set/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | -
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
116 |
117 |
--------------------------------------------------------------------------------
/src/views/feedback/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
给 掘金 官方反馈
9 |
10 | 请使用 掘金 官方渠道(APP、网站等)进行反馈。
11 | 该Web应用完全为第三方开发者开发,仅用于学习交流,禁止用于其他用途。
12 |
13 |
14 |
15 |
代码已开源
16 |
17 |
18 |
19 |
20 |
21 |
求大佬给个star
22 |
{{githubAddress}}
23 |
24 |
25 |
26 |
27 |
28 |
联系方式
29 |
30 |
31 |
32 |
33 |
34 |
通过GitHub反馈
35 |
{{githubHome}}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
通过Email反馈
44 |
{{email}}
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
通过QQ反馈
53 |
{{qq}}
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
78 |
79 |
--------------------------------------------------------------------------------
/src/views/home/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
96 |
97 |
--------------------------------------------------------------------------------
/src/views/login/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |

9 |
10 |
18 |
21 |
22 | 忘记密码?
23 | 第三方登录
24 |
25 |
26 |
27 |
28 |
29 |
81 |
82 |
--------------------------------------------------------------------------------
/src/views/my-like/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | -
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
111 |
112 |
--------------------------------------------------------------------------------
/src/views/my-purchased-book/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
58 |
59 |
--------------------------------------------------------------------------------
/src/views/pins/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
69 |
70 |
--------------------------------------------------------------------------------
/src/views/recommendation-author/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
77 |
78 |
--------------------------------------------------------------------------------
/src/views/recommendation-author/pages/recommend-author-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
69 |
70 |
--------------------------------------------------------------------------------
/src/views/search/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
20 | -
21 |
22 |
23 | {{item}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | 清空搜索记录
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
128 |
129 |
--------------------------------------------------------------------------------
/src/views/search/pages/search-result/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
74 |
75 |
--------------------------------------------------------------------------------
/src/views/section-detail/components/section-content/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
此章节为付费章节
8 |
现在购买立即解锁全部内容
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
48 |
49 |
--------------------------------------------------------------------------------
/src/views/set-psd/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
59 |
60 |
--------------------------------------------------------------------------------
/src/views/setting/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
22 |
23 |
24 | 关于
25 |
26 |
27 |
28 | 退出登录
29 |
30 |
31 |
32 |
33 |
34 |
63 |
64 |
--------------------------------------------------------------------------------
/src/views/tag-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
21 |
22 |
23 |
24 |
25 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
138 |
139 |
--------------------------------------------------------------------------------
/src/views/topic-attender/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
80 |
81 |
--------------------------------------------------------------------------------
/src/views/topic/pages/topic-pin-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
49 |
50 |
--------------------------------------------------------------------------------
/src/views/topics/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
更多话题
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
86 |
87 |
--------------------------------------------------------------------------------
/src/views/user-like/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
59 |
60 |
--------------------------------------------------------------------------------
/src/views/user-read-history/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
79 |
80 |
--------------------------------------------------------------------------------
/src/views/user-tag/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
58 |
59 |
--------------------------------------------------------------------------------
/src/views/user/pages/user-more/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 赞过的文章
6 | {{collectedEntriesCount}}
7 |
8 |
9 |
10 |
11 |
12 | 关注的标签
13 | {{subscribedTagsCount}}
14 |
15 |
16 |
17 |
18 | 收藏集
19 | {{collectionSetCount}}
20 |
21 |
22 |
23 |
24 |
25 |
50 |
51 |
--------------------------------------------------------------------------------
/src/views/user/pages/user-pin/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
43 |
44 |
--------------------------------------------------------------------------------
/src/views/user/pages/user-post/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
43 |
44 |
--------------------------------------------------------------------------------
/src/views/user/pages/user-share/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
42 |
43 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const events = require('events')
2 | events.EventEmitter.defaultMaxListeners = 50
3 | module.exports = {
4 | lintOnSave: false,
5 | devServer: {
6 | proxy: {
7 | '/timeline-merger': {
8 | target: 'http://timeline-merger-ms.juejin.im',
9 | changeOrigin: true,
10 | pathRewrite: {
11 | '/timeline-merger': '/'
12 | }
13 | },
14 | '/entry-view': {
15 | target: 'https://entry-view-storage-api-ms.juejin.im',
16 | changeOrigin: true,
17 | pathRewrite: {
18 | '/entry-view': '/'
19 | }
20 | },
21 | '/hot-topic-comment-wrapper': {
22 | target: 'https://hot-topic-comment-wrapper-ms.juejin.im',
23 | changeOrigin: true,
24 | pathRewrite: {
25 | '/hot-topic-comment-wrapper': '/'
26 | }
27 | },
28 | '/short-msg': {
29 | target: 'https://short-msg-ms.juejin.im',
30 | changeOrigin: true,
31 | pathRewrite: {
32 | '/short-msg': '/'
33 | }
34 | },
35 | '/xiaoce-cache': {
36 | target: 'https://xiaoce-cache-api-ms.juejin.im',
37 | changeOrigin: true,
38 | pathRewrite: {
39 | '/xiaoce-cache': '/'
40 | }
41 | },
42 | '/xiaoce-timeline': {
43 | target: 'https://xiaoce-timeline-api-ms.juejin.im',
44 | changeOrigin: true,
45 | pathRewrite: {
46 | '/xiaoce-timeline': '/'
47 | }
48 | },
49 |
50 | '/comment-wrapper-ms': {
51 | target: 'https://comment-wrapper-ms.juejin.im',
52 | changeOrigin: true,
53 | pathRewrite: {
54 | '/comment-wrapper-ms': '/'
55 | }
56 | },
57 | '/event-storage': {
58 | target: 'https://event-storage-api-ms.juejin.im',
59 | changeOrigin: true,
60 | pathRewrite: {
61 | '/event-storage': '/'
62 | }
63 | },
64 | '/auth-center': {
65 | target: 'https://auth-center-ms.juejin.im',
66 | changeOrigin: true,
67 | pathRewrite: {
68 | '/auth-center': '/'
69 | }
70 | },
71 | '/user-storage': {
72 | target: 'https://user-storage-api-ms.juejin.im',
73 | changeOrigin: true,
74 | pathRewrite: {
75 | '/user-storage': '/'
76 | }
77 | },
78 | '/gold-tag': {
79 | target: 'https://gold-tag-ms.juejin.im',
80 | changeOrigin: true,
81 | pathRewrite: {
82 | '/gold-tag': '/'
83 | }
84 | },
85 | '/user-like': {
86 | target: 'https://user-like-wrapper-ms.juejin.im',
87 | changeOrigin: true,
88 | pathRewrite: {
89 | '/user-like': '/'
90 | }
91 | },
92 | '/collection-set': {
93 | target: 'https://collection-set-ms.juejin.im',
94 | changeOrigin: true,
95 | pathRewrite: {
96 | '/collection-set': '/'
97 | }
98 | },
99 | '/lccro': {
100 | target: 'https://lccro-api-ms.juejin.im',
101 | changeOrigin: true,
102 | pathRewrite: {
103 | '/lccro': '/'
104 | }
105 | },
106 | '/follow-api': {
107 | target: 'https://follow-api-ms.juejin.im',
108 | changeOrigin: true,
109 | pathRewrite: {
110 | '/follow-api': '/'
111 | }
112 | },
113 | },
114 | },
115 | css: {
116 | loaderOptions: {
117 | stylus: {
118 | import: '~@/assets/css/variable.styl'
119 | }
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------