diff --git a/src/assets/core.scss b/src/assets/core.scss index 9fd54bc..92a70d2 100644 --- a/src/assets/core.scss +++ b/src/assets/core.scss @@ -170,7 +170,7 @@ @apply text-sm; background: none; .col{ - @apply text-sm text-gray-800; + @apply text-base text-gray-800; height: 42px; } } @@ -180,7 +180,7 @@ } .col { - @apply flex items-center relative pl-4 text-center justify-center; + @apply flex items-center relative pl-4 text-center justify-center text-sm; height: 60px; &:after { @@ -209,7 +209,7 @@ } .title { - @apply flex-1 text-base; + @apply flex-1; } .generated-time { diff --git a/src/assets/images/error/ic_broken_image.png b/src/assets/images/error/ic_broken_image.png new file mode 100644 index 0000000..cb76f97 Binary files /dev/null and b/src/assets/images/error/ic_broken_image.png differ diff --git a/src/components/video/video-list-item.tsx b/src/components/video/video-list-item.tsx index 21ffd28..e09c645 100644 --- a/src/components/video/video-list-item.tsx +++ b/src/components/video/video-list-item.tsx @@ -137,7 +137,7 @@ export const VideoListItem = ( {/* : )}*/} -
+
{downloadUrl && video.status == VideoStatus.Generated && - + } {hideCheckBox ? <> : { diff --git a/src/pages/live/index.tsx b/src/pages/live/index.tsx index f0434ed..4d59381 100644 --- a/src/pages/live/index.tsx +++ b/src/pages/live/index.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from "react"; -import {Button, Checkbox, Empty, Modal, Popconfirm, Space} from "antd"; +import {Checkbox, Empty, Popconfirm, Space} from "antd"; import {SortableContext, arrayMove} from '@dnd-kit/sortable'; import {DndContext} from "@dnd-kit/core"; import FlvJs from "flv.js"; @@ -7,16 +7,17 @@ import {useTranslation} from "react-i18next"; import {useSetState} from "ahooks"; import {VideoListItem} from "@/components/video/video-list-item.tsx"; -import {deleteByIds, getList, modifyOrder, playState} from "@/service/api/live.ts"; +import {deleteByIds, getList, modifyOrder, playState, restoreByIds} from "@/service/api/live.ts"; import {showErrorToast, showToast} from "@/components/message.ts"; import ButtonBatch from "@/components/button-batch.tsx"; import {formatDuration} from "@/util/strings.ts"; import {Player, PlayerInstance} from "@/components/video/player.tsx"; -import {IconDelete, IconLocked, IconRollbackCircle, IconWarningCircle} from "@/components/icons"; +import {IconDelete, IconLocked, IconRollbackCircle} from "@/components/icons"; import InfiniteScroller, {InfiniteScrollerRef} from "@/components/scoller/infinite-scroller.tsx"; import ButtonToTop from "@/components/scoller/button-to-top.tsx"; import styles from "./style.module.scss" +import {ModalWarningIcon, ModalWarningTitle} from "@/components/icons/ModalWarning.tsx"; const cache: { flvPlayer?: FlvJs.Player, timerPlayNext?: any, timerLoadState?: any, prevUrl?: string } = {} @@ -25,7 +26,6 @@ export default function LiveIndex() { const player = useRef(null) const [videoData, setVideoData] = useState([]) - const [modal, contextHolder] = Modal.useModal() const [checkedIdArray, setCheckedIdArray] = useState([]) const [editable, setEditable] = useState(false) const scrollerRef = useRef(null) @@ -195,7 +195,7 @@ export default function LiveIndex() { await deleteByIds(delIds) } if(rollbackIds.length > 0) { - showToast('回退暂未实现') + await restoreByIds(rollbackIds) } // 调整排序 await modifyOrder(ids); @@ -356,8 +356,9 @@ export default function LiveIndex() { rootClassName={'popconfirm-main'} placement={'left'} arrow={false} - icon={} - title={t('video.live_rollback_confirm_title')} + icon={} + title={} + description={t('video.live_rollback_confirm_title')} onConfirm={() => handleRollback(v)} >} } @@ -388,6 +389,5 @@ export default function LiveIndex() { }
- {contextHolder}
) } \ No newline at end of file diff --git a/src/pages/news/components/search-panel.tsx b/src/pages/news/components/search-panel.tsx index 920ea90..5e1b931 100644 --- a/src/pages/news/components/search-panel.tsx +++ b/src/pages/news/components/search-panel.tsx @@ -12,6 +12,7 @@ import {IconPin} from "@/components/icons"; import {useTranslation} from "react-i18next"; type SearchPanelProps = { + rootClassName?: string; onSearch?: (params: ApiArticleSearchParams) => void; defaultParams?: Partial; hideNewsSource?: boolean; @@ -25,7 +26,14 @@ const DEFAULT_STATE = { tag_level_2_id: -1, subOptions: [] } -export default function SearchPanel({onSearch, defaultParams, hideNewsSource,rightRender}: SearchPanelProps) { +export default function SearchPanel( + { + onSearch, + defaultParams, + hideNewsSource, + rightRender, + rootClassName + }: SearchPanelProps) { const tags = useArticleTags(); const {t} = useTranslation() const [params, setParams] = useSetState({ @@ -143,7 +151,7 @@ export default function SearchPanel({onSearch, defaultParams, hideNewsSource,rig const setFalse = () => togglePinnedManagePanel(false) useClickAway(() => setFalse(), pinnedManagePanel) - return (
+ return (
- {t('order.left_time')}: {formatDurationToTime(data?.remaining_duration)} -
} - /> -
+ return
+
+
+ {t('order.left_time')}: {formatDurationToTime(data?.remaining_duration)} +
} + /> +
+
{t('order.list.id')}
@@ -39,7 +43,7 @@ function OrderIndex() {
{t('order.list.consume_time')}
{t('order.list.operator')}
-
+
{data?.list.length === 0 &&
} @@ -51,24 +55,23 @@ function OrderIndex() {
- +
+ +
-
{item.title}
+
{item.title}
-
-
{formatTime(item.order_time, 'YYYY-MM-DD HH:mm')}
+
{formatTime(item.order_time, 'YYYY-MM-DD HH:mm')}
-
-
{formatDurationToTime(item.consumption_duration)}
-
-
-
{item.operator}
+
{formatDurationToTime(item.consumption_duration)}
+
{item.operator}
})} diff --git a/src/pages/recycle/components/video-item.tsx b/src/pages/recycle/components/video-item.tsx index ae67107..23ed2cd 100644 --- a/src/pages/recycle/components/video-item.tsx +++ b/src/pages/recycle/components/video-item.tsx @@ -7,7 +7,7 @@ import styles from './style.module.scss' type VideoItemProps = { videoInfo: VideoInfo; onLive?: boolean; - onClick?: (autoPlay:boolean) => void; + onClick?: (autoPlay: boolean) => void; onRemove?: () => void; onCheckedChange?: (checked: boolean) => void; checked?: boolean; @@ -25,14 +25,14 @@ export default function VideoItem(props: VideoItemProps) {
-
props.onClick?.(true)}>
+
props.onClick?.(true)}>
props.onClick?.(false)}>{props.videoInfo.title}
-
{timeFromNow(props.videoInfo.ctime)}
+ onClick={() => props.onClick?.(false)}>{props.videoInfo.title}
+
{timeFromNow(props.videoInfo.d_time)}
{Math.ceil(props.videoInfo.duration / 1000)}s diff --git a/src/routes/layout/dashboard-layout.tsx b/src/routes/layout/dashboard-layout.tsx index f6d03be..902269b 100644 --- a/src/routes/layout/dashboard-layout.tsx +++ b/src/routes/layout/dashboard-layout.tsx @@ -1,6 +1,6 @@ -import {Outlet, useLocation, useNavigate, useSearchParams} from "react-router-dom"; -import {Button, Divider, Dropdown, MenuProps} from "antd"; -import React, {useEffect} from "react"; +import {Outlet, useLocation, useNavigate} from "react-router-dom"; +import {Divider, Dropdown, MenuProps} from "antd"; +import React, {useEffect, useMemo} from "react"; import {useTranslation} from "react-i18next"; import AuthGuard from "@/routes/layout/auth-guard.tsx"; @@ -13,7 +13,6 @@ import useAuth from "@/hooks/useAuth.ts"; import {hidePhone} from "@/util/strings.ts"; import {defaultCache} from "@/hooks/useCache.ts"; import {IconOrderFill, IconRecycleFill} from "@/components/icons"; -import useGlobalConfig from "@/hooks/useGlobalConfig.ts"; import LanguageSwitcher from "@/components/icons/language-switcher.tsx"; @@ -84,13 +83,25 @@ const NavigationUserContainer = () => { : }
) } +const ExtraNavItems = { + '/order':'order.text', + '/recycle':'history.text', +} export const BaseLayout: React.FC = ({children}) => { - + const {pathname} = useLocation() + const {t,i18n} = useTranslation() + const extraNav = useMemo(()=>{ + if(!pathname || !ExtraNavItems[pathname]) return null + return t(ExtraNavItems[pathname]) + },[pathname,i18n.language]) return (
-
+
+ {extraNav &&
+ {extraNav} +
}
diff --git a/src/service/api/live.ts b/src/service/api/live.ts index 735a3e5..a69274c 100644 --- a/src/service/api/live.ts +++ b/src/service/api/live.ts @@ -15,6 +15,9 @@ export function modifyOrder(ids: Id[]) { export function deleteByIds(ids: Id[]) { return post('/room/remove', {ids}) } +export function restoreByIds(ids: Id[]) { + return post('/room/restore', {ids}) +} export function getLiveUrl() { return get<{flv_url:string}>({ diff --git a/src/types/api.d.ts b/src/types/api.d.ts index 10cd5e0..eb96ee7 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -108,6 +108,7 @@ declare interface VideoInfo { status: number; publish_time?: number|string; ctime?: number|string; + d_time?: number|string; } declare interface VideoListItem extends VideoInfo { playing?: boolean; diff --git a/src/util/strings.ts b/src/util/strings.ts index 2f3bab7..d1b2648 100644 --- a/src/util/strings.ts +++ b/src/util/strings.ts @@ -58,7 +58,7 @@ function getDayjs(time:any){ export function formatDurationToTime(duration?: number|string) { duration = duration ? Number(duration) : 0; if (!duration || isNaN(duration) || duration < 0) return '00:00'; - duration = Math.ceil(duration); + duration = Math.ceil(duration / 1000); // 计算 const hour = Math.floor(duration / 3600); const minute = Math.floor((duration - hour * 3600) / 60);