feat: 在AI仪表板中添加高优先级投标展示

This commit is contained in:
dmy
2026-01-13 16:34:32 +08:00
parent 5024d2c502
commit 7f36e014e6
3 changed files with 51 additions and 4 deletions

View File

@@ -53,6 +53,7 @@
<DashboardAI <DashboardAI
v-if="activeIndex === '2'" v-if="activeIndex === '2'"
:bids="bids" :bids="bids"
:high-priority-bids="highPriorityBids"
/> />
<Bids <Bids

View File

@@ -7,6 +7,38 @@
获取 AI 推荐 获取 AI 推荐
</el-button> </el-button>
</div> </div>
<el-row :gutter="20">
<el-col :span="24">
<el-card class="box-card" shadow="hover">
<template #header>
<div class="card-header" @click="toggleHighPriority" style="cursor: pointer;">
<span>High Priority Bids</span>
<div style="display: flex; align-items: center; gap: 10px;">
<el-tag type="danger">Top 10</el-tag>
<el-icon :style="{ transform: highPriorityCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)', transition: 'transform 0.3s' }">
<ArrowDown />
</el-icon>
</div>
</div>
</template>
<el-collapse-transition>
<div v-show="!highPriorityCollapsed">
<el-table :data="highPriorityBids" style="width: 100%" size="small">
<el-table-column prop="title" label="Title">
<template #default="scope">
<a :href="scope.row.url" target="_blank">{{ scope.row.title }}</a>
</template>
</el-table-column>
<el-table-column prop="source" label="Source" width="240" />
<el-table-column prop="publishDate" label="Date" width="120">
<template #default="scope">{{ formatDate(scope.row.publishDate) }}</template>
</el-table-column>
</el-table>
</div>
</el-collapse-transition>
</el-card>
</el-col>
</el-row>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h3 style="margin: 0;">选择日期范围</h3> <h3 style="margin: 0;">选择日期范围</h3>
<div style="display: flex; gap: 10px;"> <div style="display: flex; gap: 10px;">
@@ -114,7 +146,7 @@
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import axios from 'axios' import axios from 'axios'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { MagicStick, Loading, InfoFilled, List } from '@element-plus/icons-vue' import { MagicStick, Loading, InfoFilled, List, ArrowDown } from '@element-plus/icons-vue'
interface AIRecommendation { interface AIRecommendation {
@@ -127,6 +159,7 @@ interface AIRecommendation {
interface Props { interface Props {
bids: any[] bids: any[]
highPriorityBids: any[]
} }
const props = defineProps<Props>() const props = defineProps<Props>()
@@ -137,6 +170,7 @@ const dateRange = ref<[string, string] | null>(null)
const showAllBids = ref(false) const showAllBids = ref(false)
const bidsLoading = ref(false) const bidsLoading = ref(false)
const bidsByDateRange = ref<any[]>([]) const bidsByDateRange = ref<any[]>([])
const highPriorityCollapsed = ref(false)
// 从 localStorage 加载保存的日期范围 // 从 localStorage 加载保存的日期范围
const loadSavedDateRange = () => { const loadSavedDateRange = () => {
@@ -155,6 +189,18 @@ watch(dateRange, (newDateRange) => {
localStorage.setItem('dashboardAI_dateRange', JSON.stringify(newDateRange)) localStorage.setItem('dashboardAI_dateRange', JSON.stringify(newDateRange))
}, { deep: true }) }, { deep: true })
// 切换 High Priority Bids 的折叠状态
const toggleHighPriority = () => {
highPriorityCollapsed.value = !highPriorityCollapsed.value
}
// 监听 highPriorityBids当没有数据时自动折叠
watch(() => props.highPriorityBids, (newBids) => {
if (newBids.length === 0) {
highPriorityCollapsed.value = true
}
}, { immediate: true })
// 从数据库加载最新的 AI 推荐 // 从数据库加载最新的 AI 推荐
const loadLatestRecommendations = async () => { const loadLatestRecommendations = async () => {
try { try {

View File

@@ -88,7 +88,7 @@ export const ChngCrawler = {
await page.waitForNavigation({ waitUntil: 'networkidle2' }); await page.waitForNavigation({ waitUntil: 'networkidle2' });
logger.log('Clicking search result...'); logger.log('Clicking search result...');
await page.screenshot({ path: 'bing.png' }); // await page.screenshot({ path: 'bing.png' });
const firstResultSelector = '#b_results .b_algo h2 a'; const firstResultSelector = '#b_results .b_algo h2 a';
await page.waitForSelector(firstResultSelector); await page.waitForSelector(firstResultSelector);
@@ -99,7 +99,7 @@ export const ChngCrawler = {
const newPage = await newTarget.page(); const newPage = await newTarget.page();
if (newPage) { if (newPage) {
await newPage.screenshot({ path: 'newPage.png' }); // await newPage.screenshot({ path: 'newPage.png' });
await page.close(); await page.close();
page = newPage; page = newPage;
if (username && password) { if (username && password) {
@@ -125,7 +125,7 @@ export const ChngCrawler = {
// PAUSE 15 SECONDS as requested // PAUSE 15 SECONDS as requested
logger.log('Pausing 15 seconds before looking for "采购专栏"...'); logger.log('Pausing 15 seconds before looking for "采购专栏"...');
await new Promise(r => setTimeout(r, 15000)); await new Promise(r => setTimeout(r, 15000));
await page.screenshot({ path: 'huaneng.png' }); // await page.screenshot({ path: 'huaneng.png' });
logger.log('Looking for "采购专栏" link...'); logger.log('Looking for "采购专栏" link...');
await page.waitForFunction(() => { await page.waitForFunction(() => {