diff --git a/src/locales/lang/pages/cms/video/zh-CN.ts b/src/locales/lang/pages/cms/video/zh-CN.ts new file mode 100644 index 0000000..7c9ee1a --- /dev/null +++ b/src/locales/lang/pages/cms/video/zh-CN.ts @@ -0,0 +1,53 @@ +export default { + title: '视频管理', + description: '视频管理', + search: '搜索', + add: '新增', + edit: '编辑', + delete: '删除', + type_id: [ + '在线观看', '下载', '网盘' + ], + lock: [ + '未锁', '锁定' + ], + columns: { + id: 'ID', + source_url: '源站点地址', + collect_id: '站点id', + type_id: '类型', + title: '标题', + title_sub: '副标', + letter: '首字母', + tag: 'TAG', + lock: '锁定后显示', + copyright: '版权', + is_end: '完结', + status: '状态', + category_id: '分类', + pic: '图片', + pic_local: '图片本地路径或MD5', + pic_status: '图片状态', + actor: '演员', + director: '导演', + writer: '编剧', + remarks: '备注', + pubdate: '发布时间', + total: '总集数', + serial: '连载数', + duration: '视频时长', + area: '地区', + lang: '语言', + version: '资源版本', + year: '年份', + state: '资源类别', + douban_score: '豆瓣评分', + douban_id: '豆瓣ID', + imdb_score: 'imdb评分', + imdb_id: 'imdb的id', + content: '内容', + created_at: '创建时间', + updated_at: '更新时间' + + } +} \ No newline at end of file diff --git a/src/locales/lang/pages/cms/videoCloud/zh-CN.ts b/src/locales/lang/pages/cms/videoCloud/zh-CN.ts new file mode 100644 index 0000000..4ba67bd --- /dev/null +++ b/src/locales/lang/pages/cms/videoCloud/zh-CN.ts @@ -0,0 +1,52 @@ +export default { + title: '云盘视频管理', + description: '云盘视频管理', + search: '搜索', + add: '新增', + edit: '编辑', + delete: '删除', + type_id: [ + '在线观看', '下载', '网盘' + ], + lock: [ + '未锁', '锁定' + ], + columns: { + source_url: '源站点地址', + collect_id: '站点id', + type_id: '类型', + title: '标题', + title_sub: '副标', + letter: '首字母', + tag: 'TAG', + lock: '锁定后显示', + copyright: '版权', + is_end: '完结', + status: '状态', + category_id: '分类', + pic: '图片', + pic_local: '图片本地路径或MD5', + pic_status: '图片状态', + actor: '演员', + director: '导演', + writer: '编剧', + remarks: '备注', + pubdate: '发布时间', + total: '总集数', + serial: '连载数', + duration: '视频时长', + class: '分类', + area: '地区', + lang: '语言', + version: '资源版本', + year: '年份', + state: '资源类别', + douban_score: '豆瓣评分', + douban_id: '豆瓣ID', + imdb_score: 'imdb评分', + imdb_id: 'imdb的id', + content: '内容', + created_at: '创建时间', + updated_at: '更新时间' + } +} \ No newline at end of file diff --git a/src/locales/lang/pages/cms/videoMagnet/zh-CN.ts b/src/locales/lang/pages/cms/videoMagnet/zh-CN.ts new file mode 100644 index 0000000..f548e8e --- /dev/null +++ b/src/locales/lang/pages/cms/videoMagnet/zh-CN.ts @@ -0,0 +1,52 @@ +export default { + title: '磁链视频管理', + description: '磁链视频管理', + search: '搜索', + add: '新增', + edit: '编辑', + delete: '删除', + type_id: [ + '在线观看', '下载', '网盘' + ], + lock: [ + '未锁', '锁定' + ], + columns: { + source_url: '源站点地址', + collect_id: '站点id', + type_id: '类型', + title: '标题', + title_sub: '副标', + letter: '首字母', + tag: 'TAG', + lock: '锁定后显示', + copyright: '版权', + is_end: '完结', + status: '状态', + category_id: '分类', + pic: '图片', + pic_local: '图片本地路径或MD5', + pic_status: '图片状态', + actor: '演员', + director: '导演', + writer: '编剧', + remarks: '备注', + pubdate: '发布时间', + total: '总集数', + serial: '连载数', + duration: '视频时长', + class: '分类', + area: '地区', + lang: '语言', + version: '资源版本', + year: '年份', + state: '资源类别', + douban_score: '豆瓣评分', + douban_id: '豆瓣ID', + imdb_score: 'imdb评分', + imdb_id: 'imdb的id', + content: '内容', + created_at: '创建时间', + updated_at: '更新时间' + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN.ts b/src/locales/lang/zh-CN.ts index a6b66ef..0230ffe 100644 --- a/src/locales/lang/zh-CN.ts +++ b/src/locales/lang/zh-CN.ts @@ -3,92 +3,95 @@ import menus from './pages/system/menus/zh-CN.ts' import roles from './pages/system/roles/zh-CN.ts' import status from './status/zh-CN.ts' import collect from './pages/cms/collect/zh-CN.ts' +import video from './pages/cms/video/zh-CN.ts' +import videoCloud from './pages/cms/videoCloud/zh-CN.ts' +import videoMagnet from './pages/cms/videoMagnet/zh-CN.ts' export default { - ...antdZh, - status, - error: { - '404': { - title: '无法找到', - message: '找不到此页面' - }, - '403': { - title: '没有权限', - message: '对不起,您没有权限查看此页面。' - }, - 'error': { - title: '错误信息', - }, + ...antdZh, + status, + error: { + '404': { + title: '无法找到', + message: '找不到此页面' }, - route: { - goBack: '返回', + '403': { + title: '没有权限', + message: '对不起,您没有权限查看此页面。' }, - app: { - header: { - logout: '退出登录', - } + 'error': { + title: '错误信息', }, - login: { - title: '账户密码登录', - username: '用户名', - usernameMsg: '请输入用户名', - password: '密码', - passwordMsg: '请输入密码', - code: '验证码', - codeMsg: '请输入验证码', - submit: '登录', - success: '登录成功' - }, - home: { - welcome: '欢迎使用' - }, - - system: { - menus, - roles - }, - cms: { - collect, - }, - actions: { - news: '新增', - add: '添加', - edit: '编辑', - ok: '确定', - cancel: '取消', - delete: '删除', - batchDel: '批量删除', - reset: '重置', - clear: '清空', - close: '关闭', - }, - message: { - infoTitle: '提示', - errorTitle: '错误', - successTitle: '成功', - warningTitle: '警告', - batchDelete: '确定要删除所选数据吗?', - deleteConfirm: '确定要删除吗?', - success: '提交成功', - fail: '提交失败', - saveSuccess: '保存成功', - editSuccess: '修改成功', - deleteSuccess: '删除成功', - saveFail: '保存失败', - emptyData: '暂无数据', - emptyDataAdd: '暂无数据,点击添加', - required: '此项为必填项', - }, - rules: { - required: '此项为必填项', - }, - tabs: { - refresh: '刷新', - maximize: '最大化', - closeCurrent: '关闭当前', - closeLeft: '关闭左侧', - closeRight: '关闭右侧', - closeOther: '关闭其它', - closeAll: '关闭所有' + }, + route: { + goBack: '返回', + }, + app: { + header: { + logout: '退出登录', } + }, + login: { + title: '账户密码登录', + username: '用户名', + usernameMsg: '请输入用户名', + password: '密码', + passwordMsg: '请输入密码', + code: '验证码', + codeMsg: '请输入验证码', + submit: '登录', + success: '登录成功' + }, + home: { + welcome: '欢迎使用' + }, + + system: { + menus, + roles + }, + cms: { + collect, video, videoCloud, videoMagnet, + }, + actions: { + news: '新增', + add: '添加', + edit: '编辑', + ok: '确定', + cancel: '取消', + delete: '删除', + batchDel: '批量删除', + reset: '重置', + clear: '清空', + close: '关闭', + }, + message: { + infoTitle: '提示', + errorTitle: '错误', + successTitle: '成功', + warningTitle: '警告', + batchDelete: '确定要删除所选数据吗?', + deleteConfirm: '确定要删除吗?', + success: '提交成功', + fail: '提交失败', + saveSuccess: '保存成功', + editSuccess: '修改成功', + deleteSuccess: '删除成功', + saveFail: '保存失败', + emptyData: '暂无数据', + emptyDataAdd: '暂无数据,点击添加', + required: '此项为必填项', + }, + rules: { + required: '此项为必填项', + }, + tabs: { + refresh: '刷新', + maximize: '最大化', + closeCurrent: '关闭当前', + closeLeft: '关闭左侧', + closeRight: '关闭右侧', + closeOther: '关闭其它', + closeAll: '关闭所有' + } } diff --git a/src/pages/cms/video/index.tsx b/src/pages/cms/video/index.tsx new file mode 100644 index 0000000..bc9220c --- /dev/null +++ b/src/pages/cms/video/index.tsx @@ -0,0 +1,388 @@ +import { useTranslation } from '@/i18n.ts' +import { Button, Form, Popconfirm } from 'antd' +import { useAtom, useAtomValue } from 'jotai' +import { + deleteVideoAtom, + saveOrUpdateVideoAtom, videosAtom, videoSearchAtom, videoTypes +} from '@/store/cms/video.ts' +import { useEffect, useMemo, useState } from 'react' +import Switch from '@/components/switch' +import Action from '@/components/action/Action.tsx' +import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import ListPageLayout from '@/layout/ListPageLayout.tsx' + +const i18nPrefix = 'cms.video' + +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 [ open, setOpen ] = useState(false) + + const columns = useMemo(() => { + return [ + { + title: 'ID', + dataIndex: 'id', + hideInTable: true, + hideInSearch: true, + formItemProps: { hidden: true } + }, + { + 'title': t(`${i18nPrefix}.columns.title`, 'Title'), + 'dataIndex': 'title', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.title_sub`, 'TitleSub'), + 'dataIndex': 'title_sub', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.source_url`, 'SourceUrl'), + 'dataIndex': 'source_url', + ellipsis: true, + copyable: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.collect_id`, 'CollectId'), + 'dataIndex': 'collect_id', + hideInTable: true, + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + }, + { + '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}`) + }, + }, + { + 'title': t(`${i18nPrefix}.columns.letter`, 'Letter'), + 'dataIndex': 'letter' + }, + { + 'title': t(`${i18nPrefix}.columns.tag`, 'Tag'), + 'dataIndex': 'tag', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lock`, 'Lock'), + 'dataIndex': 'lock', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.copyright`, 'Copyright'), + 'dataIndex': 'copyright', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.is_end`, 'IsEnd'), + 'dataIndex': 'is_end', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.status`, 'Status'), + 'dataIndex': 'status', + valueType: 'switch', + render: (_dom, record) => { + return + }, + + }, + { + 'title': t(`${i18nPrefix}.columns.category_id`, 'CategoryId'), + 'dataIndex': 'category_id', + + }, + { + 'title': t(`${i18nPrefix}.columns.pic`, 'Pic'), + 'dataIndex': 'pic', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.pic_local`, 'PicLocal'), + 'dataIndex': 'pic_local', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.pic_status`, 'PicStatus'), + 'dataIndex': 'pic_status', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + '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.writer`, 'Writer'), + 'dataIndex': 'writer' + }, + { + 'title': t(`${i18nPrefix}.columns.remarks`, 'Remarks'), + 'dataIndex': 'remarks' + }, + { + 'title': t(`${i18nPrefix}.columns.pubdate`, 'Pubdate'), + 'dataIndex': 'pubdate', + valueType: 'dateTime' + }, + { + 'title': t(`${i18nPrefix}.columns.total`, 'Total'), + 'dataIndex': 'total', + valueType: 'digit' + }, + { + 'title': t(`${i18nPrefix}.columns.serial`, 'Serial'), + 'dataIndex': 'serial', + }, + { + 'title': t(`${i18nPrefix}.columns.duration`, 'Duration'), + 'dataIndex': 'duration', + }, + { + 'title': t(`${i18nPrefix}.columns.area`, 'Area'), + 'dataIndex': 'area', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lang`, 'Lang'), + 'dataIndex': 'lang', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.version`, 'Version'), + 'dataIndex': 'version' + }, + { + 'title': t(`${i18nPrefix}.columns.year`, 'Year'), + 'dataIndex': 'year', + valueType: 'dateYear' + }, + { + 'title': t(`${i18nPrefix}.columns.state`, 'State'), + 'dataIndex': 'state' + }, + { + 'title': t(`${i18nPrefix}.columns.douban_score`, 'DoubanScore'), + 'dataIndex': 'douban_score' + }, + { + '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' + }, + { + 'title': t(`${i18nPrefix}.columns.imdb_id`, 'ImdbId'), + 'dataIndex': 'imdb_id', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.content`, 'Content'), + 'dataIndex': 'content', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => ({ + width: 200, + }), + }, + + { + title: t(`${i18nPrefix}.columns.option`, '操作'), + key: 'option', + valueType: 'option', + fixed: 'right', + render: (_, record) => [ + { + form.setFieldsValue(record) + setOpen(true) + }}>{t('actions.edit')}, + { + deleteVideo([ record.id ]) + }} + title={t('message.deleteConfirm')}> + + {t('actions.delete', '删除')} + + + ] + } + ] as ProColumns[] + }, [ isDeleting ]) + + useEffect(() => { + if (isSuccess) { + setOpen(false) + } + }, [ isSuccess ]) + + return ( + + { + setSearch(prev => ({ + ...prev, + key: value + })) + }, + allowClear: true, + placeholder: t(`${i18nPrefix}.placeholder`, '输入视频名称') + }, + actions: [ + + ] + }} + 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, + } + }) + }, + + }} + /> + { + setOpen(open) + }} + loading={isSubmitting} + onFinish={async (values) => { + // console.log('values', values) + saveOrUpdate(values) + + }} + columns={columns as ProFormColumnsType[]}/> + + ) +} + +export default Video \ No newline at end of file diff --git a/src/pages/cms/video_cloud/index.tsx b/src/pages/cms/video_cloud/index.tsx new file mode 100644 index 0000000..c8605b6 --- /dev/null +++ b/src/pages/cms/video_cloud/index.tsx @@ -0,0 +1,395 @@ +import { useTranslation } from '@/i18n.ts' +import { Button, Form, Image, Popconfirm } from 'antd' +import { useAtom, useAtomValue } from 'jotai' +import { useEffect, useMemo, useState } from 'react' +import Switch from '@/components/switch' +import Action from '@/components/action/Action.tsx' +import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import ListPageLayout from '@/layout/ListPageLayout.tsx' +import { + deleteVideoCloudAtom, + saveOrUpdateVideoCloudAtom, + videoCloudsAtom, + videoCloudSearchAtom +} from '@/store/cms/video_cloud.ts' +import { videoTypes } from '@/store/cms/video.ts' + + +const i18nPrefix = 'cms.videoCloud' + +const VideoCloud = () => { + + // const { styles } = useStyle() + const { t } = useTranslation() + const [ form ] = Form.useForm() + const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateVideoCloudAtom) + const [ search, setSearch ] = useAtom(videoCloudSearchAtom) + const { data, isFetching, isLoading, refetch } = useAtomValue(videoCloudsAtom) + const { mutate: deleteVideo, isPending: isDeleting } = useAtomValue(deleteVideoCloudAtom) + const [ open, setOpen ] = useState(false) + + const columns = useMemo(() => { + return [ + { + title: 'ID', + dataIndex: 'id', + hideInTable: true, + hideInSearch: true, + formItemProps: { hidden: true } + }, + { + 'title': t(`${i18nPrefix}.columns.title`, 'Title'), + 'dataIndex': 'title', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.title_sub`, 'TitleSub'), + 'dataIndex': 'title_sub', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.source_url`, 'SourceUrl'), + 'dataIndex': 'source_url', + ellipsis: true, + copyable: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.collect_id`, 'CollectId'), + 'dataIndex': 'collect_id', + hideInTable: true, + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + }, + { + '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}`) + }, + }, + { + 'title': t(`${i18nPrefix}.columns.letter`, 'Letter'), + 'dataIndex': 'letter' + }, + { + 'title': t(`${i18nPrefix}.columns.tag`, 'Tag'), + 'dataIndex': 'tag', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lock`, 'Lock'), + 'dataIndex': 'lock', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.copyright`, 'Copyright'), + 'dataIndex': 'copyright', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.is_end`, 'IsEnd'), + 'dataIndex': 'is_end', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.status`, 'Status'), + 'dataIndex': 'status', + valueType: 'switch', + render: (_dom, record) => { + return + }, + + }, + { + 'title': t(`${i18nPrefix}.columns.category_id`, 'CategoryId'), + 'dataIndex': 'category_id', + + }, + { + 'title': t(`${i18nPrefix}.columns.pic`, 'Pic'), + 'dataIndex': 'pic', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.pic_local`, 'PicLocal'), + 'dataIndex': 'pic_local', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.actor`, 'Actor'), + 'dataIndex': 'actor', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.director`, 'Director'), + 'dataIndex': 'director', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.writer`, 'Writer'), + 'dataIndex': 'writer', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.pubdate`, 'Pubdate'), + 'dataIndex': 'pubdate', + valueType: 'dateTime' + }, + { + 'title': t(`${i18nPrefix}.columns.total`, 'Total'), + 'dataIndex': 'total', + valueType: 'digit' + }, + { + 'title': t(`${i18nPrefix}.columns.serial`, 'Serial'), + 'dataIndex': 'serial', + }, + { + 'title': t(`${i18nPrefix}.columns.duration`, 'Duration'), + 'dataIndex': 'duration', + }, + { + 'title': t(`${i18nPrefix}.columns.class`, 'Class'), + 'dataIndex': 'class', + }, + { + 'title': t(`${i18nPrefix}.columns.area`, 'Area'), + 'dataIndex': 'area', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lang`, 'Lang'), + 'dataIndex': 'lang', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.version`, 'Version'), + 'dataIndex': 'version' + }, + { + 'title': t(`${i18nPrefix}.columns.year`, 'Year'), + 'dataIndex': 'year', + valueType: 'dateYear' + }, + { + 'title': t(`${i18nPrefix}.columns.state`, 'State'), + 'dataIndex': 'state' + }, + { + 'title': t(`${i18nPrefix}.columns.douban_score`, 'DoubanScore'), + 'dataIndex': 'douban_score' + }, + { + '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' + }, + { + 'title': t(`${i18nPrefix}.columns.imdb_id`, 'ImdbId'), + 'dataIndex': 'imdb_id', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.content`, 'Content'), + 'dataIndex': 'content', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => ({ + width: 200, + }), + }, + + { + title: t(`${i18nPrefix}.columns.option`, '操作'), + key: 'option', + valueType: 'option', + fixed: 'right', + render: (_, record) => [ + { + form.setFieldsValue(record) + setOpen(true) + }}>{t('actions.edit')}, + { + deleteVideo([ record.id ]) + }} + title={t('message.deleteConfirm')}> + + {t('actions.delete', '删除')} + + + ] + } + ] as ProColumns[] + }, [ isDeleting ]) + + useEffect(() => { + if (isSuccess) { + setOpen(false) + } + }, [ isSuccess ]) + + return ( + + { + setSearch(prev => ({ + ...prev, + key: value + })) + }, + allowClear: true, + placeholder: t(`${i18nPrefix}.placeholder`, '输入云盘视频名称') + }, + actions: [ + + ] + }} + 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, + } + }) + }, + + }} + /> + { + setOpen(open) + }} + loading={isSubmitting} + onFinish={async (values) => { + // console.log('values', values) + saveOrUpdate(values) + + }} + columns={columns as ProFormColumnsType[]}/> + + ) +} + +export default VideoCloud \ No newline at end of file diff --git a/src/pages/cms/video_magnet/index.tsx b/src/pages/cms/video_magnet/index.tsx new file mode 100644 index 0000000..342abce --- /dev/null +++ b/src/pages/cms/video_magnet/index.tsx @@ -0,0 +1,396 @@ +import { useTranslation } from '@/i18n.ts' +import { Button, Form, Popconfirm, Image } from 'antd' +import { useAtom, useAtomValue } from 'jotai' +import { useEffect, useMemo, useState } from 'react' +import Switch from '@/components/switch' +import Action from '@/components/action/Action.tsx' +import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import ListPageLayout from '@/layout/ListPageLayout.tsx' +import { videoTypes } from '@/store/cms/video.ts' +import { + deleteVideoMagnetAtom, + saveOrUpdateVideoMagnetAtom, + videoMagnetsAtom, + videoMagnetSearchAtom +} from '@/store/cms/video_magnet.ts' + +const i18nPrefix = 'cms.videoMagnet' + +const VideoMagnet = () => { + + // const { styles } = useStyle() + const { t } = useTranslation() + const [ form ] = Form.useForm() + const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateVideoMagnetAtom) + const [ search, setSearch ] = useAtom(videoMagnetSearchAtom) + const { data, isFetching, isLoading, refetch } = useAtomValue(videoMagnetsAtom) + const { mutate: deleteVideo, isPending: isDeleting } = useAtomValue(deleteVideoMagnetAtom) + const [ open, setOpen ] = useState(false) + + const columns = useMemo(() => { + return [ + { + title: 'ID', + dataIndex: 'id', + hideInTable: true, + hideInSearch: true, + formItemProps: { hidden: true } + }, + { + 'title': t(`${i18nPrefix}.columns.title`, 'Title'), + 'dataIndex': 'title', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.title_sub`, 'TitleSub'), + 'dataIndex': 'title_sub', + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.source_url`, 'SourceUrl'), + 'dataIndex': 'source_url', + ellipsis: true, + copyable: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.collect_id`, 'CollectId'), + 'dataIndex': 'collect_id', + hideInTable: true, + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + }, + { + '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}`) + }, + }, + { + 'title': t(`${i18nPrefix}.columns.letter`, 'Letter'), + 'dataIndex': 'letter' + }, + { + 'title': t(`${i18nPrefix}.columns.tag`, 'Tag'), + 'dataIndex': 'tag', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lock`, 'Lock'), + 'dataIndex': 'lock', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.copyright`, 'Copyright'), + 'dataIndex': 'copyright', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.is_end`, 'IsEnd'), + 'dataIndex': 'is_end', + valueType: 'switch', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.status`, 'Status'), + 'dataIndex': 'status', + valueType: 'switch', + render: (_dom, record) => { + return + }, + + }, + { + 'title': t(`${i18nPrefix}.columns.category_id`, 'CategoryId'), + 'dataIndex': 'category_id', + + }, + { + 'title': t(`${i18nPrefix}.columns.pic`, 'Pic'), + 'dataIndex': 'pic', + render: (_dom, record) => { + return + }, + }, + { + 'title': t(`${i18nPrefix}.columns.pic_local`, 'PicLocal'), + 'dataIndex': 'pic_local', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.actor`, 'Actor'), + 'dataIndex': 'actor', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + + }, + { + 'title': t(`${i18nPrefix}.columns.director`, 'Director'), + 'dataIndex': 'director', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.writer`, 'Writer'), + 'dataIndex': 'writer', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.pubdate`, 'Pubdate'), + 'dataIndex': 'pubdate', + valueType: 'dateTime' + }, + { + 'title': t(`${i18nPrefix}.columns.total`, 'Total'), + 'dataIndex': 'total', + valueType: 'digit' + }, + { + 'title': t(`${i18nPrefix}.columns.serial`, 'Serial'), + 'dataIndex': 'serial', + }, + { + 'title': t(`${i18nPrefix}.columns.duration`, 'Duration'), + 'dataIndex': 'duration', + }, + { + 'title': t(`${i18nPrefix}.columns.class`, 'Class'), + 'dataIndex': 'class', + }, + { + 'title': t(`${i18nPrefix}.columns.area`, 'Area'), + 'dataIndex': 'area', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.lang`, 'Lang'), + 'dataIndex': 'lang', + ellipsis: true, + onHeaderCell: () => { + return { + width: 200, + } + }, + }, + { + 'title': t(`${i18nPrefix}.columns.version`, 'Version'), + 'dataIndex': 'version' + }, + { + 'title': t(`${i18nPrefix}.columns.year`, 'Year'), + 'dataIndex': 'year', + valueType: 'dateYear' + }, + { + 'title': t(`${i18nPrefix}.columns.state`, 'State'), + 'dataIndex': 'state' + }, + { + 'title': t(`${i18nPrefix}.columns.douban_score`, 'DoubanScore'), + 'dataIndex': 'douban_score' + }, + { + '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' + }, + { + 'title': t(`${i18nPrefix}.columns.imdb_id`, 'ImdbId'), + 'dataIndex': 'imdb_id', + hideInSearch: true, + hideInSetting: true, + formItemProps: { hidden: true }, + hideInTable: true, + }, + { + 'title': t(`${i18nPrefix}.columns.content`, 'Content'), + 'dataIndex': 'content', + valueType: 'textarea', + ellipsis: true, + onHeaderCell: () => ({ + width: 200, + }), + }, + + + { + title: t(`${i18nPrefix}.columns.option`, '操作'), + key: 'option', + valueType: 'option', + fixed: 'right', + render: (_, record) => [ + { + form.setFieldsValue(record) + setOpen(true) + }}>{t('actions.edit')}, + { + deleteVideo([ record.id ]) + }} + title={t('message.deleteConfirm')}> + + {t('actions.delete', '删除')} + + + ] + } + ] as ProColumns[] + }, [ isDeleting ]) + + useEffect(() => { + if (isSuccess) { + setOpen(false) + } + }, [ isSuccess ]) + + return ( + + { + setSearch(prev => ({ + ...prev, + key: value + })) + }, + allowClear: true, + placeholder: t(`${i18nPrefix}.placeholder`, '输入磁链视频名称') + }, + actions: [ + + ] + }} + 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, + } + }) + }, + + }} + /> + { + setOpen(open) + }} + loading={isSubmitting} + onFinish={async (values) => { + // console.log('values', values) + saveOrUpdate(values) + + }} + columns={columns as ProFormColumnsType[]}/> + + ) +} + +export default VideoMagnet \ No newline at end of file diff --git a/src/store/cms/video.ts b/src/store/cms/video.ts index b6ad5bd..50e30d1 100644 --- a/src/store/cms/video.ts +++ b/src/store/cms/video.ts @@ -6,29 +6,36 @@ import { t } from 'i18next' import { Cms } from '@/types' import cmsServ from '@/service/cms.ts' +const i18nPrefix = 'cms.video' type SearchParams = IPage & { key?: string } -export const idAtom = atom(0) +export const videoTypes = [ + { label: t(`${i18nPrefix}.type_id.0`), value: 0 }, + { label: t(`${i18nPrefix}.type_id.1`), value: 1 }, + { label: t(`${i18nPrefix}.type_id.2`), value: 2 }, +] + +export const videoIdAtom = atom(0) export const videoIdsAtom = atom([]) export const videoAtom = atom(undefined as unknown as Cms.IVideo) -export const searchAtom = atom({ +export const videoSearchAtom = atom({ key: '' } as SearchParams) -export const pageAtom = atom({ +export const videoPageAtom = atom({ pageSize: 10, page: 1, }) export const videosAtom = atomWithQuery((get) => { return { - queryKey: [ 'videos', get(searchAtom) ], + queryKey: [ 'videos', get(videoSearchAtom) ], queryFn: async ({ queryKey: [ , params ] }) => { return await cmsServ.video.list(params as SearchParams) }, @@ -64,7 +71,7 @@ export const saveOrUpdateVideoAtom = atomWithMutation((g //更新列表 // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore fix - get(queryClientAtom).invalidateQueries({ queryKey: [ 'videos', get(searchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'videos', get(videoSearchAtom) ] }) return res } @@ -80,7 +87,7 @@ export const deleteVideoAtom = atomWithMutation((get) => { onSuccess: (res) => { message.success('message.deleteSuccess') //更新列表 - get(queryClientAtom).invalidateQueries({ queryKey: [ 'videos', get(searchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'videos', get(videoSearchAtom) ] }) return res } } diff --git a/src/store/cms/video_cloud.ts b/src/store/cms/video_cloud.ts index ac84354..6d323eb 100644 --- a/src/store/cms/video_cloud.ts +++ b/src/store/cms/video_cloud.ts @@ -11,24 +11,24 @@ type SearchParams = IPage & { key?: string } -export const idAtom = atom(0) +export const videoCloudIdAtom = atom(0) export const videoCloudIdsAtom = atom([]) export const videoCloudAtom = atom(undefined as unknown as Cms.IVideoCloud) -export const searchAtom = atom({ +export const videoCloudSearchAtom = atom({ key: '' } as SearchParams) -export const pageAtom = atom({ +export const videoCloudPageAtom = atom({ pageSize: 10, page: 1, }) export const videoCloudsAtom = atomWithQuery((get) => { return { - queryKey: [ 'videoClouds', get(searchAtom) ], + queryKey: [ 'videoClouds', get(videoCloudSearchAtom) ], queryFn: async ({ queryKey: [ , params ] }) => { return await cmsServ.videoCloud.list(params as SearchParams) }, @@ -64,7 +64,7 @@ export const saveOrUpdateVideoCloudAtom = atomWithMutation { onSuccess: (res) => { message.success('message.deleteSuccess') //更新列表 - get(queryClientAtom).invalidateQueries({ queryKey: [ 'videoClouds', get(searchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'videoClouds', get(videoCloudSearchAtom) ] }) return res } } diff --git a/src/store/cms/video_magnet.ts b/src/store/cms/video_magnet.ts index d9dd464..6d7fed3 100644 --- a/src/store/cms/video_magnet.ts +++ b/src/store/cms/video_magnet.ts @@ -11,24 +11,24 @@ type SearchParams = IPage & { key?: string } -export const idAtom = atom(0) +export const videoMagnetIdAtom = atom(0) export const videoMagnetIdsAtom = atom([]) export const videoMagnetAtom = atom(undefined as unknown as Cms.IVideoMagnet) -export const searchAtom = atom({ +export const videoMagnetSearchAtom = atom({ key: '' } as SearchParams) -export const pageAtom = atom({ +export const videoMagnetPageAtom = atom({ pageSize: 10, page: 1, }) export const videoMagnetsAtom = atomWithQuery((get) => { return { - queryKey: [ 'videoMagnets', get(searchAtom) ], + queryKey: [ 'videoMagnets', get(videoMagnetSearchAtom) ], queryFn: async ({ queryKey: [ , params ] }) => { return await cmsServ.videoMagnet.list(params as SearchParams) }, @@ -64,7 +64,7 @@ export const saveOrUpdateVideoMagnetAtom = atomWithMutation { onSuccess: (res) => { message.success('message.deleteSuccess') //更新列表 - get(queryClientAtom).invalidateQueries({ queryKey: [ 'videoMagnets', get(searchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'videoMagnets', get(videoMagnetSearchAtom) ] }) return res } }