import '../models/models.dart'; import 'report_data_source.dart'; class MockReportDataSource extends ReportDataSource { MockReportDataSource(); static final Institution _wgcSummary = _institutionSummary( id: 'wgc', nameCn: '世界黄金协会', nameEn: 'World Gold Council', logoUrl: 'https://www.google.com/s2/favicons?domain=www.gold.org&sz=128', institutionType: 'industry_org', sourceTier: 'A', websiteUrl: 'https://www.gold.org', coveredTopics: ['贵金属', '央行', '跨资产'], reportCount: 6, introCn: '世界黄金协会致力于推动黄金市场研究与应用,常发布黄金需求、投资与央行购金相关分析。', credibilityNote: '公开数据、央行储备与 ETF 流量交叉验证,适合跟踪黄金需求结构变化。', ); static final Institution _bisSummary = _institutionSummary( id: 'bis', nameCn: '国际清算银行 BIS', nameEn: 'Bank for International Settlements', logoUrl: 'https://www.google.com/s2/favicons?domain=www.bis.org&sz=128', institutionType: 'official', sourceTier: 'A', websiteUrl: 'https://www.bis.org', coveredTopics: ['宏观', '货币政策'], reportCount: 4, introCn: 'BIS 关注全球金融稳定、资本流动和银行体系结构,是宏观与金融市场观察的重要来源。', credibilityNote: '跨国监管机构,通常以统计和制度性框架解释市场变化。', ); static final Institution _ieaSummary = _institutionSummary( id: 'iea', nameCn: '国际能源署 IEA', nameEn: 'International Energy Agency', logoUrl: 'https://www.google.com/s2/favicons?domain=www.iea.org&sz=128', institutionType: 'official', sourceTier: 'A', websiteUrl: 'https://www.iea.org', coveredTopics: ['能源', '大宗'], reportCount: 5, introCn: 'IEA 主要跟踪全球原油、天然气、电力与能源转型相关供需变化。', credibilityNote: '统计频率高,适合配合库存、产量与政策节奏观察。', ); static final Institution _worldBankSummary = _institutionSummary( id: 'worldbank', nameCn: '世界银行', nameEn: 'World Bank', logoUrl: 'https://www.google.com/s2/favicons?domain=www.worldbank.org&sz=128', institutionType: 'official', sourceTier: 'A', websiteUrl: 'https://www.worldbank.org', coveredTopics: ['大宗', '全球增长'], reportCount: 3, introCn: '世界银行常通过大宗商品展望、全球增长与贫困相关研究提供宏观视角。', credibilityNote: '跨国公共机构,适合作为全球价格和增长基准参考。', ); static final Institution _ssgaSummary = _institutionSummary( id: 'ssga', nameCn: '道富环球投资管理', nameEn: 'State Street Global Advisors', logoUrl: 'https://www.google.com/s2/favicons?domain=www.ssga.com&sz=128', institutionType: 'asset_manager', sourceTier: 'A', websiteUrl: 'https://www.ssga.com', coveredTopics: ['贵金属', '跨资产'], reportCount: 4, introCn: '道富的市场观点常围绕资产配置、黄金投资和 ETF 流向展开。', credibilityNote: '资产管理机构视角偏市场化,适合观察投资者行为和资金流。', ); static final ReportDetail _gold = ReportDetail( id: 'gold-demand-q2-2026', titleCn: '黄金需求趋势:央行与亚洲买家的双轮驱动', institution: _wgcSummary, oneLiner: '央行购金与亚洲投资需求,构成本季黄金需求的双轮。', source: const {'source_tier': 'A', 'source_name': 'World Gold Council'}, topics: const ['贵金属', '央行', '跨资产'], hasAudio: true, releasedAt: '2026-05-30', modules: [ _module('gold-basic', 'basic_info', '基本信息', { 'summary_cn': '央行持续买入黄金,叠加亚洲投资需求回暖,支撑本季金价中枢。', 'topics': ['贵金属', '央行', '跨资产'], }), _module('gold-insights', 'core_insights', '核心洞察', { 'points': [ {'kind': 'view', 'text': '央行购金从战术操作转向结构性配置,已成为黄金需求底层支撑。'}, {'kind': 'number', 'text': '金价重回高位后,ETF 与亚洲实物买盘接续承接,波动被更广泛的资金流吸收。'}, {'kind': 'risk', 'text': '若美元和实际利率同步抬升,黄金的防御属性仍会面临短期回撤。'}, ], }, hasDetailPage: true), _module('gold-audio', 'audio', '音频解读', { 'audio_id': 'audio_gold_q2_2026', 'title_cn': '黄金需求趋势:央行与亚洲买家的双轮驱动', 'duration_sec': 860, }), _module('gold-timeline', 'timeline', '时间线', { 'events': [ {'date': '2026-03', 'event': '央行购金维持高位', 'impact': '储备资产配置继续偏向黄金。'}, {'date': '2026-04', 'event': '亚洲投资需求回升', 'impact': '零售和机构买盘共同抬升需求。'}, { 'date': '2026-05', 'event': '金价刷新阶段高位', 'impact': '高位波动加大,但下方买盘承接仍强。', }, ], }, hasDetailPage: true), _module('gold-key-data', 'key_data', '关键数据', { 'rows': [ { 'metric': '央行净买入', 'value': '800+', 'unit': '吨', 'judgment': '仍处高位,支撑黄金中期结构性需求。', }, { 'metric': 'ETF 流向', 'value': '净流入', 'unit': '', 'judgment': '投资盘开始重新接力。', }, { 'metric': '亚洲实物需求', 'value': '回升', 'unit': '', 'judgment': '节庆和资产配置需求叠加。', }, ], }), _module('gold-study', 'study_guide', '研读指南', { 'intro_cn': '如果你只想看结论,先读核心洞察;如果你想跟踪驱动因素,继续看时间线与关键数据。', 'faq_items': [ { 'question': '为什么央行购金重要?', 'answer': '央行购金往往具有中长期配置属性,可以给金价提供比短线投机更稳定的需求锚。', }, { 'question': '亚洲买盘如何影响金价?', 'answer': '当亚洲需求在价格高位仍然保持韧性时,金价上方空间通常更容易被市场重新定价。', }, ], 'glossary': [ {'term': 'ETF', 'definition': '交易型开放式基金,常用于观察机构资金流向。'}, {'term': '央行购金', 'definition': '中央银行增持黄金储备的行为。'}, ], }, hasDetailPage: true), _module('gold-sources', 'related_sources', '相关来源', { 'items': [ {'title': '世界黄金协会季度需求报告', 'summary_cn': '黄金首饰、央行和投资需求的总览。'}, {'title': '道富黄金配置观点', 'summary_cn': '从资产配置角度看黄金在组合中的角色。'}, ], }), _module('gold-weaknesses', 'weaknesses', '风险与验证', { 'disclaimer_cn': '以下内容不构成投资建议,需结合自身风险承受能力判断。', 'items': [ { 'topic': '美元波动', 'weakness': '若美元在短期内持续走强,黄金可能承压。', 'counter_evidence': '实际利率仍处下行或中性,黄金下方支撑尚在。', }, { 'topic': '投机拥挤', 'weakness': '当资金快速涌入时,行情容易出现脉冲式回调。', 'counter_evidence': '央行和长期配置资金可部分对冲短线拥挤。', }, ], 'verification_notes': ['关注央行月度购金变化。', '关注 ETF 净流入是否持续两周以上。'], }), _module('gold-compliance', 'source_compliance', '来源与合规', { 'source_note': '来源以公开研报、统计口径和机构原文为准,结构化内容用于中文解读。', 'copyright_cn': '版权归原始发布机构与作者所有。', 'disclaimer': '本内容为公开/授权研报的结构化解读,不构成投资建议。', }), _module('gold-institution', 'institution', '机构', { 'name_cn': '世界黄金协会', 'report_count': 6, }), ], ); static final ReportDetail _bis = ReportDetail( id: 'bis-quarterly-2026-q1', titleCn: 'BIS 季报 2026年3月:市场重新校准', institution: _bisSummary, oneLiner: '表面平静之下,全球金融市场正经历深刻的流向切换与重新校准。', source: const {'source_tier': 'A', 'source_name': 'BIS'}, topics: const ['宏观', '货币政策'], hasAudio: true, releasedAt: '2026-03-05', modules: [ _module('bis-basic', 'basic_info', '基本信息', { 'summary_cn': 'BIS 关注全球宏观流动、资本配置和金融体系的再平衡。', 'topics': ['宏观', '货币政策'], }), _module('bis-insights', 'core_insights', '核心洞察', { 'points': [ {'kind': 'view', 'text': '市场定价已从单一利率路径转向对增长、通胀和资本流动的综合校准。'}, {'kind': 'number', 'text': '跨境资本流向的再分配比利率本身更能解释当下的市场分化。'}, ], }, hasDetailPage: true), _module('bis-audio', 'audio', '音频解读', { 'audio_id': 'audio_bis_q1_2026', 'title_cn': 'BIS 季报 2026年3月:市场重新校准', 'duration_sec': 1040, }), _module('bis-compliance', 'source_compliance', '来源与合规', { 'source_note': '该模块用于展示机构原文与结构化解读的对应关系。', 'copyright_cn': '版权归 BIS 原始报告与作者所有。', 'disclaimer': '本内容为公开/授权研报的结构化解读,不构成投资建议。', }), _module('bis-institution', 'institution', '机构', { 'name_cn': '国际清算银行 BIS', 'report_count': 4, }), ], ); static final ReportDetail _iea = ReportDetail( id: 'iea-oil-monthly-2026-05', titleCn: '石油市场月报:需求放缓,供给为何仍偏紧?', institution: _ieaSummary, oneLiner: '需求增速放缓,但减产纪律与库存偏低支撑油价下方。', source: const {'source_tier': 'A', 'source_name': 'IEA'}, topics: const ['能源', '大宗'], hasAudio: true, releasedAt: '2026-05-20', modules: [ _module('iea-basic', 'basic_info', '基本信息', { 'summary_cn': 'IEA 月报聚焦全球原油供需、库存和宏观风险。', 'topics': ['能源', '大宗'], }), _module('iea-insights', 'core_insights', '核心洞察', { 'points': [ {'kind': 'view', 'text': '需求放缓并不自动意味着价格回落,关键还是供给纪律和库存水平。'}, {'kind': 'number', 'text': '库存偏低时,价格对中短期扰动的敏感度明显提高。'}, ], }, hasDetailPage: true), _module('iea-audio', 'audio', '音频解读', { 'audio_id': 'audio_iea_2026_05', 'title_cn': '石油市场月报:需求放缓,供给为何仍偏紧?', 'duration_sec': 1120, }), _module('iea-key-data', 'key_data', '关键数据', { 'rows': [ { 'metric': '需求增速', 'value': '放缓', 'unit': '', 'judgment': '不代表价格立刻下行。', }, { 'metric': '供给纪律', 'value': '偏紧', 'unit': '', 'judgment': '减产执行仍在延续。', }, {'metric': '库存', 'value': '偏低', 'unit': '', 'judgment': '对价格形成支撑。'}, ], }), _module('iea-compliance', 'source_compliance', '来源与合规', { 'source_note': 'IEA 原文与统计框架保持一致,中文内容仅用于结构化阅读。', 'copyright_cn': '版权归原始发布机构与作者所有。', 'disclaimer': '本内容为公开/授权研报的结构化解读,不构成投资建议。', }), _module('iea-institution', 'institution', '机构', { 'name_cn': '国际能源署', 'report_count': 5, }), ], ); static final ReportDetail _worldBank = ReportDetail( id: 'worldbank-commodities-2026-04', titleCn: '世界银行大宗商品展望:价格见顶了吗?', institution: _worldBankSummary, oneLiner: '全球增长预期放缓,但价格路径仍受供给侧扰动影响。', source: const {'source_tier': 'A', 'source_name': 'World Bank'}, topics: const ['大宗', '全球增长'], hasAudio: true, releasedAt: '2026-04-18', modules: [ _module('wb-basic', 'basic_info', '基本信息', { 'summary_cn': '世界银行展望通常从全球增长、贸易和大宗商品价格三个层面展开。', 'topics': ['大宗', '全球增长'], }), _module('wb-insights', 'core_insights', '核心洞察', { 'points': [ {'kind': 'view', 'text': '价格是否见顶,往往取决于供给扰动能否被需求放缓完全吸收。'}, {'kind': 'risk', 'text': '若全球增长进一步放缓,大宗商品的边际弹性会显著下降。'}, ], }, hasDetailPage: true), _module('wb-audio', 'audio', '音频解读', { 'audio_id': 'audio_worldbank_2026_04', 'title_cn': '世界银行大宗商品展望:价格见顶了吗?', 'duration_sec': 980, }), _module('wb-compliance', 'source_compliance', '来源与合规', { 'source_note': '世界银行报告适合作为全球商品价格的基准视角。', 'copyright_cn': '版权归原始发布机构与作者所有。', 'disclaimer': '本内容为公开/授权研报的结构化解读,不构成投资建议。', }), _module('wb-institution', 'institution', '机构', { 'name_cn': '世界银行', 'report_count': 3, }), ], ); static final List _details = [_gold, _bis, _iea, _worldBank]; static final Map _detailById = { for (final detail in _details) detail.id: detail, }; static final Map _institutionDetails = { 'wgc': _institutionDetail( base: _wgcSummary, recentReports: [_gold.asCard()], ), 'bis': _institutionDetail( base: _bisSummary, recentReports: [_bis.asCard()], ), 'iea': _institutionDetail( base: _ieaSummary, recentReports: [_iea.asCard()], ), 'worldbank': _institutionDetail( base: _worldBankSummary, recentReports: [_worldBank.asCard()], ), 'ssga': _institutionDetail( base: _ssgaSummary, recentReports: [_gold.asCard()], ), }; static final Map _moduleDetails = { 'gold-insights': _moduleDetail(_gold.modules[1]), 'gold-timeline': _moduleDetail(_gold.modules[3]), 'gold-study': _moduleDetail(_gold.modules[5]), 'bis-insights': _moduleDetail(_bis.modules[1]), 'iea-insights': _moduleDetail(_iea.modules[1]), 'wb-insights': _moduleDetail(_worldBank.modules[1]), }; @override Future> recommended() async => [ _gold.asCard(), _bis.asCard(), _iea.asCard(), ]; @override Future> reports() async => _details.map((d) => d.asCard()).toList(); @override Future> institutions() async { return _institutionDetails.values.toList() ..sort((a, b) => b.reportCount.compareTo(a.reportCount)); } @override Future institutionDetail(String institutionId) async { return _institutionDetails[institutionId] ?? _institutionDetails['wgc']!; } @override Future> listen() async { return [ _audioFromReport(_gold, 860), _audioFromReport(_bis, 1040), _audioFromReport(_iea, 1120), _audioFromReport(_worldBank, 980), ]; } @override Future reportDetail(String reportId) async { return _detailById[reportId] ?? _gold; } @override Future moduleDetail(String reportId, String moduleId) async { return _moduleDetails[moduleId] ?? ModuleDetail( id: moduleId, type: 'basic_info', titleCn: '模块详情', content: const {'preview_summary': '该模块暂无单独详情数据。'}, ); } static Institution _institutionSummary({ required String id, required String nameCn, required String nameEn, required String logoUrl, required String institutionType, required String sourceTier, required String websiteUrl, required List coveredTopics, required int reportCount, required String introCn, required String credibilityNote, }) { return Institution( id: id, nameCn: nameCn, nameEn: nameEn, logoUrl: logoUrl, institutionType: institutionType, sourceTier: sourceTier, websiteUrl: websiteUrl, coveredTopics: coveredTopics, reportCount: reportCount, introCn: introCn, credibilityNote: credibilityNote, ); } static Institution _institutionDetail({ required Institution base, required List recentReports, }) { return Institution( id: base.id, nameCn: base.nameCn, nameEn: base.nameEn, logoUrl: base.logoUrl, institutionType: base.institutionType, sourceTier: base.sourceTier, websiteUrl: base.websiteUrl, coveredTopics: base.coveredTopics, reportCount: base.reportCount, latestReportAt: base.latestReportAt, credibilityNote: base.credibilityNote, introCn: base.introCn, recentReports: recentReports, ); } static DisplayModule _module( String id, String type, String titleCn, JsonMap content, { bool hasDetailPage = false, String renderMode = 'inline', }) { return DisplayModule( id: id, type: type, titleCn: titleCn, renderMode: renderMode, hasDetailPage: hasDetailPage, content: content, preview: content, ); } static ModuleDetail _moduleDetail(DisplayModule module) { return ModuleDetail( id: module.id, type: module.type, titleCn: module.titleCn, content: module.content, contentEtag: 'mock', cacheVersion: 'mock', ); } static AudioItem _audioFromReport(ReportDetail report, int duration) { return AudioItem( audioId: 'audio_${report.id}', reportId: report.id, titleCn: report.titleCn, reportTitleCn: report.titleCn, durationSec: duration, institution: report.institution, releasedAt: report.releasedAt, cacheVersion: 'mock', ); } }