{"version":3,"sources":["component/layout/index.tsx","component/pop-dialog/index.tsx","utils/common.ts","utils/api.ts","component/add-room-dialog/index.tsx","component/live-list/index.tsx","component/live-info/index.tsx","component/config-info/index.tsx","component/file-list/index.tsx","App.tsx","serviceWorker.ts","index.tsx"],"names":["SubMenu","Menu","Header","Layout","Content","Sider","RootLayout","className","width","style","background","mode","defaultSelectedKeys","defaultOpenKeys","height","borderRight","key","title","type","Item","to","margin","minHeight","overflow","this","props","children","React","Component","PopDialog","icon","color","onConfirm","customFetch","arg1","args","Promise","resolve","reject","fetch","call","then","rsp","ok","json","clonedRsp","clone","catch","err","text","message","err_msg","statusText","data","Utils","alertError","url","body","method","JSON","stringify","headers","Headers","console","error","size","i","Math","floor","log","Number","pow","toFixed","timestamp","date","Date","year","getFullYear","toString","padStart","month","getMonth","day","getDate","hour","getHours","min","getMinutes","sec","getSeconds","utils","API","requestGet","reqBody","requestPost","id","requestDelete","requestPut","saveSettings","err_no","alert","path","api","AddRoomDialog","state","ModalText","visible","confirmLoading","textView","showModal","setState","handleOk","addNewRoom","saveSettingsInBackground","refresh","handleCancel","textChange","e","target","value","onOk","onCancel","placeholder","onChange","LiveList","child","timer","runStatus","dataIndex","render","tags","map","tag","toUpperCase","runAction","listening","stopRecord","roomId","startRecord","deleteRoom","onClick","history","push","address","name","columns","sorter","a","b","localeCompare","room","href","rel","roomName","smallColumns","onRef","ref","onAddRoomClick","onSettingSave","requestListData","list","addRoomDialogVisible","window","setInterval","clearInterval","getRoomList","length","item","index","recording","initializing","host_name","room_name","live_url","platform_cn_name","forEach","column","addressList","Array","from","Set","filters","onFilter","record","includes","backgroundColor","ghost","subTitle","extra","screen","dataSource","pagination","LiveInfo","appName","appVersion","buildTime","gitHash","pid","platform","goVersion","getLiveInfo","app_name","app_version","build_time","git_hash","go_version","bordered","label","marginTop","getTextForCopy","copy","ConfigInfo","saveRawConfig","config","getConfigInfo","onValueChange","code","highlight","languages","js","padding","fontFamily","fontSize","FileList","showPlayer","isPlayerVisible","hidePlayer","handleChange","filtetrs","sortedInfo","onRowClick","encodeURIComponent","match","params","is_folder","art","Artplayer","pip","setting","playbackRate","aspectRatio","flip","autoSize","autoMini","mutex","miniProgressBar","backdrop","fullscreen","fullscreenWeb","lang","container","customType","flv","video","mpegtsjs","isSupported","flvPlayer","createPlayer","hasVideo","hasAudio","attachMediaElement","load","notice","show","parentFolders","currentFolderFiles","requestFileList","nextProps","folders","split","getFileList","files","order","columnKey","currentPath","rootBreadcrumbItem","items","v","sortOrder","theme","byteSizeToHumanReadableFileSize","last_modified","timestampToHumanReadable","pageSize","scroll","x","renderParentFolderBar","renderArtPlayer","renderCurrentFolderFileList","App","component","Boolean","location","hostname","ReactDOM","document","getElementById","navigator","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.e5bf8465.chunk.js","sourcesContent":["import React from 'react';\nimport { HashRouter as Router, Link } from 'react-router-dom';\nimport { Layout, Menu, Icon } from 'antd';\nimport './layout.css';\n\nconst { SubMenu } = Menu;\nconst { Header, Content, Sider } = Layout;\n\nclass RootLayout extends React.Component {\n render() {\n return (\n \n
\n

Bililive-go

\n
\n \n \n \n \n \n \n LiveClient\n \n }\n >\n 监控列表\n 系统状态\n 设置\n 文件\n \n \n \n \n \n {this.props.children}\n \n \n \n \n
\n )\n }\n}\n\nexport default RootLayout;\n","import { Popconfirm, Icon } from 'antd';\nimport React from 'react';\n\ninterface DialogContent{\n title: string,\n onConfirm?: (e?: React.MouseEvent) => void\n}\n\nclass PopDialog extends React.Component {\n render() {\n return (\n }\n onConfirm={this.props.onConfirm}>\n {this.props.children}\n \n );\n }\n}\n\nexport default PopDialog;\n","/*\n * @Author: Jmeow\n * @Date: 2020-01-28 11:25:44\n * @Description: common utils\n */\n\nfunction customFetch(arg1: Parameters[0], ...args: any[]) {\n return new Promise((resolve, reject) => {\n fetch.call(null, arg1, ...args)\n .then(rsp => {\n if (rsp.ok) {\n return rsp.json();\n } else {\n const clonedRsp = rsp.clone();\n return rsp.json()\n .catch(err => {\n return clonedRsp\n .text()\n .then((err: any) => {\n let message = \"\";\n if (err) {\n if (err.err_msg) {\n message = err.err_msg;\n } else {\n message = err;\n }\n }\n return message;\n })\n .catch(err => rsp.statusText)\n .then(data => {\n reject(data);\n throw (data);\n });\n });\n }\n }).then(data => {\n resolve(data);\n }).catch(err => {\n Utils.alertError();\n reject(err);\n });\n });\n}\n\nclass Utils {\n /**\n * Get request\n * @param url URL\n */\n requestGet(url: string) {\n return customFetch(url);\n }\n\n /**\n * Post request\n * @param url URL\n * @param body Request body\n */\n requestPost(url: string, body?: object) {\n return customFetch(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: new Headers({\n 'Content-Type': 'application/json'\n })\n });\n }\n\n /**\n * Post request\n * @param url URL\n * @param body Request body\n */\n requestPut(url: string, body?: object) {\n return customFetch(url, {\n method: 'PUT',\n body: JSON.stringify(body),\n headers: new Headers({\n 'Content-Type': 'application/json'\n })\n })\n }\n\n /**\n * Delete request\n * @param url URL\n */\n requestDelete(url: string) {\n return customFetch(url, {\n method: 'DELETE'\n });\n }\n\n /**\n * Show Error \n * @param err error Object\n */\n static alertError(err?: any) {\n console.error(err ? err : \"Server Error!\");\n }\n\n static byteSizeToHumanReadableFileSize(size: number): string {\n if (!size) {\n return \"0\";\n }\n const i = Math.floor(Math.log(size) / Math.log(1024));\n const ret = Number((size / Math.pow(1024, i)).toFixed(2)) + \" \" + ['B', 'kB', 'MB', 'GB', 'TB'][i];\n return ret;\n }\n\n static timestampToHumanReadable(timestamp: number): string {\n const date = new Date(timestamp * 1000);\n const year = date.getFullYear().toString().padStart(4, \"0\");\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const hour = date.getHours().toString().padStart(2, \"0\");\n const min = date.getMinutes().toString().padStart(2, \"0\");\n const sec = date.getSeconds().toString().padStart(2, \"0\");\n return `${year}-${month}-${day} ${hour}:${min}:${sec}`;\n }\n}\n\nexport default Utils;\n","/*\n * @Author: Jmeow\n * @Date: 2020-01-28 15:30:50\n * @Description: common API\n */\n\nimport Utils from './common';\n\nconst utils = new Utils();\n\nconst BASE_URL = \"api\";\n\nclass API {\n /**\n * 获取录播机状态\n */\n getLiveInfo() {\n return utils.requestGet(`${BASE_URL}/info`);\n }\n\n /**\n * 获取直播间列表\n */\n getRoomList() {\n return utils.requestGet(`${BASE_URL}/lives`);\n }\n\n /**\n * 添加新的直播间\n * @param url URL\n */\n addNewRoom(url: string) {\n const reqBody = [\n {\n \"url\": url,\n \"listen\": true\n }\n ];\n return utils.requestPost(`${BASE_URL}/lives`, reqBody);\n }\n\n /**\n * 删除直播间\n * @param id 直播间id\n */\n deleteRoom(id: string) {\n return utils.requestDelete(`${BASE_URL}/lives/${id}`);\n }\n\n /**\n * 开始监听直播间\n * @param id 直播间id\n */\n startRecord(id: string) {\n return utils.requestGet(`${BASE_URL}/lives/${id}/start`);\n }\n\n /**\n * 停止监听直播间\n * @param id 直播间id\n */\n stopRecord(id: string) {\n return utils.requestGet(`${BASE_URL}/lives/${id}/stop`);\n }\n\n /**\n * 保存设置至config文件\n */\n saveSettings() {\n return utils.requestPut(`${BASE_URL}/config`);\n }\n\n /**\n * 保存设置至config文件,且不处理返回结果\n */\n saveSettingsInBackground() {\n this.saveSettings()\n .then((rsp: any) => {\n if (rsp.err_no === 0) {\n console.log('Save Settings success !!');\n } else {\n console.log('Server Error !!');\n }\n })\n .catch(err => {\n alert(`保存设置失败:\\n${err}`);\n })\n }\n\n /**\n * 获取设置明文\n */\n getConfigInfo() {\n return utils.requestGet(`${BASE_URL}/raw-config`);\n }\n\n /**\n * 保存设置明文\n * @param json \\{config: \"yaml格式的设置原文\"\\}\n */\n saveRawConfig(json: any) {\n return utils.requestPut(`${BASE_URL}/raw-config`, json);\n }\n\n /**\n *\n * @param path 获取文件目录\n */\n getFileList(path: string = \"\") {\n return utils.requestGet(`${BASE_URL}/file/${path}`);\n }\n}\n\nexport default API;\n","import { Modal, Input } from 'antd';\nimport React from 'react';\nimport API from '../../utils/api';\n\nconst api = new API();\n\ninterface Props {\n refresh?: any\n}\n\nclass AddRoomDialog extends React.Component {\n state = {\n ModalText: '请输入直播间的URL地址',\n visible: false,\n confirmLoading: false,\n textView: ''\n };\n\n showModal = () => {\n this.setState({\n ModalText: '请输入直播间的URL地址',\n visible: true,\n confirmLoading: false,\n });\n };\n\n handleOk = () => {\n this.setState({\n ModalText: '正在添加直播间......',\n confirmLoading: true,\n });\n\n api.addNewRoom(this.state.textView)\n .then((rsp) => {\n // 保存设置\n api.saveSettingsInBackground();\n this.setState({\n visible: false,\n confirmLoading: false,\n textView:''\n });\n this.props.refresh();\n })\n .catch(err => {\n alert(`添加直播间失败:\\n${err}`);\n this.setState({\n visible: false,\n confirmLoading: false,\n textView:''\n });\n })\n };\n\n handleCancel = () => {\n this.setState({\n visible: false,\n textView:''\n });\n };\n\n textChange = (e: any) => {\n this.setState({\n textView: e.target.value\n })\n }\n\n render() {\n const { visible, confirmLoading, ModalText,textView } = this.state;\n return (\n
\n \n

{ModalText}

\n \n \n
\n );\n }\n}\n\nexport default AddRoomDialog;\n","import React from \"react\";\nimport { Button, Divider, PageHeader, Table, Tag } from 'antd';\nimport PopDialog from '../pop-dialog/index';\nimport AddRoomDialog from '../add-room-dialog/index';\nimport API from '../../utils/api';\nimport './live-list.css';\nimport { RouteComponentProps } from \"react-router-dom\";\nimport { ColumnProps } from 'antd/lib/table';\n\nconst api = new API();\n\nconst REFRESH_TIME = 3 * 60 * 1000;\n\ninterface Props extends RouteComponentProps {\n refresh?: () => void\n}\n\ninterface IState {\n list: ItemData[],\n addRoomDialogVisible: boolean,\n window: any\n}\n\ninterface ItemData {\n key: string,\n name: string,\n room: Room,\n address: string,\n tags: string[],\n listening: boolean\n roomId: string\n}\n\ninterface Room {\n roomName: string;\n url: string;\n}\n\nclass LiveList extends React.Component {\n //子控件\n child!: AddRoomDialog;\n //定时器\n timer!: NodeJS.Timeout;\n\n runStatus = {\n title: '运行状态',\n key: 'tags',\n dataIndex: 'tags',\n render: (tags: { map: (arg0: (tag: any) => JSX.Element) => React.ReactNode; }) => (\n \n {tags.map(tag => {\n let color = 'green';\n if (tag === '已停止') {\n color = 'grey';\n }\n if (tag === '监控中') {\n color = 'green';\n }\n if (tag === '录制中') {\n color = 'red';\n }\n if (tag === '初始化') {\n color = 'orange';\n }\n\n return (\n \n {tag.toUpperCase()}\n \n );\n })}\n \n ),\n };\n\n runAction = {\n title: '操作',\n key: 'action',\n dataIndex: 'listening',\n render: (listening: boolean, data: ItemData) => (\n \n {\n if (listening) {\n //停止监控\n api.stopRecord(data.roomId)\n .then(rsp => {\n api.saveSettingsInBackground();\n this.refresh();\n })\n .catch(err => {\n alert(`停止监控失败:\\n${err}`);\n });\n } else {\n //开启监控\n api.startRecord(data.roomId)\n .then(rsp => {\n api.saveSettingsInBackground();\n this.refresh();\n })\n .catch(err => {\n alert(`开启监控失败:\\n${err}`);\n });\n }\n }}>\n \n \n \n {\n api.deleteRoom(data.roomId)\n .then(rsp => {\n api.saveSettingsInBackground();\n this.refresh();\n })\n .catch(err => {\n alert(`删除直播间失败:\\n${err}`);\n });\n }}>\n \n \n \n \n \n ),\n };\n\n columns = [\n {\n title: '主播名称',\n dataIndex: 'name',\n key: 'name',\n sorter: (a: ItemData, b: ItemData) => {\n return a.name.localeCompare(b.name);\n },\n },\n {\n title: '直播间名称',\n dataIndex: 'room',\n key: 'room',\n render: (room: Room) => {room.roomName}\n },\n {\n title: '直播平台',\n dataIndex: 'address',\n key: 'address',\n sorter: (a: ItemData, b: ItemData) => {\n return a.address.localeCompare(b.address);\n },\n },\n this.runStatus,\n this.runAction\n ];\n\n smallColumns = [\n {\n title: '主播名称',\n dataIndex: 'name',\n key: 'name',\n render: (name: String, data: ItemData) => {name}\n },\n this.runStatus,\n this.runAction\n ];\n\n constructor(props: Props) {\n super(props);\n this.state = {\n list: [],\n addRoomDialogVisible: false,\n window: window\n }\n }\n\n componentDidMount() {\n //refresh data\n this.requestListData();\n this.timer = setInterval(() => {\n this.requestListData();\n }, REFRESH_TIME);\n }\n\n componentWillUnmount() {\n //clear refresh timer\n clearInterval(this.timer);\n }\n\n onRef = (ref: AddRoomDialog) => {\n this.child = ref\n }\n\n /**\n * 当添加房间按钮点击,弹出Dialog\n */\n onAddRoomClick = () => {\n this.child.showModal()\n }\n\n /**\n * 保存设置至config文件\n */\n onSettingSave = () => {\n api.saveSettings()\n .then((rsp: any) => {\n if (rsp.err_no === 0) {\n alert(\"设置保存成功\");\n } else {\n alert(\"Server Error!\");\n }\n }).catch(err => {\n alert(`Server Error!:\\n${err}`);\n })\n }\n\n /**\n * 刷新页面数据\n */\n refresh = () => {\n this.requestListData();\n }\n\n /**\n * 加载列表数据\n */\n requestListData() {\n api.getRoomList()\n .then(function (rsp: any) {\n if (rsp.length === 0) {\n return [];\n }\n return rsp.map((item: any, index: number) => {\n //判断标签状态\n let tags;\n if (item.listening === true) {\n tags = ['监控中'];\n } else {\n tags = ['已停止'];\n }\n\n if (item.recording === true) {\n tags = ['录制中'];\n }\n\n if (item.initializing === true) {\n tags.push('初始化')\n }\n\n return {\n key: index + 1,\n name: item.host_name,\n room: {\n roomName: item.room_name,\n url: item.live_url\n },\n address: item.platform_cn_name,\n tags,\n listening: item.listening,\n roomId: item.id\n };\n });\n })\n .then((data: ItemData[]) => {\n this.setState({\n list: data\n });\n })\n .catch(err => {\n alert(`加载列表数据失败:\\n${err}`);\n });\n }\n\n render() {\n const { list } = this.state;\n this.columns.forEach((column: ColumnProps) => {\n if (column.key === 'address') {\n // 直播平台去重数组\n const addressList = Array.from(new Set(list.map(item => item.address)));\n column.filters = addressList.map(text => ({ text, value: text }));\n column.onFilter = (value: string, record: ItemData) => record.address === value;\n }\n if (column.key === 'tags') {\n column.filters = ['初始化', '监控中', '录制中', '已停止'].map(text => ({ text, value: text }));\n column.onFilter = (value: string, record: ItemData) => record.tags.includes(value);\n }\n })\n return (\n
\n
\n 保存设置,\n ,\n \n ]}>\n \n
\n 768) ? this.columns : this.smallColumns}\n dataSource={this.state.list}\n size={(this.state.window.screen.width > 768) ? \"default\" : \"middle\"}\n pagination={false}\n />\n
\n );\n };\n}\n\nexport default LiveList;\n","import React from \"react\";\nimport API from '../../utils/api';\nimport {\n PageHeader,\n Descriptions,\n Button\n} from 'antd';\nimport copy from 'copy-to-clipboard';\n\nconst api = new API();\n\ninterface Props {\n\n}\n\ninterface IState {\n appName: string\n appVersion: string\n buildTime: string\n gitHash: string\n pid: string\n platform: string\n goVersion: string\n}\n\nclass LiveInfo extends React.Component {\n\n constructor(props: Props) {\n super(props);\n this.state = {\n appName: \"\",\n appVersion: \"\",\n buildTime: \"\",\n gitHash: \"\",\n pid: \"\",\n platform: \"\",\n goVersion: \"\"\n }\n }\n\n componentDidMount() {\n api.getLiveInfo()\n .then((rsp: any) => {\n this.setState({\n appName: rsp.app_name,\n appVersion: rsp.app_version,\n buildTime: rsp.build_time,\n gitHash: rsp.git_hash,\n pid: rsp.pid,\n platform: rsp.platform,\n goVersion: rsp.go_version\n })\n })\n .catch(err => {\n alert(\"请求服务器失败\");\n })\n }\n\n getTextForCopy(): string {\n return `\nApp Name: ${this.state.appVersion}\nApp Version: ${this.state.appVersion}\nBuild Time: ${this.state.buildTime}\nPid: ${this.state.pid}\nPlatform: ${this.state.platform}\nGo Version: ${this.state.goVersion}\nGit Hash: ${this.state.gitHash}\n`;\n }\n\n render() {\n return (\n
\n
\n \n \n
\n \n {this.state.appName}\n {this.state.appVersion}\n {this.state.buildTime}\n {this.state.pid}\n {this.state.platform}\n {this.state.goVersion}\n {this.state.gitHash}\n \n {\n const text = this.getTextForCopy();\n const result = copy(text);\n if (result) {\n alert(\"复制成功:\" + text);\n } else {\n alert(`复制失败`);\n }\n }}\n >\n 复制到剪贴板\n \n
\n )\n }\n}\n\nexport default LiveInfo;\n","import React from \"react\";\nimport Editor from 'react-simple-code-editor';\nimport { highlight, languages } from 'prismjs';\nimport 'prismjs/components/prism-clike';\nimport 'prismjs/components/prism-javascript';\nimport 'prismjs/themes/prism.css'; //Example style, you can use another\nimport API from '../../utils/api';\nimport { Button } from \"antd\";\nimport './config-info.css';\nconst api = new API();\n\ninterface Props {\n\n}\n\ninterface IState {\n config: any\n}\n\nclass ConfigInfo extends React.Component {\n\n constructor(props: Props) {\n super(props);\n this.state = {\n config: null,\n }\n }\n\n componentDidMount(): void {\n api.getConfigInfo()\n .then((rsp: any) => {\n this.setState({\n config: rsp.config\n });\n })\n .catch(err => {\n alert(\"获取配置信息失败\");\n });\n }\n\n /**\n * 保存设置至config文件\n */\n onSettingSave = () => {\n api.saveRawConfig({ config: this.state.config })\n .then((rsp: any) => {\n if (rsp.err_no === 0) {\n alert(\"设置保存成功\");\n } else {\n alert(`Server Error!\\n${rsp.err_msg}`);\n }\n })\n .catch(err => {\n alert(\"设置保存失败!\");\n })\n }\n\n render() {\n if (this.state.config === null) {\n return
loading...
;\n }\n return
\n this.setState({ config: code })}\n highlight={code => {\n const ret = highlight(code, languages.js, \"js\");\n return ret;\n }}\n padding={10}\n style={{\n fontFamily: '\"Fira code\", \"Fira Mono\", monospace',\n fontSize: 12,\n }}\n />\n \n 保存设置\n \n
\n }\n}\n\nexport default ConfigInfo;","import React from \"react\";\nimport API from \"../../utils/api\";\nimport { Breadcrumb, Divider, Icon, Table } from \"antd\";\nimport { Link, RouteComponentProps } from \"react-router-dom\";\nimport Utils from \"../../utils/common\";\nimport './file-list.css';\nimport { PaginationConfig } from \"antd/lib/pagination\";\nimport { SorterResult } from \"antd/lib/table\";\nimport Artplayer from \"artplayer\";\nimport mpegtsjs from \"mpegts.js\";\n\nconst api = new API();\n\ninterface MatchParams {\n path: string | undefined;\n}\n\ninterface Props extends RouteComponentProps {\n}\n\ntype CurrentFolderFile = {\n is_folder: boolean;\n name: string;\n last_modified: number;\n size: number;\n}\n\ninterface IState {\n parentFolders: string[];\n currentFolderFiles: CurrentFolderFile[];\n sortedInfo: Partial>;\n isPlayerVisible: boolean;\n}\n\nclass FileList extends React.Component {\n constructor(props: Props) {\n super(props);\n this.state = {\n parentFolders: [props.match.params.path ?? \"\"],\n currentFolderFiles: [],\n sortedInfo: {},\n isPlayerVisible: false,\n };\n }\n\n componentDidMount(): void {\n this.requestFileList(this.props.match.params.path);\n }\n\n componentWillReceiveProps(nextProps: Props) {\n this.requestFileList(nextProps.match.params.path);\n }\n\n setPath(path: string) {\n const folders = path.split(\"/\");\n this.setState({ parentFolders: folders });\n }\n\n requestFileList(path: string = \"\"): void {\n api.getFileList(path)\n .then((rsp: any) => {\n if (rsp?.files) {\n this.setState({\n currentFolderFiles: rsp.files,\n sortedInfo: path ? {\n order: \"descend\",\n columnKey: \"last_modified\",\n } : {\n order: \"ascend\",\n columnKey: \"name\"\n },\n })\n }\n });\n }\n\n showPlayer = () => {\n this.setState({\n isPlayerVisible: true,\n });\n };\n\n hidePlayer = () => {\n this.setState({\n isPlayerVisible: false,\n });\n };\n\n handleChange = (pagination: PaginationConfig, filtetrs: Partial>, sorter: SorterResult) => {\n this.setState({\n sortedInfo: sorter,\n });\n };\n\n onRowClick = (record: CurrentFolderFile) => {\n let path = encodeURIComponent(record.name);\n if (this.props.match.params.path) {\n path = this.props.match.params.path + \"/\" + path;\n }\n if (record.is_folder) {\n this.props.history.push(\"/fileList/\" + path);\n } else {\n this.setState({\n isPlayerVisible: true,\n }, () => {\n const art = new Artplayer({\n pip: true,\n setting: true,\n playbackRate: true,\n aspectRatio: true,\n flip: true,\n autoSize: true,\n autoMini: true,\n mutex: true,\n miniProgressBar: true,\n backdrop: false,\n fullscreen: true,\n fullscreenWeb: true,\n lang: 'zh-cn',\n container: '#art-container',\n url: `files/${path}`,\n customType: {\n flv: function (video, url) {\n if (mpegtsjs.isSupported()) {\n const flvPlayer = mpegtsjs.createPlayer({\n type: \"flv\",\n url: url,\n hasVideo: true,\n hasAudio: true,\n }, {});\n flvPlayer.attachMediaElement(video);\n flvPlayer.load();\n } else {\n if (art) {\n art.notice.show = \"不支持播放格式: flv\";\n }\n }\n },\n },\n });\n });\n }\n };\n\n renderParentFolderBar(): JSX.Element {\n const rootFolderName = \"输出文件路径\";\n let currentPath = \"/fileList\";\n const rootBreadcrumbItem = \n {rootFolderName}\n ;\n const folders = this.props.match.params.path?.split(\"/\") || [];\n const items = folders.map(v => {\n currentPath += \"/\" + v;\n return \n {v}\n \n });\n return \n {rootBreadcrumbItem}\n {items}\n ;\n }\n\n renderCurrentFolderFileList(): JSX.Element {\n let { sortedInfo } = this.state;\n sortedInfo = sortedInfo || {};\n const columns = [{\n title: \"文件名\",\n dataIndex: \"name\",\n key: \"name\",\n sorter: (a: CurrentFolderFile, b: CurrentFolderFile) => {\n if (a.is_folder === b.is_folder) {\n return a.name.localeCompare(b.name);\n } else {\n return a.is_folder ? -1 : 1;\n }\n },\n sortOrder: sortedInfo.columnKey === \"name\" && sortedInfo.order,\n render: (text: string, record: CurrentFolderFile, index: number) => {\n return [\n record.is_folder ? : ,\n ,\n record.name,\n ];\n }\n }, {\n title: \"文件大小\",\n dataIndex: \"size\",\n key: \"size\",\n sorter: (a: CurrentFolderFile, b: CurrentFolderFile) => a.size - b.size,\n sortOrder: sortedInfo.columnKey === \"size\" && sortedInfo.order,\n render: (text: string, record: CurrentFolderFile, index: number) => {\n if (record.is_folder) {\n return \"\";\n } else {\n return Utils.byteSizeToHumanReadableFileSize(record.size);\n }\n },\n }, {\n title: \"最后修改时间\",\n dataIndex: \"last_modified\",\n key: \"last_modified\",\n sorter: (a: CurrentFolderFile, b: CurrentFolderFile) => a.last_modified - b.last_modified,\n sortOrder: sortedInfo.columnKey === \"last_modified\" && sortedInfo.order,\n render: (text: string, record: CurrentFolderFile, index: number) => Utils.timestampToHumanReadable(record.last_modified),\n }];\n\n return ();\n }\n\n renderArtPlayer() {\n return
;\n }\n\n render(): JSX.Element {\n return (
\n {this.renderParentFolderBar()}\n {this.state.isPlayerVisible ? this.renderArtPlayer() : this.renderCurrentFolderFileList()}\n
);\n }\n}\n\nexport default FileList;","import React from 'react';\nimport './App.css';\nimport 'antd/dist/antd.css';\nimport { Switch, Route } from 'react-router-dom';\nimport RootLayout from './component/layout/index';\nimport LiveList from './component/live-list/index';\nimport LiveInfo from './component/live-info/index';\nimport ConfigInfo from './component/config-info/index';\nimport FileList from './component/file-list/index';\n\nconst App: React.FC = () => {\n return (\n \n \n \n \n \n \n \n \n );\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\ntype Config = {\n onSuccess?: (registration: ServiceWorkerRegistration) => void;\n onUpdate?: (registration: ServiceWorkerRegistration) => void;\n};\n\nexport function register(config?: Config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(\n process.env.PUBLIC_URL,\n window.location.href\n );\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl: string, config?: Config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl: string, config?: Config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}