fixed: 订单效果
This commit is contained in:
parent
1be407d34e
commit
cbd476d1e2
4
src/assets/images/error/error_img.svg
Normal file
4
src/assets/images/error/error_img.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3726" width="256" height="256">
|
||||
<path d="M896 213.333333v281.173334l-97.706667-98.133334c-16.64-16.64-43.946667-16.64-60.586666 0L597.333333 537.173333 456.96 396.8a42.496 42.496 0 0 0-60.16 0L256 537.173333 128 408.746667V213.333333c0-46.933333 38.4-85.333333 85.333333-85.333333h597.333334c46.933333 0 85.333333 38.4 85.333333 85.333333z m-128 273.92l128 128.426667V810.666667c0 46.933333-38.4 85.333333-85.333333 85.333333H213.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333v-280.746667l97.706667 97.706667c16.64 16.64 43.52 16.64 60.16 0l140.8-140.8 140.373333 140.373333c16.64 16.64 43.52 16.64 60.16 0l140.8-139.946667z"
|
||||
fill="#e6e6e6" />
|
||||
</svg>
|
After Width: | Height: | Size: 770 B |
@ -8,6 +8,7 @@ import ImageList from "@/components/article/list.tsx";
|
||||
import { BlockText} from "./item.tsx";
|
||||
import styles from './article.module.scss'
|
||||
import {useTranslation} from "react-i18next";
|
||||
import ModalWarning from "@/components/icons/ModalWarning.tsx";
|
||||
|
||||
type Props = {
|
||||
children?: React.ReactNode;
|
||||
@ -86,8 +87,9 @@ export default function ArticleBlock(
|
||||
rootClassName={'popconfirm-main'}
|
||||
placement={'left'}
|
||||
arrow={false}
|
||||
icon={<IconWarningCircle/>}
|
||||
title={<div style={{minWidth: 150}}><span>{t('news.edit_delete_group_confirm')}</span></div>}
|
||||
icon={<ModalWarning.Icon />}
|
||||
title={<ModalWarning.Title />}
|
||||
description={<div style={{minWidth: 150}}><span>{t('news.edit_delete_group_confirm')}</span></div>}
|
||||
onConfirm={onRemove}
|
||||
okText={t('delete')}
|
||||
cancelText={t('cancel')}
|
||||
|
@ -17,6 +17,7 @@ import {formatTime} from "@/util/strings.ts";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {saveAs} from "file-saver";
|
||||
import {DeleteItemPopoverConfirm} from "@/components/message/confirm.tsx";
|
||||
import {showLoading, showToast} from "@/components/message.ts";
|
||||
|
||||
type Props = {
|
||||
video: VideoInfo | LiveVideoInfo,
|
||||
@ -54,7 +55,7 @@ export const VideoListItem = (
|
||||
setNodeRef, transform
|
||||
} = useSortable({resizeObserverConfig: {}, id})
|
||||
|
||||
const {t} = useTranslation()
|
||||
const {t,i18n} = useTranslation()
|
||||
const [state, setState] = useSetState<{ checked?: boolean }>({})
|
||||
useEffect(() => {
|
||||
setState({checked})
|
||||
@ -65,7 +66,14 @@ export const VideoListItem = (
|
||||
const handleDownloadVideo = () => {
|
||||
if (downloadUrl && video.status == VideoStatus.Generated) {
|
||||
const ext = downloadUrl.substring(downloadUrl.lastIndexOf('.'))
|
||||
saveAs(downloadUrl, `${video.title || video.video_title}${ext}`)
|
||||
const loading = showLoading(t('downloading'))
|
||||
try{
|
||||
saveAs(downloadUrl, `${video.title || video.video_title}${ext}`)
|
||||
loading.close()
|
||||
}catch (e){
|
||||
loading.update(t('download_failed'),'error')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return <div
|
||||
@ -129,13 +137,13 @@ export const VideoListItem = (
|
||||
{/* <button className="hover:text-blue-500 cursor-move">*/}
|
||||
{/* <MenuOutlined/>*/}
|
||||
{/* </button> : <button disabled className="cursor-not-allowed"><MenuOutlined/></button>)}*/}
|
||||
<div className={"flex items-center justify-start gap-6"}>
|
||||
<div className={"flex items-center justify-center gap-6"}>
|
||||
{downloadUrl && video.status == VideoStatus.Generated &&
|
||||
<button className="hover:text-blue-500" onClick={e => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
handleDownloadVideo?.()
|
||||
}} style={{fontSize: '1.1em'}}>
|
||||
}} style={{fontSize: '1.1em'}} title={i18n.language == 'zh-CN'?'下载':'Download'}>
|
||||
<IconDownloadOutline/>
|
||||
</button>}
|
||||
{additionOperationBefore}
|
||||
@ -145,7 +153,7 @@ export const VideoListItem = (
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onEdit?.()
|
||||
}} style={{fontSize: '1.1em'}}>
|
||||
}} style={{fontSize: '1.1em'}} title={i18n.language == 'zh-CN'?'修改':'Modify'}>
|
||||
<IconEdit/>
|
||||
</button>}
|
||||
{onRegenerate && <button
|
||||
@ -153,22 +161,24 @@ export const VideoListItem = (
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onRegenerate?.()
|
||||
}} style={{fontSize: '1.1em'}}>
|
||||
}} style={{fontSize: '1.1em'}} title={i18n.language == 'zh-CN'?'重新生成':'Regenerate'}>
|
||||
<IconRegenerate/>
|
||||
</button>}
|
||||
|
||||
{onRemove && <DeleteItemPopoverConfirm
|
||||
{onRemove && !failed && <DeleteItemPopoverConfirm
|
||||
description={failed ? t('video.rollback_confirm_title') : undefined}
|
||||
onConfirm={() => onRemove(failed ? 'rollback' : 'delete')}>
|
||||
<span className="icon-btn">
|
||||
<button className="hover:text-blue-500">
|
||||
<button className="hover:text-blue-500" title={
|
||||
i18n.language == 'zh-CN'?'重新生成':'Regenerate'
|
||||
}>
|
||||
{removeIcon ? removeIcon : (failed ?
|
||||
<IconRollbackCircle/> :
|
||||
<IconDelete/>)}
|
||||
</button>
|
||||
</span>
|
||||
</DeleteItemPopoverConfirm>}
|
||||
{hideCheckBox ? <span className={"inline-block w-[18px] h-1"}></span> :
|
||||
{hideCheckBox ? <></> :
|
||||
<Checkbox checked={state.checked} onChange={() => {
|
||||
if (onCheckedChange) {
|
||||
onCheckedChange(!state.checked)
|
||||
|
@ -15,6 +15,8 @@
|
||||
"delete_failed": "Delete failed",
|
||||
"delete_success": "Delete success",
|
||||
"download": "Download",
|
||||
"downloading": "Downloading...",
|
||||
"download_fail": "Download Failed",
|
||||
"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",
|
||||
|
@ -15,6 +15,8 @@
|
||||
"delete_failed": "删除失败",
|
||||
"delete_success": "删除成功",
|
||||
"download": "下载",
|
||||
"downloading": "下载中...",
|
||||
"download_fail": "下载失败",
|
||||
"error_401": "您没有权限访问本页面",
|
||||
"error_403": "您没有权限访问本页面",
|
||||
"error_404": "访问的页面不存在",
|
||||
|
@ -55,6 +55,9 @@
|
||||
left:0;
|
||||
}
|
||||
}
|
||||
.cover{
|
||||
@apply pl-2;
|
||||
}
|
||||
.title{
|
||||
@apply flex-1 pl-0;
|
||||
&:after{
|
||||
@ -100,13 +103,23 @@
|
||||
.orderDataList{
|
||||
|
||||
:global {
|
||||
.title{
|
||||
justify-content: left;
|
||||
}
|
||||
.id{
|
||||
@apply pl-0;
|
||||
width: 120px;
|
||||
width: 130px;
|
||||
line-height: 1.2em;
|
||||
&:after{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.cover{
|
||||
img{
|
||||
width: 120px;
|
||||
max-height: 50px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@apply flex-1 pl-4;
|
||||
min-width: 100px;
|
||||
|
@ -1,19 +1,19 @@
|
||||
import SearchPanel from "@/pages/news/components/search-panel.tsx";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import styles from "@/pages/news/components/style.module.scss";
|
||||
import {Empty, Image, Pagination} from "antd";
|
||||
import {useRequest} from "ahooks";
|
||||
|
||||
import SearchPanel from "@/pages/news/components/search-panel.tsx";
|
||||
import styles from "@/pages/news/components/style.module.scss";
|
||||
import {formatDurationToTime, formatTime} from "@/util/strings.ts";
|
||||
import {IconDelete, IconEdit, IconWarningCircle} from "@/components/icons";
|
||||
import {Empty, Pagination, PaginationProps, Popconfirm} from "antd";
|
||||
import {useRequest, useSetState} from "ahooks";
|
||||
import {getList} from "@/service/api/order.ts";
|
||||
|
||||
import ImageErr from "@/assets/images/error/error_img.svg"
|
||||
|
||||
function OrderIndex() {
|
||||
const {t} = useTranslation()
|
||||
const [params, setParams] = useState<ApiArticleSearchParams>({
|
||||
pagination: {page: 1, limit: 12},
|
||||
pagination: {page: 1, limit: 10},
|
||||
time_flag: 0,
|
||||
})
|
||||
const {data} = useRequest(() => getList(params), {
|
||||
@ -33,10 +33,10 @@ function OrderIndex() {
|
||||
<div className={`${styles.newListTable} ${styles.orderDataList} `}>
|
||||
<div className="header row flex">
|
||||
<div className="col id w-[160px]">{t('order.list.id')}</div>
|
||||
<div className="col w-[180px]">{t('order.list.cover')}</div>
|
||||
<div className="col cover">{t('order.list.cover')}</div>
|
||||
<div className="col title w-min-60px">{t('order.list.title')}</div>
|
||||
<div className="col w-[180px]">{t('order.list.order_time')}</div>
|
||||
<div className="col w-[180px]">{t('order.list.consume_time')}</div>
|
||||
<div className="col w-[120px]">{t('order.list.consume_time')}</div>
|
||||
<div className="col w-[180px]">{t('order.list.operator')}</div>
|
||||
</div>
|
||||
<div >
|
||||
@ -47,21 +47,24 @@ function OrderIndex() {
|
||||
return <div key={i} className="row flex">
|
||||
<div className="col id w-[160px] text-center">
|
||||
<div className="flex-1">
|
||||
<div className="text-base">{item.order_id}</div>
|
||||
<div className="break-all">{item.order_id}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col w-[180px]">
|
||||
<img src={item.img_url} className="rounded w-[140px] h-[60px]" alt=""/>
|
||||
<div className="col cover">
|
||||
<Image
|
||||
src={item.img_url} preview={false} className="rounded object-cover"
|
||||
fallback={ImageErr}
|
||||
/>
|
||||
</div>
|
||||
<div className="col flex-1 w-min-60px">
|
||||
<div className="text-sm line-clamp-2">{item.title}</div>
|
||||
<div className="col title order-title flex-1 w-min-60px">
|
||||
<div className="line-clamp-2 ">{item.title}</div>
|
||||
</div>
|
||||
<div className="col w-[180px]">
|
||||
<div className="text-sm">{formatTime(item.order_time, 'YYYY-MM-DD HH:mm')}</div>
|
||||
</div>
|
||||
<div className="col w-[180px]">
|
||||
<div className="col w-[120px]">
|
||||
<div
|
||||
className="text-sm">{formatTime(item.consumption_duration, 'YYYY-MM-DD HH:mm')}</div>
|
||||
className="text-sm">{formatDurationToTime(item.consumption_duration)}</div>
|
||||
</div>
|
||||
<div className="col w-[180px]">
|
||||
<div className="text-sm">{item.operator}</div>
|
||||
@ -71,6 +74,12 @@ function OrderIndex() {
|
||||
|
||||
<div className="footer flex justify-end mt-10">
|
||||
<Pagination
|
||||
onChange={(page, limit) => {
|
||||
setParams({
|
||||
...params,
|
||||
pagination: {page, limit}
|
||||
})
|
||||
}}
|
||||
total={data?.pagination.total || 0}
|
||||
showTotal={(total) => <div>{t('page.total_item', {total})}</div>}
|
||||
showSizeChanger={{
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, {useEffect, useRef, useState} from "react";
|
||||
import {Checkbox, Modal, Space} from "antd";
|
||||
import {Checkbox, Empty, Modal, Space} from "antd";
|
||||
import {useRequest, useSetState} from "ahooks";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
@ -78,7 +78,7 @@ export default function RecycleIndex() {
|
||||
autoPlay: boolean
|
||||
}>()
|
||||
const handleAllCheckedChange = (checked: boolean) => {
|
||||
if (!data) return;
|
||||
if (!data || data.pagination.total == 0) return;
|
||||
setCheckedIdArray(checked ? data.list.map(v => v.id) : [])
|
||||
setState({
|
||||
checkedAll: !state.checkedAll
|
||||
@ -107,7 +107,12 @@ export default function RecycleIndex() {
|
||||
{contextHolder}
|
||||
<div className="search-form-container">
|
||||
<SearchForm
|
||||
onSearch={setParams}
|
||||
onSearch={(params) => {
|
||||
setParams({
|
||||
...params,
|
||||
pagination: {...DEFAULT_PAGE_LIMIT}
|
||||
})
|
||||
}}
|
||||
onBtnStartClick={handleLive}
|
||||
loading={loading}
|
||||
/>
|
||||
@ -126,8 +131,10 @@ export default function RecycleIndex() {
|
||||
<span className="text-sm mr-2">{t("select.select_all")}</span>
|
||||
{/*<CheckCircleFilled className={clsx({'text-blue-500': state.checkedAll})}/>*/}
|
||||
</button>
|
||||
<Checkbox checked={checkedIdArray.length == data?.list?.length}
|
||||
onChange={e => handleAllCheckedChange(e.target.checked)}/>
|
||||
<Checkbox
|
||||
disabled={data?.pagination.total == 0 || data?.list?.length == 0}
|
||||
checked={checkedIdArray.length == data?.list?.length}
|
||||
onChange={e => handleAllCheckedChange(e.target.checked)}/>
|
||||
</div>
|
||||
</div>
|
||||
<InfiniteScroller
|
||||
@ -139,6 +146,9 @@ export default function RecycleIndex() {
|
||||
}))
|
||||
}} onScroll={(top) => setState({showToTop: top > 30})}
|
||||
>
|
||||
{data?.pagination.total == 0 && !loading && <div className="mt-20">
|
||||
<Empty/>
|
||||
</div>}
|
||||
<div className={'video-list-container grid gap-4 grid-cols-3 xl:grid-cols-4'}>
|
||||
{data?.list?.map((it, idx) => (
|
||||
<VideoItem
|
||||
@ -189,10 +199,10 @@ export default function RecycleIndex() {
|
||||
icon={<IconArrowRight className={'text-white'}/>}
|
||||
onProcess={restore}
|
||||
confirmMessage={<span dangerouslySetInnerHTML={{
|
||||
__html: checkedIdArray.length == 1
|
||||
? t('video.restore_confirm')
|
||||
: t('video.restore_confirm_count', {count: checkedIdArray.length})
|
||||
}}></span>}
|
||||
__html: checkedIdArray.length == 1
|
||||
? t('video.restore_confirm')
|
||||
: t('video.restore_confirm_count', {count: checkedIdArray.length})
|
||||
}}></span>}
|
||||
emptyMessage={t('video.push_empty')}
|
||||
onError={e => {
|
||||
showToast(String((e as BizError).data || e.message), 'error')
|
||||
|
@ -306,6 +306,11 @@ export default function VideoIndex() {
|
||||
<ButtonPush2Room ids={checkedIdArray} list={videoData} onSuccess={loadList}/>
|
||||
</div>
|
||||
</div>
|
||||
<ArticleEditModal type={'video'} id={editId} onClose={() => setEditId(-1)}/>
|
||||
<ArticleEditModal type={'video'} id={editId} onClose={(saved) =>{
|
||||
setEditId(-1)
|
||||
if(saved) {
|
||||
loadList()
|
||||
}
|
||||
}}/>
|
||||
</div>)
|
||||
}
|
@ -30,7 +30,7 @@ export default defineConfig(({mode}) => {
|
||||
AUTH_TOKEN_KEY: process.env.AUTH_TOKEN_KEY || AUTH_TOKEN_KEY,
|
||||
AUTHED_PERSON_DATA_KEY: process.env.AUTHED_PERSON_DATA_KEY || 'digital-person-user-info',
|
||||
ONLY_LIVE: process.env.ONLY_LIVE || 'no',
|
||||
APP_LANG: process.env.APP_LANGUAGE || 'multiple'
|
||||
APP_LANG: process.env.APP_LANGUAGE
|
||||
}),
|
||||
AppMode: JSON.stringify(mode),
|
||||
AppBuildVersion: JSON.stringify(AppPackage.name + '-' + AppPackage.version + '-' + dayjs().format('YYYYMMDDHH_mmss'))
|
||||
|
Loading…
x
Reference in New Issue
Block a user