{"id":19614893,"url":"https://github.com/leancloud/flutterleavedemo","last_synced_at":"2025-04-28T02:30:53.566Z","repository":{"id":43404406,"uuid":"264878734","full_name":"leancloud/FlutterLeaveDemo","owner":"leancloud","description":"Flutter 请假、写周报应用","archived":false,"fork":false,"pushed_at":"2022-03-03T03:59:50.000Z","size":541,"stargazers_count":26,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-13T06:30:06.768Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://juejin.im/post/6845166890873012238","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leancloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-18T08:38:00.000Z","updated_at":"2023-04-05T05:09:32.000Z","dependencies_parsed_at":"2022-09-07T07:41:19.119Z","dependency_job_id":null,"html_url":"https://github.com/leancloud/FlutterLeaveDemo","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2FFlutterLeaveDemo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2FFlutterLeaveDemo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2FFlutterLeaveDemo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2FFlutterLeaveDemo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leancloud","download_url":"https://codeload.github.com/leancloud/FlutterLeaveDemo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224092041,"owners_count":17254152,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T10:54:24.688Z","updated_at":"2024-11-11T10:54:25.737Z","avatar_url":"https://github.com/leancloud.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n## APP 效果预览\n\n[App Store下载链接](https://apps.apple.com/us/app/id1518553843)，或者 App Store 搜索 `LeanCN` 下载。\n\n\n| 请假  | 写周报 | 联系人|\n|:-------------:|:---------------:|:-------------:|\n|![flutter-acn-overview](https://user-images.githubusercontent.com/11917002/156492081-1737d47a-41d1-4778-a9ec-7e6634189982.png)   | ![flutter-acn-overview2](https://user-images.githubusercontent.com/11917002/156492119-2c10d857-5f58-4171-b631-3f3060e3e88d.png) |     ![flutter-acn-overview3](https://user-images.githubusercontent.com/11917002/156492149-6344e63b-1758-4751-99f1-b8ee7e1b986f.png) |\n\n\n## APP 简介\n\n用 Flutter 快速实现请假与写周报 APP。\n\n\n公司使用的请假及写周报系统一直都是网页版的，之前我们也有想过出一个移动端版本，但因为一些原因没有付诸行动。刚好最近 LeanCloud 新发布了 Flutter SDK，就决定用 Flutter 来开发这款 APP。\n\n之所以选择 Flutter，主要原因是一份代码可以同时满足 iOS 和 Android 两大平台，这样所有同事都可以享受到这款 APP 带来的便利。\n\nAPP 的后端数据全部存放在 LeanCloud，不用担心后端系统的开发维护，实现起来也很简单。\n\n## 开发环境搭建\n\nFlutter 安装和环境搭建直接查看：[ Flutter 文档](https://flutter.dev/docs/get-started/install)。\n编辑器可以选择 Android Studio、Visual Studio Code 或者 Emacs，编辑器就根据个人喜好和开发习惯选择了。\n\nFlutter 开发环境配置好以后，再来创建 LeanCloud 应用。\n\n- 首先登录 [LeanCloud 控制台](https://leancloud.cn/dashboard/login.html#/signin)，创建一个新应用；\n- 在控制台 \u003e 应用 \u003e 设置 \u003e域名绑定页面绑定 **API 访问域名**。暂时没有域名可以略过这一步，LeanCloud 也提供了短期有效的免费体验域名；或者注册[ LeanCloud 国际版](https://console.leancloud.app/login.html#/signin)，国际版不要求绑定域名。\n\n在控制台 \u003e 应用 \u003e 设置 \u003e 应用 Keys 页面记录 AppID、AppKey 与服务器地址备用，这里的服务器地址就是 REST API 服务器地址。如果未绑定域名，控制台相同的位置可以获取到免费的共享域名。\n\n## 使用到的第三方库\n\n在 pubspec.yaml 中，将 LeanCloud Flutter SDK：leancloud_storage 添加到依赖项列表:\n\n```\ndependencies:\n  flutter:\n    sdk: flutter\n  cupertino_icons: ^0.1.2\n  leancloud_storage: ^0.7.7\n  http: ^0.13.4\n  date_format: ^2.0.4\n  flutter_localizations:\n    sdk: flutter\n  fluttertoast: ^8.0.8\n  shared_preferences: ^2.0.11\n  flutter_markdown: ^0.6.9\n  url_launcher: ^6.0.17\n  get_it: ^7.2.0\n```\n\n其他第三方插件的说明：\n\n\u003e date_format: 请假页面用到的日期相关格式化插件\n\u003e\n\u003e flutter_localizations：用于设置时间选择器的中文显示\n\u003e\n\u003e fluttertoast：类似 Android 中的 Toast 小插件\n\u003e\n\u003e shared_preferences：本地数据存储\n\u003e\n\u003e flutter_markdown：展示周报内容时支持 markdown 格式\n\n## APP 初始化设置\n\n#### 初始化 SDK\n\n执行下面的代码连接到在 LeanCloud 创建好的应用。\n导入如下包：\n\n```\nimport 'package:leancloud_storage/leancloud.dart';\n```\n\n初始化配置代码：\n\n```\nFuture initLeanCloud() async {\n  LeanCloud.initialize(\n      'AppID', 'AppKey',//AppID 与 AppKey 在控制台设置 \u003e 应用 Keys 页面获取\n      server: 'https://e36trlaa.lc-cn-n1-shared.com',//这里填控制台绑定的域名或共享 API 域名\n      queryCache: new LCQueryCache());\n}\n```\n\n#### 设计数据结构\n\n在 LeanCloud 控制台 \u003e 存储 \u003e 结构化数据中创建需要的 Class，并添加相关字段，比如请假表（Leave）中，需要有请假人姓名，请假时长，请假原因，开始请假日期等。\n\n客户端保存数据时，如果 Class 不存在，系统也会自动生成对应的 Class。\n\n\n![flutter-acn-class](https://user-images.githubusercontent.com/11917002/156491926-8f43df44-a48a-46bc-83d3-c8946b0e8411.png)\n\n\n\n## 登录与注册模块\n\nLeanCloud 提供了 LCUser 类来方便使用用户管理的功能，在控制台对应 _User 表。注册与登录选择了 **用户名+密码** 的方式。实现用户注册只需要执行以下代码，就会在 _User 表新增一条用户数据：\n\n```\nLCUser user = LCUser();\nuser.username = 'Tom';\nuser.password = 'cat!@#123';\nawait user.signUp();\n```\n\n用户登录也只需要传入用户名与密码：\n\n```\nLCUser user = await LCUser.login('Tom', 'cat!@#123');\n```\n\n在应用中如果想要获取当前登录用户，可以用：\n\n```\nLCUser currentUser = await LCUser.getCurrent();\n```\n\nLCUser 还支持手机号 + 验证码注册，更多登录注册方式可以查看 [LeanCloud 用户文档](https://leancloud.cn/docs/leanstorage_guide-flutter.html#hash885156)。\n\n## 请假模块的实现\n\n请假部分包含「提交一条请假记录」、「查询我的历史请假记录」与「查询今日请假同事」这三个部分。\n\n#### 提交一条请假记录\n\n保存一条数据到 LeanCloud 后台也很简单，一条数据可以看成一个 LCObject 对象，直接给 LCObject 对象赋值，save 成功以后可以在 Leave 表中看到新增了一行数据。\n\n```\n//创建 Class 并保存一条数据，Leave 表用来存放请假员工数据\nLCObject leave = LCObject('Leave');\nleave['startTime'] = startTime;//请假的开始时间(AM/PM)\nleave['endTime'] = endTime;//请假结束时间(AM/PM)\nLCUser user = await LCUser.getCurrent();\nleave['username'] = user.username;//请假员工用户名\nleave['startDate'] = startDate;//请假开始日期\nleave['type'] = leaveType;//请假类型，病假、年假或产假等\nleave['duration'] = duration;//请假时长\nleave['note'] = note;//请假原因\nleave['endDate'] = endDate;//请假结束日期\nawait leave.save();//保存到 LeanCloud 后台\n```\n\n#### 查询我的历史请假记录\n\n查询数据使用 LCQuery，query.find() 返回符合条件的 List：\n\n```\nLCUser user = await LCUser.getCurrent();\n//查询 Leave 表\nLCQuery\u003cLCObject\u003e query = LCQuery('Leave');\nquery.whereEqualTo('username', user.username);\n//按照创建时间排序\nquery.orderByDescending('createdAt');\n//leaves 是当前登录用户的全部请假记录\nList\u003cLCObject\u003e leaves = await query.find();\n```\n\n#### 查询今日请假同事\n\n```\nLCQuery\u003cLCObject\u003e query = LCQuery('Leave');\n//查找 DateTime.now() 在请假开始日期与结束日期之间的数据\nquery.whereGreaterThanOrEqualTo('endDate', DateTime.now());\nquery.whereLessThanOrEqualTo('startDate', DateTime.now());\nquery.orderByDescending('createdAt');\nList\u003cLCObject\u003e leaves = await query.find();\n```\n\n## 周报模块实现\n\n周报模块分两部分，保存一条周报和查询历史周报。展示周报支持 markdown 格式，所以在提交周报的时候，可以设置默认周报格式，用三个单引号 ''' 包起来的文本可以保留原文本格式展示：\n\n```\nString text = '''\n### This week\n* done1\n* done2\n\n### Next week\n* todo1\n* todo2\n    ''';\n```\n\n#### 保存周报\n\n为了区分提交周报的员工，创建一个 Pointer 类型字段指向 _User 表，字段名称是 user，保存数据时把当前用户赋值给 user 即可。（Leave 表同理也可以创建 Pointer 类型字段记录请假员工）。\n\n```\nLCUser user = await LCUser.getCurrent();\n//WeeklyPub 是存储周报数据的表\nLCObject obj = LCObject('WeeklyPub');\nobj['content'] = text;\n// user 字段是 pointer 类型，指向 _User 表\nobj['user'] = user;\nLCObject object = await obj.save();\n```\n\n#### 查询周报\n\n查询周报时，想要一并获取员工信息，可以使用 include，这样一次查询就可以查到这条周报的数据和员工（_User 表）的数据：\n\n```\nLCQuery\u003cLCObject\u003e query = LCQuery('WeeklyPub');\n// 查询结果同时包含用户信息\nquery.include('user');\nquery.orderByDescending('createdAt');\nquery.whereGreaterThanOrEqualTo(\n    'createdAt', DateTime.parse('2020-06-01 00:00:00Z'));\nList\u003cLCObject\u003e weekly = await query.find();\n```\n\n## 联系人列表\n\n联系人列表可以通过查询 _User 表获取，但这里会有一个问题。\n\n为了安全起见，LeanCloud 新创建的应用的 _User 表默认关闭了 find 权限。用户只能查询到自己在 _User 表中的数据，无法查询其他用户的数据。\n\n解决办法可以是单独创建一张表来保存这类数据，并开放这张表的 find 查询权限。或者可以在 [云引擎](https://leancloud.cn/docs/leanengine_overview.html) 里封装用户查询的方法，这样就无需开放 _User 表的 find 权限。\n\n本 APP 采用的办法是结合云引擎，设置了查询用户表的云函数，来保证数据安全。\n\n- 第一步参考 [在线编写云函数](https://leancloud.cn/docs/leanengine_cloudfunction_guide-node.html#hash-271574262) 文档，在 **LeanCloud 控制台 \u003e 云引擎 \u003e 部署 \u003e 在线编辑** 标签页创建云函数。例如我的云函数名是 queryUsers：\n\n```\nAV.Cloud.define('queryUsers', async function (request) {\n  if (request.currentUser) {\n    const userQuery = new AV.Query('_User');\n    userQuery.addDescending('createdAt');\n    return await userQuery.find();\n  } else {\n    throw new AV.Cloud.Error('用户未登录');\n  }\n})\n```\n\n- 然后点击「部署」按钮，部署到生产环境。\n\n部署成功后，在移动端可以直接调用云函数，Flutter 代码中可以这样调用云函数：\n\n```\nMap\u003cString, dynamic\u003e userMap = await LCCloud.run('queryUsers');\n//users 就是云函数返回的用户列表\nList\u003cdynamic\u003e users = userMap['result'];\n```\n\n## 参考文档\n\n1. [LeanCloud  - 数据存储开发指南 · Flutter](https://leancloud.cn/docs/leanstorage_guide-flutter.html#hash765832)\n2. [ Flutter 文档](https://flutter.dev/docs)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancloud%2Fflutterleavedemo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleancloud%2Fflutterleavedemo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancloud%2Fflutterleavedemo/lists"}