mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 19:36:36 +08:00
9be81222cc
- 修复发现页空白:后端 discover.go nil→[] Match,前端 discover.ts 加 ?? []
- 修复下载客户端页空白:后端 download_clients.go nil→[]model.DownloadClient,前端加 ?? []
- 修复通知渠道页空白:后端 notify_channels.go nil→[]struct{},前端加 ?? []
- 许可证页面重构:移除生成密钥功能,对接 LicenseServer 绑定/状态模式
- 所有变更通过 Go build + npm run build 零错误验证
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { api } from './client'
|
|
|
|
// ── License Server types (generic, ready for MediaStationLicenseServer integration) ──
|
|
|
|
/** Response after binding/activating a license. */
|
|
export interface LicenseActivation {
|
|
id: string
|
|
key_id: string
|
|
/** The license key string (e.g. MS-XXXX-XXXX-XXXX) */
|
|
key?: string
|
|
device_id: string
|
|
device_name?: string
|
|
plan?: string
|
|
max_activations?: number
|
|
/** ISO8601 — null means perpetual */
|
|
expires_at?: string | null
|
|
valid: boolean
|
|
ip?: string
|
|
heartbeat_at?: string | null
|
|
created_at: string
|
|
}
|
|
|
|
/** Status of the currently bound license on this device. */
|
|
export interface LicenseStatus {
|
|
/** Whether a license is currently active */
|
|
active: boolean
|
|
activation?: LicenseActivation
|
|
/** Error or status message */
|
|
message?: string
|
|
}
|
|
|
|
/** Generate a short device fingerprint from browser/OS info. */
|
|
function deviceFingerprint(): string {
|
|
const nav = window.navigator
|
|
const parts = [nav.hardwareConcurrency, nav.language, screen.width, screen.height]
|
|
return btoa(parts.join('|')).slice(0, 32).replace(/[+/=]/g, '')
|
|
}
|
|
|
|
// ── API methods ──
|
|
|
|
export const licenseAPI = {
|
|
/** Bind / activate a license key for this device. */
|
|
bind: (key: string) =>
|
|
api
|
|
.post<LicenseActivation>('/license/activate', {
|
|
key: key.trim(),
|
|
device_id: deviceFingerprint(),
|
|
device_name: navigator.platform || 'Web Client',
|
|
})
|
|
.then((r) => r.data),
|
|
|
|
/** Get the status of the currently active license. */
|
|
status: () =>
|
|
api.get<LicenseStatus>('/license/status').then((r) => r.data),
|
|
|
|
/** Refresh the heartbeat for the active license. */
|
|
heartbeat: () =>
|
|
api.post('/license/heartbeat').then((r) => r.data),
|
|
}
|