├── .gitignore ├── src ├── pages │ ├── about │ │ ├── about.wxss │ │ ├── about.json │ │ ├── about.js │ │ └── about.wxml │ ├── home │ │ ├── home.json │ │ ├── home.wxml │ │ ├── home.wxss │ │ └── home.js │ ├── my │ │ ├── my.json │ │ ├── my.wxss │ │ ├── my.js │ │ └── my.wxml │ ├── detail │ │ ├── detail.json │ │ ├── detail.wxml │ │ ├── detail.js │ │ └── detail.wxss │ ├── logs │ │ ├── logs.json │ │ ├── logs.wxss │ │ ├── logs.wxml │ │ └── logs.js │ ├── books │ │ ├── books.json │ │ ├── books.wxml │ │ ├── books.wxss │ │ └── books.js │ ├── comment │ │ ├── comment.json │ │ ├── comment.wxss │ │ ├── comment.wxml │ │ └── comment.js │ ├── today │ │ ├── today.json │ │ ├── today.wxml │ │ ├── today.wxss │ │ └── today.js │ ├── commentList │ │ ├── commentList.json │ │ ├── commentList.js │ │ ├── commentList.wxml │ │ └── commentList.wxss │ └── index │ │ ├── index.wxss │ │ ├── index.wxml │ │ └── index.js ├── images │ ├── my.png │ ├── book.png │ ├── login.png │ ├── sad.png │ ├── bought.png │ ├── bookstore.png │ ├── luckyCoin.png │ ├── mySelected.png │ └── bookSelected.png ├── utils │ ├── file.js │ ├── util.js │ ├── tip.js │ ├── cache.js │ ├── navigator.js │ └── http.js ├── config │ ├── const.js │ └── config.js ├── project.config.json ├── app.json ├── app.wxss └── app.js ├── readme ├── home.png ├── my.png ├── books.png ├── detail.png ├── scan1.jpg └── scan2.jpg └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .svn/ 2 | -------------------------------------------------------------------------------- /src/pages/about/about.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/home/home.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "首页" 3 | } -------------------------------------------------------------------------------- /src/pages/my/my.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "我的" 3 | } -------------------------------------------------------------------------------- /src/pages/about/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "关于" 3 | } -------------------------------------------------------------------------------- /src/pages/detail/detail.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "详情页" 3 | } -------------------------------------------------------------------------------- /src/pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /src/pages/books/books.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "图书列表" 3 | } -------------------------------------------------------------------------------- /src/pages/comment/comment.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "评论" 3 | } -------------------------------------------------------------------------------- /src/pages/today/today.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "历史上的今天" 3 | } -------------------------------------------------------------------------------- /src/pages/commentList/commentList.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "评论列表" 3 | } -------------------------------------------------------------------------------- /readme/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/home.png -------------------------------------------------------------------------------- /readme/my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/my.png -------------------------------------------------------------------------------- /readme/books.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/books.png -------------------------------------------------------------------------------- /readme/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/detail.png -------------------------------------------------------------------------------- /readme/scan1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/scan1.jpg -------------------------------------------------------------------------------- /readme/scan2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/readme/scan2.jpg -------------------------------------------------------------------------------- /src/images/my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/my.png -------------------------------------------------------------------------------- /src/images/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/book.png -------------------------------------------------------------------------------- /src/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/login.png -------------------------------------------------------------------------------- /src/images/sad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/sad.png -------------------------------------------------------------------------------- /src/images/bought.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/bought.png -------------------------------------------------------------------------------- /src/images/bookstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/bookstore.png -------------------------------------------------------------------------------- /src/images/luckyCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/luckyCoin.png -------------------------------------------------------------------------------- /src/images/mySelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/mySelected.png -------------------------------------------------------------------------------- /src/images/bookSelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqingwen2015/ituring_small_bookshelf/HEAD/src/images/bookSelected.png -------------------------------------------------------------------------------- /src/pages/about/about.js: -------------------------------------------------------------------------------- 1 | Page({ 2 | 3 | /** 4 | * 页面的初始数据 5 | */ 6 | data: { 7 | 8 | }, 9 | 10 | 11 | }); -------------------------------------------------------------------------------- /src/pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /src/pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/pages/comment/comment.wxss: -------------------------------------------------------------------------------- 1 | /* pages/comment/comment.wxss */ 2 | .comment-container { 3 | display: flex; 4 | flex-direction: column; 5 | padding: 20rpx 0; 6 | } 7 | 8 | .book-name { 9 | padding: 10rpx 30rpx; 10 | } 11 | 12 | .comment-area { 13 | /* margin-top: 20rpx; */ 14 | padding: 20rpx 30rpx; 15 | height: 900rpx; 16 | } -------------------------------------------------------------------------------- /src/pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /src/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | .userinfo { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .userinfo-avatar { 9 | width: 128rpx; 10 | height: 128rpx; 11 | margin: 20rpx; 12 | border-radius: 50%; 13 | } 14 | 15 | .userinfo-nickname { 16 | color: #aaa; 17 | } 18 | 19 | .usermotto { 20 | margin-top: 200px; 21 | } -------------------------------------------------------------------------------- /src/utils/file.js: -------------------------------------------------------------------------------- 1 | // 文件 2 | 3 | // 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx 4 | const openDocument = (filePath) => { 5 | wx.openDocument({ 6 | filePath: filePath, 7 | success: function (res) { 8 | //console.log('打开文档成功') 9 | } 10 | }) 11 | } 12 | 13 | 14 | 15 | module.exports = { 16 | openDocument: openDocument, 17 | 18 | } -------------------------------------------------------------------------------- /src/pages/about/about.wxml: -------------------------------------------------------------------------------- 1 | 2 | 小编QQ:408448945 3 | 开始时间:2018-07-14 4 | 最后更新时间:2018-07-18 5 | v1.1:增加功能-历史上的今天 6 | v1.0.1:修复缓存文件名称 7 | v1.0:修复下载功能 8 | 由于作者的水平和智商等原因,请容忍该作品的不完善之处! 9 | -------------------------------------------------------------------------------- /src/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{userInfo.nickName}} 8 | 9 | 10 | 11 | {{motto}} 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/utils/util.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | const formatTime = date => { 5 | const year = date.getFullYear() 6 | const month = date.getMonth() + 1 7 | const day = date.getDate() 8 | const hour = date.getHours() 9 | const minute = date.getMinutes() 10 | const second = date.getSeconds() 11 | 12 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 13 | } 14 | 15 | const formatNumber = n => { 16 | n = n.toString() 17 | return n[1] ? n : '0' + n 18 | } 19 | 20 | module.exports = { 21 | formatTime: formatTime 22 | } -------------------------------------------------------------------------------- /src/utils/tip.js: -------------------------------------------------------------------------------- 1 | // 提示 2 | 3 | // 显示消息提示框 4 | const showToast = (title, icon = 'none', callback = () => {}) => { 5 | wx.showToast({ 6 | title: title, 7 | icon: icon, 8 | duration: 2000, 9 | mask: true, 10 | success: callback 11 | }); 12 | 13 | } 14 | 15 | // 显示模态弹窗 16 | const showModal = (title, content, callback = () => {}) => { 17 | wx.showModal({ 18 | title: title, 19 | content: content, 20 | success: callback 21 | }); 22 | 23 | } 24 | 25 | module.exports = { 26 | showToast: showToast, 27 | showModal: showModal 28 | } -------------------------------------------------------------------------------- /src/config/const.js: -------------------------------------------------------------------------------- 1 | // Key 名 2 | module.exports = { 3 | // 用户标识 4 | wxUserId: 'WxUserId', 5 | 6 | // 登录标识 7 | loginFlag: 'LoginFlag', 8 | 9 | // 图标 10 | icon: { 11 | success: 'success', 12 | loading: 'loading', 13 | none: 'none' 14 | }, 15 | 16 | // url 前缀 17 | urlPrefix: { 18 | server: 'https://api.nidie.com.cn/api/', //服务器 19 | local: 'http://localhost:57196/api/', //本地 20 | test: 'http://localhost:57196/api/', //测试 21 | file: 'https://download.nidie.com.cn/', //文件 22 | image: 'http://www.ituring.com.cn/' //图片 23 | } 24 | }; -------------------------------------------------------------------------------- /src/pages/comment/comment.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /src/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "2.2.0", 15 | "appid": "", 16 | "projectname": "", 17 | "isGameTourist": false, 18 | "condition": { 19 | "search": { 20 | "current": -1, 21 | "list": [] 22 | }, 23 | "conversation": { 24 | "current": -1, 25 | "list": [] 26 | }, 27 | "game": { 28 | "currentL": -1, 29 | "list": [] 30 | }, 31 | "miniprogram": { 32 | "current": -1, 33 | "list": [] 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/pages/today/today.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 年份 10 | 事件({{today}}) 11 | 12 | 13 | 14 | 15 | {{item.year}} 16 | {{item.title}} 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/utils/cache.js: -------------------------------------------------------------------------------- 1 | // http 请求 2 | 3 | // 将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口 4 | const set = (key, data) => { 5 | wx.setStorage({ 6 | key: key, 7 | data: data 8 | }) 9 | } 10 | 11 | // 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。 12 | const setSync = (key, data) => { 13 | try { 14 | wx.setStorageSync(key, data) 15 | } catch (e) { 16 | console.log(e); 17 | } 18 | } 19 | 20 | // 从本地缓存中异步获取指定 key 对应的内容。 21 | const get = (key, callback) => { 22 | wx.getStorage({ 23 | key: key, 24 | success: callback 25 | }) 26 | } 27 | 28 | // 从本地缓存中同步获取指定 key 对应的内容。 29 | const getSync = (key) => { 30 | try { 31 | return wx.getStorageSync(key); 32 | } catch (e) { 33 | console.log(e); 34 | } 35 | } 36 | 37 | 38 | module.exports = { 39 | set: set, 40 | setSync: setSync, 41 | get: get, 42 | getSync: getSync 43 | } -------------------------------------------------------------------------------- /src/pages/today/today.wxss: -------------------------------------------------------------------------------- 1 | 2 | 3 | .today-container { 4 | /*border: 1px solid black;*/ 5 | margin-top: 3rpx; 6 | } 7 | 8 | .today-item { 9 | padding: 20rpx 30rpx; 10 | display: flex; 11 | flex-direction: row; 12 | justify-content: space-between; 13 | align-items: center; 14 | } 15 | 16 | .today-item-hover { 17 | background-color: #e6e6e6; 18 | } 19 | 20 | 21 | .text-header{ 22 | display: inline-block; 23 | margin-left: 30rpx; 24 | color: #1e1e1e; 25 | font-size: 32rpx; 26 | font-weight:bold; 27 | } 28 | 29 | .text{ 30 | display: inline-block; 31 | margin-left: 30rpx; 32 | color: #1e1e1e; 33 | font-size: 27rpx; 34 | } 35 | 36 | .today-loading { 37 | display: flex; 38 | justify-content: center; 39 | align-items: center; 40 | margin-top: 400rpx; 41 | } 42 | 43 | .loading-container { 44 | width: 250rpx; 45 | /* color: #cdcdcd; */ 46 | margin-top: 30rpx; 47 | } -------------------------------------------------------------------------------- /src/pages/today/today.js: -------------------------------------------------------------------------------- 1 | const api = require('../../config/config.js'); 2 | const cache = require('../../utils/cache.js'); 3 | const tip = require('../../utils/tip.js'); 4 | const http = require('../../utils/http.js'); 5 | 6 | 7 | 8 | Page({ 9 | 10 | /** 11 | * 页面的初始数据 12 | */ 13 | data: { 14 | list: [], 15 | today: '', 16 | isLoading: true 17 | }, 18 | 19 | // 加载数据 20 | loadData: function () { 21 | let that = this; 22 | let key = 'Today'; 23 | 24 | http.get(api.getTodayOfHistory, function (res) { 25 | that.setData({ 26 | list: res.result, 27 | today: res.today, 28 | isLoading: false 29 | }); 30 | 31 | cache.set(key, res); 32 | }) 33 | }, 34 | 35 | onLoad: function () { 36 | //this.loadData(); 37 | }, 38 | 39 | onShow: function () { 40 | this.loadData(); 41 | } 42 | }); -------------------------------------------------------------------------------- /src/config/config.js: -------------------------------------------------------------------------------- 1 | const key = require('const.js'); 2 | 3 | // 服务器域名 4 | const baseUrl = key.urlPrefix.server; 5 | //const baseUrl = key.urlPrefix.local; 6 | 7 | //获取首页的图书 8 | const getBooksOfIndex = baseUrl + 'books/v1/index'; 9 | 10 | //获取图书列表 11 | const getBooksByShowType = baseUrl + 'books/v1/list'; 12 | 13 | //获取图书 14 | const getBook = baseUrl + 'books/v1/detail'; 15 | 16 | // 保存用户信息 17 | const saveUserInfo = baseUrl + 'account/v1/save'; 18 | 19 | // 提交评论 20 | const submitComment = baseUrl + 'comment/v1/submit'; 21 | 22 | // 获取评论 23 | const getComments = baseUrl + 'comment/v1/list'; 24 | 25 | // 获取历史上的今天 26 | const getTodayOfHistory = baseUrl + 'home/v1/today'; 27 | 28 | module.exports = { 29 | getBooksOfIndex: getBooksOfIndex, 30 | getBooksByShowType: getBooksByShowType, 31 | getBook: getBook, 32 | saveUserInfo: saveUserInfo, 33 | submitComment: submitComment, 34 | getComments: getComments, 35 | getTodayOfHistory: getTodayOfHistory 36 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 图灵小书架 2 | 3 | ## 项目介绍 4 | 5 | 定时抓取图灵社区官网的首页、最热、推荐和最新等栏目的相关信息进行展示,并且可以下载相关的 PDF 进行查阅...后台免部署,直接将代码引入微信开发者工具会自动连接到服务器进行数据交互和展示... 6 | 7 | - Github:https://github.com/liqingwen2015/ituring_small_bookshelf 8 | - Gitee:https://gitee.com/liqingwen/ituring_small_bookshelf 9 | - 博客园:https://www.cnblogs.com/liqingwen/p/9339504.html 10 | - 百度百科:https://baike.baidu.com/item/%E5%9B%BE%E7%81%B5%E5%B0%8F%E4%B9%A6%E6%9E%B6/56474937?fr=aladdin 11 | 12 | ## 扫描或搜索 13 | 14 | ### 方法一 15 | 16 | ![二维码1](./readme/scan1.jpg) 17 | ![二维码2](./readme/scan2.jpg) 18 | 19 | ### 方法二 20 | 21 | 搜索:【图灵小书架】 22 | 23 | #### 主要功能截图 24 | 25 | ![首页](./readme/home.png) 26 | ![图书列表](./readme/books.png) 27 | ![详情](./readme/detail.png) 28 | ![我的个人中心](./readme/my.png) 29 | 30 | #### 软件架构 31 | 32 | 后台采用 .NET WebAPI(EF + AutoMapper + Autofac) 33 | 34 | #### 使用说明 35 | 36 | 1. 打开微信开发者工具 37 | 2. 路径引入 src 文件夹 38 | 3. 输入 APPID 和文件名即可 39 | 40 | #### 版本说明 41 | 42 | v1.1 增加功能-历史上的今天 43 | v1.0.1 修复缓存文件名称 44 | v1.0 正式 45 | 46 | -------------------------------------------------------------------------------- /src/pages/books/books.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 最新 5 | 6 | 7 | 热门 8 | 9 | 10 | 推荐 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{item.name}} 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/utils/navigator.js: -------------------------------------------------------------------------------- 1 | // 导航 2 | 3 | // Tip 4 | // 1: wx.navigateTo 和 wx.redirectTo 不允许跳转到 tabbar 页面,只能用 wx.switchTab 跳转到 tabbar 页面 5 | 6 | // 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面 7 | const navigateTo = (url, obj) => { 8 | wx.navigateTo({ 9 | url: handleUrl(url, obj) 10 | }) 11 | } 12 | 13 | // 关闭当前页面,跳转到应用内的某个页面 14 | const redirectTo = (url, obj) => { 15 | wx.redirectTo({ 16 | url: url 17 | }) 18 | } 19 | 20 | // 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 21 | const switchTab = (url) => { 22 | wx.switchTab({ 23 | url: url 24 | }) 25 | } 26 | 27 | // 处理 url 28 | const handleUrl = (url, obj) => { 29 | if (obj) { 30 | url = url + '?'; 31 | for (let key in obj) { 32 | obj[key] = encodeURIComponent(obj[key]); 33 | url += key + '=' + obj[key] + '&'; 34 | } 35 | 36 | return url = url.substring(0, url.length - 1); 37 | } 38 | return url; 39 | } 40 | 41 | // 关闭当前页面,返回上一页面或多级页面 42 | const navigateBack = (delta) => { 43 | wx.navigateBack({ 44 | delta: delta 45 | }) 46 | } 47 | 48 | module.exports = { 49 | navigateTo: navigateTo, 50 | redirectTo: redirectTo, 51 | switchTab: switchTab, 52 | navigateBack: navigateBack 53 | } -------------------------------------------------------------------------------- /src/pages/my/my.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | 3 | .user-container { 4 | padding: 50rpx 0; 5 | /*border: 1px solid black;*/ 6 | } 7 | 8 | .userinfo { 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | } 13 | 14 | .userinfo-avatar { 15 | width: 128rpx; 16 | height: 128rpx; 17 | margin: 20rpx; 18 | border-radius: 50%; 19 | } 20 | 21 | .userinfo-nickname { 22 | color: #aaa; 23 | } 24 | 25 | .tab-container { 26 | /*border: 1px solid black;*/ 27 | margin-top: 30rpx; 28 | } 29 | 30 | .tab-item { 31 | padding: 20rpx 30rpx; 32 | display: flex; 33 | flex-direction: row; 34 | justify-content: space-between; 35 | align-items: center; 36 | } 37 | 38 | .tab-item-hover { 39 | background-color: #e6e6e6; 40 | } 41 | 42 | .tab-icon { 43 | width: 30rpx; 44 | height: 30rpx; 45 | } 46 | 47 | .tab-text { 48 | display: inline-block; 49 | margin-left: 20rpx; 50 | color: #1e1e1e; 51 | } 52 | 53 | .tab-arrow { 54 | display: inline-block; 55 | width: 20rpx; 56 | height: 20rpx; 57 | border: 1px solid #cdcdcd; 58 | border-left: none; 59 | border-bottom: none; 60 | transform: rotate(45deg); 61 | } 62 | 63 | .tab-text-unrealized { 64 | float: right; 65 | color: gray; 66 | font-size: 26rpx; 67 | } -------------------------------------------------------------------------------- /src/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | 4 | "pages/home/home", 5 | "pages/today/today", 6 | "pages/commentList/commentList", 7 | "pages/comment/comment", 8 | "pages/my/my", 9 | "pages/detail/detail", 10 | "pages/books/books", 11 | "pages/about/about", 12 | "pages/index/index", 13 | "pages/logs/logs" 14 | ], 15 | "window": { 16 | "backgroundTextStyle": "light", 17 | "navigationBarBackgroundColor": "#fff", 18 | "navigationBarTitleText": "WeChat", 19 | "navigationBarTextStyle": "black" 20 | }, 21 | "tabBar": { 22 | "list": [{ 23 | "pagePath": "pages/home/home", 24 | "text": "首页", 25 | "iconPath": "images/book.png", 26 | "selectedIconPath": "images/bookSelected.png" 27 | }, { 28 | "pagePath": "pages/books/books", 29 | "text": "图书列表", 30 | "iconPath": "images/book.png", 31 | "selectedIconPath": "images/bookSelected.png" 32 | }, { 33 | "pagePath": "pages/my/my", 34 | "text": "我的", 35 | "iconPath": "images/my.png", 36 | "selectedIconPath": "images/mySelected.png" 37 | }], 38 | "color": "#bfbfbf", 39 | "selectedColor": "#1AAD19" 40 | } 41 | } -------------------------------------------------------------------------------- /src/pages/commentList/commentList.js: -------------------------------------------------------------------------------- 1 | const api = require('../../config/config.js'); 2 | const nvgt = require('../../utils/navigator.js'); 3 | const http = require('../../utils/http.js'); 4 | const cache = require('../../utils/cache.js'); 5 | 6 | Page({ 7 | /** 8 | * 页面的初始数据 9 | */ 10 | data: { 11 | list: [], 12 | isLoading: true 13 | }, 14 | 15 | // 跳转到评论页 16 | goComment: function () { 17 | nvgt.redirectTo('../comment/comment'); 18 | }, 19 | 20 | /** 21 | * 生命周期函数--监听页面加载 22 | */ 23 | onLoad: function (options) {}, 24 | 25 | 26 | /** 27 | * 生命周期函数--监听页面初次渲染完成 28 | */ 29 | onReady: function () {}, 30 | 31 | /** 32 | * 生命周期函数--监听页面显示 33 | */ 34 | onShow: function () { 35 | let that = this; 36 | let key = `CommentList`; 37 | http.get(api.getComments, function (data) { 38 | that.setData({ 39 | list: data, 40 | isLoading: false 41 | }) 42 | cache.set(key, data); 43 | }, function () { 44 | let val = cache.getSync(key); 45 | 46 | if (val) { 47 | that.setData({ 48 | list: val, 49 | isLoading: false 50 | }); 51 | } 52 | }) 53 | } 54 | }); -------------------------------------------------------------------------------- /src/pages/commentList/commentList.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{item.nickName}} 15 | {{item.content}} 16 | {{item.creationTime}} 17 | 18 | 19 | 20 | 21 | 来当第一个评论的人吧~ 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /src/pages/books/books.wxss: -------------------------------------------------------------------------------- 1 | /* pages/books/books.wxss */ 2 | 3 | .swiper-container { 4 | /*border: 1px solid red;*/ 5 | box-sizing: border-box; 6 | padding: 120rpx 0 50rpx 0; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | } 11 | 12 | .book-container { 13 | display: flex; 14 | justify-content: flex-start; 15 | align-items: flex-start; 16 | /* border: 1px solid red; */ 17 | /* height: 1000rpx; */ 18 | flex-wrap: wrap; 19 | /* background-color: gray; */ 20 | align-items: stretch; 21 | } 22 | 23 | .nav { 24 | display: flex; 25 | width: 100%; 26 | align-items: flex-start; 27 | justify-content: flex-start; 28 | /* border-bottom: 1rpx solid gray; */ 29 | position: fixed; 30 | height: 100rpx; 31 | background-color: white; 32 | } 33 | 34 | .nav-item { 35 | width: 33.33%; 36 | text-align: center; 37 | padding-top: 20rpx; 38 | padding-bottom: 20rpx; 39 | } 40 | 41 | .nav-item-text { 42 | border-bottom: 3rpx solid green; 43 | } 44 | 45 | .book-container-item { 46 | width: 50%; 47 | height: 500rpx; 48 | display: flex; 49 | flex-direction: column; 50 | align-items: center; 51 | justify-content: center; 52 | } 53 | 54 | .book-image { 55 | height: 380rpx; 56 | width: 80%; 57 | text-align: center; 58 | } 59 | 60 | .book-name { 61 | padding: 20rpx; 62 | font-size: 25rpx; 63 | } -------------------------------------------------------------------------------- /src/pages/home/home.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{item.name}} 19 | ¥ {{item.price}} 元 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/pages/home/home.wxss: -------------------------------------------------------------------------------- 1 | /* pages/books/books.wxss */ 2 | 3 | .swiper-container { 4 | /*border: 1px solid red;*/ 5 | box-sizing: border-box; 6 | padding: 120rpx 0 50rpx 0; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | } 11 | 12 | .swiper { 13 | width: 750rpx; 14 | height: 800rpx; 15 | } 16 | 17 | .swiper-item { 18 | /*border: 1px solid blue;*/ 19 | /* 宽高自动设为100% */ 20 | display: flex; 21 | justify-content: center; 22 | align-items: center; 23 | } 24 | 25 | .book-container { 26 | border: 1px solid #e6e6e6; 27 | width: 450rpx; 28 | height: 650rpx; 29 | padding: 30rpx 20rpx; 30 | display: flex; 31 | flex-direction: column; 32 | justify-content: space-around; 33 | align-items: center; 34 | border-radius: 20rpx; 35 | box-shadow: 0 0 10rpx #dbdbdb; 36 | } 37 | 38 | .book-container-hover { 39 | transform: scale(0.96, 0.96); 40 | transition: all 1 ease 0; 41 | } 42 | 43 | .book-image { 44 | /*border: 1px solid #cdcdcd;*/ 45 | /*box-shadow: 0 0 10rpx #dcdcdc;*/ 46 | } 47 | 48 | .book-image>image { 49 | width: 400rpx; 50 | height: 500rpx; 51 | } 52 | 53 | .book-info { 54 | display: flex; 55 | flex-direction: column; 56 | justify-content: space-around; 57 | align-items: center; 58 | /*border: 1px solid black;*/ 59 | margin-top: 20rpx; 60 | } 61 | 62 | .book-name { 63 | color: #1e1e1e; 64 | font-size: 32rpx; 65 | margin-bottom: 8rpx; 66 | } 67 | 68 | .author { 69 | color: #8a8a8a; 70 | font-size: 28rpx; 71 | margin-bottom: 8rpx; 72 | } 73 | 74 | .publisher { 75 | color: #cdcdcd; 76 | font-size: 30rpx; 77 | } 78 | 79 | .donut-container { 80 | padding-top: 400rpx; 81 | } -------------------------------------------------------------------------------- /src/pages/index/index.js: -------------------------------------------------------------------------------- 1 | const api = require('../../config/config.js'); 2 | 3 | //index.js 4 | //获取应用实例 5 | const app = getApp() 6 | 7 | Page({ 8 | data: { 9 | motto: 'Hello World', 10 | userInfo: {}, 11 | hasUserInfo: false, 12 | canIUse: wx.canIUse('button.open-type.getUserInfo') 13 | }, 14 | //事件处理函数 15 | bindViewTap: function () { 16 | wx.navigateTo({ 17 | url: '../logs/logs' 18 | }) 19 | }, 20 | onLoad: function () { 21 | console.log(api.getBooksOfIndex); 22 | 23 | if (app.globalData.userInfo) { 24 | this.setData({ 25 | userInfo: app.globalData.userInfo, 26 | hasUserInfo: true 27 | }) 28 | } else if (this.data.canIUse) { 29 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 30 | // 所以此处加入 callback 以防止这种情况 31 | app.userInfoReadyCallback = res => { 32 | this.setData({ 33 | userInfo: res.userInfo, 34 | hasUserInfo: true 35 | }) 36 | } 37 | } else { 38 | // 在没有 open-type=getUserInfo 版本的兼容处理 39 | wx.getUserInfo({ 40 | success: res => { 41 | app.globalData.userInfo = res.userInfo 42 | this.setData({ 43 | userInfo: res.userInfo, 44 | hasUserInfo: true 45 | }) 46 | } 47 | }) 48 | } 49 | }, 50 | getUserInfo: function (e) { 51 | //console.log(e) 52 | app.globalData.userInfo = e.detail.userInfo 53 | this.setData({ 54 | userInfo: e.detail.userInfo, 55 | hasUserInfo: true 56 | }) 57 | } 58 | }) -------------------------------------------------------------------------------- /src/pages/commentList/commentList.wxss: -------------------------------------------------------------------------------- 1 | 2 | .comment-container { 3 | padding-top: 30rpx; 4 | } 5 | 6 | .comment-title { 7 | /*border: 1px solid black;*/ 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | 12 | margin-bottom: 30rpx; 13 | } 14 | 15 | .comment-title > text { 16 | font-size: 30rpx; 17 | color: #cdcdcd; 18 | } 19 | 20 | .comment-area { 21 | /*border: 1px solid black;*/ 22 | 23 | padding: 20rpx 30rpx; 24 | } 25 | 26 | .comment-item { 27 | display: flex; 28 | flex-direction: row; 29 | justify-content: flex-start; 30 | align-items: flex-start; 31 | 32 | margin-bottom: 20rpx; 33 | } 34 | 35 | .comment-placeholder { 36 | display: flex; 37 | justify-content: center; 38 | align-items: center; 39 | 40 | color: #dcdcdc; 41 | } 42 | 43 | .comment-item:last-child { 44 | margin-bottom: 180rpx; 45 | } 46 | 47 | .avatar-container { 48 | width: 80rpx; 49 | height: 80rpx; 50 | margin-right: 20rpx; 51 | } 52 | 53 | .user-avatar { 54 | width: 80rpx; 55 | height: 80rpx; 56 | 57 | /*border: 1px solid red;*/ 58 | 59 | } 60 | 61 | .comment-content { 62 | display: flex; 63 | max-width: 590rpx; 64 | flex-direction: column; 65 | justify-content: flex-start; 66 | align-items: flex-start; 67 | } 68 | 69 | .user-name { 70 | color: #8a8a8a; 71 | font-size: 30rpx; 72 | } 73 | 74 | .user-comment { 75 | display: inline-block; 76 | margin-top: 10rpx; 77 | color: #1e1e1e; 78 | font-size: 35rpx; 79 | } 80 | 81 | .comment-time { 82 | display: inline-block; 83 | margin-top: 10rpx; 84 | color: #cdcdcd; 85 | font-size: 20rpx; 86 | } 87 | 88 | .comment-loading { 89 | display: flex; 90 | justify-content: center; 91 | align-items: center; 92 | margin-top: 300rpx; 93 | } 94 | 95 | .loading-container { 96 | width: 250rpx; 97 | color: #cdcdcd; 98 | margin-top: 30rpx; 99 | } -------------------------------------------------------------------------------- /src/pages/detail/detail.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{book.name}} 13 | {{book.author}} 14 | ¥ {{book.price}} 元 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ========== 简介 ========== 24 | 25 | 26 | 27 | 28 | {{book.intro}} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | 3 | .container { 4 | height: 100%; 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | justify-content: space-between; 9 | padding: 100rpx 0; 10 | box-sizing: border-box; 11 | /*border: 1px solid green;*/ 12 | } 13 | 14 | page { 15 | background-color: #f2f2f2; 16 | } 17 | 18 | .bg-white { 19 | background-color: #ffffff; 20 | } 21 | 22 | .image-icon { 23 | width: 30rpx; 24 | height: 30rpx; 25 | } 26 | 27 | .border-bottom { 28 | border-bottom: 1px solid #dbdbdb; 29 | } 30 | 31 | /* 修正 text 组件 英文&符号不换行的问题 begin */ 32 | 33 | text { 34 | word-wrap: break-all; 35 | word-break: break-word; 36 | text-align: justify; 37 | } 38 | 39 | /* 修正 text 组件 英文&符号不换行的问题 end */ 40 | 41 | .fixed-top { 42 | position: fixed; 43 | top: 0rpx; 44 | left: 0rpx; 45 | box-shadow: 0 -5rpx 20rpx #c9c9c9; 46 | } 47 | 48 | .fixed-bottom { 49 | position: fixed; 50 | bottom: 0rpx; 51 | left: 0rpx; 52 | box-shadow: 0 -5rpx 20rpx #c9c9c9; 53 | } 54 | 55 | .block-full-width { 56 | display: block; 57 | width: 100%; 58 | height: 150rpx; 59 | } 60 | 61 | .flex-container { 62 | display: flex; 63 | justify-content: center; 64 | align-items: center; 65 | } 66 | 67 | .full-button { 68 | width: 80%; 69 | } 70 | 71 | /*甜甜圈loading start*/ 72 | 73 | @keyframes donut-spin { 74 | 0% { 75 | transform: rotate(0deg); 76 | } 77 | 100% { 78 | transform: rotate(360deg); 79 | } 80 | } 81 | 82 | .donut { 83 | display: inline-block; 84 | border: 4rpx solid rgba(0, 0, 0, 0.1); 85 | border-left-color: #1AAD19; 86 | border-radius: 50%; 87 | width: 60rpx; 88 | height: 60rpx; 89 | animation: donut-spin 0.5s linear infinite; 90 | } 91 | 92 | /*甜甜圈loading end*/ 93 | 94 | .donut-container { 95 | padding-top: 500rpx; 96 | text-align: center; 97 | } -------------------------------------------------------------------------------- /src/utils/http.js: -------------------------------------------------------------------------------- 1 | // http 请求 2 | 3 | const tip = require('tip.js'); 4 | 5 | // get 6 | const get = (url, success = () => {}, fail = () => {}) => { 7 | wx.request({ 8 | url: url, 9 | method: "GET", 10 | success: function (res) { 11 | if (res.statusCode === 200) { 12 | success(res.data.data); 13 | return true; 14 | } 15 | 16 | console.log(res); 17 | return false; 18 | }, 19 | fail: function (err) { 20 | fail(); 21 | tip.showToast('貌似网络不好哦!请在网络顺畅的时候重新操作!'); 22 | console.log(err); 23 | } 24 | }); 25 | } 26 | 27 | /** 28 | * 封装 post 29 | */ 30 | const post = (url, data, success = () => {}, fail = () => {}) => { 31 | wx.request({ 32 | url: url, 33 | data: data, 34 | method: "POST", 35 | success: function (res) { 36 | if (res.statusCode === 200) { 37 | success(); 38 | return true; 39 | } 40 | 41 | console.log(res); 42 | return false; 43 | }, 44 | fail: function (err) { 45 | fail(); 46 | console.log(err); 47 | tip.showToast('貌似网络不好哦!请在网络顺畅的时候重新操作!'); 48 | } 49 | }); 50 | } 51 | 52 | // 下载文件资源到本地,客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径 53 | const downloadFile = (url, success = () => {}, fail = () => {}, complete = () => {}) => { 54 | wx.downloadFile({ 55 | url: url, 56 | success: function (res) { 57 | if (res.statusCode === 200) { 58 | success(res.tempFilePath); 59 | return true; 60 | } 61 | 62 | return false; 63 | }, 64 | fail: function (err) { 65 | fail(); 66 | tip.showToast("貌似失败了,请重试!多次失败请联系开发人员"); 67 | console.log(err) 68 | }, 69 | complete: function () { 70 | complete(); 71 | } 72 | }) 73 | } 74 | 75 | module.exports = { 76 | post: post, 77 | get: get, 78 | downloadFile: downloadFile 79 | } -------------------------------------------------------------------------------- /src/pages/home/home.js: -------------------------------------------------------------------------------- 1 | // pages/books/books.js 2 | 3 | // 获取服务器接口地址 4 | const api = require('../../config/config.js'); 5 | const nvgt = require('../../utils/navigator.js'); 6 | const http = require('../../utils/http.js'); 7 | const cache = require('../../utils/cache.js'); 8 | 9 | Page({ 10 | 11 | /** 12 | * 页面的初始数据 13 | */ 14 | data: { 15 | list: [], 16 | indicatorDots: false, // 是否显示轮播指示点 17 | autoplay: true, // 是否自动播放轮播 18 | interval: 5000, // 轮播间隔 19 | duration: 1000, // 轮播播放延迟 20 | circular: true, // 是否采用衔接滑动 21 | sideMargin: '100rpx', // 幻灯片前后边距 22 | isLoading: true // 是否显示loading态 23 | }, 24 | 25 | /** 26 | * 打开书籍详情页面 27 | */ 28 | goDetail: function (ev) { 29 | let info = ev.currentTarget.dataset; 30 | nvgt.navigateTo('../detail/detail', info); 31 | }, 32 | 33 | // 获取首页的书籍 34 | getBooksOfIndex: function () { 35 | let that = this; 36 | let key = 'BooksOfHome'; 37 | var res = cache.getSync(key); 38 | 39 | if (!res) { 40 | http.get(api.getBooksOfIndex, function (res) { 41 | that.setData({ 42 | list: res.books, 43 | isLoading: false 44 | }); 45 | 46 | cache.set(key, res.books) 47 | }); 48 | } else { 49 | that.setData({ 50 | list: res, 51 | isLoading: false 52 | }); 53 | } 54 | }, 55 | 56 | /** 57 | * 生命周期函数--监听页面加载 58 | */ 59 | onLoad: function (options) { 60 | 61 | }, 62 | 63 | /** 64 | * 生命周期函数--监听页面初次渲染完成 65 | */ 66 | onReady: function () {}, 67 | 68 | /** 69 | * 生命周期函数--监听页面显示 70 | */ 71 | onShow: function () { 72 | let that = this; 73 | if (that.list == null || that.list.length == 0) { 74 | that.getBooksOfIndex(); 75 | } 76 | }, 77 | 78 | /** 79 | * 设置页面转发信息 80 | */ 81 | onShareAppMessage: function (res) { 82 | if (res.from === 'button') { 83 | // 来自页面内转发按钮 84 | console.log(res.target) 85 | } 86 | return { 87 | title: '小书架首页', 88 | path: '/pages/books/books', 89 | imageUrl: '/images/bookstore.png', 90 | success: function (res) { 91 | // 转发成功 92 | console.log('转发成功'); 93 | }, 94 | fail: function (res) { 95 | // 转发失败 96 | console.log('转发失败') 97 | } 98 | } 99 | } 100 | }); -------------------------------------------------------------------------------- /src/pages/my/my.js: -------------------------------------------------------------------------------- 1 | 2 | const api = require('../../config/config.js'); 3 | const nvgt = require('../../utils/navigator.js'); 4 | const tip = require('../../utils/tip.js'); 5 | 6 | const app = getApp(); 7 | 8 | 9 | Page({ 10 | 11 | /** 12 | * 页面的初始数据 13 | */ 14 | data: { 15 | userInfo: {}, 16 | hasLogin: wx.getStorageSync('loginFlag') ? true : false 17 | }, 18 | 19 | // 跳转到 关于 20 | goAbout: function () { 21 | nvgt.navigateTo('../about/about'); 22 | }, 23 | 24 | // 跳转到 评论 25 | goComment: function () { 26 | nvgt.navigateTo('../comment/comment'); 27 | }, 28 | 29 | // 跳转到 评论列表 30 | goCommentList: function () { 31 | nvgt.navigateTo('../commentList/commentList'); 32 | 33 | }, 34 | 35 | // 跳转到 历史上的今天 36 | goToday: function () { 37 | nvgt.navigateTo('../today/today'); 38 | }, 39 | 40 | // 检查登录状态 41 | checkLoginStatus: function () { 42 | let that = this; 43 | let loginFlag = wx.getStorageSync('loginFlag'); 44 | 45 | if (loginFlag) { 46 | // 检查 session_key 是否过期 47 | wx.checkSession({ 48 | // session_key 有效(未过期) 49 | success: function () { 50 | // 获取用户头像/昵称等信息 51 | that.getUserInfo(); 52 | }, 53 | 54 | // session_key 已过期 55 | fail: function () { 56 | that.setData({ 57 | hasLogin: false 58 | }); 59 | } 60 | }); 61 | 62 | } else { 63 | that.setData({ 64 | hasLogin: false 65 | }); 66 | } 67 | }, 68 | 69 | /** 70 | * 执行登录操作 71 | */ 72 | doLogin: function (e) { 73 | let that = this; 74 | 75 | wx.showLoading({ 76 | title: '登录中...', 77 | mask: true 78 | }); 79 | 80 | app.doLogin(that.getUserInfo, e.detail.userInfo); 81 | }, 82 | 83 | /** 84 | * 从 globalData 中获取 userInfo 85 | */ 86 | getUserInfo: function () { 87 | let that = this; 88 | let userInfo = app.globalData.userInfo; 89 | 90 | if (userInfo) { 91 | that.setData({ 92 | hasLogin: true, 93 | userInfo: userInfo 94 | }); 95 | 96 | wx.hideLoading(); 97 | 98 | } else { 99 | console.log('globalData中userInfo为空'); 100 | } 101 | }, 102 | 103 | onLoad: function () { 104 | this.checkLoginStatus(); 105 | }, 106 | 107 | onShow: function () { 108 | let that = this; 109 | that.setData({ 110 | userInfo: app.globalData.userInfo 111 | }); 112 | } 113 | }); -------------------------------------------------------------------------------- /src/pages/detail/detail.js: -------------------------------------------------------------------------------- 1 | // 获取服务器接口地址 2 | const api = require('../../config/config.js'); 3 | const key = require('../../config/const.js'); 4 | const http = require('../../utils/http.js'); 5 | const file = require('../../utils/file.js'); 6 | const cache = require('../../utils/cache.js'); 7 | const tip = require('../../utils/tip.js'); 8 | 9 | Page({ 10 | data: { 11 | bookIsBuy: 0, 12 | downloading: false, 13 | book: {}, 14 | id: '', 15 | showLoading: true, 16 | isAllowDownload: false, //是否允许下载 17 | isDownloading: false //下载中标识 18 | }, 19 | 20 | // 获取书籍 21 | getBook: function (id) { 22 | let that = this; 23 | let key = `Book_${id}`; 24 | let val = cache.getSync(key); 25 | let obj = { 26 | showLoading: false 27 | }; 28 | 29 | if (val) { 30 | if (val.pdfUrl && val.pdfUrl.trim() !== '') { 31 | obj.isAllowDownload = true; 32 | } 33 | 34 | obj.book = val; 35 | that.setData(obj); 36 | return; 37 | } 38 | 39 | http.get(api.getBook + `/${id}`, function (data) { 40 | if (data.pdfUrl && data.pdfUrl.trim() !== '') { 41 | obj.isAllowDownload = true; 42 | } 43 | 44 | obj.book = data; 45 | that.setData(obj); 46 | 47 | cache.set(key, data); 48 | }); 49 | }, 50 | 51 | // 下载 52 | download: function () { 53 | let that = this; 54 | 55 | if (that.data.isDownloading) { 56 | tip.showToast('下载中,请稍安勿躁!!!'); 57 | return; 58 | } 59 | 60 | let cachekey = `Book_PDF_${that.data.id}`; 61 | let path = cache.getSync(cachekey); 62 | 63 | if (!path) { 64 | that.setData({ 65 | isDownloading: true 66 | }); 67 | 68 | let pdfUrl = that.data.book.pdfUrl.split(','); 69 | 70 | http.downloadFile(key.urlPrefix.file + pdfUrl[0], 71 | function (filePath) { 72 | file.openDocument(filePath); 73 | cache.set(cachekey, filePath); 74 | }, 75 | function () { 76 | that.setData({ 77 | isDownloading: false 78 | }); 79 | }); 80 | 81 | tip.showToast('已经开始下载,下载完毕后将自动打开,请稍后!!!'); 82 | return; 83 | } 84 | 85 | file.openDocument(path); 86 | }, 87 | 88 | /** 89 | * 生命周期函数--监听页面加载 90 | */ 91 | onLoad: function (options) { 92 | let that = this; 93 | let id = options.id; 94 | 95 | that.getBook(id); 96 | that.setData({ 97 | id: id 98 | }); 99 | }, 100 | }); -------------------------------------------------------------------------------- /src/pages/detail/detail.wxss: -------------------------------------------------------------------------------- 1 | /* pages/detail/detail.wxss */ 2 | 3 | .book-container { 4 | /*border: 1px solid black;*/ 5 | 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: space-between; 9 | align-items: center; 10 | 11 | padding: 50rpx 30rpx; 12 | } 13 | 14 | .book-info { 15 | /*border: 1px solid red;*/ 16 | 17 | display: flex; 18 | flex-direction: row; 19 | align-items: flex-start; 20 | justify-content: space-between; 21 | } 22 | 23 | .book-image { 24 | width: 240rpx; 25 | height: 280rpx; 26 | 27 | box-shadow: 0 0 10rpx #cdcdcd; 28 | } 29 | 30 | 31 | .book-desc { 32 | /*border: 1px solid yellow;*/ 33 | display: flex; 34 | flex-direction: column; 35 | justify-content: space-between; 36 | align-items: flex-start; 37 | 38 | padding-left: 30rpx; 39 | } 40 | 41 | .book-main-text { 42 | color: #1e1e1e; 43 | font-size: 35rpx; 44 | } 45 | 46 | .book-text { 47 | color: #8a8a8a; 48 | font-size: 30rpx; 49 | margin-top:15rpx; 50 | } 51 | 52 | .button-area { 53 | /*border: 1px solid blue;*/ 54 | } 55 | 56 | .button-area > button { 57 | font-size: 30rpx; 58 | } 59 | 60 | 61 | .comment-container { 62 | padding-top: 30rpx; 63 | } 64 | 65 | .comment-title { 66 | /*border: 1px solid black;*/ 67 | display: flex; 68 | justify-content: center; 69 | align-items: center; 70 | 71 | margin-bottom: 30rpx; 72 | } 73 | 74 | .comment-title > text { 75 | font-size: 30rpx; 76 | color: #cdcdcd; 77 | } 78 | 79 | .comment-area { 80 | /*border: 1px solid black;*/ 81 | 82 | padding: 20rpx 30rpx; 83 | } 84 | 85 | .comment-item { 86 | display: flex; 87 | flex-direction: row; 88 | justify-content: flex-start; 89 | align-items: flex-start; 90 | 91 | margin-bottom: 20rpx; 92 | } 93 | 94 | .comment-placeholder { 95 | display: flex; 96 | justify-content: center; 97 | align-items: center; 98 | 99 | color: black; 100 | font-size: 30rpx; 101 | } 102 | 103 | .comment-item:last-child { 104 | margin-bottom: 180rpx; 105 | } 106 | 107 | .avatar-container { 108 | width: 80rpx; 109 | height: 80rpx; 110 | margin-right: 20rpx; 111 | } 112 | 113 | .user-avatar { 114 | width: 80rpx; 115 | height: 80rpx; 116 | 117 | /*border: 1px solid red;*/ 118 | 119 | } 120 | 121 | .comment-content { 122 | display: flex; 123 | max-width: 590rpx; 124 | flex-direction: column; 125 | justify-content: flex-start; 126 | align-items: flex-start; 127 | } 128 | 129 | .user-name { 130 | color: #8a8a8a; 131 | font-size: 30rpx; 132 | } 133 | 134 | .user-comment { 135 | display: inline-block; 136 | margin-top: 10rpx; 137 | color: #1e1e1e; 138 | font-size: 35rpx; 139 | } 140 | 141 | .comment-time { 142 | display: inline-block; 143 | margin-top: 10rpx; 144 | color: #cdcdcd; 145 | font-size: 20rpx; 146 | } 147 | 148 | .comment-loading { 149 | display: flex; 150 | justify-content: center; 151 | align-items: center; 152 | } 153 | 154 | .loading-container { 155 | width: 250rpx; 156 | color: #cdcdcd; 157 | margin-top: 30rpx; 158 | } -------------------------------------------------------------------------------- /src/pages/comment/comment.js: -------------------------------------------------------------------------------- 1 | /** pages/comment/comment.js **/ 2 | 3 | // 获取服务器接口地址 4 | const api = require('../../config/config.js'); 5 | const tip = require('../../utils/tip.js'); 6 | const http = require('../../utils/http.js'); 7 | const nvgt = require('../../utils/navigator.js'); 8 | 9 | Page({ 10 | 11 | /** 12 | * 页面的初始数据 13 | */ 14 | data: { 15 | comment: '', 16 | 17 | }, 18 | 19 | /** 20 | * 用户输入评论 21 | */ 22 | inputComment: function (ev) { 23 | let that = this; 24 | that.setData({ 25 | comment: ev.detail.value 26 | }); 27 | }, 28 | 29 | /** 30 | * 检查输入是否为空 31 | */ 32 | checkEmpty: function (input) { 33 | return input === ''; 34 | }, 35 | 36 | /** 37 | * 检查用户是否输入了非法字符 38 | */ 39 | checkIllegal: function (input) { 40 | let patern = /[`#^<>:"?{}\/;'[\]]/im; 41 | let _result = patern.test(input); 42 | return _result; 43 | }, 44 | 45 | /** 46 | * 检查用户输入 47 | */ 48 | checkUserInput: function () { 49 | let that = this; 50 | let comment = that.data.comment; 51 | let showToastFlag = true; 52 | let toastWording = ''; 53 | 54 | if (that.checkEmpty(comment)) { 55 | toastWording = '输入不能为空'; 56 | } else if (that.checkIllegal(comment)) { 57 | 58 | toastWording = '含有非法字符'; 59 | } else if (comment.length > 300) { 60 | toastWording = '长度超出限制'; 61 | } else if (comment.length < 5) { 62 | toastWording = '不能少于5个字哦'; 63 | } else { 64 | showToastFlag = false; 65 | } 66 | 67 | if (showToastFlag) { 68 | tip.showToast(toastWording); 69 | return false; 70 | } else { 71 | return true; 72 | } 73 | }, 74 | 75 | /** 76 | * 提交评论内容 77 | */ 78 | submitComment: function (ev) { 79 | 80 | let that = this; 81 | 82 | let formId = ev.detail.formId; 83 | 84 | let userId = wx.getStorageSync('userId'); 85 | 86 | if (!userId) { 87 | let toastWording = '请先登录'; 88 | tip.showToast(toastWording); 89 | return false; 90 | } 91 | 92 | if (that.checkUserInput()) { 93 | let requestData = { 94 | content: that.data.comment, 95 | wxUserId: userId 96 | }; 97 | 98 | http.post(api.submitComment, requestData, function () { 99 | tip.showToast('成功!', 'success'); 100 | nvgt.redirectTo('../commentList/commentList'); 101 | }); 102 | 103 | } 104 | }, 105 | 106 | /** 107 | * 生命周期函数--监听页面加载 108 | */ 109 | onLoad: function (options) {}, 110 | 111 | /** 112 | * 生命周期函数--监听页面初次渲染完成 113 | */ 114 | onReady: function () {}, 115 | 116 | /** 117 | * 生命周期函数--监听页面显示 118 | */ 119 | onShow: function () {; 120 | } 121 | }); -------------------------------------------------------------------------------- /src/pages/my/my.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{userInfo.nickName}} 12 | 13 | 14 | 15 | 16 | 26 | 36 | 37 | 38 | 39 | 留言 | 评论 | 建议 40 | 41 | 42 | 43 | 44 | 45 | 46 | 查看所有评论 47 | 48 | 49 | 50 | 51 | 52 | 53 | 查看历史上的今天 54 | 55 | 56 | 57 | 58 | 59 | 60 | 关于 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/pages/books/books.js: -------------------------------------------------------------------------------- 1 | // pages/books/books.js 2 | 3 | // 获取服务器接口地址 4 | const api = require('../../config/config.js'); 5 | const nvgt = require('../../utils/navigator.js'); 6 | const http = require('../../utils/http.js'); 7 | // 获取app应用实例 8 | const app = getApp(); 9 | 10 | 11 | Page({ 12 | 13 | /** 14 | * 页面的初始数据 15 | */ 16 | data: { 17 | indicatorDots: false, // 是否显示轮播指示点 18 | autoplay: true, // 是否自动播放轮播 19 | interval: 5000, // 轮播间隔 20 | duration: 1000, // 轮播播放延迟 21 | circular: true, // 是否采用衔接滑动 22 | sideMargin: '100rpx', // 幻灯片前后边距 23 | showLoading: true, // 是否显示loading态 24 | isNewest: true, 25 | isHot: false, 26 | isCommendatory: false, 27 | list: [], 28 | }, 29 | 30 | // 切换类型 31 | toggelType(ev) { 32 | let that = this; 33 | let info = ev.currentTarget.dataset; 34 | 35 | let typeObj = { 36 | isNewest: false, 37 | isHot: false, 38 | isCommendatory: false, 39 | showLoading: false 40 | }; 41 | 42 | switch (info.type) { 43 | case '1': 44 | typeObj.isNewest = true; 45 | break; 46 | case '2': 47 | typeObj.isHot = true; 48 | break; 49 | case '3': 50 | typeObj.isCommendatory = true; 51 | break; 52 | default: 53 | typeObj.isNewest = true; 54 | break; 55 | } 56 | 57 | that.getList(info.type); 58 | that.setData(typeObj); 59 | }, 60 | 61 | // 跳转到详情页面 62 | goDetail: function (ev) { 63 | let info = ev.currentTarget.dataset; 64 | nvgt.navigateTo('../detail/detail', info); 65 | }, 66 | 67 | // 获取列表 68 | getList: function (type) { 69 | type = type || 1; 70 | let that = this; 71 | 72 | http.get(that.createRequestUrlOfGetList(type), function (res) { 73 | that.setData({ 74 | list: res.books 75 | }); 76 | }) 77 | 78 | }, 79 | 80 | // 生成请求 url 81 | createRequestUrlOfGetList: function (type) { 82 | return api.getBooksByShowType + `/${type}/1`; 83 | }, 84 | 85 | /** 86 | * 生命周期函数--监听页面加载 87 | */ 88 | onLoad: function (options) { 89 | let that = this; 90 | that.getList(); 91 | }, 92 | 93 | /** 94 | * 生命周期函数--监听页面初次渲染完成 95 | */ 96 | onReady: function () { 97 | }, 98 | 99 | /** 100 | * 生命周期函数--监听页面显示 101 | */ 102 | onShow: function () { 103 | }, 104 | 105 | /** 106 | * 设置页面转发信息 107 | */ 108 | onShareAppMessage: function (res) { 109 | console.log(res); 110 | 111 | if (res.from === 'button') { 112 | // 来自页面内转发按钮 113 | console.log(res.target) 114 | } 115 | 116 | return { 117 | title: '图灵书籍', 118 | path: '/pages/home/home', 119 | imageUrl: '/images/bookstore.png', 120 | success: function (res) { 121 | console.log('转发成功'); 122 | }, 123 | fail: function (res) { 124 | console.log('转发失败') 125 | } 126 | } 127 | } 128 | }); -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | const api = require('./config/config.js'); 3 | 4 | App({ 5 | // 小程序启动生命周期 6 | onLaunch: function () { 7 | let that = this; 8 | // 检查登录状态 9 | that.checkLoginStatus(); 10 | }, 11 | 12 | // 检查本地 storage 中是否有登录态标识 13 | checkLoginStatus: function () { 14 | let that = this; 15 | let loginFlag = wx.getStorageSync('loginFlag'); 16 | if (loginFlag) { 17 | // 检查 session_key 是否过期 18 | wx.checkSession({ 19 | // session_key 有效(为过期) 20 | success: function () { 21 | // 直接从Storage中获取用户信息 22 | let userStorageInfo = wx.getStorageSync('userInfo'); 23 | if (userStorageInfo) { 24 | that.globalData.userInfo = JSON.parse(userStorageInfo); 25 | } else { 26 | that.showInfo('缓存信息缺失'); 27 | console.error('登录成功后将用户信息存在Storage的userStorageInfo字段中,该字段丢失'); 28 | } 29 | 30 | }, 31 | // session_key 过期 32 | fail: function () { 33 | // session_key过期 34 | that.doLogin(); 35 | } 36 | }); 37 | } else { 38 | // 无登录态 39 | that.doLogin(); 40 | } 41 | }, 42 | 43 | // 登录动作 44 | doLogin: function (callback = () => {}, userInfo) { 45 | 46 | let that = this; 47 | 48 | if (userInfo) { 49 | 50 | that.globalData.userInfo = userInfo; 51 | wx.setStorageSync('userInfo', JSON.stringify(userInfo)); 52 | wx.setStorageSync('loginFlag', "res.skey"); 53 | callback(); 54 | 55 | wx.login({ 56 | success: function (loginRes) { 57 | if (loginRes.code) { 58 | 59 | wx.request({ 60 | url: api.saveUserInfo, 61 | data: { 62 | Code: loginRes.code, 63 | NickName: userInfo.nickName, 64 | AvatarUrl: userInfo.avatarUrl, 65 | Gender: userInfo.gender, 66 | City: userInfo.city, 67 | Province: userInfo.province, 68 | Country: userInfo.country, 69 | Language: userInfo.language 70 | }, 71 | method: "POST", 72 | success: function (res) { 73 | wx.setStorageSync('userId', res.data.data); 74 | showLoading: false; 75 | }, 76 | error: function (err) { 77 | console.log(err); 78 | showLoading: false 79 | } 80 | }); 81 | 82 | } else { 83 | // 获取 code 失败 84 | that.showInfo('登录失败'); 85 | console.log('调用wx.login获取code失败'); 86 | } 87 | }, 88 | 89 | fail: function (error) { 90 | // 调用 wx.login 接口失败 91 | that.showInfo('接口调用失败'); 92 | console.log(error); 93 | } 94 | }); 95 | } 96 | 97 | //console.log(that.globalData.userInfo); 98 | }, 99 | 100 | // 检查用户信息授权设置 101 | checkUserInfoPermission: function (callback = () => {}) { 102 | wx.getSetting({ 103 | success: function (res) { 104 | if (!res.authSetting['scope.userInfo']) { 105 | wx.openSetting({ 106 | success: function (authSetting) { 107 | console.log(authSetting) 108 | } 109 | }); 110 | } 111 | }, 112 | fail: function (error) { 113 | console.log(error); 114 | } 115 | }); 116 | }, 117 | 118 | 119 | // 获取用户登录标示 供全局调用 120 | getLoginFlag: function () { 121 | return wx.getStorageSync('loginFlag'); 122 | }, 123 | 124 | // 获取书籍已下载路径 125 | getDownloadPath: function (key) { 126 | return wx.getStorageSync(key); 127 | }, 128 | 129 | // 调用 wx.saveFile 将下载的文件保存在本地 130 | saveDownloadPath: function (key, filePath) { 131 | return new Promise((resolve, reject) => { 132 | wx.saveFile({ 133 | tempFilePath: filePath, 134 | success: function (res) { 135 | // 保存成功 在Storage中标记 下次不再下载 136 | let savedFilePath = res.savedFilePath; 137 | wx.setStorageSync(key, savedFilePath); 138 | resolve(savedFilePath); 139 | }, 140 | fail: function () { 141 | reject(false); 142 | } 143 | }); 144 | }) 145 | 146 | }, 147 | 148 | // 打开书籍 149 | openBook: function (filePath) { 150 | wx.openDocument({ 151 | filePath: filePath, 152 | success: function (res) { 153 | console.log('打开文档成功') 154 | }, 155 | fail: function (error) { 156 | console.log(error); 157 | } 158 | }); 159 | }, 160 | 161 | // app全局数据 162 | globalData: { 163 | userInfo: null 164 | } 165 | }); --------------------------------------------------------------------------------