mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-03 14:20:50 +08:00
feat:优化音源配置
This commit is contained in:
@@ -119,6 +119,33 @@ export default {
|
|||||||
imported: 'Custom Source Imported',
|
imported: 'Custom Source Imported',
|
||||||
notImported: 'Not Imported'
|
notImported: 'Not Imported'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
lxMusic: {
|
||||||
|
tabs: {
|
||||||
|
sources: 'Source Selection',
|
||||||
|
lxMusic: 'LX Music',
|
||||||
|
customApi: 'Custom API'
|
||||||
|
},
|
||||||
|
scripts: {
|
||||||
|
title: 'Imported Scripts',
|
||||||
|
importLocal: 'Import Local',
|
||||||
|
importOnline: 'Import Online',
|
||||||
|
urlPlaceholder: 'Enter LX Music Script URL',
|
||||||
|
importBtn: 'Import',
|
||||||
|
empty: 'No imported LX Music scripts',
|
||||||
|
notConfigured: 'Not configured (Configure in LX Music Tab)',
|
||||||
|
importHint: 'Import compatible custom API plugins to extend sources',
|
||||||
|
noScriptWarning: 'Please import LX Music script first',
|
||||||
|
noSelectionWarning: 'Please select an LX Music source first',
|
||||||
|
notFound: 'Source not found',
|
||||||
|
switched: 'Switched to source: {name}',
|
||||||
|
deleted: 'Deleted source: {name}',
|
||||||
|
enterUrl: 'Please enter script URL',
|
||||||
|
invalidUrl: 'Invalid URL format',
|
||||||
|
invalidScript: 'Invalid LX Music script, globalThis.lx code not found',
|
||||||
|
nameRequired: 'Name cannot be empty',
|
||||||
|
renameSuccess: 'Rename successful'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
application: {
|
application: {
|
||||||
|
|||||||
@@ -116,6 +116,33 @@ export default {
|
|||||||
imported: '已导入自定义音源',
|
imported: '已导入自定义音源',
|
||||||
notImported: '未导入'
|
notImported: '未导入'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
lxMusic: {
|
||||||
|
tabs: {
|
||||||
|
sources: '音源选择',
|
||||||
|
lxMusic: '落雪音源',
|
||||||
|
customApi: '自定义API'
|
||||||
|
},
|
||||||
|
scripts: {
|
||||||
|
title: '已导入的音源脚本',
|
||||||
|
importLocal: '本地导入',
|
||||||
|
importOnline: '在线导入',
|
||||||
|
urlPlaceholder: '输入落雪音源脚本 URL',
|
||||||
|
importBtn: '导入',
|
||||||
|
empty: '暂无已导入的落雪音源',
|
||||||
|
notConfigured: '未配置 (请去落雪音源Tab配置)',
|
||||||
|
importHint: '导入兼容的自定义 API 插件以扩展音源',
|
||||||
|
noScriptWarning: '请先导入落雪音源脚本',
|
||||||
|
noSelectionWarning: '请先选择一个落雪音源',
|
||||||
|
notFound: '音源不存在',
|
||||||
|
switched: '已切换到音源: {name}',
|
||||||
|
deleted: '已删除音源: {name}',
|
||||||
|
enterUrl: '请输入脚本 URL',
|
||||||
|
invalidUrl: '无效的 URL 格式',
|
||||||
|
invalidScript: '无效的落雪音源脚本,未找到 globalThis.lx 相关代码',
|
||||||
|
nameRequired: '名称不能为空',
|
||||||
|
renameSuccess: '重命名成功'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
application: {
|
application: {
|
||||||
|
|||||||
147
src/renderer/components/common/ResponsiveModal.vue
Normal file
147
src/renderer/components/common/ResponsiveModal.vue
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<Teleport to="body">
|
||||||
|
<Transition name="fade">
|
||||||
|
<div
|
||||||
|
v-if="show"
|
||||||
|
class="fixed inset-0 z-[1000] flex items-center justify-center md:items-center items-end"
|
||||||
|
@click="handleMaskClick"
|
||||||
|
>
|
||||||
|
<!-- Overlay -->
|
||||||
|
<div class="absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity"></div>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<Transition :name="isMobile ? 'slide-up' : 'scale-fade'">
|
||||||
|
<div
|
||||||
|
v-if="show"
|
||||||
|
class="relative z-10 w-full bg-white dark:bg-[#1c1c1e] shadow-2xl overflow-hidden flex flex-col max-h-[85vh]"
|
||||||
|
:class="[
|
||||||
|
isMobile
|
||||||
|
? 'rounded-t-[20px] pb-safe'
|
||||||
|
: 'md:max-w-[720px] md:rounded-2xl'
|
||||||
|
]"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
<!-- Header -->
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between px-4 py-3 border-b border-gray-100 dark:border-white/5 shrink-0"
|
||||||
|
>
|
||||||
|
<h3 class="text-[15px] font-semibold text-gray-900 dark:text-white truncate">
|
||||||
|
{{ title }}
|
||||||
|
</h3>
|
||||||
|
<button
|
||||||
|
class="p-1 -mr-1 rounded-full text-gray-400 hover:bg-gray-100 dark:hover:bg-white/10 transition-colors"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<i class="ri-close-line text-lg"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Body -->
|
||||||
|
<div class="flex-1 overflow-y-auto overscroll-contain px-4 py-3">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div
|
||||||
|
v-if="$slots.footer"
|
||||||
|
class="px-4 py-3 border-t border-gray-100 dark:border-white/5 shrink-0 bg-gray-50/50 dark:bg-white/5 backdrop-blur-xl"
|
||||||
|
>
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: boolean;
|
||||||
|
title?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: boolean): void;
|
||||||
|
(e: 'close'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const show = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (val) => emit('update:modelValue', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const isMobile = ref(false);
|
||||||
|
|
||||||
|
const checkMobile = () => {
|
||||||
|
isMobile.value = window.innerWidth < 768;
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
show.value = false;
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMaskClick = () => {
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checkMobile();
|
||||||
|
window.addEventListener('resize', checkMobile);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', checkMobile);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent body scroll when modal is open
|
||||||
|
watch(show, (val) => {
|
||||||
|
if (val) {
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
} else {
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PC Scale Fade Transition */
|
||||||
|
.scale-fade-enter-active,
|
||||||
|
.scale-fade-leave-active {
|
||||||
|
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-fade-enter-from,
|
||||||
|
.scale-fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile Slide Up Transition */
|
||||||
|
.slide-up-enter-active,
|
||||||
|
.slide-up-leave-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-up-enter-from,
|
||||||
|
.slide-up-leave-to {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-safe {
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user