api.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import 'dart:async';
  2. import 'dart:core';
  3. import 'dart:typed_data';
  4. import 'package:app_business/app_config.dart';
  5. import 'package:app_business/generated/base.pb.dart' as pb;
  6. import 'package:app_business/generated/google/protobuf/duration.pb.dart' as pb;
  7. import 'package:app_business/generated/google/protobuf/timestamp.pb.dart' as pb;
  8. import 'package:app_business/generated/track_offical.pbgrpc.dart' as pb;
  9. import 'package:app_business/service/app.dart';
  10. import 'package:grpc/grpc.dart';
  11. import 'package:track_common/model.dart';
  12. import 'package:track_common/track_common.dart';
  13. import 'abase.dart';
  14. export 'package:app_business/generated/base.pb.dart'
  15. show DefaultRequest, IdRequest, IdArrRequest;
  16. export 'package:app_business/generated/google/protobuf/timestamp.pb.dart';
  17. export 'package:app_business/generated/track_offical.pbgrpc.dart'
  18. show ToMatchRegusterAddRequest, ToMatchRegusterListRequest;
  19. export 'package:fixnum/fixnum.dart' show Int64;
  20. typedef SmsType = pb.SmsType;
  21. extension _ImageExt on pb.NetImage {
  22. NetImage toModel() {
  23. return NetImage(url, md5);
  24. }
  25. }
  26. extension DateTimeExt on DateTime? {
  27. pb.Timestamp toPb() {
  28. if (this != null) {
  29. return pb.Timestamp.fromDateTime(this!.toUtc());
  30. } else {
  31. return pb.Timestamp();
  32. }
  33. }
  34. }
  35. extension TSExt on pb.Timestamp {
  36. DateTime toModel() {
  37. return toDateTime(toLocal: true);
  38. }
  39. }
  40. extension DurationExt on pb.Duration {
  41. Duration toModel() {
  42. final microseconds = hasNanos() ? nanos / 1000 : 0;
  43. return Duration(
  44. seconds: seconds.toInt(), microseconds: microseconds.toInt());
  45. }
  46. }
  47. extension PositionExt on pb.Position {
  48. Position toModel() {
  49. return Position(latitude: latitude, longitude: longitude)
  50. ..altitude = altitude;
  51. }
  52. }
  53. extension PBToControlPointExt on pb.ToControlPoint {
  54. ControlPoint toModel() {
  55. final one = ControlPoint()
  56. ..areaId = sn
  57. ..intId = id
  58. ..isSuccess = isCheckSuccess
  59. ..sn = orderNo.toString()
  60. ..checkAfterPrev = checkAfterLast.toModel()
  61. ..checkAfterStart = checkAfterStart.toModel()
  62. ..checkDistanceAfterPrev = disAfterLast.meter
  63. ..distanceStraightToPrev = disStraightAfterLast.meter
  64. ..paceAfterPrev = Pace.perKm(paceAfterLast.seconds)
  65. ..paceAfterStart = Pace.perKm(paceAfterStart.seconds)
  66. ..position = ciPosition.toModel();
  67. if (cType == pb.CType.BeginType) {
  68. one.isStart = true;
  69. }
  70. if (cType == pb.CType.EndType) {
  71. one.isFinish = true;
  72. }
  73. return one;
  74. }
  75. }
  76. class ApiService extends IService {
  77. ClientChannel? channel;
  78. @override
  79. Future<void> init() async {
  80. channel = _newChannel();
  81. }
  82. ClientChannel _newChannel() {
  83. return ClientChannel(
  84. AppConfig.apiHost,
  85. port: AppConfig.apiPort,
  86. options: const ChannelOptions(credentials: ChannelCredentials.secure()
  87. // ChannelCredentials.insecure()
  88. ),
  89. );
  90. }
  91. pb.ApiToClient get stub {
  92. return _newStub(timeout: 10.seconds);
  93. }
  94. pb.ApiToClient _newStub({Duration? timeout, ClientChannel? channel}) {
  95. if (this.channel == null) {
  96. throw Exception('$runtimeType 未初始化');
  97. }
  98. final metadata = <String, String>{};
  99. metadata['version'] = _appVersion;
  100. if (token != null) {
  101. metadata['token'] = token!;
  102. }
  103. // debug("token: $token");
  104. return pb.ApiToClient(channel ?? this.channel!,
  105. options: CallOptions(
  106. metadata: metadata,
  107. timeout: timeout,
  108. ));
  109. }
  110. String get _appVersion => Get.find<AppService>().appVersion;
  111. set token(String? v) {
  112. Get.find<AppService>().token.val = v ?? '';
  113. }
  114. String? get token {
  115. final app = Get.find<AppService>();
  116. final token = app.token.val;
  117. if (token.isEmpty) {
  118. return null;
  119. }
  120. return token;
  121. }
  122. // 获取短信验证码
  123. Future<void> authSendCodeToPhone(String phone, SmsType smsType) async {
  124. info('authSendCodeToPhone [$phone]');
  125. await stub.toSendCodeToPhoneV2(pb.ToSendCodeToPhoneRequestV2()
  126. ..phone = phone
  127. ..smsType = smsType);
  128. }
  129. // 场控端_登录
  130. Future<void> signIn(String userCode, String password, String ip) async {
  131. final r = await stub.toSignInV2(pb.ToSignInRequestV2()
  132. ..userCode = userCode
  133. ..password = password
  134. ..ip = ip);
  135. token = r.token;
  136. debug('sign in success: $token');
  137. }
  138. // 场控端_登出
  139. void signOut() {
  140. stub.toSignOutV2(pb.DefaultRequest());
  141. token = null;
  142. }
  143. Future<Duration> getSmsSendLeftTime(String phone) async {
  144. final r = await stub
  145. .toGetSmsSendLeftTimeV2(pb.GetSmsSendLeftTimeRequest()..phone = phone);
  146. info('getSmsSendLeftTime: $phone - ${r.second}s');
  147. return r.second.seconds;
  148. }
  149. Future<List<MapInfo>> getMapList(int limit, int offset) async {
  150. final r = await stub.toMapListV2(pb.MapListRequestV2()
  151. ..limit = limit
  152. ..offset = offset);
  153. return r.list
  154. .map((e) => MapInfo(e.mapId, e.name, e.distance.meter, e.description,
  155. e.mapScaleNumber, e.image.toModel()))
  156. .toList();
  157. }
  158. Future<BinReader> getBinReaderByMd5(Uint8List md5) async {
  159. final stream =
  160. stub.toGetBinaryByMd5(pb.ToGetBinaryByMd5Request()..md5 = md5);
  161. final controller = StreamController<List<int>>();
  162. controller.onCancel = () {
  163. stream.cancel();
  164. };
  165. Future<void> rcv() async {
  166. try {
  167. await for (final one in stream) {
  168. controller.add(one.data);
  169. }
  170. } finally {
  171. controller.close();
  172. stream.cancel();
  173. }
  174. }
  175. rcv();
  176. stream.headers.then((value) => debug(value));
  177. final headers = await stream.headers;
  178. final lenStr = headers['all-length']!;
  179. final length = int.parse(lenStr);
  180. final nonce = headers['nonce']!;
  181. final ext = headers['ext']!;
  182. return BinReader(
  183. data: controller.stream, length: length, ext: ext, nonce: nonce);
  184. }
  185. Future<void> eventEdit(int id, EventRegisterInfo event) async {
  186. await stub.toMatchRegusterEdit(pb.ToMatchRegusterEditRequest()
  187. ..id = id
  188. ..regName = event.name
  189. ..startAt = event.startAt.toPb()
  190. ..stopAt = event.stopAt.toPb()
  191. ..isQueryPwd = event.password != null
  192. ..queryPasswd = event.password ?? '');
  193. }
  194. Future<void> eventUserAllocRoute(int checkId, int routeId) async {
  195. await stub.toCourseChackMatch(pb.ToCourseChackMatchRequest()
  196. ..id = checkId
  197. ..cId = routeId);
  198. }
  199. Future<void> eventUserAllocRouteAll(Iterable<int> checkIdList) async {
  200. await stub
  201. .allCourseChackMatch(pb.IdArrRequest()..idArr.addAll(checkIdList));
  202. }
  203. Future<void> eventUserStartAll(Iterable<int> checkIdList) async {
  204. await stub
  205. .allMatchChackInsStart(pb.IdArrRequest()..idArr.addAll(checkIdList));
  206. }
  207. Future<void> eventUserRestartAll(Iterable<int> checkIdList) async {
  208. await stub.allMatchChackInsForceResume(
  209. pb.IdArrRequest()..idArr.addAll(checkIdList));
  210. }
  211. Future<void> eventUserDelAll(Iterable<int> checkIdList) async {
  212. await stub
  213. .allMatchChackInsDel(pb.IdArrRequest()..idArr.addAll(checkIdList));
  214. }
  215. Future<void> eventSettingsRulesSave(Iterable<Rule> rules) async {
  216. await stub.toActivityRulesSave(pb.ToActivityRulesSaveRequest()
  217. ..list.addAll(rules.map((e) {
  218. final one = pb.ToActivityRulesSaveInfo()..arrId = e.id;
  219. final vt = e.value;
  220. if (vt is RuleValueBool) {
  221. one.arValue = vt.value ? 'true' : 'false';
  222. }
  223. if (vt is RuleValueArrStr) {
  224. one.arValue = vt.value;
  225. }
  226. return one;
  227. })));
  228. }
  229. Stream<CooperationInfo> cooperationInfo() async* {
  230. while (true) {
  231. await 1.seconds.delay();
  232. try {
  233. final r = await stub.toCooperationQuery(pb.DefaultRequest());
  234. yield CooperationInfo()
  235. ..name = r.name
  236. ..leftCount = r.leftMatchNum;
  237. } catch (e) {
  238. warn('获取可用数错误', e);
  239. }
  240. }
  241. }
  242. }
  243. class CooperationInfo {
  244. var name = '';
  245. // 可用数
  246. var leftCount = 0;
  247. }
  248. class EventRegisterInfo {
  249. var id = 0;
  250. var name = '';
  251. var startAt = DateTime.now();
  252. var stopAt = DateTime.now();
  253. String? password;
  254. }
  255. class Rule {
  256. var id = 0;
  257. var idx = 0;
  258. var name = '';
  259. var isLock = false;
  260. RuleValue value = RuleValueBool();
  261. }
  262. class RuleValue {}
  263. class RuleValueBool extends RuleValue {
  264. var value = false;
  265. }
  266. class RuleValueArrStr extends RuleValue {
  267. var value = '';
  268. var options = <RuleValueArrStrOption>[];
  269. }
  270. class RuleValueArrStrOption {
  271. var show = '';
  272. var value = '';
  273. }