intimacy_analyse_report_widget.dart 11 KB

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