Files
DPM/src/utils/api.js
T

158 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// API 基地址
// 同源请求(hostname=localhost/127.0.0.1):`''` 相对路径,开发模式或 macOS Tauri
// Windows Tauri(hostname 含 "tauri"):后端在本机,固定 http://localhost:10801
// 局域网访问(hostname 为 LAN IP):后端在同一台机器的 10801 端口
const hostname = window.location.hostname;
const isLocal = hostname === 'localhost' || hostname === '127.0.0.1';
const isTauri = hostname.includes('tauri');
const BASE = isLocal
? ''
: isTauri
? 'http://localhost:10801'
: `http://${hostname}:10801`;
export const API_BASE = BASE;
async function request(url, options = {}) {
const res = await fetch(`${BASE}${url}`, {
headers: { 'Content-Type': 'application/json' },
...options,
});
return res.json();
}
function formEncode(data) {
return Object.entries(data)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&');
}
// ============ Auth ============
export async function login(username, password) {
const res = await fetch(`${BASE}/api/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formEncode({ username, password }),
});
return res.json();
}
// ============ Settings ============
export async function getSettings() {
const res = await fetch(`${BASE}/api/settings`);
return res.json();
}
export async function updateSettings(data) {
return request('/api/settings', {
method: 'POST',
body: JSON.stringify(data),
});
}
// ============ Media Files ============
export async function getMediaFiles() {
const res = await fetch(`${BASE}/media`);
return res.json();
}
export async function uploadFiles(files) {
for (const file of files) {
const fd = new FormData();
fd.append('file', file);
const res = await fetch(`${BASE}/upload`, { method: 'POST', body: fd });
if (!res.ok) throw new Error(`上传失败 (${res.status})`);
}
}
export async function uploadFilesWithProgress(files, onProgress) {
for (let i = 0; i < files.length; i++) {
const file = files[i];
await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', `${BASE}/upload`);
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
onProgress({
percent: Math.round((e.loaded / e.total) * 100),
loaded: e.loaded,
total: e.total,
fileName: file.name,
current: i + 1,
total: files.length,
});
}
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve();
} else {
reject(new Error(`上传失败 (${xhr.status})`));
}
};
xhr.onerror = () => reject(new Error('网络错误,请检查连接'));
xhr.ontimeout = () => reject(new Error('上传超时'));
const fd = new FormData();
fd.append('file', file);
xhr.send(fd);
});
}
}
export async function addUrlMedia(url) {
return request('/api/media/add-url', {
method: 'POST',
body: JSON.stringify({ url }),
});
}
export async function deleteMedia(path) {
return request('/api/delete', {
method: 'POST',
body: JSON.stringify({ path }),
});
}
// ============ Playlist ============
export async function getPlaylist() {
const res = await fetch(`${BASE}/api/playlist`);
return res.json();
}
export async function addToPlaylist(path) {
return request('/api/playlist/add', {
method: 'POST',
body: JSON.stringify({ path }),
});
}
export async function removeFromPlaylist(path) {
return request('/api/playlist/remove', {
method: 'POST',
body: JSON.stringify({ path }),
});
}
// ============ Playback Control ============
export async function sendControl(action) {
return request('/api/control', {
method: 'POST',
body: JSON.stringify({ action }),
});
}
export async function getState() {
const res = await fetch(`${BASE}/api/state`);
return res.json();
}
export async function updateState(state) {
return request('/api/state', {
method: 'POST',
body: JSON.stringify({ state }),
});
}