Signed-off-by: 吴文峰 <kevin@lmve.net>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useConfigStore = defineStore('config', () => {
|
||||
// API 配置
|
||||
const apiBaseUrl = ref('')
|
||||
|
||||
// 应用配置
|
||||
const appName = ref('OPS')
|
||||
const version = ref('1.0.0')
|
||||
|
||||
// 主题配置
|
||||
const theme = ref('light')
|
||||
|
||||
// 设置 API 地址
|
||||
const setApiBaseUrl = (url) => {
|
||||
apiBaseUrl.value = url
|
||||
uni.setStorageSync('baseUrl', url)
|
||||
}
|
||||
|
||||
const getApiBaseUrl=()=>{
|
||||
if(apiBaseUrl.value==='')
|
||||
{
|
||||
apiBaseUrl.value=uni.getStorageSync('baseUrl')
|
||||
}
|
||||
return apiBaseUrl.value
|
||||
}
|
||||
|
||||
// 获取图片基础 URL(去掉末尾的 /api 部分)
|
||||
const getFileBaseUrl = () => {
|
||||
const base = getApiBaseUrl()
|
||||
if (base) {
|
||||
return base.replace(/\/api$/, '')
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
|
||||
// 设置主题
|
||||
const setTheme = (newTheme) => {
|
||||
theme.value = newTheme
|
||||
}
|
||||
|
||||
return {
|
||||
apiBaseUrl,
|
||||
appName,
|
||||
version,
|
||||
theme,
|
||||
setApiBaseUrl,
|
||||
getApiBaseUrl,
|
||||
getFileBaseUrl,
|
||||
setTheme
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,151 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useConfigStore } from './config'
|
||||
|
||||
// Storage Keys
|
||||
const STORAGE_KEY_COOKIE = 'userCookie'
|
||||
const STORAGE_KEY_COOKIE_SESSION = 'userCookieSession'
|
||||
|
||||
/**
|
||||
* 加载 JSON(永久存储)
|
||||
*/
|
||||
function loadJson(key) {
|
||||
try {
|
||||
const raw = uni.getStorageSync(key)
|
||||
return raw ? JSON.parse(raw) : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除存储
|
||||
*/
|
||||
function removeStorage() {
|
||||
uni.removeStorageSync(STORAGE_KEY_COOKIE)
|
||||
uni.removeStorageSync(STORAGE_KEY_COOKIE_SESSION)
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
// ── State ──
|
||||
const userCookie = ref(null) // Cookie 对象 { Value, Name, ExpiresAt, Remember }
|
||||
const user = ref(null) // 用户基本信息 { ID, Name, ... }
|
||||
const userInfo = ref(null) // 用户详细信息 { Username, FirstName, ... }
|
||||
|
||||
// ── Getters ──
|
||||
/** Cookie 值字符串 */
|
||||
const cookieValue = computed(() => userCookie.value?.Value ?? '')
|
||||
|
||||
/** 是否已登录 */
|
||||
const isLoggedIn = computed(() => !!userCookie.value)
|
||||
|
||||
/** 用户名 */
|
||||
const username = computed(() => {
|
||||
return userInfo.value?.Username || user.value?.Name || ''
|
||||
})
|
||||
|
||||
/** 头像 URL */
|
||||
const avatarUrl = computed(() => {
|
||||
if (userInfo.value?.AvatarPath) {
|
||||
const configStore = useConfigStore()
|
||||
return configStore.getApiBaseUrl() + '/static/avatar/' + userInfo.value.AvatarPath
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
// ── Actions ──
|
||||
|
||||
/**
|
||||
* 登录 - 保存 Cookie 并获取用户信息
|
||||
* @param {Object} cookie - 后端返回的 cookie 对象
|
||||
*/
|
||||
function login(cookie) {
|
||||
userCookie.value = cookie
|
||||
|
||||
// 持久化存储
|
||||
if (cookie.Remember) {
|
||||
uni.setStorageSync(STORAGE_KEY_COOKIE, JSON.stringify(cookie))
|
||||
}
|
||||
// 会话存储(始终保存)
|
||||
uni.setStorageSync(STORAGE_KEY_COOKIE_SESSION, JSON.stringify(cookie))
|
||||
|
||||
// 检查 cookie 是否过期
|
||||
if (cookie.ExpiresAt && new Date(cookie.ExpiresAt) < new Date()) {
|
||||
logout()
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
fetchUserInfo()
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
function logout() {
|
||||
userCookie.value = null
|
||||
user.value = null
|
||||
userInfo.value = null
|
||||
removeStorage()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
async function fetchUserInfo() {
|
||||
try {
|
||||
const { api } = await import('../api/index.js')
|
||||
const res = await api.post('/users/getinfo', {})
|
||||
if (res.errCode === 0 && res.data) {
|
||||
user.value = res.data.user ?? null
|
||||
userInfo.value = res.data.userInfo ?? null
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取用户信息失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用启动时恢复登录状态
|
||||
*/
|
||||
function restoreSession() {
|
||||
// 优先使用会话存储,否则用永久存储
|
||||
let cookieStr = uni.getStorageSync(STORAGE_KEY_COOKIE_SESSION)
|
||||
if (!cookieStr) {
|
||||
cookieStr = uni.getStorageSync(STORAGE_KEY_COOKIE)
|
||||
}
|
||||
|
||||
if (cookieStr) {
|
||||
try {
|
||||
const cookie = JSON.parse(cookieStr)
|
||||
// 检查是否过期
|
||||
if (cookie.ExpiresAt && new Date(cookie.ExpiresAt) < new Date()) {
|
||||
logout()
|
||||
return
|
||||
}
|
||||
// 直接设置状态并获取用户信息
|
||||
userCookie.value = cookie
|
||||
fetchUserInfo()
|
||||
} catch {
|
||||
logout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// State
|
||||
userCookie,
|
||||
user,
|
||||
userInfo,
|
||||
// Getters
|
||||
cookieValue,
|
||||
isLoggedIn,
|
||||
username,
|
||||
avatarUrl,
|
||||
// Actions
|
||||
login,
|
||||
logout,
|
||||
fetchUserInfo,
|
||||
restoreSession
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 用户信息缓存
|
||||
*/
|
||||
import { ref } from 'vue'
|
||||
import { usersApi } from '../api/users'
|
||||
|
||||
// 全局缓存
|
||||
const usersInfo = ref({})
|
||||
// 请求中的 promiseMap,防止重复请求
|
||||
const inflightRequests = {}
|
||||
|
||||
/**
|
||||
* 根据用户ID获取用户信息(带缓存)
|
||||
* @param {number} userID
|
||||
* @returns {Promise<{Username, UserEmail} | null>}
|
||||
*/
|
||||
export async function fetchUserInfo(userID) {
|
||||
if (!userID) return null
|
||||
|
||||
// 已有缓存
|
||||
if (usersInfo.value[userID]) {
|
||||
return usersInfo.value[userID]
|
||||
}
|
||||
|
||||
// 请求中,等待完成
|
||||
if (inflightRequests[userID]) {
|
||||
return inflightRequests[userID]
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
const promise = usersApi.getUserInfoFromUserID(userID).then((res) => {
|
||||
if (res.errCode === 0 && res.raw?.return?.userinfo) {
|
||||
const info = res.raw.return.userinfo
|
||||
usersInfo.value[userID] = info
|
||||
return info
|
||||
}
|
||||
return null
|
||||
}).finally(() => {
|
||||
delete inflightRequests[userID]
|
||||
})
|
||||
|
||||
inflightRequests[userID] = promise
|
||||
return promise
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID获取用户名(同步,需先调用 fetchUserInfo)
|
||||
* @param {number} userID
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getUsername(userID) {
|
||||
if (!userID) return ''
|
||||
const user = usersInfo.value[userID]
|
||||
return user?.Username || `用户${userID}`
|
||||
}
|
||||
|
||||
export default {
|
||||
fetchUserInfo,
|
||||
getUsername
|
||||
}
|
||||
Reference in New Issue
Block a user