Update templates/index.html
Browse files- templates/index.html +144 -393
templates/index.html
CHANGED
|
@@ -562,127 +562,18 @@
|
|
| 562 |
return <img {...props} src="https://placehold.co/600x400?text=Loading" />;
|
| 563 |
};
|
| 564 |
|
| 565 |
-
const Video = ({ video }) => {
|
| 566 |
-
|
| 567 |
-
const [showPreview, setShowPreview] = useState(null);
|
| 568 |
-
const [holdPreviews, setHoldPreviews] = useState([]);
|
| 569 |
-
const videoRef = useRef(null);
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
const clickPreview = (id) => {
|
| 573 |
-
if (!holdPreviews.includes(id)) {
|
| 574 |
-
setHoldPreviews((prev) => [...prev, id]);
|
| 575 |
-
playPreview(id);
|
| 576 |
-
}
|
| 577 |
-
};
|
| 578 |
-
|
| 579 |
-
const playPreview = (id) => {
|
| 580 |
-
const preview = document.getElementById(`preview-${id}`);
|
| 581 |
-
|
| 582 |
-
if (!preview.getAttribute("src")) {
|
| 583 |
-
preview.addEventListener("loadedmetadata", (event) => {
|
| 584 |
-
event.target.play();
|
| 585 |
-
setShowPreview(id);
|
| 586 |
-
});
|
| 587 |
-
|
| 588 |
-
preview.setAttribute("src", preview.getAttribute("data-src"));
|
| 589 |
-
} else {
|
| 590 |
-
preview.play();
|
| 591 |
-
setShowPreview(id);
|
| 592 |
-
}
|
| 593 |
-
};
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
const { mutateAsync: favoriteMutation } = useMutation({
|
| 597 |
-
mutationKey: ["switch-favorite"],
|
| 598 |
-
mutationFn: async (favorite) => {
|
| 599 |
-
showLoading();
|
| 600 |
-
return await axios.post("/favorite", favorite)
|
| 601 |
-
},
|
| 602 |
-
onSuccess: async (data, variables, context) => {
|
| 603 |
-
hideLoading();
|
| 604 |
-
layer.msg('操作成功', { time: 2000, icon: 6 });
|
| 605 |
-
},
|
| 606 |
-
onError: () => {
|
| 607 |
-
hideLoading();
|
| 608 |
-
layer.msg('操作失败', { time: 2000, icon: 5 });
|
| 609 |
-
}
|
| 610 |
-
})
|
| 611 |
-
|
| 612 |
-
return (
|
| 613 |
-
<Card>
|
| 614 |
-
<a href={video.poster} target="_blank" data-fancybox="gallery" className={holdPreviews.includes(video.id) ? 'd-none' : 'd-block'}
|
| 615 |
-
data-download-src={video.src} data-caption={createCaption(video)}>
|
| 616 |
-
<AsyncImage className="card-img-top" src={video.poster} />
|
| 617 |
-
</a>
|
| 618 |
-
<video
|
| 619 |
-
className={holdPreviews.includes(video.id) ? 'd-block' : 'd-none'}
|
| 620 |
-
id={`preview-${video.id}`}
|
| 621 |
-
ref={videoRef}
|
| 622 |
-
data-src={`https://fourhoi.com/${video.code.toLowerCase()}/preview.mp4`}
|
| 623 |
-
controls
|
| 624 |
-
autoPlay
|
| 625 |
-
webkit-playsinline="true"
|
| 626 |
-
playsinline="true"
|
| 627 |
-
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
| 628 |
-
/>
|
| 629 |
-
|
| 630 |
-
<Card.Body>
|
| 631 |
-
<Card.Title>{`${video.code} ${video.title}`}</Card.Title>
|
| 632 |
-
<Card.Text>
|
| 633 |
-
{video.tags.map((tag, index) => (
|
| 634 |
-
<a target="_blank" href={`#/tags/${encodeURIComponent(tag)}`} className="badge bg-secondary text-wrap m-1">{tag}</a>
|
| 635 |
-
))}
|
| 636 |
-
</Card.Text>
|
| 637 |
-
|
| 638 |
-
<Dropdown className="float-start">
|
| 639 |
-
<Dropdown.Toggle variant="primary" id="dropdown-basic">
|
| 640 |
-
播放
|
| 641 |
-
</Dropdown.Toggle>
|
| 642 |
-
<Dropdown.Menu>
|
| 643 |
-
<Dropdown.Item href={video.src} target="_blank">网页</Dropdown.Item>
|
| 644 |
-
<Dropdown.Item href={`vlc://${video.src}`} target="_blank">VLC</Dropdown.Item>
|
| 645 |
-
<Dropdown.Item href={`videoplayerapp://open?url=${encodeURIComponent(video.src)}`} target="_blank">Video Player</Dropdown.Item>
|
| 646 |
-
</Dropdown.Menu>
|
| 647 |
-
</Dropdown>
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
<Button variant="primary" onClick={() => clickPreview(video.id)}><Icon
|
| 651 |
-
icon="video"
|
| 652 |
-
size="8"
|
| 653 |
-
className="text-text-primary"
|
| 654 |
-
/></Button>
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
<Button className={`btn float-end ${video.favorite ? 'btn-danger' : 'btn-secondary'}`} onClick={async () => {
|
| 658 |
-
layer.confirm('确定要进行操作?不可撤销!', {
|
| 659 |
-
btn: ['确定', '取消'] //按钮
|
| 660 |
-
}, async function () {
|
| 661 |
-
await favoriteMutation({ id: video.id, favorite: !video.favorite })
|
| 662 |
-
}, async function () {
|
| 663 |
-
|
| 664 |
-
});
|
| 665 |
-
|
| 666 |
-
}}><Icon
|
| 667 |
-
icon="star"
|
| 668 |
-
size="8"
|
| 669 |
-
className="text-text-primary"
|
| 670 |
-
/></Button>
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
</Card.Body>
|
| 675 |
-
</Card>
|
| 676 |
-
)
|
| 677 |
-
}
|
| 678 |
-
|
| 679 |
//设置框
|
| 680 |
const SettingModal = (props) => {
|
| 681 |
const settings = [
|
| 682 |
-
{ "
|
| 683 |
{ "github": [{ "label": "Actions地址", "key": "github_host", "show": true }, { "label": "Github令牌", "key": "github_token", "show": false }] },
|
| 684 |
{ "directus": [{ "label": "Directus地址", "key": "directus_host", "show": true }, { "label": "Directus令牌", "key": "directus_token", "show": false }] }
|
| 685 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 686 |
const [setting, setSetting] = useState({});
|
| 687 |
// useEffect(() => {
|
| 688 |
// localStorage.setItem('settings', JSON.stringify(setting));
|
|
@@ -856,16 +747,12 @@
|
|
| 856 |
const [response, error, loading, fetchData] = useAxios();
|
| 857 |
|
| 858 |
const fetchDataByPage = async (setting, query) => {
|
| 859 |
-
var host = setting.alist_host;
|
| 860 |
-
if (!host.endsWith("/")) {
|
| 861 |
-
host = host + '/'
|
| 862 |
-
}
|
| 863 |
fetchData({
|
| 864 |
-
url:
|
| 865 |
method: "POST",
|
| 866 |
data: query,
|
| 867 |
headers: {
|
| 868 |
-
'Authorization': setting.
|
| 869 |
'Content-Type': 'application/json'
|
| 870 |
},
|
| 871 |
});
|
|
@@ -873,9 +760,25 @@
|
|
| 873 |
return [response, error, loading, fetchDataByPage];
|
| 874 |
};
|
| 875 |
|
| 876 |
-
const paginateLinksGet = async (
|
| 877 |
-
const url = `/
|
| 878 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 879 |
return data
|
| 880 |
}
|
| 881 |
|
|
@@ -938,7 +841,7 @@
|
|
| 938 |
to="/"
|
| 939 |
className="text-white"
|
| 940 |
>
|
| 941 |
-
|
| 942 |
</Navbar.Brand>
|
| 943 |
</div>
|
| 944 |
<div className="d-flex">
|
|
@@ -1008,26 +911,11 @@
|
|
| 1008 |
}
|
| 1009 |
>
|
| 1010 |
<Icon
|
| 1011 |
-
icon="
|
| 1012 |
-
size="6"
|
| 1013 |
-
className="me-2"
|
| 1014 |
-
/>
|
| 1015 |
-
收藏
|
| 1016 |
-
</Nav.Link>
|
| 1017 |
-
<Nav.Link
|
| 1018 |
-
as={Link}
|
| 1019 |
-
className="nav-link text-dark"
|
| 1020 |
-
to="/videos"
|
| 1021 |
-
onClick={
|
| 1022 |
-
handleSidebarClose
|
| 1023 |
-
}
|
| 1024 |
-
>
|
| 1025 |
-
<Icon
|
| 1026 |
-
icon="movie"
|
| 1027 |
size="6"
|
| 1028 |
className="me-2"
|
| 1029 |
/>
|
| 1030 |
-
|
| 1031 |
</Nav.Link>
|
| 1032 |
</Nav>
|
| 1033 |
</Container>
|
|
@@ -1089,151 +977,121 @@
|
|
| 1089 |
|
| 1090 |
const Videos = () => {
|
| 1091 |
const [reload, setReload] = useState(false);
|
| 1092 |
-
const
|
| 1093 |
-
const [meta, setMeta] = useState({ filter_count: 0 })
|
| 1094 |
const [keyword, setKeyword] = useState("")
|
| 1095 |
const [search, setSearch] = useState("")
|
| 1096 |
const [videos, setVideos] = useState([])
|
| 1097 |
-
const
|
| 1098 |
-
|
| 1099 |
-
|
| 1100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1101 |
})
|
|
|
|
| 1102 |
useEffect(() => {
|
| 1103 |
-
|
| 1104 |
-
}, [pagination, reload, search]);
|
| 1105 |
useEffect(() => {
|
| 1106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1107 |
}, []);
|
| 1108 |
useEffect(() => {
|
| 1109 |
if (linksData) {
|
| 1110 |
-
|
| 1111 |
-
setVideos([...linksData.
|
| 1112 |
}
|
| 1113 |
}, [linksData]);
|
| 1114 |
|
| 1115 |
-
const handleSearchClick = () => {
|
| 1116 |
-
setSearch(keyword)
|
| 1117 |
-
onPaginationChange({ pageSize: 36, pageIndex: 1 })
|
| 1118 |
-
};
|
| 1119 |
-
|
| 1120 |
-
|
| 1121 |
-
|
| 1122 |
-
const forceUpdate = () => {
|
| 1123 |
-
setReload((pre) => !pre);
|
| 1124 |
-
};
|
| 1125 |
-
|
| 1126 |
-
return (
|
| 1127 |
-
<div>
|
| 1128 |
-
<div className="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
|
| 1129 |
-
<label className="fs-3">视频列表</label>
|
| 1130 |
-
<ButtonToolbar
|
| 1131 |
-
aria-label="视频列表"
|
| 1132 |
-
className="bg-teal rounded"
|
| 1133 |
-
>
|
| 1134 |
-
<ButtonGroup className="bg-teal">
|
| 1135 |
-
<IconButton
|
| 1136 |
-
onClick={() => {
|
| 1137 |
-
forceUpdate();
|
| 1138 |
-
}}
|
| 1139 |
-
text="刷新"
|
| 1140 |
-
className="bg-teal border-0"
|
| 1141 |
-
icon="reload"
|
| 1142 |
-
iconClassName="me-1 text-white"
|
| 1143 |
-
iconSize="6"
|
| 1144 |
-
/>
|
| 1145 |
-
</ButtonGroup>
|
| 1146 |
-
</ButtonToolbar>
|
| 1147 |
-
</div>
|
| 1148 |
-
{linksError && (
|
| 1149 |
-
<div className="text-center text-danger">
|
| 1150 |
-
发生错误,请稍后重试!!!
|
| 1151 |
-
</div>
|
| 1152 |
-
)}
|
| 1153 |
-
|
| 1154 |
-
<Container fluid className="p-2">
|
| 1155 |
-
<InputGroup className="mb-3">
|
| 1156 |
-
<Form.Control
|
| 1157 |
-
placeholder="关键词"
|
| 1158 |
-
aria-label="关键词"
|
| 1159 |
-
aria-describedby="关键词"
|
| 1160 |
-
onChange={e => setKeyword(e.target.value)}
|
| 1161 |
-
/>
|
| 1162 |
-
<Button variant="outline-secondary" id="button-addon2" onClick={() => { handleSearchClick() }}>
|
| 1163 |
-
搜索
|
| 1164 |
-
</Button>
|
| 1165 |
-
</InputGroup>
|
| 1166 |
-
|
| 1167 |
-
<Row>
|
| 1168 |
-
<Col xs={12} className="py-2">
|
| 1169 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1170 |
-
</Col>
|
| 1171 |
-
</Row>
|
| 1172 |
-
{(linksLoading) && (
|
| 1173 |
-
<Row>
|
| 1174 |
-
<Col xs={12} className="py-2">
|
| 1175 |
-
<div className="text-center text-success">
|
| 1176 |
-
正在努力加载中......
|
| 1177 |
-
</div>
|
| 1178 |
-
</Col>
|
| 1179 |
-
</Row>
|
| 1180 |
-
)}
|
| 1181 |
-
{linksData && (
|
| 1182 |
-
<Row>
|
| 1183 |
-
{videos.map((video, index) => (
|
| 1184 |
-
<Col xs={12} md={3} className="py-2">
|
| 1185 |
-
<Video video={video} />
|
| 1186 |
-
</Col>
|
| 1187 |
-
))}
|
| 1188 |
-
</Row>
|
| 1189 |
-
)}
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
|
| 1193 |
-
|
| 1194 |
-
<Row>
|
| 1195 |
-
<Col xs={12} className="py-2">
|
| 1196 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1197 |
-
</Col>
|
| 1198 |
-
</Row>
|
| 1199 |
-
</Container>
|
| 1200 |
-
</div>
|
| 1201 |
-
);
|
| 1202 |
-
};
|
| 1203 |
-
|
| 1204 |
-
|
| 1205 |
-
const Favorites = () => {
|
| 1206 |
-
const [reload, setReload] = useState(false);
|
| 1207 |
-
const { limit, onPaginationChange, skip, pagination } = usePagination();
|
| 1208 |
-
const [meta, setMeta] = useState({ filter_count: 0 })
|
| 1209 |
-
const [keyword, setKeyword] = useState("")
|
| 1210 |
-
const [search, setSearch] = useState("")
|
| 1211 |
-
const [videos, setVideos] = useState([])
|
| 1212 |
-
const { data: linksData, refetch: linksRefetch, isLoading: linksLoading, error: linksError } = useQuery({
|
| 1213 |
-
queryKey: ['get_paginate_favorites', limit, pagination.pageIndex, search],
|
| 1214 |
-
queryFn: () => paginateFavoritesGet(limit, pagination.pageIndex, search),
|
| 1215 |
-
enabled: false,
|
| 1216 |
-
})
|
| 1217 |
useEffect(() => {
|
| 1218 |
-
|
| 1219 |
-
|
| 1220 |
-
|
| 1221 |
-
|
| 1222 |
-
}, []);
|
| 1223 |
-
useEffect(() => {
|
| 1224 |
-
if (linksData) {
|
| 1225 |
-
setMeta({ filter_count: linksData.total })
|
| 1226 |
-
setVideos([...linksData.items])
|
| 1227 |
-
}
|
| 1228 |
-
}, [linksData]);
|
| 1229 |
|
| 1230 |
const handleSearchClick = () => {
|
| 1231 |
setSearch(keyword)
|
| 1232 |
-
onPaginationChange({ pageSize: 36, pageIndex: 1 })
|
| 1233 |
};
|
| 1234 |
|
| 1235 |
|
| 1236 |
-
|
| 1237 |
const forceUpdate = () => {
|
| 1238 |
setReload((pre) => !pre);
|
| 1239 |
};
|
|
@@ -1241,9 +1099,9 @@
|
|
| 1241 |
return (
|
| 1242 |
<div>
|
| 1243 |
<div className="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
|
| 1244 |
-
<label className="fs-3"
|
| 1245 |
<ButtonToolbar
|
| 1246 |
-
aria-label="
|
| 1247 |
className="bg-teal rounded"
|
| 1248 |
>
|
| 1249 |
<ButtonGroup className="bg-teal">
|
|
@@ -1279,108 +1137,6 @@
|
|
| 1279 |
</Button>
|
| 1280 |
</InputGroup>
|
| 1281 |
|
| 1282 |
-
<Row>
|
| 1283 |
-
<Col xs={12} className="py-2">
|
| 1284 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1285 |
-
</Col>
|
| 1286 |
-
</Row>
|
| 1287 |
-
{(linksLoading) && (
|
| 1288 |
-
<Row>
|
| 1289 |
-
<Col xs={12} className="py-2">
|
| 1290 |
-
<div className="text-center text-success">
|
| 1291 |
-
正在努力加载中......
|
| 1292 |
-
</div>
|
| 1293 |
-
</Col>
|
| 1294 |
-
</Row>
|
| 1295 |
-
)}
|
| 1296 |
-
{linksData && (
|
| 1297 |
-
<Row>
|
| 1298 |
-
{videos.map((video, index) => (
|
| 1299 |
-
<Col xs={12} md={3} className="py-2">
|
| 1300 |
-
<Video video={video} />
|
| 1301 |
-
</Col>
|
| 1302 |
-
))}
|
| 1303 |
-
</Row>
|
| 1304 |
-
)}
|
| 1305 |
-
|
| 1306 |
-
|
| 1307 |
-
|
| 1308 |
-
|
| 1309 |
-
<Row>
|
| 1310 |
-
<Col xs={12} className="py-2">
|
| 1311 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1312 |
-
</Col>
|
| 1313 |
-
</Row>
|
| 1314 |
-
</Container>
|
| 1315 |
-
</div>
|
| 1316 |
-
);
|
| 1317 |
-
};
|
| 1318 |
-
|
| 1319 |
-
|
| 1320 |
-
const Tags = () => {
|
| 1321 |
-
const { tag } = useParams()
|
| 1322 |
-
const [reload, setReload] = useState(false);
|
| 1323 |
-
const { limit, onPaginationChange, skip, pagination } = usePagination();
|
| 1324 |
-
const [meta, setMeta] = useState({ filter_count: 0 })
|
| 1325 |
-
const [keyword, setKeyword] = useState("")
|
| 1326 |
-
const [videos, setVideos] = useState([])
|
| 1327 |
-
const { data: linksData, refetch: linksRefetch, isLoading: linksLoading, error: linksError } = useQuery({
|
| 1328 |
-
queryKey: ['get_tag_links', limit, pagination.pageIndex],
|
| 1329 |
-
queryFn: () => paginateTagLinksGet(limit, pagination.pageIndex, tag),
|
| 1330 |
-
enabled: false,
|
| 1331 |
-
})
|
| 1332 |
-
useEffect(() => {
|
| 1333 |
-
linksRefetch()
|
| 1334 |
-
}, [pagination, reload]);
|
| 1335 |
-
useEffect(() => {
|
| 1336 |
-
linksRefetch()
|
| 1337 |
-
}, []);
|
| 1338 |
-
useEffect(() => {
|
| 1339 |
-
if (linksData) {
|
| 1340 |
-
setMeta({ filter_count: linksData.total })
|
| 1341 |
-
setVideos([...linksData.items])
|
| 1342 |
-
}
|
| 1343 |
-
}, [linksData]);
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
const forceUpdate = () => {
|
| 1347 |
-
setReload((pre) => !pre);
|
| 1348 |
-
};
|
| 1349 |
-
|
| 1350 |
-
return (
|
| 1351 |
-
<div>
|
| 1352 |
-
<div className="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
|
| 1353 |
-
<label className="fs-3">视频列表</label>
|
| 1354 |
-
<ButtonToolbar
|
| 1355 |
-
aria-label="视频列表"
|
| 1356 |
-
className="bg-teal rounded"
|
| 1357 |
-
>
|
| 1358 |
-
<ButtonGroup className="bg-teal">
|
| 1359 |
-
<IconButton
|
| 1360 |
-
onClick={() => {
|
| 1361 |
-
forceUpdate();
|
| 1362 |
-
}}
|
| 1363 |
-
text="刷新"
|
| 1364 |
-
className="bg-teal border-0"
|
| 1365 |
-
icon="reload"
|
| 1366 |
-
iconClassName="me-1 text-white"
|
| 1367 |
-
iconSize="6"
|
| 1368 |
-
/>
|
| 1369 |
-
</ButtonGroup>
|
| 1370 |
-
</ButtonToolbar>
|
| 1371 |
-
</div>
|
| 1372 |
-
{linksError && (
|
| 1373 |
-
<div className="text-center text-danger">
|
| 1374 |
-
发生错误,请稍后重试!!!
|
| 1375 |
-
</div>
|
| 1376 |
-
)}
|
| 1377 |
-
|
| 1378 |
-
<Container fluid className="p-2">
|
| 1379 |
-
<Row>
|
| 1380 |
-
<Col xs={12} className="py-2">
|
| 1381 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1382 |
-
</Col>
|
| 1383 |
-
</Row>
|
| 1384 |
{(linksLoading) && (
|
| 1385 |
<Row>
|
| 1386 |
<Col xs={12} className="py-2">
|
|
@@ -1392,25 +1148,17 @@
|
|
| 1392 |
)}
|
| 1393 |
{linksData && (
|
| 1394 |
<Row>
|
| 1395 |
-
{videos
|
| 1396 |
-
<Col xs={12} md={3} className="py-2">
|
| 1397 |
-
<Video video={video} />
|
| 1398 |
-
</Col>
|
| 1399 |
-
))}
|
| 1400 |
</Row>
|
| 1401 |
)}
|
| 1402 |
|
| 1403 |
-
<Row>
|
| 1404 |
-
<Col xs={12} className="py-2">
|
| 1405 |
-
<Paginate page={pagination.pageIndex} onClick={(i) => { onPaginationChange({ pageSize: 36, pageIndex: i }) }} itemsPerPage="36" totalCount={meta.filter_count} />
|
| 1406 |
-
</Col>
|
| 1407 |
-
</Row>
|
| 1408 |
</Container>
|
| 1409 |
</div>
|
| 1410 |
);
|
| 1411 |
};
|
| 1412 |
|
| 1413 |
|
|
|
|
| 1414 |
const Tasks = () => {
|
| 1415 |
const [show, setShow] = useState(false);
|
| 1416 |
const handleClose = () => setShow(false);
|
|
@@ -1656,12 +1404,16 @@
|
|
| 1656 |
layer.msg('任务添加失败', { time: 2000, icon: 5 });
|
| 1657 |
}
|
| 1658 |
})
|
| 1659 |
-
|
| 1660 |
-
|
| 1661 |
-
|
| 1662 |
const addDowload = (fileinfo) => {
|
| 1663 |
-
const file = fileinfo.data
|
| 1664 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1665 |
setAddDownloadObject(download)
|
| 1666 |
}
|
| 1667 |
useEffect(() => {
|
|
@@ -1772,14 +1524,14 @@
|
|
| 1772 |
mutationKey: ["get-download"],
|
| 1773 |
mutationFn: async (fileinfo) => {
|
| 1774 |
showLoading();
|
| 1775 |
-
var host = setting.
|
| 1776 |
if (!host.endsWith("/")) {
|
| 1777 |
host = host + '/'
|
| 1778 |
}
|
| 1779 |
var url = host + 'api/fs/get';
|
| 1780 |
return await axios.post(url, fileinfo, {
|
| 1781 |
headers: {
|
| 1782 |
-
'Authorization': setting.
|
| 1783 |
'Content-Type': 'application/json'
|
| 1784 |
},
|
| 1785 |
})
|
|
@@ -1832,8 +1584,8 @@
|
|
| 1832 |
},
|
| 1833 |
];
|
| 1834 |
useEffect(() => {
|
| 1835 |
-
if (!setting.
|
| 1836 |
-
layer.alert("
|
| 1837 |
return
|
| 1838 |
}
|
| 1839 |
fetchDataByPage(setting, query);
|
|
@@ -1894,9 +1646,8 @@
|
|
| 1894 |
<Route path="/:path?">
|
| 1895 |
<Layout>
|
| 1896 |
<Switch>
|
| 1897 |
-
<Route path="/
|
| 1898 |
-
<Route path="/
|
| 1899 |
-
<Route path="/" exact component={Favorites} />
|
| 1900 |
</Switch>
|
| 1901 |
</Layout>
|
| 1902 |
</Route>
|
|
|
|
| 562 |
return <img {...props} src="https://placehold.co/600x400?text=Loading" />;
|
| 563 |
};
|
| 564 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 565 |
//设置框
|
| 566 |
const SettingModal = (props) => {
|
| 567 |
const settings = [
|
| 568 |
+
{ "thunderx": [{ "label": "登陆令牌", "key": "secret_token", "show": false },{ "label": "代理地址", "key": "cf_proxy", "show": true }] },
|
| 569 |
{ "github": [{ "label": "Actions地址", "key": "github_host", "show": true }, { "label": "Github令牌", "key": "github_token", "show": false }] },
|
| 570 |
{ "directus": [{ "label": "Directus地址", "key": "directus_host", "show": true }, { "label": "Directus令牌", "key": "directus_token", "show": false }] }
|
| 571 |
]
|
| 572 |
+
// const settings = [
|
| 573 |
+
// { "thunderx": [{ "label": "代理地址", "key": "cf_proxy", "show": true }, { "label": "登陆令牌", "key": "secret_token", "show": false }] },
|
| 574 |
+
// { "github": [{ "label": "Actions地址", "key": "github_host", "show": true }, { "label": "Github令牌", "key": "github_token", "show": false }] },
|
| 575 |
+
// { "directus": [{ "label": "Directus地址", "key": "directus_host", "show": true }, { "label": "Directus令牌", "key": "directus_token", "show": false }] }
|
| 576 |
+
// ]
|
| 577 |
const [setting, setSetting] = useState({});
|
| 578 |
// useEffect(() => {
|
| 579 |
// localStorage.setItem('settings', JSON.stringify(setting));
|
|
|
|
| 747 |
const [response, error, loading, fetchData] = useAxios();
|
| 748 |
|
| 749 |
const fetchDataByPage = async (setting, query) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 750 |
fetchData({
|
| 751 |
+
url: '/files',
|
| 752 |
method: "POST",
|
| 753 |
data: query,
|
| 754 |
headers: {
|
| 755 |
+
'Authorization': setting.secret_token,
|
| 756 |
'Content-Type': 'application/json'
|
| 757 |
},
|
| 758 |
});
|
|
|
|
| 760 |
return [response, error, loading, fetchDataByPage];
|
| 761 |
};
|
| 762 |
|
| 763 |
+
const paginateLinksGet = async (page_token, keyword) => {
|
| 764 |
+
//const url = `/files?size=${limit}&page=${page}&kw=${keyword}`;
|
| 765 |
+
console.log("======fuck========");
|
| 766 |
+
const url = `/files`;
|
| 767 |
+
|
| 768 |
+
const { data } = await axios.post(url,
|
| 769 |
+
{
|
| 770 |
+
"size": 100,
|
| 771 |
+
"parent_id": "",
|
| 772 |
+
"next_page_token": page_token,
|
| 773 |
+
"additional_filters": {},
|
| 774 |
+
"additionalProp1": {}
|
| 775 |
+
},
|
| 776 |
+
{
|
| 777 |
+
headers: {
|
| 778 |
+
'Authorization': setting.secret_token,
|
| 779 |
+
'Content-Type': 'application/json'
|
| 780 |
+
},
|
| 781 |
+
})
|
| 782 |
return data
|
| 783 |
}
|
| 784 |
|
|
|
|
| 841 |
to="/"
|
| 842 |
className="text-white"
|
| 843 |
>
|
| 844 |
+
文件列表
|
| 845 |
</Navbar.Brand>
|
| 846 |
</div>
|
| 847 |
<div className="d-flex">
|
|
|
|
| 911 |
}
|
| 912 |
>
|
| 913 |
<Icon
|
| 914 |
+
icon="file"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 915 |
size="6"
|
| 916 |
className="me-2"
|
| 917 |
/>
|
| 918 |
+
文件列表
|
| 919 |
</Nav.Link>
|
| 920 |
</Nav>
|
| 921 |
</Container>
|
|
|
|
| 977 |
|
| 978 |
const Videos = () => {
|
| 979 |
const [reload, setReload] = useState(false);
|
| 980 |
+
const [pageToken,setPageToken] = useState('');
|
|
|
|
| 981 |
const [keyword, setKeyword] = useState("")
|
| 982 |
const [search, setSearch] = useState("")
|
| 983 |
const [videos, setVideos] = useState([])
|
| 984 |
+
const setting = STORE.getState().settings;
|
| 985 |
+
const { id } = useParams();
|
| 986 |
+
const columns = [
|
| 987 |
+
{ title: "文件名称", dataIndex: "name" },
|
| 988 |
+
{ title: "大小", dataIndex: "size", render: (row) => (bytesToSize(Number(row.size))) },
|
| 989 |
+
{ title: "日期", dataIndex: "created_time", render: (row) => (formatDate(row.created_time)) },
|
| 990 |
+
{
|
| 991 |
+
title: "操作",
|
| 992 |
+
dataIndex: "name",
|
| 993 |
+
render: (row) => (
|
| 994 |
+
row.kind=="drive#folder" ? <Nav.Link
|
| 995 |
+
as={Link}
|
| 996 |
+
className="nav-link text-dark"
|
| 997 |
+
to={`/videos/${row.id}`}
|
| 998 |
+
target="_blank"
|
| 999 |
+
>
|
| 1000 |
+
<Icon
|
| 1001 |
+
icon="open-in-new"
|
| 1002 |
+
size="6"
|
| 1003 |
+
className="me-2"
|
| 1004 |
+
/>
|
| 1005 |
+
</Nav.Link> :
|
| 1006 |
+
<Icon
|
| 1007 |
+
icon="download-outline"
|
| 1008 |
+
size="6"
|
| 1009 |
+
className="me-2"
|
| 1010 |
+
onClick={async () => {
|
| 1011 |
+
let data = { "id": row.id }
|
| 1012 |
+
await downloadMutation(data);
|
| 1013 |
+
}}
|
| 1014 |
+
/>
|
| 1015 |
+
),
|
| 1016 |
+
},
|
| 1017 |
+
];
|
| 1018 |
+
const authorization = 'Bearer '+setting.secret_token;
|
| 1019 |
+
const { data: fileData, mutateAsync: downloadMutation } = useMutation({
|
| 1020 |
+
mutationKey: ["get-download"],
|
| 1021 |
+
mutationFn: async (fileinfo) => {
|
| 1022 |
+
showLoading();
|
| 1023 |
+
var url = '/files/'+fileinfo.id;
|
| 1024 |
+
return await axios.get(url, {
|
| 1025 |
+
headers: {
|
| 1026 |
+
'Authorization': authorization,
|
| 1027 |
+
'Content-Type': 'application/json'
|
| 1028 |
+
},
|
| 1029 |
+
})
|
| 1030 |
+
},
|
| 1031 |
+
onSuccess: async (data, variables, context) => {
|
| 1032 |
+
hideLoading();
|
| 1033 |
+
},
|
| 1034 |
+
onError: () => {
|
| 1035 |
+
hideLoading();
|
| 1036 |
+
}
|
| 1037 |
+
})
|
| 1038 |
+
const { data: linksData, mutateAsync: filesMutation,error:linksError,isPending:linksLoading } = useMutation({
|
| 1039 |
+
mutationKey: ["get-files",pageToken],
|
| 1040 |
+
mutationFn: async (query) => {
|
| 1041 |
+
showLoading();
|
| 1042 |
+
var url = '/files';
|
| 1043 |
+
return await axios.post(url, query, {
|
| 1044 |
+
headers: {
|
| 1045 |
+
'Authorization': authorization,
|
| 1046 |
+
'Content-Type': 'application/json'
|
| 1047 |
+
},
|
| 1048 |
+
})
|
| 1049 |
+
},
|
| 1050 |
+
onSuccess: async (data, variables, context) => {
|
| 1051 |
+
hideLoading();
|
| 1052 |
+
},
|
| 1053 |
+
onError: () => {
|
| 1054 |
+
hideLoading();
|
| 1055 |
+
}
|
| 1056 |
})
|
| 1057 |
+
|
| 1058 |
useEffect(() => {
|
| 1059 |
+
}, [pageToken, reload, search]);
|
|
|
|
| 1060 |
useEffect(() => {
|
| 1061 |
+
if (!setting.secret_token || setting.secret_token.length < 5) {
|
| 1062 |
+
layer.alert("请先正确配置登陆令牌,最少5位", { icon: 5 });
|
| 1063 |
+
return
|
| 1064 |
+
}
|
| 1065 |
+
|
| 1066 |
+
let data = {
|
| 1067 |
+
"size": 100,
|
| 1068 |
+
"parent_id": id,
|
| 1069 |
+
"next_page_token": pageToken,
|
| 1070 |
+
"additional_filters": {},
|
| 1071 |
+
"additionalProp1": {}
|
| 1072 |
+
}
|
| 1073 |
+
|
| 1074 |
+
filesMutation(data);
|
| 1075 |
}, []);
|
| 1076 |
useEffect(() => {
|
| 1077 |
if (linksData) {
|
| 1078 |
+
setPageToken(linksData.data.next_page_token)
|
| 1079 |
+
setVideos([...linksData.data.files])
|
| 1080 |
}
|
| 1081 |
}, [linksData]);
|
| 1082 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1083 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1084 |
useEffect(() => {
|
| 1085 |
+
if (fileData) {
|
| 1086 |
+
emitEvent("addDownload", fileData)
|
| 1087 |
+
}
|
| 1088 |
+
}, [fileData]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1089 |
|
| 1090 |
const handleSearchClick = () => {
|
| 1091 |
setSearch(keyword)
|
|
|
|
| 1092 |
};
|
| 1093 |
|
| 1094 |
|
|
|
|
| 1095 |
const forceUpdate = () => {
|
| 1096 |
setReload((pre) => !pre);
|
| 1097 |
};
|
|
|
|
| 1099 |
return (
|
| 1100 |
<div>
|
| 1101 |
<div className="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
|
| 1102 |
+
<label className="fs-3">文件列表</label>
|
| 1103 |
<ButtonToolbar
|
| 1104 |
+
aria-label="文件列表"
|
| 1105 |
className="bg-teal rounded"
|
| 1106 |
>
|
| 1107 |
<ButtonGroup className="bg-teal">
|
|
|
|
| 1137 |
</Button>
|
| 1138 |
</InputGroup>
|
| 1139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1140 |
{(linksLoading) && (
|
| 1141 |
<Row>
|
| 1142 |
<Col xs={12} className="py-2">
|
|
|
|
| 1148 |
)}
|
| 1149 |
{linksData && (
|
| 1150 |
<Row>
|
| 1151 |
+
<DataTable data={videos ? videos : []} columns={columns} />
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1152 |
</Row>
|
| 1153 |
)}
|
| 1154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1155 |
</Container>
|
| 1156 |
</div>
|
| 1157 |
);
|
| 1158 |
};
|
| 1159 |
|
| 1160 |
|
| 1161 |
+
|
| 1162 |
const Tasks = () => {
|
| 1163 |
const [show, setShow] = useState(false);
|
| 1164 |
const handleClose = () => setShow(false);
|
|
|
|
| 1404 |
layer.msg('任务添加失败', { time: 2000, icon: 5 });
|
| 1405 |
}
|
| 1406 |
})
|
|
|
|
|
|
|
|
|
|
| 1407 |
const addDowload = (fileinfo) => {
|
| 1408 |
+
const file = fileinfo.data;
|
| 1409 |
+
var url = file.web_content_link;
|
| 1410 |
+
for (const obj of file.medias) {
|
| 1411 |
+
if (obj.link.url.trim().length>10) {
|
| 1412 |
+
url = obj.link.url;
|
| 1413 |
+
break;
|
| 1414 |
+
}
|
| 1415 |
+
}
|
| 1416 |
+
const download = { name: file.name, size: Number(file.size),url:url, created: file.created_time }
|
| 1417 |
setAddDownloadObject(download)
|
| 1418 |
}
|
| 1419 |
useEffect(() => {
|
|
|
|
| 1524 |
mutationKey: ["get-download"],
|
| 1525 |
mutationFn: async (fileinfo) => {
|
| 1526 |
showLoading();
|
| 1527 |
+
var host = setting.cf_proxy;
|
| 1528 |
if (!host.endsWith("/")) {
|
| 1529 |
host = host + '/'
|
| 1530 |
}
|
| 1531 |
var url = host + 'api/fs/get';
|
| 1532 |
return await axios.post(url, fileinfo, {
|
| 1533 |
headers: {
|
| 1534 |
+
'Authorization': setting.secret_token,
|
| 1535 |
'Content-Type': 'application/json'
|
| 1536 |
},
|
| 1537 |
})
|
|
|
|
| 1584 |
},
|
| 1585 |
];
|
| 1586 |
useEffect(() => {
|
| 1587 |
+
if (!setting.secret_token || setting.secret_token.length < 5) {
|
| 1588 |
+
layer.alert("请先正确配置登陆令牌", { icon: 5 });
|
| 1589 |
return
|
| 1590 |
}
|
| 1591 |
fetchDataByPage(setting, query);
|
|
|
|
| 1646 |
<Route path="/:path?">
|
| 1647 |
<Layout>
|
| 1648 |
<Switch>
|
| 1649 |
+
<Route path="/" exact component={Videos} />
|
| 1650 |
+
<Route path="/videos/:id?" exact component={Videos} />
|
|
|
|
| 1651 |
</Switch>
|
| 1652 |
</Layout>
|
| 1653 |
</Route>
|