feat:参照研听的基础工程

This commit is contained in:
jingyun
2026-06-18 15:02:28 +08:00
commit 364fc837b3
367 changed files with 16495 additions and 0 deletions
@@ -0,0 +1,74 @@
import '../../../common/domain/metal_type.dart';
enum MarketPeriod {
h24('24h', '24时'),
d5('5d', '5日'),
m1('1m', '1月'),
m3('3m', '3月'),
y1('1y', '1年');
const MarketPeriod(this.id, this.label);
final String id;
final String label;
}
enum ExchangeChannelKind { spot, bar, retail, td, recycle }
class MetalQuote {
const MetalQuote({
required this.metal,
required this.spotPrice,
required this.changeAmount,
required this.changePercent,
required this.updatedAt,
required this.sourceLabel,
required this.basisLabel,
});
final MetalType metal;
final double spotPrice;
final double changeAmount;
final double changePercent;
final DateTime updatedAt;
final String sourceLabel;
final String basisLabel;
}
class MarketPoint {
const MarketPoint({
required this.time,
required this.open,
required this.high,
required this.low,
required this.close,
});
final DateTime time;
final double open;
final double high;
final double low;
final double close;
}
class ExchangeChannel {
const ExchangeChannel({
required this.id,
required this.metal,
required this.name,
required this.kind,
required this.pricePerGram,
required this.source,
required this.updatedAt,
required this.hint,
});
final String id;
final MetalType metal;
final String name;
final ExchangeChannelKind kind;
final double pricePerGram;
final String source;
final DateTime updatedAt;
final String hint;
}
@@ -0,0 +1,216 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../../common/domain/metal_type.dart';
import 'market_models.dart';
final mockMarketRepositoryProvider = Provider<MockMarketRepository>(
(ref) => MockMarketRepository(),
);
class MockMarketRepository {
MockMarketRepository();
final DateTime _updatedAt = DateTime(2026, 6, 18, 16, 11);
List<MetalQuote> getQuotes() {
return [
MetalQuote(
metal: MetalType.gold,
spotPrice: 943.05,
changeAmount: 8.12,
changePercent: 0.87,
updatedAt: _updatedAt,
sourceLabel: '行情聚合',
basisLabel: '上海金现货参考价',
),
MetalQuote(
metal: MetalType.platinum,
spotPrice: 384.20,
changeAmount: -2.46,
changePercent: -0.64,
updatedAt: _updatedAt,
sourceLabel: '行情聚合',
basisLabel: '国际盘换算参考价',
),
MetalQuote(
metal: MetalType.silver,
spotPrice: 15.75,
changeAmount: 0.18,
changePercent: 1.16,
updatedAt: _updatedAt,
sourceLabel: '行情聚合',
basisLabel: '上海银现货参考价',
),
];
}
MetalQuote quoteFor(MetalType metal) =>
getQuotes().firstWhere((quote) => quote.metal == metal);
List<MarketPoint> chartFor(MetalType metal, MarketPeriod period) {
final quote = quoteFor(metal);
final points = <MarketPoint>[];
final step = switch (period) {
MarketPeriod.h24 => const Duration(hours: 2),
MarketPeriod.d5 => const Duration(days: 1),
MarketPeriod.m1 => const Duration(days: 3),
MarketPeriod.m3 => const Duration(days: 9),
MarketPeriod.y1 => const Duration(days: 30),
};
for (var i = 11; i >= 0; i--) {
final drift = (i - 5.5) * quote.changeAmount / 10;
final close = quote.spotPrice - drift;
points.add(
MarketPoint(
time: _updatedAt.subtract(step * i),
open: close - quote.changeAmount / 20,
high: close + quote.spotPrice * 0.003,
low: close - quote.spotPrice * 0.003,
close: close,
),
);
}
return points;
}
List<ExchangeChannel> channelsFor(MetalType metal, {double recycle = 0.97}) {
final quote = quoteFor(metal);
return switch (metal) {
MetalType.gold => [
_channel(
'gold_spot',
metal,
'上海金现货',
ExchangeChannelKind.spot,
943.05,
'上海金现货',
'材料价值口径 · 非金店零售 / 回收价',
),
_channel(
'gold_bar',
metal,
'投资金条',
ExchangeChannelKind.bar,
955.00,
'银行 / 品牌金条参考',
'投资金条参考 · 通常含少量升水',
),
_channel(
'gold_ctf',
metal,
'周大福金店',
ExchangeChannelKind.retail,
1238.00,
'品牌零售挂牌参考',
'含工费与品牌溢价 · 以门店为准',
),
_channel(
'gold_lfx',
metal,
'老凤祥金店',
ExchangeChannelKind.retail,
1248.00,
'品牌零售挂牌参考',
'含工费与品牌溢价 · 以门店为准',
),
_channel(
'gold_td',
metal,
'黄金 T+D',
ExchangeChannelKind.td,
919.50,
'SGE 递延参考',
'交易品种参考 · 非实物购买价',
),
_channel(
'gold_recycle',
metal,
'回收参考',
ExchangeChannelKind.recycle,
quote.spotPrice * recycle,
'材料价值 × 回收折扣',
'实际以门店检测为准',
),
],
MetalType.platinum => [
_channel(
'platinum_spot',
metal,
'铂金现货',
ExchangeChannelKind.spot,
384.20,
'国际盘换算参考',
'材料价值口径 · 非饰品零售价',
),
_channel(
'platinum_retail',
metal,
'铂金饰品',
ExchangeChannelKind.retail,
498.00,
'零售挂牌参考',
'含工费与品牌溢价',
),
_channel(
'platinum_recycle',
metal,
'回收参考',
ExchangeChannelKind.recycle,
quote.spotPrice * recycle,
'材料价值 × 回收折扣',
'实际以门店检测为准',
),
],
MetalType.silver => [
_channel(
'silver_spot',
metal,
'白银现货',
ExchangeChannelKind.spot,
15.75,
'上海银现货',
'材料价值口径 · 非饰品零售价',
),
_channel(
'silver_retail',
metal,
'白银饰品',
ExchangeChannelKind.retail,
42.00,
'零售挂牌参考',
'含工费与品牌溢价',
),
_channel(
'silver_recycle',
metal,
'回收参考',
ExchangeChannelKind.recycle,
quote.spotPrice * recycle,
'材料价值 × 回收折扣',
'实际以门店检测为准',
),
],
};
}
ExchangeChannel _channel(
String id,
MetalType metal,
String name,
ExchangeChannelKind kind,
double price,
String source,
String hint,
) {
return ExchangeChannel(
id: id,
metal: metal,
name: name,
kind: kind,
pricePerGram: price,
source: source,
updatedAt: _updatedAt,
hint: hint,
);
}
}