├── components
├── loading
│ ├── index.js
│ ├── index.json
│ ├── index.wxml
│ └── index.wxss
├── classic
│ ├── essay
│ │ ├── index.wxss
│ │ ├── index.json
│ │ ├── images
│ │ │ └── essay@tag.png
│ │ ├── index.js
│ │ └── index.wxml
│ ├── movie
│ │ ├── index.wxss
│ │ ├── index.json
│ │ ├── images
│ │ │ └── movie@tag.png
│ │ ├── index.js
│ │ └── index.wxml
│ ├── music
│ │ ├── index.json
│ │ ├── images
│ │ │ ├── music@tag.png
│ │ │ ├── player@playing.png
│ │ │ └── player@waitting.png
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ └── index.js
│ ├── classic-beh.js
│ └── common.wxss
├── book
│ ├── index.json
│ ├── index.wxml
│ ├── index.js
│ └── index.wxss
├── epsoide
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ └── index.js
├── like
│ ├── index.json
│ ├── images
│ │ ├── like.png
│ │ └── like@dis.png
│ ├── index.wxml
│ ├── index.wxss
│ ├── like-beh.js
│ └── index.js
├── mask
│ ├── index.json
│ ├── index.wxml
│ ├── index.js
│ └── index.wxss
├── navi
│ ├── index.json
│ ├── images
│ │ ├── triangle@left.png
│ │ ├── triangle@right.png
│ │ ├── triangle.dis@left.png
│ │ └── triangle.dis@right.png
│ ├── index.wxss
│ ├── index.wxml
│ └── index.js
├── tag
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ └── index.js
├── image-button
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ └── index.js
├── search
│ ├── images
│ │ ├── cancel.png
│ │ └── search.png
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ └── index.js
├── preview
│ ├── index.json
│ ├── index.wxml
│ ├── index.js
│ └── index.wxss
└── behaviors
│ └── pagination.js
├── pages
├── about
│ ├── about.json
│ ├── about.wxml
│ └── about.js
├── course
│ ├── course.json
│ ├── course.wxml
│ ├── course.wxss
│ └── course.js
├── book
│ ├── book.json
│ ├── book.wxml
│ ├── book.wxss
│ └── book.js
├── my
│ ├── my.json
│ ├── my.wxml
│ ├── my.js
│ └── my.wxss
├── book-detail
│ ├── book-detail.json
│ ├── book-detail.js
│ ├── book-detail.wxml
│ └── book-detail.wxss
├── classic
│ ├── classic.json
│ ├── classic.wxss
│ ├── classic.wxml
│ └── classic.js
└── classic-detail
│ ├── classic-detail.json
│ ├── classic-detail.wxml
│ ├── classic-detail.wxss
│ └── classic-detail.js
├── images
├── my
│ ├── my.png
│ ├── about.png
│ ├── course.png
│ ├── like.png
│ ├── my@bg.png
│ ├── study.png
│ └── vendor.png
├── tab
│ ├── my.png
│ ├── book.png
│ ├── classic.png
│ ├── my@highlight.png
│ ├── book@highlight.png
│ └── classic@highlight.png
├── book
│ ├── tip.png
│ └── quality.png
└── icon
│ ├── search.png
│ └── share.png
├── 纯正商业级应用-微信小程序开发实战.mmap
├── .gitignore
├── app.wxss
├── README.md
├── config.js
├── sitemap.json
├── utils
├── filter.wxs
├── util.js
├── http-p.js
└── http.js
├── models
├── comment.js
├── keyword.js
├── like.js
├── book.js
└── classic.js
├── app.js
├── promise.md
├── app.json
├── project.config.json
└── API.md
/components/loading/index.js:
--------------------------------------------------------------------------------
1 | Component({})
2 |
--------------------------------------------------------------------------------
/components/classic/essay/index.wxss:
--------------------------------------------------------------------------------
1 | @import "../common.wxss";
--------------------------------------------------------------------------------
/components/classic/movie/index.wxss:
--------------------------------------------------------------------------------
1 | @import "../common.wxss";
--------------------------------------------------------------------------------
/pages/about/about.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true
3 | }
4 |
--------------------------------------------------------------------------------
/pages/course/course.json:
--------------------------------------------------------------------------------
1 | {
2 | "backgroundColor": "#f5f5f5"
3 | }
4 |
--------------------------------------------------------------------------------
/pages/course/course.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/course/course.wxss:
--------------------------------------------------------------------------------
1 | .img {
2 | width: 100%;
3 | height: 1984rpx;
4 | }
5 |
--------------------------------------------------------------------------------
/images/my/my.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/my.png
--------------------------------------------------------------------------------
/images/tab/my.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/my.png
--------------------------------------------------------------------------------
/components/book/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/epsoide/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/like/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/loading/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/mask/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/navi/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/tag/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/images/book/tip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/book/tip.png
--------------------------------------------------------------------------------
/images/my/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/about.png
--------------------------------------------------------------------------------
/images/my/course.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/course.png
--------------------------------------------------------------------------------
/images/my/like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/like.png
--------------------------------------------------------------------------------
/images/my/my@bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/my@bg.png
--------------------------------------------------------------------------------
/images/my/study.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/study.png
--------------------------------------------------------------------------------
/images/my/vendor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/my/vendor.png
--------------------------------------------------------------------------------
/images/tab/book.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/book.png
--------------------------------------------------------------------------------
/components/classic/movie/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/classic/music/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/mask/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/icon/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/icon/search.png
--------------------------------------------------------------------------------
/images/icon/share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/icon/share.png
--------------------------------------------------------------------------------
/images/tab/classic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/classic.png
--------------------------------------------------------------------------------
/纯正商业级应用-微信小程序开发实战.mmap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/纯正商业级应用-微信小程序开发实战.mmap
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | .vscode
3 | .idea/
4 | Pipfile.lock
5 | project.config.json
6 | node_modules
7 |
--------------------------------------------------------------------------------
/components/classic/essay/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/components/image-button/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/images/book/quality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/book/quality.png
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /* 组件会自动被 page 包裹 */
2 | page {
3 | font-family: PingFangSC-Thin;
4 | font-size: 16px;
5 | }
6 |
--------------------------------------------------------------------------------
/images/tab/my@highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/my@highlight.png
--------------------------------------------------------------------------------
/images/tab/book@highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/book@highlight.png
--------------------------------------------------------------------------------
/components/like/images/like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/like/images/like.png
--------------------------------------------------------------------------------
/images/tab/classic@highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/images/tab/classic@highlight.png
--------------------------------------------------------------------------------
/components/like/images/like@dis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/like/images/like@dis.png
--------------------------------------------------------------------------------
/components/search/images/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/search/images/cancel.png
--------------------------------------------------------------------------------
/components/search/images/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/search/images/search.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # imooc-pure
2 |
3 | > 纯正商业级应用-微信小程序开发实战 appkey
4 |
5 | - RdshydjBvcYZhMZC
6 | - GgRhTjUNUYn1fHke
7 |
8 | ## 运行
9 |
--------------------------------------------------------------------------------
/components/navi/images/triangle@left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/navi/images/triangle@left.png
--------------------------------------------------------------------------------
/components/navi/images/triangle@right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/navi/images/triangle@right.png
--------------------------------------------------------------------------------
/components/classic/essay/images/essay@tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/classic/essay/images/essay@tag.png
--------------------------------------------------------------------------------
/components/classic/movie/images/movie@tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/classic/movie/images/movie@tag.png
--------------------------------------------------------------------------------
/components/classic/music/images/music@tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/classic/music/images/music@tag.png
--------------------------------------------------------------------------------
/components/navi/images/triangle.dis@left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/navi/images/triangle.dis@left.png
--------------------------------------------------------------------------------
/components/navi/images/triangle.dis@right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/navi/images/triangle.dis@right.png
--------------------------------------------------------------------------------
/components/classic/music/images/player@playing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/classic/music/images/player@playing.png
--------------------------------------------------------------------------------
/components/loading/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/components/mask/index.js:
--------------------------------------------------------------------------------
1 | // components/mask/index.js
2 | Component({
3 | options: {
4 | multipleSlots: true // 在组件定义时的选项中启用多slot支持
5 | }
6 | })
7 |
--------------------------------------------------------------------------------
/components/classic/music/images/player@waitting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GanYihuan/wx-pure/HEAD/components/classic/music/images/player@waitting.png
--------------------------------------------------------------------------------
/components/classic/movie/index.js:
--------------------------------------------------------------------------------
1 | import { classicBehavior } from '../classic-beh.js'
2 |
3 | Component({
4 | behaviors: [classicBehavior] // 组件的属性列表
5 | })
6 |
--------------------------------------------------------------------------------
/components/classic/essay/index.js:
--------------------------------------------------------------------------------
1 | import { classicBehavior } from '../classic-beh.js'
2 |
3 | Component({
4 | // 组件的属性列表
5 | behaviors: [classicBehavior]
6 | })
7 |
--------------------------------------------------------------------------------
/components/image-button/index.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | api_blink_url: 'http://bl.7yue.pro/v1/',
3 | appkey: 'RdshydjBvcYZhMZC'
4 | // appkey: 'GgRhTjUNUYn1fHke'
5 | }
6 |
7 | export { config }
8 |
--------------------------------------------------------------------------------
/components/preview/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "tag-cmp": "/components/tag/index",
5 | "like-cmp": "/components/like/index"
6 | }
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/pages/book/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "book-cmp": "/components/book/index",
4 | "search-cmp": "/components/search/index"
5 | },
6 | "backgroundColor": "#f5f5f5"
7 | }
8 |
--------------------------------------------------------------------------------
/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/components/search/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {
4 | "tag-cmp": "../tag/index",
5 | "book-cmp": "../book/index",
6 | "loading-cmp": "../loading/index"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/pages/about/about.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/components/mask/index.wxss:
--------------------------------------------------------------------------------
1 | /* components/mask/index.wxss */
2 | .container {
3 | z-index: 99;
4 | position: fixed;
5 | top: 0;
6 | width: 100%;
7 | height: 100%;
8 | background-color: #000;
9 | opacity: 0.6;
10 | }
11 |
--------------------------------------------------------------------------------
/components/classic/classic-beh.js:
--------------------------------------------------------------------------------
1 | let classicBehavior = Behavior({
2 | properties: {
3 | type: String,
4 | img: String,
5 | content: String,
6 | hidden: Boolean
7 | }
8 | })
9 |
10 | export { classicBehavior }
11 |
--------------------------------------------------------------------------------
/pages/my/my.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "img-btn-cmp": "/components/image-button/index",
4 | "tag-cmp": "/components/tag/index",
5 | "previe-cmp": "/components/preview/index"
6 | },
7 | "backgroundColor": "#f5f5f5"
8 | }
9 |
--------------------------------------------------------------------------------
/components/classic/essay/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{content}}
5 |
--------------------------------------------------------------------------------
/components/like/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{count}}
5 |
6 |
--------------------------------------------------------------------------------
/components/tag/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{text}}
5 |
6 |
--------------------------------------------------------------------------------
/components/classic/movie/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{content}}
5 |
6 |
--------------------------------------------------------------------------------
/pages/book-detail/book-detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "tag-cmp": "/components/tag/index",
4 | "like-cmp": "/components/like/index",
5 | "mask-cmp": "/components/mask/index",
6 | "img-btn-cmp": "/components/image-button/index"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/components/tag/index.wxss:
--------------------------------------------------------------------------------
1 | /* components/tag/index.wxss */
2 | .container {
3 | flex-direction: row;
4 | justify-content: center;
5 | align-items: center;
6 | display: inline-flex;
7 | padding: 4rpx 12rpx;
8 | border-radius: 2px;
9 | font-size: 28rpx;
10 | color: #666666;
11 | background-color: #f5f5f5;
12 | }
13 |
--------------------------------------------------------------------------------
/components/image-button/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | /* display: flex;
3 | flex-direction: row;
4 | justify-content: center; */
5 | /* display: flex; */
6 | padding: 0 !important;
7 | border: none !important;
8 | /* display: inline !important; */
9 | }
10 |
11 | /* .img{
12 | width:100%;
13 | height:100%;
14 | } */
15 |
--------------------------------------------------------------------------------
/components/classic/music/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{content}}
6 |
--------------------------------------------------------------------------------
/pages/classic/classic.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "like-cmp": "/components/like/index",
4 | "movie-cmp": "/components/classic/movie/index",
5 | "epsoide-cmp": "/components/epsoide/index",
6 | "essay-cmp": "/components/classic/essay/index",
7 | "navi-cmp": "/components/navi/index",
8 | "music-cmp": "/components/classic/music/index"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/components/epsoide/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | No.
4 | {{_index}}
5 |
6 |
7 |
8 | {{month}}
9 | {{year}}
10 |
11 |
12 |
--------------------------------------------------------------------------------
/components/navi/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: inline-flex;
3 | flex-direction: row;
4 | justify-content: space-between;
5 | align-items: center;
6 | border-radius: 4rpx;
7 | width: 600rpx;
8 | height: 80rpx;
9 | background-color: #f7f7f7;
10 | }
11 |
12 | .navi-icon {
13 | width: 80rpx;
14 | height: 80rpx;
15 | }
16 |
17 | .title {
18 | font-size: 28rpx;
19 | }
20 |
--------------------------------------------------------------------------------
/components/tag/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
4 | },
5 | externalClasses: ['tag-class'], // 组件外部传入的样式
6 | properties: {
7 | text: String
8 | },
9 | methods: {
10 | onTap: function(event) {
11 | this.triggerEvent('tapping', {
12 | text: this.properties.text
13 | })
14 | }
15 | }
16 | })
17 |
--------------------------------------------------------------------------------
/components/book/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{book.title}}
5 | {{book.author}}
6 |
9 |
10 |
--------------------------------------------------------------------------------
/components/preview/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{classic.content}}
8 |
--------------------------------------------------------------------------------
/components/classic/common.wxss:
--------------------------------------------------------------------------------
1 | .classic-container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | }
6 |
7 | .classic-img {
8 | width: 750rpx;
9 | height: 500rpx;
10 | }
11 |
12 | .tag {
13 | position: relative;
14 | bottom: 58rpx;
15 | right: 310rpx;
16 | width: 46rpx;
17 | height: 142rpx;
18 | }
19 |
20 | .content {
21 | max-width: 550rpx;
22 | font-size: 36rpx;
23 | }
--------------------------------------------------------------------------------
/utils/filter.wxs:
--------------------------------------------------------------------------------
1 | var limit = function(array, length) {
2 | return array.slice(0, length)
3 | }
4 |
5 | // 不能用 const, wxs 不能用 es6 语法
6 | var format = function(text) {
7 | if (!text) {
8 | return
9 | }
10 | var reg = getRegExp('\\\\n', 'g')
11 | var text = text.replace(reg, '\n ')
12 | return text
13 | }
14 |
15 | module.exports = {
16 | format: format,
17 | limit: limit
18 | }
19 |
--------------------------------------------------------------------------------
/components/like/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: inline-flex;
3 | flex-direction: row;
4 | /* 指定宽度,否则会出现移动, 数字显示使用 10k */
5 | width: 120rpx;
6 | padding: 10rpx;
7 | }
8 |
9 | .container image {
10 | width: 32rpx;
11 | height: 28rpx;
12 | }
13 |
14 | .container text {
15 | position: relative;
16 | bottom: 10rpx;
17 | left: 6rpx;
18 | /* 取消字体上下间距 */
19 | line-height: 24rpx;
20 | font-size: 24rpx;
21 | color: #bbb;
22 | }
23 |
--------------------------------------------------------------------------------
/components/navi/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | {{title}}
10 |
16 |
--------------------------------------------------------------------------------
/pages/classic-detail/classic-detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "navi-cmp": "/components/navi/index",
4 | "epsoide-cmp": "/components/epsoide/index",
5 | "like-cmp": "/components/like/index",
6 | "movie-cmp": "/components/classic/movie/index",
7 | "music-cmp": "/components/classic/music/index",
8 | "essay-cmp": "/components/classic/essay/index",
9 | "img-btn-cmp": "/components/image-button/index"
10 | },
11 | "disableScroll": true
12 | }
13 |
--------------------------------------------------------------------------------
/components/image-button/index.js:
--------------------------------------------------------------------------------
1 | // components/image-button/index.html.js
2 | Component({
3 | options: {
4 | multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
5 | },
6 | properties: {
7 | openType: {
8 | type: String
9 | },
10 | imageSrc: {
11 | type: String
12 | },
13 | bindgetuserinfo: {
14 | type: String
15 | }
16 | },
17 | methods: {
18 | onGetUserInfo(event) {
19 | this.triggerEvent('getuserinfo', event.detail, {})
20 | }
21 | }
22 | })
23 |
--------------------------------------------------------------------------------
/models/comment.js:
--------------------------------------------------------------------------------
1 | import { HTTP } from '../utils/http-p'
2 |
3 | class CommentModel extends HTTP {
4 | getComments(bid) {
5 | return this.request({
6 | url: `${'book/'}${bid}${'/short_comment'}`
7 | })
8 | }
9 | postComment(bid, comment) {
10 | return this.request({
11 | url: 'book/add/short_comment',
12 | method: 'POST',
13 | data: {
14 | book_id: bid,
15 | content: comment
16 | }
17 | })
18 | }
19 | }
20 |
21 | export { CommentModel }
22 |
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | const chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
2 |
3 | const random = function generateMixed(n) {
4 | var res = ''
5 | for (var i = 0; i < n; i++) {
6 | var id = Math.ceil(Math.random() * 35)
7 | res += chars[id]
8 | }
9 | return res
10 | }
11 |
12 | function breakSection(text) {}
13 |
14 | module.exports = {
15 | random: random,
16 | breakSection: breakSection
17 | }
18 |
--------------------------------------------------------------------------------
/components/book/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | book: Object,
4 | showLike: {
5 | type: Boolean,
6 | value: true
7 | }
8 | },
9 | data: {
10 | title: String,
11 | author: String,
12 | img: String
13 | },
14 | methods: {
15 | onTap: function(event) {
16 | const bid = this.properties.book.id
17 | this.triggerEvent(
18 | 'booktap',
19 | {
20 | bid: this.properties.book.id
21 | },
22 | {}
23 | )
24 | wx.navigateTo({
25 | url: `/pages/book-detail/book-detail?bid=${bid}`
26 | })
27 | }
28 | }
29 | })
30 |
--------------------------------------------------------------------------------
/components/like/like-beh.js:
--------------------------------------------------------------------------------
1 | let likeBehavior = Behavior({
2 | properties: {
3 | like: Boolean,
4 | count: Number
5 | },
6 | data: {
7 | yes_url: '../images/like.png',
8 | no_url: '../images/like@dis.png'
9 | },
10 | attached: function() {},
11 | methods: {
12 | onLike: function(event) {
13 | let count = this.properties.count
14 | count = this.properties.like ? count - 1 : count + 1
15 | this.setData({
16 | count: count,
17 | like: !this.properties.like
18 | })
19 | let behavior = this.properties.like ? 'like' : 'cancel'
20 | this.triggerEvent(
21 | 'like',
22 | {
23 | behavior: behavior
24 | },
25 | {}
26 | )
27 | }
28 | }
29 | })
30 |
31 | export { likeBehavior }
32 |
--------------------------------------------------------------------------------
/components/preview/index.js:
--------------------------------------------------------------------------------
1 | // components/preview/index.js
2 | Component({
3 | properties: {
4 | classic: {
5 | type: Object,
6 | observer: function(newVal) {
7 | if (newVal) {
8 | var typeText = {
9 | 100: '电影',
10 | 200: '音乐',
11 | 300: '句子'
12 | }[newVal.type]
13 | }
14 | this.setData({
15 | typeText: typeText
16 | })
17 | }
18 | }
19 | },
20 | data: {
21 | typeText: String
22 | },
23 | methods: {
24 | onTap: function() {
25 | this.triggerEvent( // 注意 catchtap 与 bindtap 的区别
26 | 'tap',
27 | {
28 | cid: this.properties.classic.id,
29 | type: this.properties.classic.type
30 | },
31 | {}
32 | )
33 | }
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/pages/book/book.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/models/keyword.js:
--------------------------------------------------------------------------------
1 | import { HTTP } from '../utils/http-p.js'
2 |
3 | class KeywordModel extends HTTP {
4 | key = 'q'
5 | max = 10
6 | getHistory() {
7 | const words = wx.getStorageSync(this.key)
8 | if (!words) {
9 | return []
10 | }
11 | return words
12 | }
13 | getHot() {
14 | return this.request({
15 | url: '/book/hot_keyword'
16 | })
17 | }
18 | addToHistory(word) { // 关键字写入缓存中
19 | let keywords = this.getHistory()
20 | // const has = keywords.inlcludes(word)
21 | let index = keywords.indexOf(word)
22 | if (index == -1) {
23 | let length = keywords.length
24 | if (length >= this.max) {
25 | keywords.pop(word)
26 | }
27 | keywords.unshift(word)
28 | wx.setStorageSync(this.key, keywords)
29 | }
30 | }
31 | }
32 |
33 | export { KeywordModel }
34 |
--------------------------------------------------------------------------------
/components/epsoide/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: inline-flex;
3 | flex-direction: row;
4 | height: 60rpx; /* 根据最高元素 08 font-size 设置 */
5 | }
6 |
7 | .index-container {
8 | display: flex;
9 | flex-direction: row;
10 | align-items: baseline; /* No 08 | 基于底部对齐 */
11 | }
12 |
13 | .plain {
14 | font-size: 32rpx;
15 | }
16 |
17 | .index {
18 | margin: 0 14rpx 0 0;
19 | line-height: 60rpx; /* 取消字体上下间距 */
20 | font-size: 60rpx; /* 取消字体上下间距 */
21 | font-weight: 800;
22 | }
23 |
24 | .vertical-line {
25 | margin: 0 14rpx 0 0;
26 | border-left: 1rpx solid #000;
27 | height: 44rpx;
28 | }
29 |
30 | .date-container {
31 | display: flex;
32 | flex-direction: column;
33 | margin: 5rpx 0 0 0;
34 | }
35 |
36 | .month {
37 | line-height: 24rpx;
38 | font-size: 24rpx;
39 | }
40 |
41 | .year {
42 | font-size: 20rpx;
43 | }
44 |
--------------------------------------------------------------------------------
/models/like.js:
--------------------------------------------------------------------------------
1 | import { HTTP } from '../utils/http.js'
2 |
3 | class LikeModel extends HTTP {
4 | constructor() {
5 | super()
6 | }
7 | /**
8 | * @param {string} behavior 状态
9 | * @param {number} artID 电影 id 号
10 | * @param {string} category 状态码
11 | * @return: success
12 | */
13 | like(behavior, artID, category) {
14 | let url = behavior === 'like' ? 'like' : 'like/cancel'
15 | this.request({
16 | url: url,
17 | method: 'POST',
18 | data: {
19 | art_id: artID,
20 | type: category
21 | },
22 | success: data => {
23 | console.log(data)
24 | }
25 | })
26 | }
27 | getClassicLikeStatus(artID, category, success) {
28 | this.request({
29 | url: `classic/${category}/${artID}/favor`,
30 | success: success
31 | })
32 | }
33 | }
34 |
35 | export { LikeModel }
36 |
--------------------------------------------------------------------------------
/components/preview/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | width: 330rpx;
6 | background-color: #ffffff;
7 | }
8 |
9 | .head {
10 | display: flex;
11 | width: 100%;
12 | flex-direction: row;
13 | align-items: center;
14 | justify-content: space-between;
15 | height: 80rpx;
16 | }
17 |
18 | .tag {
19 | margin-left: 20rpx;
20 | margin-top: -2rpx;
21 | height: 40rpx;
22 | width: 72rpx;
23 | font-size: 24rpx;
24 | background-color: #f7f7f7 !important;
25 | }
26 |
27 | .like {
28 | margin-top: 4rpx;
29 | margin-right: 4rpx;
30 | }
31 |
32 | .other-img {
33 | width: 100%;
34 | height: 240rpx;
35 | }
36 |
37 | .music-img {
38 | border-radius: 50%;
39 | width: 240rpx;
40 | height: 240rpx;
41 | }
42 |
43 | .text {
44 | padding: 30rpx;
45 | font-size: 28rpx;
46 | height: 130rpx;
47 | color: #666666;
48 | overflow: hidden;
49 | }
50 |
--------------------------------------------------------------------------------
/components/navi/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | title: {
4 | type: String,
5 | value: '...'
6 | },
7 | latest: { // 最后一期期刊, 是最新一期期刊
8 | type: Boolean,
9 | value: false,
10 | observer: function() {}
11 | },
12 | first: { // 第一期期刊
13 | type: Boolean,
14 | value: false,
15 | observer: function() {}
16 | }
17 | },
18 | data: {
19 | disLeftSrc: 'images/triangle.dis@left.png',
20 | highLeftSrc: 'images/triangle@left.png',
21 | disRightSrc: 'images/triangle.dis@right.png',
22 | highRightSrc: 'images/triangle@right.png'
23 | },
24 | methods: {
25 | onLeft: function() {
26 | if (!this.properties.latest) {
27 | this.triggerEvent('left', {}, {})
28 | }
29 | },
30 | onRight: function() {
31 | if (!this.properties.first) {
32 | this.triggerEvent('right', {}, {})
33 | }
34 | }
35 | }
36 | })
37 |
--------------------------------------------------------------------------------
/components/loading/index.wxss:
--------------------------------------------------------------------------------
1 | .spinner {
2 | width: 40rpx;
3 | height: 40rpx;
4 | position: relative;
5 | /* margin: 100px auto; */
6 | }
7 |
8 | .double-bounce1,
9 | .double-bounce2 {
10 | width: 100%;
11 | height: 100%;
12 | border-radius: 50%;
13 | background-color: #3063b2;
14 | opacity: 0.6;
15 | position: absolute;
16 | top: 0;
17 | left: 0;
18 |
19 | -webkit-animation: bounce 2s infinite ease-in-out;
20 | animation: bounce 2s infinite ease-in-out;
21 | }
22 |
23 | .double-bounce2 {
24 | -webkit-animation-delay: -1s;
25 | animation-delay: -1s;
26 | }
27 |
28 | @-webkit-keyframes bounce {
29 | 0%,
30 | 100% {
31 | -webkit-transform: scale(0);
32 | }
33 | 50% {
34 | -webkit-transform: scale(1);
35 | }
36 | }
37 |
38 | @keyframes bounce {
39 | 0%,
40 | 100% {
41 | transform: scale(0);
42 | -webkit-transform: scale(0);
43 | }
44 | 50% {
45 | transform: scale(1);
46 | -webkit-transform: scale(1);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pages/classic-detail/classic-detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/pages/classic/classic.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | width: 100%;
6 | }
7 |
8 | .header {
9 | display: flex;
10 | flex-direction: row;
11 | justify-content: space-between;
12 | align-items: center;
13 | border-top: 1px solid #f5f5f5;
14 | border-bottom: 1px solid #f5f5f5;
15 | width: 100%;
16 | height: 50px;
17 | }
18 |
19 | .epsoide {
20 | margin-left: 10px;
21 | margin-top: 7px;
22 | }
23 |
24 | .like-container {
25 | display: flex;
26 | flex-direction: row;
27 | justify-content: space-between;
28 | align-items: center;
29 | margin-right: 30rpx;
30 | }
31 |
32 | .like {
33 | margin-right: 30rpx;
34 | margin-top: 12rpx;
35 | }
36 |
37 | .share-btn {
38 | margin-top: 28rpx;
39 | margin-left: 10rpx;
40 | }
41 |
42 | .share {
43 | /* padding:10rpx; */
44 | width: 40rpx;
45 | height: 40rpx;
46 | }
47 |
48 | .navi {
49 | position: absolute;
50 | bottom: 40rpx;
51 | }
52 |
--------------------------------------------------------------------------------
/components/epsoide/index.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | index: {
4 | type: Number,
5 | observer: function(newVal, oldVal, changedPath) { // 数据改变时调用 observer changedPath 属性被改变时执行的函数(可选),也可以写成在 methods 段中定义的方法名字符串, 如:'_propertyChange' 通常 newVal 就是新设置的数据, oldVal 是旧数据
6 | let val = newVal < 10 ? '0' + newVal : newVal
7 | this.setData({
8 | _index: val // 不要修改本身数据 index, 容易无限循环
9 | })
10 | }
11 | }
12 | },
13 | // 组件的初始数据, data 的值也会被页面绑定, data 的值不可以从组件外部设置 用 text 组件会出现双文字的情况
14 | data: {
15 | months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
16 | year: Number,
17 | month: String,
18 | _index: String
19 | },
20 | ready: function() { // 组件生命周期函数, 组件布局完成后执行
21 | let date = new Date()
22 | let month = date.getMonth()
23 | let year = date.getFullYear()
24 | this.setData({
25 | month: this.data.months[month],
26 | year: year
27 | })
28 | }
29 | })
30 |
--------------------------------------------------------------------------------
/pages/classic-detail/classic-detail.wxss:
--------------------------------------------------------------------------------
1 | .header {
2 | width: 100%;
3 | display: flex;
4 | flex-direction: row;
5 | height: 50px;
6 | align-items: center;
7 | justify-content: space-between;
8 | border-top: 1px solid #f5f5f5;
9 | border-bottom: 1px solid #f5f5f5;
10 | }
11 |
12 | .container {
13 | width: 100%;
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | }
18 |
19 | .like {
20 | margin-right: 30rpx;
21 | margin-top: 12rpx;
22 | }
23 |
24 | .like-container {
25 | display: flex;
26 | flex-direction: row;
27 | justify-content: space-between;
28 | align-items: center;
29 | margin-right: 30rpx;
30 | }
31 |
32 | .share-btn {
33 | margin-top: 28rpx;
34 | margin-left: 10rpx;
35 | }
36 |
37 | .share {
38 | /* padding:10rpx; */
39 | width: 40rpx;
40 | height: 40rpx;
41 | }
42 |
43 | .navi {
44 | position: absolute;
45 | bottom: 40rpx;
46 | }
47 |
48 | .epsoide {
49 | margin-left: 10px;
50 | margin-top: 7px;
51 | }
52 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | // app.js
2 | App({
3 | onLaunch: function() {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 | // 登录
9 | wx.login({
10 | success: res => {
11 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
12 | }
13 | })
14 | // 获取用户信息
15 | wx.getSetting({
16 | success: res => {
17 | if (res.authSetting['scope.userInfo']) {
18 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
19 | wx.getUserInfo({
20 | success: res => {
21 | // 可以将 res 发送给后台解码出 unionId
22 | this.globalData.userInfo = res.userInfo
23 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
24 | // 所以此处加入 callback 以防止这种情况
25 | if (this.userInfoReadyCallback) {
26 | this.userInfoReadyCallback(res)
27 | }
28 | }
29 | })
30 | }
31 | }
32 | })
33 | },
34 | globalData: {
35 | userInfo: null
36 | }
37 | })
38 |
--------------------------------------------------------------------------------
/components/classic/music/index.wxss:
--------------------------------------------------------------------------------
1 | @keyframes rotation {
2 | from {
3 | -webkit-transform: rotate(0deg);
4 | }
5 | to {
6 | -webkit-transform: rotate(360deg);
7 | }
8 | }
9 |
10 | .rotation {
11 | transform: rotate(360deg);
12 | animation: rotation 12s linear infinite;
13 | -moz-animation: rotation 12s linear infinite;
14 | -webkit-animation: rotation 12s linear infinite;
15 | -o-animation: rotation 12s linear infinite;
16 | }
17 |
18 | .classic-container {
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | }
23 |
24 | .classic-img {
25 | margin-top: 60rpx;
26 | border-radius: 70%;
27 | width: 422rpx;
28 | height: 422rpx;
29 | overflow: hidden;
30 | }
31 |
32 | .player-img {
33 | position: relative;
34 | bottom: 271rpx;
35 | width: 120rpx;
36 | height: 120rpx;
37 | }
38 |
39 | .tag {
40 | position: relative;
41 | bottom: 160rpx;
42 | right: 310rpx;
43 | width: 44rpx;
44 | height: 127rpx;
45 | }
46 |
47 | .content {
48 | display: block;
49 | margin-top: -90rpx;
50 | max-width: 550rpx;
51 | font-size: 36rpx;
52 | }
53 |
--------------------------------------------------------------------------------
/pages/classic/classic.wxml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/pages/about/about.js:
--------------------------------------------------------------------------------
1 | // pages/about/about.js
2 | Page({
3 |
4 | /**
5 | * Page initial data
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * Lifecycle function--Called when page load
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * Lifecycle function--Called when page is initially rendered
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * Lifecycle function--Called when page show
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * Lifecycle function--Called when page hide
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * Lifecycle function--Called when page unload
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * Page event handler function--Called when user drop down
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * Called when page reach bottom
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * Called when user click on the top right corner to share
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/pages/course/course.js:
--------------------------------------------------------------------------------
1 | // pages/course/course.js
2 | Page({
3 |
4 | /**
5 | * Page initial data
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * Lifecycle function--Called when page load
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * Lifecycle function--Called when page is initially rendered
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * Lifecycle function--Called when page show
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * Lifecycle function--Called when page hide
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * Lifecycle function--Called when page unload
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * Page event handler function--Called when user drop down
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * Called when page reach bottom
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * Called when user click on the top right corner to share
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/models/book.js:
--------------------------------------------------------------------------------
1 | import { HTTP } from '../utils/http-p.js'
2 |
3 | class BookModel extends HTTP {
4 | constructor() {
5 | super()
6 | }
7 | getHotList() {
8 | // return this.request({ // http-p.js/request({}), 里面写了 {}, 导致能传递对象, (解构赋值)
9 | // url: 'book/hot_list',
10 | // data: {
11 | // name: '1',
12 | // age: 18
13 | // },
14 | // method: 'POST'
15 | // })
16 | return this.request({
17 | url: 'book/hot_list'
18 | })
19 | }
20 | search(start, q) {
21 | return this.request({
22 | url: 'book/search?summary=1',
23 | data: {
24 | q: q,
25 | start: start
26 | }
27 | })
28 | }
29 | getMyBookCount(success) {
30 | let params = {
31 | url: '/book/favor/count',
32 | success: success
33 | }
34 | this.request(params)
35 | }
36 | getDetail(bid) {
37 | return this.request({
38 | url: `book/${bid}/detail`
39 | })
40 | }
41 | getLikeStatus(bid) {
42 | return this.request({
43 | url: `book/${bid}/favor`
44 | })
45 | }
46 | getComments(bid) {
47 | return this.request({
48 | url: `book/${bid}/short_comment`
49 | })
50 | }
51 | }
52 |
53 | export { BookModel }
54 |
--------------------------------------------------------------------------------
/promise.md:
--------------------------------------------------------------------------------
1 | # promise
2 |
3 | promise 对象能保存状态, 函数不能保存状态会马上返
4 | 回, 闭包函数能保存状态
5 | 异步代码写在 promise 中
6 |
7 | ```js
8 | const promise = new Promise((resolve, reject) => {
9 | /* promise 状态: pending(进行中) fulfilled(成功) rejected(失败) */
10 | wx.getSystemInfo({
11 | success: res => {
12 | /* 修改状态: pending(进行中) -> fulfilled(成功), 之后会凝固 */
13 | resolve(res)
14 | },
15 | fail: err => {
16 | /* 修改状态: pending(进行中) -> rejected(失败), 之后会凝固 */
17 | reject(err)
18 | }
19 | })
20 | })
21 | /* then(): 拿到异步执行后的结果状态 */
22 | promise.then(
23 | res => {
24 | console.log(res + ' success!')
25 | },
26 | err => {
27 | console.log(err + ' fail!')
28 | }
29 | )
30 | ```
31 |
32 | ```js
33 | bookModel
34 | .getHotList()
35 | .then(res => {
36 | /* res -> api1 result */
37 | console.log(res)
38 | /* invoked api2 */
39 | return bookModel.getMyBookCount()
40 | })
41 | .then(res => {
42 | /* res -> api2 result */
43 | console.log(res)
44 | /* invoked api3 */
45 | return bookModel.getMyBookCount()
46 | })
47 | .then(res => {
48 | /* res -> api3 result */
49 | console.log(res)
50 | })
51 | ```
52 |
--------------------------------------------------------------------------------
/components/book/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | /* 使其不为 static, 参考 */
5 | position: relative;
6 | margin: 30rpx 0 0 0;
7 | width: 240rpx;
8 | height: 360rpx;
9 | box-shadow: 4rpx 4rpx 6rpx #e3e3e3;
10 | }
11 |
12 | .container image {
13 | border-radius: 4rpx;
14 | width: 100%;
15 | height: 100%;
16 | }
17 |
18 | .description {
19 | display: flex;
20 | flex-direction: column;
21 | /* 覆盖 位置重叠, 参照元素为 relative 的元素, 不参考 static */
22 | position: absolute;
23 | bottom: 0;
24 | padding: 5rpx 10rpx 8rpx 15rpx;
25 | border-bottom-right-radius: 4rpx;
26 | border-bottom-left-radius: 4rpx;
27 | /* 真正宽度要加上 panding border */
28 | /* 240rpx - 10prx - 15rpx = 215rpx, 不取奇数, 216rpx */
29 | width: 216rpx;
30 | font-size: 24rpx;
31 | background-color: #fff;
32 | }
33 |
34 | .title {
35 | margin: 10rpx 0 0 0;
36 | text-overflow: ellipsis;
37 | white-space: nowrap;
38 | overflow: hidden;
39 | }
40 |
41 | .author {
42 | margin: -5rpx 0 10rpx 0;
43 | font-size: 20rpx;
44 | color: #999;
45 | text-overflow: ellipsis;
46 | white-space: nowrap;
47 | overflow: hidden;
48 | }
49 |
50 | .foot {
51 | display: flex;
52 | flex-direction: row;
53 | justify-content: flex-end;
54 | font-size: 20rpx;
55 | }
56 |
57 | .footer {
58 | color: #666;
59 | }
60 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/book/book",
4 | "pages/classic/classic",
5 | "pages/my/my",
6 | "pages/book-detail/book-detail",
7 | "pages/about/about",
8 | "pages/course/course",
9 | "pages/classic-detail/classic-detail"
10 | ],
11 | "window": {
12 | "backgroundTextStyle": "light",
13 | "navigationBarBackgroundColor": "#fff",
14 | "navigationBarTitleText": "旧岛小样",
15 | "navigationBarTextStyle": "black",
16 | "navigationStyle": "default"
17 | },
18 | "tabBar": {
19 | "borderStyle": "black",
20 | "selectedColor": "#000",
21 | "backgroundColor": "#fff",
22 | "color": "#c7c7c7",
23 | "list": [
24 | {
25 | "pagePath": "pages/classic/classic",
26 | "selectedIconPath": "/images/tab/classic@highlight.png",
27 | "iconPath": "/images/tab/classic.png",
28 | "text": "流行"
29 | },
30 | {
31 | "pagePath": "pages/book/book",
32 | "selectedIconPath": "/images/tab/book@highlight.png",
33 | "iconPath": "/images/tab/book.png",
34 | "text": "书单"
35 | },
36 | {
37 | "pagePath": "pages/my/my",
38 | "selectedIconPath": "/images/tab/my@highlight.png",
39 | "iconPath": "/images/tab/my.png",
40 | "text": "喜欢"
41 | }
42 | ]
43 | },
44 | "sitemapLocation": "sitemap.json"
45 | }
--------------------------------------------------------------------------------
/pages/book/book.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | width: 100%;
6 | }
7 |
8 | .header {
9 | z-index: 99;
10 | display: flex;
11 | flex-direction: row;
12 | justify-content: center;
13 | align-items: center;
14 | position: fixed;
15 | box-shadow: 0 0 6rpx 0 #e3e3e3;
16 | border-top: 2rpx solid #f5f5f5;
17 | border-bottom: 2rpx solid #f5f5f5;
18 | width: 100%;
19 | height: 100rpx;
20 | background-color: #fff;
21 | }
22 |
23 | .sub-container {
24 | display: flex;
25 | flex-direction: column;
26 | align-items: center;
27 | margin: 100rpx 0 0 0;
28 | background-color: #f5f5f5;
29 | }
30 |
31 | .books-container {
32 | display: flex;
33 | flex-direction: row;
34 | justify-content: space-between;
35 | flex-wrap: wrap;
36 | margin: 10rpx 0 0 0;
37 | padding: 0 90rpx;
38 | }
39 |
40 | .books-container book-cmp {
41 | margin: 0 0 30rpx 0;
42 | }
43 |
44 | .box {
45 | display: flex;
46 | flex-direction: row;
47 | justify-content: center;
48 | align-items: center;
49 | border-radius: 100rpx;
50 | height: 68rpx;
51 | width: 700rpx;
52 | color: #999;
53 | background-color: #f5f5f5;
54 | }
55 |
56 | .box image {
57 | margin: 0 20rpx -4rpx 0;
58 | width: 28rpx;
59 | height: 28rpx;
60 | }
61 |
62 | .head-img {
63 | margin: 40rpx 0 0 0;
64 | width: 106rpx;
65 | height: 34rpx;
66 | }
67 |
--------------------------------------------------------------------------------
/pages/my/my.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 关于我们
15 |
16 |
17 | {{myBooksCount}}
18 | 喜欢的书
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/utils/http-p.js:
--------------------------------------------------------------------------------
1 | import { config } from '../config.js'
2 |
3 | const tips = {
4 | 1: '出现一个错误!',
5 | 1005: 'appkey 无效',
6 | 3000: '期刊不存在'
7 | }
8 |
9 | class HTTP {
10 | request({ url, data = {}, method = 'GET' }) { // 解构 {}
11 | return new Promise((resolve, reject) => {
12 | this._request(url, resolve, reject, data, method) // 必填参数在默认参数之前
13 | })
14 | }
15 | _request(url, resolve, reject, data = {}, method = 'GET') { // 必填参数在默认参数前
16 | wx.request({
17 | url: config.api_blink_url + url,
18 | data: data,
19 | method: method,
20 | header: {
21 | 'content-type': 'application/json',
22 | appkey: config.appkey
23 | },
24 | success: res => {
25 | const code = res.statusCode.toString() // 判断以2(2xx)开头的状态码为正确
26 | if (code.startsWith('2')) {
27 | resolve(res.data)
28 | } else {
29 | reject()
30 | const error_code = res.data.error_code
31 | this._show_error(error_code)
32 | }
33 | },
34 | fail: err => { // 没网络时才调用
35 | reject()
36 | this._show_error(1)
37 | }
38 | })
39 | }
40 | _show_error(error_code) {
41 | if (!error_code) {
42 | error_code = 1
43 | }
44 | const tip = tips[error_code]
45 | wx.showToast({
46 | title: tip ? tip : tips[1],
47 | icon: 'none',
48 | duration: 2000
49 | })
50 | }
51 | }
52 |
53 | export { HTTP }
54 |
--------------------------------------------------------------------------------
/utils/http.js:
--------------------------------------------------------------------------------
1 | import { config } from '../config.js'
2 |
3 | const tips = {
4 | 1: '出现一个错误!',
5 | 1005: 'appkey 无效',
6 | 3000: '期刊不存在'
7 | }
8 |
9 | class HTTP {
10 | constructor() {
11 | this.baseRestUrl = config.api_blink_url
12 | }
13 | request(params) {
14 | let url = this.baseRestUrl + params.url
15 | if (!params.method) {
16 | params.method = 'GET'
17 | }
18 | wx.request({ // wx.request: async request
19 | url: url,
20 | data: params.data,
21 | method: params.method,
22 | header: {
23 | 'content-type': 'application/json',
24 | appkey: config.appkey
25 | },
26 | success: res => { // Receive the result of an asyn call res
27 | const code = res.statusCode.toString()
28 | if (code.startsWith('2')) {
29 | params.success && params.success(res.data) // params.success 是否为 null, 如果不是则执行后面代码
30 | } else {
31 | const error_code = res.data.error_code
32 | this._show_error(error_code)
33 | }
34 | },
35 | fail: err => { // no network invoked, 4xx not invoked
36 | this._show_error(1)
37 | }
38 | })
39 | }
40 | _show_error(error_code) { // wechat no private
41 | if (!error_code) {
42 | error_code = 1
43 | }
44 | const tip = tips[error_code]
45 | wx.showToast({
46 | title: tip ? tip : tips[1],
47 | icon: 'none',
48 | duration: 2000
49 | })
50 | }
51 | }
52 |
53 | export { HTTP }
54 |
--------------------------------------------------------------------------------
/components/search/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
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 |
--------------------------------------------------------------------------------
/components/like/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Description:
3 | * @version:
4 | * @Author: GanEhank
5 | * @Date: 2018-07-07 19:53:30
6 | * @LastEditors: GanEhank
7 | * @LastEditTime: 2019-08-20 01:32:33
8 | */
9 | Component({
10 | properties: { // 组件的属性列表, 需要开放出来的数据
11 | like: {
12 | type: Boolean
13 | },
14 | count: {
15 | type: Number
16 | },
17 | readOnly: {
18 | type: Boolean
19 | }
20 | // myProperty: {
21 | // [properties](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html)
22 | // type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
23 | // value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
24 | // observer: function(newVal, oldVal, changedPath) {
25 | // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
26 | // 通常 newVal 就是新设置的数据, oldVal 是旧数据
27 | // }
28 | // }
29 | },
30 | data: {
31 | yes_url: 'images/like.png',
32 | no_url: 'images/like@dis.png'
33 | },
34 | methods: {
35 | onLike: function(event) {
36 | if (this.properties.readOnly) {
37 | return
38 | }
39 | let like = this.properties.like
40 | let count = this.properties.count
41 | count = like ? count - 1 : count + 1
42 | this.setData({ // setData: modify data inside data, data upgrate
43 | count: count,
44 | like: !like
45 | })
46 | let behavior = this.properties.like ? 'like' : 'cancel'
47 | this.triggerEvent( // triggerEvent: 自定义事件 like: 事件名称 { behavior: behavior }: 传递参数, 设置 detail
48 | 'like',
49 | {
50 | behavior: behavior
51 | },
52 | {}
53 | )
54 | }
55 | }
56 | })
57 |
--------------------------------------------------------------------------------
/components/behaviors/pagination.js:
--------------------------------------------------------------------------------
1 | let paginationBev = Behavior({
2 | properties: {},
3 | data: {
4 | count: 20,
5 | empty: false,
6 | dataArray: [],
7 | total: null,
8 | noneResult: false,
9 | loading: false
10 | },
11 | methods: {
12 | setMoreData: function(dataArray) {
13 | if (dataArray == false) {
14 | this.data.ending = true
15 | if (this.data.dataArray === false) {
16 | this.setData({
17 | empty: true
18 | })
19 | }
20 | }
21 | let temp = this.data.dataArray.concat(dataArray)
22 | this.data.start += this.data.count
23 | this.setData({
24 | dataArray: temp
25 | })
26 | return true
27 | },
28 | setTotal(total) {
29 | this.data.total = total
30 | if (total == 0) {
31 | this.setData({
32 | noneResult: true
33 | })
34 | }
35 | },
36 | hasMore: function() {
37 | if (this.data.dataArray.length >= this.data.total) {
38 | return false
39 | } else {
40 | return true
41 | }
42 | },
43 | getCurrentStart: function() {
44 | return this.data.dataArray.length
45 | },
46 | initPagination: function() {
47 | this.data.total = null
48 | this.setData({
49 | dataArray: [],
50 | noneResult: false,
51 | loading: false
52 | })
53 | },
54 | isLocked() {
55 | return this.data.loading ? true : false
56 | },
57 | locked() {
58 | this.setData({
59 | loading: true
60 | })
61 | },
62 | unLocked() {
63 | this.setData({
64 | loading: false
65 | })
66 | }
67 | }
68 | })
69 |
70 | export { paginationBev }
71 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "Project configuration file",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": false,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true
12 | },
13 | "compileType": "miniprogram",
14 | "libVersion": "2.3.0",
15 | "appid": "wxabcaad13aeed9229",
16 | "projectname": "wx-pure",
17 | "debugOptions": {
18 | "hidedInDevtools": []
19 | },
20 | "isGameTourist": false,
21 | "simulatorType": "wechat",
22 | "simulatorPluginLibVersion": {},
23 | "condition": {
24 | "search": {
25 | "current": -1,
26 | "list": []
27 | },
28 | "conversation": {
29 | "current": -1,
30 | "list": []
31 | },
32 | "plugin": {
33 | "current": -1,
34 | "list": []
35 | },
36 | "game": {
37 | "currentL": -1,
38 | "list": []
39 | },
40 | "miniprogram": {
41 | "current": 5,
42 | "list": [
43 | {
44 | "id": -1,
45 | "name": "book-detail",
46 | "pathName": "pages/book-detail/book-detail",
47 | "query": "bid=7"
48 | },
49 | {
50 | "id": -1,
51 | "name": "classic",
52 | "pathName": "pages/classic/classic",
53 | "query": ""
54 | },
55 | {
56 | "id": -1,
57 | "name": "book-detail",
58 | "pathName": "pages/book-detail/book-detail",
59 | "query": "bid=1120"
60 | },
61 | {
62 | "id": -1,
63 | "name": "book",
64 | "pathName": "pages/book/book",
65 | "query": ""
66 | },
67 | {
68 | "id": -1,
69 | "name": "search",
70 | "pathName": "components/search/index",
71 | "query": ""
72 | },
73 | {
74 | "id": -1,
75 | "name": "my",
76 | "pathName": "pages/my/my",
77 | "query": ""
78 | }
79 | ]
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/components/classic/music/index.js:
--------------------------------------------------------------------------------
1 | import { classicBehavior } from '../classic-beh.js'
2 |
3 | let mMgr = wx.getBackgroundAudioManager() // 音乐对象
4 |
5 | Component({
6 | behaviors: [classicBehavior], // 组件的属性列表
7 | properties: {
8 | src: String,
9 | title: String
10 | },
11 | data: {
12 | playing: false,
13 | waittingUrl: 'images/player@waitting.png',
14 | playingUrl: 'images/player@playing.png'
15 | },
16 | attached: function() { // 微信生命周期, 组件进入界面节点树时执行
17 | this._recoverPlaying()
18 | this._monitorSwitch()
19 | },
20 | // hidden 不会触发完整生命周期, 适用于频繁切换; wx:if 会触发完整生命周期, 不大可能改变
21 | // detached: function() { // 微信生命周期, 组件退出界面节点树时执行
22 | // wx.pauseBackgroundAudio()
23 | // },
24 | methods: {
25 | onPlay: function(event) {
26 | if (!this.data.playing) {
27 | this.setData({
28 | playing: true
29 | })
30 | if (mMgr.src === this.properties.src) {
31 | mMgr.play()
32 | } else {
33 | mMgr.src = this.properties.src
34 | }
35 | mMgr.title = this.properties.title
36 | } else {
37 | this.setData({
38 | playing: false
39 | })
40 | mMgr.pause()
41 | }
42 | },
43 | _recoverPlaying: function() {
44 | if (mMgr.paused) {
45 | this.setData({
46 | playing: false
47 | })
48 | return
49 | }
50 | if (mMgr.src === this.properties.src) {
51 | if (!mMgr.paused) {
52 | this.setData({
53 | playing: true
54 | })
55 | }
56 | }
57 | },
58 | _monitorSwitch: function() {
59 | mMgr.onPlay(() => {
60 | this._recoverPlaying()
61 | })
62 | mMgr.onPause(() => {
63 | this._recoverPlaying()
64 | })
65 | mMgr.onStop(() => {
66 | this._recoverPlaying()
67 | })
68 | mMgr.onEnded(() => {
69 | this._recoverPlaying()
70 | })
71 | }
72 | }
73 | })
74 |
--------------------------------------------------------------------------------
/pages/my/my.js:
--------------------------------------------------------------------------------
1 | import { ClassicModel } from '../../models/classic.js'
2 | import { BookModel } from '../../models/book.js'
3 |
4 | let classicModel = new ClassicModel()
5 | let bookModel = new BookModel()
6 |
7 | Page({
8 | data: {
9 | hasUserInfo: true,
10 | userInfo: null,
11 | classics: [],
12 | myBooksCount: 0
13 | },
14 | onShow: function() { // 生命周期函数--监听页面加载
15 | this.getMyFavor()
16 | this.hasGottenUserInfo()
17 | this.getMyBookCount()
18 | },
19 | getMyBookCount() {
20 | bookModel.getMyBookCount(data => {
21 | this.setData({
22 | myBooksCount: data.count
23 | })
24 | })
25 | },
26 | hasGottenUserInfo: function() {
27 | wx.getSetting({ // 获取用户的当前设置
28 | success: data => {
29 | if (data.authSetting['scope.userInfo']) { // 如果用户已经授权
30 | wx.getUserInfo({
31 | success: data => {
32 | this.setData({
33 | hasUserInfo: true,
34 | userInfo: data.userInfo
35 | })
36 | }
37 | })
38 | } else {
39 | this.setData({
40 | hasUserInfo: false
41 | })
42 | }
43 | }
44 | })
45 | },
46 | onGetUserInfo: function(event) {
47 | let userInfo = event.detail.userInfo
48 | if (userInfo) {
49 | this.setData({
50 | hasUserInfo: true,
51 | userInfo: userInfo
52 | })
53 | }
54 | },
55 | getMyFavor: function() {
56 | classicModel.getMyFavor(data => {
57 | this.setData({
58 | classics: data
59 | })
60 | })
61 | },
62 | onPreviewTap: function(event) {
63 | wx.navigateTo({
64 | url: '/pages/classic-detail/classic-detail?cid=' + event.detail.cid + '&type=' + event.detail.type
65 | })
66 | },
67 | onJumpToAbout: function() {
68 | wx.navigateTo({
69 | url: '/pages/about/about'
70 | })
71 | },
72 | onStudy: function() {
73 | wx.navigateTo({
74 | url: '/pages/course/course'
75 | })
76 | },
77 | onShareAppMessage() {}
78 | })
79 |
--------------------------------------------------------------------------------
/pages/book/book.js:
--------------------------------------------------------------------------------
1 | import { BookModel } from '../../models/book.js'
2 | import { random } from '../../utils/util.js'
3 |
4 | let bookModel = new BookModel()
5 |
6 | Page({
7 | data: {
8 | searchPanel: false,
9 | books: Object,
10 | more: false // 加载更多
11 | },
12 | onReachBottom: function() {
13 | this.setData({
14 | more: random(16) // 改成 true, random() 保证 more 的值是变化的
15 | })
16 | },
17 | onLoad: function(options) { // Lifecycle function--Called when page load
18 | // const promise = new Promise((resolve, reject) => { // promise 对象能保存状态, 函数不能保存状态会马上返回, 闭包函数能保存状态 异步代码写在 promise 中
19 | // wx.getSystemInfo({ // promise 状态: pending(进行中) fulfilled(成功) rejected(失败)
20 | // success: res => {
21 | // resolve(res) // 修改状态: pending(进行中) -> fulfilled(成功), 之后会凝固
22 | // },
23 | // fail: err => {
24 | // reject(err) // 修改状态: pending(进行中) -> rejected(失败), 之后会凝固
25 | // }
26 | // })
27 | // })
28 |
29 | // promise.then( // then(): 拿到异步执行后的结果状态
30 | // res => {
31 | // console.log(res + ' success!')
32 | // },
33 | // err => {
34 | // console.log(err + ' fail!')
35 | // }
36 | // )
37 |
38 | // 链式调用 api1, api2, api3
39 | // bookModel
40 | // .getHotList()
41 | // .then(res => {
42 | // console.log(res) // res -> api1 结果
43 | // return bookModel.getMyBookCount() // api2 调用
44 | // })
45 | // .then(res => {
46 | // console.log(res) // res -> api2 结果
47 | // return bookModel.getMyBookCount() // api3 调用
48 | // })
49 | // .then(res => {
50 | // console.log(res) // res -> api3 结果
51 | // })
52 |
53 | bookModel
54 | .getHotList()
55 | .then(res => {
56 | this.setData({
57 | books: res
58 | })
59 | })
60 | },
61 | onActivateSearch: function() {
62 | this.setData({
63 | searchPanel: true
64 | })
65 | },
66 | onCancel: function() {
67 | this.setData({
68 | searchPanel: false
69 | })
70 | },
71 | onShareAppMessage() {}
72 | })
73 |
--------------------------------------------------------------------------------
/pages/my/my.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | }
6 |
7 | .bg {
8 | width: 750rpx;
9 | height: 574rpx;
10 | }
11 |
12 | .avatar-position {
13 | position: absolute;
14 | top: 255rpx;
15 | }
16 |
17 | .my-img {
18 | width: 120rpx;
19 | height: 120rpx;
20 | }
21 |
22 | .avatar-container {
23 | display: flex;
24 | flex-direction: column;
25 | align-items: center;
26 | }
27 |
28 | .avatar {
29 | width: 120rpx;
30 | height: 120rpx;
31 | border-radius: 50%;
32 | /* margin-bottom: 10rpx; */
33 | }
34 |
35 | .about-container {
36 | padding: 0 100rpx;
37 | width: 550rpx;
38 | display: flex;
39 | flex-direction: row;
40 | justify-content: space-between;
41 | position: absolute;
42 | top: 440rpx;
43 | }
44 |
45 | .about-us image {
46 | width: 34rpx;
47 | height: 34rpx;
48 | }
49 | .preview-container {
50 | margin-top: 30rpx;
51 | display: flex;
52 | flex-direction: row;
53 | padding: 0 30rpx;
54 | flex-wrap: wrap;
55 | justify-content: space-between;
56 | }
57 |
58 | .preview {
59 | margin-bottom: 30rpx;
60 | }
61 | .about-us {
62 | display: flex;
63 | flex-direction: column;
64 | align-items: center;
65 | justify-content: space-between;
66 | }
67 |
68 | .book-num {
69 | font-size: 36rpx;
70 | color: #000000;
71 | }
72 |
73 | .description {
74 | font-size: 24rpx;
75 | color: #999999;
76 | }
77 |
78 | .about-container > view:nth-child(2) {
79 | margin-top: -5rpx;
80 | }
81 |
82 | .like-container {
83 | /* margin-top:30rpx; */
84 | width: 100%;
85 | margin-top: -13rpx;
86 | display: flex;
87 | flex-direction: column;
88 | align-items: center;
89 | background-color: #f5f5f5;
90 | }
91 |
92 | .headline {
93 | margin-top: 30rpx;
94 | width: 97rpx;
95 | height: 42rpx;
96 | }
97 |
98 | .study {
99 | width: 88rpx;
100 | height: 88rpx;
101 | position: absolute;
102 | top: 40rpx;
103 | right: 45rpx;
104 | }
105 |
106 | .test {
107 | background-color: red !important;
108 | border-radius: 15px !important;
109 | }
110 |
--------------------------------------------------------------------------------
/pages/classic-detail/classic-detail.js:
--------------------------------------------------------------------------------
1 | // pages/classic/classic.js
2 | import { ClassicModel } from '../../models/classic.js'
3 | import { LikeModel } from '../../models/like.js'
4 |
5 | let classicModel = new ClassicModel()
6 | let likeModel = new LikeModel()
7 |
8 | Component({
9 | properties: {},
10 | data: {
11 | classic: null,
12 | latest: true,
13 | first: false,
14 | like: false,
15 | count: 0
16 | },
17 | methods: {
18 | onLoad: function(options) {
19 | let cid = options.cid
20 | let type = options.type
21 | classicModel.getById(cid, type, data => {
22 | this._getLikeStatus(data.id, data.type)
23 | this.setData({
24 | classic: data
25 | })
26 | })
27 | },
28 | onPrevious: function(event) {
29 | let index = this.data.classic.index
30 | classicModel.getPrevious(index, data => {
31 | if (data) {
32 | this._getLikeStatus(data.id, data.type)
33 | this.setData({
34 | classic: data,
35 | latest: classicModel.isLatest(data.index),
36 | first: classicModel.isFirst(data.index)
37 | })
38 | } else {
39 | console.log('not more classic')
40 | }
41 | })
42 | },
43 | onNext: function(event) {
44 | let index = this.data.classic.index
45 | classicModel.getNext(index, data => {
46 | if (data) {
47 | this._getLikeStatus(data.id, data.type)
48 | this.setData({
49 | classic: data,
50 | latest: classicModel.isLatest(data.index),
51 | first: classicModel.isFirst(data.index)
52 | })
53 | } else {
54 | console.log('not more classic')
55 | }
56 | })
57 | },
58 | onLike: function(event) {
59 | let like_or_cancel = event.detail.behavior
60 | likeModel.like(like_or_cancel, this.data.classic.id, this.data.classic.type)
61 | },
62 | _getLikeStatus: function(cid, type) {
63 | likeModel.getClassicLikeStatus(cid, type, data => {
64 | this.setData({
65 | like: data.like_status,
66 | count: data.fav_nums
67 | })
68 | })
69 | },
70 | onShareAppMessage() {}
71 | }
72 | })
73 |
--------------------------------------------------------------------------------
/models/classic.js:
--------------------------------------------------------------------------------
1 | import { HTTP } from '../utils/http.js'
2 |
3 | class ClassicModel extends HTTP {
4 | prefix = 'classic'
5 | constructor() {
6 | super()
7 | }
8 | getLatest(sCallback) { // 获取最新的期刊, 也就是最大的期刊号,可看作是最后一期期刊
9 | // this.request() is async, can't return res, invoked HTTP request()
10 | this.request({
11 | url: 'classic/latest',
12 | success: res => {
13 | let key = this._fullKey(res.index) // key 值加盐,用来定义名字
14 | wx.setStorageSync(key, res) // 缓存内容
15 | this._setLatestIndex(res.index) // 缓存刊号,用来判断是否是最后一期期刊
16 | sCallback(res) // 回调函数回传回去
17 | }
18 | })
19 | }
20 | getById(cid, type, success) {
21 | let params = {
22 | url: 'classic/' + type + '/' + cid,
23 | success: success
24 | }
25 | this.request(params)
26 | }
27 | getClassic(index, next_or_previous, sCallback) { // 获取下一期或者上一期期刊
28 | let key = next_or_previous === 'next' ? this._fullKey(index + 1) : this._fullKey(index - 1)
29 | let classic = wx.getStorageSync(key)
30 | if (!classic) {
31 | this.request({
32 | url: `classic/${index}/${next_or_previous}`,
33 | success: res => {
34 | let key = this._fullKey(res.index)
35 | wx.setStorageSync(key, res)
36 | sCallback(res)
37 | }
38 | })
39 | } else {
40 | sCallback(classic)
41 | }
42 | }
43 | getMyFavor(success) {
44 | let params = {
45 | url: 'classic/favor',
46 | success: success
47 | }
48 | this.request(params)
49 | }
50 | isFirst(index) { // 是否是最新一期期刊
51 | return index === 1 ? true : false
52 | }
53 | isLatest(index) { // 是否是最后一期期刊
54 | let latestIndex = this._getLastIndex(index)
55 | return latestIndex === index ? true : false
56 | }
57 | _fullKey(partKey) { // key 值加盐,用来定义名字
58 | let key = this.prefix + '-' + partKey
59 | return key
60 | }
61 | _setLatestIndex(index) { // 缓存 latest 刊号
62 | let key = this._fullKey('latest-' + index)
63 | wx.setStorageSync(key, index)
64 | }
65 | _getLastIndex(index) { // 读取 latest 刊号缓存, 获取刊号
66 | let key = this._fullKey('latest-' + index)
67 | let latestIndex = wx.getStorageSync(key)
68 | return latestIndex
69 | }
70 | }
71 |
72 | export { ClassicModel }
73 |
--------------------------------------------------------------------------------
/pages/classic/classic.js:
--------------------------------------------------------------------------------
1 | import { ClassicModel } from '../../models/classic.js'
2 | import { LikeModel } from '../../models/like.js'
3 |
4 | let classicModel = new ClassicModel() // Instantiated object
5 | let likeModel = new LikeModel()
6 |
7 | Page({
8 | data: {
9 | classic: null,
10 | likeCount: 0,
11 | likeStatus: false,
12 | first: false,
13 | latest: true
14 | },
15 | onLoad: function(options) { // Lifecycle function--listening page load
16 | // wx.request({ // async request
17 | // url: 'http://bl.7yue.pro/v1/classic/latest',
18 | // header: {
19 | // appkey: 'GgRhTjUNUYn1fHke'
20 | // },
21 | // success: (res) => { // Receive the result of an asyn call res
22 | // console.log(res)
23 | // console.log(this.data.likeCount)
24 | // console.log(this.res.count)
25 | // }
26 | // })
27 |
28 | // 使用回调函数剥夺了 return 能力, 不能赋值操作, promise 能解决且带有 return 能力, 回调函数能获取值 let a = ...
29 | // classicModel.getClassic() 是异步,不能用同步方式调用, 里面没有 return, let latest = classicModel.getClassic()
30 | classicModel.getLatest(res => {
31 | // console.log(res)
32 | // this._getLikeStatus(res.id, res.type)
33 | this.setData({ // setData: modify data inside data, data update
34 | classic: res,
35 | likeCount: res.fav_nums,
36 | likeStatus: res.like_status
37 | })
38 | })
39 | },
40 | onLike: function(event) {
41 | let behavior = event.detail.behavior // 获取 like/index.js 传过来的参数
42 | likeModel.like(behavior, this.data.classic.id, this.data.classic.type)
43 | },
44 | onPrevious: function() {
45 | this._updateClassic('previous')
46 | },
47 | onNext: function() {
48 | this._updateClassic('next')
49 | },
50 | _updateClassic: function(nextOrPrevious) {
51 | let index = this.data.classic.index
52 | classicModel.getClassic(index, nextOrPrevious, res => {
53 | this._getLikeStatus(res.id, res.type)
54 | this.setData({
55 | classic: res,
56 | latest: classicModel.isLatest(res.index),
57 | first: classicModel.isFirst(res.index)
58 | })
59 | })
60 | },
61 | _getLikeStatus: function(artID, category) {
62 | likeModel.getClassicLikeStatus(artID, category, data => {
63 | this.setData({
64 | likeStatus: data.like_status,
65 | likeCount: data.fav_nums
66 | })
67 | })
68 | }
69 | })
70 |
--------------------------------------------------------------------------------
/pages/book-detail/book-detail.js:
--------------------------------------------------------------------------------
1 | import { BookModel } from '../../models/book.js'
2 | import { LikeModel } from '../../models/like.js'
3 | import { CommentModel } from '../../models/comment.js'
4 |
5 | let bookModel = new BookModel()
6 | let commentModel = new CommentModel()
7 | let likeModel = new LikeModel()
8 |
9 | Page({
10 | data: {
11 | book: null,
12 | comments: [],
13 | noComment: true,
14 | posting: false,
15 | like: false,
16 | count: 0
17 | },
18 | onLoad: function(options) { // Lifecycle function--Called when page load
19 | wx.showLoading()
20 | // pages 组件传入的参数在 options 中
21 | const bid = options.bid // 接受从外部传来的参数
22 | const detail = bookModel.getDetail(bid)
23 | const comments = bookModel.getComments(bid)
24 | const likeStatus = bookModel.getLikeStatus(bid)
25 | // detail.then(res => {
26 | // this.setData({
27 | // book: res
28 | // })
29 | // })
30 | // comments.then(res => {
31 | // this.setData({
32 | // noComment: res.comments == false ? true : false,
33 | // comments: res.comments
34 | // })
35 | // })
36 | // likeStatus.then(res => {
37 | // this.setData({
38 | // like: res.like_status,
39 | // count: res.fav_nums
40 | // })
41 | // })
42 | Promise.all([detail, comments, likeStatus]).then(res => { // Promise.all 三个异步都完成后才调用 then
43 | // console.log(res)
44 | this.setData({
45 | book: res[0],
46 | comments: res[1].comments,
47 | likeStatus: res[2].like_status,
48 | likeCount: res[2].fav_nums
49 | })
50 | wx.hideLoading()
51 | })
52 | },
53 | onFakePost: function() {
54 | this.setData({
55 | posting: true
56 | })
57 | },
58 | onCancel: function() {
59 | this.setData({
60 | posting: false
61 | })
62 | },
63 | onLike: function(event) {
64 | let like_or_cancel = event.detail.behavior
65 | likeModel.like(like_or_cancel, this.data.book.id, 400)
66 | },
67 | onPost: function(event) {
68 | // event.detail.value: input 输入的值
69 | // event.detail.text: 事件触发定义的值
70 | let comment = event.detail.value || event.detail.text
71 | if (!comment) {
72 | return
73 | }
74 | if (comment.length > 12) {
75 | wx.showToast({
76 | title: '短评最多12个字',
77 | icon: 'none'
78 | })
79 | return
80 | }
81 | commentModel
82 | .postComment(this.data.book.id, comment)
83 | .then(res => {
84 | wx.showToast({
85 | title: '+ 1',
86 | icon: 'none'
87 | })
88 | this.data.comments.unshift({
89 | content: comment,
90 | nums: 1
91 | })
92 | this.setData({
93 | comments: this.data.comments,
94 | noComment: false
95 | })
96 | })
97 | },
98 | // Called when user click on the top right corner to share
99 | onShareAppMessage: function() {}
100 | })
101 |
--------------------------------------------------------------------------------
/components/search/index.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | width: 100%;
6 | /* padding-left:15px; */ /* padding-right:15px; */
7 | }
8 |
9 | .history {
10 | width: 690rpx;
11 | margin: 40rpx 0 20rpx 0;
12 | display: flex;
13 | font-size: 14px;
14 | margin-top: 160rpx;
15 | flex-direction: column;
16 | }
17 |
18 | .hot-search {
19 | margin-top: 70rpx;
20 | }
21 |
22 | .title {
23 | line-height: 15px;
24 | display: flex;
25 | flex-direction: row;
26 | align-items: center;
27 | /* margin-left:100px; */
28 | }
29 |
30 | .search-container {
31 | display: inline-flex;
32 | flex-direction: row;
33 | align-items: center;
34 | background-color: #f5f5f5;
35 | border-radius: 50px;
36 | margin-left: 20rpx;
37 | /* margin-left: */
38 | }
39 |
40 | .books-container book-cmp {
41 | margin-bottom: 25rpx;
42 | }
43 |
44 | .cancel-img {
45 | width: 14px;
46 | height: 14px;
47 | margin-right: 10px;
48 | }
49 |
50 | .books-container {
51 | width: 570rpx;
52 | margin-top: 100rpx;
53 | display: flex;
54 | flex-direction: row;
55 | flex-wrap: wrap;
56 | padding: 0 90rpx 0 90rpx;
57 | justify-content: space-between;
58 | }
59 |
60 | .loading {
61 | margin: 50rpx 0 50rpx 0;
62 | }
63 |
64 | .loading-center {
65 | position: absolute;
66 | top: 50%;
67 | left: 50%;
68 | }
69 |
70 | .empty-tip {
71 | display: inline-block;
72 | width: 100%;
73 | text-align: center;
74 | position: absolute;
75 | top: 50%;
76 | /* left: 275rpx; */
77 | }
78 |
79 | .icon {
80 | width: 14px;
81 | height: 14px;
82 | margin-left: 12px;
83 | margin-right: 8px;
84 | }
85 |
86 | .in-bar {
87 | color: #999;
88 | }
89 |
90 | .cancel {
91 | line-height: 34px;
92 | width: 60px;
93 | /* margin-left:10px; */
94 | text-align: center;
95 | display: inline-block;
96 | border: none;
97 | }
98 |
99 | .chunk {
100 | height: 15px;
101 | width: 5px;
102 | background-color: #000;
103 | display: inline-block;
104 | margin-right: 10px;
105 | }
106 |
107 | .tags {
108 | /* padding-left:15px; */
109 | display: flex;
110 | flex-direction: row;
111 | flex-wrap: wrap;
112 | /* justify-content: flex-start; */
113 | margin-top: 24rpx;
114 | padding-left: 15px;
115 | width: 630rpx;
116 | }
117 |
118 | .tags tag-cmp {
119 | margin-right: 10px;
120 | margin-bottom: 10px;
121 | /* padding-bottom: 10px; */ /* margin-right:6px; */
122 | }
123 |
124 | .header {
125 | background-color: #ffffff;
126 | position: fixed;
127 | height: 100rpx;
128 | border-top: 1px solid #f5f5f5;
129 | border-bottom: 1px solid #f5f5f5;
130 | display: flex;
131 | flex-direction: row;
132 | width: 750rpx;
133 | align-items: center;
134 | z-index: 99;
135 | /* padding-left:15px; */ /* padding-right:5px; */
136 | }
137 |
138 | .bar {
139 | border-top-right-radius: 15px;
140 | border-bottom-right-radius: 15px;
141 | display: inline-block;
142 | height: 34px;
143 | /* width:100%; */
144 | width: 500rpx;
145 | font-size: 14px;
146 | }
147 |
148 | .test {
149 | background-color: #000;
150 | }
151 |
--------------------------------------------------------------------------------
/pages/book-detail/book-detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{book.title}}
6 | {{book.author}}
7 |
8 |
9 | 短评
10 | 还没有短评
11 |
20 |
21 |
22 | 内容简介
23 |
24 | {{util.format(book.summary)}}
25 |
26 |
27 | 书本信息
28 |
29 |
30 | 出版社
31 | 出版年
32 | 页数
33 | 定价
34 | 装帧
35 |
36 |
37 | {{book.publisher}}
38 | {{book.pubdate}}
39 | {{book.pages}}
40 | {{book.price}}
41 | {{book.binding}}
42 |
43 |
44 |
45 |
46 |
47 |
48 | 输入短评
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
64 |
73 |
74 |
75 |
76 |
77 |
78 | // wxml 写 js, 尽量用 javascript 原生语法 不能用 es6 语法
79 | var limit = function(array, length) {
80 | return array.slice(0, length)
81 | }
82 | var format = function(text){
83 | if(!text){
84 | return
85 | }
86 | var reg = getRegExp('\\\\n','g')
87 | var text = text.replace(reg,'\n ')
88 | return text
89 | }
90 | var heightlight = function(index) {
91 | if(index == 0) {
92 | return 'ex-tag1'
93 | }
94 | if(index == 1) {
95 | return 'ex-tag2'
96 | }
97 | return ''
98 | }
99 | module.exports = {
100 | limit: limit,
101 | format: format,
102 | heightlight: heightlight
103 | }
104 |
--------------------------------------------------------------------------------
/components/search/index.js:
--------------------------------------------------------------------------------
1 | // import { HTTP } from '../../utils/http'
2 | import { KeywordModel } from '../../models/keyword'
3 | import { BookModel } from '../../models/book'
4 | import { paginationBev } from '../behaviors/pagination.js'
5 |
6 | // let http = new HTTP()
7 | const keyModel = new KeywordModel()
8 | const bookModel = new BookModel()
9 |
10 | Component({
11 | behaviors: [paginationBev],
12 | properties: {
13 | more: {
14 | type: String,
15 | observer: 'loadMore'
16 | }
17 | },
18 | data: {
19 | historyWords: [],
20 | hotKeys: [],
21 | q: '',
22 | loading: false, // 锁, 防止多次无用的加载
23 | loadingCenter: false,
24 | // dataArray: [],
25 | searching: false
26 | },
27 | attached: function() { // 组件进入界面 节点树时执行
28 | this.setData({
29 | historyWords: keyModel.getHistory()
30 | })
31 | keyModel
32 | .getHot()
33 | .then(res => {
34 | this.setData({
35 | hotKeys: res.hot
36 | })
37 | })
38 | },
39 | methods: {
40 | loadMore: function() {
41 | if (!this.data.q) {
42 | return
43 | }
44 | if (this.isLocked()) {
45 | return
46 | }
47 | let hasMore = this.hasMore()
48 | if (!hasMore) {
49 | return
50 | }
51 | if (this.hasMore()) {
52 | this.locked()
53 | // const length = this.data.dataArray.length
54 | bookModel
55 | .search(this.getCurrentStart(), this.data.q)
56 | .then(res => {
57 | // const tempArray = this.data.dataArray.concat(res.books)
58 | this.setMoreData(res.books)
59 | this.unLocked()
60 | },
61 | () => {
62 | this.unLocked() // 断网后避免死锁
63 | }
64 | )
65 | }
66 | // http.request({
67 | // url: 'book/search?summary=1',
68 | // data: {
69 | // q: this.data.q,
70 | // start: this.getCurrentStart()
71 | // },
72 | // success: data => {
73 | // this.setMoreData(data.books)
74 | // this.setData({
75 | // loading: false
76 | // })
77 | // }
78 | // })
79 | },
80 | _closeResult() {
81 | this.setData({
82 | searching: false,
83 | q: ''
84 | })
85 | },
86 | onCancel: function() {
87 | this.initPagination()
88 | this.triggerEvent('cancel', {}, {})
89 | },
90 | onDelete: function() {
91 | this.initPagination()
92 | this._closeResult()
93 | },
94 | onConfirm: function(event) {
95 | this._showResult()
96 | this._showLoadingCenter()
97 | const q = event.detail.value || event.detail.text // event.detail.value: input 输入的值, event.detail.text: 事件触发定义的值
98 | this.setData({
99 | q: q
100 | })
101 | bookModel
102 | .search(0, q)
103 | .then(res => {
104 | this.setMoreData(res.books)
105 | this.setTotal(res.total)
106 | keyModel.addToHistory(q)
107 | this._hideLoadingCenter()
108 | })
109 | // http.request({
110 | // url: 'book/search?summary=1',
111 | // data: {
112 | // q: q,
113 | // start: this.getCurrentStart()
114 | // },
115 | // success: data => {
116 | // if (!(data.books == false)) {
117 | // keyModel.addToHistory(q)
118 | // }
119 | // this.setMoreData(data.books)
120 | // this.setData({
121 | // q: q,
122 | // loadingCenter: false
123 | // })
124 | // }
125 | // })
126 | },
127 | _showResult() {
128 | this.setData({
129 | searching: true
130 | })
131 | },
132 | _showLoadingCenter() {
133 | this.setData({
134 | loadingCenter: true
135 | })
136 | },
137 | _hideLoadingCenter() {
138 | this.setData({
139 | loadingCenter: false
140 | })
141 | }
142 | }
143 | })
144 |
--------------------------------------------------------------------------------
/pages/book-detail/book-detail.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | width: 100%;
3 | background-color: #f5f5f5;
4 | }
5 |
6 | .head {
7 | display: flex;
8 | flex-direction: column;
9 | align-items: center;
10 | padding-top: 40rpx;
11 | padding-bottom: 40rpx;
12 | background-color: #fff;
13 | }
14 |
15 | .title {
16 | margin-top: 20rpx;
17 | font-size: 38rpx;
18 | font-weight: 600;
19 | color: #2f2f2f;
20 | }
21 |
22 | .shadow {
23 | color: #999;
24 | }
25 |
26 | .author {
27 | font-size: 28rpx;
28 | color: #999;
29 | }
30 |
31 | .head image {
32 | width: 200rpx;
33 | height: 300rpx;
34 | box-shadow: 4rpx 4rpx 6rpx #e3e3e3;
35 | }
36 |
37 | .sub-container {
38 | display: flex;
39 | flex-direction: column;
40 | align-items: center;
41 | margin-top: 30rpx;
42 | padding: 30rpx;
43 | width: 690rpx;
44 | background-color: #fff;
45 | }
46 |
47 | .comment-container {
48 | display: flex;
49 | flex-direction: row;
50 | justify-content: flex-start;
51 | flex-wrap: wrap;
52 | padding: 0 30rpx;
53 | width: 100%;
54 | }
55 |
56 | .content {
57 | font-weight: 500;
58 | text-indent: 58rpx;
59 | color: #000;
60 | }
61 |
62 | .headline {
63 | margin-bottom: 20rpx;
64 | font-size: 30rpx;
65 | font-weight: 600;
66 | color: #2f2f2f;
67 | }
68 |
69 | .post-container {
70 | display: flex;
71 | flex-direction: row;
72 | justify-content: space-between;
73 | align-items: center;
74 | position: fixed;
75 | bottom: 0;
76 | box-shadow: 1px -1px 1px #e3e3e3;
77 | width: 690rpx;
78 | height: 100rpx;
79 | padding: 0 30rpx;
80 | background-color: #fff;
81 | }
82 |
83 | .post-fake {
84 | display: flex;
85 | flex-direction: row;
86 | align-items: center;
87 | padding-left: 20rpx;
88 | border-radius: 15px;
89 | border: 1px solid #999;
90 | height: 60rpx;
91 | width: 460rpx;
92 | font-size: 22rpx;
93 | }
94 |
95 | .post {
96 | margin: 30rpx auto;
97 | padding-left: 25rpx;
98 | height: 56rpx;
99 | width: 690rpx;
100 | border-radius: 15px;
101 | background-color: #f5f5f5;
102 | }
103 |
104 | .posting-container {
105 | display: flex;
106 | flex-direction: column;
107 | align-items: center;
108 | z-index: 999;
109 | position: fixed;
110 | bottom: 0;
111 | width: 100%;
112 | background-color: #fff;
113 | }
114 |
115 | .like {
116 | margin-right: 30rpx;
117 | margin-top: 10rpx;
118 | }
119 |
120 | .like-container {
121 | display: flex;
122 | flex-direction: row;
123 | justify-content: space-between;
124 | align-items: center;
125 | }
126 |
127 | .share-btn {
128 | margin-top: 28rpx;
129 | margin-left: 10rpx;
130 | }
131 |
132 | .share {
133 | width: 40rpx;
134 | height: 40rpx;
135 | }
136 |
137 | .posting-container .comment-container {
138 | padding: 0 30rpx;
139 | width: 690rpx;
140 | }
141 |
142 | .post-header {
143 | display: flex;
144 | flex-direction: row;
145 | align-items: center;
146 | justify-content: space-between;
147 | border-top: 1px solid #f5f5f5;
148 | border-bottom: 1px solid #f5f5f5;
149 | width: 100%;
150 | height: 100rpx;
151 | }
152 |
153 | .post-header > text:first-child {
154 | font-size: 28rpx;
155 | color: #bbb;
156 | }
157 |
158 | .cancel {
159 | color: #666;
160 | }
161 |
162 | .post-header text {
163 | padding: 25rpx;
164 | }
165 |
166 | .num {
167 | margin-left: 5px;
168 | font-size: 22rpx;
169 | color: #aaa;
170 | }
171 |
172 | .comment-container > tag-cmp:nth-child(1) view {
173 | background-color: #fffbdd;
174 | }
175 |
176 | .comment-container > tag-cmp:nth-child(2) view {
177 | background-color: #eefbff !important;
178 | }
179 |
180 | .tag {
181 | margin-right: 15rpx;
182 | margin-bottom: 10rpx;
183 | border-radius: 30px !important;
184 | }
185 |
186 | .ex-tag1 {
187 | background-color: #fffbdd !important;
188 | }
189 |
190 | .ex-tag2 {
191 | background-color: #eefbff !important;
192 | }
193 |
194 | .posting-container .comment-container {
195 | padding: 40rpx 30rpx 0 30rpx;
196 | }
197 |
198 | .detail-contaner {
199 | display: flex;
200 | flex-direction: row;
201 | justify-content: flex-start;
202 | margin-bottom: 100rpx;
203 | width: 100%;
204 | font-size: 28rpx;
205 | color: #666;
206 | }
207 |
208 | .vertical {
209 | display: flex;
210 | flex-direction: column;
211 | }
212 |
213 | .vertical-1 {
214 | align-items: flex-end;
215 | }
216 |
217 | .description {
218 | margin-right: 30rpx;
219 | color: #999;
220 | }
221 |
222 | .tip {
223 | margin-top: 20rpx;
224 | margin-bottom: 30rpx;
225 | width: 694rpx;
226 | height: 130rpx;
227 | }
228 |
--------------------------------------------------------------------------------
/API.md:
--------------------------------------------------------------------------------
1 | # old-land-flask-api
2 | ## API说明
3 | * 点赞和取消点赞接口需要携带token
4 | * token必须通过小程序的code换取
5 | * 无论是提交数据还是返回数据只支持json
6 | * API遵从严格的HTTP动作并采用标准的 Http Status Code 作为响应状态,建议采用HTTP状态码作为Api调用是否成功的标识,具体异常请通过错误码判断
7 |
8 | - [返回码](README.md#返回码)
9 | * [HTTP 状态码](README.md#HTTP状态码)
10 | * [错误码(error_code)](README.md#错误码)
11 |
12 | - [期刊](README.md#期刊)
13 | * [获取最新一期](README.md#获取最新一期)
14 | * [获取当前一期的下一期](README.md#获取当前一期的下一期)
15 | * [获取某一期详细信息](README.md#获取某一期详细信息)
16 | * [获取当前一期的上一期](README.md#获取当前一期的上一期)
17 | * [获取点赞信息](README.md#获取点赞信息)
18 | * [获取我喜欢的期刊](README.md#获取我喜欢的期刊)
19 |
20 | - [书籍](README.md#书籍)
21 | * [获取热门书籍](README.md#获取热门书籍)
22 | * [获取书籍短评](README.md#获取书籍短评)
23 | * [获取喜欢书籍数量](README.md#获取喜欢书籍数量)
24 | * [获取书籍点赞情况](README.md#获取书籍点赞情况)
25 | * [新增短评](README.md#新增短评)
26 | * [获取热搜关键字](README.md#获取热搜关键字)
27 | * [书籍搜索](README.md#书籍搜索)
28 | * [获取书籍详细信息](README.md#获取书籍详细信息)
29 |
30 | - [点赞](README.md#点赞)
31 | * [进行点赞](README.md#进行点赞)
32 | * [取消点赞](README.md#取消点赞)
33 |
34 | - [小程序登录](README.md#小程序登录)
35 | * [获取token](README.md#获取token)
36 | * [验证token](README.md#验证token)
37 |
38 |
39 | # 返回码
40 | ## HTTP状态码
41 |
42 | | 状态码 | 含义 | 说明 |
43 | | ------ | ------------------------- | -------------------- |
44 | | 200 | OK | 请求成功 |
45 | | 201 | CREATED | 创建成功 |
46 | | 202 | ACCEPTED | 更新成功 |
47 | | 204 | NO CONTENT | 删除成功 |
48 | | 301 | MOVED PERMANENTLY | 永久重定向 |
49 | | 400 | BAD REQUEST | 请求包含不支持的参数 |
50 | | 401 | UNAUTHORIZED | 未授权 |
51 | | 403 | FORBIDDEN | 被禁止访问 |
52 | | 404 | NOT FOUND | 请求的资源不存在 |
53 | | 413 | REQUIRED LENGTH TOO LARGE | 上传的File体积太大 |
54 | | 500 | INTERNAL SERVER ERROR | 内部错误 |
55 |
56 |
57 | ## 错误码
58 |
59 | 请以错误码来判断具体的错误,不要以文字描述作为判断的依据
60 |
61 | >100x 通用类型:
62 |
63 | | 错误码 | 含义 |
64 | | ------ | -------------------- |
65 | | 0 | OK, 成功 |
66 | | 1000 | 输入参数错误 |
67 | | 1001 | 输入的json格式不正确 |
68 | | 1002 | 找不到资源 |
69 | | 1003 | 未知错误 |
70 | | 1004 | 禁止访问 |
71 | | 1005 | 不正确的开发者key |
72 | | 1006 | 服务器内部错误 |
73 |
74 |
75 | >200x 点赞类型
76 |
77 | | 错误码 | 含义 |
78 | | ------ | -------------- |
79 | | 2000 | 你已经点过赞了 |
80 | | 2001 | 你还没点过赞 |
81 |
82 |
83 | >300x 期刊类型
84 |
85 | | 错误码 | 含义 |
86 | | ------ | -------------- |
87 | | 3000 | 该期内容不存在 |
88 |
89 |
90 | # 期刊
91 |
92 | ## 获取最新一期
93 | URL:
94 | >GET /classic/latest
95 |
96 | Response 200:
97 | ```json
98 | {
99 | "content": "人生不能像做菜,把所有的材料准备好才下锅",
100 | "fav_nums": 2,
101 | "id": 8,
102 | "image": "http://127.0.0.1:5000/v1/movie.2.png",
103 | "index": 8,
104 | "like_status": 0,
105 | "pubdate": "2018-08-14",
106 | "title": "李安《饮食男女》",
107 | "type": 100
108 | }
109 | ```
110 |
111 | Response_description:
112 | * content:期刊内容
113 | * fav_nums: 点赞次数
114 | * image: 图片
115 | * index: 期号
116 | * like_status: 是否点赞
117 | * pubdate: 发布日期
118 | * title: 期刊题目
119 | * type: 期刊类型,这里的类型分为:100 电影 200 音乐 300 句子
120 | * id: 期刊在数据中序号,供点赞使用
121 | * 返回期刊的详细信息
122 |
123 | ## 获取当前一期的下一期
124 | URL:
125 | >GET /classic//next
126 |
127 | >demo /classic/2/next
128 |
129 | Parameters:
130 |
131 | * id:id号,必填,必须是正整数
132 |
133 | Response 200:
134 | ```json
135 | {
136 | "content": "你陪我不如蝉夏 越过城市喧嚣",
137 | "fav_nums": 0,
138 | "id": 3,
139 | "image": "http://127.0.0.1:5000/v1/music.2.png",
140 | "index": 3,
141 | "like_status": 0,
142 | "pubdate": "2018-08-14",
143 | "title": "花弼《纸短情长》",
144 | "type": 200,
145 | "url": "http://music.163.com/song/media/outer/url?id=557581284.mp3"
146 | }
147 | ```
148 |
149 | ## 获取某一期详细信息
150 | URL:
151 | >GET /classic//
152 |
153 | >demo /classic/200/1
154 |
155 | Parameters:
156 |
157 | * id:id号,必填,必须是正整数
158 | * type: 类型号,必填,为100,200,300的一种,分别表示电影,音乐,句子
159 |
160 | Response 200:
161 | ```json
162 | {
163 | "content": "岁月长,衣裳薄",
164 | "fav_nums": 0,
165 | "id": 1,
166 | "image": "http://127.0.0.1:5000/v1/music.1.png",
167 | "index": 1,
168 | "like_status": 0,
169 | "pubdate": "2018-08-14",
170 | "title": "杨千嬅《再见二丁目》",
171 | "type": 200,
172 | "url": "http://music.163.com/song/media/outer/url?id=557581284.mp3"
173 | }
174 | ```
175 |
176 | ## 获取当前一期的上一期
177 | URL:
178 | >GET /classic//next
179 |
180 | >demo /classic/5/next
181 |
182 | Parameters:
183 | * id:id号,必填,必须是正整数
184 |
185 | Response 200:
186 | ```json
187 | {
188 | "content": "在变换的生命里,岁月原来是最大的小偷",
189 | "fav_nums": 0,
190 | "id": 4,
191 | "image": "http://127.0.0.1:5000/v1/movie.1.png",
192 | "index": 4,
193 | "like_status": 0,
194 | "pubdate": "2018-08-14",
195 | "title": "罗启锐《岁月神偷》",
196 | "type": 100
197 | }
198 | ```
199 |
200 | ## 获取点赞信息
201 |
202 | URL:
203 | >GET /classic///favor
204 |
205 | >demo /classic/200/7/favor
206 |
207 | Parameters:
208 |
209 | * id:id号,必填,必须是正整数
210 | * type: 类型号,必填,为100,200,300的一种,分别表示电影,音乐,句子
211 | * token: 通过 Basic Auth方式传递 username: eyJhbGciOiJIUzI1NiIsImlhdCI6MTUzNDUxODQ0MCwiZXhwIjoxNTM3MTEwNDQwfQ.eyJ1aWQiOjEsInR5cGUiOjIwMCwic2NvcGUiOiJVc2VyU2NvcGUifQ.S1YoU30kgUIwYRgyCVeDgL2VvYcTlmeGph6P9Vd2irg, password: ''
212 |
213 | Response 200:
214 |
215 | ```json
216 | {
217 | "fav_nums": 2,
218 | "id": 7,
219 | "like_status": 1
220 | }
221 | ```
222 |
223 | ## 获取我喜欢的期刊
224 | URL:
225 | >GET /classic/favor
226 |
227 | Parameters:
228 | * token
229 |
230 | Response 200:
231 |
232 | ```json
233 | [
234 | {
235 | "content": "人生不能像做菜,把所有的材料准备好才下锅",
236 | "fav_nums": 2,
237 | "id": 8,
238 | "image": "http://127.0.0.1:5000/v1/movie.2.png",
239 | "index": 8,
240 | "like_status": 1,
241 | "pubdate": "2018-08-14",
242 | "title": "李安《饮食男女》",
243 | "type": 100
244 | },
245 | {
246 | "content": "谁念过 千字文章 秋收冬已藏",
247 | "fav_nums": 2,
248 | "id": 7,
249 | "image": "http://127.0.0.1:5000/v1/music.4.png",
250 | "index": 7,
251 | "like_status": 1,
252 | "pubdate": "2018-08-14",
253 | "title": "不才《参商》",
254 | "type": 200,
255 | "url": "http://music.163.com/song/media/outer/url?id=557581284.mp3"
256 | },
257 | {
258 | "content": "谁念过 千字文章 秋收冬已藏",
259 | "fav_nums": 2,
260 | "id": 7,
261 | "image": "http://127.0.0.1:5000/v1/music.4.png",
262 | "index": 7,
263 | "like_status": 1,
264 | "pubdate": "2018-08-14",
265 | "title": "不才《参商》",
266 | "type": 200,
267 | "url": "http://music.163.com/song/media/outer/url?id=557581284.mp3"
268 | }
269 | ]
270 | ```
271 |
272 |
273 |
274 |
275 | ## 获取热门书籍
276 |
277 | URL:
278 |
279 | >GET /book/hot_list
280 |
281 | Response 200:
282 |
283 | ```json
284 | [
285 | {
286 | "author": [
287 | "Vamei"
288 | ],
289 | "fav_nums": 3,
290 | "id": 13,
291 | "image": "https://img1.doubanio.com/lpic/s29166309.jpg",
292 | "like_status": 0,
293 | "title": "从Python开始学编程"
294 | },
295 | {
296 | "author": [
297 | "MarkPilgrim"
298 | ],
299 | "fav_nums": 2,
300 | "id": 5,
301 | "image": "https://img3.doubanio.com/lpic/s4059293.jpg",
302 | "like_status": 0,
303 | "title": "Dive Into Python 3"
304 | }
305 | ]
306 | ```
307 |
308 |
309 | ## 获取书籍短评
310 |
311 | URL:
312 |
313 | >GET /book//shot_comment
314 |
315 | Parameters:
316 |
317 | * book_id:书籍的id,必填,必须为正整数
318 | * Response 200:
319 |
320 | ```json
321 | {
322 | "book_id": 1,
323 | "comment": [
324 | {
325 | "book_id": 1,
326 | "content": "这个书不错",
327 | "nums": 1
328 | },
329 | {
330 | "book_id": 1,
331 | "content": "而是的回忆!七龙珠",
332 | "nums": 9
333 | },
334 | {
335 | "book_id": 1,
336 | "content": "回忆杀!",
337 | "nums": 19
338 | }
339 | ]
340 | }
341 | ```
342 |
343 | Response_description:
344 |
345 | * comment: 一个评论的列表,包含用户对书籍的评论及对应数量的字典
346 | * book_id: 书籍id
347 |
348 |
349 |
350 | Parameters:
351 |
352 |
353 | response_description:
354 |
355 | * fav_nums:点赞数
356 | * id: 书籍id
357 | * like_status: 是否点赞
358 | * author: 作者
359 | * title: 书籍题目
360 | * image: 书籍图片
361 | * 返回一个列表,包含所有热门书籍的概要信息
362 |
363 |
364 | ## 获取喜欢书籍数量
365 |
366 | URL:
367 |
368 | >GET /book/favor/count
369 |
370 | Parameters:
371 | * token
372 | ```json
373 | {
374 | "count": 1
375 | }
376 | ```
377 | Response_description:
378 |
379 | * count: 返回我喜欢的书籍数量
380 |
381 |
382 | ## 获取书籍点赞情况
383 |
384 | URL:
385 |
386 | >GET /book//favor
387 |
388 | Parameters:
389 |
390 | * book_id:书籍的id,必填,必须为正整数
391 |
392 | Response 200:
393 |
394 | ```json
395 | {
396 | "fav_nums": 0,
397 | "id": 1,
398 | "like_status": 0
399 | }
400 | ```
401 |
402 |
403 | ## 新增短评
404 |
405 | URL:
406 |
407 | >POST /book/add/comment
408 |
409 | Parameters:
410 |
411 | * book_id:书籍id
412 | * content:评论内容,我们可允许的评论内容范围为12字以内
413 |
414 | Response 201:
415 | ```json
416 | {
417 | "error_code": 0,
418 | "msg": "OK",
419 | "request": "POST /v1/book/add/short_comment"
420 | }
421 | ```
422 |
423 | ## 获取热搜关键字
424 |
425 | URL:
426 | >GET /json
427 |
428 | Response 200:
429 | ```json
430 | {
431 | "hot": [
432 | "鸟山明",
433 | "龙珠",
434 | "http",
435 | "PHP",
436 | "周",
437 | "阿",
438 | "火箭",
439 | "阿斯达",
440 | "\bphp",
441 | "\bpython3",
442 | "鲁迅",
443 | "python"
444 | ]
445 | }
446 | ```
447 |
448 | ## 书籍搜索
449 |
450 | URL:
451 | >GET /book/search
452 |
453 | > demo1 /book/search?q=七龙珠
454 |
455 | > demo2 /book/search?q=七龙珠&summary=1
456 |
457 | Parameters:
458 |
459 | * start: 开始记录数,默认为0
460 | * count: 记录条数,默认为20,超过依然按照20条计算
461 | * summary: 返回完整或简介,默认为0,0为完整内容,1为简介
462 | * q:搜索内容
463 |
464 | Response 200:
465 |
466 | 当summary=0,返回详细数据:
467 |
468 |
469 | ```json
470 | {
471 | "books": [
472 | {
473 | "author": [
474 | "[日]鸟山明"
475 | ],
476 | "category": "日本漫画",
477 | "id": 17699,
478 | "image": "https://img1.doubanio.com/lpic/s28671937.jpg",
479 | "isbn": "9787600100354",
480 | "pages": "全42册",
481 | "price": "367.6",
482 | "pubdate": "2005-7-1",
483 | "publisher": "中国少年儿童出版社",
484 | "subtitle": "",
485 | "summary": "《DRAGON BALL》译名《龙珠》(又名:七龙珠)是日本著名漫画家鸟山明的得意作品,1984年登场,1992年又推出『龙珠』续集。这部长篇巨作在『少年跳跃』上连载7年。\\n故事讲述了孙悟空(当然不是我们神化中的那个齐天大圣喽)父子和那7颗能满足人们心愿的龙珠,把读者从山村引到城市,从地球引到外星,又从现在引到未来。\\n根据《龙珠》的漫画故事,还推出了《龙珠》的系列动画片,无论是TV版还是剧场版,都吸引了无数的龙珠迷,掀起了一股股“龙珠”的热潮。\\n龙珠的舞台,虽说是带有中国色彩的,但是也并非就限定在中国;时代也一样,并没有把它固定在某一个具体时间。整个故事架构很简单,至于一些细节和结局,我想任其自由发展。这么一来,连我自己也会想[故事下一步会怎么发展啊],并为之捏了一把汗。因为无论怎么发挥都可以,所以乐在其中。\\n传说中,地球四处散落着7颗龙珠。如果谁将他们收集起来就可以实现自己的愿望,人们为了得到它而不断的你争我夺……每年都会有一场以龙珠为奖品的《天下第一武道大会》……在地球的一个角落,生活着孙悟空这个茁壮的孩子,他的身份其实是赛亚人卡卡罗特。因为婴儿时的变身能力不够而被派往地球,其实是为了毁灭地球生物而变成殖民地,但他生来和平,丝毫不知自己的身世……这种战斗力超强的种族“赛亚人”与宇宙中另一些种族“那美克星人”等等间发生了无数惊险有趣又富有教育意义的故事……这就是日本著名漫画家“鸟山明”创造的《七龙珠》世界。",
486 | "title": "龙珠(全42册)",
487 | "translator": [
488 | "牟琳"
489 | ]
490 | },
491 | {
492 | "author": [
493 | "[日]鸟山明"
494 | ],
495 | "category": "日本漫画",
496 | "id": 18569,
497 | "image": "https://img3.doubanio.com/lpic/s11231433.jpg",
498 | "isbn": "9787500774860",
499 | "pages": "175",
500 | "price": "6.9",
501 | "pubdate": "2005-7",
502 | "publisher": "中国少年儿童出版社",
503 | "subtitle": "孙悟空和伙伴们",
504 | "summary": "《龙珠(套装共42册)》是日本著名漫画家鸟山明的得意作品。相传,有七颗龙珠散落在世界的各个角落,当它们被聚集到一起时神龙就会出现,能够实现你的任何一个愿望。这个一个美丽的的传说引出了小悟空和他的朋友们寻找龙珠的故事。",
505 | "title": "龙珠1",
506 | "translator": [
507 | "牟琳"
508 | ]
509 | }
510 | ],
511 | "count": 20,
512 | "start": 0,
513 | "total": 2
514 | }
515 | ```
516 |
517 | 当summary=1,返回概要数据:
518 |
519 | ```json
520 | {
521 | "books": [
522 | {
523 | "author": [
524 | "[日]鸟山明"
525 | ],
526 | "id": 17699,
527 | "image": "https://img1.doubanio.com/lpic/s28671937.jpg",
528 | "isbn": "9787600100354",
529 | "price": "367.6",
530 | "title": "龙珠(全42册)"
531 | },
532 | {
533 | "author": [
534 | "[日]鸟山明"
535 | ],
536 | "id": 18569,
537 | "image": "https://img3.doubanio.com/lpic/s11231433.jpg",
538 | "isbn": "9787500774860",
539 | "price": "6.9",
540 | "title": "龙珠1"
541 | }
542 | ],
543 | "count": 20,
544 | "start": 0,
545 | "total": 2
546 | }
547 | ```
548 |
549 |
550 | ## 获取书籍详细信息
551 |
552 | URL:
553 |
554 | >GET /book//detail
555 |
556 | >demo /book/6548683/detail
557 |
558 | Parameters:
559 |
560 | id: 书籍的id号,从豆瓣API获取
561 |
562 | Response 200:
563 |
564 | ```json
565 | {
566 | "author": [
567 | "申音"
568 | ],
569 | "category": "",
570 | "id": "6548683",
571 | "image": "https://img1.doubanio.com/view/subject/m/public/s6569607.jpg",
572 | "isbn": "9787807674030",
573 | "pages": "262",
574 | "price": "35.00元",
575 | "pubdate": "2011-7-1",
576 | "publisher": "山西经济出版社",
577 | "subtitle": "为何普世商业价值在中国行不通",
578 | "summary": "★为什么美国没有史玉柱,中国没有乔布斯?\n★什么是“对的行业”、“错的行业”?\n★我们需要什么样的营销?\n★老板为什么要读商学院?\n★山寨公司还需要管理吗?\n★资源问题是个“伪问题”?\n★别把商业模式当成葵花宝典\n★给海归技术创业兄弟的九个忠告\n★在一个不伟大的行业里,做一个伟大的公司\n★是什么让互联网遭遇了有史以来最鸡犬不宁的一战?",
579 | "title": "商业的常识",
580 | "translator": ""
581 | }
582 | ```
583 |
584 | # 点赞
585 |
586 | ## 进行点赞
587 | URL:
588 |
589 | >POST /like
590 |
591 | Parameters:
592 |
593 | * art_id: 点赞对象,例如你想对电影进行点赞,那这个参数就是电影的id号
594 | * type:点赞类型分为四种:100 电影 200 音乐 300 句子 400 书籍
595 |
596 | Response Status 201:
597 |
598 | ```json
599 | {
600 | "error_code": 0,
601 | "msg": "OK",
602 | "request": "POST /v1/like"
603 | }
604 | ```
605 |
606 | ## 取消点赞
607 | URL:
608 | >POST /like/cancel
609 |
610 | Parameters:
611 |
612 | * art_id: 点赞对象id
613 | * type:点赞类型
614 |
615 | Response Status 201:
616 | ```json
617 | {
618 | "error_code": 0,
619 | "msg": "OK",
620 | "request": "POST /v1/like"
621 | }
622 | ```
623 |
624 |
625 | # 小程序登录
626 |
627 | ## 获取token
628 |
629 | URL:
630 | >POST /token/mina
631 |
632 | Parameters:
633 | * code: wx.login API获取的code值。
634 |
635 | Response Status 200:
636 | ```json
637 | {
638 | "token" : "eyJhbGciOiJIUzI1NiIsImlhdCI6MTUzNDUxODQ0MCwiZXhwIjoxNTM3MTEwNDQwfQ.eyJ1aWQiOjEsInR5cGUiOjIwMCwic2NvcGUiOiJVc2VyU2NvcGUifQ.S1YoU30kgUIwYRgyCVeDgL2VvYcTlmeGph6P9Vd2irg"
639 | }
640 | ```
641 |
642 | Response_description:
643 |
644 | * token: 供需要权限认证的接口请使用
645 |
646 | ## 验证token
647 |
648 | Parameters:
649 | * token: 需要权限认证的接口请使用HTTP BASIC方式在header头中传递token,headers中的键名为 Authorization, 键值为 base64(basic token:'')
650 |
651 | Response Status 200:
652 | ```json
653 | {
654 | "error_code": 1008,
655 | "msg": "token is invalid",
656 | "request": "POST /v1/like/cancel"
657 | }
658 | ```
659 |
--------------------------------------------------------------------------------