Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增了任务列表 #6

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 微信小程序--番茄时钟
##### 演示:
![](./image/view.gif)
![](./images/timer/view-index.jpg)
![](./images/timer/view-todo.jpg)
![](./images/timer/view-task.jpg)
![](./images/timer/view-setting.jpg)
39 changes: 37 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
@@ -5,7 +5,12 @@ const defaultTime = {
}

App({
onLaunch: function() {
onLaunch: function () {
// 展示本地存储能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)

let workTime = wx.getStorageSync('workTime')
let restTime = wx.getStorageSync('restTime')
if (!workTime) {
@@ -20,5 +25,35 @@ App({
data: defaultTime.defaultRestTime
})
}

// 登录
// wx.login({
// success: res => {
// // 发送 res.code 到后台换取 openId, sessionKey, unionId
// }
// })
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo

// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
globalData: {
userInfo: null,
}
})
})
44 changes: 24 additions & 20 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"pages": [
"pages/index/index",
"pages/todos/todos",
"pages/task/task",
"pages/logs/logs",
"pages/timeset/timeset",
"pages/setting/setting"
],
"window": {
@@ -11,25 +14,26 @@
"navigationBarTextStyle": "white"
},
"tabBar": {
"color": "#dddddd",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "image/wechat.png",
"selectedIconPath": "image/wechatHL.png",
"text": "主页"
}, {
"pagePath": "pages/logs/logs",
"iconPath": "image/wechat.png",
"selectedIconPath": "image/wechatHL.png",
"text": "记录"
}, {
"pagePath": "pages/setting/setting",
"iconPath": "image/wechat.png",
"selectedIconPath": "image/wechatHL.png",
"text": "设置"
}]
"position": "bottom",
"list": [
{
"iconPath": "images/home_48px.png",
"selectedIconPath": "images/home_48px.png",
"pagePath": "pages/index/index",
"text": "首页"
},
{
"iconPath": "images/checkout_shoppingcart_48px.png",
"selectedIconPath": "images/checkout_shoppingcart_48px.png",
"pagePath": "pages/todos/todos",
"text": "今日待办"
},
{
"iconPath": "images/manage_user_48px.png",
"selectedIconPath": "images/manage_user_48px.png",
"pagePath": "pages/timeset/timeset",
"text": "我的"
}
]
}
}
Binary file removed image/view.gif
Binary file not shown.
Binary file added images/bookmark_favorite_full_star_48px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/checkout_shoppingcart_48px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/design.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/empty_star_48px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/home_48px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/manage_user_48px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/mini_program.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/mistore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
Binary file added images/timer/pomodoro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/timer/view-index.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/timer/view-setting.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/timer/view-task.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/timer/view-todo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
Binary file added images/ygoclub.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
225 changes: 93 additions & 132 deletions pages/index/index.js
Original file line number Diff line number Diff line change
@@ -1,146 +1,107 @@
const util = require('../../utils/util.js')
const defaultLogName = {
work: '工作',
rest: '休息'
}
const actionName = {
stop: '停止',
start: '开始'
}

const initDeg = {
left: 45,
right: -45,
}

//index.js
//获取应用实例
var app = getApp()
Page({

data: {
remainTimeText: '',
timerType: 'work',
log: {},
completed: false,
isRuning: false,
leftDeg: initDeg.left,
rightDeg: initDeg.right
motto: 'MiHome_Store',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
indicatorDots: true,
autoplay: true,
interval: 3000,
duration: 100,
"banner_list": [
{
"banner": [
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_904608692a4d8415d0de39a0a5897e80.jpeg&w=1080&h=600&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_0f5e43035a8b8d27a4b6f315d222fd9b.jpeg&w=1080&h=600&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_4ba3d814639ab27570f174467133619f.png&w=1080&h=600&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_91f29509f14ea243958285aaf5d5b640.jpeg&w=1080&h=600&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_5c752db8097555831469356f5f389078.jpeg&w=1080&h=600&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
}
]
},
{
"banner": [
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_3237b46c5de819816125d88e9d06b7bf.jpg&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_c02bce3048058edb194dc3efb230d06b.jpg&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_45b3c9ed56aef44994176b50ae5d8a69.jpg&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",
},
{
"pic_url": "http://static.home.mi.com/app/shop/img?id=shop_95583f54ee857e8fa5f4cf1b9f791a74.jpg&crop=a_0_120_1080_480&t=webp&z=1.15&q=78",

}
]
}
],
hotgoods: [
{
"name": "番茄工作法",
"isTab": true,
"url":"../todos/todos",
"summary": "提升工作效率",
"ext_tag": "http://static.home.mi.com/app/shop/img?id=shop_9d57f6e89d1f560b7bce31e0b85a7285.png&w=420&h=240&crop=a_0_120_1080_480&t=png",
"pic_url": "../../images/timer/pomodoro.png"
},
]
},

onShow: function() {
if (this.data.isRuning) return
let workTime = util.formatTime(wx.getStorageSync('workTime'), 'HH')
let restTime = util.formatTime(wx.getStorageSync('restTime'), 'HH')
this.setData({
workTime: workTime,
restTime: restTime,
remainTimeText: workTime + ':00'
})
},

startTimer: function(e) {
let startTime = Date.now()
let isRuning = this.data.isRuning
let timerType = e.target.dataset.type
let showTime = this.data[timerType + 'Time']
let keepTime = showTime * 60 * 1000
let logName = this.logName || defaultLogName[timerType]

if (!isRuning) {
this.timer = setInterval((function() {
this.updateTimer()
this.startNameAnimation()
}).bind(this), 1000)
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse) {
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
this.stopTimer()
}

this.setData({
isRuning: !isRuning,
completed: false,
timerType: timerType,
remainTimeText: showTime + ':00',
taskName: logName
})

this.data.log = {
name: logName,
startTime: Date.now(),
keepTime: keepTime,
endTime: keepTime + startTime,
action: actionName[isRuning ? 'stop' : 'start'],
type: timerType
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}

this.saveLog(this.data.log)
},

startNameAnimation: function() {
let animation = wx.createAnimation({
duration: 450
})
animation.opacity(0.2).step()
animation.opacity(1).step()
getUserInfo: function (e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
nameAnimation: animation.export()
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},

stopTimer: function() {
// reset circle progress
this.setData({
leftDeg: initDeg.left,
rightDeg: initDeg.right
switchTab:function(e){
var hotgoods = this.data.hotgoods;
wx.switchTab({
"url": hotgoods[e.currentTarget.id].url,
})

// clear timer
this.timer && clearInterval(this.timer)
},

updateTimer: function() {
let log = this.data.log
let now = Date.now()
let remainingTime = Math.round((log.endTime - now) / 1000)
let H = util.formatTime(Math.floor(remainingTime / (60 * 60)) % 24, 'HH')
let M = util.formatTime(Math.floor(remainingTime / (60)) % 60, 'MM')
let S = util.formatTime(Math.floor(remainingTime) % 60, 'SS')
let halfTime

// update text
if (remainingTime > 0) {
let remainTimeText = (H === "00" ? "" : (H + ":")) + M + ":" + S
this.setData({
remainTimeText: remainTimeText
})
} else if (remainingTime == 0) {
this.setData({
completed: true
})
this.stopTimer()
return
}

// update circle progress
halfTime = log.keepTime / 2
if ((remainingTime * 1000) > halfTime) {
this.setData({
leftDeg: initDeg.left - (180 * (now - log.startTime) / halfTime)
})
} else {
this.setData({
leftDeg: -135
})
this.setData({
rightDeg: initDeg.right - (180 * (now - (log.startTime + halfTime)) / halfTime)
})
}
},

changeLogName: function(e) {
this.logName = e.detail.value
},

saveLog: function(log) {
var logs = wx.getStorageSync('logs') || []
logs.unshift(log)
wx.setStorageSync('logs', logs)
}
})
1 change: 1 addition & 0 deletions pages/index/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
79 changes: 41 additions & 38 deletions pages/index/index.wxml
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
<view class="container timer {{isRuning ? 'timer--runing': ''}}">
<view class="timer_main">
<view class="timer_time-wrap">
<view class="timer_progress_mask"></view>
<view class="timer_progress timer_left">
<view class="timer_circle timer_circle--left" style="transform: rotate({{leftDeg}}deg);"></view>
</view>
<view class="timer_progress timer_right">
<view class="timer_circle timer_circle--right" style="transform: rotate({{rightDeg}}deg);"></view>
</view>
<text wx:if="{{!completed}}" class="timer_time">{{remainTimeText}}</text>
<text
wx:if="{{isRuning}}"
animation="{{nameAnimation}}"
class="timer_taskName">{{taskName}}{{completed ? '已完成!' : '中'}}</text>
<image
wx:if="{{completed}}"
class="timer_done"
src="../../image/complete.png"></image>
</view>
<input
type="text"
placeholder-style="text-align:center"
class="timer_inputname"
bindinput="changeLogName"
placeholder="给您的任务取个名字吧"/>
</view>

<view class="timer_footer">
<view
bindtap="startTimer"
data-type="work"
class="timer_ctrl {{isRuning && timerType == 'rest' ? 'hide' : ''}}" >{{isRuning ? '完成': '工作'}}</view>
<!--index.wxml-->
<view class="container-page">
<!-- <swiper indicator-dots="{{indicatorDots}}"
autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
<block wx:for-items="{{banner_list[0].banner}}" wx:key="{{banner_list}}">
<swiper-item>
<image src="{{item.pic_url}}" class="slide-image" />
</swiper-item>
</block>
</swiper> -->

<!-- <view>
<view class='menueview' >
<block wx:for-items="{{banner_list[1].banner}}" wx:key="{{banner_list}}">
<image src="{{item.pic_url}}" class="menue-image" />
</block>
</view>
</view> -->

<view class='separator'></view>
<view class='floortitle'>
<view class='floortitlemoreicon'>时间管理工具</view>
<!-- <view class='floortitlemoretext'>更多> </view> -->
</view>

<view class='hotgoodcontainer'>
<view class='goodcontainer' wx:for="{{hotgoods}}" wx:for-index="idx" wx:for-item="good" wx:key="*this">
<view wx:if='{{good.isTab}}' class='gooditem' bindtap='switchTab'id='{{idx}}'>
<view class='imgview'>
<image class='productimg' src='{{good.pic_url}}'/>
</view>
<view>{{good.name}}</view>
</view>
<navigator wx:else url='{{good.url}}' class='gooditem' id='{{idx}}'>
<view class='imgview'>
<image class='productimg' src='{{good.pic_url}}'/>
</view>
<view>{{good.name}}</view>
</navigator>
</view>
</view>

<view
bindtap="startTimer"
data-type="rest"
class="timer_ctrl {{isRuning && timerType == 'work' ? 'hide' : ''}}" >{{isRuning ? '完成': '休息'}}</view>
</view>
</view>

254 changes: 78 additions & 176 deletions pages/index/index.wxss
Original file line number Diff line number Diff line change
@@ -1,184 +1,86 @@
.container {
/**index.wxss**/
.userinfo {
display: flex;
height: 100%;
flex-direction: column;
overflow: hidden;
background-color: #fff;
}

.timer_main {
position: relative;
display: flex;
flex: 2;
justify-content: center;
align-items: center;
text-align: center;
background-color: #3197ed;
transition: all .5s;
z-index: 1;
padding: 10px 0;
}

.timer_time-wrap {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 150px;
height: 150px;
text-align: center;
transition: all .3s;
}

.timer_progress {
position: absolute;
top: 0;
width: 75px;
height: 150px;
overflow: hidden;
transition: all .3s;
}

.timer_progress_mask {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 3px solid #1589eb;
opacity: .5;
border-radius: 50%;
}

.timer_left {
left: 0;
}

.timer_right {
right: 0;
}

.timer_circle {
position: absolute;
top: 0;
width: 150px;
height: 150px;
border: 3px solid transparent;
border-radius: 50%;
transition: all .3s;
}

.timer_circle--left {
left: 0;
border-left: 3px solid #fff;
border-bottom: 3px solid #fff;
transform: rotate(45deg);
}

.timer_circle--right {
right: 0;
border-right: 3px solid #fff;
border-bottom: 3px solid #fff;
transform: rotate(-45deg);
}

.timer_time-right {}

.timer_time {
font-size: 40px;
color: #fff;
font-weight: lighter;
transition: font-size .3s;
}

.timer_taskName {
position: absolute;
top: -100px;
font-size: 14px;
letter-spacing: 5px;
color: #fff;
}

.timer_done {
width: 64px;
height: 64px;
}

.timer_inputname {
position: absolute;
bottom: -40px;
width: 100%;
text-align: center;
height: 40px;
padding-left: 10px;
border-bottom: 1px solid #f2f2f2;
color: #999;
}

.timer_footer {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding-top: 40px;
transition: all .3s;
}

.timer .timer_ctrl {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 12px;
color: #fff;
width: 80px;
height: 80px;
margin: 0 20px;
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
transition: all .7s;
background-color: #48c23d;
}

.timer .timer_ctrl text {}


/*runing style*/

.timer--runing .timer_main {
flex: 1;
}

.timer--runing .timer_time {
font-size: 45px;
}

.timer--runing .timer_time-wrap {
width: 200px;
height: 200px;
}

.timer--runing .timer_progress {
width: 100px;
height: 200px;
}

.timer--runing .timer_circle {
width: 200px;
height: 200px;
}

.timer--runing .timer_footer {
flex: 0;
position: absolute;
bottom: 0;
width: 100%;
z-index: 10;
}

.timer--runing .timer_ctrl {
background-color: #208DEA;
height: 30px;
margin-bottom: 30px;
border: 1px dashed #dedede;
border-radius: 20px;
}
.userinfo-nickname {
color: #aaa;
}

.usermotto {
margin-top: 200px;
}

.slide-image{
display: block;
height: 150px;
width:100%
}
.menueview{
display:flex;
background-color:#FFF;
padding:5px 0
}
.menue-image{
flex:1;
height:50px;
height:auto
}
.separator{
height: 4px;
width:20rem;
background-color: #F3F3F3
}
.floortitle{
display:flex;
height:34px;
align-items:center;
justify-content:space-between;
padding:0 13px;
font-size:14px;
color:rgba(0,0,0,0.7);
border-bottom: 1px solid #e2e2e3
}
.hotgoodcontainer{
display:flex;
flex-wrap: wrap;
width:100%;
}
.goodcontainer{
width:33.333333%;
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
box-sizing:border-box;
padding-bottom:10px;
}
.gooditem{
width:100%;
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
font-size:12px;
box-sizing:border-box;
margin: 5px 0 0 10px;
padding-bottom: 10px;
border: 0.5px solid #e2e2e3;
}
.productimg{
width:80px;
height:80px;
}
.imgview{
width:80px;
height:80px;
}
3 changes: 3 additions & 0 deletions pages/logs/logs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
3 changes: 3 additions & 0 deletions pages/setting/setting.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
157 changes: 157 additions & 0 deletions pages/task/task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
const util = require('../../utils/util.js')
const defaultLogName = {
work: '工作',
rest: '休息'
}
const actionName = {
stop: '停止',
start: '开始'
}

const initDeg = {
left: 45,
right: -45,
}

Page({

data: {
taskName:'',
remainTimeText: '',
timerType: 'work',
log: {},
completed: false,
isRuning: false,
leftDeg: initDeg.left,
rightDeg: initDeg.right
},

onLoad: function (e) {
// console.log(e);
wx.setNavigationBarTitle({
title: '工作任务-' + e.name,
})
this.setData({
taskName: e.name
})
},

onShow: function () {
if (this.data.isRuning) return
let workTime = util.formatTime2(wx.getStorageSync('workTime'), 'HH')
let restTime = util.formatTime2(wx.getStorageSync('restTime'), 'HH')
this.setData({
workTime: workTime,
restTime: restTime,
remainTimeText: workTime + ':00'
})
},

startTimer: function (e) {
let startTime = Date.now()
let isRuning = this.data.isRuning
let timerType = e.target.dataset.type
let showTime = this.data[timerType + 'Time']
let keepTime = showTime * 60 * 1000
let logName = this.data.taskName

if (!isRuning) {
this.timer = setInterval((function () {
this.updateTimer()
// this.startNameAnimation()
}).bind(this), 500)
} else {
this.stopTimer()
}

this.setData({
isRuning: !isRuning,
completed: false,
timerType: timerType,
remainTimeText: showTime + ':00',
taskName: logName
})

this.data.log = {
name: logName,
startTime: Date.now(),
keepTime: keepTime,
endTime: keepTime + startTime,
action: actionName[isRuning ? 'stop' : 'start'],
type: timerType
}

this.saveLog(this.data.log)
},

startNameAnimation: function () {
let animation = wx.createAnimation({
duration: 450
})
animation.opacity(0.4).step()
animation.opacity(1).step()
this.setData({
nameAnimation: animation.export()
})
},

stopTimer: function () {
// reset circle progress
this.setData({
leftDeg: initDeg.left,
rightDeg: initDeg.right
})

// clear timer
this.timer && clearInterval(this.timer)
},

updateTimer: function () {
let log = this.data.log
let now = Date.now()
let remainingTime = Math.round((log.endTime - now) / 1000)
let H = util.formatTime2(Math.floor(remainingTime / (60 * 60)) % 24, 'HH')
let M = util.formatTime2(Math.floor(remainingTime / (60)) % 60, 'MM')
let S = util.formatTime2(Math.floor(remainingTime) % 60, 'SS')
let halfTime

// update text
if (remainingTime > 0) {
let remainTimeText = (H === "00" ? "" : (H + ":")) + M + ":" + S
this.setData({
remainTimeText: remainTimeText
})
} else if (remainingTime == 0) {
this.setData({
completed: true
})
this.stopTimer()
return
}

// update circle progress
halfTime = log.keepTime / 2
if ((remainingTime * 1000) > halfTime) {
this.setData({
leftDeg: initDeg.left - (180 * (now - log.startTime) / halfTime)
})
} else {
this.setData({
leftDeg: -135
})
this.setData({
rightDeg: initDeg.right - (180 * (now - (log.startTime + halfTime)) / halfTime)
})
}
},

changeLogName: function (e) {
this.logName = e.detail.value
},

saveLog: function (log) {
var logs = wx.getStorageSync('logs') || []
logs.unshift(log)
wx.setStorageSync('logs', logs)
}
})
3 changes: 3 additions & 0 deletions pages/task/task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
42 changes: 42 additions & 0 deletions pages/task/task.wxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!--pages/task/task.wxml-->

<view class="container-page timer {{isRuning ? 'timer--runing': ''}}">
<view class="timer_main">
<view class="timer_time-wrap">
<view class="timer_progress_mask"></view>
<view class="timer_progress timer_left">
<view class="timer_circle timer_circle--left" style="transform: rotate({{leftDeg}}deg);"></view>
</view>
<view class="timer_progress timer_right">
<view class="timer_circle timer_circle--right" style="transform: rotate({{rightDeg}}deg);"></view>
</view>
<text wx:if="{{!completed}}" class="timer_time">{{remainTimeText}}</text>
<text
wx:if="{{isRuning}}"
animation="{{nameAnimation}}"
class="timer_taskName">{{timerType=='work'?taskName:'休息中'}}{{completed ? '已完成!' : ''}}</text>
<image
wx:if="{{completed}}"
class="timer_done"
src="../../image/complete.png"></image>
</view>
<input
type="text"
placeholder-style="text-align:center"
class="timer_inputname"
bindinput="changeLogName"
value="{{taskName}}"/>
</view>

<view class="timer_footer">
<view
bindtap="startTimer"
data-type="work"
class="timer_ctrl timer_ctrl_work {{isRuning && timerType == 'rest' ? 'hide' : ''}}" >{{isRuning ? '完成': '工作'}}</view>

<view
bindtap="startTimer"
data-type="rest"
class="timer_ctrl timer_ctrl_rest {{isRuning && timerType == 'work' ? 'hide' : ''}}" >{{isRuning ? '完成': '休息'}}</view>
</view>
</view>
266 changes: 266 additions & 0 deletions pages/task/task.wxss
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/* pages/task/task.wxss */
view,
sroll-view,
swiper,
icon,
text,
progress,
button,
checkbox,
form,
input,
label,
input,
picker,
radio,
slider,
switch,
action-sheet,
modal,
toast,
loading,
navigator,
audio,
image,
video,
map,
canvas {
box-sizing: border-box;
}
page {
height: 100%;
}

.hide {
display: none!important;
}

.container,
input,
button {
font: 14px "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
}

.container {
height: 100%;
background-color: #f5f5f5;
}

.panel {
background: #fff;
border-radius: 3px;
padding: 5px 10px;
}
.nodata{
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}

.nodata_img{
display: block;
width: 45px;
height: 45px;
}

.nodata_text{
color:#dedede;
font-size: 12px;
padding-left: 10px;
}

.container-page {
display: flex;
height: 100%;
flex-direction: column;
overflow: hidden;
background-color: #fff;
}

.timer_main {
position: relative;
display: flex;
flex: 2;
justify-content: center;
align-items: center;
text-align: center;
background-color: #3197ed;
transition: all .5s;
z-index: 1;
padding: 10px 0;
}

.timer_time-wrap {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 150px;
height: 150px;
text-align: center;
transition: all .3s;
}

.timer_progress {
position: absolute;
top: 0;
width: 75px;
height: 150px;
overflow: hidden;
transition: all .3s;
}

.timer_progress_mask {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 3px solid #1589eb;
opacity: .5;
border-radius: 50%;
}

.timer_left {
left: 0;
}

.timer_right {
right: 0;
}

.timer_circle {
position: absolute;
top: 0;
width: 150px;
height: 150px;
border: 3px solid transparent;
border-radius: 50%;
transition: all .3s;
}

.timer_circle--left {
left: 0;
border-left: 3px solid #fff;
border-bottom: 3px solid #fff;
transform: rotate(45deg);
}

.timer_circle--right {
right: 0;
border-right: 3px solid #fff;
border-bottom: 3px solid #fff;
transform: rotate(-45deg);
}

.timer_time-right {}

.timer_time {
font-size: 40px;
color: #fff;
font-weight: lighter;
transition: font-size .3s;
}

.timer_taskName {
position: absolute;
top: -100px;
font-size: 32px;
letter-spacing: 5px;
color: #fff;
padding: 5rpx 35rpx;
border-bottom: 2px solid #ddd;
}

.timer_done {
width: 64px;
height: 64px;
}

.timer_inputname {
position: absolute;
bottom: -40px;
width: 100%;
text-align: center;
height: 40px;
padding-left: 10px;
border-bottom: 1px solid #f2f2f2;
color: #999;
}

.timer_footer {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding-top: 40px;
transition: all .3s;
}

.timer .timer_ctrl {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 12px;
color: #fff;
width: 80px;
height: 80px;
margin: 0 20px;
border-radius: 50%;
transition: all .7s;
}

.timer .timer_ctrl text {}

.timer_ctrl_work{
background-color: red;
}

.timer_ctrl_rest{
background-color: #48c23d;
}

/*runing style*/

.timer--runing .timer_main {
flex: 1;
}

.timer--runing .timer_time {
font-size: 45px;
}

.timer--runing .timer_time-wrap {
width: 200px;
height: 200px;
}

.timer--runing .timer_progress {
width: 100px;
height: 200px;
}

.timer--runing .timer_circle {
width: 200px;
height: 200px;
}

.timer--runing .timer_footer {
flex: 0;
position: absolute;
bottom: 0;
width: 100%;
z-index: 10;
}

.timer--runing .timer_ctrl {
background-color: #208DEA;
width: 150px;
height: 50px;
font-size: 20px;
margin-bottom: 30px;
border: 1px dashed #dedede;
border-radius: 20px;
}
84 changes: 84 additions & 0 deletions pages/timeset/timeset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// pages/timeset/timeset.js
Page({

/**
* 页面的初始数据
*/
data: {

},

/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {

},

/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {

},

/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
wx.setNavigationBarTitle({
title: '设置'
})
this.setData({
workTime: wx.getStorageSync('workTime'),
restTime: wx.getStorageSync('restTime')
})
},

/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {

},

/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {

},

/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {

},

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {

},

/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {

},
changeWorkTime: function (e) {
wx.setStorage({
key: 'workTime',
data: e.detail.value
})
},
changeRestTime: function (e) {
wx.setStorage({
key: 'restTime',
data: e.detail.value
})
}
})
3 changes: 3 additions & 0 deletions pages/timeset/timeset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
51 changes: 51 additions & 0 deletions pages/timeset/timeset.wxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!--pages/timeset/timeset.wxml-->
<view class="container-page">
<view class="section panel">
<text class="section_title">工作时长(分钟)</text>
<view class="section_body">
<slider
bindchange="changeWorkTime"
show-value="true"
min="1"
max="60"
value="{{workTime}}"
left-icon="cancel"
right-icon="success_no_circle"/>
</view>
</view>

<view class="section panel">
<text class="section_title">休息时长(分钟)</text>
<view class="section_body">
<slider
bindchange="changeRestTime"
show-value="true"
min="5"
max="60"
value="{{restTime}}"
left-icon="cancel"
right-icon="success_no_circle"/>
</view>
</view>

<view class="section panel">
<view class="section_title">
<text>主页背景</text>
</view>
<view class="section_body">
<text bindtab="" class="section_tip">选择背景 > </text>
</view>
</view>

<view class="section panel">
<view class="section_title">
<switch class="section_check" type="checkbox" size="mini" checked bindchange="switch1Change"/>
<text>启用铃声</text>
</view>
<view class="section_body">
<text bindtab="" class="section_tip">选择铃声 > </text>
</view>
</view>

</view>

23 changes: 23 additions & 0 deletions pages/timeset/timeset.wxss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* pages/timeset/timeset.wxss */
.container-page{
padding:15px 10px;
}
.section{
margin-bottom: 10px;
}
.section_title{
font-size: 12px;
color:#999;
}
.section_check{
margin-right: 5px;
}
.section_tip{
display: block;
text-align: right;
color: #CEC9C9;
padding-bottom: 10px;
}
.section_body{
margin-top: 15px;
}
165 changes: 165 additions & 0 deletions pages/todos/todos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// pages/todos/todos.js
const util = require('../../utils/util.js')
Page({

/**
* 页面的初始数据
*/
data: {
todos: [],
activeTodos: [],
editedTodo: {},
draft: '',
editDraft: null,
},

/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {

},

/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
this.setData({
todos: [...wx.getStorageSync("todos")],
activeTodos: [...wx.getStorageSync("activeTodos")]
})
},

/**
* 生命周期函数--监听页面显示
*/
onShow: function () {

},

/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {

},

/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {

},

/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {

},

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {

},

/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {

},
setTodos: function (todos) {
console.log(todos)
const activeTodos = todos.filter(todo => !todo.done);
wx.setStorageSync("todos", todos);
wx.setStorageSync("activeTodos", activeTodos);
this.setData({
todos,
activeTodos,
});
},
addTodo: function () {
var value = this.data.draft && this.data.draft.trim()
if (!value) {
return;
}
let newTodo = this.data.todos;
newTodo.push({
id: util.formatDate(new Date()),
done: false,
content: value
});
const activeTodos = newTodo.filter(todo => !todo.done);
wx.setStorageSync("todos", newTodo);
wx.setStorageSync("activeTodos", activeTodos);
this.setData({
todos: newTodo,
activeTodos,
draft: ''
});
},
toggleDone: function ({
target: {
dataset: {
id
}
}
}) {
const { todos } = this.data;
const currentTodo = todos.filter(todo => todo.id === id)[0];
currentTodo.done = !currentTodo.done;
this.setTodos(todos)
},
editTodo: function ({
target: {
dataset: {
id
}
}
}) {
this.setData({
editDraft: null,
editedTodo: this.data.todos.filter(todo => todo.id === id)[0] || {}
});
},
removeDone: function () {
const activeTodos = this.data.todos.filter(todo => !todo.done)
console.log(activeTodos);
this.setTodos(activeTodos)
},
updateDraft: function ({
detail: {
value
}
}) {
// Android 真机上会诡异地触发多次时 value 为空的事件
if (!value) return;
this.setData({
draft: value
});
},
goTodo: function ({
target: {
dataset: {
id
}
}
}) {
const currentToDo = this.data.todos.filter(todo => todo.id === id)[0] || {};
console.log(currentToDo)
if (!currentToDo.done){
wx.navigateTo({
url: '../task/task?name=' + currentToDo.content,
});
}

},
setting: function () {
wx.navigateTo({
url: '../timeset/timeset',
});
},
})
3 changes: 3 additions & 0 deletions pages/todos/todos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
46 changes: 46 additions & 0 deletions pages/todos/todos.wxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--pages/todos/todos.wxml-->
<view class="flex-wrap header">
<input
placeholder="添加一个任务"
bindinput="updateDraft"
value="{{draft}}"
class="new-todo"/>
<text style="display: {{draft ? 'inline': 'none'}}" class="add tappable" ontap="addTodo">添加</text>
</view>
<view class="todo-list">
<block wx:for="{{todos}}" wx:for-item="todo" wx:for-index="objectId" wx:key="objectId">
<view class="flex-wrap todo">
<icon
type="{{todo.done ? 'success_circle' : 'circle'}}"
data-id="{{todo.id}}"
ontap="toggleDone"
class="todo-icon tappable"
size="24"/>
<text data-id="{{todo.id}}"
class="todo-text tappable {{todo.done ? 'done': ''}}"
ontap="goTodo">
{{todo.content}}
</text>
<!-- <text
wx:if="{{todo.objectId != editedTodo.objectId}}"
data-id="{{todo.objectId}}"
class="todo-text tappable {{todo.done ? 'done': ''}}"
ontap="editTodo">
{{todo.content}}
</text>
<input
wx:if="{{todo.objectId == editedTodo.objectId}}"
data-id="{{todo.objectId}}"
value="{{todo.content}}"
auto-focus
bindinput="updateEditedContent"
bindblur="doneEdit"
class="todo-input"/> -->
</view>
</block>
</view>
<view class="footer">
<text ontap="setting" class="setting tappable">设置</text>
<text class="status">{{activeTodos.length}} / {{todos.length}}</text>
<text ontap="removeDone" class="remove-done tappable" wx-if="{{activeTodos.length !== todos.length}}">清除已完成</text>
</view>
90 changes: 90 additions & 0 deletions pages/todos/todos.wxss
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* pages/todos/todos.wxss */
.flex-wrap{
display: flex;
flex-direction: row;
}

.tappable:hover {
opacity: .6;
}

.header {
height: 54px;
align-items: center;
background-color: #FFF;
}

.new-todo {
flex: 1;
font-size: 18px;
box-sizing: border-box;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
padding-left: 12px;
line-height: 100%;
height: 100%;
}
.add {
color: #FFF;
background-color: #1aad19;
font-size: 16px;
line-height: 53px;
padding: 0 16px;
}

.todo-list {
padding: 4px 6px 48px;
}
.done {
text-decoration: line-through;
color: #ccc;
}
.todo {
font-size: 18px;
height: 30px;
padding: 10px 12px;
overflow: hidden;
align-items: center;
background-color: #fff;
margin: 1px 0;
border-radius: 3px;
}
.todo-icon {
margin-right: 12px;
}
.todo-text {
white-space: nowrap;
display: block;
width: 100%;
height: 50px;
line-height: 17px;
}
.todo-input {
font-size: 18px;
width: 100%;
}

.footer {
position: fixed;
bottom: 0;
height: 44px;
width: 100%;
line-height: 44px;
color: #666;
border-top: 1px solid #eee;
background: #fff;
font-size: 16px;
text-align: center;
}
.remove-done,
.setting {
color: #1aad19;
}
.remove-done {
position: absolute;
right: 12px;
}
.setting {
position: absolute;
left: 12px;
}
36 changes: 33 additions & 3 deletions utils/util.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
function formatTime(time, format) {
function formatTime2(time, format) {
let temp = '0000000000' + time
let len = format.length
return temp.substr(-len)
}

const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()

return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}

const formatDate = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()

return [year, month, day, hour, minute, second].map(formatNumber).join('')
}


const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}

module.exports = {
formatTime: formatTime
}
formatTime: formatTime,
formatTime2: formatTime2,
formatDate: formatDate
}