view.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. import 'package:electronic_assistant/base/base_page.dart';
  2. import 'package:electronic_assistant/resource/assets.gen.dart';
  3. import 'package:electronic_assistant/resource/colors.gen.dart';
  4. import 'package:electronic_assistant/resource/string.gen.dart';
  5. import 'package:electronic_assistant/utils/expand.dart';
  6. import 'package:electronic_assistant/utils/toast_util.dart';
  7. import 'package:flutter/gestures.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:flutter_screenutil/flutter_screenutil.dart';
  10. import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
  11. import 'package:get/get.dart';
  12. import '../../router/app_pages.dart';
  13. import 'controller.dart';
  14. class HomePage extends BasePage<HomePageController> {
  15. HomePage({super.key});
  16. BuildContext? todoTargetContext;
  17. @override
  18. Widget buildBody(BuildContext context) {
  19. return Stack(
  20. children: [
  21. buildBgBox(),
  22. buildTopGradient(),
  23. SafeArea(
  24. child: Column(
  25. children: [
  26. Container(
  27. width: 1.sw,
  28. padding: const EdgeInsets.all(12).w,
  29. child: buildOperationBar(),
  30. ),
  31. Expanded(
  32. child: CustomScrollView(
  33. slivers: [
  34. buildTalkRecordTitle(),
  35. SliverToBoxAdapter(
  36. child: Container(
  37. height: 0.3111.sw,
  38. margin: EdgeInsets.only(bottom: 15.h),
  39. child: buildTalkRecord(),
  40. ),
  41. ),
  42. buildTalkTodoTitle(),
  43. SliverAnimatedList(
  44. itemBuilder: _buildTodoItem, initialItemCount: 20),
  45. buildSeeMoreView(),
  46. ],
  47. ))
  48. ],
  49. ),
  50. )
  51. ],
  52. );
  53. }
  54. @override
  55. bool immersive() {
  56. return true;
  57. }
  58. SliverToBoxAdapter buildSeeMoreView() {
  59. return SliverToBoxAdapter(
  60. child: Container(
  61. alignment: Alignment.center,
  62. padding: const EdgeInsets.only(top: 12, bottom: 36).w,
  63. child: RichText(
  64. text: TextSpan(
  65. text: StringName.homeTalkTodo1.tr,
  66. style:
  67. TextStyle(color: ColorName.secondaryTextColor, fontSize: 12.sp),
  68. children: <TextSpan>[
  69. TextSpan(
  70. text: StringName.homeTalkTodo2.tr,
  71. style:
  72. TextStyle(color: ColorName.colorPrimary, fontSize: 12.sp),
  73. recognizer: TapGestureRecognizer()
  74. ..onTap = () {
  75. ToastUtil.showToast('点击了全部');
  76. }),
  77. ],
  78. ),
  79. ),
  80. ),
  81. );
  82. }
  83. SliverToBoxAdapter buildTalkTodoTitle() {
  84. return SliverToBoxAdapter(
  85. child: Column(
  86. children: [
  87. SizedBox(height: 9.w),
  88. buildTitle(StringName.homeTalkTodoTitle.tr, () {
  89. ToastUtil.showToast('待办事项 查看全部');
  90. }),
  91. SizedBox(height: 12.w)
  92. ],
  93. ));
  94. }
  95. SliverToBoxAdapter buildTalkRecordTitle() {
  96. return SliverToBoxAdapter(
  97. child: Column(
  98. children: [
  99. SizedBox(height: 7.w),
  100. buildTitle(StringName.homeTalkRecord.tr, () {
  101. controller.goTalkRecordPage();
  102. }),
  103. SizedBox(height: 12.w)
  104. ],
  105. ),
  106. );
  107. }
  108. Row buildOperationBar() {
  109. return Row(children: [buildGoLogin(), const Spacer(), buildGoStore()]);
  110. }
  111. GestureDetector buildGoStore() {
  112. return GestureDetector(
  113. child: DecoratedBox(
  114. decoration: BoxDecoration(
  115. color: Colors.white,
  116. borderRadius: BorderRadius.circular(16),
  117. ),
  118. child: Padding(
  119. padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2).w,
  120. child: Row(
  121. crossAxisAlignment: CrossAxisAlignment.center,
  122. children: [
  123. SizedBox(
  124. width: 28.w,
  125. height: 28.w,
  126. child: Assets.images.iconCharge.image()),
  127. SizedBox(width: 4.w),
  128. SizedBox(
  129. width: 28.w, child: Assets.images.iconChargeTxt.image()),
  130. SizedBox(
  131. width: 12.w,
  132. height: 12.w,
  133. child: Assets.images.iconChargeArrow.image()),
  134. ],
  135. ),
  136. )),
  137. onTap: () {
  138. ToastUtil.showToast('GoStore');
  139. });
  140. }
  141. Widget buildGoLogin() {
  142. return Obx(() {
  143. return GestureDetector(
  144. onTap: () {
  145. if (controller.isLogin) {
  146. controller.showLoginDrawer();
  147. } else {
  148. Get.toNamed(RoutePath.login);
  149. }
  150. },
  151. child: Row(
  152. children: [
  153. SizedBox(
  154. width: 36.w,
  155. height: 36.w,
  156. child: controller.isLogin
  157. ? Assets.images.iconHomeLogged.image()
  158. : Assets.images.iconHomeNoLogin.image()),
  159. SizedBox(width: 8.w),
  160. Text(controller.loginTxt,
  161. style: TextStyle(
  162. fontWeight: FontWeight.bold,
  163. fontSize: 15.sp,
  164. color: ColorName.primaryTextColor)),
  165. SizedBox(width: 6.w),
  166. controller.isLogin
  167. ? const SizedBox.shrink()
  168. : SizedBox(
  169. height: 16.w, child: Assets.images.iconGoLoginArrow.image())
  170. ],
  171. ),
  172. );
  173. });
  174. }
  175. Container buildTopGradient() {
  176. return Container(
  177. width: 1.sw,
  178. height: 112.h,
  179. decoration: BoxDecoration(
  180. gradient: LinearGradient(
  181. colors: ['#E8EBFF'.toColor(), '#00E8EBFF'.toColor()],
  182. begin: Alignment.topCenter,
  183. end: Alignment.bottomCenter,
  184. stops: const [0.3, 1.0],
  185. ),
  186. ) // 其他子小部件
  187. );
  188. }
  189. DecoratedBox buildBgBox() {
  190. return DecoratedBox(
  191. decoration: BoxDecoration(color: '#F6F6F6'.toColor()),
  192. child: Container(
  193. height: double.infinity,
  194. ));
  195. }
  196. Widget buildTalkRecord() {
  197. return SizedBox(
  198. width: 1.sw,
  199. child: CustomScrollView(
  200. scrollDirection: Axis.horizontal,
  201. slivers: [
  202. SliverToBoxAdapter(child: SizedBox(width: 12.w)),
  203. buildGoRecordView(),
  204. SliverAnimatedList(itemBuilder: _buildTalkItem, initialItemCount: 10)
  205. ],
  206. ),
  207. );
  208. }
  209. SliverToBoxAdapter buildGoRecordView() {
  210. return SliverToBoxAdapter(
  211. child: GestureDetector(
  212. onTap: () {
  213. showUnfinishedRecordPopup();
  214. },
  215. child: Container(
  216. margin: EdgeInsets.only(right: 8.w),
  217. decoration: BoxDecoration(
  218. color: Colors.white,
  219. border: Border.all(color: '#EBEBFF'.toColor(), width: 1),
  220. borderRadius: BorderRadius.circular(8.0),
  221. ),
  222. child: SizedBox(
  223. width: 100.w,
  224. height: double.infinity,
  225. child: Stack(
  226. children: [
  227. Positioned(
  228. right: 0,
  229. bottom: 0,
  230. child: SizedBox(
  231. width: 48.w,
  232. child: Assets.images.bgHomeQuickAudio.image(),
  233. ),
  234. ),
  235. Positioned.fill(
  236. child: Align(
  237. alignment: Alignment.center,
  238. child: Column(
  239. children: [
  240. SizedBox(height: 20.h),
  241. SizedBox(
  242. width: 32.w,
  243. height: 32.w,
  244. child: Assets.images.iconAddTalk.image()),
  245. SizedBox(height: 6.h),
  246. Text(StringName.homeTalkAudio.tr,
  247. style: TextStyle(
  248. fontSize: 14.sp,
  249. color: ColorName.colorPrimary,
  250. fontWeight: FontWeight.bold)),
  251. Builder(builder: (context) {
  252. todoTargetContext = context;
  253. return Text(StringName.homeTalkQuickAudio.tr,
  254. style: TextStyle(
  255. fontSize: 10.sp,
  256. color: ColorName.secondaryTextColor));
  257. })
  258. ],
  259. ),
  260. )),
  261. ],
  262. ),
  263. ),
  264. ),
  265. ));
  266. }
  267. Widget _buildTodoItem(
  268. BuildContext context, int index, Animation<double> animation) {
  269. return Container(
  270. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 17).w,
  271. margin: const EdgeInsets.only(left: 12, right: 12, bottom: 8).w,
  272. decoration: BoxDecoration(
  273. color: Colors.white,
  274. borderRadius: BorderRadius.circular(8),
  275. ),
  276. child: Row(
  277. crossAxisAlignment: CrossAxisAlignment.center,
  278. children: [
  279. SizedBox(
  280. width: 20.w,
  281. height: 20.w,
  282. child: Assets.images.iconAgentChecked.image()),
  283. SizedBox(width: 8.w),
  284. Text('今天要完成某项任务',
  285. style: TextStyle(
  286. fontSize: 15.sp,
  287. fontWeight: FontWeight.bold,
  288. color: ColorName.primaryTextColor)),
  289. const Spacer(),
  290. Container(
  291. decoration: BoxDecoration(
  292. gradient: LinearGradient(
  293. colors: ['#9075FF'.toColor(), '#4366FF'.toColor()],
  294. stops: const [0.3, 1.0],
  295. ),
  296. borderRadius: BorderRadius.circular(6),
  297. ),
  298. padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 4).w,
  299. child: Text(
  300. StringName.homeTalkThinking.tr,
  301. style: TextStyle(fontSize: 13.sp, color: ColorName.white),
  302. ),
  303. )
  304. ],
  305. ),
  306. );
  307. }
  308. Widget _buildTalkItem(
  309. BuildContext context, int index, Animation<double> animation) {
  310. return Container(
  311. width: 258.w,
  312. margin: EdgeInsets.only(right: 8.w),
  313. decoration: BoxDecoration(
  314. color: Colors.white,
  315. border: Border.all(color: '#F0F0F0'.toColor(), width: 1),
  316. borderRadius: BorderRadius.circular(8),
  317. ),
  318. height: double.infinity,
  319. padding: EdgeInsets.symmetric(horizontal: 12.w),
  320. child: Column(
  321. mainAxisAlignment: MainAxisAlignment.center,
  322. crossAxisAlignment: CrossAxisAlignment.start,
  323. children: [
  324. Row(
  325. children: [
  326. Container(
  327. padding: const EdgeInsets.symmetric(horizontal: 6).w,
  328. decoration: BoxDecoration(
  329. color: '#DFE4FC'.toColor(),
  330. borderRadius: BorderRadius.circular(4),
  331. ),
  332. child: Text(
  333. StringName.homeTalkExample.tr,
  334. style: TextStyle(
  335. fontSize: 12.sp, color: ColorName.colorPrimary),
  336. )),
  337. SizedBox(width: 6.w),
  338. Text('与吴总张总沟通活动策划',
  339. style: TextStyle(
  340. fontSize: 15.sp,
  341. color: ColorName.colorPrimary,
  342. fontWeight: FontWeight.bold))
  343. ],
  344. ),
  345. SizedBox(height: 5.h),
  346. Text(
  347. style: TextStyle(
  348. fontSize: 12.sp, color: ColorName.secondaryTextColor),
  349. overflow: TextOverflow.ellipsis,
  350. maxLines: 2,
  351. '这个群,现在由我管理。目的是把你们训练成一个个社会高薪人士,从本周起,已经个个社会高薪人士,从本周起,已经个个社会高薪人士,从本周起,已经'),
  352. SizedBox(height: 8.h),
  353. Row(
  354. crossAxisAlignment: CrossAxisAlignment.center,
  355. children: [
  356. Text('1m12s',
  357. style: TextStyle(
  358. fontSize: 12.sp, color: ColorName.tertiaryTextColor)),
  359. SizedBox(width: 6.w),
  360. Container(
  361. width: 1, height: 9, color: ColorName.tertiaryTextColor),
  362. SizedBox(width: 6.w),
  363. Text('2024-04-15 10:04',
  364. style: TextStyle(
  365. fontSize: 12.sp, color: ColorName.tertiaryTextColor))
  366. ],
  367. )
  368. ],
  369. ));
  370. }
  371. Widget buildTitle(String titleName, VoidCallback onTap) {
  372. return Padding(
  373. padding: const EdgeInsets.symmetric(horizontal: 12).w,
  374. child: Row(
  375. crossAxisAlignment: CrossAxisAlignment.center,
  376. children: [
  377. Text(titleName,
  378. style: TextStyle(
  379. fontWeight: FontWeight.bold,
  380. fontSize: 17.sp,
  381. color: ColorName.primaryTextColor)),
  382. const Spacer(),
  383. GestureDetector(
  384. onTap: onTap,
  385. child: Padding(
  386. padding: const EdgeInsets.symmetric(vertical: 6).w,
  387. child: Row(
  388. crossAxisAlignment: CrossAxisAlignment.center,
  389. children: [
  390. Text(
  391. StringName.homeTalkSeeAll.tr,
  392. style: TextStyle(
  393. fontSize: 13.sp, color: ColorName.secondaryTextColor),
  394. ),
  395. SizedBox(
  396. width: 16.w,
  397. height: 16.w,
  398. child: Assets.images.iconHomeTalkArrow.image()),
  399. ],
  400. ),
  401. ),
  402. )
  403. ],
  404. ),
  405. );
  406. }
  407. attachDialog(BuildContext? context, Alignment alignment) {
  408. SmartDialog.showAttach(
  409. targetContext: context,
  410. alignment: alignment,
  411. animationType: SmartAnimationType.fade,
  412. clickMaskDismiss: true,
  413. maskColor: Colors.transparent,
  414. bindPage: true,
  415. builder: (_) => Padding(
  416. padding: const EdgeInsets.only(top: 7).h,
  417. child: Stack(
  418. alignment: Alignment.topCenter,
  419. children: [
  420. SizedBox(
  421. width: 146.w,
  422. height: 66.w,
  423. child: Assets.images.bgAudioTodoPopup.image()),
  424. Container(
  425. alignment: Alignment.center,
  426. padding: const EdgeInsets.only(top: 17).w,
  427. width: 146.w,
  428. child: Text(StringName.homePopupTipsTxt.tr,
  429. style: TextStyle(fontSize: 14.sp, color: Colors.white)))
  430. ],
  431. ),
  432. ),
  433. );
  434. }
  435. void showUnfinishedRecordPopup() {
  436. attachDialog(todoTargetContext, Alignment.bottomRight);
  437. }
  438. }