AI审核支持微调/自定义审核重点
- 新增审核可选择审核重点(字典驱动,合同/简历各一套)并填写附加要求自由文本, 两者合并为 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>
This commit is contained in:
@@ -30,6 +30,23 @@
|
||||
: '评估候选人,分析与目标岗位的匹配度、优势、短板与面试建议。' }}
|
||||
支持 PDF / Word(.doc/.docx),≤ 20MB。
|
||||
</div>
|
||||
|
||||
<!-- 审核重点 / 附加要求 -->
|
||||
<div class="req-area">
|
||||
<div class="req-line">
|
||||
<span class="req-label">审核重点</span>
|
||||
<el-checkbox-group v-model="checkedItems" size="mini" :disabled="streaming" class="req-items">
|
||||
<el-checkbox v-for="it in itemOptions" :key="it.value" :label="it.label" border>{{ it.label }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<span class="req-tip">可在「系统管理→字典管理」增删审核项</span>
|
||||
</div>
|
||||
<div class="req-line">
|
||||
<span class="req-label">附加要求</span>
|
||||
<el-input v-model="extraText" type="textarea" :rows="2" :disabled="streaming"
|
||||
class="req-extra" maxlength="500" show-word-limit
|
||||
placeholder="可补充本次审核的特殊关注点,例如:重点核查付款比例是否对我方有利、是否有自动续约陷阱…" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-row :gutter="12" class="body">
|
||||
@@ -96,6 +113,7 @@
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { getDicts } from '@/api/system/dict/data'
|
||||
const marked = require('marked')
|
||||
|
||||
export default {
|
||||
@@ -107,6 +125,11 @@ export default {
|
||||
rawFile: null,
|
||||
fileName: '',
|
||||
|
||||
// 审核重点(字典) + 附加要求(自由文本)
|
||||
itemDicts: { contract: [], resume: [] },
|
||||
checkedItems: [],
|
||||
extraText: '',
|
||||
|
||||
streaming: false,
|
||||
done: false,
|
||||
reasoning: '',
|
||||
@@ -124,15 +147,37 @@ export default {
|
||||
computed: {
|
||||
renderedMd () {
|
||||
try { return marked(this.content) } catch (e) { return this.content }
|
||||
},
|
||||
itemOptions () {
|
||||
return this.itemDicts[this.reviewType] || []
|
||||
},
|
||||
requirements () {
|
||||
const parts = []
|
||||
if (this.checkedItems.length) parts.push('重点审核项:' + this.checkedItems.join('、'))
|
||||
if (this.extraText && this.extraText.trim()) parts.push('其他要求:' + this.extraText.trim())
|
||||
return parts.join('\n')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 切换类型时清空已选审核项(两套字典不同)
|
||||
reviewType () { this.checkedItems = [] }
|
||||
},
|
||||
created () {
|
||||
marked.setOptions({ breaks: true })
|
||||
this.loadItemDicts()
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.previewUrl) URL.revokeObjectURL(this.previewUrl)
|
||||
},
|
||||
methods: {
|
||||
loadItemDicts () {
|
||||
getDicts('oa_ai_review_item_contract').then(res => {
|
||||
this.itemDicts = { ...this.itemDicts, contract: (res.data || []).map(d => ({ label: d.dictLabel, value: d.dictValue })) }
|
||||
})
|
||||
getDicts('oa_ai_review_item_resume').then(res => {
|
||||
this.itemDicts = { ...this.itemDicts, resume: (res.data || []).map(d => ({ label: d.dictLabel, value: d.dictValue })) }
|
||||
})
|
||||
},
|
||||
goBack () { this.$router.push('/hint/aiReview') },
|
||||
goDetail () { if (this.savedId) this.$router.push('/hint/aiReview/detail/' + this.savedId) },
|
||||
riskTagType (r) { return r === '高' ? 'danger' : (r === '中' ? 'warning' : 'success') },
|
||||
@@ -167,6 +212,7 @@ export default {
|
||||
fd.append('file', this.rawFile)
|
||||
fd.append('reviewType', this.reviewType)
|
||||
if (this.reviewType === 'resume' && this.position) fd.append('position', this.position)
|
||||
if (this.requirements) fd.append('requirements', this.requirements)
|
||||
|
||||
try {
|
||||
const resp = await fetch(process.env.VUE_APP_BASE_API + '/oa/aiReview/analyzeStream', {
|
||||
@@ -264,6 +310,18 @@ export default {
|
||||
}
|
||||
.bar-hint { font-size: 12px; color: #909399; margin-top: 8px; }
|
||||
|
||||
.req-area { margin-top: 10px; border-top: 1px dashed #ebeef5; padding-top: 8px; }
|
||||
.req-line { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 8px;
|
||||
&:last-child { margin-bottom: 0; }
|
||||
}
|
||||
.req-label { flex: 0 0 56px; font-size: 12px; color: #606266; padding-top: 5px; font-weight: 600; }
|
||||
.req-items { flex: 1; display: flex; flex-wrap: wrap; gap: 6px 0;
|
||||
::v-deep .el-checkbox { margin-right: 8px; margin-left: 0; }
|
||||
::v-deep .el-checkbox.is-bordered { padding: 4px 10px 4px 8px; height: auto; }
|
||||
}
|
||||
.req-tip { flex: 0 0 auto; font-size: 11px; color: #c0c4cc; padding-top: 5px; }
|
||||
.req-extra { flex: 1; }
|
||||
|
||||
.body { margin-top: 0; }
|
||||
.panel { ::v-deep .el-card__header { padding: 9px 14px; } }
|
||||
.hd { display: flex; justify-content: space-between; align-items: center;
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
<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" />
|
||||
|
||||
Reference in New Issue
Block a user