home_view.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import 'dart:io';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:get/get.dart';
  5. import 'package:naiyouwl/app/common/constants.dart';
  6. import 'package:naiyouwl/app/component/button_select.dart';
  7. import 'package:naiyouwl/app/component/connection_status.dart';
  8. import 'package:naiyouwl/app/component/connection_widget.dart';
  9. import 'package:naiyouwl/app/component/sys_app_bar.dart';
  10. import 'package:naiyouwl/app/controller/controllers.dart';
  11. import 'package:naiyouwl/app/utils/system_proxy.dart';
  12. import 'package:url_launcher/url_launcher.dart';
  13. import '../controllers/home_controller.dart';
  14. class HomeView extends GetView<HomeController> {
  15. const HomeView({Key? key}) : super(key: key);
  16. @override
  17. Widget build(BuildContext context) {
  18. return Container(
  19. decoration: const BoxDecoration(
  20. image: DecorationImage(
  21. image: AssetImage("assets/images/main/main.png"),
  22. fit: BoxFit.fill,
  23. ),
  24. ),
  25. child: Scaffold(
  26. backgroundColor: Colors.transparent,
  27. appBar: SysAppBar(title: const Text(""), actions: [
  28. Row(
  29. children: [
  30. IconButton(
  31. icon: const Icon(Icons.refresh),
  32. tooltip: '刷新节点',
  33. onPressed: () {
  34. controller.fetchNode();
  35. },
  36. ),
  37. IconButton(onPressed: (){
  38. controller.outlogin();
  39. } ,tooltip: '切换账号', icon: const Icon(Icons.exit_to_app))
  40. ],
  41. ),
  42. ],),
  43. body: Obx(() {
  44. if(controller.errAdminMsg.value){
  45. controller.errAdminMsg.value = false;
  46. Future.delayed(Duration.zero, () async {
  47. bool? result = await controllers.dialog.showNormalDialog(
  48. title: "提示",
  49. content: '网卡模式需要用户管理员模式去运行,点击确定管理员模式重启如果无法重启,手动重启。',
  50. cancelText: "取消",
  51. enterText: "确定",
  52. );
  53. if (result != null && result) {
  54. await controllers.global.onRunAdmin();
  55. } else {
  56. // User pressed "取消" or dismissed the dialog
  57. }
  58. });
  59. }
  60. if (controllers.global.errorMsg.isNotEmpty) {
  61. // WidgetsBinding.instance.addPostFrameCallback((_) {
  62. // ScaffoldMessenger.of(context).showSnackBar(
  63. // SnackBar(content: Text(controller.errorMsg.value))
  64. // );
  65. // });
  66. String message = controllers.global.errorMsg.value;
  67. controllers.global.errorMsg.value = ''; // Clear the error message immediately
  68. // Show the dialog and wait for the result
  69. Future.delayed(Duration.zero, () async {
  70. bool? result = await controllers.dialog.showNormalDialog(
  71. title: "提示",
  72. content: message,
  73. cancelText: "取消",
  74. enterText: "确认",
  75. );
  76. if (result != null && result) {
  77. // User pressed "确认"
  78. if(controllers.global.statusCode.value == 445){
  79. await launchUrl(Uri.parse(controller.UsersysConfig.value.userBuy ?? ""));
  80. }
  81. } else {
  82. // User pressed "取消" or dismissed the dialog
  83. }
  84. });
  85. }
  86. final disabled = !controllers.service.isRunning;
  87. return controller.isLoading.value ? const Center(
  88. child: CircularProgressIndicator()) : Column(
  89. children: [
  90. // 错误消息展示
  91. UserStatusWidget(
  92. isActive: controller.GetEnable(),
  93. isLoading: controller.isLoading.value,
  94. username: controller.GetUserName(),
  95. expiryDate: controller.GetExpiredAt(),
  96. userTraffic: controller.GetTraffic(),
  97. onRefresh: () async {
  98. // 这里插入刷新操作代码
  99. //await Future.delayed(Duration(seconds: 2));
  100. if (controller.isLoading.value != true) {
  101. controller.fetchUserinfo();
  102. }
  103. },),
  104. Padding(
  105. padding: const EdgeInsets.fromLTRB(20, 20, 0, 0),
  106. child: Row(
  107. children: controller.imageMap.entries.expand((entry) {
  108. return [
  109. GestureDetector(
  110. onTap: () => controller.onImageTap(entry.key),
  111. child: Image(
  112. image: AssetImage(entry.value),
  113. width: 60,
  114. height: 60,
  115. ),
  116. ),
  117. //Spacer(), // 平均分配间隔
  118. const SizedBox(width: 30),
  119. ];
  120. }).toList()
  121. ..removeLast(), // 删除最后一个Spacer
  122. )
  123. ),
  124. const SizedBox(height: 35,),
  125. Padding(
  126. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  127. child: Row(
  128. children: [
  129. Text(controller.getHttp().toString()),
  130. const Spacer(),
  131. Text(controller.getSocket().toString()),
  132. ],
  133. ),
  134. ),
  135. ConnectionWidget(
  136. status: controller.connectStatus.value, onTap: () {
  137. if(controllers.service.coreIsRuning == false){
  138. return;
  139. }
  140. if(controller.isConnect.value){
  141. controller.stopVpn();
  142. } else
  143. {
  144. controller.fetchAuthUser();
  145. }
  146. },),
  147. Align(
  148. alignment: Alignment.center,
  149. child: Text(controllers.global.msgStatus.value),
  150. ),
  151. const SizedBox(height: 20,),
  152. Padding(
  153. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  154. child: SizedBox(
  155. width: 200,
  156. height: 40,
  157. child: ElevatedButton(
  158. onPressed: () {
  159. controller.RouteNode();
  160. },
  161. style: ElevatedButton.styleFrom(
  162. primary: Colors.white, // 设置背景颜色为白色
  163. onPrimary: Colors.black, // 设置文字颜色为黑色,确保在白色背景上可见
  164. shape: RoundedRectangleBorder(
  165. borderRadius: BorderRadius.circular(20), // 设置圆角
  166. ),
  167. ),
  168. child: Text(controller.GetNode()),
  169. ),
  170. ),
  171. ),
  172. const SizedBox(height: 20,),
  173. Center(
  174. child: Row(
  175. mainAxisAlignment: MainAxisAlignment.center,
  176. children: [
  177. ButtonSelect(
  178. labels: ['setting_mode_rules'.tr,'setting_mode_global'.tr,],
  179. value: controllers.global.modes.indexOf(controllers.global.modesSelect.value),
  180. onSelect: (idx) => {
  181. controllers.global.updateMode(controllers.global.modes[idx])
  182. },
  183. ),
  184. // const SizedBox(width: 10,),
  185. // ButtonSelect(
  186. // labels: ['route_sys_tile'.tr,'route_tun_title'.tr,],
  187. // value: controllers.global.routeModes.indexOf(controllers.global.routeModesSelect.value),
  188. // onSelect: (idx) => {
  189. // controllers.global.updateRoute(controllers.global.routeModes[idx])
  190. // }
  191. // ),
  192. ],
  193. ),
  194. ),
  195. controllers.service.serviceMode.value == true ? Padding(
  196. padding: const EdgeInsets.fromLTRB(60, 10, 50, 0),
  197. child: Row(
  198. mainAxisAlignment: MainAxisAlignment.center,
  199. children: [
  200. ElevatedButton(onPressed: () async {
  201. await controllers.service.serviceModeSwitch(false);
  202. }, child: const Text("卸载服务")),
  203. ],
  204. ),
  205. ) : Container(),
  206. // const SizedBox(height: 20,),
  207. // Align(
  208. // alignment: Alignment.center,
  209. // child:,
  210. // )
  211. Text("版本号:$kVersion"),
  212. // ElevatedButton(onPressed: () async {
  213. // await controllers.global.showConsole();
  214. // }, child: Text("显示控制台")),
  215. // ElevatedButton(onPressed: () async {
  216. // await controllers.global.hideConsole();
  217. // }, child: Text("隐藏控制台")),
  218. const SizedBox(height: 10,),
  219. Text("当前:${controllers.global.sysInfo.value}"),
  220. ],
  221. );
  222. })
  223. ),
  224. );
  225. }
  226. }
  227. class UserStatusWidget extends StatefulWidget {
  228. final Future<void> Function() onRefresh; // 新增的回调
  229. final bool isActive;
  230. final bool isLoading; // 新增的变量
  231. final String username;
  232. final String userTraffic;
  233. final String expiryDate;
  234. const UserStatusWidget(
  235. {Key? key, required this.isActive, required this.isLoading, required this.username, required this.userTraffic, required this.expiryDate, required this.onRefresh})
  236. : super(key: key);
  237. @override
  238. _UserStatusWidgetState createState() => _UserStatusWidgetState();
  239. }
  240. class _UserStatusWidgetState extends State<UserStatusWidget> {
  241. @override
  242. Widget build(BuildContext context) {
  243. String imagePath = widget.isActive
  244. ? "assets/images/main/userstatus.png"
  245. : "assets/images/main/userstatusoff.png";
  246. return Align(
  247. alignment: Alignment.topCenter,
  248. child: Padding(
  249. padding: const EdgeInsets.fromLTRB(5.0, 0, 5.0, 0.0),
  250. child:
  251. Row(
  252. children: [
  253. const SizedBox(
  254. width: 80,
  255. height: 20,
  256. ),
  257. Column(
  258. crossAxisAlignment: CrossAxisAlignment.start, // 这将使子组件从左边开始对齐
  259. children: [
  260. Row(
  261. children: [
  262. Container(
  263. width: 150,
  264. child: Text(
  265. widget.username,
  266. overflow: TextOverflow.ellipsis, // 使用省略号
  267. softWrap: false, // 关闭文本自动换行
  268. maxLines: 1, // 设置文本最大行数为 1
  269. ),
  270. ),
  271. const SizedBox(width: 2,),
  272. Image(
  273. image: AssetImage(imagePath),
  274. width: 80,
  275. height: 30,
  276. ),
  277. const SizedBox(width: 10,),
  278. IconButton(
  279. tooltip: '刷新账号状态',
  280. icon: widget.isLoading
  281. ? const CircularProgressIndicator()
  282. : Image(image: AssetImage("assets/images/main/refresh.png"),width: 20,height: 20,),
  283. onPressed: () {
  284. // 刷新操作
  285. if (!widget.isLoading) {
  286. widget.onRefresh();
  287. }
  288. },
  289. )
  290. ],
  291. ),
  292. Text(
  293. widget.expiryDate,
  294. style: const TextStyle(
  295. fontSize: 12.0, // 设置字体大小为20像素
  296. ),
  297. ),
  298. Text(
  299. widget.userTraffic,
  300. style: const TextStyle(
  301. fontSize: 12.0, // 设置字体大小为20像素
  302. ),
  303. )
  304. ],
  305. ),
  306. ],
  307. ),
  308. // const SizedBox(height: 10,), // 可调整间隔
  309. ),
  310. );
  311. }
  312. }