天天看点

【软工课期末项目】基于微信小程序的简约轻量习惯培养软件ehabit

大家好,今天很高兴给大家分享这次作业。我们是第七最帅小组。

小程序简介:

ehabit针对普遍群体存在难以养成良好习惯,以及当前软件市场的习惯养成软件冗余复杂等问题,基于微信小程序便携式的设计,研发一款能够解决人们在想要养成好习惯时意志不坚定问题的轻量级软件,为用户提供推荐习惯,自定义习惯等功能,从而达到用户养成良好习惯的目的。

我们已经上线,预览请扫码,观察效果和使用:

【软工课期末项目】基于微信小程序的简约轻量习惯培养软件ehabit

项目及代码详情见github:https://github.com/a1171404817/the-terminal-project-in-ruangong.git

五次站立会议博客地址:

https://blog.csdn.net/qq_42741048/article/details/90274001

https://blog.csdn.net/qq_42741048/article/details/90474908

https://blog.csdn.net/qq_42741048/article/details/90474979

https://blog.csdn.net/guifei0/article/details/93873441

https://blog.csdn.net/guifei0/article/details/93873468

效果图:

【软工课期末项目】基于微信小程序的简约轻量习惯培养软件ehabit
【软工课期末项目】基于微信小程序的简约轻量习惯培养软件ehabit

花费时间,大概花费了三周多,一开始完成没有任何学习小程序的知识,然后在b站上找课程一两天刷完了,一点一点做总共js有1000行代码,加上样式、wxml文件300行代码;

其中用到了很多工具类,比如这个报表、日期转星期,这些都用通用的工具类,只要拿过来调用就好。

功能介绍:

1、右滑开始、左滑停止 这个会有动画、计时、进度条的效果;

2、长按可以编辑时间和删除;

3、右下可以添加推荐的习惯、自定义习惯、清除进度条和统计表的功能;

4、上方是统计折线图 可以统计每一周的习惯次数;

5、还支持锁屏计时功能。既锁屏之后,后台记录锁屏的时间,当你锁屏之后,会自动加上去;

6、小程序介绍页面。

部分源代码:

首页

<!--index.wxml-->

<view class="container">
  <view class="title1">{{list.length}}个任务</view>
   <view class="title2">今天·{{listID1+" "+date1[0].week}} </view>
   
    <canvas canvas-id="lineCanvas" disable-scroll="true" class="canvas" bindtouchstart="touchHandler"></canvas>

  <view class="todoAll" wx:for="{{list}}" wx:for-key="index" wx:for-item="item">
    <movable-area class="todoArea">
      <movable-view class="todoBar" direction="horizontal" damping="30" friction="1" out-of-bounds="true" catchtouchstart="start" catchtouchmove="move" catchtouchend="end" id="{{index+1}}" style="background:{{item.chooseColor}}">
        <view class="text">
          <view class="todoProgress">{{item.todoProgress}}%</view>
          <view class="todoText">{{item.todoText}}</view>
          <view class="todoTime">{{item.todoTime}}</view>
          <image class="workImg" src="../../img/work.gif" mode="aspectFit" hidden="{{item.work}}"></image>
          <view class="todoDone">{{item.todoDone}}</view>
          <progress class="progressBar" percent="{{item.todoProgress}}" activeColor="#1AAD19" backgroundColor="{{item.chooseColor}}" stroke-width="4" active active-mode="forwards"/>
        </view>
      </movable-view>
    </movable-area>

  </view>
</view>

<image class="tip" src="{{imgSrc}}" mode="aspectFill" style="display:{{firstLog?'block':'none'}}"></image>
<view class="float" bindtap="float">{{call}}</view>
<view class="clear" bindtap="clear" animation="{{buttonAni}}"><image class="buttonIcon" src="../../img/clear.png" style="width:50%;height:50%;margin-top:9px"></image></view>
<view class="add" bindtap="add" animation="{{buttonAni}}"><image class="buttonIcon" src="../../img/add.png" style="width:50%;height:50%;margin-top:9px"></image></view>

<view class="zidingyi" bindtap="zidingyiadd" animation="{{buttonAni}}"><image class="buttonIcon" src="../../img/zidingyi.png" style="width:50%;height:50%;margin-top:9px"></image></view>

<view class="qingchu" bindtap="clearbaobiao" animation="{{buttonAni}}"><image class="buttonIcon" src="../../img/qingchu.png" style="width:50%;height:50%;margin-top:9px"></image></view>

<view class="addForm" animation="{{addAnimation}}">
  <form bindsubmit="formSubmit" class="white">
    
    <view class="label">新的习惯</view>
    <picker-view class="timePicker" value="{{first}}" indicator-style="height:50px" catchchange="pickerChange">

  <picker-view-column>
        <view class="habits" name="habits" wx:for="{{habits}}" style="line-height:50px;text-align:center">{{item}}</view>
      </picker-view-column>

      <picker-view-column>
        <view class="hour" name="hour" wx:for="{{hours}}" style="line-height:50px;text-align:center;">{{item}}</view>
      </picker-view-column>
      
      <picker-view-column>
        <view class="min" name="min" wx:for="{{mins}}" style="line-height:50px;text-align:center">{{item}}</view>
      </picker-view-column>

      
    </picker-view>
    <view class="formButton">
      <button size="mini" type="primary" form-type="submit">添加</button>
      <button size="mini" type="warn" bindtap="cancel">取消</button>
    </view>
  </form>
</view>

<view class="zidingyiForm" animation="{{zidingyiAnimation}}">
<form bindsubmit="zidingyiformSubmit" class="white">
    <input class="todoName" name="todoName" type="text" placeholder=" 任务名" placeholder-class="place" maxlength="9" maxlength='20' />
    <view class="label">自定义</view>
    <picker-view class="timePicker" value="{{first}}" indicator-style="height:50px" catchchange="zidingyipickerChange">
      <picker-view-column>
        <view class="hour" name="hour" wx:for="{{hours}}" style="line-height:50px;text-align:center;">{{item}}</view>
      </picker-view-column>
      <picker-view-column>
        <view class="min" name="min" wx:for="{{mins}}" style="line-height:50px;text-align:center">{{item}}</view>
      </picker-view-column>
    </picker-view>
    <view class="formButton">
      <button size="mini" type="primary" form-type="submit">添加</button>
      <button size="mini" type="warn" bindtap="zidingyicancel">取消</button>
    </view>
  </form>
</view>


<view class="editForm" animation="{{editAnimation}}">
  <form bindsubmit="editSubmit" class="white">
    <input class="todoName" name="todoName" type="text" placeholder=" 任务名" placeholder-class="place" maxlength="9" value="{{editName}}" disabled="disabled" maxlength='20'/>
    <view class="label">Edit</view>
    <picker-view class="timePicker" value="{{first}}" indicator-style="height:50px" catchchange="editPickerChange" value="{{valueID}}">

      <picker-view-column>
        <view class="hour" name="hour" wx:for="{{hours}}" style="line-height:50px;text-align:center;">{{item}}</view>
      </picker-view-column>

      <picker-view-column>
        <view class="min" name="min" wx:for="{{mins}}" style="line-height:50px;text-align:center" value="{{minID}}">{{item}}</view>
      </picker-view-column>

    </picker-view>

    <view class="formButton">
      <button size="mini" type="warn" catchtap="del">删除</button>
      <button size="mini" type="primary" form-type="submit">修改</button>
    </view>
  </form>
</view>



           

部分js

let sysdate = require('../../utils/date.js');
let time = sysdate.formatDate(new Date());
var lineChart = null;
var util = require('../../utils/util.js');
var wxCharts = require('../../utils/wxcharts.js');
var app = getApp()
Page({
  data: {
    arrHabitsWeeks: [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]],
    timeID: "",
    firstLog: true,
    imgSrc: "../../img/right_gaitubao_1080x1796.png",
    preIndex: '',
    userInfo: {},
    listID: "",
    listID1: "",
    first: [0,0,0],
    hours: [],  //hours实是分
    mins: [],   //mins实是秒
    habits: ["喝水", "吃个好早餐", "锻炼", "今天感觉棒极了", "充电小睡", "写日记", "创建时间表", "刷牙", "喝茶", "沐浴", "冥想", "学习与研究", "心存感恩", "打扮自己", "排除干扰", "摆脱与创造", "晨间随笔", "清洁与整理", "瑜伽", "给父母打电话", "联系朋友","获取灵感", "记下待办事项", "记录我的时间", "走步", "阅读", "瑜伽", "零邮件箱", "自定义习惯"],
    timeHour: '0',
    timeMin: '00',
    habitlist: "0",
    addAnimation: {},
    zidingyiAnimation:{},
    editAnimation: {},
    buttonAni: {},
    call: "+",
    index: "",
    ifPicker: 0,
    list: [
      {
        todoID: 1,
        todoText: "开启ehabit之旅",
        todoTime: "2:00",
        todoDone: "1:00",
        todoProgress: 50,
        work: true,
        chooseColor: "#ffffff",
      }
    ],
    //可修改数据
    setTime: 1000,//这里是计时时间,一分钟进行一次计时时间
    date1: [],
    week_n_tran_str:["周一","周二","周三","周四","周五","周六","周日"],
  },
  //事件处理函数
  bindViewTap: function () {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
     
   var that=this;

    wx.getStorage({
      key: 'key1',
      success(res) {
        console.log(res.data)
        that.data.arrHabitsWeeks = res.data;
      }
    })


    this.setData({
      date1: sysdate.getDates(1, time)
    });
    console.log(this.data.date1[0]);
    console.log(this.weekstringTransInt(this.data.date1[0].week));
    console.log('onLoad');
    var that = this;
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function (userInfo) {
      //更新数据
      that.setData({
        userInfo: userInfo
      });
    });
    var date = new Date();
    var listID = String(date.getFullYear()) + String(date.getMonth() + 1) + String(date.getDate());
    // var listID1 = String(date.getMonth() + 1) + "月" + String(date.getDate())+ "日" + String(date.getHours()) + "时" + String(date.getMinutes())+"分";
    var listID1 = String(date.getMonth() + 1) + "月" + String(date.getDate()) + "日";
    console.log(date.getDate());
    var hours = [], mins = [];
    for (var i = 0; i < 121; i++) { hours.push(i); };
    for (var i = 0; i < 12; i++) { mins.push(i * 5); };
    that.setData({
      listID: listID,
      listID1: listID1,
      hours: hours,
      mins: mins,
      stayHour: date.getHours(),
      stayMin: date.getMinutes()
    });//格式未19951030这样的格式,这是今天的时间,根据这个值从本地储存获得对应的list
    wx.getStorage({
      key: 'list' + that.data.listID,
      success: function (res) {
        that.setData({
          list: res.data
        });
      },
      fail: function () {
        that.getTodo();
        console.log("获取前一次的数据");
      }
    })//首次打开页面重本地储存获取当天的数据

    wx.getStorage({
      key: "firstLog",
      success: function (res) {
        that.setData({
          firstLog: false,
          imgSrc: ""
        });
      },
    })//判断是否是第一次打开

   //onload报表部分
    var windowWidth = 320;
    try {
      var res = wx.getSystemInfoSync();
      windowWidth = res.windowWidth;
    } catch (e) {
      console.error('getSystemInfoSync failed!');
    }

    var simulationData = this.createSimulationData();
    lineChart = new wxCharts({
      canvasId: 'lineCanvas',
      type: 'line',
      categories: simulationData.categories,
      animation: true,
      // background: '#f5f5f5',
      series: [{
        name: that.data.habits[that.data.habitlist],
        data: that.data.arrHabitsWeeks[that.data.habitlist],   //控制上面的每一个点
        format: function (val, name) {
          return val.toFixed(1);
        }
      }
      ],
      xAxis: {
        disableGrid: true
      },
      yAxis: {
        title: '次数',
        format: function (val) {
          return val.toFixed(1);
        },
        min: 0
      },
      width: windowWidth,
      height: 160,
      dataLabel: false,
      dataPointShape: true,
      extra: {
        lineStyle: 'curve'
      }
    });
   
  },
           

代码说明:

用到了两个重要的工具类:

一个date 将日期转周

还有wx charts 报表 图标插件,使用canvas画的 可以绘制这折现图饼图等等

Js代码说明:

Data数据 这个是报表的数组,二位数组,每一个数组代表一个习惯,里面每一个数代表每一天这个数的次数(比较暴力)

Onload 一个页面打开只加载一次

Onshow 页面跳转就会加载 加载数据和初始化

Move start end 处理滑动 长按 与前面的move-view 用bintap想关联上

Formsubmit 处理添加新的习惯表单的函数

Pickchange 将数据与前台的picker(滚动选择器)关联

add、canel、reduce 负责和前面的表单Animation属性实现点的动画效果  如果他不是立刻出现 而是有个向上的 还有消失效果

Editsumbit 编辑的页面同理

Del和删除习惯条有关

Clear 全清习惯条

touchHandler下面的、updateData 是工具类 处理报表的函数

前台:

{{读取后端的data}}

Canvas画图

前端通过for在生成进度掉

动态通过animation藏起来

里面有个表单

Picker滚动选择器

不足之处:

  1. 报表的数据数据持久化,使用是本地缓存(存在本地)暂时解决。更好的数据持久化可以用leancloud、或者微信自带的数据库。
  2. 统计图有点小瑕疵,小小数点和负数的时候会出现进度条 要去改工具类包比较麻烦。但它是自适应得 数大了就没有小数(如上10)和负责,数小得时候他比较精确,有点不完美,但影响不大。

     3.还有一些细节的地方不够完善,如介绍页面右箭头没有完全的对齐,和推荐习惯里有“自定义习惯”一项= =是当时时代的产物,没有删掉(这个后面抽取出来作为了一个单独功能)

     4.自适应问题,有些定位采用的因为margin,用得是以iPhonex位模板,这个可以正确显示,其他会有些小距离

感受:

学了这门课,感觉掌握了一门技能,就是开发微信小程序。

这有时候一个小问题卡到崩溃,但突然又换条路,柳暗花明,那种绝望中又有希望,那种解决问题之后得开心是难以表述得,实在非常开心!

而且速成,这是我们得第一个上线微信小程序。

并且直接可以使用,没有之前分享:要构建自己得服务器那么麻烦,

直接上线就可以二维码分享 非常的方便,这就是微信小程序的优点吧。

最后感谢我的组员,让我完成了我的第一个微信小程序小项目,离不开他们的支持。

特别感谢:我的室友,张继露同学。一起参加微信小程序大赛的缘故,虽然他做的小程序做的很好、有点严格没有少帮我让我学到了很多小程序的知识能应用到这个项目上来。

继续阅读