itemId = $itemId; $this->itemName = $itemName; parent::__construct(); } /** * 初始化卡片内容 * * @return void */ protected function init() { parent::init(); $title = $this->itemName ? "{$this->itemName} - 价格趋势" : '价格趋势'; $this->title($title); $this->height(400); $this->chartHeight(300); // 设置下拉选项 $this->dropdown([ '7' => '最近 7 天', '14' => '最近 14 天', '30' => '最近 30 天', '90' => '最近 90 天', ]); } /** * 处理请求 * * @param Request $request * @return mixed|void */ public function handle(Request $request) { $days = (int) $request->get('option', 7); $itemId = $this->itemId ?? $request->get('item_id'); $currencyType = $request->get('currency_type', FUND_CURRENCY_TYPE::ZUANSHI->value); $data = $this->getMultiLinePriceTrendData($days, $itemId, $currencyType); // 卡片内容 - 显示最新收盘价 $latestPrice = $data['latest_close_price'] ?? 0; $priceChange = $data['price_change'] ?? 0; $changePercent = $data['change_percent'] ?? 0; $changeText = $priceChange >= 0 ? "+{$changePercent}%" : "{$changePercent}%"; $this->withContent(number_format($latestPrice, 5), $changeText); // 添加详细信息 $dataCount = count($data['dates']); $this->subTitle("数据点: {$dataCount} | 时间范围: {$days}天"); // 图表数据 - 多线图 $this->withMultiLineChart($data); } /** * 获取多线价格趋势数据 * * @param int $days * @param int|null $itemId * @param int $currencyType * @return array */ protected function getMultiLinePriceTrendData(int $days, ?int $itemId = null, int $currencyType = 2): array { $startDate = now()->subDays($days - 1)->toDateString(); $endDate = now()->toDateString(); if ($itemId) { // 如果指定了商品ID,显示该商品的价格趋势 $trends = MexDailyPriceTrend::whereBetween('trade_date', [$startDate, $endDate]) ->where('currency_type', $currencyType) ->where('item_id', $itemId) ->orderBy('trade_date') ->get(); } else { // 如果没有指定商品ID,显示所有商品的平均价格趋势 $trends = MexDailyPriceTrend::selectRaw(' trade_date, AVG(open_price) as avg_open_price, AVG(close_price) as avg_close_price, AVG(high_price) as avg_high_price, AVG(low_price) as avg_low_price ') ->whereBetween('trade_date', [$startDate, $endDate]) ->where('currency_type', $currencyType) ->groupBy('trade_date') ->orderBy('trade_date') ->get(); } $dates = []; $openPrices = []; $closePrices = []; $highPrices = []; $lowPrices = []; $latestClosePrice = 0; $firstClosePrice = 0; foreach ($trends as $trend) { // 确保 trade_date 被正确解析为 Carbon 对象 $tradeDate = $trend->trade_date instanceof \Carbon\Carbon ? $trend->trade_date : \Carbon\Carbon::parse($trend->trade_date); $dates[] = $tradeDate->format('m-d'); if ($itemId) { // 单个商品的数据 $openPrices[] = (float) $trend->open_price; $closePrices[] = (float) $trend->close_price; $highPrices[] = (float) $trend->high_price; $lowPrices[] = (float) $trend->low_price; if (!$firstClosePrice) { $firstClosePrice = (float) $trend->close_price; } $latestClosePrice = (float) $trend->close_price; } else { // 平均价格数据 $openPrices[] = (float) $trend->avg_open_price; $closePrices[] = (float) $trend->avg_close_price; $highPrices[] = (float) $trend->avg_high_price; $lowPrices[] = (float) $trend->avg_low_price; if (!$firstClosePrice) { $firstClosePrice = (float) $trend->avg_close_price; } $latestClosePrice = (float) $trend->avg_close_price; } } // 计算价格变化 $priceChange = $latestClosePrice - $firstClosePrice; $changePercent = $firstClosePrice > 0 ? round(($priceChange / $firstClosePrice) * 100, 2) : 0; return [ 'dates' => $dates, 'open_prices' => $openPrices, 'close_prices' => $closePrices, 'high_prices' => $highPrices, 'low_prices' => $lowPrices, 'latest_close_price' => $latestClosePrice, 'price_change' => $priceChange, 'change_percent' => $changePercent, ]; } /** * 设置多线图表数据 * * @param array $data * @return $this */ public function withMultiLineChart(array $data) { $series = [ [ 'name' => '最低价', 'data' => $data['low_prices'], ], [ 'name' => '最高价', 'data' => $data['high_prices'], ], [ 'name' => '收盘价', 'data' => $data['close_prices'], ], ]; // 定义不同线条的颜色 $colors = [ '#52c41a', // 绿色 - 最低价 '#f5222d', // 红色 - 最高价 '#1890ff', // 蓝色 - 收盘价 ]; return $this->chart([ 'series' => $series, 'colors' => $colors, 'xaxis' => [ 'categories' => $data['dates'], 'labels' => [ 'show' => true, ], ], 'legend' => [ 'show' => true, 'position' => 'bottom', 'horizontalAlign' => 'center' ], 'tooltip' => [ 'shared' => true, 'intersect' => false, ], ]); } /** * 设置图表数据(兼容旧方法) * * @param array $data * @param array $categories * @return $this */ public function withChart(array $data, array $categories) { return $this->chart([ 'series' => [ [ 'name' => '平均价格', 'data' => $data, ], ], 'xaxis' => [ 'categories' => $categories, ], ]); } }