intimacy_analyse_report_widget.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:keyboard/resource/string.gen.dart';
  4. import '../../../resource/assets.gen.dart';
  5. import '../../../resource/colors.gen.dart';
  6. import '../../../widget/animated_progress_bar.dart';
  7. import '../../../widget/markdown/markdown_viewer.dart';
  8. /// 亲密度报告组件
  9. class IntimacyAnalyseReportWidget extends StatelessWidget {
  10. /// 报告内容
  11. final String reportContent;
  12. const IntimacyAnalyseReportWidget({super.key, required this.reportContent});
  13. @override
  14. Widget build(BuildContext context) {
  15. return reportContent.isEmpty
  16. // 报告生成中
  17. ? CreatingReportCardWidget()
  18. // 已出报告
  19. : ExistReportCardWidget(reportContent: reportContent);
  20. }
  21. }
  22. /// 已有报告组件
  23. class ExistReportCardWidget extends StatelessWidget {
  24. /// 报告内容,Markdown格式
  25. final String reportContent;
  26. const ExistReportCardWidget({super.key, required this.reportContent});
  27. @override
  28. Widget build(BuildContext context) {
  29. return ReportCardFrameWidget(
  30. height: 850.h,
  31. child: Column(
  32. mainAxisSize: MainAxisSize.min,
  33. children: [
  34. _buildReportOverview(),
  35. SizedBox(height: 10.h),
  36. _buildReportDetail(),
  37. ],
  38. ),
  39. );
  40. }
  41. /// 报告概览,包含概览数值和图表
  42. Widget _buildReportOverview() {
  43. // 圆角背景
  44. return Container(
  45. padding: EdgeInsets.only(left: 12.w, right: 12.w, top: 12.h),
  46. decoration: BoxDecoration(
  47. color: ColorName.white,
  48. borderRadius: BorderRadius.circular(20.r),
  49. ),
  50. child: Column(
  51. mainAxisSize: MainAxisSize.min,
  52. children: [
  53. // 概览数值
  54. Container(
  55. padding: EdgeInsets.symmetric(horizontal: 18.w),
  56. decoration: BoxDecoration(
  57. color: ColorName.bgReportOverview,
  58. borderRadius: BorderRadius.all(Radius.circular(10.r)),
  59. ),
  60. child: Row(
  61. children: [
  62. _buildIntimacyOverviewItem("30"),
  63. _buildOverviewDivider(),
  64. _buildCurrentStageOverviewItem("相互了解"),
  65. ],
  66. ),
  67. ),
  68. SizedBox(height: 36.h),
  69. // 图表
  70. _buildChart(),
  71. ],
  72. ),
  73. );
  74. }
  75. /// 概览数值的分割线
  76. Widget _buildOverviewDivider() {
  77. return Container(
  78. height: 44.h,
  79. width: 1.w,
  80. decoration: BoxDecoration(color: ColorName.black5),
  81. margin: EdgeInsets.symmetric(vertical: 10.h),
  82. );
  83. }
  84. /// 概览亲密度的数值项
  85. Widget _buildIntimacyOverviewItem(String value) {
  86. return Expanded(
  87. child: Row(
  88. // 左对齐
  89. mainAxisAlignment: MainAxisAlignment.start,
  90. children: [
  91. // 图表
  92. Assets.images.iconIntimacyAnalyseReportOverviewLove.image(
  93. height: 22.w,
  94. width: 22.w,
  95. ),
  96. SizedBox(width: 14.w),
  97. Column(
  98. crossAxisAlignment: CrossAxisAlignment.start,
  99. children: [
  100. // 数值区域
  101. Row(
  102. children: [
  103. // 数值
  104. Text(
  105. value,
  106. style: TextStyle(
  107. color: ColorName.black80,
  108. fontSize: 20.sp,
  109. fontWeight: FontWeight.w700,
  110. ),
  111. ),
  112. SizedBox(width: 2.w),
  113. // 百分比符号
  114. Text(
  115. StringName.intimacyValuePercent,
  116. style: TextStyle(
  117. color: ColorName.black46,
  118. fontSize: 13.sp,
  119. fontWeight: FontWeight.w700,
  120. ),
  121. ),
  122. ],
  123. ),
  124. // 描述
  125. Text(
  126. StringName.intimacyValue,
  127. style: TextStyle(
  128. color: ColorName.textReportOverviewValueDesc,
  129. fontSize: 12.sp,
  130. fontWeight: FontWeight.w400,
  131. ),
  132. ),
  133. ],
  134. ),
  135. ],
  136. ),
  137. );
  138. }
  139. /// 概览目前阶段的数值项
  140. Widget _buildCurrentStageOverviewItem(String value) {
  141. return Expanded(
  142. child: Row(
  143. // 右对齐
  144. mainAxisAlignment: MainAxisAlignment.end,
  145. children: [
  146. // 图标
  147. Assets.images.iconIntimacyAnalyseReportOverviewStage.image(
  148. height: 22.w,
  149. width: 22.w,
  150. ),
  151. SizedBox(width: 14.w),
  152. Column(
  153. crossAxisAlignment: CrossAxisAlignment.start,
  154. children: [
  155. // 数值
  156. Text(
  157. value,
  158. style: TextStyle(
  159. color: ColorName.black80,
  160. fontSize: 14.sp,
  161. fontWeight: FontWeight.w700,
  162. ),
  163. ),
  164. // 描述
  165. Text(
  166. StringName.intimacyCurrentStage,
  167. style: TextStyle(
  168. color: ColorName.textReportOverviewValueDesc,
  169. fontSize: 12.sp,
  170. fontWeight: FontWeight.w400,
  171. ),
  172. ),
  173. ],
  174. ),
  175. ],
  176. ),
  177. );
  178. }
  179. /// 报告图表
  180. Widget _buildChart() {
  181. return Column(
  182. mainAxisSize: MainAxisSize.min,
  183. children: [
  184. _buildValueItem(
  185. iconProvider: Assets.images.iconEmojiLike.provider(),
  186. title: "互动好感度",
  187. value: 0.5,
  188. progressColors: [ColorName.blueGradient1, ColorName.blueGradient2],
  189. ),
  190. SizedBox(height: 18.h),
  191. _buildValueItem(
  192. iconProvider: Assets.images.iconEmojiChat.provider(),
  193. title: "话题好感度",
  194. value: 0.35,
  195. progressColors: [ColorName.greenGradient1, ColorName.greenGradient2],
  196. ),
  197. SizedBox(height: 18.h),
  198. _buildValueItem(
  199. iconProvider: Assets.images.iconEmojiLike.provider(),
  200. title: "情绪回应",
  201. value: 1.0,
  202. progressColors: [
  203. ColorName.yellowGradient1,
  204. ColorName.yellowGradient2,
  205. ],
  206. ),
  207. SizedBox(height: 18.h),
  208. _buildValueItem(
  209. iconProvider: Assets.images.iconEmojiPercent.provider(),
  210. title: "亲密词占比",
  211. value: 0.4,
  212. progressColors: [ColorName.pinkGradient1, ColorName.pinkGradient2],
  213. ),
  214. SizedBox(height: 18.h),
  215. _buildValueItem(
  216. iconProvider: Assets.images.iconEmojiLove.provider(),
  217. title: "缘分指数",
  218. value: 0.15,
  219. progressColors: [
  220. ColorName.purpleGradient1,
  221. ColorName.purpleGradient2,
  222. ],
  223. ),
  224. SizedBox(height: 12, width: double.infinity),
  225. ],
  226. );
  227. }
  228. /// 构建数值Item
  229. /// [iconProvider] icon图标的ImageProvider
  230. /// [title] 标题
  231. /// [progressColors] 进度条渐变色
  232. /// [value] 进度条的数值,从0到1.0
  233. Widget _buildValueItem({
  234. required ImageProvider iconProvider,
  235. required String title,
  236. required List<Color> progressColors,
  237. required double value,
  238. }) {
  239. return Row(
  240. mainAxisSize: MainAxisSize.min,
  241. crossAxisAlignment: CrossAxisAlignment.center,
  242. children: [
  243. // 图标
  244. Container(
  245. padding: EdgeInsets.all(6.w),
  246. decoration: BoxDecoration(
  247. // 圆形背景
  248. shape: BoxShape.circle,
  249. color: ColorName.bgReportValueIcon,
  250. ),
  251. child: ClipOval(
  252. child: Image(
  253. image: iconProvider,
  254. width: 15.w,
  255. height: 15.w,
  256. fit: BoxFit.fill,
  257. ),
  258. ),
  259. ),
  260. SizedBox(width: 5.w),
  261. // 文字
  262. Text(title),
  263. SizedBox(width: 10.w),
  264. // 进度条
  265. Expanded(
  266. child: AnimatedGradientProgressBar(
  267. // 进度值
  268. targetValue: value,
  269. // 渐变色
  270. gradient: LinearGradient(colors: progressColors),
  271. // 动画时长
  272. duration: const Duration(milliseconds: 1500),
  273. ),
  274. ),
  275. ],
  276. );
  277. }
  278. /// 报告详情
  279. Widget _buildReportDetail() {
  280. return Container(
  281. height: 424.h,
  282. decoration: ShapeDecoration(
  283. color: ColorName.white,
  284. shape: RoundedRectangleBorder(
  285. borderRadius: BorderRadius.circular(30.r),
  286. ),
  287. ),
  288. child: MarkdownViewer(content: reportContent),
  289. );
  290. }
  291. }
  292. /// 报告生成中的卡片
  293. class CreatingReportCardWidget extends StatelessWidget {
  294. const CreatingReportCardWidget({super.key});
  295. @override
  296. Widget build(BuildContext context) {
  297. return ReportCardFrameWidget(
  298. height: 300.h,
  299. child: Container(
  300. decoration: ShapeDecoration(
  301. color: ColorName.white,
  302. shape: RoundedRectangleBorder(
  303. borderRadius: BorderRadius.circular(30.r),
  304. ),
  305. ),
  306. child: Center(
  307. child: Column(
  308. // 垂直水平都居中
  309. mainAxisAlignment: MainAxisAlignment.center,
  310. crossAxisAlignment: CrossAxisAlignment.center,
  311. children: [
  312. // 图标
  313. Assets.images.iconIntimacyAnalysisReportCreating.image(
  314. width: 82,
  315. height: 82,
  316. ),
  317. SizedBox(height: 3.h),
  318. // 文字
  319. Text(
  320. StringName.intimacyAnalyseReportCreating,
  321. style: TextStyle(
  322. fontSize: 14.sp,
  323. color: ColorName.black60,
  324. fontWeight: FontWeight.w400,
  325. ),
  326. ),
  327. ],
  328. ),
  329. ),
  330. ),
  331. );
  332. }
  333. }
  334. /// 报告卡片框架组件,只定义报告卡片的基本框架,例如卡片背景和顶部的标题,内容由子组件来实现
  335. class ReportCardFrameWidget extends StatelessWidget {
  336. // 卡片高度
  337. final double height;
  338. /// 内容子组件
  339. final Widget child;
  340. const ReportCardFrameWidget({
  341. super.key,
  342. required this.height,
  343. required this.child,
  344. });
  345. @override
  346. Widget build(BuildContext context) {
  347. // 卡片背景
  348. return Container(
  349. height: height,
  350. margin: EdgeInsets.only(left: 12, right: 12, bottom: 0),
  351. padding: EdgeInsets.only(bottom: 12),
  352. decoration: BoxDecoration(
  353. image: DecorationImage(
  354. image: Assets.images.bgIntimacyAnalyseReportPreview.provider(),
  355. fit: BoxFit.fill,
  356. ),
  357. ),
  358. child: Stack(
  359. children: [
  360. // 顶部的图标和标题
  361. Positioned(left: 0, right: 0, top: 0, child: _buildReportTopLayout()),
  362. // 内容区域
  363. Positioned(top: 51, left: 12, right: 12, bottom: 5, child: child),
  364. ],
  365. ),
  366. );
  367. }
  368. /// 报告的顶部布局-包含:图标和标题
  369. Widget _buildReportTopLayout() {
  370. return Row(
  371. children: [
  372. Assets.images.iconIntimacyAnalyseReportPreviewLove.image(
  373. width: 50,
  374. height: 48,
  375. ),
  376. Assets.images.iconIntimacyAnalyseReportPreviewTitle.image(
  377. width: 178,
  378. height: 24,
  379. ),
  380. ],
  381. );
  382. }
  383. }