2023-12-28 10:45:11 +08:00
|
|
|
|
<template>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<n-scrollbar>
|
2024-12-28 16:43:52 +08:00
|
|
|
|
<div class="set-page">
|
|
|
|
|
|
<div class="set-item">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">主题模式</div>
|
|
|
|
|
|
<div class="set-item-content">切换日间/夜间主题</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-switch v-model:value="isDarkTheme">
|
|
|
|
|
|
<template #checked>
|
|
|
|
|
|
<i class="ri-moon-line"></i>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template #unchecked>
|
|
|
|
|
|
<i class="ri-sun-line"></i>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</n-switch>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- <div v-if="isElectron" class="set-item">
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">代理</div>
|
|
|
|
|
|
<div class="set-item-content">无法听音乐时打开</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-switch v-model:value="setData.isProxy" />
|
2024-12-28 16:43:52 +08:00
|
|
|
|
</div> -->
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<div>
|
2025-01-01 02:25:18 +08:00
|
|
|
|
<div class="set-item-title">音乐API端口</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div class="set-item-content">修改后需要重启应用</div>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
</div>
|
2025-01-01 02:25:18 +08:00
|
|
|
|
<n-input-number v-model:value="setData.musicApiPort" />
|
2024-12-08 21:50:58 +08:00
|
|
|
|
</div>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<div class="set-item">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">动画速度</div>
|
|
|
|
|
|
<div class="set-item-content">调节动画播放速度</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="text-sm text-gray-400">{{ setData.animationSpeed }}x</span>
|
|
|
|
|
|
<div class="w-40">
|
|
|
|
|
|
<n-slider
|
|
|
|
|
|
v-model:value="setData.animationSpeed"
|
|
|
|
|
|
:min="0.1"
|
|
|
|
|
|
:max="3"
|
|
|
|
|
|
:step="0.1"
|
|
|
|
|
|
:marks="{
|
|
|
|
|
|
0.1: '极慢',
|
|
|
|
|
|
1: '正常',
|
2025-01-01 02:25:18 +08:00
|
|
|
|
3: '极快'
|
2024-12-08 21:57:34 +08:00
|
|
|
|
}"
|
|
|
|
|
|
:disabled="setData.noAnimate"
|
|
|
|
|
|
class="w-40"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2024-12-08 21:50:58 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2025-01-02 00:14:05 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">下载目录</div>
|
|
|
|
|
|
<div class="set-item-content">
|
|
|
|
|
|
{{ setData.downloadPath || '默认下载目录' }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<n-button size="small" @click="openDownloadPath">打开目录</n-button>
|
|
|
|
|
|
<n-button size="small" @click="selectDownloadPath">修改目录</n-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<div class="set-item">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">版本</div>
|
2025-01-01 02:25:18 +08:00
|
|
|
|
<div class="set-item-content">
|
|
|
|
|
|
{{ updateInfo.currentVersion }}
|
|
|
|
|
|
<template v-if="updateInfo.hasUpdate">
|
|
|
|
|
|
<n-tag type="success" class="ml-2">发现新版本 {{ updateInfo.latestVersion }}</n-tag>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<n-button
|
|
|
|
|
|
:type="updateInfo.hasUpdate ? 'primary' : 'default'"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
:loading="checking"
|
|
|
|
|
|
@click="checkForUpdates(true)"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ checking ? '检查中...' : '检查更新' }}
|
|
|
|
|
|
</n-button>
|
|
|
|
|
|
<n-button
|
|
|
|
|
|
v-if="updateInfo.hasUpdate"
|
|
|
|
|
|
type="success"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
@click="openReleasePage"
|
|
|
|
|
|
>
|
|
|
|
|
|
前往更新
|
|
|
|
|
|
</n-button>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
</div>
|
2023-12-28 10:45:11 +08:00
|
|
|
|
</div>
|
2025-01-01 02:25:18 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="set-item cursor-pointer hover:text-green-500 hover:bg-green-950 transition-all"
|
|
|
|
|
|
@click="openAuthor"
|
|
|
|
|
|
>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
<div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<coffee>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">作者</div>
|
|
|
|
|
|
<div class="set-item-content">algerkong 点个star🌟呗</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</coffee>
|
2025-01-01 22:42:25 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<n-button size="small" type="primary" @click="openAuthor"
|
|
|
|
|
|
><i class="ri-github-line"></i>前往github</n-button
|
|
|
|
|
|
>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
</div>
|
2023-12-28 10:45:11 +08:00
|
|
|
|
</div>
|
2025-01-06 22:03:50 +08:00
|
|
|
|
<div class="set-item">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">音质设置</div>
|
|
|
|
|
|
<div class="set-item-content">选择音乐播放音质(VIP)</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-select
|
|
|
|
|
|
v-model:value="setData.musicQuality"
|
|
|
|
|
|
:options="[
|
|
|
|
|
|
{ label: '标准', value: 'standard' },
|
|
|
|
|
|
{ label: '较高', value: 'higher' },
|
|
|
|
|
|
{ label: '极高', value: 'exhigh' },
|
|
|
|
|
|
{ label: '无损', value: 'lossless' },
|
|
|
|
|
|
{ label: 'Hi-Res', value: 'hires' },
|
|
|
|
|
|
{ label: '高清环绕声', value: 'jyeffect' },
|
|
|
|
|
|
{ label: '沉浸环绕声', value: 'sky' },
|
|
|
|
|
|
{ label: '杜比全景声', value: 'dolby' },
|
|
|
|
|
|
{ label: '超清母带', value: 'jymaster' }
|
|
|
|
|
|
]"
|
|
|
|
|
|
style="width: 160px"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2025-01-03 22:24:13 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">关闭行为</div>
|
|
|
|
|
|
<div class="set-item-content">
|
|
|
|
|
|
{{ closeActionLabels[setData.closeAction] || '每次询问' }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-select
|
|
|
|
|
|
v-model:value="setData.closeAction"
|
|
|
|
|
|
:options="[
|
|
|
|
|
|
{ label: '每次询问', value: 'ask' },
|
|
|
|
|
|
{ label: '最小化到托盘', value: 'minimize' },
|
|
|
|
|
|
{ label: '直接退出', value: 'close' }
|
|
|
|
|
|
]"
|
2025-01-03 23:53:07 +08:00
|
|
|
|
style="width: 160px"
|
2025-01-03 22:24:13 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-01-06 22:03:50 +08:00
|
|
|
|
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2025-01-01 02:25:18 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">重启</div>
|
|
|
|
|
|
<div class="set-item-content">重启应用</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-button type="primary" @click="restartApp">重启</n-button>
|
|
|
|
|
|
</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2025-01-03 23:53:07 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">代理设置</div>
|
|
|
|
|
|
<div class="set-item-content">无法访问音乐时可以开启代理</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<n-switch v-model:value="setData.proxyConfig.enable">
|
|
|
|
|
|
<template #checked>开启</template>
|
|
|
|
|
|
<template #unchecked>关闭</template>
|
|
|
|
|
|
</n-switch>
|
|
|
|
|
|
<n-button size="small" @click="showProxyModal = true">配置</n-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div v-if="isElectron" class="set-item">
|
2025-01-03 23:53:07 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">realIP</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<div class="set-item-content">
|
|
|
|
|
|
由于限制,此项目在国外使用会受到限制可使用realIP参数,传进国内IP解决,如:116.25.146.177
|
|
|
|
|
|
即可解决
|
|
|
|
|
|
</div>
|
2025-01-03 23:53:07 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<n-switch v-model:value="setData.enableRealIP">
|
|
|
|
|
|
<template #checked>开启</template>
|
|
|
|
|
|
<template #unchecked>关闭</template>
|
|
|
|
|
|
</n-switch>
|
|
|
|
|
|
<n-input
|
|
|
|
|
|
v-if="setData.enableRealIP"
|
|
|
|
|
|
v-model:value="setData.realIP"
|
|
|
|
|
|
placeholder="realIP"
|
|
|
|
|
|
style="width: 200px"
|
2025-01-10 22:49:55 +08:00
|
|
|
|
@blur="validateAndSaveRealIP"
|
2025-01-03 23:53:07 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-01-11 18:22:14 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="p-4 bg-light dark:bg-dark rounded-lg mb-4 border border-gray-200 dark:border-gray-700 rounded-lg"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="set-item-title">捐赠支持</div>
|
|
|
|
|
|
<div class="set-item-content">感谢您的支持,让我有动力能够持续改进</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<donation-list />
|
|
|
|
|
|
</div>
|
2023-12-28 10:45:11 +08:00
|
|
|
|
</div>
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<play-bottom />
|
2025-01-03 23:53:07 +08:00
|
|
|
|
<n-modal
|
|
|
|
|
|
v-model:show="showProxyModal"
|
|
|
|
|
|
preset="dialog"
|
|
|
|
|
|
title="代理设置"
|
|
|
|
|
|
positive-text="确认"
|
|
|
|
|
|
negative-text="取消"
|
2025-01-10 22:49:55 +08:00
|
|
|
|
:show-icon="false"
|
2025-01-03 23:53:07 +08:00
|
|
|
|
@positive-click="handleProxyConfirm"
|
|
|
|
|
|
@negative-click="showProxyModal = false"
|
|
|
|
|
|
>
|
|
|
|
|
|
<n-form
|
|
|
|
|
|
ref="formRef"
|
|
|
|
|
|
:model="proxyForm"
|
|
|
|
|
|
:rules="proxyRules"
|
|
|
|
|
|
label-placement="left"
|
|
|
|
|
|
label-width="80"
|
|
|
|
|
|
require-mark-placement="right-hanging"
|
|
|
|
|
|
>
|
|
|
|
|
|
<n-form-item label="代理协议" path="protocol">
|
|
|
|
|
|
<n-select
|
|
|
|
|
|
v-model:value="proxyForm.protocol"
|
|
|
|
|
|
:options="[
|
|
|
|
|
|
{ label: 'HTTP', value: 'http' },
|
|
|
|
|
|
{ label: 'HTTPS', value: 'https' },
|
|
|
|
|
|
{ label: 'SOCKS5', value: 'socks5' }
|
|
|
|
|
|
]"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</n-form-item>
|
|
|
|
|
|
<n-form-item label="代理地址" path="host">
|
|
|
|
|
|
<n-input v-model:value="proxyForm.host" placeholder="请输入代理地址" />
|
|
|
|
|
|
</n-form-item>
|
|
|
|
|
|
<n-form-item label="代理端口" path="port">
|
2025-01-10 22:49:55 +08:00
|
|
|
|
<n-input-number
|
|
|
|
|
|
v-model:value="proxyForm.port"
|
|
|
|
|
|
placeholder="请输入代理端口"
|
|
|
|
|
|
:min="1"
|
|
|
|
|
|
:max="65535"
|
|
|
|
|
|
/>
|
2025-01-03 23:53:07 +08:00
|
|
|
|
</n-form-item>
|
|
|
|
|
|
</n-form>
|
|
|
|
|
|
</n-modal>
|
2024-12-08 21:57:34 +08:00
|
|
|
|
</n-scrollbar>
|
2023-12-28 10:45:11 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-01-03 23:53:07 +08:00
|
|
|
|
import type { FormRules } from 'naive-ui';
|
2025-01-10 22:49:55 +08:00
|
|
|
|
import { useMessage } from 'naive-ui';
|
|
|
|
|
|
import { computed, onMounted, ref, watch } from 'vue';
|
|
|
|
|
|
import { useStore } from 'vuex';
|
|
|
|
|
|
|
|
|
|
|
|
import Coffee from '@/components/Coffee.vue';
|
2025-01-11 18:22:14 +08:00
|
|
|
|
import DonationList from '@/components/common/DonationList.vue';
|
2025-01-10 22:49:55 +08:00
|
|
|
|
import PlayBottom from '@/components/common/PlayBottom.vue';
|
2025-01-01 13:12:46 +08:00
|
|
|
|
import { isElectron } from '@/utils';
|
2025-01-10 22:49:55 +08:00
|
|
|
|
import { openDirectory, selectDirectory } from '@/utils/fileOperation';
|
2025-01-01 13:12:46 +08:00
|
|
|
|
import { checkUpdate, UpdateResult } from '@/utils/update';
|
2025-01-10 22:49:55 +08:00
|
|
|
|
|
2025-01-01 02:25:18 +08:00
|
|
|
|
import config from '../../../../package.json';
|
2024-05-22 12:07:48 +08:00
|
|
|
|
|
2024-12-28 16:43:52 +08:00
|
|
|
|
const store = useStore();
|
2025-01-01 02:25:18 +08:00
|
|
|
|
const checking = ref(false);
|
2025-01-01 13:12:46 +08:00
|
|
|
|
const updateInfo = ref<UpdateResult>({
|
2025-01-01 02:25:18 +08:00
|
|
|
|
hasUpdate: false,
|
|
|
|
|
|
latestVersion: '',
|
|
|
|
|
|
currentVersion: config.version,
|
|
|
|
|
|
releaseInfo: null
|
2024-12-08 21:50:58 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-01-03 22:24:13 +08:00
|
|
|
|
const closeActionLabels = {
|
|
|
|
|
|
ask: '每次询问',
|
|
|
|
|
|
minimize: '最小化到托盘',
|
|
|
|
|
|
close: '直接退出'
|
|
|
|
|
|
} as const;
|
|
|
|
|
|
|
2025-01-03 23:53:07 +08:00
|
|
|
|
const setData = computed(() => {
|
|
|
|
|
|
const data = store.state.setData;
|
|
|
|
|
|
// 确保代理配置存在
|
|
|
|
|
|
if (!data.proxyConfig) {
|
|
|
|
|
|
data.proxyConfig = {
|
|
|
|
|
|
enable: false,
|
|
|
|
|
|
protocol: 'http',
|
|
|
|
|
|
host: '127.0.0.1',
|
|
|
|
|
|
port: 7890
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-01-06 20:54:42 +08:00
|
|
|
|
// 确保音质设置存在
|
|
|
|
|
|
if (!data.musicQuality) {
|
|
|
|
|
|
data.musicQuality = 'higher';
|
|
|
|
|
|
}
|
2025-01-03 23:53:07 +08:00
|
|
|
|
return data;
|
|
|
|
|
|
});
|
2025-01-01 02:25:18 +08:00
|
|
|
|
|
2025-01-10 22:49:55 +08:00
|
|
|
|
watch(
|
|
|
|
|
|
() => setData.value,
|
|
|
|
|
|
(newVal) => {
|
|
|
|
|
|
store.commit('setSetData', newVal);
|
|
|
|
|
|
},
|
|
|
|
|
|
{ deep: true }
|
|
|
|
|
|
);
|
2025-01-01 02:25:18 +08:00
|
|
|
|
|
2024-12-28 16:43:52 +08:00
|
|
|
|
const isDarkTheme = computed({
|
|
|
|
|
|
get: () => store.state.theme === 'dark',
|
2025-01-01 02:25:18 +08:00
|
|
|
|
set: () => store.commit('toggleTheme')
|
2024-12-28 16:43:52 +08:00
|
|
|
|
});
|
2024-12-08 21:50:58 +08:00
|
|
|
|
|
|
|
|
|
|
const openAuthor = () => {
|
2024-12-28 16:43:52 +08:00
|
|
|
|
window.open(setData.value.authorUrl);
|
2024-05-16 18:54:30 +08:00
|
|
|
|
};
|
2025-01-01 02:25:18 +08:00
|
|
|
|
|
|
|
|
|
|
const restartApp = () => {
|
|
|
|
|
|
window.electron.ipcRenderer.send('restart');
|
|
|
|
|
|
};
|
|
|
|
|
|
const message = useMessage();
|
|
|
|
|
|
const checkForUpdates = async (isClick = false) => {
|
|
|
|
|
|
checking.value = true;
|
|
|
|
|
|
try {
|
2025-01-01 13:12:46 +08:00
|
|
|
|
const result = await checkUpdate(config.version);
|
|
|
|
|
|
if (result) {
|
|
|
|
|
|
updateInfo.value = result;
|
|
|
|
|
|
if (!result.hasUpdate && isClick) {
|
|
|
|
|
|
message.success('当前已是最新版本');
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (isClick) {
|
2025-01-01 02:25:18 +08:00
|
|
|
|
message.success('当前已是最新版本');
|
|
|
|
|
|
}
|
2025-01-01 13:12:46 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('检查更新失败:', error);
|
|
|
|
|
|
if (isClick) {
|
|
|
|
|
|
message.error('检查更新失败,请稍后重试');
|
|
|
|
|
|
}
|
2025-01-01 02:25:18 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
checking.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const openReleasePage = () => {
|
2025-01-10 22:49:55 +08:00
|
|
|
|
store.commit('setShowUpdateModal', true);
|
2025-01-01 02:25:18 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-01-02 00:14:05 +08:00
|
|
|
|
const selectDownloadPath = async () => {
|
|
|
|
|
|
const path = await selectDirectory(message);
|
|
|
|
|
|
if (path) {
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
downloadPath: path
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const openDownloadPath = () => {
|
|
|
|
|
|
openDirectory(setData.value.downloadPath, message);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-01-03 23:53:07 +08:00
|
|
|
|
const showProxyModal = ref(false);
|
|
|
|
|
|
const formRef = ref();
|
|
|
|
|
|
const proxyForm = ref({
|
|
|
|
|
|
protocol: 'http',
|
|
|
|
|
|
host: '127.0.0.1',
|
|
|
|
|
|
port: 7890
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const proxyRules: FormRules = {
|
|
|
|
|
|
protocol: {
|
|
|
|
|
|
required: true,
|
|
|
|
|
|
message: '请选择代理协议',
|
|
|
|
|
|
trigger: ['blur', 'change']
|
|
|
|
|
|
},
|
|
|
|
|
|
host: {
|
|
|
|
|
|
required: true,
|
|
|
|
|
|
message: '请输入代理地址',
|
|
|
|
|
|
trigger: ['blur', 'change'],
|
|
|
|
|
|
validator: (_rule, value) => {
|
|
|
|
|
|
if (!value) return false;
|
|
|
|
|
|
// 简单的IP或域名验证
|
2025-01-10 22:49:55 +08:00
|
|
|
|
const ipRegex =
|
|
|
|
|
|
/^(\d{1,3}\.){3}\d{1,3}$|^localhost$|^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/;
|
2025-01-03 23:53:07 +08:00
|
|
|
|
return ipRegex.test(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
port: {
|
|
|
|
|
|
required: true,
|
|
|
|
|
|
message: '请输入有效的端口号(1-65535)',
|
|
|
|
|
|
trigger: ['blur', 'change'],
|
|
|
|
|
|
validator: (_rule, value) => {
|
|
|
|
|
|
return value >= 1 && value <= 65535;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化时从store获取代理配置
|
2025-01-01 02:25:18 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
checkForUpdates();
|
2025-01-03 23:53:07 +08:00
|
|
|
|
if (setData.value.proxyConfig) {
|
|
|
|
|
|
proxyForm.value = { ...setData.value.proxyConfig };
|
|
|
|
|
|
}
|
|
|
|
|
|
// 确保enableRealIP有默认值
|
|
|
|
|
|
if (setData.value.enableRealIP === undefined) {
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
enableRealIP: false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听代理配置变化
|
2025-01-10 22:49:55 +08:00
|
|
|
|
watch(
|
|
|
|
|
|
() => setData.value.proxyConfig,
|
|
|
|
|
|
(newVal) => {
|
|
|
|
|
|
if (newVal) {
|
|
|
|
|
|
proxyForm.value = {
|
|
|
|
|
|
protocol: newVal.protocol || 'http',
|
|
|
|
|
|
host: newVal.host || '127.0.0.1',
|
|
|
|
|
|
port: newVal.port || 7890
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{ immediate: true, deep: true }
|
|
|
|
|
|
);
|
2025-01-03 23:53:07 +08:00
|
|
|
|
|
|
|
|
|
|
const handleProxyConfirm = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await formRef.value?.validate();
|
|
|
|
|
|
// 保存代理配置时保留enable状态
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
proxyConfig: {
|
|
|
|
|
|
enable: setData.value.proxyConfig?.enable || false,
|
|
|
|
|
|
protocol: proxyForm.value.protocol,
|
|
|
|
|
|
host: proxyForm.value.host,
|
|
|
|
|
|
port: proxyForm.value.port
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
showProxyModal.value = false;
|
|
|
|
|
|
message.success('代理设置已保存,重启应用后生效');
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
message.error('请检查输入是否正确');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const validateAndSaveRealIP = () => {
|
|
|
|
|
|
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
|
|
|
|
if (!setData.value.realIP || ipRegex.test(setData.value.realIP)) {
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
realIP: setData.value.realIP,
|
|
|
|
|
|
enableRealIP: true
|
|
|
|
|
|
});
|
|
|
|
|
|
if (setData.value.realIP) {
|
|
|
|
|
|
message.success('真实IP设置已保存');
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
message.error('请输入有效的IP地址');
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
realIP: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 监听enableRealIP变化,当关闭时清空realIP
|
2025-01-10 22:49:55 +08:00
|
|
|
|
watch(
|
|
|
|
|
|
() => setData.value.enableRealIP,
|
|
|
|
|
|
(newVal) => {
|
|
|
|
|
|
if (!newVal) {
|
|
|
|
|
|
store.commit('setSetData', {
|
|
|
|
|
|
...setData.value,
|
|
|
|
|
|
realIP: '',
|
|
|
|
|
|
enableRealIP: false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-01-03 23:53:07 +08:00
|
|
|
|
}
|
2025-01-10 22:49:55 +08:00
|
|
|
|
);
|
2023-12-28 10:45:11 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
2024-12-28 16:43:52 +08:00
|
|
|
|
<style lang="scss" scoped>
|
2024-05-16 18:54:30 +08:00
|
|
|
|
.set-page {
|
2025-01-02 00:14:05 +08:00
|
|
|
|
@apply p-4 bg-light dark:bg-dark pb-20;
|
2023-12-28 10:45:11 +08:00
|
|
|
|
}
|
2024-12-28 16:43:52 +08:00
|
|
|
|
|
2024-05-16 18:54:30 +08:00
|
|
|
|
.set-item {
|
2024-12-28 16:43:52 +08:00
|
|
|
|
@apply flex items-center justify-between p-4 rounded-lg mb-4 transition-all;
|
|
|
|
|
|
@apply bg-light dark:bg-dark text-gray-900 dark:text-white;
|
|
|
|
|
|
@apply border border-gray-200 dark:border-gray-700;
|
|
|
|
|
|
|
|
|
|
|
|
&-title {
|
|
|
|
|
|
@apply text-base font-medium mb-1;
|
2023-12-28 10:45:11 +08:00
|
|
|
|
}
|
2024-12-28 16:43:52 +08:00
|
|
|
|
|
|
|
|
|
|
&-content {
|
|
|
|
|
|
@apply text-sm text-gray-500 dark:text-gray-400;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
@apply bg-gray-50 dark:bg-gray-800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.cursor-pointer:hover {
|
|
|
|
|
|
@apply text-green-500 bg-green-50 dark:bg-green-900;
|
2023-12-28 10:45:11 +08:00
|
|
|
|
}
|
2024-12-08 21:50:58 +08:00
|
|
|
|
}
|
2024-05-16 18:54:30 +08:00
|
|
|
|
</style>
|