You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

416 lines
13 KiB

import { useTranslation } from '@/i18n.ts'
import { getToken } from '@/store/system.ts'
import { Button, DatePicker, Form, Image, Popconfirm } from 'antd'
import dayjs from 'dayjs'
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
import {
deleteVideoAtom, getTypeName,
saveOrUpdateVideoAtom, videosAtom, videoSearchAtom, videoTypes
} from '@/store/videos/video.ts'
import { useEffect, useMemo, useState } from 'react'
import Switch from '@/components/switch'
import Action from '@/components/action/Action.tsx'
import {
BetaSchemaForm,
ProColumns,
ProFormColumnsType,
ProFormDatePicker,
ProFormUploadButton,
ProTable
} from '@ant-design/pro-components'
import ListPageLayout from '@/layout/ListPageLayout.tsx'
import { categoryByIdAtom, categoryIdAtom } from '@/store/videos/category.ts'
import TagPro from '@/components/tag-pro/TagPro.tsx'
const i18nPrefix = 'videos.list'
const Video = () => {
// const { styles } = useStyle()
const { t } = useTranslation()
const [ form ] = Form.useForm()
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateVideoAtom)
const [ search, setSearch ] = useAtom(videoSearchAtom)
const { data, isFetching, isLoading, refetch } = useAtomValue(videosAtom)
const { mutate: deleteVideo, isPending: isDeleting } = useAtomValue(deleteVideoAtom)
const setCategoryId = useSetAtom(categoryIdAtom)
const { data: category, isLoading: isCategoryFetching } = useAtomValue(categoryByIdAtom)
const [ open, setOpen ] = useState(false)
const columns = useMemo(() => {
return [
{
title: 'ID',
dataIndex: 'id',
hideInTable: true,
hideInSearch: true,
formItemProps: { hidden: true }
},
{
'title': t(`${i18nPrefix}.columns.video_id`, 'VideoId'),
'dataIndex': 'video_id',
hideInTable: true,
hideInSearch: true,
hideInSetting: true,
formItemProps: { hidden: true },
},
{
'title': t(`${i18nPrefix}.columns.title`, 'Title'),
'dataIndex': 'title',
onHeaderCell: () => {
return {
width: 200,
}
},
colProps: {
span: 8
}
},
{
'title': t(`${i18nPrefix}.columns.title_sub`, 'TitleSub'),
'dataIndex': 'title_sub',
onHeaderCell: () => {
return {
width: 200,
}
},
colProps: {
span: 8
}
},
{
'title': t(`${i18nPrefix}.columns.type_id`, 'TypeId'),
'dataIndex': 'type_id',
valueType: 'select',
fieldProps: {
options: videoTypes,
},
render: (_dom, record) => {
return t(`${i18nPrefix}.type_id.${record.type_id}`)
},
colProps: {
span: 8
}
},
{
'title': t(`${i18nPrefix}.columns.source_url`, 'SourceUrl'),
'dataIndex': 'source_url',
ellipsis: true,
copyable: true,
onHeaderCell: () => {
return {
width: 200,
}
},
},
{
'title': t(`${i18nPrefix}.columns.year`, 'Year'),
'dataIndex': 'year',
valueType: 'dateYear',
colProps: {
span: 4
},
render: (_dom, record) => {
return record.year
},
renderFormItem: (_schema, config) => {
return <DatePicker
picker={'year'}
{...config}
value={dayjs().set('year', config.value || new Date().getFullYear())}
/>
}
},
{
'title': t(`${i18nPrefix}.columns.category_id`, 'CategoryId'),
'dataIndex': 'class_name',
colProps: {
span: 4
},
},
{
'title': t(`${i18nPrefix}.columns.img`, '封面'),
'dataIndex': 'pic',
hideInSearch: true,
hideInTable: true,
colProps: {
span: 4
},
renderFormItem: (_schema, _config, form) => {
return <ProFormUploadButton
fieldProps={{
name: 'file',
listType: 'picture-card',
data: { videoId: form.getFieldValue('video_id') },
headers: {
'Authorization': `Bearer ${getToken()}`
},
}}
fileList={[]}
action="/api/v1/videos/image/upload"
/>
}
},
{
'title': t(`${i18nPrefix}.columns.actor`, 'Actor'),
'dataIndex': 'actor',
ellipsis: true,
onHeaderCell: () => {
return {
width: 200,
}
},
},
{
'title': t(`${i18nPrefix}.columns.director`, 'Director'),
'dataIndex': 'director'
},
{
'title': t(`${i18nPrefix}.columns.content`, 'Content'),
'dataIndex': 'content',
valueType: 'textarea',
ellipsis: true,
onHeaderCell: () => ({
width: 200,
}),
},
{
'title': t(`${i18nPrefix}.columns.writer`, 'Writer'),
'dataIndex': 'writer'
},
{
'title': t(`${i18nPrefix}.columns.remarks`, 'Remarks'),
'dataIndex': 'remarks'
},
{
'title': t(`${i18nPrefix}.columns.tag`, 'Tag'),
'dataIndex': 'tag',
valueType: 'textarea',
ellipsis: true,
onHeaderCell: () => {
return {
width: 200,
}
},
renderFormItem: (schema, config) => {
return <TagPro loading={isCategoryFetching}
tags={category?.extend?.class?.split(',') ?? []} {...config} {...schema.fieldProps} />
}
},
{
'title': t(`${i18nPrefix}.columns.area`, 'Area'),
'dataIndex': 'area',
ellipsis: true,
onHeaderCell: () => {
return {
width: 200,
}
},
renderFormItem: (schema, config) => {
return <TagPro loading={isCategoryFetching}
tags={category?.extend?.area?.split(',') ?? []} {...config} {...schema.fieldProps} />
}
},
{
'title': t(`${i18nPrefix}.columns.lang`, 'Lang'),
'dataIndex': 'lang',
ellipsis: true,
onHeaderCell: () => {
return {
width: 200,
}
},
renderFormItem: (schema, config) => {
return <TagPro loading={isCategoryFetching}
tags={category?.extend?.lang?.split(',') ?? []} {...config} {...schema.fieldProps} />
}
},
/*{
'title': t(`${i18nPrefix}.columns.version`, 'Version'),
'dataIndex': 'version',
renderFormItem: (schema, config) => {
return <TagPro loading={isCategoryFetching}
tags={category?.extend?.version?.split(',') ?? []} {...config} {...schema.fieldProps} />
}
},
{
'title': t(`${i18nPrefix}.columns.state`, 'State'),
'dataIndex': 'state',
renderFormItem: (schema, config) => {
return <TagPro loading={isCategoryFetching}
tags={category?.extend?.state?.split(',') ?? []} {...config} {...schema.fieldProps} />
}
},*/
{
'title': t(`${i18nPrefix}.columns.douban_score`, 'DoubanScore'),
'dataIndex': 'douban_score',
hideInSearch: true,
hideInSetting: true,
formItemProps: { hidden: true },
hideInTable: true,
},
{
'title': t(`${i18nPrefix}.columns.douban_id`, 'DoubanId'),
'dataIndex': 'douban_id',
hideInSearch: true,
hideInSetting: true,
formItemProps: { hidden: true },
hideInTable: true,
},
{
'title': t(`${i18nPrefix}.columns.imdb_score`, 'ImdbScore'),
'dataIndex': 'imdb_score',
hideInSearch: true,
hideInSetting: true,
formItemProps: { hidden: true },
hideInTable: true,
},
{
'title': t(`${i18nPrefix}.columns.imdb_id`, 'ImdbId'),
'dataIndex': 'imdb_id',
hideInSearch: true,
hideInSetting: true,
formItemProps: { hidden: true },
hideInTable: true,
},
{
title: t(`${i18nPrefix}.columns.option`, '操作'),
key: 'option',
valueType: 'option',
fixed: 'right',
render: (_, record) => [
<Action key="edit"
as={'a'}
onClick={() => {
setCategoryId(record.type_id)
form.setFieldsValue(record)
setOpen(true)
}}>{t('actions.edit')}</Action>,
<Popconfirm
key={'del_confirm'}
disabled={isDeleting}
onConfirm={() => {
deleteVideo([ record.id ])
}}
title={t('message.deleteConfirm')}>
<a key="del">
{t('actions.delete', '删除')}
</a>
</Popconfirm>
]
}
] as ProColumns[]
}, [ isDeleting, category, isCategoryFetching ])
useEffect(() => {
if (isSuccess) {
setOpen(false)
}
}, [ isSuccess ])
return (
<ListPageLayout>
<ProTable
rowKey="id"
headerTitle={t(`${i18nPrefix}.title`, '视频管理')}
toolbar={{
search: {
loading: isFetching && !!search.key,
onSearch: (value: string) => {
setSearch(prev => ({
...prev,
key: value
}))
},
allowClear: true,
placeholder: t(`${i18nPrefix}.placeholder`, '输入视频名称')
},
actions: [
<Button
onClick={() => {
form.resetFields()
form.setFieldsValue({
id: 0,
})
setOpen(true)
}}
type={'primary'}>{t(`${i18nPrefix}.add`, '添加')}</Button>
]
}}
scroll={{
x: 3500,
}}
loading={isLoading || isFetching}
dataSource={data?.rows ?? []}
columns={columns}
search={false}
options={{
reload: () => {
refetch()
},
}}
pagination={{
total: data?.total,
pageSize: search.pageSize,
current: search.page,
onChange: (current, pageSize) => {
setSearch(prev => {
return {
...prev,
page: current,
pageSize: pageSize,
}
})
},
}}
/>
<BetaSchemaForm
grid={true}
shouldUpdate={false}
width={1000}
form={form}
layout={'vertical'}
scrollToFirstError={true}
title={t(`${i18nPrefix}.title_${form.getFieldValue('id') !== 0 ? 'edit' : 'add'}`, form.getFieldValue('id') !== 0 ? '视频编辑' : '视频添加')}
// colProps={{ span: 24 }}
// labelCol={{ span: 8 }}
// wrapperCol={{ span: 14 }}
layoutType={'DrawerForm'}
open={open}
drawerProps={{
maskClosable: false,
}}
onOpenChange={(open) => {
setOpen(open)
}}
loading={isSubmitting}
onValuesChange={(values) => {
if (values.type_id) {
setCategoryId(values.type_id)
const typeName = getTypeName(values.type_id)
form.setFieldsValue({
class_name: typeName,
})
}
}}
onFinish={async (values) => {
// console.log('values', values)
saveOrUpdate(values)
}}
columns={columns as ProFormColumnsType[]}/>
</ListPageLayout>
)
}
export default Video