feat-完善AI质检和AI样本标记功能和样式

This commit is contained in:
zhang.weiwei
2025-03-12 22:57:29 +08:00
parent ea6f13a5df
commit b46158a897
18 changed files with 86 additions and 77 deletions

View File

@@ -159,8 +159,7 @@ import {
import { useRouter, useRoute } from 'vue-router';
import { message } from 'ant-design-vue';
import useEmitter from '@/composables/useEmitter';
import { publishSurvey, getSurveyInfo } from '@/api/publish';
import { aiQualityInspection } from '@/api/ai';
import { publishSurvey, getSurveyInfo, aiQualityInspection } from '@/api/publish';
import { useStore } from 'vuex';
import {
ExclamationCircleFilled,
@@ -337,15 +336,16 @@ const toAiInspection = () => {
questions.forEach((question) => {
question.ai_inspection_result = null;
});
store.commit('common/M_COMMON_SET_QUESTION_INFO', questionInfo);
message.success('AI问卷质检完成');
return;
}
// 3. 有质检结果,先清空质检结果,再将质检结果合并到问题列表中
const questionMap = {};
questions.forEach((question) => {
question.ai_inspection_result = null;
questionMap[question.title] = question;
if (question.title) {
question.ai_inspection_result = null;
questionMap[question.title] = question;
}
});
resultList.forEach((result) => {
const question = questionMap[result.title];
@@ -354,7 +354,6 @@ const toAiInspection = () => {
question.ai_inspection_result = result.advice;
}
});
store.commit('common/M_COMMON_SET_QUESTION_INFO', questionInfo);
message.success('AI问卷质检完成');
})
.finally(() => {

View File

@@ -1,20 +0,0 @@
/** add by zhangweiwei 20250331_ai AI 质检 start */
/**
* AI API
*/
import request from '@/utils/request';
/**
* 创建问卷AI 质检
* @param {String} sn 问卷编号
* @param {Object} data
*/
export function aiQualityInspection(sn, data) {
return request({
url: `/ai/${sn}/qualityInspectionAssistant`,
method: 'post',
data,
timeout: 120000
});
}
/** add by zhangweiwei 20250331_ai AI 质检 end */

View File

@@ -189,6 +189,7 @@ export function aiSampleMark(sn, data) {
return request({
url: `/console/surveys/${sn}/answer_mark_ai`,
method: 'post',
toastError: false,
data,
timeout: 120000
});

View File

@@ -32,3 +32,19 @@ export function getCheckSurvey(sn) {
method: 'get'
});
}
/** add by zhangweiwei 20250331_ai AI 质检 start */
/**
* 创建问卷AI 质检
* @param {String} sn 问卷编号
* @param {Object} data
*/
export function aiQualityInspection(sn, data) {
return request({
url: `/ai/${sn}/qualityInspectionAssistant`,
method: 'post',
data,
timeout: 120000
});
}
/** add by zhangweiwei 20250331_ai AI 质检 end */

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -10,7 +10,7 @@
>
<div class="ai-loading">
<div class="loading">
<img :src="require('@/assets/img/ai/ai-loading.png')" alt="" />
<img :src="require('@/assets/img/ai/ai-loading.gif')" alt="" />
</div>
<div class="title">{{ title }}</div>
<div class="desc">

View File

@@ -39,7 +39,12 @@ service.interceptors.request.use(
// response interceptor
service.interceptors.response.use(
(response) => {
if (response.status === 200 || response.status === 201 || response.status === 202 || response.status === 204) {
if (
response.status === 200
|| response.status === 201
|| response.status === 202
|| response.status === 204
) {
if (response.config.method === 'put') {
message.success('保存中...');
}
@@ -75,7 +80,14 @@ service.interceptors.response.use(
path: '/error/500'
});
} else {
message.error(error.response.data?.message || '服务器错误');
/** modify by zhangweiwei 20250331_ai 无效样本标记-处理其他异常码 start */
// 判断是否需要弹异常提示,不需要:直接抛出错误用于自己处理异常的场景
const toastError = !error.response.config || error.response.config.toastError !== false;
if (toastError) {
// 不需要弹异常提示,直接抛出错误
message.error(error.response.data?.message || '服务器错误');
}
/** modify by zhangweiwei 20250331_ai 无效样本标记-处理其他异常码 start */
}
return Promise.reject(error.response);
}

View File

@@ -14,8 +14,10 @@
<!--带有图标的标题AI/人工样本标记-->
<div class="common-text">{{ titleInfo.title }}</div>
</a-tooltip>
<a-tooltip placement="top">
<a-tooltip
placement="top"
:overlayClassName="titleInfo.titleIconTipType === 'ai' ? 'custom-icon-tooltip' : ''"
>
<template #title>
<div class="custom-head-preview">{{ titleInfo.titleIconTip }}</div>
</template>
@@ -54,7 +56,7 @@
</template>
<script setup>
import { ref, computed, watchEffect, defineProps } from 'vue';
import { ref, computed, watchEffect, defineProps, onMounted } from 'vue';
import { useStore } from 'vuex';
import { downloadAnswerFile } from '@api/data-analyse';
import { convertQueryToString } from '@utils/httpFormat';
@@ -62,6 +64,9 @@ import { downloadFile } from '@views/DataAnalyse/composables/downloadFile';
import { addDownloadCenter } from '@/api/download.js';
import { useRouter, useRoute } from 'vue-router';
import DownloadCenter from '@/views/DownloadCenter/index.vue';
import { document } from 'postcss';
import { tr } from 'element-plus/lib/locale';
import { get } from 'lodash';
const store = useStore();
const props = defineProps({
data: {
@@ -84,6 +89,7 @@ const question_type = ref(null);
const includeHtmlTag = computed(() => /<\/?[a-z][\s\S]*>/i.test(content.value));
const shortTitle = computed(() => (content.value ? content.value.slice(0, 40) : ''));
const searchParams = ref({});
function download() {
const params = JSON.parse(JSON.stringify(props.search_params));
const query = convertQueryToString(params);
@@ -139,6 +145,15 @@ watchEffect(() => {
width: 40px;
height: 40px;
}
body .custom-icon-tooltip {
.ant-tooltip-inner {
background: linear-gradient(90deg, #BE53E8 , #3962FF );
}
.ant-tooltip-arrow-content {
background: linear-gradient(90deg, #BE53E8 , #3962FF );
}
}
</style>
<style lang="scss" scoped>
@@ -184,29 +199,5 @@ watchEffect(() => {
margin-left: 4px;
}
}
.custom-tooltip {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
}
}
.icon-tip-wrapper {
:deep(.ant-tooltip) {
z-index: 9999;
.ant-tooltip-inner {
min-width: 58px;
background-color: transparent;
background-image: url('~@/assets/img/ai/data-analyse-ai-mark-tip-bg.png');
background-size: cover;
}
.ant-tooltip-arrow {
display: none;
}
}
}
</style>

View File

@@ -1344,7 +1344,9 @@ const clearInfo = (type) => {
// 作答状态
searchData.value.answerStatus = ['1'];
// 标记状态
searchData.value.isMark = ['0', '1'];
/** modify by zhangweiwei 20250331_ai 无效样本标记-筛选标记状态新增【AI标记】选项 start */
searchData.value.isMark = ['2', '1', '0'];
/** modify by zhangweiwei 20250331_ai 无效样本标记-筛选标记状态新增【AI标记】选项 start */
// 样本编码
searchData.value.sample_encoding = '';
// 数据类型

View File

@@ -179,12 +179,12 @@
</a-input>
</a-modal>
<notData @reset="reset" ref="notDataRef"></notData>
<!-- add by zhangweiwei 20250331_ai 无效样本标记-列表新增AI/人工样本标记 start -->
<ai-loading
<!-- add by zhangweiwei 20250331_ai 无效样本标记-列表新增AI/人工样本标记 start -->
<ai-loading
:visible="showAiLoading"
desc="正在启动AI火眼金睛模式为您进行深度扫描这次需要多扫描一会儿才能确保标记精准度认真工作的我马上带着结果回来哦~"
/>
<!-- add by zhangweiwei 20250331_ai 无效样本标记-列表新增AI/人工样本标记 end -->
<!-- add by zhangweiwei 20250331_ai 无效样本标记-列表新增AI/人工样本标记 end -->
</template>
<script setup>
@@ -633,7 +633,6 @@ function onPageChange(data) {
* @param column
*/
function onHeaderClick(column) {
console.log('onHeaderClick', column);
if (column.key === 'mark_des_ai') {
aiMark(sn);
} else if (column.key === 'mark_des') {
@@ -646,17 +645,26 @@ function onHeaderClick(column) {
* @param sn 问卷sn
*/
function aiMark(sn) {
showAiLoading.value = true;
aiSampleMark(sn, {
surveySn: sn
})
.then((res) => {
message.success('AI样本标记成功');
getData();
resetSelection();
showAiLoading.value = true;
// 5s后关闭
setTimeout(() => {
showAiLoading.value = false;
// getData();
// resetSelection();
}, 5000);
})
.finally(() => {
showAiLoading.value = false;
.catch((error) => {
console.error('----->', error);
if (error.data?.code === 10014) {
// 正在AI标记中
message.warn(error.data?.message);
} else {
message.error(error.data?.message || '服务器错误');
}
});
}
@@ -665,7 +673,7 @@ function aiMark(sn) {
* @param item 当前行数据
* @param isMarked 是否已标记
*/
function onAiMarkClick(item,isMarked) {
function onAiMarkClick(item, isMarked) {
console.log('onAiMarkClick', item);
if (!isMarked) {
// 没有标记,不允许单个标记

View File

@@ -17,8 +17,8 @@
<slot name="noMrgOption"></slot>
<div style="padding-left: 16px"><slot name="footer"></slot></div>
<!-- add by zhangweiwei 20250331_ai AI 质检 新增 AI 质检结果组件 start -->
<div>
<ai-inspection-result v-if="info?.ai_inspection_result" :result="info.ai_inspection_result"/>
<div class="ai-inspection-result" v-if="info?.ai_inspection_result">
<ai-inspection-result :result="info.ai_inspection_result"/>
</div>
<!-- add by zhangweiwei 20250331_ai AI 质检 新增 AI 质检结果组件 end -->
</div>

View File

@@ -1,6 +1,6 @@
<template>
<div class="bpto">
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="bpto-card-list">
<template v-for="(item, index) in optionList" :key="index">

View File

@@ -1,5 +1,5 @@
<template>
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="classify">
<div class="classify-card">

View File

@@ -1,5 +1,5 @@
<template>
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="date">
<a-date-picker

View File

@@ -1,5 +1,5 @@
<template>
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="picture" :class="{ single: [0].includes(info.config.show_type) }">
<template v-if="optionList.length > 0">

View File

@@ -1,6 +1,6 @@
<template>
<div>
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="cascade-main-table">
<LogicalTitle

View File

@@ -1,5 +1,5 @@
<template>
<QuesBaseItem>
<QuesBaseItem :info="info">
<template v-slot:option>
<div class="sort">
<div class="sort-card">