168 lines
3.7 KiB
Vue
168 lines
3.7 KiB
Vue
<template>
|
||
<div class="page">
|
||
<div class="page-head">
|
||
<h2>设置</h2>
|
||
<p>配置音乐来源,之后的请求会使用你选择的平台(更改自动保存)</p>
|
||
</div>
|
||
|
||
<section class="setting-card">
|
||
<div class="setting-head">
|
||
<h3>音乐源</h3>
|
||
<p>勾选后,搜索等请求会同时在所选平台查找;至少保留一个。</p>
|
||
</div>
|
||
<n-checkbox-group :value="settingsStore.enabledSources" @update:value="settingsStore.setEnabledSources">
|
||
<div class="source-grid">
|
||
<div
|
||
v-for="source in ALL_SOURCES"
|
||
:key="source"
|
||
class="source-item"
|
||
:class="{ checked: settingsStore.enabledSources.includes(source) }"
|
||
>
|
||
<n-checkbox :value="source" />
|
||
<span class="source-label">{{ SOURCE_LABELS[source] }}</span>
|
||
<span class="source-key">{{ source }}</span>
|
||
</div>
|
||
</div>
|
||
</n-checkbox-group>
|
||
</section>
|
||
|
||
<section class="setting-card">
|
||
<div class="setting-head">
|
||
<h3>默认音乐源</h3>
|
||
<p>可从全部音乐源中任选一个作为默认,不要求已勾选;用于歌单详情、分类浏览,以及歌曲未携带平台信息时解析播放直链。</p>
|
||
</div>
|
||
<n-radio-group
|
||
:value="settingsStore.defaultSource"
|
||
@update:value="settingsStore.setDefaultSource"
|
||
class="default-group"
|
||
>
|
||
<n-radio
|
||
v-for="source in ALL_SOURCES"
|
||
:key="source"
|
||
:value="source"
|
||
:label="SOURCE_LABELS[source]"
|
||
class="default-radio"
|
||
/>
|
||
</n-radio-group>
|
||
</section>
|
||
|
||
<QrLogin />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { NCheckboxGroup, NRadioGroup } from "naive-ui"
|
||
import QrLogin from "@/components/QrLogin.vue"
|
||
import { ALL_SOURCES, SOURCE_LABELS, useSettingsStore } from "@/stores/settings"
|
||
|
||
const settingsStore = useSettingsStore()
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page {
|
||
max-width: 1100px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.page-head {
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.page-head h2 {
|
||
margin: 0 0 4px;
|
||
font-size: clamp(22px, 2.5vw, 26px);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.page-head p {
|
||
margin: 0;
|
||
font-size: 13px;
|
||
color: var(--app-text-muted);
|
||
}
|
||
|
||
.setting-card {
|
||
margin-bottom: 20px;
|
||
padding: clamp(16px, 2vw, 22px);
|
||
border: 1px solid var(--app-border);
|
||
border-radius: 14px;
|
||
background: rgba(255, 250, 240, 0.72);
|
||
}
|
||
|
||
.setting-head {
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.setting-head h3 {
|
||
margin: 0 0 4px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.setting-head p {
|
||
margin: 0;
|
||
font-size: 12px;
|
||
color: var(--app-text-muted);
|
||
}
|
||
|
||
.source-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
|
||
gap: 10px;
|
||
}
|
||
|
||
.source-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 10px 12px;
|
||
border: 1px solid var(--app-border);
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
transition:
|
||
border-color 0.15s ease,
|
||
background-color 0.15s ease;
|
||
}
|
||
|
||
.source-item:hover {
|
||
border-color: rgba(180, 83, 42, 0.5);
|
||
background: rgba(180, 83, 42, 0.08);
|
||
}
|
||
|
||
.source-item.checked {
|
||
border-color: rgba(112, 132, 91, 0.58);
|
||
background: rgba(112, 132, 91, 0.1);
|
||
}
|
||
|
||
.source-label {
|
||
font-size: 13px;
|
||
color: var(--app-text);
|
||
}
|
||
|
||
.source-key {
|
||
margin-left: auto;
|
||
font-size: 11px;
|
||
color: var(--app-text-muted);
|
||
font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
|
||
}
|
||
|
||
.default-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px 20px;
|
||
}
|
||
|
||
.default-radio {
|
||
padding: 8px 12px;
|
||
border: 1px solid var(--app-border);
|
||
border-radius: 10px;
|
||
transition:
|
||
border-color 0.15s ease,
|
||
background-color 0.15s ease;
|
||
}
|
||
|
||
.default-radio:hover {
|
||
border-color: rgba(180, 83, 42, 0.5);
|
||
background: rgba(180, 83, 42, 0.08);
|
||
}
|
||
</style>
|