RMO-Front/src/components/QuoteRequestModal.vue

174 lines
6.4 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 v-if="quoteModal.isOpen" class="quote-modal-overlay" @click="handleClose">
<div class="quote-modal" @click.stop>
<div class="quote-modal-header">
<h2 class="quote-modal-title">获取报价</h2>
<button type="button" class="quote-modal-close" @click="handleClose" aria-label="关闭">×</button>
</div>
<div class="quote-modal-body">
<p class="quote-modal-desc">请填写或上传报价所需资料,生成报价后可向各保司获取精准报价。</p>
<section class="quote-section">
<h3 class="quote-section-title">1. 报价需提交的资料</h3>
<div class="quote-fill-mode">
<label class="quote-radio">
<input type="radio" name="fillMode" :checked="fillMode === 'manual'" @change="fillMode = 'manual'" />
<span>手动填写</span>
</label>
<label class="quote-radio">
<input type="radio" name="fillMode" :checked="fillMode === 'upload'" @change="fillMode = 'upload'" />
<span>上传项目方案AI 识别填充)</span>
</label>
</div>
<div v-if="fillMode === 'upload'" class="form-group">
<label>上传项目方案</label>
<input type="file" accept=".pdf,.doc,.docx" @change="handleUploadChange" />
<p v-if="uploading" class="form-hint">AI 识别中…</p>
</div>
<div class="quote-form-grid">
<div class="form-group">
<label>项目方案编号</label>
<input v-model="formData.projectCode" type="text" placeholder="如CT-2025-001" />
</div>
<div class="form-group">
<label>项目标题</label>
<input v-model="formData.projectTitle" type="text" placeholder="试验方案标题" />
</div>
<div class="form-group">
<label>申办者</label>
<input v-model="formData.sponsor" type="text" placeholder="申办者名称" />
</div>
<div class="form-group">
<label>项目分期</label>
<input v-model="formData.projectPhase" type="text" placeholder="如I期、II期、III期" />
</div>
</div>
</section>
<section class="quote-section">
<h3 class="quote-section-title">2. 生成报价</h3>
<button
type="button"
class="btn btn-primary"
:disabled="!canGenerateQuote || generatingQuote"
@click="handleGenerateQuote"
>
{{ generatingQuote ? 'AI 生成中…' : '生成报价' }}
</button>
<div v-if="aiQuote" class="quote-ai-result">
<pre>{{ aiQuote }}</pre>
</div>
</section>
<section class="quote-section">
<h3 class="quote-section-title">3. 获取精准报价</h3>
<p class="quote-section-desc">系统将把报价资料整合后以邮件发送至各保司,保司回复后将经临研安审核并回显到报价页面。</p>
<button
type="button"
class="btn btn-primary"
:disabled="!aiQuote || sendingPrecise"
@click="handleGetPreciseQuote"
>
{{ sendingPrecise ? '发送中…' : preciseSent ? '已发送至各保司' : '获取精准报价' }}
</button>
<div v-if="preciseSent" class="quote-precise-tip">
<p>已向各保司发送询价邮件,保司将回复至 rmo@vdano.com审核通过后将展示在报价页面。</p>
<button
v-if="auth.isAuthenticated"
type="button"
class="btn btn-secondary btn-sm"
@click="goToQuotes"
>
前往报价页面查看
</button>
</div>
</section>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { useQuoteModalStore } from '@/stores/quoteModal'
import { useAuthStore } from '@/stores/auth'
const router = useRouter()
const quoteModal = useQuoteModalStore()
const auth = useAuthStore()
const fillMode = ref<'manual' | 'upload'>('manual')
const formData = ref({
projectCode: '',
projectTitle: '',
sponsor: '',
projectPhase: '',
})
const uploading = ref(false)
const aiQuote = ref<string | null>(null)
const generatingQuote = ref(false)
const preciseSent = ref(false)
const sendingPrecise = ref(false)
const canGenerateQuote = computed(() =>
formData.value.projectCode.trim() !== '' &&
formData.value.projectTitle.trim() !== '' &&
formData.value.sponsor.trim() !== '' &&
formData.value.projectPhase.trim() !== ''
)
function handleClose() {
quoteModal.closeQuoteModal()
formData.value = { projectCode: '', projectTitle: '', sponsor: '', projectPhase: '' }
aiQuote.value = null
preciseSent.value = false
}
async function handleUploadChange(e: Event) {
const input = e.target as HTMLInputElement
const file = input.files?.[0]
if (!file) return
uploading.value = true
await new Promise(r => setTimeout(r, 1200))
formData.value = {
projectCode: 'CT-2025-' + Math.floor(1000 + Math.random() * 9000),
projectTitle: file.name.replace(/\.[^.]+$/, '') || '临床试验方案',
sponsor: '示例申办者',
projectPhase: 'I期',
}
uploading.value = false
}
async function handleGenerateQuote() {
if (!canGenerateQuote.value) return
generatingQuote.value = true
await new Promise(r => setTimeout(r, 1500))
aiQuote.value =
`基于当前项目信息(${formData.value.projectTitle}${formData.value.projectPhase})的预估报价:\n` +
'· 建议每人保额80120 万\n· 每次事故限额400600 万\n· 预估年保费区间:约 1.1 万1.4 万元\n实际以各保司精准报价为准'
generatingQuote.value = false
}
async function handleGetPreciseQuote() {
if (!auth.isAuthenticated) {
if (window.confirm('获取精准报价需先登录,是否前往登录?')) {
handleClose()
router.push({ path: '/login', query: { from: '/dashboard/project-quotes' } })
}
return
}
if (!aiQuote.value) return
sendingPrecise.value = true
await new Promise(r => setTimeout(r, 1000))
preciseSent.value = true
sendingPrecise.value = false
}
function goToQuotes() {
handleClose()
router.push('/dashboard/project-quotes')
}
</script>
<style scoped>
@import './QuoteRequestModal.css';
</style>