feat: 新闻编辑UI新增背景选择
This commit is contained in:
parent
b7b15e7471
commit
d270d615a2
@ -443,21 +443,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.article-title {
|
.article-title {
|
||||||
@apply px-6 pt-10 pb-6;
|
border-bottom: 1px solid rgba(0,0,0,0.09);
|
||||||
}
|
}
|
||||||
|
|
||||||
.article-body {
|
.article-body {
|
||||||
@apply p-6
|
@apply p-6 pt-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-control-footer {
|
.modal-control-footer {
|
||||||
@apply p-6
|
@apply p-6
|
||||||
}
|
}
|
||||||
|
.hot-news-list{
|
||||||
|
@apply focus-within:bg-[#e6ebf1] focus-within:border-gray-100;
|
||||||
|
}
|
||||||
.input-box {
|
.input-box {
|
||||||
// focus-within:shadow
|
// focus-within:shadow
|
||||||
@apply bg-[#f8f8f8] border border-transparent w-full px-4 py-2 focus-within:bg-[#f0f0f0] focus-within:border-gray-300;
|
@apply text-base bg-[#f8f8f8] border border-transparent w-full px-3 focus-within:bg-[#f3f3f3] focus-within:border-gray-100;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
color:#3d3d3d;
|
||||||
|
}
|
||||||
|
.main-human-text{
|
||||||
|
@apply focus-within:bg-[#e6ebf1] focus-within:border-gray-100;
|
||||||
|
}
|
||||||
|
.main-human-text-input{
|
||||||
|
// focus-within:shadow
|
||||||
|
@apply text-base bg-[#f8f8f8] border border-transparent w-full p-2;
|
||||||
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.icon-language{
|
.icon-language{
|
||||||
|
BIN
src/components/article/assets/bg1.jpg
Normal file
BIN
src/components/article/assets/bg1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
src/components/article/assets/bg2.jpg
Normal file
BIN
src/components/article/assets/bg2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
@ -1,21 +1,25 @@
|
|||||||
import {Modal,App} from "antd";
|
import { Modal, App, Radio, Popover } from 'antd';
|
||||||
import React, {useEffect, useState} from "react";
|
import React, { useEffect, useState } from 'react';
|
||||||
import {useSetState} from "ahooks";
|
import { useSetState } from 'ahooks';
|
||||||
import {useTranslation} from "react-i18next";
|
import { useTranslation } from 'react-i18next';
|
||||||
import * as article from "@/service/api/article.ts";
|
import { TFunction } from 'i18next';
|
||||||
import {regenerate} from "@/service/api/video.ts";
|
|
||||||
import {push2video} from "@/service/api/article.ts";
|
import * as article from '@/service/api/article.ts';
|
||||||
import {showErrorToast, showToast} from "@/components/message.ts";
|
import { regenerate } from '@/service/api/video.ts';
|
||||||
import ArticleGroup, {HotNewsData} from "@/components/article/group.tsx";
|
import { push2video } from '@/service/api/article.ts';
|
||||||
import type {HookAPI as ModalHookAPI} from "antd/es/modal/useModal";
|
import { showErrorToast, showToast } from '@/components/message.ts';
|
||||||
import {TFunction} from "i18next";
|
import ArticleGroup, { HotNewsData } from '@/components/article/group.tsx';
|
||||||
import {IconWarningCircle} from "@/components/icons";
|
import type { HookAPI as ModalHookAPI } from 'antd/es/modal/useModal';
|
||||||
|
import { IconWarningCircle } from '@/components/icons';
|
||||||
|
|
||||||
|
import Bg1 from './assets/bg1.jpg'
|
||||||
|
import Bg2 from './assets/bg2.jpg'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id?: number;
|
id?: number;
|
||||||
type: 'news' | 'video';
|
type: 'news' | 'video';
|
||||||
onClose?: (saved?: boolean) => void;
|
onClose?: (saved?: boolean) => void;
|
||||||
onRefresh?: ()=>void
|
onRefresh?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
@ -24,15 +28,15 @@ const DEFAULT_STATE = {
|
|||||||
msgTitle: '',
|
msgTitle: '',
|
||||||
msgGroup: '',
|
msgGroup: '',
|
||||||
error: ''
|
error: ''
|
||||||
}
|
};
|
||||||
|
|
||||||
function pushBlocksToGroup(blocks: BlockContent[], groups: BlockContent[][]) {
|
function pushBlocksToGroup(blocks: BlockContent[], groups: BlockContent[][]) {
|
||||||
const lastGroup = groups[groups.length - 1]
|
const lastGroup = groups[groups.length - 1];
|
||||||
if (lastGroup && lastGroup.filter(s => s.type == 'text').length == 0) {
|
if (lastGroup && lastGroup.filter(s => s.type == 'text').length == 0) {
|
||||||
// 如果上一个group中没有文本则直接合并
|
// 如果上一个group中没有文本则直接合并
|
||||||
lastGroup.push(...blocks)
|
lastGroup.push(...blocks);
|
||||||
} else {
|
} else {
|
||||||
groups.push(blocks)
|
groups.push(blocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,109 +47,114 @@ function rebuildGroups(groups: BlockContent[][]) {
|
|||||||
if (!blocks) return;
|
if (!blocks) return;
|
||||||
blocks = blocks.filter(s => !!s).sort((a, b) => {
|
blocks = blocks.filter(s => !!s).sort((a, b) => {
|
||||||
if (a.type == 'text' && b.type == 'text') return 1;
|
if (a.type == 'text' && b.type == 'text') return 1;
|
||||||
return a.type == 'text' ? -1 : 1
|
return a.type == 'text' ? -1 : 1;
|
||||||
})
|
});
|
||||||
if (blocks.length == 1) {
|
if (blocks.length == 1) {
|
||||||
if (index == 0) _groups.push(blocks)
|
if (index == 0) _groups.push(blocks);
|
||||||
else pushBlocksToGroup(blocks, _groups)
|
else pushBlocksToGroup(blocks, _groups);
|
||||||
} else {
|
} else {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
_groups.push([blocks[0]])
|
_groups.push([blocks[0]]);
|
||||||
_groups.push(blocks.slice(1))
|
_groups.push(blocks.slice(1));
|
||||||
} else {
|
} else {
|
||||||
pushBlocksToGroup(blocks, _groups)
|
pushBlocksToGroup(blocks, _groups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (_groups.length < 2) {
|
if (_groups.length < 2) {
|
||||||
Array(2 - _groups.length).fill([{type: 'text', content: ''}]).forEach((it) => {
|
Array(2 - _groups.length).fill([{ type: 'text', content: '' }]).forEach((it) => {
|
||||||
_groups.push(it)
|
_groups.push(it);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
// console.log('rebuildGroups', _groups)
|
// console.log('rebuildGroups', _groups)
|
||||||
return _groups;
|
return _groups;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function groupHasImageAndText(blocks: BlockContent[]) {
|
function groupHasImageAndText(blocks: BlockContent[]) {
|
||||||
return blocks.some(s=>s.type == 'image' && s.content.trim().length > 0) && blocks.some(s=>s.type == 'text' && s.content.trim().length > 0)
|
return blocks.some(s => s.type == 'image' && s.content.trim().length > 0) && blocks.some(s => s.type == 'text' && s.content.trim().length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证分组数据是否合法
|
// 验证分组数据是否合法
|
||||||
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 || (_.length == 1 && _[0].content.trim().length > 0) ;
|
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++) {
|
||||||
if(!groupHasImageAndText(groups[index])) return false;
|
if (!groupHasImageAndText(groups[index])) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
function checkHotNewsValid(hotNews: HotNewsData,modal:ModalHookAPI,t:TFunction<"translation", undefined>) {
|
|
||||||
return new Promise<boolean>((resolve)=>{
|
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){
|
if (hotNews.mode == 'manual' && hotNews.list.filter(s => s.trim().length > 0).length < 3) {
|
||||||
modal.warning({
|
modal.warning({
|
||||||
wrapClassName: 'root-modal-confirm',
|
wrapClassName: 'root-modal-confirm',
|
||||||
icon: <span className="anticon anticon-exclamation-circle"><IconWarningCircle/></span>,
|
icon: <span className="anticon anticon-exclamation-circle"><IconWarningCircle /></span>,
|
||||||
title: t('modal.hot_news.empty_notice_title'),
|
title: t('modal.hot_news.empty_notice_title'),
|
||||||
content: <span dangerouslySetInnerHTML={{__html:t('modal.hot_news.empty_notice_message')}}></span>,
|
content: <span dangerouslySetInnerHTML={{ __html: t('modal.hot_news.empty_notice_message') }}></span>,
|
||||||
centered:true,
|
centered: true,
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
resolve(false)
|
resolve(false);
|
||||||
},
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
resolve(false)
|
resolve(false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(true)
|
resolve(true);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ArticleEditModal(props: Props) {
|
export default function ArticleEditModal(props: Props) {
|
||||||
const {t,i18n} = useTranslation()
|
const { t, i18n } = useTranslation();
|
||||||
const {modal} = App.useApp()
|
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>({
|
const [tag, setTag] = useState('');
|
||||||
list: ['','',''],
|
const [backgroundImage, setBackgroundImage] = useState('1');
|
||||||
|
const [hotNews, setHotNews] = useState<HotNewsData>({
|
||||||
|
list: ['', '', ''],
|
||||||
mode: 'auto'
|
mode: 'auto'
|
||||||
})
|
});
|
||||||
const [state, setState] = useSetState({
|
const [state, setState] = useSetState({
|
||||||
...DEFAULT_STATE,
|
...DEFAULT_STATE,
|
||||||
generating:false,
|
generating: false,
|
||||||
pushed: false,
|
pushed: false
|
||||||
})
|
});
|
||||||
|
|
||||||
// 保存数据
|
// 保存数据
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
setState({error: ''})
|
setState({ error: '' });
|
||||||
if (!title) {
|
if (!title) {
|
||||||
// setState({msgTitle: '请输入标题内容'});
|
// setState({msgTitle: '请输入标题内容'});
|
||||||
return;
|
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: t('news.edit_empty_human_content')});
|
setState({ msgGroup: t('news.edit_empty_human_content') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 验证图文都存在时,文图是否匹配
|
// 验证图文都存在时,文图是否匹配
|
||||||
if(!checkGroupsValid(groups)) {
|
if (!checkGroupsValid(groups)) {
|
||||||
// 获取图文设置不正确的数据
|
// 获取图文设置不正确的数据
|
||||||
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)
|
const hotNewsValid = await checkHotNewsValid(hotNews, modal, t);
|
||||||
if(!hotNewsValid) return;
|
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({
|
save({
|
||||||
title,
|
title,
|
||||||
metahuman_text: groups[0][0].content,
|
metahuman_text: groups[0][0].content,
|
||||||
@ -153,83 +162,83 @@ export default function ArticleEditModal(props: Props) {
|
|||||||
hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list,
|
hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list,
|
||||||
id: props.id && props.id > 0 ? props.id : undefined
|
id: props.id && props.id > 0 ? props.id : undefined
|
||||||
}).then(() => {
|
}).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') });
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
setState({loading: false})
|
setState({ loading: false });
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
const handlePush2Video = async () =>{
|
const handlePush2Video = async () => {
|
||||||
if(state.pushed) return;
|
if (state.pushed) return;
|
||||||
if (!title) {
|
if (!title) {
|
||||||
// setState({msgTitle: '请输入标题内容'});
|
// setState({msgTitle: '请输入标题内容'});
|
||||||
return;
|
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: t('news.edit_empty_human_content')});
|
setState({ msgGroup: t('news.edit_empty_human_content') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 验证图文都存在时,文图是否匹配
|
// 验证图文都存在时,文图是否匹配
|
||||||
if(!checkGroupsValid(groups)) {
|
if (!checkGroupsValid(groups)) {
|
||||||
// 获取图文设置不正确的数据
|
// 获取图文设置不正确的数据
|
||||||
setState({msgGroup: t('news.edit_empty_group_content')});
|
setState({ msgGroup: t('news.edit_empty_group_content') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!props.id || state.generating) return;
|
if (!props.id || state.generating) return;
|
||||||
const hotNewsValid = await checkHotNewsValid(hotNews,modal,t)
|
const hotNewsValid = await checkHotNewsValid(hotNews, modal, t);
|
||||||
if(!hotNewsValid) return;
|
if (!hotNewsValid) return;
|
||||||
setState({generating:true})
|
setState({ generating: true });
|
||||||
await article.save({
|
await article.save({
|
||||||
title,
|
title,
|
||||||
metahuman_text: groups[0][0].content,
|
metahuman_text: groups[0][0].content,
|
||||||
content_group: groups.slice(1),
|
content_group: groups.slice(1),
|
||||||
hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list,
|
hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list,
|
||||||
id: props.id,
|
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');
|
||||||
setState({pushed:true})
|
setState({ pushed: true });
|
||||||
props.onClose?.(true)
|
props.onClose?.(true);
|
||||||
// props.onRefresh?.();
|
// props.onRefresh?.();
|
||||||
// navigate('/create?state=push-success',{
|
// navigate('/create?state=push-success',{
|
||||||
// state: 'push-success'
|
// state: 'push-success'
|
||||||
// })
|
// })
|
||||||
// props.onSuccess?.()
|
// props.onSuccess?.()
|
||||||
}).catch(showErrorToast).finally(()=>{
|
}).catch(showErrorToast).finally(() => {
|
||||||
setState({generating:false})
|
setState({ generating: false });
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setState({...DEFAULT_STATE})
|
setState({ ...DEFAULT_STATE });
|
||||||
if (typeof (props.id) != 'undefined') {
|
if (typeof (props.id) != 'undefined') {
|
||||||
// 如果传入了id则获取数据
|
// 如果传入了id则获取数据
|
||||||
if (props.id > 0) {
|
if (props.id > 0) {
|
||||||
article.getById(props.id).then(res => {
|
article.getById(props.id).then(res => {
|
||||||
if(res.hot_news){
|
if (res.hot_news) {
|
||||||
const len = res.hot_news.length
|
const len = res.hot_news.length;
|
||||||
const list = len >= 3 ? res.hot_news :res.hot_news.concat(Array(3 - len).fill(''))
|
const list = len >= 3 ? res.hot_news : res.hot_news.concat(Array(3 - len).fill(''));
|
||||||
const mode = res.hot_news && res.hot_news.filter(s=>s.length > 0).length == 3 ?'manual':'auto';
|
const mode = res.hot_news && res.hot_news.filter(s => s.length > 0).length == 3 ? 'manual' : 'auto';
|
||||||
setHotNews({
|
setHotNews({
|
||||||
list,
|
list,
|
||||||
mode
|
mode
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
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);
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
// 新增
|
// 新增
|
||||||
setGroups([])
|
setGroups([]);
|
||||||
setTitle('')
|
setTitle('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [props.id])
|
}, [props.id]);
|
||||||
|
|
||||||
return (<Modal
|
return (<Modal
|
||||||
title={null}
|
title={null}
|
||||||
centered={true}
|
centered={true}
|
||||||
rootClassName={"article-edit-modal"}
|
rootClassName={'article-edit-modal'}
|
||||||
open={props.id != undefined && props.id >= 0}
|
open={props.id != undefined && props.id >= 0}
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
keyboard={false}
|
keyboard={false}
|
||||||
@ -237,32 +246,49 @@ export default function ArticleEditModal(props: Props) {
|
|||||||
footer={null}
|
footer={null}
|
||||||
closeIcon={null}
|
closeIcon={null}
|
||||||
onCancel={() => props.onClose?.()}
|
onCancel={() => props.onClose?.()}
|
||||||
okButtonProps={{loading: state.loading}}
|
okButtonProps={{ loading: state.loading }}
|
||||||
onOk={handleSave}
|
onOk={handleSave}
|
||||||
okText={props.type == 'news' ? t('confirm_text') : t('news.edit_generate_video_again')}
|
okText={props.type == 'news' ? t('confirm_text') : t('news.edit_generate_video_again')}
|
||||||
>
|
>
|
||||||
<div className="article-title mt-5">
|
<div className="mt-5 px-6 pt-10">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center pb-3 article-title">
|
||||||
<span className="mr-2 text-lg">{t('news.title')}</span>
|
<span className="mr-2 text-lg">{t('news.title')}</span>
|
||||||
<input className={'input-box text-lg flex-1'} value={title} onChange={e => {
|
<input className={'input-box text-lg flex-1 py-2'} value={title} onChange={e => {
|
||||||
setTitle(e.target.value)
|
setTitle(e.target.value);
|
||||||
setState({msgTitle: e.target.value ? '' : t('news.edit_notice_enter_article_title1')})
|
setState({ msgTitle: e.target.value ? '' : t('news.edit_notice_enter_article_title1') });
|
||||||
}} placeholder={t('news.edit_notice_enter_article_title')}/>
|
}} placeholder={t('news.edit_notice_enter_article_title')} />
|
||||||
</div>
|
</div>
|
||||||
<div className="text-red-500 mt-2">{state.msgTitle}</div>
|
<div className="text-red-500 mt-2">{state.msgTitle}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="article-body">
|
<div className="article-body">
|
||||||
<div className="box">
|
<div className="box text-base">
|
||||||
<ArticleGroup
|
<ArticleGroup
|
||||||
errorMessage={state.msgGroup}
|
errorMessage={state.msgGroup}
|
||||||
editable
|
editable
|
||||||
groups={groups}
|
groups={groups}
|
||||||
hotNews={hotNews}
|
hotNews={hotNews}
|
||||||
onChange={(list,hotNews) => {
|
onChange={(list, hotNews) => {
|
||||||
setHotNews(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') : '' });
|
||||||
}}
|
}}
|
||||||
|
leftPanelHeader={<div>
|
||||||
|
<div className="row tag flex items-center mt-2">
|
||||||
|
<span className="mr-2">{t('news.edit.tag')}</span>
|
||||||
|
<input className={'input-box flex-1 py-1.5'} value={tag} onChange={e => {
|
||||||
|
setTag(e.target.value);
|
||||||
|
}} placeholder={t('news.edit.tag_placeholder')} />
|
||||||
|
</div>
|
||||||
|
<div className="row bg flex items-center my-3">
|
||||||
|
<span className="mr-2">{t('news.edit.bg')}</span>
|
||||||
|
<div className="bg-radio-container">
|
||||||
|
<Radio.Group>
|
||||||
|
<Popover placement="bottomLeft" arrow={false} content={<img src={Bg1} />}><Radio value="1">背景1</Radio></Popover>
|
||||||
|
<Popover placement="bottomLeft" arrow={false} content={<img src={Bg2} />}><Radio value="2">背景2</Radio></Popover>
|
||||||
|
</Radio.Group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>}
|
||||||
/>
|
/>
|
||||||
<div className="text-red-500 mt-2">{state.msgGroup}</div>
|
<div className="text-red-500 mt-2">{state.msgGroup}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -270,9 +296,11 @@ export default function ArticleEditModal(props: Props) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="modal-control-footer flex justify-end">
|
<div className="modal-control-footer flex justify-end">
|
||||||
<div className="flex gap-10 ">
|
<div className="flex gap-10 ">
|
||||||
{props.type == 'news' && props.id ? <button className="text-gray-400 hover:text-gray-800" onClick={handlePush2Video}>{t('news.edit_generate_video')}{state.pushed?`${i18n.language == 'zh-CN'?'中':''}...`:(state.generating?`${i18n.language == 'zh-CN'?'推送中':'Pushing'}...`:'')}</button> : null}
|
{props.type == 'news' && props.id ? <button className="text-gray-400 hover:text-gray-800"
|
||||||
|
onClick={handlePush2Video}>{t('news.edit_generate_video')}{state.pushed ? `${i18n.language == 'zh-CN' ? '中' : ''}...` : (state.generating ? `${i18n.language == 'zh-CN' ? '推送中' : 'Pushing'}...` : '')}</button> : null}
|
||||||
<button className="text-gray-400 hover:text-gray-800" onClick={() => props.onClose?.()}>{t('cancel')}</button>
|
<button className="text-gray-400 hover:text-gray-800" onClick={() => props.onClose?.()}>{t('cancel')}</button>
|
||||||
<button onClick={handleSave} className="text-gray-800 hover:text-blue-500">{props.type == 'news' ? t('news.save_text') : t('news.edit_generate_again')}</button>
|
<button onClick={handleSave}
|
||||||
|
className="text-gray-800 hover:text-blue-500">{props.type == 'news' ? t('news.save_text') : t('news.edit_generate_again')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>);
|
</Modal>);
|
||||||
|
@ -18,10 +18,11 @@ type Props = {
|
|||||||
onChange?: (groups: BlockContent[][], hotNews: HotNewsData) => void;
|
onChange?: (groups: BlockContent[][], hotNews: HotNewsData) => void;
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
hotNews: HotNewsData;
|
hotNews: HotNewsData;
|
||||||
|
leftPanelHeader?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function ArticleGroup({groups, editable, onChange, errorMessage, hotNews}: Props) {
|
export default function ArticleGroup({groups, editable, onChange, errorMessage, hotNews, leftPanelHeader}: Props) {
|
||||||
const {t, i18n} = useTranslation()
|
const {t, i18n} = useTranslation()
|
||||||
// const groups = rebuildGroups(_groups)
|
// const groups = rebuildGroups(_groups)
|
||||||
/**
|
/**
|
||||||
@ -57,19 +58,21 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage,
|
|||||||
|
|
||||||
return <div className={styles.group}>
|
return <div className={styles.group}>
|
||||||
<div className={'panel digital-person h-[544px]'}>
|
<div className={'panel digital-person h-[544px]'}>
|
||||||
|
{leftPanelHeader}
|
||||||
<div className="area-title">
|
<div className="area-title">
|
||||||
<span className="">{t('news.edit_digital_text')}</span>
|
<span className="">{t('news.edit_digital_text')}</span>
|
||||||
{i18n.language == 'zh-CN' && <span className="text-gray-400">(出现数字人形象)</span>}
|
{i18n.language == 'zh-CN' && <span className="text-gray-400">(出现数字人形象)</span>}
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body p-3 flex-1 ">
|
<div className="panel-body p-3 flex-1 main-human-text">
|
||||||
{/* value={groups || groups[0][0].content}*/}
|
{/* value={groups || groups[0][0].content}*/}
|
||||||
<div className={`pt-2 h-full rounded-xl overflow-hidden bg-gray-50`}>
|
<div className={`h-full rounded-xl overflow-hidden bg-gray-50`}>
|
||||||
<div className="human-tts">
|
<div className="human-tts h-full">
|
||||||
{editable ? <div className="relative">
|
{editable ? <div className="relative h-full">
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
placeholder={t('news.edit_notice_enter_text')}
|
placeholder={t('news.edit_notice_enter_text')}
|
||||||
|
className="main-human-text-input"
|
||||||
value={groups && groups.length > 0 ? groups[0][0].content : ''}
|
value={groups && groups.length > 0 ? groups[0][0].content : ''}
|
||||||
autoSize={{maxRows: hotNews.mode == 'auto'?20:13}}
|
autoSize={{maxRows: hotNews.mode == 'auto'?15:8}}
|
||||||
variant={"borderless"}
|
variant={"borderless"}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
handleDigitalPersonContentChange(e.target.value)
|
handleDigitalPersonContentChange(e.target.value)
|
||||||
|
@ -93,6 +93,11 @@
|
|||||||
"delete_the_picture": "Are you sure delete the picture?",
|
"delete_the_picture": "Are you sure delete the picture?",
|
||||||
"download_empty": "Please select the news to download",
|
"download_empty": "Please select the news to download",
|
||||||
"download_failed": "Download failed!",
|
"download_failed": "Download failed!",
|
||||||
|
"edit": {
|
||||||
|
"bg": "Background",
|
||||||
|
"tag": "Tag",
|
||||||
|
"tag_placeholder": "Example: Enterprise dynamics"
|
||||||
|
},
|
||||||
"edit_add_group": "Add Group",
|
"edit_add_group": "Add Group",
|
||||||
"edit_delete_group": "Delete Group",
|
"edit_delete_group": "Delete Group",
|
||||||
"edit_delete_group_confirm": "Are you sure you want to delete the group?",
|
"edit_delete_group_confirm": "Are you sure you want to delete the group?",
|
||||||
|
@ -93,6 +93,11 @@
|
|||||||
"delete_the_picture": "请确认删除此图片",
|
"delete_the_picture": "请确认删除此图片",
|
||||||
"download_empty": "请选择要下载的新闻",
|
"download_empty": "请选择要下载的新闻",
|
||||||
"download_failed": "下载新闻失败,请重试!",
|
"download_failed": "下载新闻失败,请重试!",
|
||||||
|
"edit": {
|
||||||
|
"bg": "背景",
|
||||||
|
"tag": "标签",
|
||||||
|
"tag_placeholder": "例:企业动态"
|
||||||
|
},
|
||||||
"edit_add_group": "新增分组",
|
"edit_add_group": "新增分组",
|
||||||
"edit_delete_group": "删除此分组",
|
"edit_delete_group": "删除此分组",
|
||||||
"edit_delete_group_confirm": "请确认删除此分组?",
|
"edit_delete_group_confirm": "请确认删除此分组?",
|
||||||
|
@ -87,6 +87,7 @@ export default function LiveIndex() {
|
|||||||
const playedTime = (Date.now() / 1000 >> 0) - liveState.live_start_time
|
const playedTime = (Date.now() / 1000 >> 0) - liveState.live_start_time
|
||||||
if (playedTime < 0 || playedTime > duration) { // 已播放时间大于总时长了
|
if (playedTime < 0 || playedTime > duration) { // 已播放时间大于总时长了
|
||||||
//initPlayingState() // 重新获取播放状态
|
//initPlayingState() // 重新获取播放状态
|
||||||
|
console.log('已播放时间大于总时长')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.current?.play(video.video_oss_url, playedTime)
|
player.current?.play(video.video_oss_url, playedTime)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user