├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app.js ├── app.json ├── app.wxss ├── config.js ├── demo └── diaries.js ├── files └── preview.gif ├── images ├── icons │ ├── add.png │ ├── collect.png │ ├── collectHL.png │ ├── comment.png │ ├── compose.png │ ├── composeHL.png │ ├── like.png │ ├── likeHL.png │ ├── mark.png │ ├── markHL.png │ ├── mine.png │ ├── mineHL.png │ ├── more.png │ ├── moreHL.png │ ├── poi.png │ ├── strategy.png │ ├── strategyHL.png │ └── user_privatemsg.png ├── nav │ ├── comment.png │ ├── download.png │ ├── fav.png │ └── share.png └── tabbar │ ├── Plus Math.png │ ├── add.png │ ├── cancel.png │ ├── image.png │ ├── more.png │ ├── ok.png │ └── text.png ├── pages ├── entry │ ├── entry.js │ ├── entry.wxml │ └── entry.wxss ├── list │ ├── list.js │ ├── list.wxml │ └── list.wxss ├── mine │ ├── mine.js │ ├── mine.wxml │ └── mine.wxss └── new │ ├── new.js │ ├── new.wxml │ └── new.wxss ├── services ├── geo.js └── request.js └── utils ├── input.js └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2016-10-12 2 | 3 | * 更新开发者工具至`v0.10.101100` 4 | * 修改`new`页的数据绑定方式 & 修改多行文本框输入时的bug 5 | 6 | # 2016-10-13 7 | 8 | * 完善日志编辑页 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 小闹钟 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微信小程序之小熊の日记 # 2 | 3 | ## 关于 ## 4 | 5 | * 我是一名后端程序员,做这个仅仅是因为觉得微信小程序好玩; 6 | * 没有明确的产品意图,东抄抄西抄抄只是为了验证和学习微信小程序; 7 | * 大体是想做一个个人/家庭日常记录的app; 8 | * 持续开发中,有兴趣请持续关注 9 | 10 | ## 预览 ## 11 | 12 | * 概览 13 | 14 |

15 | 截频演示 16 |

17 | 18 | ## 功能特点 ## 19 | 20 | * 功能完备,实用导向 21 | * Server端API支持 22 | * 涵盖众多组件、API使用,适用于学习微信小程序 23 | * 多行文本模拟实现 24 | * tab切换 25 | * 模态框 26 | * 本地数据组织及存储 27 | * 图片预览功能 28 | 29 | ## 使用步骤 30 | 31 | 1. 克隆代码: 32 | 33 | ```bash 34 | $ cd path/to/your/workspace 35 | $ git clone https://github.com/harveyqing/BearDiary.git 36 | ``` 37 | 38 | 2. 打开`微信Web开放者工具`(注意:须`v0.10.101100`及以上版本) 39 | 40 | 3. 添加项目 41 | 42 | * AppID:选`无AppID` 43 | * 项目名称:任意填写 44 | * 项目目录:path/to/your/workspace 45 | * 点击 `添加项目` 46 | 47 | ## 开发计划 ## 48 | 49 | - [ ] 开发server端API接口 50 | - [ ] 完成日记撰写页 51 | - [ ] 添加评论、喜欢、收藏功能 52 | - [ ] 规范`coding style` 53 | 54 | ## 小程序开发相关资源 ## 55 | 56 | ### 开发者工具下载 ### 57 | 58 | > 最新版本 0.10.101100 59 | 60 | - [windows 64](https://servicewechat.com/wxa-dev-logic/download_redirect?type=x64&from=mpwiki&t=1476434677599) 61 | - [windows 32](https://servicewechat.com/wxa-dev-logic/download_redirect?type=ia32&from=mpwiki&t=1476434677599) 62 | - [mac](https://servicewechat.com/wxa-dev-logic/download_redirect?type=darwin&from=mpwiki&t=1476434677599) 63 | 64 | ### 开发者文档 ### 65 | 66 | - [微信官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/) 67 | 68 | ### 最好的资源集 ### 69 | 70 | - [justjavac/awesome-wechat-weapp](https://github.com/justjavac/awesome-wechat-weapp) 71 | 72 | ## Anyway, 欢迎PR ## 73 | 74 | ## LICENSE ## 75 | 76 | [MIT](./LICENSE) 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // app.js 2 | 3 | const config = require('config'); 4 | const diaries = require('demo/diaries'); 5 | 6 | App({ 7 | 8 | onLaunch: function () { 9 | }, 10 | 11 | // 获取用户信息 12 | getUserInfo: function(cb) { 13 | var that = this; 14 | 15 | if (this.globalData.userInfo) { 16 | typeof cb == 'function' && cb(this.globalData.userInfo) 17 | } else { 18 | // 先登录 19 | wx.login({ 20 | success: function() { 21 | wx.getUserInfo({ 22 | success: (res) => { 23 | that.globalData.userInfo = res.userInfo; 24 | typeof cb == 'function' && cb(that.globalData.userInfo) 25 | } 26 | }) 27 | } 28 | }) 29 | } 30 | }, 31 | 32 | // 获取本地全部日记列表 33 | getDiaryList(cb) { 34 | var that = this; 35 | 36 | if (this.globalData.diaryList) { 37 | typeof cb == 'function' && cb(this.globalData.diaryList); 38 | } else { 39 | let list = []; 40 | 41 | this.getLocalDiaries(storage => { 42 | // 本地缓存数据 43 | for (var k in storage) { 44 | list.push(storage[k]); 45 | } 46 | }); 47 | 48 | // 本地假数据 49 | list.push(...diaries.diaries); 50 | that.globalData.diaryList = list; 51 | typeof cb == 'function' && cb(that.globalData.diaryList) 52 | } 53 | }, 54 | 55 | // 获取本地日记缓存 56 | getLocalDiaries(cb) { 57 | var that = this; 58 | 59 | if (this.globalData.localDiaries) { 60 | typeof cb == 'function' && cb(this.globalData.localDiaries); 61 | } else { 62 | wx.getStorage({ 63 | key: config.storage.diaryListKey, 64 | success: (res) => { 65 | that.globalData.localDiaries = res.data; 66 | typeof cb == 'function' && cb(that.globalData.localDiaries); 67 | }, 68 | fail: (error) => { 69 | that.globalData.localDiaries = {}; 70 | typeof cb == 'function' && cb(that.globalData.localDiaries); 71 | } 72 | }); 73 | } 74 | }, 75 | 76 | // 获取当前设备信息 77 | getDeviceInfo: function(callback) { 78 | var that = this; 79 | 80 | if (this.globalData.deviceInfo) { 81 | typeof callback == "function" && callback(this.globalData.deviceInfo) 82 | } else { 83 | wx.getSystemInfo({ 84 | success: function(res) { 85 | that.globalData.deviceInfo = res; 86 | typeof callback == "function" && callback(that.globalData.deviceInfo) 87 | } 88 | }) 89 | } 90 | }, 91 | 92 | globalData: { 93 | // 设备信息,主要用于获取屏幕尺寸而做适配 94 | deviceInfo: null, 95 | 96 | // 本地日记缓存列表 + 假数据 97 | // TODO 真实数据同步至服务端,本地只做部分缓存 98 | diaryList: null, 99 | 100 | // 本地日记缓存 101 | localDiaries: null, 102 | 103 | // 用户信息 104 | userInfo: null, 105 | } 106 | 107 | }) 108 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/list/list", 4 | "pages/mine/mine", 5 | "pages/new/new", 6 | "pages/entry/entry" 7 | ], 8 | "window":{ 9 | "backgroundTextStyle": "light", 10 | "navigationBarBackgroundColor": "#39b5de", 11 | "navigationBarTitleText": "小熊の日记", 12 | "navigationBarTextStyle": "white", 13 | "backgroundColor": "#eceff4" 14 | }, 15 | "tabBar": { 16 | "color": "#858585", 17 | "selectedColor": "#39b5de", 18 | "backgroundColor": "#ffffff", 19 | "borderStyle": "black", 20 | "list":[ 21 | { 22 | "pagePath": "pages/list/list", 23 | "iconPath": "images/icons/mark.png", 24 | "selectedIconPath": "images/icons/markHL.png", 25 | "text": "印记" 26 | }, 27 | { 28 | "pagePath": "pages/mine/mine", 29 | "iconPath": "images/icons/mine.png", 30 | "selectedIconPath": "images/icons/mineHL.png", 31 | "text": "我的" 32 | } 33 | ] 34 | }, 35 | "debug": true 36 | } 37 | -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /** 2 | app.wxss 3 | 全局样式 4 | **/ 5 | 6 | page { 7 | width: 100%; 8 | height: 100%; 9 | padding: 0; 10 | background-color: #eceff4; 11 | font-size: 30rpx; 12 | font-family: -apple-system-font, 'Helvetica Neue', Helvetica, 'Microsoft YaHei', sans-serif; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // 全局配置 2 | 3 | module.exports = { 4 | /** 腾讯地图 **/ 5 | map: { 6 | baseUrl: 'https://apis.map.qq.com/ws', 7 | key: '2TCBZ-IM7K5-XHCIZ-QXLRT-CIT4J-DEFSM', 8 | }, 9 | 10 | /** 输入框控件设置 **/ 11 | input: { 12 | charWidth: 14, // 单个字符的宽度,in rpx 13 | }, 14 | 15 | /** 本地存储 **/ 16 | // TODO 数据通过API全部存储于服务端 17 | storage: { 18 | diaryListKey: 'bearDiaryList', 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /demo/diaries.js: -------------------------------------------------------------------------------- 1 | var diaries = [ 2 | { 3 | meta: { // 内容元数据 4 | cover: "http://m.chanyouji.cn/index-cover/64695-2679221.jpg?imageView2/1/w/620/h/330/format/jpg", 5 | avatar: "https://pic4.zhimg.com/e515adf3b_xl.jpg", 6 | title: "此刻静好,愿幸福长存", 7 | meta: "2016.10.17", 8 | create_time: "2016.10.18 11:57:27", 9 | nickName: "肥肥的小狗熊", 10 | }, 11 | list: [ 12 | { 13 | type: "TEXT", 14 | content: '9月11日,15年的911事件使这天蒙上了特殊的意义。2016年的这一天,怀着激动的心情,开启了高原寻秘之旅,向着那圣洁之地出发。全程自驾近2000公里,雨崩徒步80公里,完成觐见之旅。', 15 | poi: { 16 | longitude: 117.2, 17 | latitude: 37.5, 18 | name: "北京市", 19 | }, 20 | description: "", 21 | id: 1, 22 | commentNum: 0, 23 | likeNum: 0, 24 | }, 25 | { 26 | type: "IMAGE", 27 | content: 'http://p.chanyouji.cn/1473699595/1740E45C-D5AF-497E-A351-06E5BA22B1A3.jpg', 28 | poi: { 29 | longitude: 117.2, 30 | latitude: 37.5, 31 | name: "深圳市", 32 | }, 33 | description: "深圳宝安国际机场", 34 | id: 2, 35 | commentNum: 1, 36 | likeNum: 5, 37 | }, 38 | { 39 | type: "IMAGE", 40 | content: 'http://p.chanyouji.cn/1473699603/7C3B253F-0A31-4754-B042-E04115F2C931.jpg', 41 | poi: { 42 | longitude: 117.2, 43 | latitude: 37.5, 44 | name: "丽江三义机场", 45 | }, 46 | description: "丽江三义机场", 47 | id: 2, 48 | commentNum: 1, 49 | likeNum: 5, 50 | }, 51 | { 52 | type: "TEXT", 53 | content: ' 玉水寨在白沙溪镇,是纳西族中部地区的东巴圣地,是丽江古城的溯源。\n\nTips:门票50元/人,游玩时间2小时。', 54 | poi: { 55 | longitude: 117.2, 56 | latitude: 37.5, 57 | name: "玉水寨", 58 | }, 59 | description: "", 60 | id: 1, 61 | commentNum: 0, 62 | likeNum: 0, 63 | }, 64 | { 65 | type: "IMAGE", 66 | content: 'http://p.chanyouji.cn/1473685830/2A48B40F-1F11-498D-ABD2-B0EDCD09F776.jpg', 67 | poi: { 68 | longitude: 117.2, 69 | latitude: 37.5, 70 | name: "玉水寨", 71 | }, 72 | description: "阳光下的玉水寨", 73 | id: 2, 74 | commentNum: 1, 75 | likeNum: 5, 76 | }, 77 | { 78 | type: "VIDEO", 79 | content: 'http://flv.bn.netease.com/videolib3/1605/22/auDfZ8781/HD/auDfZ8781-mobile.mp4', 80 | poi: { 81 | longitude: 117.2, 82 | latitude: 37.5, 83 | name: "深圳宝安国际机场", 84 | }, 85 | description: "", 86 | id: 2, 87 | commentNum: 10, 88 | likeNum: 200, 89 | }, 90 | ] 91 | }, 92 | { 93 | meta: { // 内容元数据 94 | cover: "http://m.chanyouji.cn/articles/625/ca9e50f74e273041e3a399bf5528f7b5.jpg?imageView2/1/w/620/h/330/format/jpg", 95 | avatar: "https://pic4.zhimg.com/e515adf3b_xl.jpg", 96 | title: "梦想实现的地方-马达加斯加第二季", 97 | meta: "2013.8.10", 98 | create_time: "2016.10.18 11:57:27", 99 | nickName: "小闹钟", 100 | }, 101 | list: [ 102 | { 103 | type: "TEXT", 104 | content: '2012年十一,我和朋友一行五人第一次登上这个被非洲大陆抛弃的岛屿,看到了可爱的狐猴,憨态可掬的变色龙,明信片一样的猴面包树,天真的孩子淳朴的人民,结识了我们生命中一个重要的朋友导游小温(可以加地接小温QQ或微信咨询:109300820),从此,我们爱上了这片土地。马达加斯加是一个海岛,一年分成旱季和雨季,没有特别的低温或者高温季节,几乎全年都适合旅游,只是观赏的重点略有不同而已。 \n导游小温向我们介绍,在这里,每年的7月到9月,可以近距离观看座头鲸,于是,我们从那时开始期待这个夏季的到来。', 105 | poi: { 106 | longitude: 117.2, 107 | latitude: 37.5, 108 | name: "塔那那利佛", 109 | }, 110 | description: "", 111 | id: 1, 112 | commentNum: 0, 113 | likeNum: 0, 114 | }, 115 | { 116 | type: "TEXT", 117 | content: '第一天 8月10日 天气晴\n\n长时间的飞行,多少会有一些枯燥,然而只要你愿意,依然可以看到心中的那片风景。 \n嗨!别郁闷了,和我一起到三万英尺的高空来看云。 \n喜欢飞机起飞的刹那间,加速再加速直到脱离开地球的引力冲向自由的天空。喜欢像鸟一样俯视地面的视角,高高在上,笑看人间。 \n天,蓝,云,白。机窗外的云时而像珍珠点点,时而像棉絮团团。\n夕阳将至,云和机翼被镀上一层华丽的金。 \n金红色的阳光与蓝色的天空最终合成出一片淡淡的紫,绚丽而梦幻。', 118 | poi: { 119 | longitude: 117.2, 120 | latitude: 37.5, 121 | name: "塔那那利佛", 122 | }, 123 | description: "", 124 | id: 1, 125 | commentNum: 0, 126 | likeNum: 0, 127 | }, 128 | { 129 | type: "IMAGE", 130 | content: 'http://p.chanyouji.cn/64695/1377177446705p182j2oa9031j1p0b5vpuvj1voj2.jpg-o', 131 | poi: { 132 | longitude: 117.2, 133 | latitude: 37.5, 134 | name: "塔那那利佛", 135 | }, 136 | description: "", 137 | id: 2, 138 | commentNum: 1, 139 | likeNum: 5, 140 | }, 141 | ] 142 | } 143 | ] 144 | 145 | module.exports = { 146 | diaries: diaries, 147 | } 148 | -------------------------------------------------------------------------------- /files/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/files/preview.gif -------------------------------------------------------------------------------- /images/icons/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/add.png -------------------------------------------------------------------------------- /images/icons/collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/collect.png -------------------------------------------------------------------------------- /images/icons/collectHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/collectHL.png -------------------------------------------------------------------------------- /images/icons/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/comment.png -------------------------------------------------------------------------------- /images/icons/compose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/compose.png -------------------------------------------------------------------------------- /images/icons/composeHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/composeHL.png -------------------------------------------------------------------------------- /images/icons/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/like.png -------------------------------------------------------------------------------- /images/icons/likeHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/likeHL.png -------------------------------------------------------------------------------- /images/icons/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/mark.png -------------------------------------------------------------------------------- /images/icons/markHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/markHL.png -------------------------------------------------------------------------------- /images/icons/mine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/mine.png -------------------------------------------------------------------------------- /images/icons/mineHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/mineHL.png -------------------------------------------------------------------------------- /images/icons/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/more.png -------------------------------------------------------------------------------- /images/icons/moreHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/moreHL.png -------------------------------------------------------------------------------- /images/icons/poi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/poi.png -------------------------------------------------------------------------------- /images/icons/strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/strategy.png -------------------------------------------------------------------------------- /images/icons/strategyHL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/strategyHL.png -------------------------------------------------------------------------------- /images/icons/user_privatemsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/icons/user_privatemsg.png -------------------------------------------------------------------------------- /images/nav/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/nav/comment.png -------------------------------------------------------------------------------- /images/nav/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/nav/download.png -------------------------------------------------------------------------------- /images/nav/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/nav/fav.png -------------------------------------------------------------------------------- /images/nav/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/nav/share.png -------------------------------------------------------------------------------- /images/tabbar/Plus Math.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/Plus Math.png -------------------------------------------------------------------------------- /images/tabbar/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/add.png -------------------------------------------------------------------------------- /images/tabbar/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/cancel.png -------------------------------------------------------------------------------- /images/tabbar/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/image.png -------------------------------------------------------------------------------- /images/tabbar/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/more.png -------------------------------------------------------------------------------- /images/tabbar/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/ok.png -------------------------------------------------------------------------------- /images/tabbar/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harveyqing/BearDiary/aee2bfa9f758268699591d319baadae5b4dd5626/images/tabbar/text.png -------------------------------------------------------------------------------- /pages/entry/entry.js: -------------------------------------------------------------------------------- 1 | // entry.js 2 | 3 | const toolbar = [ 4 | '../../images/nav/download.png', '../../images/nav/fav.png', 5 | '../../images/nav/share.png', '../../images/nav/comment.png', 6 | ]; 7 | const app = getApp(); 8 | 9 | Page({ 10 | data: { 11 | // 当前日志详情 12 | diary: undefined, 13 | 14 | // 右上角工具栏 15 | toolbar: toolbar, 16 | 17 | // 图片预览模式 18 | previewMode: false, 19 | 20 | // 当前预览索引 21 | previewIndex: 0, 22 | 23 | // 多媒体内容列表 24 | mediaList: [], 25 | }, 26 | 27 | // 加载日记 28 | getDiary(params) { 29 | console.log("Loading diary data...", params); 30 | 31 | var id = params["id"], diary; 32 | app.getDiaryList(list => { 33 | if (typeof id === 'undefined') { 34 | diary = list[0]; 35 | } else { 36 | diary = list[id]; 37 | } 38 | }); 39 | 40 | this.setData({ 41 | diary: diary, 42 | }); 43 | }, 44 | 45 | // 过滤出预览图片列表 46 | getMediaList() { 47 | if (typeof this.data.diary !== 'undefined' && 48 | this.data.diary.list.length) { 49 | this.setData({ 50 | mediaList: this.data.diary.list.filter( 51 | content => content.type === 'IMAGE'), 52 | }) 53 | } 54 | }, 55 | 56 | // 进入预览模式 57 | enterPreviewMode(event) { 58 | let url = event.target.dataset.src; 59 | let urls = this.data.mediaList.map(media => media.content); 60 | let previewIndex = urls.indexOf(url); 61 | 62 | this.setData({previewMode: true, previewIndex}); 63 | }, 64 | 65 | // 退出预览模式 66 | leavePreviewMode() { 67 | this.setData({previewMode: false, previewIndex: 0}); 68 | }, 69 | 70 | onLoad: function(params) { 71 | this.getDiary(params); 72 | this.getMediaList(); 73 | }, 74 | 75 | onHide: function() { 76 | }, 77 | }) 78 | -------------------------------------------------------------------------------- /pages/entry/entry.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {{diary.meta.title}} 51 | {{diary.meta.meta}} 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | THE 65 | END 66 | 67 | DESIGNED BY 小闹钟 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /pages/entry/entry.wxss: -------------------------------------------------------------------------------- 1 | /** item.wxss **/ 2 | 3 | .container { 4 | font-size: 26rpx; 5 | } 6 | 7 | .header { 8 | height: 400rpx; 9 | } 10 | 11 | .toolbar { 12 | height: 60rpx; 13 | position: fixed; 14 | top: 0; 15 | right: 0; 16 | display: flex; 17 | flex-direction: row; 18 | justify-content: space-between; 19 | align-items: center; 20 | } 21 | 22 | .toolbar .item { 23 | width: 40rpx; 24 | height: 40rpx; 25 | margin: 10rpx 20rpx; 26 | } 27 | 28 | .title { 29 | height: 120rpx; 30 | position: absolute; 31 | top: 280rpx; 32 | } 33 | 34 | .title .avatar { 35 | margin: 20rpx; 36 | width: 80rpx; 37 | height: 80rpx; 38 | border-radius: 40rpx; 39 | float: left; 40 | } 41 | 42 | .title .desc { 43 | height: 100rpx; 44 | width: 630rpx; 45 | margin: 10rpx 0; 46 | float: right; 47 | color: white; 48 | display: flex; 49 | flex-direction: column; 50 | } 51 | 52 | .desc .item { 53 | height: 50%; 54 | padding: 12rpx 0; 55 | } 56 | 57 | .content { 58 | padding: 10rpx; 59 | border-bottom: 1px solid #E5E7ED; 60 | } 61 | 62 | .content .text { 63 | line-height: 42rpx; 64 | } 65 | 66 | .content .media { 67 | width: 730rpx; 68 | } 69 | 70 | .content .footer { 71 | height: 60rpx; 72 | margin-top: 10rpx; 73 | font-size:22rpx; 74 | color: #70899D; 75 | } 76 | 77 | .content .footer image { 78 | width: 20rpx; 79 | height: 20rpx; 80 | } 81 | 82 | .content .footer .left { 83 | display: inline-block; 84 | height: 40rpx; 85 | margin: 10rpx 0; 86 | } 87 | 88 | .content .footer .right { 89 | display: flex; 90 | justify-content: space-between; 91 | align-items: center; 92 | float: right; 93 | height: 40rpx; 94 | margin-left: 20rpx; 95 | background-color: #E5E7ED; 96 | font-size: 20rpx; 97 | } 98 | 99 | .content .footer .right image { 100 | margin: 10rpx; 101 | } 102 | 103 | .content .footer .right text { 104 | font-size: 20rpx; 105 | padding:10rpx 10rpx 10rpx 0; 106 | } 107 | 108 | #footer { 109 | width: 100%; 110 | height: 300rpx; 111 | display: flex; 112 | justify-content: center; 113 | align-items: center; 114 | } 115 | 116 | #footer .container { 117 | height: 100rpx; 118 | display: flex; 119 | flex-direction: column; 120 | justify-content: space-between; 121 | align-items: center; 122 | } 123 | 124 | #footer .container .item { 125 | height: 50%; 126 | display: flex; 127 | justify-content: center; 128 | align-items: center; 129 | } 130 | 131 | .swiper-container { 132 | position: fixed; 133 | left: 0; 134 | top: 0; 135 | width: 100%; 136 | height: 100%; 137 | background-color: #000; 138 | } 139 | 140 | .swiper-container image { 141 | width: 100%; 142 | height: 100%; 143 | } 144 | -------------------------------------------------------------------------------- /pages/list/list.js: -------------------------------------------------------------------------------- 1 | // index.js 2 | // 日记聚合页 3 | 4 | const config = require("../../config"); 5 | 6 | var app = getApp(); 7 | 8 | Page({ 9 | 10 | data: { 11 | // 日记列表 12 | // TODO 从server端拉取 13 | diaries: null, 14 | 15 | // 是否显示loading 16 | showLoading: false, 17 | 18 | // loading提示语 19 | loadingMessage: '', 20 | }, 21 | 22 | /** 23 | * 生命周期函数--监听页面加载 24 | */ 25 | onLoad() { 26 | this.getDiaries(); 27 | }, 28 | 29 | /** 30 | * 获取日记列表 31 | * 目前为本地缓存数据 + 本地假数据 32 | * TODO 从服务端拉取 33 | */ 34 | getDiaries() { 35 | var that = this; 36 | app.getDiaryList(list => { 37 | that.setData({diaries: list}); 38 | }) 39 | }, 40 | 41 | // 查看详情 42 | showDetail(event) { 43 | wx.navigateTo({ 44 | url: '../entry/entry?id=' + event.currentTarget.id, 45 | }); 46 | } 47 | }) 48 | -------------------------------------------------------------------------------- /pages/list/list.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{item.meta.title}} 9 | {{item.meta.meta}} 10 | 11 | 12 | 13 | {{item.meta.nickName}} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pages/list/list.wxss: -------------------------------------------------------------------------------- 1 | /** list.wxss **/ 2 | 3 | .item-container { 4 | margin: 10rpx 20rpx; 5 | position: relative; 6 | } 7 | 8 | .cover { 9 | width: 100%; 10 | height: 400rpx; 11 | display: block; 12 | } 13 | 14 | .desc { 15 | margin: 10rpx 0; 16 | display: flex; 17 | justify-content: space-between; 18 | align-items: center; 19 | padding-bottom: 20rpx; 20 | border-bottom: 1px solid #E5E7ED; 21 | } 22 | 23 | .desc .left { 24 | } 25 | 26 | .desc .right { 27 | display: flex; 28 | flex-direction: column; 29 | align-items: center; 30 | } 31 | 32 | .right image{ 33 | display: block; 34 | width: 60rpx; 35 | height: 60rpx; 36 | border-radius: 30rpx; 37 | } 38 | -------------------------------------------------------------------------------- /pages/mine/mine.js: -------------------------------------------------------------------------------- 1 | // mine.js 2 | 3 | // 自定义标签 4 | var iconPath = "../../images/icons/" 5 | var tabs = [ 6 | { 7 | "icon": iconPath + "mark.png", 8 | "iconActive": iconPath + "markHL.png", 9 | "title": "日记", 10 | "extraStyle": "", 11 | }, 12 | { 13 | "icon": iconPath + "collect.png", 14 | "iconActive": iconPath + "collectHL.png", 15 | "title": "收藏", 16 | "extraStyle": "", 17 | }, 18 | { 19 | "icon": iconPath + "like.png", 20 | "iconActive": iconPath + "likeHL.png", 21 | "title": "喜欢", 22 | "extraStyle": "", 23 | }, 24 | { 25 | "icon": iconPath + "more.png", 26 | "iconActive": iconPath + "moreHL.png", 27 | "title": "更多", 28 | "extraStyle": "border:none;", 29 | }, 30 | ] 31 | var userInfo = { 32 | avatar: "https://pic4.zhimg.com/e515adf3b_xl.jpg", 33 | nickname: "小闹钟", 34 | sex: "♂", // 0, male; 1, female 35 | meta: '1篇日记', 36 | } 37 | 38 | 39 | Page({ 40 | 41 | // data 42 | data: { 43 | // 展示的tab标签 44 | tabs: tabs, 45 | 46 | // 当前选中的标签 47 | currentTab: "tab1", 48 | 49 | // 高亮的标签索引 50 | highLightIndex: "0", 51 | 52 | // 模态对话框样式 53 | modalShowStyle: "", 54 | 55 | // 待新建的日记标题 56 | diaryTitle: "", 57 | 58 | // TODO 用户信息 59 | userInfo: userInfo, 60 | }, 61 | 62 | // 隐藏模态框 63 | hideModal() { 64 | this.setData({modalShowStyle: ""}); 65 | }, 66 | 67 | // 清除日记标题 68 | clearTitle() { 69 | this.setData({diaryTitle: ""}); 70 | }, 71 | 72 | onShow: function() { 73 | this.hideModal(); 74 | this.clearTitle(); 75 | }, 76 | 77 | // 点击tab项事件 78 | touchTab: function(event){ 79 | var tabIndex = parseInt(event.currentTarget.id); 80 | var template = "tab" + (tabIndex + 1).toString(); 81 | 82 | this.setData({ 83 | currentTab: template, 84 | highLightIndex: tabIndex.toString() 85 | } 86 | ); 87 | }, 88 | 89 | // 点击新建日记按钮 90 | touchAdd: function (event) { 91 | this.setData({ 92 | modalShowStyle: "opacity:1;pointer-events:auto;" 93 | }) 94 | }, 95 | 96 | // 新建日记 97 | touchAddNew: function(event) { 98 | this.hideModal(); 99 | 100 | wx.navigateTo({ 101 | url: "../new/new?title=" + this.data.diaryTitle, 102 | }); 103 | }, 104 | 105 | // 取消标题输入 106 | touchCancel: function(event) { 107 | this.hideModal(); 108 | this.clearTitle(); 109 | }, 110 | 111 | // 标题输入事件 112 | titleInput: function(event) { 113 | this.setData({ 114 | diaryTitle: event.detail.value, 115 | }) 116 | } 117 | }) 118 | -------------------------------------------------------------------------------- /pages/mine/mine.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 请输入日记标题 29 | 30 | 31 | 32 | 33 | 34 | 确定 35 | 取消 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | {{userInfo.nickname}} 46 | {{userInfo.sex}} 47 | 48 | {{userInfo.meta}} 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {{item.title}} 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /pages/mine/mine.wxss: -------------------------------------------------------------------------------- 1 | /**mine.wxss**/ 2 | 3 | .header { 4 | height: 130px; 5 | background: white; 6 | } 7 | 8 | .header .profile { 9 | height: 50%; 10 | } 11 | 12 | .profile .avatar { 13 | width: 50px; 14 | height: 50px; 15 | float: left; 16 | margin: 7.5px 10px; 17 | border-radius: 25px; 18 | } 19 | 20 | .profile .description { 21 | display: inline-block; 22 | margin: 7.5px auto; 23 | height: 50px; 24 | } 25 | 26 | .description .item { 27 | height: 50%; 28 | display: flex; 29 | align-items: center; 30 | } 31 | 32 | .profile .add { 33 | float: right; 34 | margin: 15px 10px; 35 | height: 35px; 36 | width: 35px; 37 | } 38 | 39 | .header .tablist { 40 | height: 50%; 41 | display: flex; 42 | justify-content: space-between; 43 | align-items: center; 44 | } 45 | 46 | .tablist .tab { 47 | display: flex; 48 | justify-content: center; 49 | align-items: center; 50 | height: 50px; 51 | width: 25%; 52 | margin: 7.5px 0px; 53 | border-right: 1px solid #eceff4; 54 | } 55 | 56 | .tab .content{ 57 | width: 25px; 58 | height: 50px; 59 | font-size: 12px; 60 | color: #B3B3B3; 61 | } 62 | 63 | .tab .image { 64 | width: 25px; 65 | height: 25px; 66 | margin-top: 10px; 67 | } 68 | 69 | .modal { 70 | position: fixed; 71 | top: 0; 72 | left: 0; 73 | bottom: 0; 74 | right: 0; 75 | background: rgba(0, 0, 0, .5); 76 | z-index: 99999; 77 | opacity: 0; 78 | transition: opacity 400ms ease-in; 79 | pointer-events: none; 80 | display: flex; 81 | justify-content: center; 82 | align-items: center; 83 | } 84 | 85 | .modal .dialog { 86 | width: 84%; 87 | height: 28%; 88 | background-color: #eceff4; 89 | border-radius: 4px; 90 | display: flex; 91 | flex-direction: column; 92 | justify-content: space-between; 93 | } 94 | 95 | .dialog .modal-item { 96 | height: 33.3%; 97 | width: 100%; 98 | } 99 | 100 | .modal-button { 101 | height: 100rpx; 102 | margin-bottom: 0; 103 | display: flex; 104 | flex-direction: row; 105 | justify-content: space-between; 106 | } 107 | 108 | .modal-button view { 109 | width: 50%; 110 | border-top: 1px solid #E5E7ED; 111 | display: flex; 112 | justify-content: center; 113 | align-items: center; 114 | } -------------------------------------------------------------------------------- /pages/new/new.js: -------------------------------------------------------------------------------- 1 | // new.js 2 | // TODO 并不是所有非中文字符宽度都为中文字符宽度一半,需特殊处理 3 | // TODO 由于文本框聚焦存在bug,故编辑模式待实现 4 | 5 | const input = require('../../utils/input'); 6 | const config = require('../../config'); 7 | const geo = require('../../services/geo'); 8 | const util = require('../../utils/util'); 9 | 10 | const RESOLUTION = 750; // 微信规定屏幕宽度为750rpx 11 | const MARGIN = 10; // 写字面板左右margin 12 | const ROW_CHARS = Math.floor((RESOLUTION - 2 * MARGIN) / config.input.charWidth); 13 | const MAX_CHAR = 1000; // 最多输1000字符 14 | 15 | // 内容布局 16 | const layoutColumnSize = 3; 17 | 18 | // 日记内容类型 19 | const TEXT = 'TEXT'; 20 | const IMAGE = 'IMAGE'; 21 | const VIDEO = 'VIDEO'; 22 | 23 | const mediaActionSheetItems = ['拍照', '选择照片', '选择视频']; 24 | const mediaActionSheetBinds = ['chooseImage', 'chooseImage', 'chooseVideo']; 25 | 26 | var app = getApp(); 27 | 28 | Page({ 29 | 30 | data: { 31 | // 日记对象 32 | diary: { 33 | meta: {}, 34 | list: [], 35 | }, 36 | 37 | // 日记内容布局列表(2x2矩阵) 38 | layoutList: [], 39 | 40 | // 是否显示loading 41 | showLoading: false, 42 | 43 | // loading提示语 44 | loadingMessage: '', 45 | 46 | // 页面所处模式 47 | showMode: 'common', 48 | 49 | // 输入框状态对象 50 | inputStatus: { 51 | row: 0, 52 | column: 0, 53 | lines: [''], 54 | mode: 'INPUT', 55 | auto: false, // 是否有自动换行 56 | }, 57 | 58 | // 当前位置信息 59 | poi: null, 60 | 61 | // 点击`图片`tab的action-sheet 62 | mediaActionSheetHidden: true, 63 | 64 | // 多媒体文件插入action-sheet 65 | mediaActionSheetItems: mediaActionSheetItems, 66 | 67 | // 多媒体文件插入项点击事件 68 | mediaActionSheetBinds: mediaActionSheetBinds, 69 | 70 | // 是否显示底部tab栏 71 | showTab: true, 72 | }, 73 | 74 | // 显示底部tab 75 | showTab() { 76 | this.setData({showTab: true}); 77 | }, 78 | 79 | // 隐藏底部tab 80 | hideTab() { 81 | this.setData({showTab: false}); 82 | }, 83 | 84 | // 显示loading提示 85 | showLoading(loadingMessage) { 86 | this.setData({showLoading: true, loadingMessage}); 87 | }, 88 | 89 | // 隐藏loading提示 90 | hideLoading() { 91 | this.setData({showLoading: false, loadingMessage: ''}); 92 | }, 93 | 94 | // 数据初始化 95 | init() { 96 | this.getPoi(); 97 | this.setMeta(); 98 | }, 99 | 100 | // 设置日记数据 101 | setDiary(diary) { 102 | let layout = util.listToMatrix(diary.list, layoutColumnSize); 103 | this.setData({diary: diary, layoutList: layout}); 104 | this.saveDiary(diary); 105 | }, 106 | 107 | // 保存日记 108 | // TODO sync to server 109 | saveDiary(diary) { 110 | const key = config.storage.diaryListKey; 111 | 112 | app.getLocalDiaries(diaries => { 113 | diaries[diary.meta.title] = diary; 114 | wx.setStorage({key: key, data: diaries}); 115 | }) 116 | }, 117 | 118 | // 页面初始化 119 | onLoad: function(options) { 120 | if (options) { 121 | let title = options.title; 122 | if (title) {this.setData({ 123 | 'diary.meta.title': title, 124 | 'diary.meta.create_time': util.formatTime(new Date()), 125 | 'diary.meta.cover': '' 126 | });} 127 | } 128 | 129 | this.init(); 130 | }, 131 | 132 | // 页面渲染完成 133 | onReady: function(){ 134 | wx.setNavigationBarTitle({title: '编辑日记'}); 135 | }, 136 | 137 | onShow:function(){ 138 | // 页面显示 139 | }, 140 | 141 | onHide:function(){ 142 | // 页面隐藏 143 | }, 144 | 145 | onUnload:function(){ 146 | // 页面关闭 147 | console.log('页面跳转中...'); 148 | }, 149 | 150 | // 清除正在输入文本 151 | clearInput() { 152 | this.setData({inputStatus: { 153 | row: 0, 154 | common: 0, 155 | lines: [''], 156 | mode: 'INPUT', 157 | auto: false, 158 | }}); 159 | }, 160 | 161 | // 结束文本输入 162 | inputDone() { 163 | let text = this.data.inputStatus.lines.join('\n'); 164 | let diary = this.data.diary; 165 | 166 | if (text) { 167 | diary.list.push(this.makeContent(TEXT, text, '')); 168 | this.setDiary(diary); 169 | } 170 | 171 | this.inputCancel(); 172 | }, 173 | 174 | // 进入文本编辑模式 175 | inputTouch(event) { 176 | this.setData({showMode: 'inputText'}); 177 | }, 178 | 179 | // 取消文本编辑 180 | inputCancel() { 181 | this.setData({showMode: 'common'}); 182 | this.clearInput(); 183 | }, 184 | 185 | // 文本输入 186 | textInput(event) { 187 | console.log(event); 188 | let context = event.detail; 189 | 190 | // 输入模式 191 | if (this.data.inputStatus.mode === 'INPUT') { 192 | if (context.value.length != context.cursor) { 193 | console.log('用户输入中...'); 194 | } else { 195 | let text = context.value; 196 | let len = input.strlen(text); 197 | let lines = this.data.inputStatus.lines; 198 | let row = this.data.inputStatus.row; 199 | let [extra, extra_index] = [[['']], 0]; 200 | let hasNewLine = false; 201 | console.log('当前文本长度: ' + len); 202 | 203 | // 当前输入长度超过规定长度 204 | if (len >= ROW_CHARS) { 205 | // TODO 此处方案不完善 206 | // 一次输入最好不超过两行 207 | hasNewLine = true; 208 | while (input.strlen(text) > ROW_CHARS) { 209 | let last = text[text.length - 1]; 210 | 211 | if (input.strlen(extra[extra_index] + last) > ROW_CHARS) { 212 | extra_index += 1; 213 | extra[extra_index] = ['']; 214 | } 215 | 216 | extra[extra_index].unshift(last); 217 | text = text.slice(0, -1); 218 | } 219 | } 220 | 221 | lines[lines.length - 1] = text; 222 | if (hasNewLine) { 223 | extra.reverse().forEach((element, index, array) => { 224 | lines.push(element.join('')); 225 | row += 1; 226 | }); 227 | } 228 | 229 | let inputStatus = { 230 | lines: lines, 231 | row: row, 232 | mode: 'INPUT', 233 | auto: true, // // 自动换行的则处于输入模式 234 | }; 235 | 236 | this.setData({inputStatus}); 237 | } 238 | } 239 | }, 240 | 241 | // 文本框获取到焦点 242 | focusInput(event) { 243 | let isInitialInput = this.data.inputStatus.row == 0 && 244 | this.data.inputStatus.lines[0].length == 0; 245 | let isAutoInput = this.data.inputStatus.mode == 'INPUT' && 246 | this.data.inputStatus.auto == true; 247 | let mode = 'EDIT'; 248 | 249 | if (isInitialInput || isAutoInput) { 250 | mode = 'INPUT'; 251 | } 252 | 253 | this.setData({'inputStatus.mode': mode}); 254 | }, 255 | 256 | // 点击多媒体插入按钮 257 | mediaTouch() { 258 | this.setData({ 259 | showTab: false, 260 | mediaActionSheetHidden: false, 261 | }); 262 | }, 263 | 264 | mediaActionSheetChange(event) { 265 | this.setData({ 266 | showTab: true, 267 | mediaActionSheetHidden: true, 268 | }) 269 | }, 270 | 271 | // 将内容写入至日记对象 272 | writeContent(res, type) { 273 | let diary = this.data.diary; 274 | 275 | if (type === IMAGE) { 276 | res.tempFilePaths.forEach((element, index, array) => { 277 | // TODO 内容上传至服务器 278 | diary.list.push(this.makeContent(type, element, '')) 279 | }); 280 | } 281 | 282 | if (type === VIDEO) { 283 | // TODO 内容上传至服务器 284 | diary.list.push(this.makeContent(type, res.tempFilePath, '')) 285 | } 286 | 287 | // 设置日记封面 288 | if (type === IMAGE && !this.data.diary.meta.cover) { 289 | this.setData({'diary.meta.cover': res.tempFilePaths[0]}); 290 | } 291 | 292 | this.setDiary(diary); 293 | this.hideLoading(); 294 | this.showTab(); 295 | }, 296 | 297 | // 从相册选择照片或拍摄照片 298 | chooseImage() { 299 | let that = this; 300 | 301 | wx.chooseImage({ 302 | count: 9, // 最多选9张 303 | sizeType: ['origin', 'compressed'], 304 | sourceType: ['album', 'camera'], 305 | 306 | success: (res) => { 307 | this.setData({mediaActionSheetHidden: true}); 308 | this.showLoading('图片处理中...'); 309 | that.writeContent(res, IMAGE); 310 | } 311 | }) 312 | }, 313 | 314 | // 从相册选择视频文件 315 | chooseVideo() { 316 | let that = this; 317 | 318 | wx.chooseVideo({ 319 | sourceType: ['album'], // 仅从相册选择 320 | success: (res) => { 321 | this.setData({mediaActionSheetHidden: true}); 322 | this.showLoading('视频处理中...'); 323 | that.writeContent(res, VIDEO); 324 | } 325 | }) 326 | }, 327 | 328 | // 获得当前位置信息 329 | getPoi() { 330 | var that = this; 331 | wx.getLocation({ 332 | type: 'gcj02', 333 | success: function(res) { 334 | geo.mapRequest( 335 | 'geocoder', 336 | {'location': geo.formatLocation(res)}, 337 | loc => { 338 | let poi = { 339 | 'latitude': res.latitude, 340 | 'longitude': res.longitude, 341 | 'name': loc.result.address, 342 | }; 343 | that.setData({poi: poi}); 344 | }) 345 | } 346 | }) 347 | }, 348 | 349 | // 构造日记内容对象 350 | makeContent(type, content, description) { 351 | return { 352 | type: type, 353 | content: content, 354 | description: description, 355 | poi: this.data.poi, 356 | }; 357 | }, 358 | 359 | // 构造日记meta信息 360 | setMeta() { 361 | var that = this; 362 | app.getUserInfo(info => { 363 | that.setData({ 364 | 'diary.meta.avatar': info.avatarUrl, 365 | 'diary.meta.nickName': info.nickName, 366 | }) 367 | }) 368 | }, 369 | 370 | }) 371 | -------------------------------------------------------------------------------- /pages/new/new.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 45 | 46 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | -------------------------------------------------------------------------------- /pages/new/new.wxss: -------------------------------------------------------------------------------- 1 | /** new.wxss **/ 2 | 3 | .container { 4 | height: 91%; 5 | } 6 | 7 | .common-container { 8 | margin: 0.1rem; 9 | } 10 | 11 | .item-group { 12 | display: flex; 13 | align-items: center; 14 | } 15 | 16 | .album-item { 17 | flex-direction: column; 18 | margin: 0.1rem; 19 | background: white; 20 | width: 6.4rem; 21 | height: 6.4rem; 22 | } 23 | 24 | .content-text{ 25 | justify-content: center; 26 | align-items: center; 27 | display: flex; 28 | } 29 | 30 | .content-text view { 31 | overflow: hidden; 32 | text-overflow: ellipsis; 33 | font-size: 10px; 34 | line-height: 15px; 35 | } 36 | 37 | .tabbar { 38 | position: fixed; 39 | width: 100%; 40 | height: 8%; 41 | left: 0; 42 | right: 0; 43 | bottom: 0; 44 | background-color: white; 45 | display: flex; 46 | flex-direction: row; 47 | justify-content: space-between; 48 | } 49 | 50 | .tabbar .item { 51 | width: 33.33%; 52 | display: flex; 53 | justify-content: center; 54 | align-items: center; 55 | } 56 | 57 | .item .icon { 58 | width: 50rpx; 59 | height: 50rpx; 60 | } 61 | 62 | .input-container { 63 | height: 80%; 64 | background-color: #eceff4; 65 | background-image: linear-gradient(#E1E6EA .1em, transparent .1em); 66 | background-size: 100% 48rpx; 67 | padding: 0; 68 | box-sizing: border-box; 69 | margin: 0 10rpx; 70 | } 71 | 72 | .input-container input{ 73 | height: 47rpx; 74 | max-height: 47rpx; 75 | font-size: 28rpx; 76 | margin: 0px; 77 | } 78 | 79 | .action-item, .action-cacel { 80 | font-size: 30rpx; 81 | color: #39b5de; 82 | } 83 | -------------------------------------------------------------------------------- /services/geo.js: -------------------------------------------------------------------------------- 1 | // 基于腾讯地图API的地理位置功能封装 2 | 3 | const config = require('../config.js'); 4 | const request = require('request.js'); 5 | 6 | const statusCodeMap = { // 请求失败原因映射 7 | 110: '请求来源未被授权', 8 | 301: '请求参数信息有误', 9 | 311: 'key格式错误', 10 | 306: '请求有护持信息请检查字符串', 11 | } 12 | 13 | module.exports = { 14 | 15 | // 地图API请求方法 16 | mapRequest(method, params, callback) { 17 | var url = [config.map.baseUrl, method, 'v1/'].join('/'); 18 | let param = Object.assign({'key': config.map.key}, params); 19 | let queryString = Object.keys(param).map(q => [q, param[q]].join('=')).join('&'); 20 | url += '?' + queryString; 21 | 22 | request({'method': 'GET', 'url': url}).then(resp => { 23 | if (resp.status != 0) { 24 | console.log('请求错误:' + (statusCodeMap[resp.status] || resp.message)); 25 | request 26 | } 27 | 28 | return callback(resp); 29 | }).catch(err => {console.log(err);}); 30 | }, 31 | 32 | // 格式化地理位置 33 | formatLocation(loc) { 34 | return [loc.latitude, loc.longitude].map(f => f.toString()).join(','); 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /services/request.js: -------------------------------------------------------------------------------- 1 | // 对微信网络请求的异步封装 2 | 3 | module.exports = (options) => { 4 | return new Promise((resolve, reject) => { 5 | options = Object.assign(options, { 6 | success(result) { 7 | if (result.statusCode === 200) { 8 | resolve(result.data); 9 | } else { 10 | reject(result); 11 | } 12 | }, 13 | 14 | fail: reject, 15 | }); 16 | 17 | wx.request(options); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /utils/input.js: -------------------------------------------------------------------------------- 1 | // 输入框相关处理函数 2 | 3 | module.exports = { 4 | 5 | // 计算字符串长度(英文占一个字符,中文汉字占2个字符) 6 | strlen(str) { 7 | var len = 0; 8 | for (var i = 0; i < str.length; i++) { 9 | var c = str.charCodeAt(i); 10 | if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) { 11 | len++; 12 | } else { 13 | len += 2; 14 | } 15 | } 16 | return len; 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | // 工具函数 2 | 3 | function formatTime(date) { 4 | var year = date.getFullYear() 5 | var month = date.getMonth() + 1 6 | var day = date.getDate() 7 | 8 | var hour = date.getHours() 9 | var minute = date.getMinutes() 10 | var second = date.getSeconds(); 11 | 12 | 13 | return [year, month, day].map(formatNumber).join('.') + ' ' + [hour, minute, second].map(formatNumber).join(':') 14 | } 15 | 16 | function formatNumber(n) { 17 | n = n.toString() 18 | return n[1] ? n : '0' + n 19 | } 20 | 21 | // 将一维数组转为二维数组 22 | function listToMatrix(list, elementPerSubArray) { 23 | let matrix = [], i, k; 24 | 25 | for (i = 0, k = -1; i < list.length; i += 1) { 26 | if (i % elementPerSubArray === 0) { 27 | k += 1; 28 | matrix[k] = []; 29 | } 30 | 31 | matrix[k].push(list[i]); 32 | } 33 | 34 | return matrix; 35 | } 36 | 37 | module.exports = { 38 | formatTime: formatTime, 39 | listToMatrix: listToMatrix, 40 | } 41 | --------------------------------------------------------------------------------