442 lines
12 KiB
Vue
442 lines
12 KiB
Vue
<template>
|
||
<div class="data-source-selection">
|
||
<el-card v-loading="loading">
|
||
<template #header>
|
||
<div class="card-header">
|
||
<span>选择数据源 - {{ inquiry.requestNumber }}</span>
|
||
<el-button @click="goBack" text>返回</el-button>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- 关键词展示 -->
|
||
<el-alert
|
||
title="已确认的关键词"
|
||
type="success"
|
||
:closable="false"
|
||
style="margin-bottom: 20px;"
|
||
>
|
||
<div class="keywords-display">
|
||
<el-tag
|
||
v-if="keywords.drugNameChinese"
|
||
type="success"
|
||
size="large"
|
||
style="margin-right: 10px;"
|
||
>
|
||
{{ keywords.drugNameChinese }}
|
||
</el-tag>
|
||
<el-tag
|
||
v-if="keywords.drugNameEnglish"
|
||
type="primary"
|
||
size="large"
|
||
style="margin-right: 10px;"
|
||
>
|
||
{{ keywords.drugNameEnglish }}
|
||
</el-tag>
|
||
<el-tag
|
||
v-if="keywords.requestItem"
|
||
type="warning"
|
||
size="large"
|
||
style="margin-right: 10px;"
|
||
>
|
||
{{ keywords.requestItem }}
|
||
</el-tag>
|
||
<el-tag
|
||
v-for="(tag, index) in keywords.additionalKeywords"
|
||
:key="index"
|
||
type="info"
|
||
size="large"
|
||
style="margin-right: 10px;"
|
||
>
|
||
{{ tag }}
|
||
</el-tag>
|
||
</div>
|
||
</el-alert>
|
||
|
||
<!-- 数据源选择 -->
|
||
<div class="source-selection">
|
||
<h3 style="margin-bottom: 20px;">请选择需要检索的数据源:</h3>
|
||
|
||
<el-form :model="form" label-position="top">
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-card
|
||
shadow="hover"
|
||
:class="{ 'source-card': true, 'selected': form.searchInternalData }"
|
||
@click="toggleSource('searchInternalData')"
|
||
>
|
||
<div class="source-content">
|
||
<el-checkbox
|
||
v-model="form.searchInternalData"
|
||
size="large"
|
||
@click.stop
|
||
/>
|
||
<div class="source-info">
|
||
<div class="source-title">
|
||
<el-icon :size="24" color="#409EFF"><Document /></el-icon>
|
||
<span>内部数据</span>
|
||
</div>
|
||
<div class="source-desc">
|
||
企业自有研究数据、历史回复记录、内部文献等
|
||
</div>
|
||
<el-tag size="small" type="primary">企业数据</el-tag>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
|
||
<el-col :span="12">
|
||
<el-card
|
||
shadow="hover"
|
||
:class="{ 'source-card': true, 'selected': form.searchKnowledgeBase }"
|
||
@click="toggleSource('searchKnowledgeBase')"
|
||
>
|
||
<div class="source-content">
|
||
<el-checkbox
|
||
v-model="form.searchKnowledgeBase"
|
||
size="large"
|
||
@click.stop
|
||
/>
|
||
<div class="source-info">
|
||
<div class="source-title">
|
||
<el-icon :size="24" color="#67C23A"><FolderOpened /></el-icon>
|
||
<span>知识库</span>
|
||
</div>
|
||
<div class="source-desc">
|
||
已整理的企业知识库数据、专家意见等
|
||
</div>
|
||
<el-tag size="small" type="success">推荐</el-tag>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
|
||
<el-col :span="12">
|
||
<el-card
|
||
shadow="hover"
|
||
:class="{ 'source-card': true, 'selected': form.searchCnki }"
|
||
@click="toggleSource('searchCnki')"
|
||
>
|
||
<div class="source-content">
|
||
<el-checkbox
|
||
v-model="form.searchCnki"
|
||
size="large"
|
||
@click.stop
|
||
/>
|
||
<div class="source-info">
|
||
<div class="source-title">
|
||
<el-icon :size="24" color="#E6A23C"><Reading /></el-icon>
|
||
<span>知网 (CNKI)</span>
|
||
</div>
|
||
<div class="source-desc">
|
||
中国知网学术文献数据库
|
||
</div>
|
||
<el-tag size="small" type="warning">中文文献</el-tag>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
|
||
<el-col :span="12">
|
||
<el-card
|
||
shadow="hover"
|
||
:class="{ 'source-card': true, 'selected': form.searchClinicalTrials }"
|
||
@click="toggleSource('searchClinicalTrials')"
|
||
>
|
||
<div class="source-content">
|
||
<el-checkbox
|
||
v-model="form.searchClinicalTrials"
|
||
size="large"
|
||
@click.stop
|
||
/>
|
||
<div class="source-info">
|
||
<div class="source-title">
|
||
<el-icon :size="24" color="#F56C6C"><Experiment /></el-icon>
|
||
<span>ClinicalTrials.gov</span>
|
||
</div>
|
||
<div class="source-desc">
|
||
美国国家医学图书馆临床试验数据库
|
||
</div>
|
||
<el-tag size="small" type="danger">临床试验</el-tag>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
|
||
<!-- 选择提示 -->
|
||
<el-alert
|
||
v-if="!hasSelectedSource"
|
||
title="请至少选择一个数据源"
|
||
type="warning"
|
||
:closable="false"
|
||
style="margin-top: 20px;"
|
||
/>
|
||
|
||
<el-alert
|
||
v-else
|
||
:title="`已选择 ${selectedCount} 个数据源`"
|
||
type="info"
|
||
:closable="false"
|
||
style="margin-top: 20px;"
|
||
>
|
||
<div>将在以下数据源中进行检索:{{ selectedSourcesText }}</div>
|
||
</el-alert>
|
||
|
||
<!-- 操作按钮 -->
|
||
<div class="action-buttons">
|
||
<el-button
|
||
type="primary"
|
||
size="large"
|
||
@click="handleConfirm"
|
||
:loading="confirming"
|
||
:disabled="!hasSelectedSource"
|
||
>
|
||
确认并开始检索
|
||
</el-button>
|
||
<el-button size="large" @click="handleSelectAll">
|
||
全选
|
||
</el-button>
|
||
<el-button size="large" @click="handleClearAll">
|
||
清空
|
||
</el-button>
|
||
<el-button size="large" @click="goBack">
|
||
返回
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, onMounted } from 'vue'
|
||
import { useRouter, useRoute } from 'vue-router'
|
||
import { getInquiryDetail, selectDataSources, performSearch } from '@/api/inquiry'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { Document, FolderOpened, Reading, Experiment } from '@element-plus/icons-vue'
|
||
|
||
const router = useRouter()
|
||
const route = useRoute()
|
||
|
||
const loading = ref(false)
|
||
const confirming = ref(false)
|
||
const inquiry = ref({})
|
||
const keywords = ref({})
|
||
|
||
const form = reactive({
|
||
searchInternalData: false,
|
||
searchKnowledgeBase: true, // 默认选中推荐项
|
||
searchCnki: false,
|
||
searchClinicalTrials: true // 默认选中推荐项
|
||
})
|
||
|
||
const hasSelectedSource = computed(() => {
|
||
return form.searchInternalData ||
|
||
form.searchKnowledgeBase ||
|
||
form.searchCnki ||
|
||
form.searchClinicalTrials
|
||
})
|
||
|
||
const selectedCount = computed(() => {
|
||
let count = 0
|
||
if (form.searchInternalData) count++
|
||
if (form.searchKnowledgeBase) count++
|
||
if (form.searchCnki) count++
|
||
if (form.searchClinicalTrials) count++
|
||
return count
|
||
})
|
||
|
||
const selectedSourcesText = computed(() => {
|
||
const sources = []
|
||
if (form.searchInternalData) sources.push('内部数据')
|
||
if (form.searchKnowledgeBase) sources.push('知识库')
|
||
if (form.searchCnki) sources.push('知网')
|
||
if (form.searchClinicalTrials) sources.push('ClinicalTrials.gov')
|
||
return sources.join('、')
|
||
})
|
||
|
||
onMounted(() => {
|
||
loadDetail()
|
||
})
|
||
|
||
const loadDetail = async () => {
|
||
loading.value = true
|
||
try {
|
||
const id = route.params.id
|
||
const data = await getInquiryDetail(id)
|
||
inquiry.value = data
|
||
|
||
// 解析关键词
|
||
if (data.keywords) {
|
||
try {
|
||
keywords.value = JSON.parse(data.keywords)
|
||
} catch (error) {
|
||
console.error('解析关键词失败', error)
|
||
}
|
||
}
|
||
|
||
// 如果已有数据源选择,恢复状态
|
||
if (data.searchInternalData !== null) {
|
||
form.searchInternalData = data.searchInternalData || false
|
||
}
|
||
if (data.searchKnowledgeBase !== null) {
|
||
form.searchKnowledgeBase = data.searchKnowledgeBase || false
|
||
}
|
||
if (data.searchCnki !== null) {
|
||
form.searchCnki = data.searchCnki || false
|
||
}
|
||
if (data.searchClinicalTrials !== null) {
|
||
form.searchClinicalTrials = data.searchClinicalTrials || false
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('加载详情失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const toggleSource = (source) => {
|
||
form[source] = !form[source]
|
||
}
|
||
|
||
const handleSelectAll = () => {
|
||
form.searchInternalData = true
|
||
form.searchKnowledgeBase = true
|
||
form.searchCnki = true
|
||
form.searchClinicalTrials = true
|
||
}
|
||
|
||
const handleClearAll = () => {
|
||
form.searchInternalData = false
|
||
form.searchKnowledgeBase = false
|
||
form.searchCnki = false
|
||
form.searchClinicalTrials = false
|
||
}
|
||
|
||
const handleConfirm = async () => {
|
||
if (!hasSelectedSource.value) {
|
||
ElMessage.warning('请至少选择一个数据源')
|
||
return
|
||
}
|
||
|
||
ElMessageBox.confirm(
|
||
`确认在以下数据源中检索:${selectedSourcesText.value}?`,
|
||
'确认检索',
|
||
{
|
||
confirmButtonText: '开始检索',
|
||
cancelButtonText: '取消',
|
||
type: 'info'
|
||
}
|
||
).then(async () => {
|
||
confirming.value = true
|
||
try {
|
||
// 保存数据源选择
|
||
await selectDataSources(inquiry.value.id, form)
|
||
ElMessage.success('数据源选择已保存')
|
||
|
||
// 开始检索
|
||
await performSearch(inquiry.value.id)
|
||
ElMessage.success('检索已完成,正在跳转到结果页面...')
|
||
|
||
// 跳转到检索结果页面
|
||
router.push(`/inquiry/${inquiry.value.id}/search-results`)
|
||
} catch (error) {
|
||
ElMessage.error('操作失败: ' + (error.message || '未知错误'))
|
||
} finally {
|
||
confirming.value = false
|
||
}
|
||
}).catch(() => {
|
||
// 用户取消
|
||
})
|
||
}
|
||
|
||
const goBack = () => {
|
||
router.back()
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.data-source-selection {
|
||
width: 100%;
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.keywords-display {
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.source-selection {
|
||
padding: 20px 0;
|
||
}
|
||
|
||
.source-card {
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.source-card:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
.source-card.selected {
|
||
border: 2px solid #409EFF;
|
||
background-color: #ecf5ff;
|
||
}
|
||
|
||
.source-content {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 15px;
|
||
}
|
||
|
||
.source-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.source-title {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin-bottom: 10px;
|
||
color: #303133;
|
||
}
|
||
|
||
.source-desc {
|
||
color: #606266;
|
||
line-height: 1.6;
|
||
margin-bottom: 10px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.action-buttons {
|
||
margin-top: 30px;
|
||
text-align: center;
|
||
}
|
||
|
||
.action-buttons .el-button {
|
||
margin: 0 10px;
|
||
}
|
||
|
||
:deep(.el-checkbox__label) {
|
||
display: none;
|
||
}
|
||
</style>
|
||
|
||
|
||
|
||
|
||
|
||
|