feat: ️ 新增新闻热点功能,支持手动/自动填充热点内容并完善相关验证逻辑

This commit is contained in:
LittleBoy 2025-04-06 20:26:24 +08:00
parent de7088f642
commit e61bfcc26c
9 changed files with 257 additions and 98 deletions

View File

@ -0,0 +1,61 @@
import styles from './article.module.scss'
import {useTranslation} from "react-i18next";
import {Input, Switch} from "antd";
import {useMemo} from "react";
type HotNewsProps = {
news: string[];
mode: string;
onValueChange: (values: {
news: string[],
mode: string
}) => void;
}
function HotNews({news, mode, onValueChange}: HotNewsProps) {
const {t,i18n} = useTranslation()
const demoPlaceholderList = useMemo(()=>{
return i18n.language == 'zh-CN' ? [
'例:韩正会见英国汇丰集团主席',
'例: 丁薛祥出席全国高校毕业生等青年就业创业工作视频...',
'例:俄称乌方再度袭击俄能源设施 乌称击退俄军进攻',
] : [
'please type hot news',
'please type hot news',
'please type hot news',
]
},[i18n.language])
const handleValueChange = (value: string, index: number) => {
const values = [...news]
values[index] = value
onValueChange({news: values, mode})
}
return (
<div className={`${styles.hotNews} mt-3`}>
<div className="flex justify-between">
<div className="area-title">
<span className="title">{t("modal.hot_news.title")}</span>
</div>
<div className="mode">
<span className="mr-2">{mode == 'auto' ? t("modal.hot_news.edit_auto") : t("modal.hot_news.edit_manual")}</span>
<Switch size="small" checked={mode == 'auto'} onChange={checked => {
onValueChange({news, mode: checked ? 'auto' : 'manual'})
}}/>
</div>
</div>
<div className="hot-news-list panel-body p-3 ">
{news.map((item, index) => <div key={index} className={`hot-news-item bg-gray-50 ${index == 0?'':'mt-3'} rounded-xl`}>
<Input
variant={"borderless"}
readOnly={mode == 'auto'}
placeholder={mode != 'auto' ? demoPlaceholderList[index] : ''}
value={item}
onChange={e => handleValueChange(e.target.value, index)}/>
</div>)}
</div>
</div>
)
}
export default HotNews

View File

@ -46,7 +46,7 @@
@apply flex gap-4; @apply flex gap-4;
:global{ :global{
.area-title{ .area-title{
@apply text-gray-400 text-sm text-gray-800; @apply text-gray-400 text-base text-gray-800;
} }
.digital-person{ .digital-person{
width: 450px; width: 450px;
@ -133,3 +133,9 @@
.textarea { .textarea {
@apply border-0 @apply border-0
} }
// hot news
.hotNews{
.title{}
}

View File

@ -1,12 +1,15 @@
import {Modal} from "antd"; import {Modal,App} from "antd";
import ArticleGroup from "@/components/article/group.tsx"; import React, {useEffect, useState} from "react";
import {useEffect, useState} from "react";
import {useSetState} from "ahooks"; import {useSetState} from "ahooks";
import {useTranslation} from "react-i18next";
import * as article from "@/service/api/article.ts"; import * as article from "@/service/api/article.ts";
import {regenerate} from "@/service/api/video.ts"; import {regenerate} from "@/service/api/video.ts";
import {push2video} from "@/service/api/article.ts"; import {push2video} from "@/service/api/article.ts";
import {showErrorToast, showToast} from "@/components/message.ts"; import {showErrorToast, showToast} from "@/components/message.ts";
import {useTranslation} from "react-i18next"; import ArticleGroup, {HotNewsData} from "@/components/article/group.tsx";
import type {HookAPI as ModalHookAPI} from "antd/es/modal/useModal";
import {TFunction} from "i18next";
import {IconWarningCircle} from "@/components/icons";
type Props = { type Props = {
id?: number; id?: number;
@ -70,7 +73,7 @@ function groupHasImageAndText(blocks: BlockContent[]) {
function checkGroupsValid(_groups: BlockContent[][]) { function checkGroupsValid(_groups: BlockContent[][]) {
const groups = _groups.filter((_,index)=>{ const groups = _groups.filter((_,index)=>{
if (index == 0) return true; if (index == 0) return true;
return _.length>1; return _.length > 1 || (_.length == 1 && _[0].content.trim().length > 0) ;
}) })
if (groups.length == 1) return true; if (groups.length == 1) return true;
for (let index = 1;index< groups.length; index ++) { for (let index = 1;index< groups.length; index ++) {
@ -78,19 +81,46 @@ function checkGroupsValid(_groups: BlockContent[][]) {
} }
return true; return true;
} }
function checkHotNewsValid(hotNews: HotNewsData,modal:ModalHookAPI,t:TFunction<"translation", undefined>) {
return new Promise<boolean>((resolve)=>{
// 验证热点新闻数据是否正确
if(hotNews.mode == 'manual' && hotNews.list.filter(s=>s.trim().length > 0).length < 3){
modal.confirm({
wrapClassName: 'root-modal-confirm',
icon: <span className="anticon anticon-exclamation-circle"><IconWarningCircle/></span>,
title: t('modal.hot_news.empty_notice_title'),
content: t('modal.hot_news.empty_notice_message'),
centered:true,
onOk: () => {
resolve(true)
},
onCancel: () => {
resolve(false)
}
})
return;
}
resolve(true)
})
}
export default function ArticleEditModal(props: Props) { export default function ArticleEditModal(props: Props) {
const {t} = useTranslation() const {t} = useTranslation()
const {modal} = App.useApp()
const [groups, setGroups] = useState<BlockContent[][]>([]); const [groups, setGroups] = useState<BlockContent[][]>([]);
const [title, setTitle] = useState('') const [title, setTitle] = useState('')
const [hotNews,setHotNews] = useState<HotNewsData>({
list: ['','',''],
mode: 'auto'
})
const [state, setState] = useSetState({ const [state, setState] = useSetState({
...DEFAULT_STATE, ...DEFAULT_STATE,
generating:false generating:false
}) })
// 保存数据 // 保存数据
const handleSave = () => { const handleSave = async () => {
setState({error: ''}) setState({error: ''})
if (!title) { if (!title) {
// setState({msgTitle: '请输入标题内容'}); // setState({msgTitle: '请输入标题内容'});
@ -106,13 +136,21 @@ export default function ArticleEditModal(props: Props) {
setState({msgGroup: t('news.edit_empty_group_content')}); setState({msgGroup: t('news.edit_empty_group_content')});
return; return;
} }
const hotNewsValid = await checkHotNewsValid(hotNews,modal,t)
if(!hotNewsValid) return;
// if (groups.length == 0 || groups[0].length == 0 || !groups[0][0].content) { // if (groups.length == 0 || groups[0].length == 0 || !groups[0][0].content) {
// // setState({msgGroup: '请输入正文文本内容'}); // // setState({msgGroup: '请输入正文文本内容'});
// return; // return;
// } // }
const save = props.type == 'news' ? article.save : regenerate const save = props.type == 'news' ? article.save : regenerate
setState({loading: true}) setState({loading: true})
save(title, groups[0][0].content, groups.slice(1), props.id && props.id > 0 ? props.id : undefined).then(() => { save({
title,
metahuman_text: groups[0][0].content,
content_group: groups.slice(1),
hot_news: hotNews.list,
id: props.id && props.id > 0 ? props.id : undefined
}).then(() => {
props.onClose?.(true) props.onClose?.(true)
}).catch(e => { }).catch(e => {
setState({error: e.message || t('news.edit_save_failed')}) setState({error: e.message || t('news.edit_save_failed')})
@ -121,6 +159,7 @@ export default function ArticleEditModal(props: Props) {
}); });
} }
const handlePush2Video = async () =>{ const handlePush2Video = async () =>{
//
if (!title) { if (!title) {
// setState({msgTitle: '请输入标题内容'}); // setState({msgTitle: '请输入标题内容'});
return; return;
@ -136,8 +175,16 @@ export default function ArticleEditModal(props: Props) {
return; return;
} }
if(!props.id || state.generating) return; if(!props.id || state.generating) return;
const hotNewsValid = await checkHotNewsValid(hotNews,modal,t)
if(!hotNewsValid) return;
setState({generating:true}) setState({generating:true})
await article.save(title, groups[0][0].content, groups.slice(1), props.id) await article.save({
title,
metahuman_text: groups[0][0].content,
content_group: groups.slice(1),
hot_news: hotNews.list,
id: props.id,
})
push2video([props.id]).then(() => { push2video([props.id]).then(() => {
showToast(t('news.push_stream_success'), 'success') showToast(t('news.push_stream_success'), 'success')
// navigate('/create?state=push-success',{ // navigate('/create?state=push-success',{
@ -154,6 +201,13 @@ export default function ArticleEditModal(props: Props) {
// 如果传入了id则获取数据 // 如果传入了id则获取数据
if (props.id > 0) { if (props.id > 0) {
article.getById(props.id).then(res => { article.getById(props.id).then(res => {
const len = res.hot_news.length
const list = len >= 3 ? res.hot_news :res.hot_news.concat(Array(3 - len).fill(''))
console.log('list,',list,res.hot_news)
setHotNews({
list,
mode: res.hot_news_mode ?? 'auto'
})
setGroups(rebuildGroups([[{content: res.metahuman_text, type: "text"}], ...res.content_group])) setGroups(rebuildGroups([[{content: res.metahuman_text, type: "text"}], ...res.content_group]))
setTitle(res.title) setTitle(res.title)
}) })
@ -190,8 +244,12 @@ export default function ArticleEditModal(props: Props) {
<div className="article-body"> <div className="article-body">
<div className="box"> <div className="box">
<ArticleGroup <ArticleGroup
errorMessage={state.msgGroup} editable groups={groups} errorMessage={state.msgGroup}
onChange={list => { editable
groups={groups}
hotNews={hotNews}
onChange={(list,hotNews) => {
setHotNews(hotNews)
setGroups(() => list) setGroups(() => list)
setState({msgGroup: (list.length == 0 || list[0].length == 0 || !list[0][0].content) ? t('news.edit_empty_human_content') : ''}); setState({msgGroup: (list.length == 0 || list[0].length == 0 || !list[0][0].content) ? t('news.edit_empty_human_content') : ''});
}} }}

View File

@ -6,16 +6,22 @@ import {showToast} from "@/components/message.ts";
import React from "react"; import React from "react";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {IconAdd} from "@/components/icons"; import {IconAdd} from "@/components/icons";
import HotNews from "@/components/article/HotNews.tsx";
export type HotNewsData = {
list: string[];
mode: string
}
type Props = { type Props = {
groups: BlockContent[][]; groups: BlockContent[][];
editable?: boolean; editable?: boolean;
onChange?: (groups: BlockContent[][]) => void; onChange?: (groups: BlockContent[][], hotNews: HotNewsData) => void;
errorMessage?: string; errorMessage?: string;
hotNews: HotNewsData;
} }
export default function ArticleGroup({groups, editable, onChange, errorMessage}: Props) { export default function ArticleGroup({groups, editable, onChange, errorMessage, hotNews}: Props) {
const {t, i18n} = useTranslation() const {t, i18n} = useTranslation()
// const groups = rebuildGroups(_groups) // const groups = rebuildGroups(_groups)
/** /**
@ -41,12 +47,12 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
} else { } else {
_groups.splice(insertIndex, 0, newGroup) _groups.splice(insertIndex, 0, newGroup)
} }
onChange?.(_groups) onChange?.(_groups, hotNews)
} }
const handleDigitalPersonContentChange = (content: string) => { const handleDigitalPersonContentChange = (content: string) => {
groups[0] = [{type: 'text', content}] groups[0] = [{type: 'text', content}]
onChange?.([...groups]) onChange?.([...groups], hotNews)
} }
return <div className={styles.group}> return <div className={styles.group}>
@ -57,7 +63,8 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
</div> </div>
<div className="panel-body p-3"> <div className="panel-body p-3">
{/* value={groups || groups[0][0].content}*/} {/* value={groups || groups[0][0].content}*/}
<div className="h-[486px] pt-2 rounded-xl overflow-hidden bg-gray-50"> <div className="h-[306px] pt-2 rounded-xl overflow-hidden bg-gray-50">
<div className="human-tts">
{editable ? <div className="relative"> {editable ? <div className="relative">
<Input.TextArea <Input.TextArea
placeholder={t('news.edit_notice_enter_text')} placeholder={t('news.edit_notice_enter_text')}
@ -72,6 +79,16 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
</div> </div>
</div> </div>
</div> </div>
<div className="hot-news-container">
<HotNews
news={hotNews.list} mode={hotNews.mode}
onValueChange={(hotNews) => {
onChange?.([...groups], {
list:hotNews.news,mode: hotNews.mode
})
}}/>
</div>
</div>
<div className={"panel groups-list flex-1"}> <div className={"panel groups-list flex-1"}>
<div className={"area-title"}> <div className={"area-title"}>
<span className="">{t('news.edit_other_text')}</span> <span className="">{t('news.edit_other_text')}</span>
@ -81,9 +98,12 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
<div className="panel-body py-3"> <div className="panel-body py-3">
<div className="max-h-[485px] overflow-auto py-4"> <div className="max-h-[485px] overflow-auto py-4">
{editable && groups.length == 1 && <div className={`${styles.blockContainer} group`}><div className={'divider-container before'}><Divider> {editable && groups.length == 1 && <div className={`${styles.blockContainer} group`}>
<span onClick={()=>handleAddGroup?.(1,1)} className="article-action-add" title={t('news.materials.add_group')}><IconAdd style={{fontSize: 24}}/></span> <div className={'divider-container before'}><Divider>
</Divider></div></div> } <span onClick={() => handleAddGroup?.(1, 1)} className="article-action-add"
title={t('news.materials.add_group')}><IconAdd style={{fontSize: 24}}/></span>
</Divider></div>
</div>}
{groups.map((g, index) => ( {groups.map((g, index) => (
index == 0 ? null : <ArticleBlock index == 0 ? null : <ArticleBlock
@ -92,7 +112,7 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
blocks={g} blocks={g}
onChange={(blocks) => { onChange={(blocks) => {
groups[index] = blocks groups[index] = blocks
onChange?.([...groups]) onChange?.([...groups], hotNews)
}} }}
errorMessage={errorMessage} errorMessage={errorMessage}
index={index} index={index}
@ -105,7 +125,7 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
message.warning(t('news.edit_notice_keep_1')) message.warning(t('news.edit_notice_keep_1'))
return; return;
} }
onChange?.(groups.filter((_, idx) => index !== idx)) onChange?.(groups.filter((_, idx) => index !== idx), hotNews)
}} }}
/> />
))} ))}
@ -113,7 +133,7 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage}:
</div> </div>
</div> </div>
{groups.length == 0 && editable && {groups.length == 0 && editable &&
<ArticleBlock editable onChange={blocks => onChange?.([blocks])} index={0} <ArticleBlock editable onChange={blocks => onChange?.([blocks],hotNews)} index={0}
blocks={[{type: 'text', content: ''}]}/>} blocks={[{type: 'text', content: ''}]}/>}
</div> </div>
} }

View File

@ -1,14 +1,8 @@
{ {
"AppTitle": "AI Livesteam", "AppTitle": "AI Livesteam",
"go_to_home": "Go to Homepage" ,
"Hello": "Hello", "Hello": "Hello",
"cancel": "Cancel", "cancel": "Cancel",
"close": "Close", "close": "Close",
"service_error": "Service exception, please contact customer support.",
"error_401": "You do not have permission to access this page",
"error_403": "You do not have permission to access this page",
"error_404": "Page not found",
"error_500": "Service exception, please contact customer support.",
"confirm": { "confirm": {
"push_title": "Push Notice", "push_title": "Push Notice",
"push_video": "Are you sure editing selected news?", "push_video": "Are you sure editing selected news?",
@ -20,9 +14,14 @@
"delete_failed": "Delete failed", "delete_failed": "Delete failed",
"delete_success": "Delete success", "delete_success": "Delete success",
"download": "Download", "download": "Download",
"error_401": "You do not have permission to access this page",
"error_403": "You do not have permission to access this page",
"error_404": "Page not found",
"error_500": "Service exception, please contact customer support.",
"generating": { "generating": {
"title": "Preview - Click the video to play" "title": "Preview - Click the video to play"
}, },
"go_to_home": "Go to Homepage",
"history": { "history": {
"delete_confirm": "Are you sure you want to delete this video?", "delete_confirm": "Are you sure you want to delete this video?",
"push_success": "Streaming success", "push_success": "Streaming success",
@ -49,6 +48,26 @@
"username": "Please enter your phone number", "username": "Please enter your phone number",
"welcome": "Welcome" "welcome": "Welcome"
}, },
"modal": {
"hot_news": {
"edit_auto": "Smart",
"edit_manual": "Manual",
"empty_notice_message": "\"Hot News\" has not been filled in yet. Should it be filled in automatically by the system?",
"empty_notice_title": "Notice",
"title": "Hot news"
},
"push_article": {
"action_all": "Still generating",
"action_cancel": "Cancel",
"action_skip": "Skip the news",
"content_error": "<span class=\"modal-count-normal\">{{count}}</span> news are selected, and <span class=\"modal-count-warning\">{{error_count}}</span> metahuman contents are too short in these news below. Do you want to transfer them to videos?",
"content_error_single": "<span class=\"modal-count-normal\">{{count}}</span> news is selected, and the metahuman content is too short in this news. Do you want to transfer it to a video?",
"content_normal": "<span class=\"modal-count-normal\">{{count}}</span> news are selected, Do you want to transfer them into videos?",
"content_normal_single": "<span class=\"modal-count-normal\">{{count}}</span> news is selected. Do you want to transfer it to a video?",
"error_title": "Abnormal news"
},
"warning": "Warning"
},
"nav": { "nav": {
"editing": "Editing", "editing": "Editing",
"generating": "Generating", "generating": "Generating",
@ -89,8 +108,8 @@
"get_detail_error": "Get new details failed", "get_detail_error": "Get new details failed",
"image_count": "Images", "image_count": "Images",
"materials": { "materials": {
"title": "News Materials", "add_group": "Add Group",
"add_group": "Add Group" "title": "News Materials"
}, },
"news_all_source": "All", "news_all_source": "All",
"push_empty": "please select the news to edit", "push_empty": "please select the news to edit",
@ -118,6 +137,7 @@
"text": "Select", "text": "Select",
"total": "Total: {{count}}" "total": "Total: {{count}}"
}, },
"service_error": "Service exception, please contact customer support.",
"time_filter": { "time_filter": {
"all": "All", "all": "All",
"last_week": "Last week", "last_week": "Last week",
@ -142,8 +162,8 @@
"delete_description_count": "Are you sure you want to delete these {{count}} videos?", "delete_description_count": "Are you sure you want to delete these {{count}} videos?",
"delete_empty": "Select the video you want to delete", "delete_empty": "Select the video you want to delete",
"download": "Download", "download": "Download",
"generating": "Generating",
"generate_failed": "Generate Failed", "generate_failed": "Generate Failed",
"generating": "Generating",
"playing": "Playing", "playing": "Playing",
"push_confirm": "Are you sure you want to streaming these video?", "push_confirm": "Are you sure you want to streaming these video?",
"push_empty": "Select the video you want to streaming", "push_empty": "Select the video you want to streaming",
@ -159,18 +179,5 @@
"title_generated_time": "Time stamp", "title_generated_time": "Time stamp",
"title_operation": "", "title_operation": "",
"title_thumb": "Cover" "title_thumb": "Cover"
},
"modal": {
"warning": "Warning",
"push_article": {
"content_normal": "<span class=\"modal-count-normal\">{{count}}</span> news are selected, Do you want to transfer them into videos?",
"content_normal_single": "<span class=\"modal-count-normal\">{{count}}</span> news is selected. Do you want to transfer it to a video?",
"content_error": "<span class=\"modal-count-normal\">{{count}}</span> news are selected, and <span class=\"modal-count-warning\">{{error_count}}</span> metahuman contents are too short in these news below. Do you want to transfer them to videos?",
"content_error_single": "<span class=\"modal-count-normal\">{{count}}</span> news is selected, and the metahuman content is too short in this news. Do you want to transfer it to a video?",
"error_title": "Abnormal news",
"action_cancel": "Cancel",
"action_skip": "Skip the news",
"action_all": "Still generating"
}
} }
} }

View File

@ -1,14 +1,8 @@
{ {
"AppTitle": "数字人直播", "AppTitle": "数字人直播",
"go_to_home": "返回首页" ,
"Hello": "你好", "Hello": "你好",
"cancel": "取消", "cancel": "取消",
"close": "关闭", "close": "关闭",
"service_error": "新闻异常,无法生成,请咨询客服",
"error_401": "您没有权限访问本页面",
"error_403": "您没有权限访问本页面",
"error_404": "访问的页面不存在",
"error_500": "服务异常,请咨询客服.",
"confirm": { "confirm": {
"push_title": "推流提示", "push_title": "推流提示",
"push_video": "是否确定一键推流选中新闻视频?", "push_video": "是否确定一键推流选中新闻视频?",
@ -20,9 +14,14 @@
"delete_failed": "删除失败", "delete_failed": "删除失败",
"delete_success": "删除成功", "delete_success": "删除成功",
"download": "下载", "download": "下载",
"error_401": "您没有权限访问本页面",
"error_403": "您没有权限访问本页面",
"error_404": "访问的页面不存在",
"error_500": "服务异常,请咨询客服.",
"generating": { "generating": {
"title": "预览视频 - 点击视频列表播放" "title": "预览视频 - 点击视频列表播放"
}, },
"go_to_home": "返回首页",
"history": { "history": {
"delete_confirm": "是否要删除该视频", "delete_confirm": "是否要删除该视频",
"push_success": "一键推流成功,已推流至数字人直播间,请查看!", "push_success": "一键推流成功,已推流至数字人直播间,请查看!",
@ -49,6 +48,26 @@
"username": "请输入账号", "username": "请输入账号",
"welcome": "欢迎登录" "welcome": "欢迎登录"
}, },
"modal": {
"hot_news": {
"edit_auto": "智能填充",
"edit_manual": "手动编辑",
"empty_notice_message": "“新闻热点”尚未填写,是否由系统自动填充?",
"empty_notice_title": "操作提示",
"title": "新闻热点"
},
"push_article": {
"action_all": "全部生成",
"action_cancel": "全部取消",
"action_skip": "跳过异常新闻",
"content_error": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,<span class=\"modal-count-warning\">{{error_count}}</span>条新闻数字人播报字数过少,是否生成全部<span class=\"modal-count-normal\">{{count}}</span>条视频?",
"content_error_single": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,<span class=\"modal-count-warning\">{{error_count}}</span>条新闻数字人播报字数过少,是否生成全部<span class=\"modal-count-normal\">{{count}}</span>条视频?",
"content_normal": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,是否全部生成?",
"content_normal_single": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,是否生成?",
"error_title": "异常新闻"
},
"warning": "操作提示"
},
"nav": { "nav": {
"editing": "新闻编辑", "editing": "新闻编辑",
"generating": "视频生成", "generating": "视频生成",
@ -89,8 +108,8 @@
"get_detail_error": "获取新闻详情失败", "get_detail_error": "获取新闻详情失败",
"image_count": "图片数", "image_count": "图片数",
"materials": { "materials": {
"title": "新闻素材", "add_group": "新增分组",
"add_group": "新增分组" "title": "新闻素材"
}, },
"news_all_source": "全部来源", "news_all_source": "全部来源",
"push_empty": "请选择要推入编辑的新闻", "push_empty": "请选择要推入编辑的新闻",
@ -118,6 +137,7 @@
"text": "选择", "text": "选择",
"total": "总共 {{count}} 条" "total": "总共 {{count}} 条"
}, },
"service_error": "新闻异常,无法生成,请咨询客服",
"time_filter": { "time_filter": {
"all": "所有时间", "all": "所有时间",
"last_week": "近一周", "last_week": "近一周",
@ -142,8 +162,8 @@
"delete_description_count": "已选择{{count}}条,确定要全部删除吗?", "delete_description_count": "已选择{{count}}条,确定要全部删除吗?",
"delete_empty": "请选择要删除的视频", "delete_empty": "请选择要删除的视频",
"download": "下载视频", "download": "下载视频",
"generating": "生成中",
"generate_failed": "生成失败", "generate_failed": "生成失败",
"generating": "生成中",
"playing": "播放中", "playing": "播放中",
"push_confirm": "是否确定一键推流选中新闻视频?", "push_confirm": "是否确定一键推流选中新闻视频?",
"push_empty": "请选择要推流的新闻视频", "push_empty": "请选择要推流的新闻视频",
@ -159,18 +179,5 @@
"title_generated_time": "生成时间", "title_generated_time": "生成时间",
"title_operation": "操作", "title_operation": "操作",
"title_thumb": "缩略图" "title_thumb": "缩略图"
},
"modal": {
"warning": "操作提示",
"push_article": {
"content_normal": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,是否全部生成?",
"content_normal_single": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,是否生成?",
"content_error": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,<span class=\"modal-count-warning\">{{error_count}}</span>条新闻数字人播报字数过少,是否生成全部<span class=\"modal-count-normal\">{{count}}</span>条视频?",
"content_error_single": "已选中<span class=\"modal-count-normal\">{{count}}</span>条新闻,<span class=\"modal-count-warning\">{{error_count}}</span>条新闻数字人播报字数过少,是否生成全部<span class=\"modal-count-normal\">{{count}}</span>条视频?",
"error_title": "异常新闻",
"action_cancel": "全部取消",
"action_skip": "跳过异常新闻",
"action_all": "全部生成"
}
} }
} }

View File

@ -20,13 +20,8 @@ export function getById(id: Id) {
return post<ArticleDetail>({url: '/article/detail/' + id}) return post<ArticleDetail>({url: '/article/detail/' + id})
} }
export function save(title: string, metahuman_text: string, content_group: BlockContent[][], id?: number) { export function save(params:{title: string, metahuman_text: string, content_group: BlockContent[][],hot_news: string[], id?: number}) {
return post<{ content: string }>(id && id > 0 ? '/article/modify' : '/article/create/new', { return post<{ content: string }>(params.id && params.id > 0 ? '/article/modify' : '/article/create/new',params)
title,
metahuman_text,
content_group,
id
})
} }
export function push2video(article_ids: Id[]) { export function push2video(article_ids: Id[]) {

View File

@ -17,21 +17,24 @@ export function deleteHistories(ids: Id[]) {
* @param content_group * @param content_group
* @param article_id * @param article_id
*/ */
export function regenerate(title: string, metahuman_text: string, content_group: BlockContent[][], article_id?: Id) { export function regenerate(params:{title: string, metahuman_text: string, content_group: BlockContent[][], id?: Id}) {
return post<{ content: string }>({ return post<{ content: string }>({
url: '/video/regenerate', url: '/video/regenerate',
data: { data: {
title, ...params,
metahuman_text, article_id:params.id
content_group,
article_id
} }
}) })
} }
// 重新生成视频 // 重新生成视频
export async function regenerateById(article_id: Id) { export async function regenerateById(article_id: Id) {
const article = await getArticle(article_id); const article = await getArticle(article_id);
return await regenerate(article.title, article.metahuman_text, article.content_group, article_id) return await regenerate({
title:article.title,
metahuman_text:article.metahuman_text,
content_group:article.content_group,
id:article_id
})
} }
export function getById(id: Id) { export function getById(id: Id) {

2
src/types/core.d.ts vendored
View File

@ -32,6 +32,8 @@ declare interface ArticleDetail {
id: number; id: number;
title: string; title: string;
metahuman_text: string; metahuman_text: string;
hot_news_mode?: string;
hot_news: string[]; // 4月 6 日新增
content_group: BlockContent[][] content_group: BlockContent[][]
} }