123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- //index.js
- const app = getApp()
- const util = require('../../utils/util.js')
- Page({
- data: {
- userInfo:{},
- hasUserInfo:false,
- clockShow: false,
- clockHeight: 0,
- time: '25',
- mTime: 1500000,
- timeStr: '25:00',
- rate: '',
- timer: null,
- cateArr: [
- { icon: 'work', text: '工作' },
- { icon: 'study', text: "学习" },
- { icon: 'think', text: '思考' },
- { icon: 'write', text: '写作' },
- { icon: 'sport', text: '运动' },
- { icon: 'read', text: "阅读" }
- ],
- cateActive: null,
- okShow: false,
- pauseShow: true,
- continueCancleShow: false,
- customTask: '',
- showCustomInput: false,
- plans: [],
- selectedPlan: null,
- editMode: false,
- editPlanId: null,
- currentTask: '',
- userInfo: null,
- isLoggedIn: false,
- theme: {},
- containerStyle: '',
- buttonStyle: '', // 按钮动态样式
- timerStyle: '', // 计时器动态样式
- progressStyle: '', // 进度条动态样式
- photoPath: '',
- isTimerRunning: false, // 新增:计时器是否正在运行
- startTime: 0, // 新增:开始时间戳
- endTime: 0, // 新增:结束时间戳
- remainingTime: 0 // 新增:剩余时间(毫秒)
- },
- onLoad: function () {
- const res = wx.getSystemInfoSync();
- const rate = 750 / res.windowWidth;
- this.setData({
- rate: rate,
- clockHeight: res.windowHeight * 2,
- time: '25',
- mTime: 25 * 60 * 1000,
- timeStr: '25:00'
- });
- const plans = wx.getStorageSync('plans') || [];
- this.setData({ plans });
-
- if (app.globalData.userInfo) {
- this.setData({
- userInfo: app.globalData.userInfo,
- hasUserInfo: true,
- isLoggedIn: true
- });
- } else {
- // 没有用户信息,引导用户授权
- wx.showModal({
- title: '授权提示',
- content: '需要获取您的用户信息以提供更好的服务,请授权登录',
- success: res => {
- if (res.confirm) {
- wx.getUserProfile({
- desc: '用于完善用户资料',
- success: res => {
- app.globalData.userInfo = res.userInfo;
- this.setData({
- userInfo: res.userInfo,
- hasUserInfo: true,
- isLoggedIn: true
- });
- }
- });
- }
- }
- });
- }
- if (app.eventBus) {
- app.eventBus.on('userInfoChange', (userInfo) => {
- this.setData({
- userInfo: userInfo,
- isLoggedIn: !!userInfo
- });
- });
- app.eventBus.on('themeChange', (theme) => {
- this.setData({ theme });
- this.updateThemeStyles();
- });
- }
- this.setData({
- userInfo: app.globalData.userInfo,
- isLoggedIn: !!app.globalData.userInfo,
- theme: app.globalData.theme
- });
- this.updateThemeStyles();
- },
- onShow: function() {
- this.updateNavigationBarColor();
- },
- onUnload: function() {
- if (this.data.timer) {
- clearInterval(this.data.timer);
- this.setData({ timer: null });
- }
- if (app.eventBus) {
- app.eventBus.off('userInfoChange');
- app.eventBus.off('themeChange');
- }
- },
- updateNavigationBarColor: function() {
- const { theme } = this.data;
- if (theme && theme.primaryColor && theme.textColor) {
- wx.setNavigationBarColor({
- frontColor: theme.textColor === '#333' ? '#000000' : '#ffffff',
- backgroundColor: theme.primaryColor,
- animation: {
- duration: 300,
- timingFunc: 'easeIn'
- }
- });
- }
- },
- updateThemeStyles: function () {
- const { theme } = this.data;
- const { bgColor, textColor, primaryColor } = theme;
-
- this.setData({
- containerStyle: `background-color: ${bgColor}; color: ${textColor};`,
- buttonStyle: `background-color: ${primaryColor}; color: ${textColor};`,
- timerStyle: `color: ${primaryColor};`,
- progressStyle: primaryColor,
- sliderStyle: primaryColor // 新增滑块主题色
- });
-
- this.updateNavigationBarColor();
- },
- slideChange: function (e) {
- const minutes = e.detail.value;
- this.setData({
- time: minutes.toString(),
- timeStr: minutes >= 10 ? minutes + ':00' : '0' + minutes + ':00',
- mTime: minutes * 60 * 1000
- });
- },
- clickCate: function (e) {
- this.setData({
- cateActive: e.currentTarget.dataset.index,
- showCustomInput: false,
- selectedPlan: null,
- editMode: false
- });
- },
- showCustomTaskInput: function() {
- this.setData({
- showCustomInput: true,
- cateActive: null,
- selectedPlan: null,
- customTask: '',
- editMode: false
- });
- },
- inputCustomTask: function(e) {
- this.setData({ customTask: e.detail.value });
- },
- savePlan: function() {
- if (!this.data.customTask.trim()) {
- wx.showToast({ title: '请输入任务内容', icon: 'none' });
- return;
- }
- let updatedPlans = [];
- if (this.data.editMode) {
- updatedPlans = this.data.plans.map(plan => {
- if (plan.id === this.data.editPlanId) {
- return { ...plan, content: this.data.customTask, time: this.data.time };
- }
- return plan;
- });
- wx.showToast({ title: '计划更新成功', icon: 'success' });
- } else {
- const newPlan = {
- id: Date.now(),
- content: this.data.customTask,
- time: this.data.time,
- createdAt: new Date().toISOString()
- };
- updatedPlans = [...this.data.plans, newPlan];
- wx.showToast({ title: '计划添加成功', icon: 'success' });
- }
- this.setData({
- plans: updatedPlans,
- customTask: '',
- showCustomInput: false,
- editMode: false,
- editPlanId: null
- });
- wx.setStorageSync('plans', updatedPlans);
- },
- selectPlan: function(e) {
- const { index } = e.currentTarget.dataset;
- const selectedPlan = this.data.plans[index];
- this.setData({
- time: selectedPlan.time,
- customTask: selectedPlan.content,
- cateActive: null,
- showCustomInput: false,
- selectedPlan: selectedPlan,
- editMode: false
- });
- },
- editPlan: function(e) {
- const { index } = e.currentTarget.dataset;
- const planToEdit = this.data.plans[index];
- this.setData({
- time: planToEdit.time,
- customTask: planToEdit.content,
- showCustomInput: true,
- editMode: true,
- editPlanId: planToEdit.id,
- selectedPlan: null
- });
- },
- deletePlan: function(e) {
- const { index } = e.currentTarget.dataset;
- const planToDelete = this.data.plans[index];
- wx.showModal({
- title: '确认删除',
- content: `确定要删除计划"${planToDelete.content}"吗?`,
- success: (res) => {
- if (res.confirm) {
- const updatedPlans = this.data.plans.filter((_, i) => i !== index);
- this.setData({ plans: updatedPlans, selectedPlan: null });
- wx.setStorageSync('plans', updatedPlans);
- wx.showToast({ title: '计划已删除', icon: 'success' });
- }
- }
- });
- },
- start: function () {
- let taskContent = '';
- let time = parseInt(this.data.time);
- let categoryIndex = this.data.cateActive;
- if (this.data.selectedPlan) {
- taskContent = this.data.selectedPlan.content;
- time = parseInt(this.data.selectedPlan.time);
- } else if (this.data.showCustomInput && this.data.customTask) {
- taskContent = this.data.customTask;
- categoryIndex = null;
- } else if (this.data.cateActive !== null) {
- taskContent = this.data.cateArr[this.data.cateActive].text;
- } else {
- wx.showToast({ title: '请选择一个任务', icon: 'none' });
- return;
- }
- this.setData({
- clockShow: true,
- mTime: time * 60 * 1000,
- timeStr: time >= 10 ? time + ':00' : '0' + time + ':00',
- time: time.toString(),
- currentTask: taskContent,
- cateActive: categoryIndex
- });
- this.drawBg();
- this.drawActive();
- this.showPhotoConfirm();
- },
- drawBg: function () {
- const lineWidth = 6 / this.data.rate;
- const ctx = wx.createCanvasContext('progress_bg');
- const center = 250 / this.data.rate;
- const radius = center - 2 * lineWidth;
- ctx.setLineWidth(lineWidth);
- ctx.setStrokeStyle('#f0f0f0');
- ctx.setLineCap('round');
- ctx.beginPath();
- ctx.arc(center, center, radius, 0, 2 * Math.PI, false);
- ctx.stroke();
- ctx.draw();
- },
- drawActive: function () {
- const _this = this;
- const lineWidth = 6 / this.data.rate;
- const center = 250 / this.data.rate;
- const radius = center - 2 * lineWidth;
- const timer = setInterval(function () {
- const angle = 1.5 + 2 * (_this.data.time * 60 * 1000 - _this.data.mTime) / (_this.data.time * 60 * 1000);
- const currentTime = _this.data.mTime - 100;
- _this.setData({ mTime: currentTime });
- if (angle < 3.5) {
- if (currentTime % 1000 == 0) {
- let timeStr1 = currentTime / 1000;
- let timeStr2 = parseInt(timeStr1 / 60);
- let timeStr3 = (timeStr1 - timeStr2 * 60) >= 10 ?
- (timeStr1 - timeStr2 * 60) : '0' + (timeStr1 - timeStr2 * 60);
- timeStr2 = timeStr2 >= 10 ? timeStr2 : '0' + timeStr2;
- _this.setData({ timeStr: timeStr2 + ':' + timeStr3 });
- }
- const ctx = wx.createCanvasContext('progress_active');
- ctx.setLineWidth(lineWidth);
- ctx.setStrokeStyle(_this.data.theme.primaryColor);
- ctx.setLineCap('round');
- ctx.beginPath();
- ctx.arc(center, center, radius, 1.5 * Math.PI, angle * Math.PI, false);
- ctx.stroke();
- ctx.draw();
- } else {
- const logs = wx.getStorageSync('logs') || [];
- logs.unshift({
- date: util.formatTime(new Date),
- task: _this.data.currentTask,
- cate: _this.data.cateActive,
- time: _this.data.time
- });
- wx.setStorageSync('logs', logs);
- _this.setData({
- timeStr: '00:00',
- okShow: true,
- pauseShow: false,
- continueCancleShow: false
- });
- clearInterval(timer);
- }
- }, 100);
- _this.setData({ timer: timer });
- },
- showPhotoConfirm: function() {
- wx.showModal({
- title: '打卡拍照',
- content: '开始专注前需要拍照打卡确认',
- confirmText: '拍照',
- cancelText: '暂不',
- success: (res) => {
- if (res.confirm) {
- this.checkCameraPermission();
- } else {
- // 取消拍照则重置界面
- this.resetTimerUI();
- wx.showToast({ title: '拍照打卡已取消', icon: 'none' });
- }
- }
- });
- },
- checkCameraPermission: function() {
- wx.getSetting({
- success: (res) => {
- if (!res.authSetting['scope.camera']) {
- wx.authorize({
- scope: 'scope.camera',
- success: () => this.takePhoto(),
- fail: () => {
- wx.showModal({
- title: '权限申请',
- content: '需要授予相机权限才能拍照打卡',
- success: (res) => {
- if (res.confirm) wx.openSetting();
- else this.resetTimerUI(); // 拒绝权限则重置界面
- }
- });
- }
- });
- } else {
- this.takePhoto();
- }
- }
- });
- },
- takePhoto: function () {
- wx.chooseImage({
- count: 1,
- sourceType: ['camera'],
- success: (res) => {
- const photoPath = res.tempFilePaths[0];
- this.setData({ photoPath });
- wx.setStorageSync('checkInPhoto', photoPath);
- wx.showToast({ title: '拍照成功' });
-
- // 拍照成功后才开始计时
- this.startTimer();
- },
- fail: (err) => {
- console.error('拍照失败', err);
- wx.showToast({ title: '拍照失败', icon: 'none' });
- this.resetTimerUI(); // 拍照失败则重置界面
- }
- });
- },
- startTimer: function() {
- // 记录开始时间和预计结束时间
- const now = Date.now();
- this.setData({
- isTimerRunning: true,
- startTime: now,
- endTime: now + this.data.remainingTime
- });
-
- // 更新计时器显示
- this.updateTimer();
- },
- updateTimer: function() {
- if (!this.data.isTimerRunning) return;
-
- const now = Date.now();
- let remaining = this.data.endTime - now;
-
- // 处理计时结束
- if (remaining <= 0) {
- this.finishTimer();
- return;
- }
-
- // 更新剩余时间显示
- const minutes = Math.floor(remaining / 60000);
- const seconds = Math.floor((remaining % 60000) / 1000);
- const timeStr = `${minutes >= 10 ? minutes : '0' + minutes}:${seconds >= 10 ? seconds : '0' + seconds}`;
-
- this.setData({
- remainingTime: remaining,
- timeStr: timeStr
- });
-
- // 更新进度环
- this.drawActive();
-
- // 每秒更新一次
- this.timerInterval = setTimeout(() => {
- this.updateTimer();
- }, 1000);
- },
- // 重置计时器UI
- resetTimerUI: function() {
- this.setData({
- clockShow: false,
- isTimerRunning: false,
- photoPath: ''
- });
- clearTimeout(this.timerInterval);
- },
- // 完成计时
- finishTimer: function() {
- this.setData({
- isTimerRunning: false,
- timeStr: '00:00'
- });
- clearTimeout(this.timerInterval);
-
- // 显示完成提示
- wx.showToast({
- title: '专注完成!',
- icon: 'success',
- duration: 2000
- });
- },
- pause: function () {
- clearInterval(this.data.timer);
- this.setData({
- pauseShow: false,
- continueCancleShow: true,
- okShow: false
- });
- },
- continue: function () {
- this.drawActive();
- this.setData({
- pauseShow: true,
- continueCancleShow: false,
- okShow: false
- });
- },
- cancle: function () {
- clearInterval(this.data.timer);
- this.setData({
- pauseShow: true,
- continueCancleShow: false,
- okShow: false,
- clockShow: false
- });
- },
- ok: function () {
- clearInterval(this.data.timer);
- this.setData({
- pauseShow: true,
- continueCancleShow: false,
- okShow: false,
- clockShow: false
- });
- }
- })
|