├── 20191231204944869.jpg ├── 20191231205313718.jpg ├── 20191231205553436.jpg ├── 20191231205809984.jpg ├── LICENSE ├── README.md ├── README_imgs ├── 20191231204944869.jpg ├── 20191231205313718.jpg ├── 20191231205553436.jpg └── 20191231205809984.jpg ├── cloudfunctions ├── login │ ├── index.js │ └── package.json └── openapi │ ├── config.json │ ├── index.js │ └── package.json ├── miniprogram ├── app.js ├── app.json ├── app.wxss ├── assert │ ├── add.svg │ ├── calendar.svg │ ├── goback.svg │ └── more-default.svg ├── components │ ├── carditem │ │ ├── carditem.js │ │ ├── carditem.json │ │ ├── carditem.wxml │ │ └── carditem.wxss │ └── navbar │ │ ├── navbar.js │ │ ├── navbar.json │ │ ├── navbar.wxml │ │ └── navbar.wxss ├── images │ ├── button │ │ ├── count.png │ │ └── countback.png │ ├── icon │ │ ├── aboutus.png │ │ ├── add_timecard.png │ │ ├── arrow-right.png │ │ ├── brand.png │ │ ├── calendar.png │ │ ├── cards-ed.png │ │ ├── cards.png │ │ ├── delete.png │ │ ├── feedback.png │ │ ├── model.png │ │ ├── person.png │ │ ├── share.png │ │ ├── station-ed.png │ │ └── station.png │ └── role │ │ ├── Ant-Man.svg │ │ ├── Aquaman.svg │ │ ├── Batman.svg │ │ ├── Captain-America.svg │ │ ├── Captain-Atom.svg │ │ ├── Cyclops.svg │ │ ├── Deadpool.svg │ │ ├── Green-Lantern.svg │ │ ├── Hulk.svg │ │ ├── Iron-Man.svg │ │ ├── Martian-Manhunter.svg │ │ ├── Mister-Fantastic.svg │ │ ├── Spider-Man.svg │ │ ├── Superman.svg │ │ ├── The-Flash.svg │ │ ├── Thor.svg │ │ └── Wolverine.svg ├── pages │ ├── create │ │ ├── create.js │ │ ├── create.json │ │ ├── create.wxml │ │ └── create.wxss │ ├── index │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ └── login │ │ ├── login.js │ │ ├── login.json │ │ ├── login.wxml │ │ └── login.wxss ├── sitemap.json ├── style │ └── guide.wxss └── utils │ ├── convertDate.js │ └── util.js └── project.config.json /20191231204944869.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/20191231204944869.jpg -------------------------------------------------------------------------------- /20191231205313718.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/20191231205313718.jpg -------------------------------------------------------------------------------- /20191231205553436.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/20191231205553436.jpg -------------------------------------------------------------------------------- /20191231205809984.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/20191231205809984.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | @[TOC](TimeCard) 2 | `微信小程序` `倒计日` `累计日` 3 | # 项目介绍 4 | **TimeCard**——一个基于微信开发工具所编写的一款小程序,它是一个关于效率的小程序,主要提供倒计日和目标日(待完成)的功能。该项目正在持续开发中(2019年12月31日重新启动),目前版本更新为`v0.1.1`。(项目地址) 5 | 6 | ## CSDN 7 | TimeCard 8 | 9 | # 新的改变 10 | 11 | 我对**时光车站**项目进行了一些界面上的优化与数据存储结构和存储位置调整: 12 | 1. **船新的界面设计** ,增加了相应的按钮旋转动画,类型选择`ease`。这样在按下按钮时,动画不会过于生硬。同时为遮罩层添加**颜色渐变动画**,同时也为弹出的功能抽屉赋予动画。为使用者带来良好的编辑体验; 13 | 2. 为首页的卡片展示,**重新布局样式**,使用**金色**来标记起始时间与结束时间,寓意着时间的珍贵; 14 | 3. 将时间进度条拉长~~~~长,**加粗**; 15 | 4. 去掉了 ~~**已过天数 / 总天数**~~ 的显示; 16 | 5. 增加了进度条上的图表显示,如**漫威人物**等;![美国队长,来自Iconfont](https://img-blog.csdnimg.cn/20191231201954871.png#pic_center) 17 | 6. 增加了 **可旋转的** 操作按钮; 18 | 19 | # 项目功能 20 | 21 | > TimeCard 22 | >> 登录注册(使用微信自身提供的方法) 23 | >> 选择创建类型 24 | >> 25 | >>> 倒计日 26 | >>>> 创建 27 | >>>> 分享 28 | >>>> 修改 29 | >>>> 删除 30 | >>> 31 | >>> 累计日 32 | >>>> 创建 33 | >>>> 分享 34 | >>>> 修改 35 | >>>> 删除 36 | 37 | ## 已完成功能及还需完成功能 38 | - [x] 用户登录注册 39 | - [x] 新建时点击按钮的动画 40 | - [x] 倒计日创建 41 | - [ ] 倒计日模块中修改、分享及删除 42 | - [ ] 累计日模块 43 | - [ ] 名称搜索 44 | - [ ] 日期筛选 45 | - [ ] 标签模块 46 | 47 | 48 | 49 | ## 项目运行效果图 50 | 51 | 1. 登录界面 52 | 53 | 2. 程序主页 54 | 55 | 3. 选择创建类型 56 | 57 | 4. 创建倒计日 58 | 59 | 60 | ## 用户数据存储 61 | 本项目数据存储的方式由`知晓云`更改为`云开发`(微信开发工具自己开发的数据存储,为了方便前后端结合在一起开发),个人开发者小型项目免费版本基本可以满足需求。 62 | 63 | 总共设置了三个集合来存储相应的数据(以后还会增加...) 64 | 1. 用于存储用户信息的集合(`user表`) 65 | 2. 用于存储用户所填卡片信息的集合(`user-cards表`) 66 | 3. 用于存储一个用户下所有的卡片ID的集合(`user-cards-set表`) 67 | 68 | ## 云开发 quickstart 69 | 70 | 这是云开发的快速启动指引,其中演示了如何上手使用云开发的三大基础能力: 71 | 72 | - 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 文档型数据库 73 | - 文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理 74 | - 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写业务逻辑代码 75 | 76 | ### 参考文档 77 | 78 | - [云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html) 79 | 80 | # 联系我 81 | 82 | 如果你喜欢这个项目,欢迎Star、Fork。也欢迎 Pull requests 一起完善这个项目。 83 | 邮箱:agonyperkey@gmail.com 84 | QQ:314068298 85 | 86 | 目前,该项目已有旧版在微信小程序上发布,但是这次所做出的修改与变化是巨大的,明年年初可以将新版本发布到微信平台,自己也在这个项目中学习到了许多关于项目开发的常识。 87 | 最后,祝大家新年快乐,不忘初心,砥砺前行! 88 | # License 89 | 90 | >Licensed under the Apache License, Version 2.0 (the “License”); 91 | you may not use this file except in compliance with the License. 92 | You may obtain a copy of the License at 93 | http://www.apache.org/licenses/LICENSE-2.0 94 | Unless required by applicable law or agreed to in writing, software 95 | distributed under the License is distributed on an “AS IS” BASIS, 96 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 97 | See the License for the specific language governing permissions and 98 | limitations under the License. 99 | -------------------------------------------------------------------------------- /README_imgs/20191231204944869.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/README_imgs/20191231204944869.jpg -------------------------------------------------------------------------------- /README_imgs/20191231205313718.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/README_imgs/20191231205313718.jpg -------------------------------------------------------------------------------- /README_imgs/20191231205553436.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/README_imgs/20191231205553436.jpg -------------------------------------------------------------------------------- /README_imgs/20191231205809984.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/README_imgs/20191231205809984.jpg -------------------------------------------------------------------------------- /cloudfunctions/login/index.js: -------------------------------------------------------------------------------- 1 | // 云函数模板 2 | // 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署” 3 | 4 | const cloud = require('wx-server-sdk') 5 | 6 | // 初始化 cloud 7 | cloud.init() 8 | 9 | /** 10 | * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端 11 | * 12 | * event 参数包含小程序端调用传入的 data 13 | * 14 | */ 15 | exports.main = (event, context) => { 16 | console.log(event) 17 | console.log(context) 18 | 19 | // 可执行其他自定义逻辑 20 | // console.log 的内容可以在云开发云函数调用日志查看 21 | 22 | // 获取 WX Context (微信调用上下文),包括 OPENID、APPID、及 UNIONID(需满足 UNIONID 获取条件) 23 | const wxContext = cloud.getWXContext() 24 | 25 | return { 26 | event, 27 | openid: wxContext.OPENID, 28 | appid: wxContext.APPID, 29 | unionid: wxContext.UNIONID, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cloudfunctions/login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "login", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cloudfunctions/openapi/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | "wxacode.get", 5 | "templateMessage.send", 6 | "templateMessage.addTemplate", 7 | "templateMessage.deleteTemplate", 8 | "templateMessage.getTemplateList", 9 | "templateMessage.getTemplateLibraryById", 10 | "templateMessage.getTemplateLibraryList" 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /cloudfunctions/openapi/index.js: -------------------------------------------------------------------------------- 1 | // 云函数入口文件 2 | const cloud = require('wx-server-sdk') 3 | 4 | cloud.init() 5 | 6 | // 云函数入口函数 7 | exports.main = async (event, context) => { 8 | switch (event.action) { 9 | case 'sendTemplateMessage': { 10 | return sendTemplateMessage(event) 11 | } 12 | case 'getWXACode': { 13 | return getWXACode(event) 14 | } 15 | default: { 16 | return 17 | } 18 | } 19 | } 20 | 21 | async function sendTemplateMessage(event) { 22 | const { OPENID } = cloud.getWXContext() 23 | 24 | // 接下来将新增模板、发送模板消息、然后删除模板 25 | // 注意:新增模板然后再删除并不是建议的做法,此处只是为了演示,模板 ID 应在添加后保存起来后续使用 26 | const addResult = await cloud.openapi.templateMessage.addTemplate({ 27 | id: 'AT0002', 28 | keywordIdList: [3, 4, 5] 29 | }) 30 | 31 | const templateId = addResult.templateId 32 | 33 | const sendResult = await cloud.openapi.templateMessage.send({ 34 | touser: OPENID, 35 | templateId, 36 | formId: event.formId, 37 | page: 'pages/openapi/openapi', 38 | data: { 39 | keyword1: { 40 | value: '未名咖啡屋', 41 | }, 42 | keyword2: { 43 | value: '2019 年 1 月 1 日', 44 | }, 45 | keyword3: { 46 | value: '拿铁', 47 | }, 48 | } 49 | }) 50 | 51 | await cloud.openapi.templateMessage.deleteTemplate({ 52 | templateId, 53 | }) 54 | 55 | return sendResult 56 | } 57 | 58 | async function getWXACode(event) { 59 | 60 | // 此处将获取永久有效的小程序码,并将其保存在云文件存储中,最后返回云文件 ID 给前端使用 61 | 62 | const wxacodeResult = await cloud.openapi.wxacode.get({ 63 | path: 'pages/openapi/openapi', 64 | }) 65 | 66 | const fileExtensionMatches = wxacodeResult.contentType.match(/\/([^\/]+)/) 67 | const fileExtension = (fileExtensionMatches && fileExtensionMatches[1]) || 'jpg' 68 | 69 | const uploadResult = await cloud.uploadFile({ 70 | // 云文件路径,此处为演示采用一个固定名称 71 | cloudPath: `wxacode_default_openapi_page.${fileExtension}`, 72 | // 要上传的文件内容可直接传入图片 Buffer 73 | fileContent: wxacodeResult.buffer, 74 | }) 75 | 76 | if (!uploadResult.fileID) { 77 | throw new Error(`upload failed with empty fileID and storage server status code ${uploadResult.statusCode}`) 78 | } 79 | 80 | return uploadResult.fileID 81 | } 82 | -------------------------------------------------------------------------------- /cloudfunctions/openapi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openapi", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /miniprogram/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | 5 | if (!wx.cloud) { 6 | console.error('请使用 2.2.3 或以上的基础库以使用云能力') 7 | } else { 8 | wx.cloud.init({ 9 | traceUser: true, 10 | }) 11 | } 12 | 13 | this.globalData = { 14 | 15 | } 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/login/login", 4 | "pages/index/index", 5 | "pages/create/create" 6 | ], 7 | "window": { 8 | "backgroundColor": "#F6F6F6", 9 | "backgroundTextStyle": "light", 10 | "navigationBarBackgroundColor": "#F6F6F6", 11 | "navigationBarTitleText": "时光车站", 12 | "navigationBarTextStyle": "black", 13 | "navigationStyle": "custom" 14 | }, 15 | "sitemapLocation": "sitemap.json" 16 | } -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | page{ 3 | background-color: #FFFBF3; 4 | } 5 | .container{ 6 | margin-top: 160rpx; 7 | } 8 | -------------------------------------------------------------------------------- /miniprogram/assert/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/assert/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/assert/goback.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/assert/more-default.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/components/carditem/carditem.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | /*title: { // 属性名 4 | type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) 5 | value: '标题' // 属性初始值(可选),如果未指定则会根据类型选择一个 6 | },*/ 7 | cardTitle: { 8 | type: String, 9 | value: '请输入标题...' 10 | }, 11 | cardColor: { 12 | type: String, 13 | value: '#e63c56' 14 | }, 15 | startTime: { 16 | type: String, 17 | value: '2019-05-01' 18 | }, 19 | roleName: { 20 | type: String, 21 | value: 'Superman' 22 | }, 23 | endTime: { 24 | type: String, 25 | value: '2019-09-01' 26 | }, 27 | percent: { 28 | type: Number, 29 | value: 0 30 | }, 31 | finished: { 32 | type: Boolean, 33 | value: false 34 | } 35 | }, 36 | attached: function() { 37 | this.aniAct(); 38 | }, 39 | data: { 40 | cardHandle: true, 41 | }, 42 | methods: { 43 | aniAct: function() { 44 | var that = this; 45 | // 定义旋转动画 46 | that.aniRotate = wx.createAnimation({ 47 | duration: 1000, 48 | timingFunction: 'ease', 49 | }); 50 | }, 51 | // 点击操作,按钮旋转 52 | rotate90: function() { 53 | var that = this 54 | // 旋转角度是固定的,不是基于当前的位置 55 | if (that.data.cardHandle) { 56 | that.aniRotate.rotate(90).step() 57 | } else { 58 | that.aniRotate.rotate(0).step() 59 | } 60 | that.setData({ 61 | aniRotateA: that.aniRotate.export(), 62 | cardHandle: !that.data.cardHandle 63 | }) 64 | }, 65 | } 66 | }) -------------------------------------------------------------------------------- /miniprogram/components/carditem/carditem.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /miniprogram/components/carditem/carditem.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{cardTitle}} 7 | 起始日:{{startTime}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 27 | 28 | 31 | 截止日:{{endTime}} 32 | 33 | 34 | 36 | 37 | 倒计日 38 | 39 | 40 | 累计日 41 | 42 | 43 | -------------------------------------------------------------------------------- /miniprogram/components/carditem/carditem.wxss: -------------------------------------------------------------------------------- 1 | .card-items { 2 | display: flex; 3 | flex-direction: column; 4 | position: relative; 5 | width: 92%; 6 | /* 加上标签 */ 7 | height: 300rpx; 8 | padding: 14rpx; 9 | margin: 18rpx auto; 10 | border-radius: 20rpx; 11 | box-shadow: 2px 2px 3px #999; 12 | } 13 | 14 | /* 事件标题、时间及操作 */ 15 | 16 | .card-title-createtime-handle { 17 | display: flex; 18 | flex-direction: row; 19 | justify-content: space-between; 20 | width: 100%; 21 | } 22 | 23 | .card-title-createtime { 24 | display: flex; 25 | flex-direction: column; 26 | } 27 | 28 | .card-title { 29 | color: #fff; 30 | line-height: 50rpx; 31 | font-size: 48rpx; 32 | font-weight: bolder; 33 | font-family: "heiti"; 34 | } 35 | 36 | .card-createtime { 37 | font-size: 24rpx; 38 | line-height: 40rpx; 39 | color: #eee8aa; 40 | } 41 | 42 | .card-handle image { 43 | width: 80rpx; 44 | height: 80rpx; 45 | } 46 | 47 | /* 进度条 */ 48 | 49 | .card-role-progress { 50 | position: relative; 51 | width: 90%; 52 | margin: 18rpx auto 0; 53 | } 54 | 55 | .card-role image { 56 | position: relative; 57 | margin-left: -42rpx; 58 | width: 90rpx; 59 | } 60 | 61 | .progress-con { 62 | position: relative; 63 | height: 18rpx; 64 | } 65 | 66 | .progress { 67 | position: absolute; 68 | top: 0; 69 | height: 18rpx; 70 | background-color: #fffbf3; 71 | border-radius: 10rpx; 72 | z-index: 4; 73 | } 74 | 75 | .progress-bott { 76 | position: absolute; 77 | top: 0; 78 | width: 100%; 79 | height: 18rpx; 80 | background-color: #505050; 81 | opacity: 0.5; 82 | border-radius: 10rpx; 83 | z-index: 3; 84 | } 85 | 86 | /* 结束时间样式与起始日相同 */ 87 | 88 | .card-endtime { 89 | position: absolute; 90 | bottom: 50rpx; 91 | right: 10rpx; 92 | font-size: 24rpx; 93 | line-height: 40rpx; 94 | color: #eee8aa; 95 | text-align: right; 96 | } 97 | 98 | /* 已结束字体样式 */ 99 | .finished{ 100 | font-size: 80rpx; 101 | color: #ffffff; 102 | text-align: center; 103 | } 104 | 105 | /* 标签 */ 106 | 107 | .card-tag { 108 | display: flex; 109 | flex-direction: row; 110 | position: absolute; 111 | bottom: 10rpx; 112 | right: 5rpx; 113 | height: 36rpx; 114 | /* background- color: red; */ 115 | } 116 | 117 | .tag-item { 118 | padding: 0 4rpx; 119 | font-size: 30rpx; 120 | color: #79a2a8; 121 | font-weight: bolder; 122 | line-height: 36rpx; 123 | background-color: #fffbf3; 124 | border-radius: 6rpx; 125 | margin: 0 8rpx; 126 | right: 0; 127 | } 128 | -------------------------------------------------------------------------------- /miniprogram/components/navbar/navbar.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | /*title: { // 属性名 4 | type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) 5 | value: '标题' // 属性初始值(可选),如果未指定则会根据类型选择一个 6 | },*/ 7 | 8 | // 背景颜色 9 | backgroundColor: { 10 | type: String, 11 | value: '#FFFBF3' 12 | }, 13 | // 导航栏标题 14 | navTitleText: { 15 | type: String, 16 | value: '导航栏' 17 | }, 18 | // 导航栏操作图标 19 | navHandleImg: { 20 | type: String, 21 | value: '' 22 | }, 23 | method: { 24 | type: String, 25 | value: '' 26 | } 27 | }, 28 | attached: function() { 29 | var that = this; 30 | that.setNavSize(); 31 | that.setAnimate(); 32 | }, 33 | data: { 34 | statusBarHeight: 0, 35 | titleBarHeight: 0, 36 | animationB: {}, 37 | addStatus: false, 38 | hideAddPopup: true 39 | }, 40 | methods: { 41 | // 通过获取系统信息计算导航栏高度 42 | setNavSize: function() { 43 | var sysinfo = wx.getSystemInfoSync(); 44 | var statusBarH = sysinfo.statusBarHeight; 45 | if (sysinfo.system.indexOf('iOS') > -1) { 46 | // 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2 47 | // ios的导航栏高度 48 | var titleBarH = 32 + 6 * 2; 49 | } else { 50 | // Android的导航栏高度 51 | var titleBarH = 32 + 8 * 2; 52 | } 53 | this.setData({ 54 | // 状态栏高度 + 标题栏高度 55 | statusBarHeight: sysinfo.statusBarHeight, 56 | titleBarHeight: titleBarH 57 | }); 58 | }, 59 | // 设置动画 60 | setAnimate: function() { 61 | var that = this; 62 | that.animation = wx.createAnimation({ 63 | duration: 1000, 64 | timingFunction: 'ease', 65 | }) 66 | }, 67 | // 点击添加按钮,旋转图标并弹出菜单栏 68 | /* 69 | 点击出现菜单后,在点击时会出现bug 70 | 目前解决办法:使用遮罩层进行屏蔽,覆盖在按钮上面 71 | */ 72 | createButtonHandle: function() { 73 | var that = this; 74 | var addStatus = that.data.addStatus; 75 | // 旋转角度是固定的,不是基于当前的位置 76 | if (!addStatus) { 77 | that.animation.rotate(45).step(); 78 | // console.log("运行了1") 79 | that.setData({ 80 | animationB: that.animation.export(), 81 | addStatus: !addStatus, 82 | hideAddPopup: !that.data.hideAddPopup 83 | }) 84 | that.TAddPopup(); 85 | 86 | } else { 87 | that.animation.rotate(0).step(); 88 | that.setData({ 89 | animationB: that.animation.export(), 90 | addStatus: !addStatus, 91 | hideAddPopup: !that.data.hideAddPopup 92 | }) 93 | } 94 | 95 | }, 96 | // 改变hideAddPopup的值实现对AddPopup的控制 97 | TAddPopup: function() { 98 | // console.log(this.data.hideAddPopup) 99 | let temp = this.data.hideAddPopup; 100 | // 点击事件带参传入父级 101 | this.triggerEvent('updataAddPopup', temp); 102 | }, 103 | 104 | // 隐藏Add菜单 105 | hideAddPopup: function() { 106 | var that = this; 107 | that.setData({ 108 | hideAddPopup: true 109 | }) 110 | }, 111 | // 显示Add菜单 112 | showAddPopup: function() { 113 | var that = this; 114 | that.setData({ 115 | hideAddPopup: false 116 | }) 117 | }, 118 | // 返回按钮 119 | goback: function() { 120 | wx.navigateBack({ 121 | delta: 1 122 | }) 123 | } 124 | } 125 | }) -------------------------------------------------------------------------------- /miniprogram/components/navbar/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /miniprogram/components/navbar/navbar.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{navTitleText}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /miniprogram/components/navbar/navbar.wxss: -------------------------------------------------------------------------------- 1 | .status-title-bar { 2 | width: 100%; 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | z-index: 90; 7 | } 8 | 9 | .status-bar { 10 | width: 100%; 11 | } 12 | 13 | .title-bar { 14 | width: 100%; 15 | position: relative; 16 | } 17 | .navHandle{ 18 | position: absolute; 19 | width: 32px; 20 | height: 32px; 21 | left: 24rpx; 22 | top: 50%; 23 | margin-top: -16px; 24 | } 25 | .navHandle image{ 26 | width: 32px; 27 | } 28 | .navTitle { 29 | text-align: center; 30 | font-weight: bolder; 31 | color: #505050; 32 | font-size: 40rpx; 33 | letter-spacing: 0.3em; 34 | } -------------------------------------------------------------------------------- /miniprogram/images/button/count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/button/count.png -------------------------------------------------------------------------------- /miniprogram/images/button/countback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/button/countback.png -------------------------------------------------------------------------------- /miniprogram/images/icon/aboutus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/aboutus.png -------------------------------------------------------------------------------- /miniprogram/images/icon/add_timecard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/add_timecard.png -------------------------------------------------------------------------------- /miniprogram/images/icon/arrow-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/arrow-right.png -------------------------------------------------------------------------------- /miniprogram/images/icon/brand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/brand.png -------------------------------------------------------------------------------- /miniprogram/images/icon/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/calendar.png -------------------------------------------------------------------------------- /miniprogram/images/icon/cards-ed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/cards-ed.png -------------------------------------------------------------------------------- /miniprogram/images/icon/cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/cards.png -------------------------------------------------------------------------------- /miniprogram/images/icon/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/delete.png -------------------------------------------------------------------------------- /miniprogram/images/icon/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/feedback.png -------------------------------------------------------------------------------- /miniprogram/images/icon/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/model.png -------------------------------------------------------------------------------- /miniprogram/images/icon/person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/person.png -------------------------------------------------------------------------------- /miniprogram/images/icon/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/share.png -------------------------------------------------------------------------------- /miniprogram/images/icon/station-ed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/station-ed.png -------------------------------------------------------------------------------- /miniprogram/images/icon/station.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinkpear/TimeCard/1ba936d013e266e27319c2d50f69f6b4cf7f4921/miniprogram/images/icon/station.png -------------------------------------------------------------------------------- /miniprogram/images/role/Ant-Man.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Aquaman.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Batman.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Captain-America.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Captain-Atom.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Cyclops.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Deadpool.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Green-Lantern.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Hulk.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Iron-Man.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Martian-Manhunter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Mister-Fantastic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Superman.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/The-Flash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Thor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/role/Wolverine.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/create/create.js: -------------------------------------------------------------------------------- 1 | // 获得工具utils工具js里面函数,先模块化引用utils里面的js地址 reqiure('js地址')成一个面向对象 2 | var app = getApp(); 3 | var convertDate = require('../../utils/convertDate.js'); 4 | var util = require('../../utils/util.js'); 5 | Page({ 6 | 7 | /** 8 | * 页面的初始数据 9 | */ 10 | data: { 11 | title: "请输入标题...", 12 | startdate: "2018-04-01", 13 | enddate: "2018-04-01", 14 | nowdate: "2018-04-01", 15 | cardstype: "", 16 | roleName: "Hulk", 17 | color: "#e63c56", 18 | roleGroups: { 19 | 'Hulk': { 20 | 'roleEname': 'Hulk', 21 | 'roleName': '浩克' 22 | }, 23 | 'Superman': { 24 | 'roleEname': 'Superman', 25 | 'roleName': '超人' 26 | }, 27 | 'Thor': { 28 | 'roleEname': 'Thor', 29 | 'roleName': '雷神' 30 | }, 31 | 'Spider-Man': { 32 | 'roleEname': 'Spider-Man', 33 | 'roleName': '蜘蛛侠' 34 | }, 35 | 'Iron-Man': { 36 | 'roleEname': 'Iron-Man', 37 | 'roleName': '钢铁侠' 38 | }, 39 | 'Green-Lantern': { 40 | 'roleEname': 'Green-Lantern', 41 | 'roleName': '绿灯侠' 42 | }, 43 | 'Batman': { 44 | 'roleEname': 'Batman', 45 | 'roleName': '蝙蝠侠' 46 | } 47 | } 48 | }, 49 | 50 | /** 51 | * 生命周期函数--监听页面加载 52 | */ 53 | onLoad: function(options) { 54 | var that = this; 55 | that.getdate(); 56 | that.setData({ 57 | cardstype: options.cardstype 58 | }) 59 | }, 60 | 61 | /** 62 | * 生命周期函数--监听页面初次渲染完成 63 | */ 64 | onReady: function() { 65 | 66 | }, 67 | 68 | /** 69 | * 生命周期函数--监听页面显示 70 | */ 71 | onShow: function() { 72 | 73 | 74 | }, 75 | 76 | /** 77 | * 生命周期函数--监听页面隐藏 78 | */ 79 | onHide: function() { 80 | 81 | }, 82 | 83 | /** 84 | * 生命周期函数--监听页面卸载 85 | */ 86 | onUnload: function() { 87 | 88 | }, 89 | 90 | /** 91 | * 页面相关事件处理函数--监听用户下拉动作 92 | */ 93 | onPullDownRefresh: function() { 94 | 95 | }, 96 | 97 | /** 98 | * 页面上拉触底事件的处理函数 99 | */ 100 | onReachBottom: function() { 101 | 102 | }, 103 | 104 | /** 105 | * 用户点击右上角分享 106 | */ 107 | onShareAppMessage: function() { 108 | 109 | }, 110 | // 同步显示到下方预览处 111 | bindKeyInput: function(e) { 112 | var str = e.detail.value; 113 | if (str.length > 0 && str.length <= 10) { 114 | this.setData({ 115 | title: e.detail.value 116 | }) 117 | } else if (str.length == 0) { 118 | this.setData({ 119 | title: "请输入标题..." 120 | }) 121 | } else { 122 | this.setData({ 123 | title: str.substring(0, 9) + "..." 124 | }) 125 | } 126 | 127 | }, 128 | // 改变颜色 129 | changecolor: function(e) { 130 | var that = this; 131 | var color = e.currentTarget.dataset.color; 132 | this.setData({ 133 | color: color 134 | }) 135 | }, 136 | // 改变角色 137 | changerole: function(e) { 138 | var that = this; 139 | var roleName = e.currentTarget.dataset.rolename; 140 | this.setData({ 141 | roleName: roleName 142 | }) 143 | }, 144 | // 获取所有角色 145 | getrolegroups: function() { 146 | var that = this; 147 | var temp = that.data.roleGroups; 148 | for (var i in temp) { 149 | console.log(i) 150 | console.log(temp[i].roleName) 151 | } 152 | }, 153 | // 获取当前日期 154 | getdate: function() { 155 | var that = this; 156 | var d = new Date(); 157 | var startdate = convertDate.dateformat("yyyy-MM-dd", d); 158 | that.setData({ 159 | startdate: startdate, 160 | enddate: startdate, 161 | nowdate: startdate 162 | }) 163 | }, 164 | // 触发起始日选择器 165 | bindDateStart: function(e) { 166 | var that = this; 167 | // console.log('picker发送选择改变,携带值为', e.detail.value) 168 | this.setData({ 169 | startdate: e.detail.value 170 | }) 171 | var days = util.getdays(that.data.startdate, that.data.nowdate); 172 | var alldays = util.getdays(that.data.startdate, that.data.enddate); 173 | var percent = parseInt(days / alldays * 100); 174 | // console.log(percent) 175 | that.setData({ 176 | complete: days, 177 | days: alldays, 178 | percent: percent 179 | }) 180 | }, 181 | // 触发目标日选择器 182 | bindDateEnd: function(e) { 183 | // console.log('picker发送选择改变,携带值为', e.detail.value) 184 | var that = this; 185 | var d1 = e.detail.value 186 | var d2 = that.data.nowdate 187 | var days = util.getdays(that.data.startdate, d1); 188 | that.setData({ 189 | days: days 190 | }) 191 | var completedays = util.getdays(that.data.startdate, d2); 192 | var percent = parseInt(completedays / days * 100).toFixed(1); 193 | that.setData({ 194 | enddate: e.detail.value, 195 | percent: percent 196 | }) 197 | }, 198 | // 保存选项 199 | formSubmit: function() { 200 | var that = this; 201 | that.addTimeCard(); 202 | }, 203 | // 创建一个新的卡片 204 | addTimeCard: function() { 205 | var that = this; 206 | /* 207 | 将卡片记录存储到数据库user-cards表中 208 | 返回的记录id,存储到user-cards-set表中 209 | */ 210 | const db = wx.cloud.database(); 211 | db.collection('user-cards').add({ 212 | data: { 213 | carditem: { 214 | title: that.data.title, 215 | starttime: that.data.startdate, 216 | endtime: that.data.enddate, 217 | color: that.data.color, 218 | cardstype: that.data.cardstype, 219 | rolename: that.data.roleName 220 | } 221 | }, 222 | success: res => { 223 | // 在返回结果中会包含新创建的记录的 _id 224 | var recordid = res._id; 225 | var userCardsset = wx.getStorageSync('userCardsset'); 226 | userCardsset.push(recordid); 227 | // 更新本地数据库 228 | wx.setStorageSync('userCardsset', userCardsset) 229 | // 更新网络数据库中的user-cards-set 230 | db.collection('user-cards-set').doc(wx.getStorageSync('userCardsset_id')).update({ 231 | // data 传入需要局部更新的数据 232 | data: { 233 | // 表示将 本地保存的卡片集添加新的数据并存储到数据库中 234 | cardsSet: userCardsset 235 | }, 236 | success(res) { 237 | wx.setStorageSync('isNew', 1); 238 | // 新建成功,页面返回 239 | wx.navigateBack({ 240 | delta: 1 241 | }) 242 | } 243 | }) 244 | }, 245 | fail: err => { 246 | wx.showToast({ 247 | icon: 'none', 248 | title: '登录失败,请重新尝试' 249 | }) 250 | console.error('[数据库] [新增记录] 失败:', err) 251 | } 252 | }) 253 | } 254 | }) -------------------------------------------------------------------------------- /miniprogram/pages/create/create.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "navbar": "../../components/navbar/navbar", 4 | "carditem": "../../components/carditem/carditem" 5 | } 6 | } -------------------------------------------------------------------------------- /miniprogram/pages/create/create.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 卡片标题 9 | 10 | 11 | 12 | 13 | 14 | 起始日期 15 | 16 | 17 | 18 | 19 | 20 | 21 | {{startdate}} 22 | 23 | 24 | 25 | 26 | 27 | 目标日期 28 | 29 | 30 | 31 | 32 | 33 | 34 | {{enddate}} 35 | 36 | 37 | 38 | 39 | 40 | 卡片颜色 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 角色选择 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {{itemName.roleName}} 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 卡片预览 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 |
-------------------------------------------------------------------------------- /miniprogram/pages/create/create.wxss: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 0 24rpx; 3 | } 4 | 5 | .title-groups { 6 | font-size: 32rpx; 7 | font-family: "pingfang"; 8 | font-weight: bolder; 9 | color: #20bfe9; 10 | } 11 | 12 | .section { 13 | margin: 20rpx auto; 14 | /* 里面是input必须加上display与flex-direction */ 15 | display: flex; 16 | flex-direction: row; 17 | justify-content: space-between; 18 | background-color: #fff; 19 | font-size: 35rpx; 20 | height: 76rpx; 21 | border-radius: 60rpx; 22 | width: 84%; 23 | padding: 0 32rpx; 24 | } 25 | 26 | .section input { 27 | margin: auto 0; 28 | width: 100%; 29 | color: #505050; 30 | } 31 | 32 | .section__title { 33 | display: flex; 34 | flex-direction: row; 35 | color: #666; 36 | } 37 | 38 | .calendar { 39 | width: 50rpx; 40 | height: 50rpx; 41 | margin: auto 0; 42 | } 43 | 44 | .picker { 45 | line-height: 76rpx; 46 | color: #505050; 47 | } 48 | 49 | .color-pick { 50 | margin: 15rpx auto; 51 | display: flex; 52 | flex-direction: row; 53 | justify-content: space-between; 54 | background-color: #fff; 55 | height: 76rpx; 56 | width: 93%; 57 | border-radius: 60rpx; 58 | } 59 | 60 | .colorpoint { 61 | width: 60rpx; 62 | height: 60rpx; 63 | border-radius: 50rpx; 64 | margin: auto 0; 65 | } 66 | 67 | .colorpointselected { 68 | width: 60rpx; 69 | height: 60rpx; 70 | border-radius: 50rpx; 71 | margin: auto 0; 72 | -webkit-box-shadow: 0px 0px 26rpx #333; 73 | } 74 | 75 | /* 角色选择 */ 76 | 77 | .role-pick { 78 | margin: 15rpx auto; 79 | background-color: #fff; 80 | width: 93%; 81 | border-radius: 28rpx; 82 | } 83 | 84 | .role_scroll_x_box { 85 | width: 100%; 86 | height: 130rpx; 87 | white-space: nowrap; 88 | display: block; 89 | } 90 | 91 | ::-webkit-scrollbar { 92 | width: 0; 93 | height: 0; 94 | color: transparent; 95 | } 96 | 97 | .role-items { 98 | display: inline-flex; 99 | flex-direction: column; 100 | width: 104rpx; 101 | height: 120rpx; 102 | margin: auto 15rpx; 103 | } 104 | .role-items-selected { 105 | display: inline-flex; 106 | flex-direction: column; 107 | width: 104rpx; 108 | height: 120rpx; 109 | margin: auto 15rpx; 110 | border-bottom: 1rpx solid #333; 111 | } 112 | 113 | .role-items image { 114 | width: 80rpx; 115 | margin: auto; 116 | } 117 | 118 | .role-items-title { 119 | font-size: 22rpx; 120 | color: #505050; 121 | text-align: center; 122 | height: 35rpx; 123 | line-height: 20rpx; 124 | font-weight: lighter; 125 | } 126 | 127 | /* 保存按钮 */ 128 | 129 | .submit { 130 | margin-top: 25rpx; 131 | background-color: #1968fc; 132 | left: 268rpx; 133 | border-radius: 50rpx; 134 | width: 145rpx; 135 | height: 70rpx; 136 | line-height: 70rpx; 137 | font-size: 35rpx; 138 | font-weight: bolder; 139 | Letter-spacing: 5rpx; 140 | color: #fbfbfb; 141 | } 142 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.js: -------------------------------------------------------------------------------- 1 | var util = require('../../utils/util.js'); 2 | var convertDate = require('../../utils/convertDate.js'); 3 | Page({ 4 | 5 | /** 6 | * 页面的初始数据 7 | */ 8 | data: { 9 | hideAddPopup: true, 10 | // 存放用户创建的卡片对应的记录id 11 | userCardsset: [], 12 | // 云端的记录此id 13 | userCardsset_id: '', 14 | // 存放所有用户创建的卡片(直接从云端获取的) 15 | cardsSet: [], 16 | // 存放处理后的用户卡片 17 | cardsPed: [], 18 | // 第一次进入该页面 19 | firstIn: true 20 | }, 21 | 22 | /** 23 | * 生命周期函数--监听页面加载 24 | */ 25 | onLoad: function(options) { 26 | var that = this; 27 | var cardsSet = wx.getStorageSync('cardsSet'); 28 | that.getdate(); 29 | if (cardsSet == '') { 30 | // 获取当前日期 31 | that.getCardsSet(); 32 | if (wx.getStorageSync('userCardsset_id') == '') { 33 | // 获取用户卡片集_id 34 | that.getUserscardsSet(); 35 | } 36 | } else { 37 | that.getCardsProgress(cardsSet); 38 | that.setData({ 39 | cardsSet: cardsSet 40 | // cardsPed: wx.getStorageSync('cardsPed') 41 | }) 42 | } 43 | 44 | }, 45 | 46 | /** 47 | * 生命周期函数--监听页面初次渲染完成 48 | */ 49 | onReady: function() { 50 | var that = this; 51 | that.aniAct(); 52 | // 接收组件传递数据 53 | that.singList = that.selectComponent("#navComp"); 54 | // console.log(that.singList) 55 | 56 | }, 57 | 58 | /** 59 | * 生命周期函数--监听页面显示 60 | */ 61 | onShow: function() { 62 | var that = this; 63 | if (!that.data.firstIn) { 64 | console.log("第一次显示") 65 | if (wx.getStorageSync('isNew') == 1) { 66 | that.getCardsSet(); 67 | } 68 | console.log("执行了查询卡片操作") 69 | that.getCardsProgress(wx.getStorageSync('cardsSet')); 70 | } 71 | that.setData({ 72 | firstIn: false 73 | }) 74 | 75 | }, 76 | 77 | /** 78 | * 生命周期函数--监听页面隐藏 79 | */ 80 | onHide: function() { 81 | 82 | }, 83 | 84 | /** 85 | * 生命周期函数--监听页面卸载 86 | */ 87 | onUnload: function() { 88 | 89 | }, 90 | 91 | /** 92 | * 页面相关事件处理函数--监听用户下拉动作 93 | */ 94 | onPullDownRefresh: function() { 95 | 96 | }, 97 | 98 | /** 99 | * 页面上拉触底事件的处理函数 100 | */ 101 | onReachBottom: function() { 102 | 103 | }, 104 | 105 | /** 106 | * 用户点击右上角分享 107 | */ 108 | onShareAppMessage: function() { 109 | 110 | }, 111 | switchAddPopup: function(e) { 112 | var that = this; 113 | // console.log(e); 114 | var temp = e.detail; 115 | if (!temp) { 116 | that.showAddPopup(); 117 | } else { 118 | that.closeAddPopup(); 119 | } 120 | }, 121 | // 关闭Add弹出框 122 | closeAddPopup: function() { 123 | var that = this; 124 | // 运行组件navbar中的方法 125 | that.singList.createButtonHandle(); 126 | // Add菜单下滑动画 127 | that.aniPopup.bottom("-380rpx").step(); 128 | // 遮罩层动画 129 | that.aniMask.backgroundColor("#FFF").opacity(0).step(); 130 | that.setData({ 131 | aniPopupA: that.aniPopup.export(), 132 | aniMaskA: that.aniMask.export(), 133 | }) 134 | setTimeout(function() { 135 | that.setData({ 136 | hideAddPopup: !that.data.hideAddPopup 137 | }) 138 | }, 1000) 139 | 140 | }, 141 | // 显示Add弹出框 142 | showAddPopup() { 143 | // console.log(e) //可以从e中得到传过来信息 144 | var that = this; 145 | that.setData({ 146 | hideAddPopup: !that.data.hideAddPopup 147 | }); 148 | // Add菜单上滑动画 149 | that.aniPopup.bottom("0rpx").step(); 150 | // 遮罩层动画 151 | that.aniMask.backgroundColor("#333").opacity(0.5).step(); 152 | that.setData({ 153 | aniPopupA: that.aniPopup.export(), 154 | aniMaskA: that.aniMask.export(), 155 | }); 156 | }, 157 | /* 158 | 跳转到创建卡片页面 159 | */ 160 | oncreate: function(e) { 161 | var that = this; 162 | that.closeAddPopup(); 163 | var cardstype = e.target.dataset.type; 164 | // console.log(cardstype) 165 | wx.navigateTo({ 166 | url: '/pages/create/create?cardstype=' + cardstype, 167 | }) 168 | }, 169 | // 创建动画总函数 170 | aniAct: function() { 171 | var that = this; 172 | // 定义遮罩层动画 173 | that.aniMask = wx.createAnimation({ 174 | duration: 1000, 175 | timingFunction: 'ease' 176 | }); 177 | // 定义Add菜单上滑动画 178 | that.aniPopup = wx.createAnimation({ 179 | duration: 500, 180 | timingFunction: 'ease', 181 | }); 182 | }, 183 | // 查询数据库中用户所创建的时间卡片 184 | // 查询数据库中的记录 185 | getUserscardsSet: function() { 186 | var that = this; 187 | console.log('执行了Query'); 188 | const db = wx.cloud.database() 189 | // 查询当前用户所有的 users 190 | db.collection('user-cards-set').where({ 191 | _openid: wx.getStorageSync('user-openid') 192 | }).get({ 193 | success: res => { 194 | console.log(res); 195 | // 如果记录为空的的话就保存查询到的记录集id 196 | 197 | wx.setStorageSync('userCardsset_id', res.data[0]._id); 198 | var userCard = res.data[0]; 199 | wx.setStorageSync('userCardsset', userCard.cardsSet); 200 | that.setData({ 201 | userCardsset: userCard.cardsSet 202 | }) 203 | }, 204 | fail: err => { 205 | wx.showToast({ 206 | icon: 'none', 207 | title: '查询记录失败' 208 | }) 209 | console.error('[数据库] [查询记录] 失败:', err) 210 | } 211 | }) 212 | }, 213 | // 获取卡片集 214 | getCardsSet: function() { 215 | var cardsSet = []; 216 | var that = this; 217 | // 获取云端创建的所有卡片(默认:按创建时间排序) 218 | const db = wx.cloud.database() 219 | // 查询当前用户所有的 cards 220 | db.collection('user-cards').where({ 221 | _openid: wx.getStorageSync('user-openid') 222 | }).get({ 223 | success: res => { 224 | console.log("113") 225 | console.log(res) 226 | var cardsSet = res.data; 227 | that.getCardsProgress(cardsSet); 228 | wx.setStorageSync('cardsSet', cardsSet); 229 | // 更新标记设置为0 230 | wx.setStorageSync('isNew', 0); 231 | that.setData({ 232 | cardsSet: cardsSet 233 | }) 234 | }, 235 | fail: err => { 236 | wx.showToast({ 237 | icon: 'none', 238 | title: '查询记录失败' 239 | }) 240 | console.error('[数据库] [查询记录] 失败:', err) 241 | } 242 | }) 243 | }, 244 | // 获取当前日期 245 | getdate: function() { 246 | var that = this; 247 | var d = new Date(); 248 | var nowdate = convertDate.dateformat("yyyy-MM-dd", d); 249 | that.setData({ 250 | nowdate: nowdate 251 | }) 252 | }, 253 | // 处理所得到了卡片 254 | getCardsProgress: function(cardsSet) { 255 | console.log("执行了卡片处理函数"); 256 | var that = this; 257 | var cardsSet = cardsSet; 258 | var userCardsset = wx.getStorageSync('userCardsset'); 259 | var cardsPed = []; 260 | for (var i in userCardsset) { 261 | for (var j in cardsSet) { 262 | /* 263 | 用户可定制顺序 264 | */ 265 | // 用户创建的卡片对应的记录id与所有记录的id对应的存放到数组中 266 | if (userCardsset[i] == cardsSet[j]._id) { 267 | var carditem = cardsSet[j].carditem; 268 | var passeddays = util.getdays(carditem.starttime, that.data.nowdate); 269 | var alldays = util.getdays(carditem.starttime, carditem.endtime); 270 | var percent = ((passeddays / alldays) * 100).toFixed(1); 271 | var finished = false; 272 | // 使进度条的宽度不会超出 273 | if(percent > 100.0){ 274 | percent = 100.0; 275 | finished = true; 276 | } 277 | var obj = { 278 | cardid: cardsSet[j]._id, 279 | cardtype: carditem.cardstype, 280 | cardcolor: carditem.color, 281 | cardendtime: carditem.endtime, 282 | cardrolename: carditem.rolename, 283 | cardstarttime: carditem.starttime, 284 | cardtitle: carditem.title, 285 | percent: percent, 286 | finished: finished 287 | } 288 | cardsPed.push(obj); 289 | } 290 | } 291 | } 292 | wx.setStorageSync('cardsPed', cardsPed) 293 | that.setData({ 294 | cardsPed: cardsPed 295 | }) 296 | } 297 | }) -------------------------------------------------------------------------------- /miniprogram/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "navbar": "../../components/navbar/navbar", 4 | "carditem": "../../components/carditem/carditem" 5 | } 6 | } -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /* 页面内容 */ 2 | .container { 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | .card-items { 7 | display: flex; 8 | flex-direction: column; 9 | position: relative; 10 | width: 92%; 11 | height: 300rpx; 12 | padding: 14rpx; 13 | margin: 18rpx auto; 14 | border-radius: 20rpx; 15 | background-color: #e63c56; 16 | box-shadow: 2px 2px 3px #999; 17 | } 18 | 19 | /* 事件标题、时间及操作 */ 20 | 21 | .card-title-createtime-handle { 22 | display: flex; 23 | flex-direction: row; 24 | justify-content: space-between; 25 | width: 100%; 26 | } 27 | 28 | .card-title-createtime { 29 | display: flex; 30 | flex-direction: column; 31 | } 32 | 33 | .card-title { 34 | color: #fff; 35 | line-height: 50rpx; 36 | font-size: 48rpx; 37 | font-weight: bolder; 38 | font-family: "heiti"; 39 | } 40 | 41 | .card-createtime { 42 | font-size: 24rpx; 43 | line-height: 40rpx; 44 | color: #eee8aa; 45 | } 46 | 47 | .card-handle image { 48 | width: 80rpx; 49 | height: 80rpx; 50 | } 51 | 52 | /* 进度条 */ 53 | 54 | .card-man-progress { 55 | position: relative; 56 | width: 90%; 57 | margin: 18rpx auto 0; 58 | } 59 | 60 | .card-man image { 61 | width: 90rpx; 62 | margin-left: 80rpx; 63 | } 64 | 65 | .progress-con { 66 | position: relative; 67 | height: 18rpx; 68 | } 69 | 70 | .progress { 71 | position: absolute; 72 | top: 0; 73 | width: 20%; 74 | height: 18rpx; 75 | background-color: #fffbf3; 76 | border-radius: 10rpx; 77 | z-index: 4; 78 | } 79 | 80 | .progress-bott { 81 | position: absolute; 82 | top: 0; 83 | width: 100%; 84 | height: 18rpx; 85 | background-color: #505050; 86 | opacity: 0.5; 87 | border-radius: 10rpx; 88 | z-index: 3; 89 | } 90 | 91 | /* 结束时间样式与起始日相同 */ 92 | 93 | .card-endtime { 94 | position: absolute; 95 | bottom: 40rpx; 96 | right: 10rpx; 97 | font-size: 24rpx; 98 | line-height: 40rpx; 99 | color: #eee8aa; 100 | text-align: right; 101 | } 102 | 103 | /* 标签 */ 104 | 105 | .card-tag { 106 | display: flex; 107 | flex-direction: row; 108 | position: absolute; 109 | bottom: 10rpx; 110 | right: 5rpx; 111 | height: 36rpx; 112 | /* background- color: red; */ 113 | } 114 | 115 | .tag-item { 116 | padding: 0 4rpx; 117 | font-size: 30rpx; 118 | color: #79a2a8; 119 | font-weight: bolder; 120 | line-height: 36rpx; 121 | background-color: #fffbf3; 122 | border-radius: 6rpx; 123 | margin: 0 8rpx; 124 | right: 0; 125 | } 126 | 127 | /* 弹出的添加操作框 */ 128 | 129 | .show-popup { 130 | position: fixed; 131 | top: 0; 132 | left: 0; 133 | width: 100%; 134 | height: 100%; 135 | z-index: 96; 136 | } 137 | 138 | .popup-mask { 139 | position: fixed; 140 | top: 0; 141 | left: 0; 142 | width: 100%; 143 | height: 100%; 144 | /*透明色 */ 145 | /* background-color: rgba(0, 0, 0, 0.5); */ 146 | opacity: 0; 147 | z-index: 97; 148 | } 149 | 150 | .popup-contents { 151 | position: fixed; 152 | display: flex; 153 | flex-direction: column; 154 | left: 0; 155 | bottom: -380rpx; 156 | width: 100%; 157 | height: 380rpx; 158 | background-color: #fff; 159 | z-index: 98; 160 | } 161 | 162 | .popup-cancel { 163 | margin-top: 30rpx; 164 | } 165 | 166 | .popup-cancel .txt { 167 | float: right; 168 | margin-right: 40rpx; 169 | color: #666; 170 | } 171 | 172 | .popup-title { 173 | margin: 0 auto; 174 | font-size: 45rpx; 175 | font-weight: bolder; 176 | color: #333; 177 | border-bottom: 2rpx solid #666; 178 | } 179 | 180 | .button-container { 181 | margin: 70rpx auto 0 auto; 182 | display: flex; 183 | flex-direction: row; 184 | justify-content: space-between; 185 | width: 90%; 186 | } 187 | 188 | .button-img { 189 | width: 300rpx; 190 | height: 100rpx; 191 | background-color: #fff; 192 | border-radius: 15rpx; 193 | box-shadow: 4rpx 4rpx 6rpx #666; 194 | } 195 | -------------------------------------------------------------------------------- /miniprogram/pages/login/login.js: -------------------------------------------------------------------------------- 1 | // pages/login/login.js 2 | const app = getApp(); 3 | var convertDate = require('../../utils/convertDate.js'); 4 | Page({ 5 | 6 | /** 7 | * 页面的初始数据 8 | */ 9 | data: { 10 | logged: false, 11 | loginStatus: 0, 12 | userInfo: {}, 13 | cardsSet: [] 14 | }, 15 | 16 | /** 17 | * 生命周期函数--监听页面加载 18 | */ 19 | onLoad: function(options) { 20 | var that = this; 21 | // 查看本地存储中的user-openid是否存在用户的openid 22 | var openid = wx.getStorageSync('user-openid'); 23 | if (openid != '') { 24 | that.onQuery(); 25 | } 26 | // 获取当前系统的宽高,并保存 27 | var a = wx.getSystemInfoSync(); 28 | that.setData({ 29 | screenHeight: a.screenHeight, 30 | screenWidth: a.screenWidth 31 | }) 32 | // 按类获取元素的宽高 33 | var obj = wx.createSelectorQuery(); 34 | obj.selectAll('.logo').boundingClientRect(function(rect) { 35 | that.setData({ 36 | logoWidth: rect[0].width, 37 | logoHeight: rect[0].height 38 | }) 39 | }) 40 | obj.exec(); 41 | // 获取本地卡片数组存储 42 | var cardsSet = wx.getStorageSync('cardsSet'); 43 | if (cardsSet != '') { 44 | that.setData({ 45 | cardsSet: cardsSet 46 | }) 47 | } 48 | }, 49 | 50 | /** 51 | * 生命周期函数--监听页面初次渲染完成 52 | */ 53 | onReady: function() { 54 | 55 | }, 56 | 57 | /** 58 | * 生命周期函数--监听页面显示 59 | */ 60 | onShow: function() { 61 | 62 | }, 63 | 64 | /** 65 | * 生命周期函数--监听页面隐藏 66 | */ 67 | onHide: function() { 68 | 69 | }, 70 | 71 | /** 72 | * 生命周期函数--监听页面卸载 73 | */ 74 | onUnload: function() { 75 | 76 | }, 77 | 78 | /** 79 | * 页面相关事件处理函数--监听用户下拉动作 80 | */ 81 | onPullDownRefresh: function() { 82 | 83 | }, 84 | 85 | /** 86 | * 页面上拉触底事件的处理函数 87 | */ 88 | onReachBottom: function() { 89 | 90 | }, 91 | 92 | /** 93 | * 用户点击右上角分享 94 | */ 95 | onShareAppMessage: function() { 96 | 97 | }, 98 | // 点击登录按钮要做的事情 99 | // 获取用户信息,并存到当前的Data中 100 | onGotUserInfo: function (e) { 101 | var that = this; 102 | // 设置按钮的样式 103 | that.setLoading(); 104 | // 获取用户的openid 105 | that.onGetOpenid(); 106 | console.log(e) 107 | if (!that.data.logged && e.detail.userInfo) { 108 | that.setData({ 109 | logged: true, 110 | userInfo: e.detail.userInfo 111 | }); 112 | // 在插入时检查数据库中是否已经存在 113 | setTimeout(function () { 114 | that.onQuery(); 115 | }, 1000) 116 | } 117 | }, 118 | /* 119 | 120 | 登录状态:0:未登录/登录失败,1:登录成功,2:登录中 121 | */ 122 | // 按钮出显示加载图标 123 | setLoading: function(e) { 124 | var that = this; 125 | var loginStatus = that.data.loginStatus; 126 | if (loginStatus == 0) { 127 | that.setData({ 128 | loading: !this.data.loading, 129 | loginStatus: 2 130 | }) 131 | } 132 | }, 133 | // 获取用户的openid 134 | onGetOpenid: function() { 135 | var that = this; 136 | // 调用云函数 137 | wx.cloud.callFunction({ 138 | name: 'login', 139 | data: {}, 140 | success: res => { 141 | console.log('[云函数] [login] user openid: ', res.result.openid) 142 | app.globalData.openid = res.result.openid; 143 | // 将openid存储到本地以便使用 144 | wx.setStorageSync("user-openid", res.result.openid) 145 | }, 146 | fail: err => { 147 | console.error('[云函数] [login] 调用失败', err) 148 | that.setData({ 149 | loginStatus: 0 150 | }) 151 | wx.showToast({ 152 | title: '登录失败', 153 | }) 154 | 155 | } 156 | }) 157 | }, 158 | 159 | // 登录成功 160 | loginSuccess: function() { 161 | var that = this; 162 | that.setData({ 163 | loginStatus: 1 164 | }); 165 | // 显示登录成功延迟0.5秒跳转页面 166 | setTimeout(function() { 167 | wx.redirectTo({ 168 | url: '../index/index', 169 | }) 170 | }, 200); 171 | }, 172 | // 向数据库中添加用户数据 173 | onAdd: function() { 174 | const db = wx.cloud.database() 175 | db.collection('users').add({ 176 | data: { 177 | userInfo: this.data.userInfo 178 | }, 179 | success: res => { 180 | // 在返回结果中会包含新创建的记录的 _id 181 | console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id) 182 | }, 183 | fail: err => { 184 | wx.showToast({ 185 | icon: 'none', 186 | title: '登录失败,请重新尝试' 187 | }) 188 | console.error('[数据库] [新增记录] 失败:', err) 189 | } 190 | }) 191 | }, 192 | // 查询数据库中的记录 193 | onQuery: function() { 194 | var that = this; 195 | console.log('执行了Query'); 196 | const db = wx.cloud.database() 197 | // 查询当前用户所有的 users 198 | db.collection('users').where({ 199 | _openid: wx.getStorageSync('user-openid') 200 | }).get({ 201 | success: res => { 202 | if (res.data.length != 0) { 203 | this.loginSuccess(); 204 | this.setData({ 205 | loginStatus: 1 206 | }) 207 | } else { 208 | // 查询结果中没有存储用户的信息,将信息存储到云端 209 | if (that.data.loginStatus != 1 && wx.getStorageSync('user-openid') != '') { 210 | console.log("运行存储"); 211 | // 添加用户信息、初始化卡片到数据库中 212 | this.onAdd(); 213 | this.createFirst(); 214 | } 215 | } 216 | 217 | }, 218 | fail: err => { 219 | wx.showToast({ 220 | icon: 'none', 221 | title: '查询记录失败' 222 | }) 223 | console.error('[数据库] [查询记录] 失败:', err) 224 | } 225 | }) 226 | }, 227 | // 获取当前日期 228 | getdate: function() { 229 | var that = this; 230 | var d = new Date(); 231 | var nowdate = convertDate.dateformat("yyyy-MM-dd", d); 232 | var year = convertDate.dateformat("yyyy", d); 233 | that.setData({ 234 | startdate: year + '-01-01', 235 | enddate: year + '-12-31', 236 | nowdate: nowdate 237 | }) 238 | }, 239 | // 创建一个今年已经度过时间卡片 240 | createFirst: function() { 241 | var that = this; 242 | that.getdate(); 243 | const db = wx.cloud.database(); 244 | db.collection('user-cards').add({ 245 | data: { 246 | carditem: { 247 | title: '距2019年结束', 248 | starttime: that.data.startdate, 249 | endtime: that.data.enddate, 250 | color: '#e63c56', 251 | cardstype: 'countback', 252 | rolename: 'Superman' 253 | } 254 | }, 255 | success: res => { 256 | // 在返回结果中会包含新创建的记录的 _id 257 | var recordid = res._id; 258 | var cardsSet = that.data.cardsSet; 259 | cardsSet.push(recordid); 260 | db.collection('user-cards-set').add({ 261 | data: { 262 | cardsSet: cardsSet 263 | }, 264 | success: res => { 265 | // 在返回结果中会包含新创建的记录的 _id 266 | console.log('卡片集添加数据成功: ', res._id) 267 | // 将存放记录id存入到本地 268 | wx.setStorageSync('userCardsset_id', res._id) 269 | that.loginSuccess(); 270 | }, 271 | fail: err => { 272 | console.error('卡片集添加数据失败:', err) 273 | } 274 | }) 275 | console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id) 276 | }, 277 | fail: err => { 278 | wx.showToast({ 279 | icon: 'none', 280 | title: '登录失败,请重新尝试' 281 | }) 282 | console.error('[数据库] [新增记录] 失败:', err) 283 | } 284 | }) 285 | }, 286 | 287 | }) -------------------------------------------------------------------------------- /miniprogram/pages/login/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/login/login.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /miniprogram/pages/login/login.wxss: -------------------------------------------------------------------------------- 1 | /* pages/login/login.wxss */ 2 | 3 | .container { 4 | position: relative; 5 | margin: 0; 6 | } 7 | 8 | .logo { 9 | position: absolute; 10 | top: 24%; 11 | font-size: 80rpx; 12 | text-indent : 30rpx; 13 | letter-spacing: 30rpx; 14 | font-weight: lighter; 15 | text-align: center; 16 | 17 | } 18 | 19 | .login-btn-container { 20 | position: absolute; 21 | bottom: 100rpx; 22 | } 23 | 24 | .login-btn { 25 | margin: 0 auto; 26 | } 27 | -------------------------------------------------------------------------------- /miniprogram/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /miniprogram/style/guide.wxss: -------------------------------------------------------------------------------- 1 | page { 2 | background: #f6f6f6; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: flex-start; 6 | } 7 | 8 | .list { 9 | margin-top: 40rpx; 10 | height: auto; 11 | width: 100%; 12 | background: #fff; 13 | padding: 0 40rpx; 14 | border: 1px solid rgba(0, 0, 0, 0.1); 15 | border-left: none; 16 | border-right: none; 17 | transition: all 300ms ease; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: stretch; 21 | box-sizing: border-box; 22 | } 23 | 24 | .list-item { 25 | width: 100%; 26 | padding: 0; 27 | line-height: 104rpx; 28 | font-size: 34rpx; 29 | color: #007aff; 30 | border-top: 1px solid rgba(0, 0, 0, 0.1); 31 | display: flex; 32 | flex-direction: row; 33 | align-content: center; 34 | justify-content: space-between; 35 | box-sizing: border-box; 36 | } 37 | 38 | .list-item:first-child { 39 | border-top: none; 40 | } 41 | 42 | .list-item image { 43 | max-width: 100%; 44 | max-height: 20vh; 45 | margin: 20rpx 0; 46 | } 47 | 48 | .request-text { 49 | color: #222; 50 | padding: 20rpx 0; 51 | font-size: 24rpx; 52 | line-height: 36rpx; 53 | word-break: break-all; 54 | } 55 | 56 | .guide { 57 | width: 100%; 58 | padding: 40rpx; 59 | box-sizing: border-box; 60 | display: flex; 61 | flex-direction: column; 62 | } 63 | 64 | .guide .headline { 65 | font-size: 34rpx; 66 | font-weight: bold; 67 | color: #555; 68 | line-height: 40rpx; 69 | } 70 | 71 | .guide .p { 72 | margin-top: 20rpx; 73 | font-size: 28rpx; 74 | line-height: 36rpx; 75 | color: #666; 76 | } 77 | 78 | .guide .code { 79 | margin-top: 20rpx; 80 | font-size: 28rpx; 81 | line-height: 36rpx; 82 | color: #666; 83 | background: white; 84 | white-space: pre; 85 | } 86 | 87 | .guide .code-dark { 88 | margin-top: 20rpx; 89 | background: rgba(0, 0, 0, 0.8); 90 | padding: 20rpx; 91 | font-size: 28rpx; 92 | line-height: 36rpx; 93 | border-radius: 6rpx; 94 | color: #fff; 95 | white-space: pre 96 | } 97 | 98 | .guide image { 99 | max-width: 100%; 100 | } 101 | 102 | .guide .image1 { 103 | margin-top: 20rpx; 104 | max-width: 100%; 105 | width: 356px; 106 | height: 47px; 107 | } 108 | 109 | .guide .image2 { 110 | margin-top: 20rpx; 111 | width: 264px; 112 | height: 100px; 113 | } 114 | 115 | .guide .flat-image { 116 | height: 100px; 117 | } 118 | 119 | .guide .code-image { 120 | max-width: 100%; 121 | } 122 | 123 | .guide .copyBtn { 124 | width: 180rpx; 125 | font-size: 20rpx; 126 | margin-top: 16rpx; 127 | margin-left: 0; 128 | } 129 | 130 | .guide .nav { 131 | margin-top: 50rpx; 132 | display: flex; 133 | flex-direction: row; 134 | align-content: space-between; 135 | } 136 | 137 | .guide .nav .prev { 138 | margin-left: unset; 139 | } 140 | 141 | .guide .nav .next { 142 | margin-right: unset; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /miniprogram/utils/convertDate.js: -------------------------------------------------------------------------------- 1 | // 对Date的扩展,将 Date 转化为指定格式的String 2 | // 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, 3 | // 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) 4 | // 例子: 5 | // (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 6 | // (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 7 | var dateformat = function dateFtt(fmt, date) { //author: meizz 8 | var o = { 9 | "M+": date.getMonth() + 1, //月份 10 | "d+": date.getDate(), //日 11 | "h+": date.getHours(), //小时 12 | "m+": date.getMinutes(), //分 13 | "s+": date.getSeconds(), //秒 14 | "q+": Math.floor((date.getMonth() + 3) / 3), //季度 15 | "S": date.getMilliseconds() //毫秒 16 | }; 17 | if (/(y+)/.test(fmt)) 18 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); 19 | for (var k in o) 20 | if (new RegExp("(" + k + ")").test(fmt)) 21 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 22 | return fmt; 23 | } 24 | 25 | // 要引用这个文件的函数或者变量,除了在要引用的的js文件中模块化之外(var utils=require('js地址')), 26 | // 在被引用的的js中要通过 module.exports={a:a}作为面向对象的变量输出函数如下: 27 | module.exports = { 28 | dateformat: dateformat//要引用的函数 xx:xx 29 | } -------------------------------------------------------------------------------- /miniprogram/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 | return [year, month, day].map(formatNumber).join('') 11 | } 12 | 13 | function formatNumber(n) { 14 | n = n.toString() 15 | return n[1] ? n : '0' + n 16 | } 17 | 18 | function convertToStarsArray(stars) { 19 | var num = stars.toString().substring(0, 1); 20 | var array = []; 21 | for (var i = 1; i <= 5; i++) { 22 | if (i <= num) { 23 | array.push(1); 24 | } else { 25 | array.push(0); 26 | } 27 | } 28 | return array; 29 | } 30 | 31 | function http(url, callBack) { 32 | wx.request({ 33 | url: url, 34 | method: 'GET', 35 | header: { 36 | "Content-Type": "json" 37 | }, 38 | success: function(res) { 39 | callBack(res.data); 40 | }, 41 | fail: function(error) { 42 | console.log(error) 43 | } 44 | }) 45 | } 46 | 47 | function convertToCastString(casts) { 48 | var castsjoin = ""; 49 | for (var idx in casts) { 50 | castsjoin = castsjoin + casts[idx].name + " / "; 51 | } 52 | return castsjoin.substring(0, castsjoin.length - 2); 53 | } 54 | 55 | function convertToCastInfos(casts) { 56 | var castsArray = [] 57 | for (var idx in casts) { 58 | var cast = { 59 | img: casts[idx].avatars ? casts[idx].avatars.large : "", 60 | name: casts[idx].name 61 | } 62 | castsArray.push(cast); 63 | } 64 | return castsArray; 65 | } 66 | 67 | // 两日期相减得到相差天数 68 | function getdays(day1, day2) { 69 | var that = this; 70 | var d1 = day1; 71 | var d2 = day2; 72 | d1 = d1.replace(/\-/g, "/"); 73 | d2 = d2.replace(/\-/g, "/"); 74 | var date1 = new Date(d1); 75 | var date2 = new Date(d2); 76 | var days = Math.ceil((date2 - date1) / (24 * 60 * 60 * 1000)); 77 | return days; 78 | } 79 | 80 | 81 | 82 | 83 | module.exports = { 84 | formatTime: formatTime, 85 | convertToStarsArray: convertToStarsArray, 86 | http: http, 87 | convertToCastString: convertToCastString, 88 | convertToCastInfos: convertToCastInfos, 89 | getdays: getdays 90 | } -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "miniprogram/", 3 | "cloudfunctionRoot": "cloudfunctions/", 4 | "setting": { 5 | "urlCheck": true, 6 | "es6": true, 7 | "postcss": true, 8 | "minified": true, 9 | "newFeature": true 10 | }, 11 | "appid": "输入自己的", 12 | "projectname": "TimeCard", 13 | "libVersion": "2.2.5", 14 | "simulatorType": "wechat", 15 | "simulatorPluginLibVersion": {}, 16 | "condition": { 17 | "search": { 18 | "current": -1, 19 | "list": [] 20 | }, 21 | "conversation": { 22 | "current": -1, 23 | "list": [] 24 | }, 25 | "plugin": { 26 | "current": -1, 27 | "list": [] 28 | }, 29 | "game": { 30 | "list": [] 31 | }, 32 | "miniprogram": { 33 | "current": 0, 34 | "list": [ 35 | { 36 | "id": -1, 37 | "name": "db guide", 38 | "pathName": "pages/databaseGuide/databaseGuide" 39 | } 40 | ] 41 | } 42 | } 43 | } --------------------------------------------------------------------------------