feat: 分享内容稿件

This commit is contained in:
rd
2025-08-08 12:12:46 +08:00
parent d07f773123
commit 6cb7ce5a0f
8 changed files with 322 additions and 123 deletions

View File

@ -0,0 +1,175 @@
<script lang="jsx">
import { Image, Spin, Button } from '@arco-design/web-vue';
import TextOverTips from '@/components/text-over-tips';
import { RESULT_LIST, ENUM_OPINION } from './constants';
import icon1 from '@/assets/img/creative-generation-workshop/icon-line.png';
const _iconMap = new Map([
[1, { icon: <icon-check-circle-fill size={16} class="color-#25C883" /> }],
[2, { icon: <icon-exclamation-circle-fill size={16} class="color-#F64B31" /> }],
[3, { icon: <icon-exclamation-circle-fill size={16} class="color-#FFAE00" /> }],
[4, { icon: <icon-exclamation-circle-fill size={16} class="color-#939499" /> }],
]);
const data1 = [
{
label: '色情检测',
level: 1,
},
{
label: '涉政检测',
level: 2,
},
{
label: '涉政正负向检测',
level: 3,
},
{
label: '涉政正负向检测',
level: 3,
},
{
label: '涉政正负向检测',
level: 3,
},
{
label: '涉政正负向检测',
level: 3,
},
{
label: '暴恐检测',
level: 4,
},
{
label: '暴恐检测',
level: 4,
},
];
export default {
props: {
isExpand: {
type: Boolean,
default: true,
},
},
emits: ['toggle'],
setup(props, { emit, expose }) {
return () => (
<section class="py-16px absolute right-16px w-440px h-full">
<div class="ai-suggest-box p-24px">
<div class="mb-16px w-full flex justify-between">
<div class="mb-24px relative w-fit">
<span class="ai-text">AI 智能审核</span>
<img src={icon1} class="w-80px h-10.8px absolute bottom-1px left--9px" />
</div>
<icon-menu-unfold
size={20}
class="color-#55585F cursor-pointer hover:color-#6D4CFE"
onClick={() => emit('toggle', false)}
/>
</div>
<div class="result-box p-16px rounded-8px mb-16px">
<div class="flex items-center justify-between mb-16px">
<p class="cts bold !color-#000 !text-16px">审核结果</p>
<Button type="text" class="!color-#6D4CFE hover:!color-#8A70FE">
展开详情
</Button>
</div>
<div class="flex items-center">
{RESULT_LIST.map((item, 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="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
</div>
))}
</div>
</div>
<div class="result-box p-16px rounded-8px mb-16px">
<p class="cts bold !color-#000 !text-16px mb-16px">敏感词检测</p>
<div class="grid grid-cols-3 gap-x-24px gap-y-8px">
{
data1.map((item, index) => (
<div class="audit-item" key={index}>
<div class="flex items-center">
{_iconMap.get(item.level)?.icon}
<TextOverTips context={item.label} class="cts ml-4px" />
</div>
</div>
))
}
</div>
</div>
<div class="result-box p-16px rounded-8px mb-16px">
<p class="cts bold !color-#000 !text-16px mb-16px">图片内容违规检测</p>
<p class="cts bold !color-#000 !text-16px mb-16px">图片文字违规检测</p>
</div>
</div>
</section>
);
},
};
</script>
<style lang="scss" scoped>
.ai-suggest-box {
.cts {
color: #939499;
font-family: $font-family-regular;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
&.bold {
font-family: $font-family-medium;
}
}
width: 440px;
height: fit-content;
max-height: 100%;
border-radius: 16px;
background: linear-gradient(126deg, #eef2fd 8.36%, #f5ebfe 49.44%, #fdebf3 90.52%);
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);
.ai-text {
font-family: $font-family-medium;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
background: linear-gradient(85deg, #7d419d 4.56%, #31353d 94.75%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.result-box {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(4px);
.result-item {
.s1 {
color: var(--Brand-6, #6d4cfe);
font-family: $font-family-manrope-regular;
font-size: 24px;
font-style: normal;
font-weight: 700;
line-height: 32px; /* 133.333% */
}
&:first-child {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
width: 1px;
height: 32px;
background: var(--Border-1, #d7d7d9);
}
}
}
}
}
</style>

View File

@ -0,0 +1,27 @@
export const RESULT_LIST = [
{
label: '合规程度',
value: 'compliance_degree',
class: '!color-#6d4cfe',
},
{
label: '检验项',
value: 'compliance',
class: '!color-#211F24',
},
{
label: '高风险',
value: 'high_risk',
class: '!color-#F64B31',
},
{
label: '中风险',
value: 'medium_risk',
class: '!color-#FFAE00',
},
];
export const ENUM_OPINION = {
wait: 0, // 待确认
confirm: 1, // 已确认
};

View File

@ -1,41 +1,23 @@
<script lang="jsx">
import { Image, Spin, Button } from '@arco-design/web-vue';
import AiSuggest from './aiSuggest.vue';
import { getShareWorksDetail } from '@/api/all/generationWorkshop.ts';
import { getShareWorksList, getShareWorksDetail, patchShareWorksConfirm } from '@/api/all/generationWorkshop.ts';
import { convertVideoUrlToCoverUrl, exactFormatTime } from '@/utils/tools.ts';
import { EnumManuscriptType } from '@/views/creative-generation-workshop/manuscript/list/constants.ts';
import { RESULT_LIST, ENUM_OPINION } from './constants';
import icon1 from '@/assets/logo.svg';
import icon2 from '@/assets/img/creative-generation-workshop/icon-confirm.png';
import icon3 from '@/assets/img/creative-generation-workshop/icon-line.png';
const RESULT_LIST = [
{
label: '合规程度',
value: 'compliance_degree',
class: '!color-#6d4cfe',
},
{
label: '检验项',
value: 'compliance',
class: '!color-#211F24',
},
{
label: '高风险',
value: 'high_risk',
class: '!color-#F64B31',
},
{
label: '中风险',
value: 'medium_risk',
class: '!color-#FFAE00',
},
];
export default {
setup(props, { emit, expose }) {
const route = useRoute();
const router = useRouter();
const dataSource = ref({});
const shareWorks = ref({});
const isExpand = ref(true);
const loading = ref(false);
@ -47,8 +29,17 @@ export default {
const images = ref([]);
const isVideo = computed(() => dataSource.value.type === EnumManuscriptType.Video);
const isMultiWork = computed(() => shareWorks.value.works?.length > 1);
const shareCode = computed(() => route.params.shareCode);
const hasPrevBtn = computed(() => dataSource.value.prev);
const hasNextBtn = computed(() => dataSource.value.next);
const initData = () => {
videoUrl.value = '';
coverImageUrl.value = '';
images.value = [];
if (!dataSource.value.files.length) return;
const [fileOne, ...fileOthers] = dataSource.value.files ?? [];
if (isVideo.value) {
videoUrl.value = fileOne.url;
@ -61,9 +52,10 @@ export default {
const getDetail = async () => {
try {
dataSource.value = {};
loading.value = true;
const { id, shareCode } = route.params;
const { code, data } = await getShareWorksDetail(id, shareCode);
const { id } = route.params;
const { code, data } = await getShareWorksDetail(id, shareCode.value);
if (code === 200) {
dataSource.value = data;
initData();
@ -73,6 +65,13 @@ export default {
}
};
const getShareWorks = async () => {
const { code, data } = await getShareWorksList(shareCode.value);
if (code === 200) {
shareWorks.value = data;
}
};
const renderMainImg = () => {
if (!coverImageUrl.value) return null;
@ -116,8 +115,68 @@ export default {
isPlaying.value = false;
};
const onBackList = () => {
router.push({
path: `/explore/list/${shareCode.value}`,
});
};
const onPrevWork = async () => {
await router.push({
path: `/explore/detail/${shareCode.value}/${dataSource.value.prev.id}`,
});
getDetail();
};
const onNextWork = async () => {
await router.push({
path: `/explore/detail/${shareCode.value}/${dataSource.value.next.id}`,
});
getDetail();
};
const handleConfirm = async () => {
const { code, data } = await patchShareWorksConfirm(dataSource.value.id, shareCode.value);
if (code === 200) {
dataSource.value.customer_opinion = ENUM_OPINION.confirm;
}
};
const renderConfirmBtn = () => {
if (dataSource.value.customer_opinion === ENUM_OPINION.confirm) return null;
return (
<Button type="primary" size="large" onClick={handleConfirm}>
确认内容稿件
</Button>
);
};
const renderActionRow = () => {
if (loading.value) return null;
if (isMultiWork.value) {
return (
<>
{hasPrevBtn.value && (
<Button type="text" size="large" class="mr-12px" onClick={onPrevWork}>
上一条
</Button>
)}
{hasNextBtn.value && (
<Button type="text" size="large" class="mr-12px" onClick={onNextWork}>
下一条
</Button>
)}
<Button type="outline" size="large" class="mr-12px" onClick={onBackList}>
返回列表
</Button>
{renderConfirmBtn()}
</>
);
}
return renderConfirmBtn();
};
onMounted(() => {
getDetail();
getShareWorks();
});
onBeforeUnmount(() => {
if (videoRef.value) {
@ -130,8 +189,9 @@ export default {
return (
<div class="explore-page">
<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 justify-between">
<img src={icon1} alt="" width={130} />
<div class="flex items-center">{renderActionRow()}</div>
</div>
</header>
{loading.value ? (
@ -147,12 +207,14 @@ export default {
<p class="cts color-#737478 mb-32px">
{exactFormatTime(dataSource.value.last_modified_at, 'YYYY年MM月DD日')}修改
</p>
{dataSource.value.customer_opinion === 1 && (
{dataSource.value.customer_opinion === ENUM_OPINION.confirm && (
<img src={icon2} width={92} height={92} class="absolute right-0 bottom-0" />
)}
</div>
{renderMainImg()}
<p class="cts !color-#211F24">{dataSource.value.content}</p>
<div class="w-full">
<p class="cts !color-#211F24">{dataSource.value.content}</p>
</div>
{/* 仅图片类型显示图片列表 */}
{!isVideo.value && (
@ -166,38 +228,7 @@ export default {
)}
</section>
{isExpand.value && (
<section class="py-16px absolute right-16px w-440px h-full">
<div class="ai-suggest-box p-24px">
<div class="mb-16px w-full flex justify-between">
<div class="mb-24px relative w-fit">
<span class="ai-text">AI 审核建议</span>
<img src={icon3} class="w-80px h-10.8px absolute bottom-1px left--9px" />
</div>
<icon-menu-unfold
size={20}
class="color-#55585F cursor-pointer hover:color-#6D4CFE"
onClick={() => (isExpand.value = false)}
/>
</div>
<div class="result-box p-16px rounded-8px mb-16px">
<div class="flex items-center justify-between mb-16px">
<p class="cts bold !color-#000 !text-16px">审核结果</p>
<Button type="text" class="!color-#6D4CFE hover:!color-#8A70FE">
展开详情
</Button>
</div>
<div class="flex items-center">
{RESULT_LIST.map((item, 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="cts mt-4px !lh-20px !text-12px !color-#737478">{item.label}</span>
</div>
))}
</div>
</div>
</div>
</section>
<AiSuggest isExpand={isExpand.value} onToggle={(expand) => (isExpand.value = expand)} />
)}
</div>
)}

View File

@ -101,51 +101,5 @@
.play-icon:hover {
background-image: url('@/assets/img/creative-generation-workshop/icon-play-hover.png');
}
.ai-suggest-box {
width: 440px;
height: fit-content;
max-height: 100%;
border-radius: 16px;
background: linear-gradient(126deg, #eef2fd 8.36%, #f5ebfe 49.44%, #fdebf3 90.52%);
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);
.ai-text {
font-family: $font-family-medium;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
background: linear-gradient(85deg, #7d419d 4.56%, #31353d 94.75%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.result-box {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(4px);
.result-item {
.s1 {
color: var(--Brand-6, #6d4cfe);
font-family: $font-family-manrope-regular;
font-size: 24px;
font-style: normal;
font-weight: 700;
line-height: 32px; /* 133.333% */
}
&:first-child {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
width: 1px;
height: 32px;
background: var(--Border-1, #d7d7d9);
}
}
}
}
}
}
}

View File

@ -4,6 +4,7 @@ import { Image, Spin } from '@arco-design/web-vue';
import { exactFormatTime } from '@/utils/tools';
import { getShareWorksList } from '@/api/all/generationWorkshop';
import { ENUM_OPINION } from '../detail/constants';
import icon1 from '@/assets/img/error-img.png';
import icon2 from '@/assets/logo.svg';
@ -78,9 +79,16 @@ export default {
/>
<div class="p-16px">
<TextOverTips context={item.title} class=" !lh-24px !text-16px mb-8px bold" />
<p class="cts color-#737478">
{exactFormatTime(item.last_modified_at, 'YYYY年MM月DD日')}修改
</p>
<div class="flex justify-between">
<p class="cts color-#737478">
{exactFormatTime(item.last_modified_at, 'YYYY年MM月DD日')}修改
</p>
{item.customer_opinion === ENUM_OPINION.confirm && (
<div class="h-24px px-8px flex justify-center items-center rounded-2px bg-#EBF7F2">
<span class="cts bold color-#25C883">已确认</span>
</div>
)}
</div>
</div>
</div>
);

View File

@ -3,6 +3,16 @@
padding-top: $navbar-height;
min-width: 1200px;
background: #fff;
.cts {
font-family: $font-family-regular;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
&.bold {
font-family: $font-family-medium;
}
}
.page-header {
position: fixed;
left: 0;
@ -20,13 +30,6 @@
.explore-container {
width: 1200px;
.explore-list-wrap {
.cts {
font-family: $font-family-regular;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
}
:deep(.overflow-text) {
color: var(--Text-1, #211f24);
font-family: $font-family-regular;

View File

@ -166,8 +166,9 @@ export default {
</div>
{renderMainImg()}
<p class="cts !color-#211F24 ">{dataSource.value.content}</p>
<div class="w-full">
<p class="cts !color-#211F24 ">{dataSource.value.content}</p>
</div>
{/* 仅图片类型显示图片列表 */}
{!isVideo.value && (