diff --git a/src/assets/core.scss b/src/assets/core.scss index 92a70d2..71d1854 100644 --- a/src/assets/core.scss +++ b/src/assets/core.scss @@ -443,21 +443,32 @@ } .article-title { - @apply px-6 pt-10 pb-6; + border-bottom: 1px solid rgba(0,0,0,0.09); } .article-body { - @apply p-6 + @apply p-6 pt-1; } .modal-control-footer { @apply p-6 } - + .hot-news-list{ + @apply focus-within:bg-[#e6ebf1] focus-within:border-gray-100; + } .input-box { // 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; + 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{ diff --git a/src/components/article/assets/bg1.jpg b/src/components/article/assets/bg1.jpg new file mode 100644 index 0000000..ec7674c Binary files /dev/null and b/src/components/article/assets/bg1.jpg differ diff --git a/src/components/article/assets/bg2.jpg b/src/components/article/assets/bg2.jpg new file mode 100644 index 0000000..7750103 Binary files /dev/null and b/src/components/article/assets/bg2.jpg differ diff --git a/src/components/article/edit-modal.tsx b/src/components/article/edit-modal.tsx index 984c159..1567dca 100644 --- a/src/components/article/edit-modal.tsx +++ b/src/components/article/edit-modal.tsx @@ -1,21 +1,25 @@ -import {Modal,App} from "antd"; -import React, {useEffect, useState} from "react"; -import {useSetState} from "ahooks"; -import {useTranslation} from "react-i18next"; -import * as article from "@/service/api/article.ts"; -import {regenerate} from "@/service/api/video.ts"; -import {push2video} from "@/service/api/article.ts"; -import {showErrorToast, showToast} from "@/components/message.ts"; -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"; +import { Modal, App, Radio, Popover } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { useSetState } from 'ahooks'; +import { useTranslation } from 'react-i18next'; +import { TFunction } from 'i18next'; + +import * as article from '@/service/api/article.ts'; +import { regenerate } from '@/service/api/video.ts'; +import { push2video } from '@/service/api/article.ts'; +import { showErrorToast, showToast } from '@/components/message.ts'; +import ArticleGroup, { HotNewsData } from '@/components/article/group.tsx'; +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 = { id?: number; type: 'news' | 'video'; onClose?: (saved?: boolean) => void; - onRefresh?: ()=>void + onRefresh?: () => void } const DEFAULT_STATE = { @@ -24,15 +28,15 @@ const DEFAULT_STATE = { msgTitle: '', msgGroup: '', error: '' -} +}; 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) { // 如果上一个group中没有文本则直接合并 - lastGroup.push(...blocks) + lastGroup.push(...blocks); } else { - groups.push(blocks) + groups.push(blocks); } } @@ -43,109 +47,114 @@ function rebuildGroups(groups: BlockContent[][]) { if (!blocks) return; blocks = blocks.filter(s => !!s).sort((a, b) => { 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 (index == 0) _groups.push(blocks) - else pushBlocksToGroup(blocks, _groups) + if (index == 0) _groups.push(blocks); + else pushBlocksToGroup(blocks, _groups); } else { if (index == 0) { - _groups.push([blocks[0]]) - _groups.push(blocks.slice(1)) + _groups.push([blocks[0]]); + _groups.push(blocks.slice(1)); } else { - pushBlocksToGroup(blocks, _groups) + pushBlocksToGroup(blocks, _groups); } } }); if (_groups.length < 2) { - Array(2 - _groups.length).fill([{type: 'text', content: ''}]).forEach((it) => { - _groups.push(it) - }) + Array(2 - _groups.length).fill([{ type: 'text', content: '' }]).forEach((it) => { + _groups.push(it); + }); } // console.log('rebuildGroups', _groups) return _groups; } + 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[][]) { - const groups = _groups.filter((_,index)=>{ + const groups = _groups.filter((_, index) => { 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; - for (let index = 1;index< groups.length; index ++) { - if(!groupHasImageAndText(groups[index])) return false; + for (let index = 1; index < groups.length; index++) { + if (!groupHasImageAndText(groups[index])) return false; } return true; } -function checkHotNewsValid(hotNews: HotNewsData,modal:ModalHookAPI,t:TFunction<"translation", undefined>) { - return new Promise((resolve)=>{ + +function checkHotNewsValid(hotNews: HotNewsData, modal: ModalHookAPI, t: TFunction<'translation', undefined>) { + return new Promise((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({ wrapClassName: 'root-modal-confirm', - icon: , + icon: , title: t('modal.hot_news.empty_notice_title'), - content: , - centered:true, + content: , + centered: true, onOk: () => { - resolve(false) + resolve(false); }, onCancel: () => { - resolve(false) + resolve(false); } - }) + }); return; } - resolve(true) - }) + resolve(true); + }); } export default function ArticleEditModal(props: Props) { - const {t,i18n} = useTranslation() - const {modal} = App.useApp() + const { t, i18n } = useTranslation(); + const { modal } = App.useApp(); const [groups, setGroups] = useState([]); - const [title, setTitle] = useState('') - const [hotNews,setHotNews] = useState({ - list: ['','',''], + const [title, setTitle] = useState(''); + const [tag, setTag] = useState(''); + const [backgroundImage, setBackgroundImage] = useState('1'); + const [hotNews, setHotNews] = useState({ + list: ['', '', ''], mode: 'auto' - }) + }); const [state, setState] = useSetState({ ...DEFAULT_STATE, - generating:false, - pushed: false, - }) + generating: false, + pushed: false + }); // 保存数据 const handleSave = async () => { - setState({error: ''}) + setState({ error: '' }); if (!title) { // setState({msgTitle: '请输入标题内容'}); return; } 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; } // 验证图文都存在时,文图是否匹配 - if(!checkGroupsValid(groups)) { + if (!checkGroupsValid(groups)) { // 获取图文设置不正确的数据 - setState({msgGroup: t('news.edit_empty_group_content')}); + setState({ msgGroup: t('news.edit_empty_group_content') }); return; } - const hotNewsValid = await checkHotNewsValid(hotNews,modal,t) - if(!hotNewsValid) return; + const hotNewsValid = await checkHotNewsValid(hotNews, modal, t); + if (!hotNewsValid) return; // if (groups.length == 0 || groups[0].length == 0 || !groups[0][0].content) { // // setState({msgGroup: '请输入正文文本内容'}); // return; // } - const save = props.type == 'news' ? article.save : regenerate - setState({loading: true}) + const save = props.type == 'news' ? article.save : regenerate; + setState({ loading: true }); save({ title, metahuman_text: groups[0][0].content, @@ -153,83 +162,83 @@ export default function ArticleEditModal(props: Props) { hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list, id: props.id && props.id > 0 ? props.id : undefined }).then(() => { - props.onClose?.(true) + props.onClose?.(true); }).catch(e => { - setState({error: e.message || t('news.edit_save_failed')}) + setState({ error: e.message || t('news.edit_save_failed') }); }).finally(() => { - setState({loading: false}) + setState({ loading: false }); }); - } - const handlePush2Video = async () =>{ - if(state.pushed) return; + }; + const handlePush2Video = async () => { + if (state.pushed) return; if (!title) { // setState({msgTitle: '请输入标题内容'}); return; } 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; } // 验证图文都存在时,文图是否匹配 - if(!checkGroupsValid(groups)) { + if (!checkGroupsValid(groups)) { // 获取图文设置不正确的数据 - setState({msgGroup: t('news.edit_empty_group_content')}); + setState({ msgGroup: t('news.edit_empty_group_content') }); return; } - if(!props.id || state.generating) return; - const hotNewsValid = await checkHotNewsValid(hotNews,modal,t) - if(!hotNewsValid) return; - setState({generating:true}) + if (!props.id || state.generating) return; + const hotNewsValid = await checkHotNewsValid(hotNews, modal, t); + if (!hotNewsValid) return; + setState({ generating: true }); await article.save({ title, metahuman_text: groups[0][0].content, content_group: groups.slice(1), hot_news: hotNews.mode == 'auto' ? [''] : hotNews.list, - id: props.id, - }) + id: props.id + }); push2video([props.id]).then(() => { - showToast(t('news.push_stream_success'), 'success') - setState({pushed:true}) - props.onClose?.(true) + showToast(t('news.push_stream_success'), 'success'); + setState({ pushed: true }); + props.onClose?.(true); // props.onRefresh?.(); // navigate('/create?state=push-success',{ // state: 'push-success' // }) // props.onSuccess?.() - }).catch(showErrorToast).finally(()=>{ - setState({generating:false}) - }) - } + }).catch(showErrorToast).finally(() => { + setState({ generating: false }); + }); + }; useEffect(() => { - setState({...DEFAULT_STATE}) + setState({ ...DEFAULT_STATE }); if (typeof (props.id) != 'undefined') { // 如果传入了id则获取数据 if (props.id > 0) { article.getById(props.id).then(res => { - if(res.hot_news){ - const len = res.hot_news.length - 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'; + if (res.hot_news) { + const len = res.hot_news.length; + 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'; setHotNews({ list, mode - }) + }); } - setGroups(rebuildGroups([[{content: res.metahuman_text, type: "text"}], ...res.content_group])) - setTitle(res.title) - }) + setGroups(rebuildGroups([[{ content: res.metahuman_text, type: 'text' }], ...res.content_group])); + setTitle(res.title); + }); } else { // 新增 - setGroups([]) - setTitle('') + setGroups([]); + setTitle(''); } } - }, [props.id]) + }, [props.id]); return (= 0} maskClosable={false} keyboard={false} @@ -237,32 +246,49 @@ export default function ArticleEditModal(props: Props) { footer={null} closeIcon={null} onCancel={() => props.onClose?.()} - okButtonProps={{loading: state.loading}} + okButtonProps={{ loading: state.loading }} onOk={handleSave} okText={props.type == 'news' ? t('confirm_text') : t('news.edit_generate_video_again')} > -
-
+
+
{t('news.title')} - { - setTitle(e.target.value) - setState({msgTitle: e.target.value ? '' : t('news.edit_notice_enter_article_title1')}) - }} placeholder={t('news.edit_notice_enter_article_title')}/> + { + setTitle(e.target.value); + setState({ msgTitle: e.target.value ? '' : t('news.edit_notice_enter_article_title1') }); + }} placeholder={t('news.edit_notice_enter_article_title')} />
{state.msgTitle}
-
+
{ - setHotNews(hotNews) - setGroups(() => list) - setState({msgGroup: (list.length == 0 || list[0].length == 0 || !list[0][0].content) ? t('news.edit_empty_human_content') : ''}); + onChange={(list, hotNews) => { + setHotNews(hotNews); + setGroups(() => list); + setState({ msgGroup: (list.length == 0 || list[0].length == 0 || !list[0][0].content) ? t('news.edit_empty_human_content') : '' }); }} + leftPanelHeader={
+
+ {t('news.edit.tag')} + { + setTag(e.target.value); + }} placeholder={t('news.edit.tag_placeholder')} /> +
+
+ {t('news.edit.bg')} +
+ + }>背景1 + }>背景2 + +
+
+
} />
{state.msgGroup}
@@ -270,9 +296,11 @@ export default function ArticleEditModal(props: Props) {
- {props.type == 'news' && props.id ? : null} + {props.type == 'news' && props.id ? : null} - +
); diff --git a/src/components/article/group.tsx b/src/components/article/group.tsx index 0488260..5d41f96 100644 --- a/src/components/article/group.tsx +++ b/src/components/article/group.tsx @@ -18,10 +18,11 @@ type Props = { onChange?: (groups: BlockContent[][], hotNews: HotNewsData) => void; errorMessage?: string; 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 groups = rebuildGroups(_groups) /** @@ -57,19 +58,21 @@ export default function ArticleGroup({groups, editable, onChange, errorMessage, return
+ {leftPanelHeader}
{t('news.edit_digital_text')} {i18n.language == 'zh-CN' && (出现数字人形象)}
-
+
{/* value={groups || groups[0][0].content}*/} -
-
- {editable ?
+
+
+ {editable ?
0 ? groups[0][0].content : ''} - autoSize={{maxRows: hotNews.mode == 'auto'?20:13}} + autoSize={{maxRows: hotNews.mode == 'auto'?15:8}} variant={"borderless"} onChange={e => { handleDigitalPersonContentChange(e.target.value) diff --git a/src/i18n/translations/en-US.json b/src/i18n/translations/en-US.json index 7490cc3..7c8be31 100644 --- a/src/i18n/translations/en-US.json +++ b/src/i18n/translations/en-US.json @@ -93,6 +93,11 @@ "delete_the_picture": "Are you sure delete the picture?", "download_empty": "Please select the news to download", "download_failed": "Download failed!", + "edit": { + "bg": "Background", + "tag": "Tag", + "tag_placeholder": "Example: Enterprise dynamics" + }, "edit_add_group": "Add Group", "edit_delete_group": "Delete Group", "edit_delete_group_confirm": "Are you sure you want to delete the group?", diff --git a/src/i18n/translations/zh-CN.json b/src/i18n/translations/zh-CN.json index c41726e..fc60d7e 100644 --- a/src/i18n/translations/zh-CN.json +++ b/src/i18n/translations/zh-CN.json @@ -93,6 +93,11 @@ "delete_the_picture": "请确认删除此图片", "download_empty": "请选择要下载的新闻", "download_failed": "下载新闻失败,请重试!", + "edit": { + "bg": "背景", + "tag": "标签", + "tag_placeholder": "例:企业动态" + }, "edit_add_group": "新增分组", "edit_delete_group": "删除此分组", "edit_delete_group_confirm": "请确认删除此分组?", diff --git a/src/pages/live/index.tsx b/src/pages/live/index.tsx index 4d59381..cbbcd53 100644 --- a/src/pages/live/index.tsx +++ b/src/pages/live/index.tsx @@ -87,6 +87,7 @@ export default function LiveIndex() { const playedTime = (Date.now() / 1000 >> 0) - liveState.live_start_time if (playedTime < 0 || playedTime > duration) { // 已播放时间大于总时长了 //initPlayingState() // 重新获取播放状态 + console.log('已播放时间大于总时长') return; } player.current?.play(video.video_oss_url, playedTime)