- 新增审核可选择审核重点(字典驱动,合同/简历各一套)并填写附加要求自由文本, 两者合并为 requirements 随请求提交,后端追加进系统提示词,让模型按需聚焦 - 审核项存字典 oa_ai_review_item_contract / oa_ai_review_item_resume, 用户可在系统管理→字典管理自行增删审核项(无需改代码),各预置10项 - oa_ai_review 增加 requirements 列(已应用到生产库),落库留痕;详情页展示 - 前后端贯通:analyze / analyzeStream 均新增 requirements 参数 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
114 lines
4.4 KiB
Vue
114 lines
4.4 KiB
Vue
<template>
|
|
<div class="app-container ai-review-detail" v-loading="loading">
|
|
<el-card shadow="never" class="panel">
|
|
<div slot="header" class="hd">
|
|
<div class="hd-left">
|
|
<el-button size="small" icon="el-icon-back" @click="goBack">返回列表</el-button>
|
|
<span class="title"><i class="el-icon-document-checked" /> 审核详情</span>
|
|
</div>
|
|
<div v-if="info" class="hd-right">
|
|
<el-tag size="small" :type="info.reviewType === 'contract' ? 'warning' : 'success'">
|
|
{{ info.reviewType === 'contract' ? '合同审核' : '简历审核' }}
|
|
</el-tag>
|
|
<el-tag v-if="info.reviewType === 'resume' && info.matchScore != null"
|
|
size="small" type="success" effect="dark">匹配度 {{ info.matchScore }}</el-tag>
|
|
<el-tag v-if="info.reviewType === 'contract' && info.riskLevel"
|
|
size="small" :type="riskTagType(info.riskLevel)" effect="dark">{{ info.riskLevel }}风险</el-tag>
|
|
</div>
|
|
</div>
|
|
|
|
<el-descriptions v-if="info" :column="3" size="small" border class="meta">
|
|
<el-descriptions-item label="文件名">
|
|
<span>{{ info.fileName }}</span>
|
|
<el-button v-if="info.fileUrl" type="text" size="mini" icon="el-icon-download"
|
|
style="margin-left:8px" @click="downloadFile">下载原件</el-button>
|
|
</el-descriptions-item>
|
|
<el-descriptions-item v-if="info.reviewType === 'resume'" label="目标岗位">
|
|
{{ info.position || '—' }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="模型">{{ info.model || '—' }}</el-descriptions-item>
|
|
<el-descriptions-item label="审核时间">{{ info.createTime }}</el-descriptions-item>
|
|
<el-descriptions-item label="审核人">{{ info.createBy || '—' }}</el-descriptions-item>
|
|
<el-descriptions-item v-if="info.requirements" label="审核重点 / 附加要求" :span="3">
|
|
<span style="white-space: pre-wrap">{{ info.requirements }}</span>
|
|
</el-descriptions-item>
|
|
</el-descriptions>
|
|
|
|
<div v-if="info" class="md-body" v-html="renderedMd" />
|
|
</el-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getAiReview } from '@/api/oa/aiReview'
|
|
const marked = require('marked')
|
|
|
|
export default {
|
|
name: 'OaAiReviewDetail',
|
|
data () {
|
|
return {
|
|
loading: true,
|
|
info: null
|
|
}
|
|
},
|
|
computed: {
|
|
renderedMd () {
|
|
if (!this.info || !this.info.resultMd) return ''
|
|
try { return marked(this.info.resultMd) } catch (e) { return this.info.resultMd }
|
|
}
|
|
},
|
|
created () {
|
|
marked.setOptions({ breaks: true })
|
|
const id = this.$route.params.id
|
|
if (id) this.load(id)
|
|
else this.loading = false
|
|
},
|
|
methods: {
|
|
load (id) {
|
|
this.loading = true
|
|
getAiReview(id).then(res => { this.info = res.data })
|
|
.finally(() => { this.loading = false })
|
|
},
|
|
goBack () {
|
|
this.$router.push('/hint/aiReview')
|
|
},
|
|
downloadFile () {
|
|
if (this.info && this.info.fileUrl) window.open(this.info.fileUrl, '_blank')
|
|
},
|
|
riskTagType (r) {
|
|
return r === '高' ? 'danger' : (r === '中' ? 'warning' : 'success')
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.ai-review-detail { padding: 10px; }
|
|
.panel { ::v-deep .el-card__header { padding: 10px 14px; } }
|
|
.hd { display: flex; justify-content: space-between; align-items: center;
|
|
.hd-left { display: flex; align-items: center; gap: 12px;
|
|
.title { font-weight: 600; font-size: 14px; color: #303133; i { color: #409eff; margin-right: 4px; } }
|
|
}
|
|
.hd-right { display: flex; align-items: center; gap: 8px; }
|
|
}
|
|
.meta { margin-bottom: 16px; }
|
|
|
|
.md-body {
|
|
font-size: 14px; color: #2c3e50; line-height: 1.8; padding: 4px 6px;
|
|
::v-deep {
|
|
h1, h2, h3 { color: #303133; margin: 18px 0 10px; font-weight: 600; }
|
|
h1 { font-size: 19px; } h2 { font-size: 16px; border-left: 3px solid #409eff; padding-left: 8px; }
|
|
h3 { font-size: 14px; }
|
|
p { margin: 8px 0; }
|
|
ul, ol { padding-left: 22px; margin: 8px 0; }
|
|
li { margin: 4px 0; }
|
|
strong { color: #c0392b; }
|
|
code { background: #f4f7fa; padding: 1px 5px; border-radius: 3px; font-size: 13px; color: #e6a23c; }
|
|
table { border-collapse: collapse; width: 100%; margin: 10px 0; }
|
|
th, td { border: 1px solid #ebeef5; padding: 6px 10px; font-size: 13px; }
|
|
th { background: #f5f7fa; }
|
|
blockquote { border-left: 3px solid #dcdfe6; padding-left: 10px; color: #909399; margin: 8px 0; }
|
|
}
|
|
}
|
|
</style>
|