home_view.dart 12 KB

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