diff --git a/server/app/api/controller/MatchController.php b/server/app/api/controller/MatchController.php
index d94aef0..e026efa 100644
--- a/server/app/api/controller/MatchController.php
+++ b/server/app/api/controller/MatchController.php
@@ -533,7 +533,11 @@ class MatchController extends BaseApiController
$this->request->get('include_special/d', 0),
min(max($this->request->get('limit/d', 120), 1), 300),
$this->request->get('sport_type/d', 0),
- trim($this->request->get('league_name/s', ''))
+ trim($this->request->get('league_name/s', '')),
+ false,
+ trim($this->request->get('home_team/s', '')),
+ trim($this->request->get('away_team/s', '')),
+ trim($this->request->get('match_date/s', ''))
),
'platform_options' => $this->getOddsPlatformOptions(),
]);
@@ -565,7 +569,10 @@ class MatchController extends BaseApiController
int $limit,
int $sportType = 0,
string $leagueName = '',
- bool $worldCupEventOnly = false
+ bool $worldCupEventOnly = false,
+ string $homeTeam = '',
+ string $awayTeam = '',
+ string $matchDate = ''
): array {
$validShowTypes = ['live', 'today', 'early'];
@@ -601,6 +608,25 @@ class MatchController extends BaseApiController
->whereOr('match_time_text', 'like', $likeKeyword);
});
}
+ if ($homeTeam !== '') {
+ $query->where('home_team', 'like', '%' . addcslashes($homeTeam, '\\%_') . '%');
+ }
+ if ($awayTeam !== '') {
+ $query->where('away_team', 'like', '%' . addcslashes($awayTeam, '\\%_') . '%');
+ }
+ $matchDatePatterns = $this->buildOddsMatchDatePatterns($matchDate);
+ if (!empty($matchDatePatterns)) {
+ $query->where(function ($query) use ($matchDatePatterns) {
+ foreach ($matchDatePatterns as $index => $pattern) {
+ $likePattern = '%' . addcslashes($pattern, '\\%_') . '%';
+ if ($index === 0) {
+ $query->where('match_time_text', 'like', $likePattern);
+ } else {
+ $query->whereOr('match_time_text', 'like', $likePattern);
+ }
+ }
+ });
+ }
$rows = $query
->field('id,source_site,source_url,source_match_id,source_league_id,sport_type,show_type,odds_type,league_name,match_time_text,home_team,away_team,handicap_line,handicap_home_odds,handicap_away_odds,total_line,total_over_odds,total_under_odds,home_win_odds,draw_odds,away_win_odds,update_time')
@@ -734,6 +760,42 @@ class MatchController extends BaseApiController
return trim($matchTimeText);
}
+ private function buildOddsMatchDatePatterns(string $matchDate): array
+ {
+ $matchDate = trim($matchDate);
+ if ($matchDate === '') {
+ return [];
+ }
+
+ $normalized = str_replace('/', '-', $matchDate);
+ if (preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $normalized, $matches)) {
+ $year = (int)$matches[1];
+ $month = (int)$matches[2];
+ $day = (int)$matches[3];
+ return array_values(array_unique([
+ sprintf('%04d-%02d-%02d', $year, $month, $day),
+ sprintf('%04d/%02d/%02d', $year, $month, $day),
+ sprintf('%02d-%02d', $month, $day),
+ sprintf('%02d/%02d', $month, $day),
+ sprintf('%d-%d', $month, $day),
+ sprintf('%d/%d', $month, $day),
+ ]));
+ }
+
+ if (preg_match('/^(\d{1,2})-(\d{1,2})$/', $normalized, $matches)) {
+ $month = (int)$matches[1];
+ $day = (int)$matches[2];
+ return array_values(array_unique([
+ sprintf('%02d-%02d', $month, $day),
+ sprintf('%02d/%02d', $month, $day),
+ sprintf('%d-%d', $month, $day),
+ sprintf('%d/%d', $month, $day),
+ ]));
+ }
+
+ return [$matchDate];
+ }
+
private function buildTeamPairKey(string $homeTeam, string $awayTeam): string
{
$homeTeam = preg_replace('/\s+/u', '', trim($homeTeam));
diff --git a/uniapp/src/api/match.ts b/uniapp/src/api/match.ts
index 14fda00..646a85d 100644
--- a/uniapp/src/api/match.ts
+++ b/uniapp/src/api/match.ts
@@ -181,6 +181,9 @@ export function getMatchOdds(data?: {
show_type?: 'live' | 'today' | 'early'
source_site?: string
keyword?: string
+ home_team?: string
+ away_team?: string
+ match_date?: string
include_special?: number
limit?: number
}) {
diff --git a/uniapp/src/components/match-odds-detail/match-odds-detail.vue b/uniapp/src/components/match-odds-detail/match-odds-detail.vue
new file mode 100644
index 0000000..ae03741
--- /dev/null
+++ b/uniapp/src/components/match-odds-detail/match-odds-detail.vue
@@ -0,0 +1,345 @@
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+ 赔率加载中...
+
+
+
+
+
+
+ {{ platform.platform_name }}
+
+ {{ platform.show_type_text }}
+
+
+ {{ formatUpdateTime(platform.update_time) }}
+
+
+
+
+ {{ market.label }}
+ {{ market.line }}
+
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uniapp/src/packages_match/components/MatchCenterTabsPanel.vue b/uniapp/src/packages_match/components/MatchCenterTabsPanel.vue
index a8300bd..203f95b 100644
--- a/uniapp/src/packages_match/components/MatchCenterTabsPanel.vue
+++ b/uniapp/src/packages_match/components/MatchCenterTabsPanel.vue
@@ -248,11 +248,14 @@ type MatchCenterTab = 'schedule' | 'live' | 'odds'
type OddsShowType = '' | 'live' | 'today' | 'early'
type OddsPlatformOption = { key: string; label: string }
-const contentTabs: { key: MatchCenterTab; label: string }[] = [
+const showStandaloneOddsTab = false
+
+const allContentTabs: { key: MatchCenterTab; label: string }[] = [
{ key: 'schedule', label: '赛程' },
{ key: 'live', label: '直播' },
{ key: 'odds', label: '赔率' },
]
+const contentTabs = allContentTabs.filter((item) => showStandaloneOddsTab || item.key !== 'odds')
const oddsShowTypeOptions: { key: OddsShowType; label: string }[] = [
{ key: '', label: '全部盘口' },
diff --git a/uniapp/src/packages_match/components/WorldCupPanel.vue b/uniapp/src/packages_match/components/WorldCupPanel.vue
index 454a152..48bfd9e 100644
--- a/uniapp/src/packages_match/components/WorldCupPanel.vue
+++ b/uniapp/src/packages_match/components/WorldCupPanel.vue
@@ -381,7 +381,9 @@ const emit = defineEmits<{
(e: 'back'): void
}>()
-const tabs: { key: MainTab; label: string }[] = [
+const showStandaloneOddsTab = false
+
+const allTabs: { key: MainTab; label: string }[] = [
{ key: 'live', label: '直播' },
{ key: 'schedule', label: '比分和赛程' },
{ key: 'odds', label: '赔率' },
@@ -389,6 +391,7 @@ const tabs: { key: MainTab; label: string }[] = [
{ key: 'bracket', label: '对阵图' },
{ key: 'news', label: '新闻' }
]
+const tabs = allTabs.filter((item) => showStandaloneOddsTab || item.key !== 'odds')
const oddsShowTypeOptions: { key: OddsShowType; label: string }[] = [
{ key: '', label: '全部盘口' },
@@ -1042,8 +1045,10 @@ const initViewState = async () => {
activeTab.value = 'live'
} else if (legacyTab === 'schedule') {
activeTab.value = 'schedule'
- } else if (legacyTab === 'odds') {
+ } else if (legacyTab === 'odds' && showStandaloneOddsTab) {
activeTab.value = 'odds'
+ } else if (legacyTab === 'odds') {
+ activeTab.value = 'schedule'
} else if (legacyTab === 'rank' || legacyTab === 'standings') {
activeTab.value = 'rank'
rankingMode.value = 'standings'
diff --git a/uniapp/src/pages/match_detail/match_detail.vue b/uniapp/src/pages/match_detail/match_detail.vue
index 10afb06..8424b46 100644
--- a/uniapp/src/pages/match_detail/match_detail.vue
+++ b/uniapp/src/pages/match_detail/match_detail.vue
@@ -177,7 +177,7 @@
-
+
赔率信息
@@ -235,11 +235,18 @@
-->
-
+
比赛尚未开始
+
+
+
+
+
@@ -476,6 +483,7 @@