diff --git a/src/api/cardKeys.js b/src/api/cardKeys.js index a8810b3..2215dfe 100644 --- a/src/api/cardKeys.js +++ b/src/api/cardKeys.js @@ -1,15 +1,14 @@ import { apiRequest } from "./client.js"; /** - * @param {string} token - * @param {string} serialNumber + * @param {{ username: string, serialNumber: string }} payload */ -export function activateCardKeyApi(token, serialNumber) { +export function activateCardKeyApi({ username, serialNumber }) { return apiRequest("/card-keys/activate", { method: "POST", - headers: { - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ serial_number: serialNumber }), + body: JSON.stringify({ + username: username.trim(), + serial_number: serialNumber.trim().toUpperCase(), + }), }); } diff --git a/src/main.js b/src/main.js index a5ea7d7..cc0a89f 100644 --- a/src/main.js +++ b/src/main.js @@ -88,12 +88,19 @@ function setupHeartbeatLogoutListener() { if (!authStore.isAuthenticated) { return; } - authStore.currentUser.vip_end_time="2022-06-28T16:01:13"; - await router.replace({ name: "card-activate" }); - + authStore.redirectToCardActivate(router); + }); +} + +function setupVipWatch() { + authStore.$subscribe(() => { + if (!authStore.needsVipActivation) return; + if (router.currentRoute.value.name === "card-activate") return; + authStore.redirectToCardActivate(router); }); } setupHeartbeatLogoutListener(); +setupVipWatch(); app.mount("#app"); diff --git a/src/router/index.js b/src/router/index.js index 4e04c91..dec765f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -390,6 +390,10 @@ router.beforeEach((to) => { const auth = useAuthStore(); + if (to.name === "card-activate") { + return true; + } + const requiresAuth = to.matched.some((record) => record.meta.requiresAuth); @@ -402,6 +406,17 @@ router.beforeEach((to) => { + if (auth.needsVipActivation) { + + return { + name: "card-activate", + query: { username: auth.currentUser?.username ?? "" }, + }; + + } + + + if ((to.name === "login" || to.name === "register") && auth.isAuthenticated) { return { name: "home" }; @@ -417,8 +432,6 @@ router.beforeEach((to) => { .find((role) => role != null); - console.log('requiredRole',requiredRole); - console.log('auth.roleId',auth.roleId); if (requiredRole != null && auth.roleId !== requiredRole) { return { name: "home" }; diff --git a/src/stores/auth.js b/src/stores/auth.js index af56a43..8fdd4c8 100644 --- a/src/stores/auth.js +++ b/src/stores/auth.js @@ -5,11 +5,24 @@ import { fetchMeApi, loginApi, logoutApi, registerApi } from "../api/auth.js"; const TOKEN_KEY = "aiclient_token"; const USER_KEY = "aiclient_current_user"; +/** 普通用户 */ +export const ROLE_USER = 0; /** 管理员 */ export const ROLE_ADMIN = 1; /** 代理 */ export const ROLE_AGENT = 2; -export const ROLE_OEM=3; +export const ROLE_OEM = 3; + +export function isVipExpired(vipEndTime) { + if (!vipEndTime) return true; + const d = new Date(vipEndTime); + if (Number.isNaN(d.getTime())) return true; + return d.getTime() <= Date.now(); +} + +function isStaffRole(roleId) { + return roleId === ROLE_ADMIN || roleId === ROLE_AGENT || roleId === ROLE_OEM; +} async function syncAuthSessionToRust(token, user) { @@ -32,7 +45,6 @@ function applyTokenResponse(store, res, fallbackMessage) { if (!data?.access_token || !data?.user) { return { ok: false, message: "服务器返回数据异常" }; } - console.log(data.user); store.setSession(data.access_token, { id: data.user.id, username: data.user.username, @@ -62,7 +74,13 @@ export const useAuthStore = defineStore("auth", { roleId: (state) => state.currentUser?.role_id ?? null, isAdmin: (state) => state.currentUser?.role_id === ROLE_ADMIN, isAgent: (state) => state.currentUser?.role_id === ROLE_AGENT, - isOEM : (state) => state.currentUser?.role_id === ROLE_OEM, + isOEM: (state) => state.currentUser?.role_id === ROLE_OEM, + isVipExpired: (state) => isVipExpired(state.currentUser?.vip_end_time), + needsVipActivation: (state) => { + if (!state.token || !state.currentUser) return false; + if (isStaffRole(state.currentUser.role_id ?? ROLE_USER)) return false; + return isVipExpired(state.currentUser.vip_end_time); + }, }, actions: { @@ -87,6 +105,19 @@ export const useAuthStore = defineStore("auth", { syncAuthSessionToRust(this.token, this.currentUser); }, + cardActivateQuery() { + return { + username: this.currentUser?.username ?? "", + }; + }, + + redirectToCardActivate(router) { + router.replace({ + name: "card-activate", + query: this.cardActivateQuery(), + }); + }, + async register({ username, password, confirmPassword }) { const name = username?.trim(); if (!name || !password) { diff --git a/src/views/CardActivateView.vue b/src/views/CardActivateView.vue index e6b4b5e..6f8216d 100644 --- a/src/views/CardActivateView.vue +++ b/src/views/CardActivateView.vue @@ -1,16 +1,22 @@ - - - 卡密激活 - 输入卡密序列号,兑换会员时长或点数 - + + + {{ feedback.message }} + - - - - 会员到期 - {{ vipEndLabel }} - - - 当前点数 - {{ pointsLabel }} - + + + 会员到期 + {{ vipEndLabel }} + + + 当前点数 + {{ pointsLabel }} - - - {{ feedback.message }} - - - - - 卡密序列号 - - - - - + + + + 用户名 + + + + 卡密序列号 + + + + + +
输入卡密序列号,兑换会员时长或点数