├── pages ├── todos │ ├── todos.js │ ├── todos.wxml │ └── todos.wxss ├── logs │ ├── logs.json │ ├── logs.wxss │ ├── logs.wxml │ └── logs.js ├── doing │ ├── doing.wxml │ ├── doing.wxss │ └── doing.js └── todo │ ├── todo.wxml │ ├── todo.wxss │ └── todo.js ├── images ├── wxxcx.gif ├── icon_db.png ├── icon_dbj.png ├── icon_db_HL.png └── icon_dbj_HL.png ├── app.js ├── app.wxss ├── utils └── util.js ├── README.md └── app.json /pages/todos/todos.js: -------------------------------------------------------------------------------- 1 | Page({ 2 | 3 | }) -------------------------------------------------------------------------------- /pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /images/wxxcx.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maczyt/wxapp_ToDo/HEAD/images/wxxcx.gif -------------------------------------------------------------------------------- /images/icon_db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maczyt/wxapp_ToDo/HEAD/images/icon_db.png -------------------------------------------------------------------------------- /images/icon_dbj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maczyt/wxapp_ToDo/HEAD/images/icon_dbj.png -------------------------------------------------------------------------------- /images/icon_db_HL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maczyt/wxapp_ToDo/HEAD/images/icon_db_HL.png -------------------------------------------------------------------------------- /images/icon_dbj_HL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maczyt/wxapp_ToDo/HEAD/images/icon_dbj_HL.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /pages/todos/todos.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 当前没有ToDos, 点击+号创建一个吧 5 | 6 | -------------------------------------------------------------------------------- /pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | //调用API从本地缓存中获取数据 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | } 9 | }) -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: space-between; 7 | padding: 40rpx 40rpx 0; 8 | box-sizing: border-box; 9 | } 10 | -------------------------------------------------------------------------------- /pages/todos/todos.wxss: -------------------------------------------------------------------------------- 1 | /**todos.wxss**/ 2 | .not-todo { 3 | min-height: 100%; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | .text { 9 | font-size: 28rpx; 10 | color: #999999; 11 | } -------------------------------------------------------------------------------- /pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | var util = require('../../utils/util.js') 3 | Page({ 4 | data: { 5 | logs: [] 6 | }, 7 | onLoad: function () { 8 | this.setData({ 9 | logs: (wx.getStorageSync('logs') || []).map(function (log) { 10 | return util.formatTime(new Date(log)) 11 | }) 12 | }) 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | function formatTime(date) { 2 | var year = date.getFullYear() 3 | var month = date.getMonth() + 1 4 | var day = date.getDate() 5 | 6 | var hour = date.getHours() 7 | var minute = date.getMinutes() 8 | var second = date.getSeconds() 9 | 10 | 11 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 12 | } 13 | 14 | function formatNumber(n) { 15 | n = n.toString() 16 | return n[1] ? n : '0' + n 17 | } 18 | 19 | module.exports = { 20 | formatTime: formatTime 21 | } 22 | -------------------------------------------------------------------------------- /pages/doing/doing.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{wisdom}} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{time}} 16 | 17 | 18 | {{tdTitle}} 19 | 进行中 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微信小程序 ToDoList 2 | 3 | ## 说明书 4 | 5 | 1. 新增ToDo,目前只有[5, 25, 35]的时间选择,以后将可以自定义时间 6 | 2. 在进行todo时,`header`目前是写死了,我写了五条名言随机出现,以后将增加更多或者直接进行网络请求 7 | 3. ToDos(待办集)目前还没开发(因为我也没使用过待办集,嘻嘻~~~) 8 | 4. 导航 9 | ``` 10 | 1. todo(首页) 11 | 2. doing(进行页) 12 | 3. todos(待办集页) 13 | 4. logs(日志页) 14 | ``` 15 | 16 | ## 开发遇到的问题 17 | 18 | 1. 首先就是页面间的跳转问题,*并不知道该用如何以正确姿势来使用*,看了官方文档只发现到导航,并使用了,结果差强人意 19 | 2. 组件的控制,发现没有DOM(可能是我没找到吧),好多效果都没有实现 20 | 3. 倒计时动画,使用了wx.createAnimation,当然让我很不爽,问题应该出自二 21 | 4. placeholder-(style|class)和按钮的hover-class不起效,估计是姿势不对 22 | 23 | --- 24 | 25 | ## 暂时的效果图 26 | 27 | 效果图 28 | 29 | --- 30 | 31 | ## 学习资料 32 | 33 | 1. [官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/index.html) 34 | 2. [设计指南](https://mp.weixin.qq.com/debug/wxadoc/design/index.html) 35 | 3. [开发工具](https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html?t=1474644089359) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/todo/todo", 4 | "pages/todos/todos", 5 | "pages/doing/doing", 6 | "pages/logs/logs" 7 | ], 8 | "window":{ 9 | "backgroundTextStyle":"light", 10 | "navigationBarBackgroundColor": "#393F4F", 11 | "navigationBarTitleText": "ToDo", 12 | "navigationBarTextStyle":"white" 13 | }, 14 | "tabBar": { 15 | "color": "#515151", 16 | "selectedColor": "#0e932e", 17 | "borderStyle": "black", 18 | "backgroundColor": "#ffffff", 19 | "list": [ 20 | { 21 | "pagePath": "pages/todo/todo", 22 | "iconPath": "images/icon_db.png", 23 | "selectedIconPath": "images/icon_db_HL.png", 24 | "text": "待办" 25 | }, 26 | { 27 | "pagePath": "pages/todos/todos", 28 | "iconPath": "images/icon_dbj.png", 29 | "selectedIconPath": "images/icon_dbj_HL.png", 30 | "text": "待办集" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pages/doing/doing.wxss: -------------------------------------------------------------------------------- 1 | /**doing.wxss**/ 2 | .container { 3 | background: #ff6666; 4 | } 5 | .wisdom { 6 | width: 100%; 7 | line-height: 1.3; 8 | color: white; 9 | font-size: 30rpx; 10 | font-weight: bold; 11 | } 12 | .wisdom::before { 13 | content: '“'; 14 | display: block; 15 | float: left; 16 | font-size: 60rpx; 17 | line-height: .6; 18 | color: white; 19 | margin-right: 20rpx; 20 | } 21 | 22 | /**圆动画**/ 23 | .circle { 24 | width: 360rpx; 25 | height: 360rpx; 26 | line-height: 360rpx; 27 | border-radius: 50%; 28 | text-align: center; 29 | margin: -100rpx auto 0; 30 | font-weight: bold; 31 | font-size: 50rpx; 32 | color: white; 33 | position: relative; 34 | } 35 | .left, .right { 36 | position: absolute; 37 | width: 186rpx; 38 | height: 372rpx; 39 | top: -6rpx; 40 | overflow: hidden; 41 | } 42 | .left { 43 | left: -6rpx; 44 | } 45 | .right { 46 | right: -6rpx; 47 | } 48 | #l-after, #r-after { 49 | width: 360rpx; 50 | height: 360rpx; 51 | border-width: 6rpx; 52 | border-style: solid; 53 | border-color: transparent transparent white white; 54 | top: 0; 55 | position: absolute; 56 | border-radius: 50%; 57 | transform: rotate(-135deg); 58 | } 59 | #l-after { 60 | left: 0; 61 | } 62 | #r-after { 63 | right: 0; 64 | border-color: white white transparent transparent; 65 | } 66 | 67 | /**圆动画 END**/ 68 | 69 | .td-title { 70 | width: 100%; 71 | margin-bottom: 100rpx; 72 | text-algin: center; 73 | } 74 | .title, .doing { 75 | text-align: center; 76 | font-size: 20rpx; 77 | color: white; 78 | } 79 | .title { 80 | margin-bottom: 10rpx; 81 | font-size: 40rpx; 82 | } -------------------------------------------------------------------------------- /pages/todo/todo.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 当前没有ToDo, 点击+号创建一个吧 5 | 6 | + 7 | 8 | 9 | 10 | 11 | 12 | {{item.name}} 13 | {{item.time}}分钟 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 33 | 34 | 35 | 38 | 39 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /pages/doing/doing.js: -------------------------------------------------------------------------------- 1 | Page({ 2 | data: { 3 | wisdoms: [ 4 | '你热爱生命吗?那么别浪费时间,因为时间是构成生命的材料。', 5 | '炫耀什么,说明内心缺少什么。', 6 | '丈夫志四海,万里犹比邻。', 7 | '再牛的梦想,也抵不住你傻瓜似的坚持。', 8 | '知而好问,然后能才。' 9 | ], 10 | wisdom: '', 11 | animateLeft: {}, 12 | animateRight: {}, 13 | tdTitle: '', 14 | time: '开始', 15 | timeTotal: 0 16 | }, 17 | onShow: function() { 18 | var wisdoms = this.data.wisdoms; 19 | var index = Math.floor(Math.random()*wisdoms.length); 20 | var time = Number(wx.getStorageSync('todoTime')); 21 | var name = wx.getStorageSync('todoName'); 22 | this.setData({ 23 | wisdom: wisdoms[index], 24 | timeTotal: time, 25 | tdTitle: name 26 | }) 27 | var animation = wx.createAnimation({ 28 | duration: 1000, 29 | timingFunction: "ease", 30 | delay: 0 31 | }); 32 | this.animation = animation; 33 | setTimeout(function () { 34 | animation.rotate(45).step(); 35 | this.setData({ 36 | animateRight: animation.export() 37 | }) 38 | }.bind(this), 1000) 39 | 40 | setTimeout(function () { 41 | animation.rotate(45).step(); 42 | this.setData({ 43 | animateLeft: animation.export() 44 | }) 45 | }.bind(this), 2000) 46 | 47 | setTimeout(this.countDown.bind(this), 3000); 48 | }, 49 | // 倒计时控制函数 50 | countDown: function() { 51 | var time = this.data.timeTotal 52 | var second = time * 60; 53 | this.changeCD(second); 54 | }, 55 | changeCD: function(t) { 56 | setTimeout(function () { 57 | t --; 58 | var branch = 0, second = t % 60; 59 | if (t >= 60) { 60 | branch = Math.floor(t / 60); 61 | } 62 | branch = branch < 10 ? '0'+branch : ''+branch; 63 | second = second < 10 ? '0'+second : ''+second; 64 | this.setData({ 65 | time: branch+':'+second 66 | }) 67 | var total = this.data.timeTotal * 60; 68 | var animation = this.animation; 69 | if (t > total/2) { 70 | animation.rotate(45-(total - t)/total*360).step() 71 | this.setData({ 72 | animateLeft: animation.export() 73 | }) 74 | } else { 75 | animation.rotate(-135).step(); 76 | this.setData({ 77 | animateLeft: animation.export() 78 | }) 79 | animation.rotate(45-(total/2 - t)/total*360).step(); 80 | this.setData({ 81 | animateRight: animation.export() 82 | }) 83 | } 84 | 85 | if (t > 0) { 86 | this.changeCD(t); 87 | } else { 88 | this.setData({ 89 | time: '结束' 90 | }) 91 | } 92 | }.bind(this), 1000); 93 | } 94 | }) -------------------------------------------------------------------------------- /pages/todo/todo.wxss: -------------------------------------------------------------------------------- 1 | /**todo.wxss**/ 2 | .not-todo { 3 | min-height: 100%; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | .text { 9 | font-size: 28rpx; 10 | color: #999999; 11 | } 12 | .add { 13 | position: fixed; 14 | right: 40rpx; 15 | bottom: 40rpx; 16 | background: #393F4F; 17 | color: #ffffff; 18 | font-weight: bold; 19 | font-size: 60rpx; 20 | width: 50rpx; 21 | height: 50rpx; 22 | line-height: 50rpx; 23 | padding: 16rpx; 24 | text-align: center; 25 | border-radius: 50%; 26 | box-shadow: 0 0 8px 1px #666699; 27 | z-index: 1000; 28 | } 29 | .input { 30 | border-bottom: 3rpx solid black; 31 | height: 50rpx; 32 | padding-bottom: 3rpx; 33 | } 34 | .time { 35 | display: flex; 36 | justify-content: center; 37 | align-items: center; 38 | margin-top: 14rpx; 39 | } 40 | .label { 41 | font-size: 34rpx; 42 | color: #393F4F; 43 | margin: 0 36rpx; 44 | } 45 | .radio { 46 | margin-right: 6rpx; 47 | } 48 | 49 | .todo { 50 | border: 2rpx solid #ddd; 51 | height: 110rpx; 52 | box-shadow: 0 1px 1px #666; 53 | margin-bottom: 6rpx; 54 | } 55 | .t-text { 56 | box-sizing: border-box; 57 | padding-left: 45rpx; 58 | color: #ffffff; 59 | width: 80%; 60 | float: left; 61 | position: relative; 62 | } 63 | .cover { 64 | position: absolute; 65 | z-index: 1000; 66 | top: 0; right: 0; bottom: 0; left: 0; 67 | } 68 | .t-title { 69 | font-weight: bold; 70 | height: 40rpx; 71 | font-size: 35rpx; 72 | line-height: 40rpx; 73 | width: 100%; 74 | overflow: hidden; 75 | margin: 20rpx 0 5rpx; 76 | text-overflow: ellipsis; 77 | white-space: nowrap; 78 | } 79 | .t-time { 80 | font-size: 20rpx; 81 | height: 25rpx; 82 | line-height: 25rpx; 83 | } 84 | .t-btn { 85 | line-height: 110rpx; 86 | width: 20%; 87 | float: left; 88 | height: 100%; 89 | } 90 | 91 | .item, .cancel { 92 | font-size: 30rpx; 93 | color: #3399cc; 94 | } 95 | .cancel { 96 | color: #0099cc; 97 | } 98 | 99 | .bg1 { 100 | background: #5C258D; 101 | background: -webkit-linear-gradient(to left, #5C258D , #4389A2); 102 | background: linear-gradient(to left, #5C258D , #4389A2); 103 | } 104 | .bg2 { 105 | background: #085078; 106 | background: -webkit-linear-gradient(to left, #085078 , #85D8CE); 107 | background: linear-gradient(to left, #085078 , #85D8CE); 108 | } 109 | .bg3 { 110 | background: #16222A; 111 | background: -webkit-linear-gradient(to left, #16222A , #3A6073); 112 | background: linear-gradient(to left, #16222A , #3A6073); 113 | } 114 | .bg4 { 115 | background: #EB3349; 116 | background: -webkit-linear-gradient(to left, #EB3349 , #F45C43); 117 | background: linear-gradient(to left, #EB3349 , #F45C43); 118 | } 119 | .bg5 { 120 | background: #1D976C; 121 | background: -webkit-linear-gradient(to left, #1D976C , #93F9B9); 122 | background: linear-gradient(to left, #1D976C , #93F9B9); 123 | } -------------------------------------------------------------------------------- /pages/todo/todo.js: -------------------------------------------------------------------------------- 1 | //todo.js 2 | Page({ 3 | data: { 4 | textShow: true, // 是否有todo存在 5 | modalHidden: true, // 新增todo窗口 6 | flagSubmit: false, // 新增todo时是否填写事件 7 | toastHidden: true, // 消息提示框 8 | 9 | actionTodo: true, // 修改todo 10 | actionSheetItems: ['置顶', '提醒', '编辑', '删除'], 11 | actionWhich: -1, 12 | not_active: '提醒', // 暂不提供提醒功能 13 | 14 | userTime: 25, // 默认时间 15 | addVal: '', 16 | 17 | startD: 0, 18 | naviFlag: false, 19 | 20 | todo: [ 21 | /*{ 22 | name: '游泳', 23 | time: 20, 24 | bgCls: 'bg1' 25 | }, 26 | { 27 | name: '跑步', 28 | time: 20, 29 | bgCls: 'bg3' 30 | }, 31 | { 32 | name: '骑车', 33 | time: 20, 34 | bgCls: 'bg5' 35 | }*/ 36 | ], 37 | defaults: { 38 | time: [ 39 | {value: '5'}, 40 | {value: '25', checked: 'true'}, 41 | {value: '35'} 42 | ] 43 | } 44 | }, 45 | onShow: function () { 46 | if (this.data.todo.length < 1) { 47 | this.setData({ 48 | textShow: false 49 | }) 50 | } 51 | }, 52 | /** 53 | * user defined methods & property 54 | */ 55 | // xss & trim 56 | dataFormat: function(data) { 57 | var remove_spaces = /^\s+|\s+$/g, 58 | remove_lt = //g; 60 | return data.toString() 61 | .replace(remove_spaces, '') 62 | .replace(remove_lt, '<') 63 | .replace(remove_gt, '>'); 64 | }, 65 | // 添加ToDo 66 | addHandle: function(e) { 67 | this.setData({ 68 | textShow: true, 69 | modalHidden: false 70 | }) 71 | }, 72 | // 弹出ToDo内容框 73 | modalChange: function(e) { 74 | if (this.data.flagSubmit) { 75 | this.setData({ 76 | modalHidden: true, 77 | todo: [].concat(this.data.todo, { 78 | name: this.data.addVal, 79 | time: this.data.userTime, 80 | bgCls: 'bg'+(Math.ceil(Math.random()*5)) 81 | }) 82 | }) 83 | // 处理新增ToDo 84 | } 85 | }, 86 | // input失去焦点触发 87 | inputChange: function(e) { 88 | var val = this.dataFormat(e.detail.value) 89 | if (val.length > 0) { 90 | this.setData({ 91 | flagSubmit: true, 92 | addVal: val 93 | }) 94 | } 95 | }, 96 | // radio修改 97 | rChange: function(e) { 98 | this.setData({ 99 | userTime: e.detail.value 100 | }) 101 | }, 102 | 103 | // 长按todo 104 | changeTodo: function(e) { 105 | var index = e.target.dataset.index; 106 | this.setData({ 107 | actionTodo: false, 108 | actionWhich: index 109 | }) 110 | }, 111 | // 取消长按 112 | cancelTodo: function(e) { 113 | this.setData({ 114 | actionTodo: true, 115 | actionWhich: -1 116 | }) 117 | }, 118 | // 操作todo 119 | todoItem: function(e) { 120 | var index = e.target.dataset.index; 121 | /** 122 | * 开关选项 123 | * 0: 置顶 124 | * 1: 提醒 125 | * 2: 编辑 126 | * 3: 删除 127 | */ 128 | switch(index) { 129 | case '0': 130 | // 置顶操作 131 | var todo = this.data.todo; 132 | var item = todo.splice(this.data.actionWhich, 1)[0]; 133 | todo.unshift(item); 134 | this.setData({ 135 | todo: todo, 136 | actionTodo: true 137 | }) 138 | break; 139 | case '1': 140 | this.setData({ 141 | not_active: '提醒', 142 | actionTodo: true, 143 | toastHidden: false 144 | }) 145 | break; 146 | case '2': 147 | this.setData({ 148 | not_active: '编辑', 149 | actionTodo: true, 150 | toastHidden: false 151 | }) 152 | break; 153 | case '3': 154 | var todo = this.data.todo; 155 | todo.splice(this.data.actionWhich, 1); 156 | if (todo.length === 0) { 157 | this.setData({ 158 | todo: todo, 159 | actionTodo: true, 160 | textShow: false 161 | }) 162 | } else { 163 | this.setData({ 164 | todo: todo, 165 | actionTodo: true 166 | }) 167 | } 168 | break; 169 | } 170 | }, 171 | // 消息提示框 172 | toastChange: function(e) { 173 | this.setData({ 174 | toastHidden: true 175 | }) 176 | }, 177 | 178 | // 触摸事件 179 | touchStart: function(e) { 180 | this.setData({ 181 | startD: e.touches[0].clientX 182 | }) 183 | }, 184 | touchMove: function(e){ 185 | var to = e.touches[0].clientX; 186 | if ((this.data.startD - to) > 100) { 187 | this.setData({ 188 | naviFlag: true 189 | }) 190 | } 191 | }, 192 | touchEnd: function(e) { 193 | if (this.data.naviFlag) { 194 | this.setData({ 195 | naviFlag: false 196 | }); 197 | wx.navigateTo({ 198 | url: '/pages/todos/todos' 199 | }) 200 | } 201 | }, 202 | 203 | // 开始todo 204 | startTodo: function(e) { 205 | var index = e.target.dataset.index; 206 | var time = ''+this.data.todo[index].time; 207 | var name = this.data.todo[index].name; 208 | wx.setStorageSync('todoTime', time); 209 | wx.setStorageSync('todoName', name) 210 | wx.navigateTo({ 211 | url: '/pages/doing/doing', 212 | complete: function() { 213 | wx.navigateBack(); 214 | } 215 | }) 216 | } 217 | }) 218 | --------------------------------------------------------------------------------