flyzto 2 nedēļas atpakaļ
vecāks
revīzija
eae3aff403

+ 1 - 1
server/models/GamesPs.js

@@ -35,7 +35,7 @@ const PS_IOR_KEYS = [
 ];
 
 const IOR_KEYS_TYPE = {
-  A: 1, L: 1,
+  A: 1, L: 1, R: 1,
   D: 2, K: 2,
 }
 

+ 0 - 217
web/apps/web-antd/src/views/match/components/match_card_bak.vue

@@ -1,217 +0,0 @@
-<script setup>
-const parseEventKey = (key) => {
-  if (key == 'm') {
-    return '独赢';
-  }
-  else if (key?.startsWith('wm')) {
-    const ratio = key.split('_')[1];
-    return `净胜 ${ratio}`;
-  }
-  else if (key?.startsWith('ou')) {
-    const ratio = key.split('_')[1];
-    return `大/小 ${ratio}`;
-  }
-  else if (key?.startsWith('ot')) {
-    const ratio = key.split('_')[1];
-    return `进球数 ${ratio}`;
-  }
-  return key;
-}
-defineProps({
-  eventId: {
-    type: Number,
-    required: true
-  },
-  platform: {
-    type: String,
-    required: true
-  },
-  leagueName: {
-    type: String,
-    required: true
-  },
-  teamHomeName: {
-    type: String,
-    required: true
-  },
-  teamAwayName: {
-    type: String,
-    required: true
-  },
-  dateTime: {
-    type: String,
-    required: true
-  },
-  events: {
-    type: Array,
-    required: true
-  },
-  matchNumStr: {
-    type: String,
-    required: false
-  },
-  selected: {
-    type: Array,
-    required: false
-  },
-  stage: {
-    type: String,
-    required: false
-  },
-  retime: {
-    type: String,
-    required: false
-  },
-  score: {
-    type: String,
-    required: false
-  }
-})
-</script>
-
-<template>
-  <div class="match-card">
-    <div class="card-header">
-      <div class="league-name"><strong v-if="stage && platform == 'ps'">[{{ stage }}<span v-if="retime">&nbsp;{{ retime }}</span>]</strong>{{ leagueName }}</div>
-      <div class="date-time">{{ dateTime }}</div>
-    </div>
-    <div class="team-name">
-      <span class="home-name">{{ teamHomeName }}</span>
-      <em v-if="stage">{{ score }}</em><em v-else>VS</em>
-      <span class="away-name">{{ teamAwayName }}</span>
-    </div>
-    <div class="events-list" :class="{'list-row2': events.length <= 2}">
-      <table>
-        <tr v-for="item in events">
-          <th>{{ parseEventKey(item[0]) }}</th>
-          <td>
-            <span :class="{'selected': selected.includes(item[1]?.key)}">{{ item[1]?.value ? item[1].value : '-' }}</span>
-            <em v-if="item[1]?.origin">{{ item[1].origin }}</em>
-          </td>
-          <td>
-            <span :class="{'selected': selected.includes(item[2]?.key)}">{{ item[2]?.value ? item[2].value : '-' }}</span>
-            <em v-if="item[2]?.origin">{{ item[2].origin }}</em>
-          </td>
-          <td>
-            <span :class="{'selected': selected.includes(item[3]?.key)}">{{ item[3]?.value ? item[3].value : '-' }}</span>
-            <em v-if="item[3]?.origin">{{ item[3].origin }}</em>
-          </td>
-        </tr>
-      </table>
-    </div>
-  </div>
-</template>
-
-<style lang="scss" scoped>
-.match-card {
-  display: flex;
-  flex-direction: column;
-  padding: 20px;
-}
-.card-header {
-  display: flex;
-  height: 30px;
-  align-items: center;
-  justify-content: space-between;
-  .league-name {
-    font-size: 16px;
-    strong {
-      margin-right: 4px;
-      font-weight: normal;
-      color: hsl(var(--destructive));
-    }
-  }
-  .date-time {
-    font-size: 12px;
-    color: hsl(var(--foreground) / 0.7);
-  }
-}
-.team-name {
-  display: flex;
-  align-items: center;
-  font-size: 14px;
-  .disabled & {
-    display: none;
-  }
-  span, em {
-    display: block;
-  }
-  span {
-    flex: 1;
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    &:first-child {
-      text-align: left;
-    }
-    &:last-child {
-      text-align: right;
-    }
-  }
-  em {
-    margin: 0 10px;
-    font-style: normal;
-    color: #ff9d4a;
-  }
-  .home-name {
-    color: hsl(var(--primary));
-  }
-  .away-name {
-    color: hsl(var(--destructive));
-  }
-}
-.events-list {
-  margin-top: 10px;
-  .disabled & {
-    display: none;
-  }
-  table {
-    width: 100%;
-    border-collapse: collapse;
-    border-spacing: 0;
-    table-layout: fixed;
-    th, td {
-      padding: 5px;
-      border: 1px solid hsl(var(--border));
-      text-align: center;
-    }
-    th {
-      width: 80px;
-      font-weight: normal;
-    }
-    td {
-      width: calc((100% - 64px) / 2);
-      font-size: 0;
-    }
-    span {
-      display: inline-block;
-      height: 20px;
-      padding: 0 5px;
-      line-height: 20px;
-      vertical-align: middle;
-      font-size: 14px;
-      &.selected {
-        border-radius: 4px;
-        background-color: hsl(var(--primary));
-        color: hsl(var(--primary-foreground));
-      }
-    }
-    em {
-      display: block;
-      height: 18px;
-      margin-top: -3px;
-      line-height: 18px;
-      font-style: normal;
-      font-size: 12px;
-      color: hsl(var(--foreground) / 0.5);
-    }
-  }
-  &.list-row2 {
-    table {
-      th, td {
-        height: 45px;
-      }
-    }
-  }
-}
-</style>

+ 10 - 1
web/apps/web-antd/src/views/match/solutions/index.vue

@@ -20,6 +20,7 @@ const updateTimer = ref(null);
 const minProfitRate = ref(2);
 const marketType = ref(-1);
 const dataType = ref(0);
+const showLower = ref(true);
 const searchValue = ref('');
 const updateLoaderHide = ref(null);
 
@@ -55,7 +56,7 @@ const getSolutions = async () => {
     const sk = searchValue.value.trim();
     const win_min = !!sk ? -99999 : minProfitRate.value * 100;
     const with_events = true;
-    const show_lower = true;
+    const show_lower = showLower.value;
     const data = await requestClient.get('/pstery/get_games_solutions', { params: { win_min, mk, tp, sk, with_events, show_lower } });
     return data;
   }
@@ -184,6 +185,14 @@ watch(dataType, (newVal) => {
   }, 1000);
 });
 
+watch(showLower, (newVal) => {
+  clearTimeout(updateTimer.value);
+  updateTimer.value = setTimeout(() => {
+    setLocalStorage('showLower', newVal);
+    updateSolutions();
+  }, 1000);
+});
+
 onMounted(() => {
   loopActive.value = true;
   const min_win_rate = getLocalStorage('minProfitRate');

+ 0 - 664
web/apps/web-antd/src/views/match/solutions/index_bak.vue

@@ -1,664 +0,0 @@
-<script setup>
-import { requestClient } from '#/api/request';
-import { Button, message, Form, InputNumber, RadioGroup, Radio, Drawer } from 'ant-design-vue';
-import { ref, reactive, computed, watch, onMounted, onUnmounted } from 'vue';
-import dayjs from 'dayjs';
-
-import MatchCard from '../components/match_card.vue';
-
-import { useContentsPositionStore } from '@vben/stores';
-const contentsPositionStore = useContentsPositionStore();
-
-const solutions = ref([]);
-const markCount = ref({ all: 0, rollball: 0, today: 0, early: 0 });
-const selectedSolutions = reactive([]);
-const totalProfit = ref({});
-const loopActive = ref(false);
-const loopTimer = ref(null);
-const updateTimer = ref(null);
-const minProfitRate = ref(2);
-const marketType = ref(-1);
-const updateLoaderHide = ref(null);
-
-const totalProfitVisible = ref(false);
-
-const fixFloat = (number, x = 2) => {
-  return parseFloat(number.toFixed(x));
-}
-
-const headerStyle = computed(() => {
-  return {
-    position: contentsPositionStore.position,
-    top: contentsPositionStore.top,
-    left: contentsPositionStore.left,
-    width: contentsPositionStore.width,
-    paddingLeft: contentsPositionStore.paddingLeft,
-  }
-});
-
-// const totalProfitValue = computed(() => {
-//   const { profit = {}, preSolution = {}, subSolution = {}, gamesEvents = {} } = totalProfit.value;
-//   const sol1 = formatSolution(preSolution, gamesEvents);
-//   const sol2 = formatSolution(subSolution, gamesEvents);
-
-//   const psInfo = [];
-//   const outPreSol = [];
-//   const outSubSol = [];
-
-//   const solutions = [sol1, sol2].filter(item => item);
-//   solutions.forEach((item, index) => {
-//     const { sol: { ps_index }, cpr } = item;
-//     const newCpr = [...cpr];
-//     const ps_info = newCpr.splice(ps_index, 1);
-//     psInfo.push({ ...ps_info[0] });
-//     newCpr.forEach((c, i) => {
-//       let side = '';
-//       if (ps_index == 0) {
-//         if (i == 0) {
-//           side = "B"
-//         }
-//         else {
-//           side = "M";
-//         }
-//       }
-//       else if (ps_index == 1) {
-//         if (i == 0) {
-//           side = "A";
-//         }
-//         else {
-//           side = "M";
-//         }
-//       }
-//       else {
-//         if (i == 0) {
-//           side = "A";
-//         }
-//         else {
-//           side = "B";
-//         }
-//       }
-//       if (index == 0) {
-//         outPreSol.push({ ...c, g: profitInfo[`gold${side}${index+1}`] });
-//       }
-//       else {
-//         outSubSol.push({ ...c, g: profitInfo[`gold${side}${index+1}`] });
-//       }
-//     })
-//   });
-
-//   return { solutions, profit: profitInfo, psInfo, outPreSol, outSubSol };
-// });
-
-const solutionsList = computed(() => {
-  const startTimestamp = selectedSolutions[0]?.timestamp ?? 0;
-  return solutions.value.map(item => {
-    const selected = selectedSolutions.findIndex(sol => sol.sid === item.sid) >= 0;
-    const disabled = false && !selected && (item.info.ps.timestamp < startTimestamp + 1000 * 60 * 60 * 2);
-    const { sol: { inner_base, win_average } } = item;
-    const win_average_rate = fixFloat(win_average / inner_base * 100);
-    const currentSol = { ...item.sol, win_average_rate };
-    return { ...item, sol: currentSol, selected, disabled };
-  });
-});
-
-const getSolutions = async () => {
-  try {
-    const win_min = minProfitRate.value * 100;
-    const mk = marketType.value;
-    const with_events = true;
-    const data = await requestClient.get('/pstery/get_solutions', { params: { win_min, mk, with_events } });
-    return data;
-  }
-  catch (error) {
-    console.error('Failed to fetch solutions:', error);
-    message.error('获取中单方案失败');
-    return [];
-  }
-}
-
-const calcTotalProfit = async () => {
-  const sids = selectedSolutions.map(item => item.sid);
-  try {
-    const totalProfit = await requestClient.post('/pstery/calc_total_profit', [...sids]);
-    return totalProfit;
-  }
-  catch (error) {
-    console.error('Failed to calc total profit:', error);
-    message.error('计算综合利润失败');
-    return {};
-  }
-}
-
-const parseIorKey = (iorKey) => {
-  const [, type, accept, side, , ratioString] = iorKey.match(/^ior_(r|ou|m|wm|ot|os)(a?)(h|c|n)?(_([\d-]+))?$/);
-  let ratio = 0;
-  if (type === 'ot' || type === 'os') {
-    ratio = ratioString;
-  }
-  else if (ratioString) {
-    ratio = `${ratioString[0]}.${ratioString.slice(1)}` * (accept ? 1 : -1);
-  }
-  return { type, side, ratio };
-}
-
-const PS_IOR_KEYS = [
-  ['0', 'ior_mh', 'ior_mn', 'ior_mc'],
-  ['-1', 'ior_rh_15', 'ior_wmh_1', 'ior_rac_05'],
-  ['-2', 'ior_rh_25', 'ior_wmh_2', 'ior_rac_15'],
-  ['+1', 'ior_rah_05', 'ior_wmc_1', 'ior_rc_15'],
-  ['+2', 'ior_rah_15', 'ior_wmc_2', 'ior_rc_25'],
-  // ['0-1', 'ior_ot_0', 'ior_os_0-1', 'ior_ot_1'],
-  // ['2-3', 'ior_ot_2', 'ior_os_2-3', 'ior_ot_3'],
-  ['ot_1', '-', 'ior_ot_1', '-'],
-  ['ot_2', '-', 'ior_ot_2', '-'],
-  ['ot_3', '-', 'ior_ot_3', '-'],
-  ['ot_4', '-', 'ior_ot_4', '-'],
-  ['ot_5', '-', 'ior_ot_5', '-'],
-  ['ot_6', '-', 'ior_ot_6', '-'],
-  ['ot_7', '-', 'ior_ot_7', '-'],
-];
-
-const formatPsEvents = (events) => {
-  return PS_IOR_KEYS.map(([label, ...keys]) => {
-    const match = keys.map(key => ({
-      key,
-      value: events[key]?.v ?? 0,
-      origin: events[key]?.r
-    }));
-    return {
-      label,
-      match
-    };
-  })
-  // .filter(item => item.match.every(entry => entry.value !== 0))
-  .map(({label, match}) => [label, ...match]);
-}
-
-// const rivalIor = (ior) => {
-//   const map = {
-//     "ior_rh": "ior_rac",
-//     "ior_rc": "ior_rah",
-//     "ior_rac": "ior_rh",
-//     "ior_rah": "ior_rc",
-//     "ior_wmh": "ior_wmc",
-//     "ior_wmc": "ior_wmh",
-//     "ior_wmh_2": "ior_wmc_2",
-//     "ior_wmc_2": "ior_wmh_2"
-//   };
-//   const iorInfos = ior.split('_');
-//   const iorStart = iorInfos.slice(0, 2).join('_');
-//   if (!map[iorStart]) {
-//     return ior;
-//   }
-//   return `${map[iorStart]}_${iorInfos[2]}`;
-// }
-
-const formatEvents = (events, cprKeys) => {
-  const eventsMap = {};
-  Object.keys(events).forEach(key => {
-    const { type, side, ratio } = parseIorKey(key);
-    let ratioKey, index;
-    if (type === 'r') {
-      if (side === 'h') {
-        ratioKey = ratio;
-        index = 0;
-      }
-      else if (side === 'c') {
-        ratioKey = -ratio;
-        index = 2;
-      }
-    }
-    else if (type === 'm') {
-      ratioKey = 'm';
-      if (side == 'h') {
-        index = 0;
-      }
-      else if (side == 'c') {
-        index = 2;
-      }
-      else {
-        index = 1;
-      }
-    }
-    else if (type === 'wm') {
-      ratioKey = `wm_${Math.abs(ratio)}`;
-      if (side === 'h') {
-        index = 0;
-      }
-      else if (side === 'c') {
-        index = 2;
-      }
-    }
-    else if (type === 'ou') {
-      ratioKey = `ou_${Math.abs(ratio)}`;
-      if (side === 'c') {
-        index = 0;
-      }
-      else if (side === 'h') {
-        index = 2;
-      }
-    }
-    // else if (type === 'os') {
-    //   ratioKey = ratio;
-    //   index = 1;
-    // }
-    else if (type === 'ot') {
-      ratioKey = `ot_${ratio}`;
-      index = 1;
-      // switch (ratio) {
-      //   case '0':
-      //     ratioKey = '0-1';
-      //     index = 0;
-      //     break;
-      //   case '1':
-      //     ratioKey = '0-1';
-      //     index = 2;
-      //     break;
-      //   case '2':
-      //     ratioKey = '2-3';
-      //     index = 0;
-      //     break;
-      //   case '3':
-      //     ratioKey = '2-3';
-      //     index = 2;
-      //     break;
-      // }
-    }
-    if (typeof (ratioKey) == 'number') {
-      if (ratioKey > 0) {
-        ratioKey = `+${ratioKey}`;
-      }
-      // else if (ratioKey === 0) {
-      //   ratioKey = '-0';
-      // }
-      else {
-        ratioKey = `${ratioKey}`;
-      }
-    }
-
-    if (!ratioKey) {
-      return;
-    }
-
-    if (!eventsMap[ratioKey]) {
-      eventsMap[ratioKey] = new Array(3).fill(undefined);
-    }
-
-    const value = events[key]?.v ?? 0;
-    const origin = events[key]?.r;
-    eventsMap[ratioKey][index] = { key, value, origin };
-  });
-
-  return Object.keys(eventsMap).sort((a, b) => a.localeCompare(b)).map(key => {
-    return [key, ...eventsMap[key]];
-  });
-}
-
-const formatSolution = (solution, eventsList) => {
-  const { cpr, info } = solution;
-  if (!cpr || !info) {
-    return null;
-  }
-
-  const cprKeys = cpr.map(item => item.k);
-
-  const psEvents = eventsList.ps?.[info.ps.eventId] ?? {};
-  const obEvents = eventsList.ob?.[info.ob.eventId] ?? {};
-  const hgEvents = eventsList.hg?.[info.hg.eventId] ?? {};
-
-  info.ps.events = formatPsEvents(psEvents);
-  info.ob.events = formatEvents(obEvents, cprKeys);
-  info.hg.events = formatEvents(hgEvents, cprKeys);
-
-  info.ps.dateTime = dayjs(info.ps.timestamp).format('YYYY-MM-DD HH:mm:ss');
-  info.ob.dateTime = dayjs(info.ob.timestamp).format('YYYY-MM-DD HH:mm:ss');
-  info.hg.dateTime = dayjs(info.hg.timestamp).format('YYYY-MM-DD HH:mm:ss');
-
-  cpr.forEach(item => {
-    const { k, p } = item;
-    if (!info[p]['selected']) {
-      info[p]['selected'] = [];
-    }
-    info[p]['selected'].push(k);
-  });
-
-  return solution;
-}
-
-const updateSolutions = async (showLoading=false) => {
-  clearTimeout(loopTimer.value);
-  if (showLoading && !updateLoaderHide.value) {
-    updateLoaderHide.value = message.loading('数据加载中...', 0);
-  }
-  getSolutions()
-  .then(({ solutions: solutionsList, gamesEvents: eventsList, mkCount: mkCountData }) => {
-    solutions.value = solutionsList?.map(solution => formatSolution(solution, eventsList)) ?? [];
-    markCount.value = mkCountData;
-  })
-  .catch(error => {
-    console.error('Failed to update solutions:', error);
-    message.error('获取中单方案失败');
-  })
-  .finally(() => {
-    updateLoaderHide.value?.();
-    updateLoaderHide.value = null;
-    if (loopActive.value) {
-      loopTimer.value = setTimeout(() => {
-        updateSolutions();
-      }, 1000 * 10);
-    }
-  });
-}
-
-const showTotalProfit = async () => {
-  totalProfit.value = await calcTotalProfit();
-  totalProfitVisible.value = true;
-  const { profit } = totalProfit.value;
-  console.log('profit', profit);
-};
-
-const closeTotalProfit = () => {
-  totalProfitVisible.value = false;
-  selectedSolutions.length = 0;
-  totalProfit.value = {};
-};
-
-const toggleSolution = (sid, timestamp) => {
-  const findIndex = selectedSolutions.findIndex(item => item.sid === sid);
-  if (findIndex >= 0) {
-    selectedSolutions.splice(findIndex, 1);
-  }
-  else if (selectedSolutions.length < 2) {
-    selectedSolutions.push({ sid, timestamp });
-  }
-  else {
-    selectedSolutions.splice(1, 1, { sid, timestamp });
-  }
-  if (selectedSolutions.length == 2) {
-    showTotalProfit();
-  }
-}
-
-const setLocalStorage = (key, value) => {
-  localStorage.setItem(key, JSON.stringify(value));
-}
-
-const getLocalStorage = (key) => {
-  const value = localStorage.getItem(key);
-  return value ? JSON.parse(value) : null;
-}
-
-watch(minProfitRate, (newVal) => {
-  clearTimeout(updateTimer.value);
-  updateTimer.value = setTimeout(() => {
-    setLocalStorage('minProfitRate', newVal);
-    updateSolutions();
-  }, 1000);
-});
-
-watch(marketType, (newVal) => {
-  if (!updateLoaderHide.value) {
-    updateLoaderHide.value = message.loading('数据更新中...', 0);
-  }
-  clearTimeout(updateTimer.value);
-  updateTimer.value = setTimeout(() => {
-    setLocalStorage('marketType', newVal);
-    updateSolutions();
-  }, 1000);
-});
-
-onMounted(() => {
-  loopActive.value = true;
-  const min_win_rate = getLocalStorage('minProfitRate');
-  const mk = getLocalStorage('marketType');
-  if (min_win_rate !== null) {
-    minProfitRate.value = min_win_rate;
-  }
-  if (mk !== null) {
-    marketType.value = mk;
-  }
-  setTimeout(() => {
-    updateSolutions(true);
-  }, 100);
-});
-
-onUnmounted(() => {
-  loopActive.value = false;
-});
-
-
-</script>
-
-<template>
-  <div class="solution-container">
-
-    <div class="contents-header transition-all duration-200" :style="headerStyle">
-      <div class="solution-options">
-        <Form layout="inline" class="sol-opt-container">
-          <Form.Item label="盘口类型" class="sol-opt-item">
-            <RadioGroup v-model:value="marketType">
-              <Radio :value="-1">全部({{ markCount.all ?? 0 }})</Radio>
-              <Radio :value="2">滚球({{ markCount.rollball ?? 0 }})</Radio>
-              <Radio :value="1">今日({{ markCount.today ?? 0 }})</Radio>
-              <Radio :value="0">早盘({{ markCount.early ?? 0 }})</Radio>
-            </RadioGroup>
-          </Form.Item>
-          <Form.Item label="最小利润率(%)" class="sol-opt-item">
-            <InputNumber style="width: 60px" size="small" max="100" min="-100" step="0.1" placeholder="最小利润率(%)" v-model:value="minProfitRate"/>
-          </Form.Item>
-        </Form>
-      </div>
-      <div class="solution-header">
-        <span>PS</span>
-        <span>OB</span>
-        <span>HG</span>
-        <em>利润</em>
-      </div>
-    </div>
-
-    <div class="solution-list">
-      <div class="solution-item"
-        v-for="{ sid, sol: { win_average_rate, win_profit_rate, cross_type }, info: { ps, ob, hg }, selected, disabled } in solutionsList" :key="sid"
-        :class="{ 'selected': selected, 'disabled': disabled }">
-        <MatchCard platform="ps" :eventId="ps.eventId" :leagueName="ps.leagueName" :teamHomeName="ps.teamHomeName"
-          :teamAwayName="ps.teamAwayName" :dateTime="ps.dateTime" :eventInfo="ps.eventInfo" :events="ps.events ?? []"
-          :matchNumStr="ps.matchNumStr" :selected="ps.selected ?? []" :stage="ps.stage" :retime="ps.retime" :score="ps.score" />
-
-        <MatchCard platform="ob" :eventId="ob.eventId" :leagueName="ob.leagueName" :teamHomeName="ob.teamHomeName"
-          :teamAwayName="ob.teamAwayName" :dateTime="ob.dateTime" :events="ob.events ?? []"
-          :selected="ob.selected ?? []" :stage="ob.stage" :retime="ob.retime" :score="ob.score" />
-
-        <MatchCard platform="hg" :eventId="hg.eventId" :leagueName="hg.leagueName" :teamHomeName="hg.teamHomeName"
-          :teamAwayName="hg.teamAwayName" :dateTime="hg.dateTime" :events="hg.events ?? []"
-          :selected="hg.selected ?? []" :stage="hg.stage" :retime="hg.retime" :score="hg.score" />
-
-        <div class="solution-profit" @click="!disabled && toggleSolution(sid, ps.timestamp)">
-          <p>{{ win_average_rate }}%</p>
-          <p>{{ win_profit_rate }}%</p>
-          <p>{{ cross_type }}</p>
-        </div>
-      </div>
-    </div>
-    <div class="list-empty" v-if="!solutionsList.length">暂无数据</div>
-
-    <!-- <Drawer
-      title="综合利润方案"
-      placement="bottom"
-      height="600"
-      :visible="totalProfitVisible"
-      @close="closeTotalProfit"
-    >
-      <div class="solution-total-profit" v-if="totalProfitValue.solutions.length">
-        <div class="solution-item"
-          v-for="{ sid, info: { ps, ob, hg } } in totalProfitValue.solutions" :key="sid">
-          <MatchCard platform="ps" :eventId="ps.eventId" :leagueName="ps.leagueName" :teamHomeName="ps.teamHomeName"
-            :teamAwayName="ps.teamAwayName" :dateTime="ps.dateTime" :eventInfo="ps.eventInfo" :events="ps.events ?? []"
-            :matchNumStr="ps.matchNumStr" :selected="ps.selected ?? []" />
-
-          <MatchCard platform="ob" :eventId="ob.eventId" :leagueName="ob.leagueName" :teamHomeName="ob.teamHomeName"
-            :teamAwayName="ob.teamAwayName" :dateTime="ob.dateTime" :events="ob.events ?? []"
-            :selected="ob.selected ?? []" />
-
-          <MatchCard platform="hg" :eventId="hg.eventId" :leagueName="hg.leagueName" :teamHomeName="hg.teamHomeName"
-            :teamAwayName="hg.teamAwayName" :dateTime="hg.dateTime" :events="hg.events ?? []"
-            :selected="hg.selected ?? []" />
-        </div>
-      </div>
-      <div class="profit-info">
-        <table>
-          <tr>
-            <th></th>
-            <td>PS</td>
-            <td colspan="2">第一场</td>
-            <td colspan="2">第二场</td>
-          </tr>
-          <tr>
-            <th>赔率</th>
-            <td>{{ totalProfitValue.psInfo[0]?.v }}: {{ totalProfitValue.psInfo[1]?.v }}</td>
-            <td>{{ totalProfitValue.outPreSol[0]?.p }}: {{ totalProfitValue.outPreSol[0]?.v }}</td>
-            <td>{{ totalProfitValue.outPreSol[1]?.p }}: {{ totalProfitValue.outPreSol[1]?.v }}</td>
-            <td>{{ totalProfitValue.outSubSol[0]?.p }}: {{ totalProfitValue.outSubSol[0]?.v }}</td>
-            <td>{{ totalProfitValue.outSubSol[1]?.p }}: {{ totalProfitValue.outSubSol[1]?.v }}</td>
-          </tr>
-          <tr>
-            <th>下注</th>
-            <td>{{ psOptions.bet }}</td>
-            <td>{{ totalProfitValue.outPreSol[0]?.g }}</td>
-            <td>{{ totalProfitValue.outPreSol[1]?.g }}</td>
-            <td>{{ totalProfitValue.outSubSol[0]?.g }}</td>
-            <td>{{ totalProfitValue.outSubSol[1]?.g }}</td>
-          </tr>
-          <tr>
-            <th>利润</th>
-            <td>{{ totalProfitValue.profit.win_ps }}</td>
-            <td colspan="2">{{ totalProfitValue.profit.win_target }}</td>
-            <td colspan="2">{{ totalProfitValue.profit.win_target }}</td>
-          </tr>
-        </table>
-      </div>
-    </Drawer> -->
-
-  </div>
-</template>
-
-<style lang="scss" scoped>
-.contents-header {
-  position: fixed;
-  top: 0;
-  left: 0;
-  z-index: 201;
-  width: 100%;
-  border-bottom: 1px solid hsl(var(--border));
-  background-color: hsl(var(--background));
-}
-
-.solution-options {
-  position: relative;
-  display: flex;
-  align-items: center;
-  padding: 5px 20px;
-  border-bottom: 1px solid hsl(var(--border));
-}
-
-.sol-opt-container {
-  flex-grow: 1;
-  justify-content: space-between;
-}
-
-.sol-opt-item:last-child {
-  margin-inline-end: 0 !important;
-}
-
-.solution-header {
-  position: relative;
-  display: flex;
-  align-items: center;
-  height: 30px;
-  padding: 0 20px;
-  span,
-  em {
-    display: block;
-    text-align: center;
-  }
-
-  span {
-    flex: 1;
-  }
-
-  em {
-    width: 80px;
-    font-style: normal;
-  }
-}
-
-.solution-container {
-  padding-top: 74px;
-}
-
-.solution-item {
-  display: flex;
-  .match-card {
-    flex: 1;
-  }
-}
-
-.solution-list {
-  padding: 20px;
-  overflow: hidden;
-
-  .solution-item {
-    border-radius: 10px;
-    background-color: hsl(var(--card));
-
-    &.selected {
-      background-color: hsl(var(--primary) / 0.15);
-    }
-
-    &.disabled {
-      opacity: 0.5;
-      cursor: not-allowed;
-    }
-
-    &:not(:last-child) {
-      margin-bottom: 20px;
-    }
-
-    .match-card {
-      border-right: 1px solid hsl(var(--border));
-    }
-
-    .solution-profit {
-      display: flex;
-      flex-direction: column;
-      width: 80px;
-      align-items: center;
-      justify-content: center;
-    }
-  }
-}
-
-.profit-info {
-  table {
-    width: 100%;
-    border-collapse: collapse;
-    border-spacing: 0;
-    table-layout: fixed;
-    th, td {
-      height: 30px;
-      border: 1px solid hsl(var(--border));
-      text-align: center;
-    }
-    th {
-      width: 64px;
-      font-weight: normal;
-    }
-  }
-}
-
-.list-empty {
-  text-align: center;
-  padding: 10px;
-  font-size: 18px;
-  color: hsl(var(--foreground) / 0.7);
-}
-</style>