2025-10-29 15:17:26 +08:00

544 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- 搜索区域 -->
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="80px">
<el-form-item label="赛事编号" prop="matchNumStr">
<el-input v-model="queryParams.matchNumStr" placeholder="请输入赛事编号" clearable style="width: 240px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="联赛类型" prop="leagueAbbName">
<el-select v-model="queryParams.leagueAbbName" @change="handleQuery" style="width: 240px" clearable placeholder="请选择联赛类型">
<el-option
v-for="item in dataScopeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="标记状态" prop="flagStatus">
<el-select v-model="queryParams.flagStatus" @change="handleQuery" style="width: 240px" clearable placeholder="请选择标记状态">
<el-option
v-for="item in flagStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="时间">
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" style="width: 240px"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery" :loading="loading">查询</el-button>
<el-button icon="Refresh" @click="resetQuery" :loading="loading">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<!--loading-->
<div
v-if="loading"
v-loading="loading"
class="loading-page"
element-loading-text="正在加载..."
style="width: 100%; height: calc(100vh - 250px)"
></div>
<div v-else-if="pageList.length && !loading">
<!-- 表格数据 -->
<el-table v-loading="loading" :data="pageList">
<el-table-column label="赛事编号" prop="matchNumStr" />
<el-table-column label="联赛" prop="leagueAllName" :show-overflow-tooltip="true" />
<el-table-column label="主队" prop="homeTeamAllName" :show-overflow-tooltip="true" />
<el-table-column label="客队" prop="awayTeamAbbName" />
<el-table-column label="赛果" prop="matchId">
<template #default="scope">
<el-popover placement="bottom" :width="360">
<template #reference>
<el-button link type="primary" @dblclick="handleJumpLink(scope.row)">查看</el-button>
</template>
<template #default>
<div>
<el-table border :data="scope.row.matchResults">
<el-table-column label="游戏" prop="matchNumStr">
<template #default="item">
{{ item.row.codeName }}
</template>
</el-table-column>
<el-table-column label="开赛结果" prop="reportSatus">
<template #default="item">
<el-tag type="error">{{ item.row.combinationDesc }}</el-tag>
</template>
</el-table-column>
<el-table-column label="奖金" prop="matchNumStr">
<template #default="item">
{{ item.row.odds }}
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="AI预测" prop="matchId">
<template #default="scope">
<el-popover placement="bottom" :width="360">
<template #reference>
<el-button link type="primary">查看</el-button>
</template>
<template #default>
<div style="padding: 8px;">
<el-radio-group v-model="activeName" style="margin-bottom: 10px">
<el-radio-button value="FINYX_F">finyx-AI</el-radio-button>
<el-radio-button value="D3_F">D3-index</el-radio-button>
</el-radio-group>
<div v-show="activeName === 'FINYX_F'">
<el-table border :data="scope.row.farmatReportResults['FINYX_F']" :show-header="false">
<el-table-column>
<template #default="item">
{{ item.row.lable }}
</template>
</el-table-column>
<el-table-column>
<template #default="item">
{{ item.row.value || '-' }}
</template>
</el-table-column>
</el-table>
</div>
<div v-show="activeName === 'D3_F'">
<el-table border :data="scope.row.farmatReportResults['D3_F']" :show-header="false">
<el-table-column>
<template #default="item">
{{ item.row.lable }}
</template>
</el-table-column>
<el-table-column>
<template #default="item">
{{ item.row.value || '-' }}
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="结果标记" align="center" class-name="small-padding fixed-width" width="280">
<template #default="scope">
<el-button
v-show="showBtn(scope.row, 'FINYX_F')"
link
type="primary"
icon="Edit"
@click="openDialog(scope.row, 'FINYX_F')"
:class="[matchIdType.id === scope.row.matchId && matchIdType.type === 'FINYX_F' ? 'has-active' : '']"
>finyx-AI</el-button>
<el-button
v-show="showBtn(scope.row, 'D3_F')"
link
type="primary"
icon="Edit"
@click="openDialog(scope.row, 'D3_F')"
:class="[matchIdType.id === scope.row.matchId && matchIdType.type === 'D3_F' ? 'has-active' : '']"
>D3-index</el-button>
</template>
</el-table-column>
<el-table-column label="Finyx预测结果" width="300" align="center">
<el-table-column label="常" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'resultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="让" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'hhadResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="分" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'scoreResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="总" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'goalsResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="半" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'halfFullResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="亚" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'FINYX_F', 'asianHandicapFlag')]"></span>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="D3预测结果" width="300" align="center">
<el-table-column label="常" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'resultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="让" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'hhadResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="分" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'scoreResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="总" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'goalsResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="半" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'halfFullResultFlag')]"></span>
</template>
</el-table-column>
<el-table-column label="亚" width="50" align="center">
<template #default="scope">
<span :class="['icon-d3', tableColumnActive(scope.row, 'D3_F', 'asianHandicapFlag')]"></span>
</template>
</el-table-column>
</el-table-column>
</el-table>
<!-- 分页区域 -->
<pagination
:show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList" />
</div>
<lz-page-empty v-else-if="!loading" :type="'2'">
<lz-svg-icon icon-class="empty2" style="font-size: 312px;"/>
</lz-page-empty>
<!-- 修改对话框 -->
<el-dialog :title="dialogTitle" v-model="dialogOpen" width="600px" append-to-body>
<Prediction :data="dialogForm" type="edit" v-if="dialogOpen" @submit="submitForm" ref="editHadRef"/>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="OperationReport">
import { Info, infoSelectDistinctLeagueAbbNames, reportResultUpdate } from "@/api/tc/eventAnalysisReport"
import { jumpLink } from "@/utils/tc"
import { processMatchResults } from "@/utils/tc"
import Prediction from "@/views/operation/report/components/Prediction.vue"
import { ref } from "vue"
const router = useRouter()
const { proxy } = getCurrentInstance()
const pageList = ref([])
const loading = ref(false)
const showSearch = ref(true)
const total = ref(0)
const dateRange = ref([])
const editHadRef = ref(null)
const activeName = ref('FINYX_F')
const matchIdType = ref({ id: '', type: '' })
const dialogOpen = ref(false)
const dialogTitle = ref('标记')
const dialogForm = ref({})
/** 数据范围选项*/
const dataScopeOptions = ref([])
const flagStatusOptions = ref([
{ value: 1, label: '已标记' },
{ value: 0, label: '未标记' },
])
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
matchNumStr: undefined,
leagueAbbName: undefined,
flagStatus: undefined,
},
rules: {},
})
const { queryParams } = toRefs(data)
function tableColumnActive(row, modelType, key) {
// 检查row是否为空对象或缺少必要属性
if (!row || Object.keys(row).length === 0) {
return '';
}
// 确保reportResults存在且为数组
if (!row.reportResults || !Array.isArray(row.reportResults)) {
return '';
}
// 查找对应modelType的数据
const reportData = row.reportResults.find(item => item.modelType === modelType);
// 如果没有找到对应数据,返回空字符串
if (!reportData) {
return '';
}
// 根据key值获取对应字段的值并判断是否应该添加active类
const value = reportData[key];
if (value && value === '1') {
return 'table-column-active-1';
}
if (value && value === '0.5') {
return 'table-column-active-11';
}
if (value && value === '-1') {
return 'table-column-active-2';
}
if (value && value === '-0.5') {
return 'table-column-active-22';
}
return '4';
}
function rowPrediction(row, modelType) {
return row.reportResults && row.reportResults.find(el => el.modelType === modelType) || {}
}
function showBtn(row, type) {
// 判断reportResults是否存在不存在则返回false
if(!row.reportResults) {
return false
}
if(row.reportResults.find(el => el.modelType === type)) {
return true
}
return false
}
/** 导出按钮操作 */
function handleExport() {
// proxy.download("system/user/export", {
// ...queryParams.value,
// },`user_${new Date().getTime()}.xlsx`)
}
/** 提交表单 */
function submitForm() {
const data = editHadRef.value.getFormData()
reportResultUpdate(data).then(response => {
proxy.$message.success(response.msg)
getList()
}).finally(() => {
dialogOpen.value = false
})
}
/** 取消按钮 */
function cancel() {
dialogOpen.value = false
dialogForm.value = {}
}
function openDialog(row, type='') {
if(row && row.reportResults && type){
dialogForm.value = row.reportResults.find(el => el.modelType === type)
dialogOpen.value = true
dialogTitle.value = ' 标记 ' + row.matchNumStr + ' ' + type+ '模型'
matchIdType.value = { id: row.matchId, type: type }
}
}
/** 获取联赛类型 */
function getLeagueAbbNames() {
infoSelectDistinctLeagueAbbNames().then(response => {
dataScopeOptions.value = response.rows ? response.rows.map(item => ({ value: item, label: item })) : []
})
}
/** 跳转链接 */
function handleJumpLink(row) {
jumpLink(row.matchId, 1)
}
function reportResultsModelType(arr){
const res = {}
arr.forEach(item => {
res[item.modelType] = [
{
lable: '主队',
value: item.homeTeamName,
key: 'result'
},
{
lable: '客队',
value: item.awayTeamName,
key: 'result'
},
{
lable: '胜平负',
value: item.result,
key: 'result'
},
{
lable: '让分胜平负',
value: item.hhadResult,
key: 'hhadResult'
},
{
lable: '比分',
value: item.scoreResult,
key: 'scoreResult'
},
{
lable: '进球数',
value: item.goalsResult,
key: 'goalsResult'
},
{
lable: '半全场',
value: item.halfFullResult,
key: 'halfFullResult'
},
{
lable: '亚盘',
value: item.asianHandicap,
key: 'asianHandicap'
}
]
})
return res;
}
function farmatReportResults(list) {
const res = list.map(item => ({
...item,
farmatReportResults: item.reportResults ? reportResultsModelType(item.reportResults): {}
}));
return res;
}
/** 查询列表 */
function getList() {
loading.value = true
const data = { ...queryParams.value }
if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
data.beginTime = dateRange.value[0]
data.endTime = dateRange.value[1]
} else {
data.beginTime = undefined
data.endTime = undefined
}
Info(data).then(response => {
const res = response.rows.map(item => ({
...item,
matchResults: item.matchResults ? processMatchResults(item.matchResults): null
}));
// 格式化reportResults
pageList.value = farmatReportResults(res)
total.value = response.total
}).finally(() => {
loading.value = false
})
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = []
proxy.resetForm("queryRef")
handleQuery()
matchIdType.value = { id: '', type: '' }
}
onMounted(() => {
// 联赛类型
getLeagueAbbNames()
// 列表查询
getList()
})
</script>
<style scoped lang="scss">
.icon-d3 {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #fff;
border: 2px solid #3067EF;
box-sizing: border-box;
}
.table-column-active-1 {
background-color: #f56c6c;
border-color: #f56c6c;
}
.table-column-active-11 {
background-color: #f56c6c;
border-color: #f56c6c;
position: relative;
}
.table-column-active-11::after {
content: '';
display: block;
width: 20px;
height: 10px;
background-color: #fff;
position: absolute;
top: 50%;
left: -2px;
}
.table-column-active-2 {
background-color: #333;
border-color: #333;
}
.table-column-active-22 {
background-color: #333;
border-color: #333;
position: relative;
}
.table-column-active-22::after {
content: '';
display: block;
width: 20px;
height: 10px;
background-color: #fff;
position: absolute;
top: 50%;
left: -2px;
}
</style>