1. 加工费模块重构
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled

2. 快递费模块重构
3. 订单导出功能优化
4. 商品订单的折扣功能
5. 修复了一些已知BUG
This commit is contained in:
李琦
2026-06-24 08:11:15 +08:00
parent 824dc2b0e3
commit e6306eea75
8 changed files with 279 additions and 532 deletions

View File

@@ -0,0 +1,133 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
import Player from 'xgplayer';
import 'xgplayer/dist/index.min.css';
interface Props {
src: string;
autoplay?: boolean;
controls?: boolean;
thumbnail?: boolean;
width?: number | string;
height?: number | string;
poster?: string;
}
const props = withDefaults(defineProps<Props>(), {
autoplay: false,
controls: true,
thumbnail: false,
width: '100%',
height: '100%',
poster: undefined,
});
const emit = defineEmits<{
ready: [player: Player];
error: [error: any];
ended: [];
}>();
const containerRef = ref<HTMLDivElement>();
const player = shallowRef<Player | null>(null);
function createPlayer() {
if (!containerRef.value || !props.src) return;
player.value?.destroy();
player.value = null;
const ignores = props.thumbnail
? [
'cssfullscreen',
'screenshot',
'pip',
'miniscreen',
'keyboard',
'download',
'playbackrate',
'time',
'definition',
'fullscreen',
'loading',
'mobile',
'pc',
'play',
'poster',
'progress',
'replay',
'start',
'volume',
]
: [];
const p = new Player({
el: containerRef.value,
url: props.src,
autoplay: props.autoplay,
controls: props.thumbnail ? false : props.controls,
closeVideoClick: props.thumbnail,
closeVideoDblclick: props.thumbnail,
ignores,
fluid: true,
fitVideoSize: 'fixWidth',
videoInit: true,
poster: props.poster,
playsinline: true,
enableContextmenu: !props.thumbnail,
});
p.on('ready', () => {
emit('ready', p);
});
p.on('error', (e: any) => {
emit('error', e);
});
p.on('ended', () => {
emit('ended');
});
player.value = p;
}
onMounted(() => {
createPlayer();
});
onBeforeUnmount(() => {
player.value?.destroy();
player.value = null;
});
watch(
() => props.src,
() => {
createPlayer();
},
);
defineExpose({
getPlayer: () => player.value,
play: () => player.value?.play(),
pause: () => player.value?.pause(),
destroy: () => {
player.value?.destroy();
player.value = null;
},
});
</script>
<template>
<div ref="containerRef" class="xg-video-player"></div>
</template>
<style scoped>
.xg-video-player {
width: v-bind(width);
height: v-bind(height);
}
</style>

View File

@@ -0,0 +1 @@
export { default as XgVideoPlayer } from './XgVideoPlayer.vue';

View File

@@ -11,11 +11,11 @@
alt="预览"
class="w-full h-full object-cover"
/>
<video
<XgVideoPlayer
v-else-if="uploadPreview.type === 'video'"
:src="uploadPreview.url"
class="w-full h-full object-cover"
preload="metadata"
thumbnail
/>
<FileOutlined v-else class="text-2xl text-gray-400"/>
</div>
@@ -61,6 +61,7 @@
<script setup>
import {inject} from 'vue';
import {FileOutlined, SendOutlined, CloseOutlined} from '@ant-design/icons-vue';
import { XgVideoPlayer } from '#/components/video-player';
const uploadPreview = inject('uploadPreview');
const sendFile = inject('sendFile');

View File

@@ -1,27 +1,15 @@
<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { computed, onMounted, onUnmounted } from 'vue';
import { Image } from 'ant-design-vue';
import { XgVideoPlayer } from '#/components/video-player';
import { useMediaPreview } from '../composables/useMediaPreview.ts';
// import VueEasyLightbox from 'vue-easy-lightbox';
import { useThemeStore } from '../stores/theme.ts';
const themeStore = useThemeStore();
const { visible, mediaData, hidePreview, previewType } = useMediaPreview();
// 视频相关状态
const videoPlayer = ref(null);
const isPlaying = ref(false);
const isMuted = ref(false);
const volume = ref(1);
const currentTime = ref(0);
const duration = ref(0);
const showControls = ref(true);
const isPortrait = ref(false);
const controlsTimeout = ref(null);
// 计算属性
const showImagePreview = computed(
() => visible.value && previewType.value === 'image',
);
@@ -29,341 +17,47 @@ const showVideoPreview = computed(
() => visible.value && previewType.value === 'video',
);
const progressPercent = computed(() => {
if (duration.value === 0) return 0;
return (currentTime.value / duration.value) * 100;
});
// 视频加载完成
const handleVideoLoad = () => {
if (videoPlayer.value) {
duration.value = videoPlayer.value.duration;
// 检测视频方向
const video = videoPlayer.value;
isPortrait.value = video.videoHeight > video.videoWidth;
// 监听时间更新
video.addEventListener('timeupdate', updateTime);
}
};
// 图片加载完成
const handleImageLoad = () => {
// 可以在这里添加图片加载完成的逻辑
};
// 更新播放时间
const updateTime = () => {
if (videoPlayer.value) {
currentTime.value = videoPlayer.value.currentTime;
}
};
// 视频播放/暂停事件
const handleVideoPlay = () => {
isPlaying.value = true;
hideControlsAfterDelay();
};
const handleVideoPause = () => {
isPlaying.value = false;
showControls.value = true;
clearTimeout(controlsTimeout.value);
};
// 控制功能
const togglePlay = () => {
if (videoPlayer.value) {
if (isPlaying.value) {
videoPlayer.value.pause();
} else {
videoPlayer.value.play();
}
}
};
const toggleMute = () => {
if (videoPlayer.value) {
videoPlayer.value.muted = !videoPlayer.value.muted;
isMuted.value = videoPlayer.value.muted;
}
};
const updateVolume = () => {
if (videoPlayer.value) {
videoPlayer.value.volume = volume.value;
isMuted.value = volume.value === 0;
}
};
const seekTo = (event) => {
if (videoPlayer.value) {
const rect = event.target.getBoundingClientRect();
const percent = (event.clientX - rect.left) / rect.width;
videoPlayer.value.currentTime = percent * duration.value;
}
};
const toggleFullscreen = () => {
if (videoPlayer.value) {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
videoPlayer.value.requestFullscreen();
}
}
};
const togglePictureInPicture = async () => {
if (videoPlayer.value) {
try {
await (document.pictureInPictureElement
? document.exitPictureInPicture()
: videoPlayer.value.requestPictureInPicture());
} catch (error) {
console.error('画中画功能不支持:', error);
}
}
};
// 隐藏控制栏
const hideControlsAfterDelay = () => {
clearTimeout(controlsTimeout.value);
controlsTimeout.value = setTimeout(() => {
if (isPlaying.value) {
showControls.value = false;
}
}, 3000);
};
// 显示控制栏
const showControlsTemporarily = () => {
showControls.value = true;
if (isPlaying.value) {
hideControlsAfterDelay();
}
};
// 格式化时间
const formatDuration = (seconds) => {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
};
// 下载媒体
const downloadMedia = () => {
if (mediaData.value?.url) {
const link = document.createElement('a');
link.href = mediaData.value.url;
link.download = `media_${Date.now()}`;
link.click();
}
};
// 分享媒体
const shareMedia = async () => {
if (navigator.share && mediaData.value?.url) {
try {
await navigator.share({
title: '分享媒体',
url: mediaData.value.url,
});
} catch {
console.log('分享取消或失败');
}
} else {
// 复制链接到剪贴板
navigator.clipboard.writeText(mediaData.value?.url || '');
alert('链接已复制到剪贴板');
}
};
// 键盘事件处理
const handleKeydown = (event) => {
if (!visible.value) return;
switch (event.code) {
case 'ArrowLeft': {
if (showVideoPreview.value && videoPlayer.value) {
event.preventDefault();
videoPlayer.value.currentTime -= 10;
}
break;
}
case 'ArrowRight': {
if (showVideoPreview.value && videoPlayer.value) {
event.preventDefault();
videoPlayer.value.currentTime += 10;
}
break;
}
case 'Escape': {
if (event.code === 'Escape') {
hidePreview();
break;
}
case 'Space': {
if (showVideoPreview.value) {
event.preventDefault();
togglePlay();
}
break;
}
}
};
// 监听媒体数据变化
watch(mediaData, () => {
if (previewType.value === 'video') {
isPlaying.value = false;
currentTime.value = 0;
duration.value = 0;
showControls.value = true;
}
});
onMounted(() => {
document.addEventListener('keydown', handleKeydown);
});
onUnmounted(() => {
document.removeEventListener('keydown', handleKeydown);
clearTimeout(controlsTimeout.value);
});
</script>
<template>
<!-- 图片预览组件 -->
<!-- <div
v-if="showImagePreview"
class="media-preview-overlay"
:class="{ 'dark': themeStore.isDarkMode }"
@click.self="hidePreview"
>
<div class="preview-container">
<button class="preview-close-btn" @click="hidePreview">
<i class="fas fa-times"></i>
</button>
<div class="image-preview-content">
<img
:src="mediaData"
:alt="'图片预览'"
class="preview-image"
@load="handleImageLoad"
/>
</div>
<div class="preview-actions">
<button class="action-btn" @click="downloadMedia" title="下载">
<i class="fas fa-download"></i>
</button>
<button class="action-btn" @click="shareMedia" title="分享">
<i class="fas fa-share"></i>
</button>
</div>
</div>
</div>-->
<Image
:imgs="[{ src: mediaData }]"
:visible="showImagePreview"
@hide="hidePreview"
/>
<!-- 视频预览组件 -->
<div
v-if="showVideoPreview"
:class="{ dark: themeStore.isDarkMode }"
class="media-preview-overlay video-preview"
class="media-preview-overlay"
@click.self="hidePreview"
>
<div :class="{ portrait: isPortrait }" class="video-preview-container">
<div class="video-preview-container">
<button class="preview-close-btn" @click="hidePreview">
<i class="fas fa-times"></i>
</button>
<div class="video-content">
<video
ref="videoPlayer"
<XgVideoPlayer
:src="mediaData"
autoplay
class="preview-video"
controls
@loadedmetadata="handleVideoLoad"
@pause="handleVideoPause"
@play="handleVideoPlay"
></video>
<!-- 自定义视频控制栏 -->
<div v-if="showControls" class="video-controls">
<div class="controls-top">
<div class="video-title">视频预览</div>
<div class="video-info">
{{ formatDuration(currentTime) }} / {{ formatDuration(duration) }}
</div>
</div>
<div class="controls-bottom">
<button class="control-btn" @click="togglePlay">
<i :class="isPlaying ? 'fa-pause' : 'fa-play'" class="fas"></i>
</button>
<div class="progress-container">
<div class="progress-bar" @click="seekTo">
<div
:style="{ width: `${progressPercent}%` }"
class="progress-fill"
></div>
<div
:style="{ left: `${progressPercent}%` }"
class="progress-thumb"
></div>
</div>
</div>
<button class="control-btn" @click="toggleMute">
<i
:class="isMuted ? 'fa-volume-mute' : 'fa-volume-up'"
class="fas"
></i>
</button>
<div class="volume-container">
<input
v-model="volume"
class="volume-slider"
max="1"
min="0"
step="0.1"
type="range"
@input="updateVolume"
autoplay
/>
</div>
<button class="control-btn" @click="toggleFullscreen">
<i class="fas fa-expand"></i>
</button>
</div>
</div>
</div>
<div class="video-actions">
<button class="action-btn" title="下载" @click="downloadMedia">
<i class="fas fa-download"></i>
</button>
<button class="action-btn" title="分享" @click="shareMedia">
<i class="fas fa-share"></i>
</button>
<button
class="action-btn"
title="画中画"
@click="togglePictureInPicture"
>
<i class="fas fa-external-link-alt"></i>
</button>
</div>
</div>
</div>
</template>
@@ -396,15 +90,6 @@ onUnmounted(() => {
}
}
.preview-container {
position: relative;
max-width: 90vw;
max-height: 90vh;
display: flex;
flex-direction: column;
align-items: center;
}
.video-preview-container {
position: relative;
max-width: 90vw;
@@ -417,10 +102,6 @@ onUnmounted(() => {
overflow: hidden;
}
.video-preview-container.portrait {
max-width: 60vw;
}
.preview-close-btn {
position: absolute;
top: -50px;
@@ -445,178 +126,17 @@ onUnmounted(() => {
transform: scale(1.1);
}
.image-preview-content {
position: relative;
}
.preview-image {
max-width: 100%;
max-height: 80vh;
border-radius: 8px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.video-content {
position: relative;
width: 100%;
height: 100%;
}
.preview-video {
width: 100%;
height: 100%;
max-height: 80vh;
object-fit: contain;
width: 90vw;
max-height: 85vh;
}
.video-controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
color: white;
padding: 20px;
transition: all 0.3s ease;
}
.controls-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.video-title {
font-size: 16px;
font-weight: 600;
}
.video-info {
font-size: 14px;
opacity: 0.8;
}
.controls-bottom {
display: flex;
align-items: center;
gap: 16px;
}
.control-btn {
width: 40px;
height: 40px;
background: rgba(255, 255, 255, 0.2);
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: all 0.3s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1);
}
.progress-container {
flex: 1;
margin: 0 16px;
}
.progress-bar {
position: relative;
height: 6px;
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
cursor: pointer;
}
.progress-fill {
height: 100%;
background: #4361ee;
border-radius: 3px;
transition: width 0.1s ease;
}
.progress-thumb {
position: absolute;
top: -4px;
width: 14px;
height: 14px;
background: #4361ee;
border-radius: 50%;
transform: translateX(-50%);
transition: left 0.1s ease;
}
.volume-container {
width: 80px;
}
.volume-slider {
width: 100%;
height: 4px;
background: rgba(255, 255, 255, 0.3);
border-radius: 2px;
outline: none;
cursor: pointer;
}
.volume-slider::-webkit-slider-thumb {
appearance: none;
width: 12px;
height: 12px;
background: #4361ee;
border-radius: 50%;
cursor: pointer;
}
.preview-actions,
.video-actions {
position: absolute;
top: 20px;
right: 60px;
display: flex;
gap: 12px;
}
.action-btn {
width: 40px;
height: 40px;
background: rgba(255, 255, 255, 0.2);
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: all 0.3s ease;
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1);
}
/* 响应式设计 */
@media (max-width: 768px) {
.preview-container,
.video-preview-container {
max-width: 95vw;
max-height: 95vh;
}
.video-preview-container.portrait {
max-width: 95vw;
}
.preview-close-btn {
top: -40px;
width: 36px;
@@ -624,35 +144,9 @@ onUnmounted(() => {
font-size: 16px;
}
.video-controls {
padding: 16px;
}
.controls-bottom {
gap: 12px;
}
.control-btn {
width: 36px;
height: 36px;
font-size: 14px;
}
.volume-container {
width: 60px;
}
.preview-actions,
.video-actions {
top: 16px;
right: 50px;
gap: 8px;
}
.action-btn {
width: 36px;
height: 36px;
font-size: 14px;
.preview-video {
width: 95vw;
max-height: 90vh;
}
}
</style>

View File

@@ -54,6 +54,7 @@ import previewMedia from '../composables/useMediaPreview.ts';
import { useThemeStore } from '../stores/theme.ts';
import { useUserStore as chatUseUserStore } from '../stores/user';
import AudioMessage from './AudioMessage.vue';
import { XgVideoPlayer } from '#/components/video-player';
import PatientExperienceCard from '#/views/doctor/online-consultation/components/PatientExperienceCard.vue';
import FollowUpDrugAssistantCard from './FollowUpDrugAssistantCard.vue';
import ProductCard from '#/views/doctor/online-consultation/components/ProductCard.vue';
@@ -472,12 +473,11 @@ const getSexText = (sex) => {
class="video-message relative cursor-pointer"
@click="handlePreviewMedia(parsedContent, 'video')"
>
<video
<XgVideoPlayer
:src="parsedContent"
class="video-thumbnail max-w-full rounded-lg"
preload="metadata"
@error="handleVideoError"
></video>
thumbnail
/>
<div class="video-overlay">
<div class="play-button">
<i class="fas fa-play"></i>

View File

@@ -6,6 +6,7 @@ import { useVbenDrawer } from '@vben/common-ui';
import { Button, Descriptions, Image, Spin } from 'ant-design-vue';
import MIcon from '#/components/icon/icon.vue';
import { XgVideoPlayer } from '#/components/video-player';
import type { FileGalleryDetail } from '#/api/core/file-gallery';
import { getFileGalleryDetail } from '#/api/core/file-gallery';
@@ -70,11 +71,10 @@ defineExpose({
<template v-if="detail">
<div class="preview-wrap">
<Image v-if="detail.type === 0" :src="detail.url" :width="220" />
<video
<XgVideoPlayer
v-else-if="detail.type === 1"
class="media-player"
controls
:src="detail.url"
class="media-player"
/>
<audio
v-else-if="detail.type === 2"

View File

@@ -118,6 +118,7 @@
"js-base64": "^3.7.7",
"lodash-es": "^4.17.21",
"lucide-vue-next": "^0.487.0",
"md-editor-v3": "^5.4.5"
"md-editor-v3": "^5.4.5",
"xgplayer": "^3.0.24"
}
}

117
pnpm-lock.yaml generated
View File

@@ -493,6 +493,9 @@ importers:
md-editor-v3:
specifier: ^5.4.5
version: 5.4.5(vue@3.5.13(typescript@5.6.3))
xgplayer:
specifier: ^3.0.24
version: 3.0.24(core-js@3.39.0)
devDependencies:
'@changesets/changelog-github':
specifier: 'catalog:'
@@ -5233,6 +5236,13 @@ packages:
engines: {node: '>=v12.20.0'}
hasBin: true
d@1.0.2:
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
engines: {node: '>=0.12'}
danmu.js@1.2.1:
resolution: {integrity: sha512-evDEImUBo94c846fC92K//Dzll8jXnZ3zKmYlQHwMzmvw6IW2IyjWL3Ew2SqEAzuqauFnDkwJEgZauu3uW/p1Q==}
dargs@8.1.0:
resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==}
engines: {node: '>=12'}
@@ -5360,6 +5370,9 @@ packages:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
denque@2.1.0:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'}
@@ -5601,6 +5614,17 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
es5-ext@0.10.64:
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
engines: {node: '>=0.10'}
es6-iterator@2.0.3:
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
es6-symbol@3.1.4:
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
engines: {node: '>=0.12'}
esbuild@0.24.0:
resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
engines: {node: '>=18'}
@@ -5814,6 +5838,10 @@ packages:
jiti:
optional: true
esniff@2.0.1:
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
engines: {node: '>=0.10'}
espree@10.3.0:
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -5856,6 +5884,9 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
@@ -5863,6 +5894,9 @@ packages:
eventemitter3@2.0.3:
resolution: {integrity: sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==}
eventemitter3@4.0.7:
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
@@ -5890,6 +5924,9 @@ packages:
resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
engines: {node: '>=12.0.0'}
ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -7352,6 +7389,9 @@ packages:
engines: {node: '>= 4.4.x'}
hasBin: true
next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
nitropack@2.10.4:
resolution: {integrity: sha512-sJiG/MIQlZCVSw2cQrFG1H6mLeSqHlYfFerRjLKz69vUfdu0EL2l0WdOxlQbzJr3mMv/l4cOlCCLzVRzjzzF/g==}
engines: {node: ^16.11.0 || >=17.0.0}
@@ -9281,6 +9321,9 @@ packages:
resolution: {integrity: sha512-UJShLPYi1aWqCdq9HycOL/gwsuqda1OISdBO3t8RlXQC4QvtuIz4b5FCfe2dQIWEpmlRExKmcTBfP1r9bhY7ig==}
engines: {node: '>=16'}
type@2.7.3:
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -9914,6 +9957,16 @@ packages:
xe-utils@3.5.32:
resolution: {integrity: sha512-R8ZT2lRnRBQO3pchM1za/Aru+/29DVDWD/OmOFODWWGkiQYz0iVIr8Bq8uKXS6zMhEsSqVCrn46bXzfe/Agjcw==}
xgplayer-subtitles@3.0.24:
resolution: {integrity: sha512-yrHROepD9kTGWiTSxBjh+TGaK9orQOHQ1GUxWFOkQzO8BLl/pcIAqqJkHiAoP0j+eU8VdIhpb55oJRIkTTWPsA==}
peerDependencies:
core-js: '>=3.12.1'
xgplayer@3.0.24:
resolution: {integrity: sha512-rK3hoJ+1Pbl9PUCHgeJv1GnOQF28BKLQFTBxdvi0pHsibJeXaDUf51SLFcgNVAPN15aDYcjJgaSf7LQ0RfEFPQ==}
peerDependencies:
core-js: '>=3.12.1'
xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'}
@@ -14376,6 +14429,15 @@ snapshots:
czg@1.11.0: {}
d@1.0.2:
dependencies:
es5-ext: 0.10.64
type: 2.7.3
danmu.js@1.2.1:
dependencies:
event-emitter: 0.3.5
dargs@8.1.0: {}
data-view-buffer@1.0.2:
@@ -14466,6 +14528,8 @@ snapshots:
delayed-stream@1.0.0: {}
delegate@3.2.0: {}
denque@2.1.0: {}
depcheck@1.4.7:
@@ -14751,6 +14815,24 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
es5-ext@0.10.64:
dependencies:
es6-iterator: 2.0.3
es6-symbol: 3.1.4
esniff: 2.0.1
next-tick: 1.1.0
es6-iterator@2.0.3:
dependencies:
d: 1.0.2
es5-ext: 0.10.64
es6-symbol: 3.1.4
es6-symbol@3.1.4:
dependencies:
d: 1.0.2
ext: 1.7.0
esbuild@0.24.0:
optionalDependencies:
'@esbuild/aix-ppc64': 0.24.0
@@ -15054,6 +15136,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
esniff@2.0.1:
dependencies:
d: 1.0.2
es5-ext: 0.10.64
event-emitter: 0.3.5
type: 2.7.3
espree@10.3.0:
dependencies:
acorn: 8.14.0
@@ -15090,10 +15179,17 @@ snapshots:
etag@1.8.1: {}
event-emitter@0.3.5:
dependencies:
d: 1.0.2
es5-ext: 0.10.64
event-target-shim@5.0.1: {}
eventemitter3@2.0.3: {}
eventemitter3@4.0.7: {}
eventemitter3@5.0.1: {}
events@3.3.0: {}
@@ -15143,6 +15239,10 @@ snapshots:
expect-type@1.1.0: {}
ext@1.7.0:
dependencies:
type: 2.7.3
extend@3.0.2: {}
extendable-error@0.1.7: {}
@@ -16577,6 +16677,8 @@ snapshots:
sax: 1.4.1
optional: true
next-tick@1.1.0: {}
nitropack@2.10.4(encoding@0.1.13)(typescript@5.7.2):
dependencies:
'@cloudflare/kv-asset-handler': 0.3.4
@@ -18667,6 +18769,8 @@ snapshots:
type-fest@4.30.2: {}
type@2.7.3: {}
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.3
@@ -19461,6 +19565,19 @@ snapshots:
xe-utils@3.5.32: {}
xgplayer-subtitles@3.0.24(core-js@3.39.0):
dependencies:
core-js: 3.39.0
eventemitter3: 4.0.7
xgplayer@3.0.24(core-js@3.39.0):
dependencies:
core-js: 3.39.0
danmu.js: 1.2.1
delegate: 3.2.0
eventemitter3: 4.0.7
xgplayer-subtitles: 3.0.24(core-js@3.39.0)
xlsx@0.18.5:
dependencies:
adler-32: 1.3.1