import React, { useState, useRef } from 'react'; import { PlusOutlined, TagsOutlined, UploadOutlined } from '@ant-design/icons'; import { Button, message, Modal, Col, Row, Space, Upload } from 'antd'; import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; import type { ProColumns, ActionType } from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table'; import { BetaSchemaForm, ModalForm } from '@ant-design/pro-form'; import type { ProDescriptionsItemProps } from '@ant-design/pro-descriptions'; import ProDescriptions from '@ant-design/pro-descriptions'; import type { FormValueType } from './components/UpdateForm'; import { queryTagList, saveCourse, removeCourse, queryCourseList } from './service'; import type { TableListItem, TableListPagination } from './data'; import Tags from './components/Tags'; import type { DataItem } from '@antv/data-set/lib/transform/tag-cloud'; import { VideoJS } from './components/VideoJS'; import { v4 as uuidv4 } from 'uuid'; const uuid = uuidv4(); /** * 添加课程 * * @param fields */ const handleAdd = async (fields: TableListItem) => { const hide = message.loading('正在添加'); try { await saveCourse({ ...fields, attachment_filesize:0, }); hide(); message.success('添加成功'); return true; } catch (error) { hide(); message.error('添加失败请重试!'); return false; } }; /** * 更新课程 * * @param fields */ const handleUpdate = async (fields: FormValueType, currentRow?: TableListItem) => { const hide = message.loading('正在配置'); try { await saveCourse({ ...currentRow, ...fields, }); hide(); message.success('配置成功'); return true; } catch (error) { hide(); message.error('配置失败请重试!'); return false; } }; /** * 删除课程(接口不支持批量) * 参数为记录数组 * @param selectedRows */ const handleRemove = async (selectedRows: TableListItem[]) => { const hide = message.loading('正在删除'); if (!selectedRows) return true; console.log('key', selectedRows); try { await removeCourse({ key: selectedRows.map((row) => row.key), }); hide(); message.success('删除成功,即将刷新'); return true; } catch (error) { console.log('error', error) hide(); message.error('删除失败,请重试'); return false; } }; const CourseList: React.FC = () => { /** 新建窗口的弹窗 */ const [tagsModalVisible, handleTagsModalVisible] = useState(false); /** 更新窗口的弹窗 */ const [createModalVisible, handleCreateModalVisible] = useState(false); const [detailModalVisible, handleDetailModalVisible] = useState(false); const [updateModalVisible, handleUpdateModalVisible] = useState(false); const actionRef = useRef(); const playerRef = React.useRef(null); // 播放器引用 const [currentRow, setCurrentRow] = useState(); const [selectedRowsState, setSelectedRows] = useState([]); const [uploadFileName, SetUploadFileName] = useState(); const [uploadFileExt, SetUploadFileExt] = useState(); /** 列表项定义 */ const columns: ProColumns[] = [ { title: '序号', key: 'index', valueType: 'indexBorder', render: (text: React.ReactNode, _: any, index: number) => { if (actionRef && actionRef?.current && actionRef?.current?.pageInfo) { return `${ (actionRef?.current?.pageInfo?.current - 1) * actionRef.current.pageInfo?.pageSize + (index + 1) }`; } else { return ''; } }, width: 48, }, { title: '课程名称', dataIndex: 'course_name', valueType: 'text', hideInTable: false, hideInDescriptions: false, hideInForm: false, hideInSearch: true, formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, { max: 50, message: '最大长度为50字符', } ], }, // 传递给 Form.Item 的配置 }, { title: '主讲教师', dataIndex: 'lecture_teacher', valueType: 'text', sorter: false, hideInTable: false, hideInForm: false, hideInSearch: true, renderText: (val: string) => `${val}`, formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, { max: 20, message: '最大长度为20字符', } ], }, // 传递给 Form.Item 的配置 }, { title: '课时', dataIndex: 'course_minutes', valueType: 'text', sorter: false, hideInTable: true, hideInForm: false, hideInSearch: true, renderText: (val: string) => `${val}`, formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, { max: 4, message: '最大长度为4字符', } ], }, // 传递给 Form.Item 的配置 }, { title: '课程描述', valueType: 'textarea', dataIndex: 'course_describe', sorter: false, hideInTable: false, hideInForm: false, hideInSearch: true, renderText: (val: string) => `${val}`, formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, { max: 150, message: '最大长度为150字符', } ], }, // 传递给 Form.Item 的配置 }, { title: '标签', dataIndex: 'tag_id', sorter: false, valueType: 'select', hideInForm: false, request: async () => { const {data: Items} = await queryTagList({}); const tags = [] for(let i=0; i ( { console.log('file', file) // 获取文件名 SetUploadFileName(file?.name) ; // 获取最后一个.的位置 const index = file?.name.lastIndexOf("."); // 获取后缀 SetUploadFileExt(file?.name.substr(index+1)); }} data={{ name: uploadFileName, chunk: 0, chunks: 1, key: `down/Syzx/${uuid?.substr(0,2)}/${uuid}.${uploadFileExt}` }} maxCount={1} multiple={false} > ), formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, ], }, // 传递给 Form.Item 的配置 //renderText: (val: string) => `${val}M`, }, { title: '视频大小', dataIndex: 'attachment_filesize', sorter: false, hideInForm: true, hideInSearch: true, renderText: (val: string) => `${val}M`, formItemProps: { // 参照 https://ant.design/components/form-cn/#Rule rules: [ { required: true, message: '此项为必填项', }, ], }, // 传递给 Form.Item 的配置 }, { title: '创建时间', dataIndex: 'create_time', valueType: 'dateRange', sorter: true, hideInTable: true, hideInForm: true, hideInSearch: false, //renderText: (val: string) => `${val}`, }, { title: '操作', dataIndex: 'option', valueType: 'option', render: (_dom: any, record: React.SetStateAction) => [ { setCurrentRow(record); handleDetailModalVisible(true); }} > 查看 , { setCurrentRow(record); handleUpdateModalVisible(true); }} > 编辑 , { handleRemove([{key: record?.course_id}]); // 调用批量删除函数(如果接口不支持批量需要在service中处理) setSelectedRows([]); actionRef.current?.reloadAndRest?.(); }}> 删除 , ], }, ]; /** 获取列数据初始值 */ const getInitialValues = (cols: any[], vals: any) => { console.log('getInitialValues-columns', columns); console.log('getInitialValues-values', vals); const initialValues: any[] = []; cols.forEach((column: { dataIndex: string }) => { const key: any = column?.dataIndex || ''; initialValues.push({ ...column, initialValue: key ? vals[key] : '' }); }); console.log('initialValues::', initialValues); return initialValues || []; }; return ( headerTitle={false} actionRef={actionRef} rowKey="course_id" options={false} search={{ labelWidth: 120, }} toolBarRender={() => [ , , ]} request={async (value) => { console.log('value', value) const { create_time } = value; if(create_time){ value['begin_time'] = create_time[0] value['end_time'] = create_time[1] } const {data} = await queryCourseList({ ...value, page_number: value?.current || 1, page_size: value?.pageSize, }); return { current: data?.page_number, data: data?.list, pageSize: data?.page_size, success: true, total: data?.total_row || 0, }; }} // dataSource={list} columns={columns} rowSelection={false} /> {selectedRowsState?.length > 0 && ( 已选择{' '} {selectedRowsState.length} {' '} 项    } > )} { playerRef.current?.pause(); //videoRef.current.play() console.log('playerRef:', playerRef.current) setCurrentRow(undefined); // 设置当前行 handleDetailModalVisible(false); }} footer={null} centered > {console.log('currentRow', currentRow)} {console.log('columns', columns.slice(0, columns.length - 1))} {currentRow?.course_id && ( 加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持) language: 'zh-CN', aspectRatio: '4:3', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3") fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。 sources: [ { src: (currentRow?.attachment_json?.url) || '/dsideal_yy/html/down/M3u8/2D/2D99BF1D-2F37-47FB-8A24-45112A236B8F.m3u8', // 测试地址后续请删除 type: 'application/x-mpegURL' } ], poster: currentRow?.attachment_json?.img || '', // 你的封面地址 width: document.documentElement.clientWidth, notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。 controlBar: { timeDivider: true, durationDisplay: true, remainingTimeDisplay: true, fullscreenToggle: true // 全屏按钮 } }} onReady={(play: any) => { //console.log('play====', play); playerRef.current = play play.play(); play.on("timeupdate", function (event) { //const _timeCurrent = Date.parse(new Date().toString()) / 1000; // 当前时间 //setTimeUpdateState(_timeCurrent); //timeUpdateState console.log('play--', play.currentTime()) console.log('play-%-', parseInt(play.currentTime()) % 15) if (parseInt(play.currentTime()) % 15 === 0) { // 每15秒更新进度 console.log() } //var currentTime = parseInt(this.currentTime()); //当前时间 //var duration = this.duration(); //视频时常 //var percent = (currentTime / duration * 100).toFixed(0) + "%"; //console.log('event',event); //$("#current").text(this.currentTime()); //$("#duration").text(duration); }) }} /> column={1} /* title={currentRow?.name} */ dataSource={currentRow} /* request={async () => ({ data: currentRow || {}, })}*/ params={{ id: currentRow?.course_id, }} columns={ columns.slice(0, columns.length - 1) as ProDescriptionsItemProps[] } style={{ padding: '0 24px' }} /> )} { handleCreateModalVisible(false); }} footer={null} > layout="horizontal" layoutType="Form" labelCol={{ span: 8 }} wrapperCol={{ span: 12 }} onFinish={async (values: any) => { // 表单处理 //console.log('columns:', columns); console.log('values:', values); console.log('uploadFileName',uploadFileName) //return false; // values.attachment_json.response.file.response.url await handleAdd({ ...values, attachment_json: `{"img":"", "name": "${values.attachment_json.file.name}", "url": "down/M3u8/${uuid?.substr(0,2)}/${uuid}.m3u8"}` }); handleCreateModalVisible(false); actionRef.current?.reloadAndRest?.(); }} submitter={{ render: (props, doms) => ( {doms} ), }} // action = '' title="新建" columns={columns||[]} /> { handleUpdateModalVisible(false); }} footer={null} > {currentRow?.course_id && ( layout="horizontal" layoutType="Form" labelCol={{ span: 8 }} wrapperCol={{ span: 12 }} onFinish={async (values) => { console.log(values); }} submitter={{ render: (props, doms) => ( {doms} ), }} // action = '' title="编辑" columns={getInitialValues(columns, currentRow)} /> )} ); }; export default CourseList;