deviceauth_controller.dart 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:nomo/app/components/ix_snackbar.dart';
  5. class DeviceauthController extends GetxController {
  6. // 用户类型:true为VIP用户,false为免费用户
  7. final isPremium = true.obs;
  8. // 授权码相关
  9. final authCode = '673999'.obs;
  10. final countdownSeconds = 899.obs; // 15分钟 = 900秒,从899开始倒计时
  11. Timer? _countdownTimer;
  12. // 输入码相关
  13. final inputCode = ''.obs;
  14. final isCodeComplete = false.obs;
  15. final isAuthorizing = false.obs;
  16. // 设备管理
  17. final currentDevices = <DeviceInfo>[].obs;
  18. final maxDevices = 4;
  19. // 授权状态
  20. final authorizationStatus = AuthorizationStatus.waiting.obs;
  21. @override
  22. void onInit() {
  23. super.onInit();
  24. _initializeDevices();
  25. _startCountdown();
  26. }
  27. @override
  28. void onClose() {
  29. _countdownTimer?.cancel();
  30. super.onClose();
  31. }
  32. /// 初始化设备列表
  33. void _initializeDevices() {
  34. currentDevices.add(
  35. DeviceInfo(
  36. id: '1',
  37. name: 'Current Device',
  38. type: DeviceTypeEnum.ios,
  39. date: '2022/01/25 13:45',
  40. isCurrent: true,
  41. ),
  42. );
  43. }
  44. /// 开始倒计时
  45. void _startCountdown() {
  46. _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
  47. if (countdownSeconds.value > 0) {
  48. countdownSeconds.value--;
  49. } else {
  50. // 倒计时结束,刷新授权码
  51. _refreshAuthCode();
  52. countdownSeconds.value = 899;
  53. }
  54. });
  55. }
  56. /// 刷新授权码
  57. void _refreshAuthCode() {
  58. // 生成新的6位随机码
  59. final random = DateTime.now().millisecondsSinceEpoch;
  60. authCode.value = (random % 900000 + 100000).toString();
  61. }
  62. /// 设置输入码(由pinput调用)
  63. void setInputCode(String code) {
  64. inputCode.value = code;
  65. isCodeComplete.value = code.length == 6;
  66. }
  67. /// 提交授权码
  68. void submitAuthCode() {
  69. if (inputCode.value.length == 6) {
  70. // 检查设备数量限制
  71. if (currentDevices.length >= maxDevices) {
  72. IXSnackBar.showIXErrorSnackBar(
  73. title: 'Device Limit Reached',
  74. message: 'You can only authorize up to $maxDevices devices',
  75. );
  76. inputCode.value = '';
  77. isCodeComplete.value = false;
  78. return;
  79. }
  80. isAuthorizing.value = true;
  81. authorizationStatus.value = AuthorizationStatus.configuring;
  82. // 模拟授权过程(实际应该调用API)
  83. Timer(const Duration(seconds: 2), () {
  84. isAuthorizing.value = false;
  85. authorizationStatus.value = AuthorizationStatus.success;
  86. // 添加新设备
  87. final newId = (currentDevices.length + 1).toString();
  88. currentDevices.add(
  89. DeviceInfo(
  90. id: newId,
  91. name: 'Android devices',
  92. type: DeviceTypeEnum.android,
  93. uid: 'UID 123-456-789-10$newId',
  94. date: _getCurrentDateTime(),
  95. isCurrent: false,
  96. ),
  97. );
  98. // 显示成功提示
  99. IXSnackBar.showIXSnackBar(
  100. title: 'Device Authorized',
  101. message: 'New device has been successfully authorized',
  102. );
  103. // 清空输入码
  104. inputCode.value = '';
  105. isCodeComplete.value = false;
  106. // 重置状态
  107. Timer(const Duration(milliseconds: 500), () {
  108. authorizationStatus.value = AuthorizationStatus.waiting;
  109. });
  110. });
  111. }
  112. }
  113. /// 获取当前日期时间
  114. String _getCurrentDateTime() {
  115. final now = DateTime.now();
  116. return '${now.year}/${now.month.toString().padLeft(2, '0')}/${now.day.toString().padLeft(2, '0')} '
  117. '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
  118. }
  119. /// 移除设备
  120. void removeDevice(String deviceId) {
  121. final device = currentDevices.firstWhere((d) => d.id == deviceId);
  122. Get.dialog(
  123. AlertDialog(
  124. title: const Text('Relieve Device'),
  125. content: Text(
  126. 'Are you sure you want to relieve ${device.name}?\n\n'
  127. 'This device will lose Premium access.',
  128. ),
  129. actions: [
  130. TextButton(onPressed: () => Get.back(), child: const Text('Cancel')),
  131. TextButton(
  132. onPressed: () {
  133. currentDevices.removeWhere((d) => d.id == deviceId);
  134. Get.back();
  135. Get.snackbar(
  136. 'Device Relieved',
  137. '${device.name} has been removed from authorized devices',
  138. snackPosition: SnackPosition.bottom,
  139. );
  140. },
  141. child: const Text('Relieve', style: TextStyle(color: Colors.red)),
  142. ),
  143. ],
  144. ),
  145. );
  146. }
  147. /// 复制授权码
  148. void copyAuthCode() {
  149. // TODO: 实现复制到剪贴板
  150. IXSnackBar.showIXSnackBar(title: '已复制', message: '授权码已复制到剪贴板');
  151. }
  152. /// 获取倒计时显示文本
  153. String get countdownText {
  154. final minutes = countdownSeconds.value ~/ 60;
  155. final seconds = countdownSeconds.value % 60;
  156. return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
  157. }
  158. /// 获取当前设备数量
  159. int get currentDeviceCount => currentDevices.length;
  160. /// 获取设备数量显示文本
  161. String get deviceCountText => '$currentDeviceCount/$maxDevices';
  162. }
  163. /// 设备信息类
  164. class DeviceInfo {
  165. final String id;
  166. final String name;
  167. final DeviceTypeEnum type;
  168. final String? uid;
  169. final String? date;
  170. final bool isCurrent;
  171. DeviceInfo({
  172. required this.id,
  173. required this.name,
  174. required this.type,
  175. this.uid,
  176. this.date,
  177. this.isCurrent = false,
  178. });
  179. }
  180. /// 设备类型枚举
  181. enum DeviceTypeEnum { ios, android, windows, mac }
  182. /// 授权状态枚举
  183. enum AuthorizationStatus { waiting, configuring, success, failed }