feat: 对接ai审核接口
This commit is contained in:
@ -78,6 +78,17 @@ export const putWorkAuditsAuditPass = (params = {}) => {
|
|||||||
return Http.put(`/v1/work-audits/${auditId}/audit-pass`, rest);
|
return Http.put(`/v1/work-audits/${auditId}/audit-pass`, rest);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 内容稿件审核-AI审查
|
||||||
|
export const postWorkAuditsAiReview = (params = {}) => {
|
||||||
|
const { id, ...rest } = params as { id: string; [key: string]: any };
|
||||||
|
return Http.post(`/v1/work-audits/${id}/ai-review`, rest);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 内容稿件审核-获取AI审查结果
|
||||||
|
export const getWorkAuditsAiReviewResult = (id: string, ticket: string) => {
|
||||||
|
return Http.get(`/v1/work-audits/${id}/ai-review/${ticket}`);
|
||||||
|
};
|
||||||
|
|
||||||
// 内容稿件-列表(客户)
|
// 内容稿件-列表(客户)
|
||||||
export const getShareWorksList = (shareCode: string) => {
|
export const getShareWorksList = (shareCode: string) => {
|
||||||
return Http.get(
|
return Http.get(
|
||||||
@ -120,3 +131,4 @@ export const deleteShareWorksComments = (id: string, commentId: string, shareCod
|
|||||||
headers: { 'share-code': shareCode },
|
headers: { 'share-code': shareCode },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="navbar-wrap">
|
<div class="navbar-wrap">
|
||||||
<div class="left-wrap">
|
<div class="left-wrap">
|
||||||
<a-space class="cursor-pointer" @click="router.push('/')">
|
<div class="h-full flex items-center cursor-pointer" @click="handleUserHome">
|
||||||
<img src="@/assets/LOGO.svg" alt="" />
|
<img src="@/assets/LOGO.svg" alt="" />
|
||||||
</a-space>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<NavbarMenu />
|
<NavbarMenu />
|
||||||
@ -16,6 +16,7 @@
|
|||||||
import NavbarMenu from './components/navbar-menu';
|
import NavbarMenu from './components/navbar-menu';
|
||||||
import RightSide from './components/right-side';
|
import RightSide from './components/right-side';
|
||||||
|
|
||||||
|
import { handleUserHome } from '@/utils/user.ts';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -28,7 +29,7 @@ import router from '@/router';
|
|||||||
.left-wrap {
|
.left-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 20px;
|
padding-left: 24px;
|
||||||
}
|
}
|
||||||
.arco-dropdown-option-suffix {
|
.arco-dropdown-option-suffix {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
54
src/hooks/useGetAiReviewResult.ts
Normal file
54
src/hooks/useGetAiReviewResult.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { postWorkAuditsAiReview, getWorkAuditsAiReviewResult } from '@/api/all/generationWorkshop';
|
||||||
|
export default function useGetAiReviewResult({ cardInfo, updateAiReview }: { cardInfo: any; updateAiReview: (ai_review: any) => void }) {
|
||||||
|
const statusPollingTimer = ref<number | null>(null);
|
||||||
|
const ticket = ref('');
|
||||||
|
const checkLoading = ref(false);
|
||||||
|
const checkResult = ref<any>({});
|
||||||
|
|
||||||
|
const handleStartCheck = async () => {
|
||||||
|
checkLoading.value = true;
|
||||||
|
const { id, platform, content } = cardInfo.value;
|
||||||
|
const { code, data } = await postWorkAuditsAiReview({ id, platform, content });
|
||||||
|
if (code === 200) {
|
||||||
|
ticket.value = data.ticket;
|
||||||
|
startStatusPolling();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleAgainCheck = async () => {
|
||||||
|
checkResult.value = {};
|
||||||
|
ticket.value = '';
|
||||||
|
clearStatusPollingTimer();
|
||||||
|
handleStartCheck();
|
||||||
|
};
|
||||||
|
const startStatusPolling = () => {
|
||||||
|
clearStatusPollingTimer();
|
||||||
|
statusPollingTimer.value = setInterval(async () => {
|
||||||
|
const { code, data } = await getWorkAuditsAiReviewResult(cardInfo.value.id, ticket.value);
|
||||||
|
if (code === 200 && data.status === 1) {
|
||||||
|
checkResult.value = data.ai_review;
|
||||||
|
updateAiReview?.(data.ai_review);
|
||||||
|
checkLoading.value = false;
|
||||||
|
clearStatusPollingTimer();
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearStatusPollingTimer = () => {
|
||||||
|
if (statusPollingTimer.value) {
|
||||||
|
clearInterval(statusPollingTimer.value);
|
||||||
|
statusPollingTimer.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearStatusPollingTimer();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
handleStartCheck,
|
||||||
|
handleAgainCheck,
|
||||||
|
checkResult,
|
||||||
|
checkLoading,
|
||||||
|
ticket,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import { getShareWorksList, getShareWorksDetail, patchShareWorksConfirm } from '
|
|||||||
import { convertVideoUrlToCoverUrl, exactFormatTime } from '@/utils/tools.ts';
|
import { convertVideoUrlToCoverUrl, exactFormatTime } from '@/utils/tools.ts';
|
||||||
import { EnumManuscriptType } from '@/views/creative-generation-workshop/manuscript/list/constants.ts';
|
import { EnumManuscriptType } from '@/views/creative-generation-workshop/manuscript/list/constants.ts';
|
||||||
import { RESULT_LIST, ENUM_OPINION } from './constants';
|
import { RESULT_LIST, ENUM_OPINION } from './constants';
|
||||||
|
import { handleUserHome } from '@/utils/user.ts';
|
||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
import icon1 from '@/assets/logo.svg';
|
import icon1 from '@/assets/logo.svg';
|
||||||
@ -212,7 +213,9 @@ export default {
|
|||||||
<div class="explore-page">
|
<div class="explore-page">
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<div class="content w-full px-24px flex items-center bg-#fff justify-between">
|
<div class="content w-full px-24px flex items-center bg-#fff justify-between">
|
||||||
|
<div class="h-full flex items-center cursor-pointer" onClick={handleUserHome}>
|
||||||
<img src={icon1} alt="" width={130} />
|
<img src={icon1} alt="" width={130} />
|
||||||
|
</div>
|
||||||
<div class="flex items-center">{renderActionRow()}</div>
|
<div class="flex items-center">{renderActionRow()}</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import TextOverTips from '@/components/text-over-tips';
|
|||||||
import { Image, Spin } from '@arco-design/web-vue';
|
import { Image, Spin } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import { exactFormatTime } from '@/utils/tools';
|
import { exactFormatTime } from '@/utils/tools';
|
||||||
|
import { handleUserHome } from '@/utils/user.ts';
|
||||||
import { getShareWorksList } from '@/api/all/generationWorkshop';
|
import { getShareWorksList } from '@/api/all/generationWorkshop';
|
||||||
import { ENUM_OPINION } from '../detail/constants';
|
import { ENUM_OPINION } from '../detail/constants';
|
||||||
|
|
||||||
@ -44,7 +45,9 @@ export default {
|
|||||||
<div class="explore-page">
|
<div class="explore-page">
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<div class="content w-full px-24px flex items-center bg-#fff">
|
<div class="content w-full px-24px flex items-center bg-#fff">
|
||||||
<img src={icon2} alt="" width={130} />
|
<div class="h-full flex items-center cursor-pointer" onClick={handleUserHome}>
|
||||||
|
<img src={icon2} alt="" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{loading.value ? (
|
{loading.value ? (
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.page-wrapper {
|
.page-wrapper {
|
||||||
min-height: 500px;
|
min-height: calc(100vh - $navbar-height);
|
||||||
.explore-container {
|
.explore-container {
|
||||||
width: 1200px;
|
width: 1200px;
|
||||||
.explore-list-wrap {
|
.explore-list-wrap {
|
||||||
|
|||||||
@ -1,42 +1,53 @@
|
|||||||
const FORM_RULES = {
|
export const FORM_RULES = {
|
||||||
title: [{ required: true, message: '请输入标题' }],
|
title: [{ required: true, message: '请输入标题' }],
|
||||||
};
|
};
|
||||||
const enumTab = {
|
export const enumTab = {
|
||||||
TEXT: 0,
|
TEXT: 0,
|
||||||
IMAGE: 1,
|
IMAGE: 1,
|
||||||
};
|
};
|
||||||
const TAB_LIST = [
|
export const TAB_LIST = [
|
||||||
{
|
{
|
||||||
label: '文本',
|
label: '文本',
|
||||||
value: enumTab.TEXT,
|
value: enumTab.TEXT,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
label: '图片',
|
// label: '图片',
|
||||||
value: enumTab.IMAGE,
|
// value: enumTab.IMAGE,
|
||||||
},
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export enum Enum_Level {
|
||||||
|
LOW = 0,
|
||||||
|
MEDIUM = 1,
|
||||||
|
HIGH = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LEVEL_MAP = new Map([
|
||||||
|
[Enum_Level.LOW, { label: '低风险', value: 'low_risk_number', class: '!color-#6d4cfe' }],
|
||||||
|
[Enum_Level.MEDIUM, { label: '中风险', value: 'medium_risk_number', class: 'color-#FFAE00' }],
|
||||||
|
[Enum_Level.HIGH, { label: '高风险', value: 'high_risk_number', class: '!color-#F64B31' }],
|
||||||
|
]);
|
||||||
|
|
||||||
export const RESULT_LIST = [
|
export const RESULT_LIST = [
|
||||||
{
|
{
|
||||||
label: '合规程度',
|
label: '合规程度',
|
||||||
value: 'compliance_degree',
|
value: 'compliance_level',
|
||||||
class: '!color-#6d4cfe',
|
class: LEVEL_MAP.get(Enum_Level.LOW)?.class,
|
||||||
|
suffix: '%',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '检验项',
|
label: '检验项',
|
||||||
value: 'compliance',
|
value: 'inspection_items',
|
||||||
class: '!color-#211F24',
|
class: '!color-#211F24',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '高风险',
|
label: '高风险',
|
||||||
value: 'high_risk',
|
value: 'high_risk_number',
|
||||||
class: '!color-#F64B31',
|
class: LEVEL_MAP.get(Enum_Level.HIGH)?.class,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '中风险',
|
label: '中风险',
|
||||||
value: 'medium_risk',
|
value: 'medium_risk_number',
|
||||||
class: '!color-#FFAE00',
|
class: LEVEL_MAP.get(Enum_Level.MEDIUM)?.class,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export { FORM_RULES, enumTab, TAB_LIST };
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import TextOverTips from '@/components/text-over-tips';
|
|||||||
import 'swiper/css';
|
import 'swiper/css';
|
||||||
import 'swiper/css/navigation';
|
import 'swiper/css/navigation';
|
||||||
import { Navigation } from 'swiper/modules';
|
import { Navigation } from 'swiper/modules';
|
||||||
import { FORM_RULES, enumTab, TAB_LIST, RESULT_LIST } from './constants';
|
import { FORM_RULES, enumTab, TAB_LIST, RESULT_LIST, LEVEL_MAP } from './constants';
|
||||||
import { getImagePreSignedUrl } from '@/api/all/common';
|
import { getImagePreSignedUrl } from '@/api/all/common';
|
||||||
import { EnumManuscriptType } from '@/views/creative-generation-workshop/manuscript/list/constants';
|
import { EnumManuscriptType } from '@/views/creative-generation-workshop/manuscript/list/constants';
|
||||||
|
|
||||||
@ -36,31 +36,25 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: {},
|
default: {},
|
||||||
},
|
},
|
||||||
checkResult: {
|
|
||||||
type: Object,
|
|
||||||
default: {},
|
|
||||||
},
|
|
||||||
selectedImageInfo: {
|
selectedImageInfo: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: {},
|
default: {},
|
||||||
},
|
},
|
||||||
|
checkLoading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue', 'filesChange', 'selectImage'],
|
},
|
||||||
|
emits: ['update:modelValue', 'filesChange', 'selectImage', 'againCheck', 'startCheck'],
|
||||||
setup(props, { emit, expose }) {
|
setup(props, { emit, expose }) {
|
||||||
const activeTab = ref(enumTab.TEXT);
|
const activeTab = ref(enumTab.TEXT);
|
||||||
const aiCheckLoading = ref(false);
|
const aiCheckLoading = ref(false);
|
||||||
const formRef = ref(null);
|
const formRef = ref(null);
|
||||||
const uploadRef = ref(null);
|
const uploadRef = ref(null);
|
||||||
const modules = [Navigation];
|
const modules = [Navigation];
|
||||||
const checkLoading = ref(false);
|
|
||||||
|
|
||||||
const tabList = computed(() => {
|
|
||||||
if (props.modelValue.type === EnumManuscriptType.Image) {
|
|
||||||
return TAB_LIST;
|
|
||||||
}
|
|
||||||
return TAB_LIST.filter((item) => item.value !== enumTab.IMAGE);
|
|
||||||
});
|
|
||||||
const isTextTab = computed(() => activeTab.value === enumTab.TEXT);
|
const isTextTab = computed(() => activeTab.value === enumTab.TEXT);
|
||||||
|
const aiReview = computed(() => props.modelValue.ai_review);
|
||||||
|
|
||||||
const onAiReplace = () => {
|
const onAiReplace = () => {
|
||||||
if (aiCheckLoading.value) return;
|
if (aiCheckLoading.value) return;
|
||||||
@ -71,15 +65,12 @@ export default {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCheck = () => {
|
const onAgainCheck = () => {
|
||||||
if (!isTextTab.value && !props.modelValue.files?.length) {
|
if (!isTextTab.value && !props.modelValue.files?.length) {
|
||||||
AMessage.warning('请先上传需审核图片');
|
AMessage.warning('请先上传需审核图片');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkLoading.value = true;
|
emit('againCheck');
|
||||||
setTimeout(() => {
|
|
||||||
checkLoading.value = false;
|
|
||||||
}, 2000);
|
|
||||||
};
|
};
|
||||||
const onReplaceImage = () => {
|
const onReplaceImage = () => {
|
||||||
uploadRef.value?.upload?.();
|
uploadRef.value?.upload?.();
|
||||||
@ -102,7 +93,6 @@ export default {
|
|||||||
formRef.value?.resetFields?.();
|
formRef.value?.resetFields?.();
|
||||||
formRef.value?.clearValidate?.();
|
formRef.value?.clearValidate?.();
|
||||||
aiCheckLoading.value = false;
|
aiCheckLoading.value = false;
|
||||||
checkLoading.value = false;
|
|
||||||
};
|
};
|
||||||
const getFileExtension = (filename) => {
|
const getFileExtension = (filename) => {
|
||||||
const match = filename.match(/\.([^.]+)$/);
|
const match = filename.match(/\.([^.]+)$/);
|
||||||
@ -180,7 +170,7 @@ export default {
|
|||||||
const renderFooterRow = () => {
|
const renderFooterRow = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button class="mr-12px" size="medium" onClick={onCheck}>
|
<Button class="mr-12px" size="medium" onClick={onAgainCheck}>
|
||||||
再次审核
|
再次审核
|
||||||
</Button>
|
</Button>
|
||||||
{isTextTab.value ? (
|
{isTextTab.value ? (
|
||||||
@ -220,7 +210,7 @@ export default {
|
|||||||
size="large"
|
size="large"
|
||||||
maxLength={30}
|
maxLength={30}
|
||||||
show-word-limit
|
show-word-limit
|
||||||
disabled={checkLoading.value}
|
disabled={props.checkLoading}
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="作品描述" field="content" class="flex-1 content-form-item">
|
<FormItem label="作品描述" field="content" class="flex-1 content-form-item">
|
||||||
@ -231,7 +221,7 @@ export default {
|
|||||||
show-word-limit
|
show-word-limit
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
show-word-limit
|
show-word-limit
|
||||||
disabled={checkLoading.value}
|
disabled={props.checkLoading}
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
@ -322,7 +312,7 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderRightBox = () => {
|
const renderRightBox = () => {
|
||||||
if (checkLoading.value) {
|
if (props.checkLoading) {
|
||||||
return (
|
return (
|
||||||
<div class="right-box flex-1 h-210px rounded-8px border-1px border-#E6E6E8 border-solid p-16px flex flex-col overflow-y-auto">
|
<div class="right-box flex-1 h-210px rounded-8px border-1px border-#E6E6E8 border-solid p-16px flex flex-col overflow-y-auto">
|
||||||
<p class="cts bold !text-16px !lh-24px !color-#211F24 mb-16px">审核结果</p>
|
<p class="cts bold !text-16px !lh-24px !color-#211F24 mb-16px">审核结果</p>
|
||||||
@ -330,14 +320,14 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (isEmpty(props.checkResult)) {
|
if (!aiReview.value?.violation_items?.length) {
|
||||||
return (
|
return (
|
||||||
<div class="right-box flex-1 h-372px rounded-8px border-1px border-#E6E6E8 border-solid p-16px flex flex-col overflow-y-auto">
|
<div class="right-box flex-1 h-372px rounded-8px border-1px border-#E6E6E8 border-solid p-16px flex flex-col overflow-y-auto">
|
||||||
<p class="cts bold !text-16px !lh-24px !color-#211F24 mb-16px">审核结果</p>
|
<p class="cts bold !text-16px !lh-24px !color-#211F24 mb-16px">审核结果</p>
|
||||||
<div class="flex items-center mb-16px">
|
<div class="flex items-center mb-16px">
|
||||||
{RESULT_LIST.map((item, index) => (
|
{RESULT_LIST.map((item, index) => (
|
||||||
<div class="flex flex-col justify-center items-center flex-1 result-item" key={index}>
|
<div class="flex flex-col justify-center items-center flex-1 result-item" key={index}>
|
||||||
<span class={`s1 ${item.class}`}>30</span>
|
<span class={`s1 ${item.class}`}>{aiReview.value?.[item.value]}</span>
|
||||||
<span class="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
|
<span class="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -364,7 +354,9 @@ export default {
|
|||||||
<div class="flex items-center mb-16px">
|
<div class="flex items-center mb-16px">
|
||||||
{RESULT_LIST.map((item, index) => (
|
{RESULT_LIST.map((item, index) => (
|
||||||
<div class="flex flex-col justify-center items-center flex-1 result-item" key={index}>
|
<div class="flex flex-col justify-center items-center flex-1 result-item" key={index}>
|
||||||
<span class={`s1 ${item.class}`}>30</span>
|
<span class={`s1 color-#6d4cfe ${item.class}`}>{`${aiReview.value?.[item.value]}${
|
||||||
|
item.suffix || ''
|
||||||
|
}`}</span>
|
||||||
<span class="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
|
<span class="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -374,7 +366,7 @@ export default {
|
|||||||
<span class="ai-text">AI 审核建议</span>
|
<span class="ai-text">AI 审核建议</span>
|
||||||
<img src={icon2} class="w-80px h-10.8px absolute bottom-1px left-1px" />
|
<img src={icon2} class="w-80px h-10.8px absolute bottom-1px left-1px" />
|
||||||
</div>
|
</div>
|
||||||
{descs.map((item, index) => (
|
{aiReview.value?.suggestion?.map((item, index) => (
|
||||||
<p class="cts !color-#55585F !text-12px !lh-20px" key={index}>{`${index + 1}. ${item}`}</p>
|
<p class="cts !color-#55585F !text-12px !lh-20px" key={index}>{`${index + 1}. ${item}`}</p>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -382,16 +374,18 @@ export default {
|
|||||||
<div class="forbid-word-box flex-1 flex">
|
<div class="forbid-word-box flex-1 flex">
|
||||||
<div class="left mr-32px w-56px">
|
<div class="left mr-32px w-56px">
|
||||||
<p class="mb-12px cts !text-12px">违禁词</p>
|
<p class="mb-12px cts !text-12px">违禁词</p>
|
||||||
{forbidWords.map((item, index) => (
|
{aiReview.value?.violation_items?.map((item, index) => (
|
||||||
<p class={`mb-12px cts level${item.level}`} key={index}>
|
<TextOverTips
|
||||||
{item.label}
|
context={item.word}
|
||||||
</p>
|
class={`mb-12px cts ${LEVEL_MAP.get(item.risk_level)?.class}`}
|
||||||
|
key={index}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div class="right flex-1">
|
<div class="right flex-1 overflow-hidden">
|
||||||
<p class="mb-12px cts !text-12px">解释</p>
|
<p class="mb-12px cts !text-12px">解释</p>
|
||||||
{forbidWords.map((item, index) => (
|
{aiReview.value?.violation_items?.map((item, index) => (
|
||||||
<TextOverTips context={item.desc} class="mb-12px" key={index} />
|
<TextOverTips context={item.reason} class="mb-12px" key={index} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -405,44 +399,28 @@ export default {
|
|||||||
reset,
|
reset,
|
||||||
});
|
});
|
||||||
|
|
||||||
const descs = [
|
|
||||||
'删除 “效果炸裂”“医院都做不到” 等夸大对比的表述;',
|
|
||||||
'去掉 “顽固体质逆袭”“腰围小 10cm” 等具体效果承诺(食品 / 非药品不得宣称减肥等功效);',
|
|
||||||
'严禁提及 “孕妇能吃”,明确标注不适宜人群;',
|
|
||||||
'“进口纯天然” 需有依据,避免绝对化,可改为 “选用进口原料,成分温和”;',
|
|
||||||
'去掉 “当糖吃” 等误导性表述,强调正常食用量。',
|
|
||||||
];
|
|
||||||
const forbidWords = [
|
|
||||||
{
|
|
||||||
label: '纯天然',
|
|
||||||
desc: '涉嫌虚假内容相关词语',
|
|
||||||
level: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '安全',
|
|
||||||
desc: '涉嫌绝对化承诺保证',
|
|
||||||
level: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '副作用',
|
|
||||||
desc: '涉嫌夸大词语',
|
|
||||||
level: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '副作用',
|
|
||||||
desc: '涉嫌夸大词语',
|
|
||||||
level: 3,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class="h-full w-full px-24px pt-16px pb-24px content-wrap flex">
|
<div class="h-full w-full px-24px pt-16px pb-24px content-wrap flex">
|
||||||
<div class="flex-2 left-box mr-24px flex flex-col">
|
<div class="flex-2 left-box mr-24px flex flex-col">
|
||||||
<div class="flex-1 mb-12px rounded-8px border-1px pt-8px flex flex-col pb-16px bg-#F7F8FA border-#E6E6E8 border-solid">
|
<div class="flex-1 mb-12px rounded-8px border-1px pt-8px flex flex-col pb-16px bg-#F7F8FA border-#E6E6E8 border-solid">
|
||||||
<Tabs v-model={activeTab.value} onTabClick={handleTabClick} class="mb-16px">
|
<Tabs v-model={activeTab.value} onTabClick={handleTabClick} class="mb-16px">
|
||||||
{tabList.value.map((item) => (
|
{TAB_LIST.map((item) => (
|
||||||
<TabPane key={item.value} title={item.label}></TabPane>
|
<TabPane
|
||||||
|
key={item.value}
|
||||||
|
v-slots={{
|
||||||
|
title: () => (
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<span>{item.label}</span>
|
||||||
|
{
|
||||||
|
activeTab.value === item.value && aiReview.value?.violation_items.length > 0 && (
|
||||||
|
<icon-exclamation-circle-fill size={14} class="color-#F64B31 absolute right--10px top-0" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div class="flex-1 px-16px">{isTextTab.value ? renderTextForm() : renderImageForm()}</div>
|
<div class="flex-1 px-16px">{isTextTab.value ? renderTextForm() : renderImageForm()}</div>
|
||||||
|
|||||||
@ -131,7 +131,6 @@
|
|||||||
}
|
}
|
||||||
.right-box {
|
.right-box {
|
||||||
.s1 {
|
.s1 {
|
||||||
color: var(--Brand-6, #6d4cfe);
|
|
||||||
font-family: $font-family-manrope-regular;
|
font-family: $font-family-manrope-regular;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -175,15 +174,17 @@
|
|||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
.forbid-word-box {
|
.forbid-word-box {
|
||||||
.level1 {
|
:deep(.overflow-text) {
|
||||||
|
&.level0 {
|
||||||
color: #6d4cfe;
|
color: #6d4cfe;
|
||||||
}
|
}
|
||||||
.level2 {
|
&.level2 {
|
||||||
color: #f64b31;
|
color: #f64b31;
|
||||||
}
|
}
|
||||||
.level3 {
|
&.level1 {
|
||||||
color: #ffae00;
|
color: #ffae00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import ContentCard from './components/content-card';
|
|||||||
import CheckListDrawer from './components/check-list-drawer';
|
import CheckListDrawer from './components/check-list-drawer';
|
||||||
|
|
||||||
import { slsWithCatch, rlsWithCatch, glsWithCatch } from '@/utils/stroage.ts';
|
import { slsWithCatch, rlsWithCatch, glsWithCatch } from '@/utils/stroage.ts';
|
||||||
|
import useGetAiReviewResult from '@/hooks/useGetAiReviewResult.ts';
|
||||||
import {
|
import {
|
||||||
patchWorkAuditsAudit,
|
patchWorkAuditsAudit,
|
||||||
patchWorkAuditsBatchAudit,
|
patchWorkAuditsBatchAudit,
|
||||||
@ -14,6 +15,7 @@ import {
|
|||||||
putWorkAuditsAuditPass,
|
putWorkAuditsAuditPass,
|
||||||
getWorkAuditsDetail,
|
getWorkAuditsDetail,
|
||||||
getWorkAuditsBatchDetail,
|
getWorkAuditsBatchDetail,
|
||||||
|
postWorkAuditsAiReview,
|
||||||
} from '@/api/all/generationWorkshop.ts';
|
} from '@/api/all/generationWorkshop.ts';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -30,11 +32,18 @@ export default {
|
|||||||
const submitLoading = ref(false);
|
const submitLoading = ref(false);
|
||||||
const contentCardRef = ref(null);
|
const contentCardRef = ref(null);
|
||||||
const checkListDrawerRef = ref(null);
|
const checkListDrawerRef = ref(null);
|
||||||
const checkResult = ref({});
|
|
||||||
|
|
||||||
const selectCardInfo = ref({});
|
const selectCardInfo = ref({});
|
||||||
const selectedImageInfo = ref(null);
|
const selectedImageInfo = ref(null);
|
||||||
|
|
||||||
|
const { handleStartCheck, handleAgainCheck, ticket, checkLoading } = useGetAiReviewResult({
|
||||||
|
cardInfo: selectCardInfo,
|
||||||
|
updateAiReview(ai_review) {
|
||||||
|
console.log('updateAiReview', ai_review);
|
||||||
|
selectCardInfo.value.ai_review = ai_review;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
router.push({ name: 'ManuscriptCheckList' });
|
router.push({ name: 'ManuscriptCheckList' });
|
||||||
};
|
};
|
||||||
@ -43,9 +52,16 @@ export default {
|
|||||||
contentCardRef.value.reset();
|
contentCardRef.value.reset();
|
||||||
isSaved.value = false;
|
isSaved.value = false;
|
||||||
submitLoading.value = false;
|
submitLoading.value = false;
|
||||||
checkResult.value = {};
|
checkLoading.value = false;
|
||||||
|
ticket.value = '';
|
||||||
|
|
||||||
|
const { files = [], ai_review } = item;
|
||||||
selectCardInfo.value = cloneDeep(item);
|
selectCardInfo.value = cloneDeep(item);
|
||||||
selectedImageInfo.value = cloneDeep(item.files?.[0] ?? {});
|
selectedImageInfo.value = cloneDeep(files?.[0] ?? {});
|
||||||
|
|
||||||
|
if (isEmpty(ai_review)) {
|
||||||
|
handleStartCheck();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCardClick = async (item) => {
|
const onCardClick = async (item) => {
|
||||||
@ -71,8 +87,16 @@ export default {
|
|||||||
|
|
||||||
dataSource.value = _data;
|
dataSource.value = _data;
|
||||||
remoteDataSource.value = cloneDeep(_data);
|
remoteDataSource.value = cloneDeep(_data);
|
||||||
selectCardInfo.value = cloneDeep(_data?.[0] ?? {});
|
|
||||||
selectedImageInfo.value = cloneDeep(_data?.[0].files?.[0] ?? {});
|
const _firstCard = _data?.[0] ?? {};
|
||||||
|
const { id, ai_review } = _firstCard;
|
||||||
|
|
||||||
|
selectCardInfo.value = cloneDeep(_firstCard);
|
||||||
|
selectedImageInfo.value = cloneDeep(_firstCard.files?.[0] ?? {});
|
||||||
|
|
||||||
|
if (isEmpty(ai_review)) {
|
||||||
|
handleStartCheck();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,6 +159,10 @@ export default {
|
|||||||
const onFilesChange = (files) => {
|
const onFilesChange = (files) => {
|
||||||
selectCardInfo.value.files = cloneDeep(files);
|
selectCardInfo.value.files = cloneDeep(files);
|
||||||
};
|
};
|
||||||
|
const onAgainCheck = () => {
|
||||||
|
handleAgainCheck();
|
||||||
|
};
|
||||||
|
|
||||||
const renderFooterRow = () => {
|
const renderFooterRow = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -190,10 +218,12 @@ export default {
|
|||||||
ref={contentCardRef}
|
ref={contentCardRef}
|
||||||
v-model={selectCardInfo.value}
|
v-model={selectCardInfo.value}
|
||||||
selectCardInfo={selectCardInfo.value}
|
selectCardInfo={selectCardInfo.value}
|
||||||
checkResult={checkResult.value}
|
|
||||||
onFilesChange={onFilesChange}
|
onFilesChange={onFilesChange}
|
||||||
selectedImageInfo={selectedImageInfo.value}
|
selectedImageInfo={selectedImageInfo.value}
|
||||||
onSelectImage={onSelectImage}
|
onSelectImage={onSelectImage}
|
||||||
|
checkLoading={checkLoading.value}
|
||||||
|
onAgainCheck={onAgainCheck}
|
||||||
|
onStartCheck={handleStartCheck}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user