From 59c8e7bfeae02b07d5ead2891bb6e04742287976 Mon Sep 17 00:00:00 2001 From: JsonYe Date: Thu, 4 Nov 2021 19:26:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E7=AC=AC=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +- LICENSE | 14 +- README.md | 280 ++++++++++++++++++++++++++++-- lib/src/helper/where_builder.dart | 24 +-- pubspec.yaml | 6 +- test/no_safe_test.dart | 33 ++-- test/safe_test.dart | 1 + test/table/book.dart | 25 ++- 8 files changed, 341 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cc7d8..394eadc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,2 @@ -## 0.0.1 - -* TODO: Describe initial release. +## 0.1.0 +Bmob API interface encapsulation. diff --git a/LICENSE b/LICENSE index ba75c69..87acd1b 100644 --- a/LICENSE +++ b/LICENSE @@ -1 +1,13 @@ -TODO: Add your license here. +Copyright 2021 JsonYe + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index dd44b49..1624b6c 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,279 @@ +## mini_bmob +Bmob API 接口封装,包含加密传输,包含用户管理、ACL和角色、地理位置、条件查询、数据关联、数组、对象操作。 -## Features +> Bmob API interface encapsulation, including encrypted transmission, including user management, ACL and role, geographic location, conditional query, data association, array and object operation. -TODO: List what your package can do. Maybe include images, gifs, or videos. +## Usage -## Getting started +### 1. 初始化 -TODO: List prerequisites and provide or point to information on how to -start using the package. +- 非加密形式 -## Usage +> 可查看测试代码`no_safe_test.dart` + +```dart +BmobConfig.init( +appId, +apiKey, +masterKey: masterKey, +printError: (object, extra) =>L.e(object), +printResponse: (object, extra) =>L.d(object)); +``` + +- 加密形式 + +> 可查看测试代码`safe_test.dart` + +```dart +BmobConfig.initSafe( + secretKey, + safeToken: 'JsonYe-', // 安全码,详见官方文档 + masterKey: masterKey, //masterKey 不必填 + printError: ( + object, extra) => + L.e(object), // 访问API时,打印错误信息 + printResponse: ( + object, extra) => + L.d(object), +); // 访问API时,打印正常请求信息 +``` + +### 2. ACL + +> ACL 已经集成到基类中,若要启动,直接设置即可。可参考 `acl_test.dart` + +### 3 创建表对象 + +> 以`book.dart`为例介绍 + +#### 3.1 创建[表名]Table类,继承BmobTable + +```dart +class BookTable extends BmobTable { +} +``` + +#### 3.2 实现一个抽象方法 `getBmobTabName()`,返回bmob数据表中对应的表名称。 -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. +```dart +@override +String getBmobTabName() => "book"; +``` + +#### 3.3 添加自有字段 + +##### 3.3.1 基本数据类型 + +```dart +/// 数名 +String? name; +``` + +##### 3.3.2 Pointer数据类型 ```dart -const like = 'sample'; +/// 所属类别 +late BmobPointer category; ``` -## Additional information +##### 3.3.3 Relation 数据类型 -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +```dart +/// 作者 +late BmobRelation author; +``` + +##### 3.3.4 DateTime数据类型 + +```dart +/// 出版时间 +BmobDateTime? pubDate; +``` + +#### 3.4 重写方法,补全解析代码 + +##### 3.4.1 构造方法 + +> 基础数据类型,可直接初始化。对于自定义的数据类型,建议传入基础数据类型,在构造函数中进行初始化。 + +```dart +BookTable({ + this.name, + DateTime? pubDate, + List author = const [], + CategoryTable? category, +}) { + assert(category == null || category.objectId != null); + assert( + author.isEmpty || !author.any((element) => element.objectId == null)); + if (pubDate != null) { + this.pubDate = BmobDateTime(pubDate); + } + this.author = BmobRelation( + this, + AuthorTable(), + 'author', + (json) => AuthorTable().fromJson(json), + author, + ); + this.category = BmobPointer(category); +} +``` + +##### 3.4.2 fromJson 方法 +> 此方法也将用到对象查询中,json转对象,所以需要补全 + +```dart +@override +BookTable fromJson(Map json) { + super.fromJson(json); + name = json['name']; + if (json.containsKey('pubdate')) { + pubDate = BmobDateTime.fromJson(json['pubdate']); + } + if (category.subSet == null) { + category.subSet = CategoryTable() + ..fromJson(json['category']); + } else { + category.fromJson(json['category']); + } + author = BmobRelation( + this, + AuthorTable(), + 'author', + (json) => AuthorTable().fromJson(json), + [], + ); + return this; +} +``` + +##### 3.4.3 createJson 方法 +> 此方法,将用在数据新增、修改时会被调用,自动转换,需要补全 + +```dart +@override +Map createJson() => { + ...super.createJson(), //此处建议包含基类的createJson方法,会自动完成ACL的设置。 + "name": name, + "pubdate": pubDate?.toJson(), + "category": category.createJson(), + "author": author.createJson(), +}; +``` + +##### 3.4.4 toJson() 方法,可选 +> 此方法,用于将对象进行json化。组件中未引用。所以可结合实际使用需求进行补全。 +```dart +@override +Map createJson() => { + ...super.createJson(), + "name": name, + "pubdate": pubDate?.toJson(), + "category": category.createJson(), + "author": author.createJson(), + }; +``` + +### 4 查询 +#### 4.1 WhereBuilder +> 用于生成查询语句,包含基础字段查询(包括DateTime类型)、复合查询、关联对象查询、位置查询、分页查询、聚合查询、排序、字段过滤 +##### 4.1.1 基础字段查询 +```dart +BmobWhereBuilder where = BmobWhereBuilder(); +where + .whereBasic('age') + .lte(100) + .gte(20) + .contain([30, 40, 50, 60]) + .unContain([50]) + .ne(30) + .all([20, 23, 12]); +where + .whereBasic('birthday') + .gte(DateTime.parse('2020-10-12 12:10:09')) + .lte(DateTime(2021, 12, 13, 23, 12, 12)); +/// 打印查询语句 +L.i(jsonEncode(where.builder())); +``` +##### 4.1.2 复合查询 +```dart +BmobWhereBuilder where = BmobWhereBuilder(); +where.or('width').gte(12.0).lte(34.9); +where.or('width').gte(13.0).lte(34.9); +where.and('height').gte(13.0).lte(34.9); +where.and('height').gte(23.0).lte(44.9); +/// 打印查询语句 +L.i(jsonEncode(where.builder())); +``` +##### 4.1.3 关联对象查询 +> 关联对象,直接调用其include方法即可 +```dart +/// Relation 对象 +await book.category.include(); +/// Pointer 对象 +await book.author.include(); +``` +##### 4.1.4 位置查询 +TODO: or和and的复合查询,未测试过,不知是否可行 + +```dart +BmobWhereBuilder geo = BmobWhereBuilder(); +// 基本查询 +geo + .whereGeoPoint('location', BmobGeoPoint(37.423112, 114.123412)) + .maxDistanceInKilometers(1000); + +// or复合查询 +geo + .orGeoPoint('location', BmobGeoPoint(37.423112, 114.123412)) + .maxDistanceInKilometers(1000); + +// and 复合查询 +geo + .andGeoPoint('location', BmobGeoPoint(37.123421, 114.124412)) + .maxDistanceInKilometers(1000); +/// 打印查询语句 +L.i(jsonEncode(geo.builder())); +``` + +##### 4.1.5 分页查询 +> pageIndex 从1开始。小于1的会自动转化成1 + +```dart +BmobWhereBuilder where = BmobWhereBuilder(); +where.page(1,20); // 页码、每页数量。 +/// 打印查询语句 +L.i(jsonEncode(where.builder())); +``` + +##### 4.1.6 聚合查询 +> 支持常见的 max、min、sum、average、groupBy。支持聚合后的筛选having +```dart +BmobWhereBuilder agr = BmobWhereBuilder(); +agr.max(['age', 'height']) + .min(['age', 'height']) + .average(['age', 'height']) + .sum(['age']) + .groupBy(fields: ['sex'], groupCount: true); // 分组字段,是否对分组进行统计 +L.i(agr.builder()); +``` + +##### 4.1.7 排序 +> 支持多字段排序,升序直接写字段名称,降序在字段名称前加-,也支持聚合查询后的字段排序。 + +```dart +BmobWhereBuilder where = BmobWhereBuilder(); +where.order(['name','-age']); +/// 打印查询语句 +L.i(jsonEncode(where.builder())); +``` + +##### 4.1.8 字段过滤 +```dart +BmobWhereBuilder where = BmobWhereBuilder(); +where.keys(['name','age']); +/// 打印查询语句 +L.i(jsonEncode(where.builder())); +``` \ No newline at end of file diff --git a/lib/src/helper/where_builder.dart b/lib/src/helper/where_builder.dart index d5a6cef..55e5c2f 100644 --- a/lib/src/helper/where_builder.dart +++ b/lib/src/helper/where_builder.dart @@ -44,23 +44,23 @@ class BmobWhereBuilder { BmobWhereBuilder(); /// 位置信息字段查询 - GeoPointBuilder whereGeoPoint(String key) { + GeoPointBuilder whereGeoPoint(String key, BmobGeoPoint center) { if (_whereGeoPoint.containsKey(key)) { return _whereGeoPoint[key]; } - _whereGeoPoint[key] = GeoPointBuilder._(); + _whereGeoPoint[key] = GeoPointBuilder._(center); return _whereGeoPoint[key]; } /// 条件查询-复合查询中的或查询 - GeoPointBuilder orGeoPoint(String key) { - _orGeoPoint.add({key: GeoPointBuilder._()}); + GeoPointBuilder orGeoPoint(String key, BmobGeoPoint center) { + _orGeoPoint.add({key: GeoPointBuilder._(center)}); return _orGeoPoint.last[key]; } /// 条件查询-复合查询中的与查询 - GeoPointBuilder andGeoPoint(String key) { - _orGeoPoint.add({key: GeoPointBuilder._()}); + GeoPointBuilder andGeoPoint(String key, BmobGeoPoint center) { + _orGeoPoint.add({key: GeoPointBuilder._(center)}); return _orGeoPoint.last[key]; } @@ -352,14 +352,16 @@ class KeyBuilder { class GeoPointBuilder { final Map _json = {}; - GeoPointBuilder._(); - - /// 查询的中心点 - GeoPointBuilder nearSphere(BmobGeoPoint point) { + GeoPointBuilder._(BmobGeoPoint point) { _json['\$nearSphere'] = point.toJson(); - return this; } + // /// 查询的中心点 + // GeoPointBuilder nearSphere(BmobGeoPoint point) { + // _json['\$nearSphere'] = point.toJson(); + // return this; + // } + /// 距离中心点的最大距离 /// [miles] (英里) GeoPointBuilder maxDistanceInMiles([double? miles]) { diff --git a/pubspec.yaml b/pubspec.yaml index 8c43832..af6e56e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: mini_bmob -description: A new Flutter project. -version: 0.0.1 -homepage: +description: Bmob API interface encapsulation supports encrypted transmission, including user management, ACL and role, geographic location, condition query, data association, array, object operation and other module functions +version: 0.1.0 +homepage: https://github.com/collectFlutter/mini_bmob environment: sdk: ">=2.12.0 <3.0.0" diff --git a/test/no_safe_test.dart b/test/no_safe_test.dart index 4c7b7a9..16e17db 100644 --- a/test/no_safe_test.dart +++ b/test/no_safe_test.dart @@ -201,17 +201,14 @@ void main() { group('WhereBuilder Test', () { test('位置查询', () { BmobWhereBuilder geo = BmobWhereBuilder(); - // geo - // .whereGeoPoint('location') - // .nearSphere(BmobGeoPoint(12, 34)) - // .maxDistanceInKilometers(1000); geo - .orGeoPoint('location') - .nearSphere(BmobGeoPoint(22, 34)) + .whereGeoPoint('location', BmobGeoPoint(37.423112, 114.123412)) .maxDistanceInKilometers(1000); geo - .orGeoPoint('location') - .nearSphere(BmobGeoPoint(23, 34)) + .orGeoPoint('location', BmobGeoPoint(37.423112, 114.123412)) + .maxDistanceInKilometers(1000); + geo + .andGeoPoint('location', BmobGeoPoint(37.123421, 114.124412)) .maxDistanceInKilometers(1000); L.i(jsonEncode(geo.builder())); L.i(geo.builder()); @@ -219,10 +216,10 @@ void main() { test("聚合查询", () { BmobWhereBuilder agr = BmobWhereBuilder(); - agr.max(['age', 'height']).min(['age', 'height']).average( - ['age', 'height']).sum(['age']).groupBy(fields: [ - 'sex' - ], groupCount: true).order(['-age']); + agr.max(['age', 'height']).min(['age', 'height']).average([ + 'age', + 'height' + ]).sum(['age']).groupBy(fields: ['sex'], groupCount: true); L.i(agr.builder()); }); @@ -249,6 +246,18 @@ void main() { where.order(['-birthday', 'age']); L.i(where.builder()); }); + + test('分页查询', () { + BmobWhereBuilder where = BmobWhereBuilder(); + where.page(1, 20); + L.i(where.builder()); + }); + + test('字段过滤', () { + BmobWhereBuilder where = BmobWhereBuilder(); + where.keys(['name', 'age']); + L.i(where.builder()); + }); }); group('QueryHelper Test', () { diff --git a/test/safe_test.dart b/test/safe_test.dart index f563e28..312f8d9 100644 --- a/test/safe_test.dart +++ b/test/safe_test.dart @@ -12,6 +12,7 @@ import 'config.dart'; void main() { BmobConfig.initSafe(secretKey, masterKey: masterKey, + safeToken: 'JsonYe-', printError: (object, extra) => L.e(object), printResponse: (object, extra) => L.d(object)); diff --git a/test/table/book.dart b/test/table/book.dart index 8c885c2..ffee2e8 100644 --- a/test/table/book.dart +++ b/test/table/book.dart @@ -4,17 +4,30 @@ import 'author.dart'; import 'category.dart'; class BookTable extends BmobTable { + /// 图书名称 String? name; + + /// 出版时间 + BmobDateTime? pubDate; + + /// 作者 late BmobRelation author; + + /// 所属类别 late BmobPointer category; - BookTable( - {this.name, - List author = const [], - CategoryTable? category}) { + BookTable({ + this.name, + DateTime? pubDate, + List author = const [], + CategoryTable? category, + }) { assert(category == null || category.objectId != null); assert( author.isEmpty || !author.any((element) => element.objectId == null)); + if (pubDate != null) { + this.pubDate = BmobDateTime(pubDate); + } this.author = BmobRelation( this, AuthorTable(), @@ -32,6 +45,7 @@ class BookTable extends BmobTable { Map createJson() => { ...super.createJson(), "name": name, + "pubdate": pubDate?.toJson(), "category": category.createJson(), "author": author.createJson(), }; @@ -40,6 +54,9 @@ class BookTable extends BmobTable { BookTable fromJson(Map json) { super.fromJson(json); name = json['name']; + if (json.containsKey('pubdate')) { + pubDate = BmobDateTime.fromJson(json['pubdate']); + } if (category.subSet == null) { category.subSet = CategoryTable()..fromJson(json['category']); } else {