Files
medical-mall/utils/deliveryAuth.uts

316 lines
8.6 KiB
Plaintext

import { AkReq } from '@/uni_modules/ak-req/index.uts'
import type { UserProfile } from '@/types/mall-types.uts'
import type { DeliveryInfoType } from '@/types/delivery.uts'
import { getDeliveryProfileByUserId } from '@/api/delivery.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { getCurrentUser, setIsLoggedIn, setUserProfile } from '@/utils/store.uts'
export type DeliveryAuthOptions = {
redirectOnFail?: boolean
toastOnFail?: boolean
redirect?: string
message?: string
}
export type DeliveryAuthResult = {
ok: boolean
message: string
userInfo: UserProfile | null
deliveryInfo: DeliveryInfoType | null
}
const DELIVERY_LOGIN_PATH = '/pages/user/login'
const DELIVERY_LOGIN_TARGET = '/pages/user/login?mode=delivery'
const DELIVERY_HOME_PATH = '/pages/mall/delivery/home/index'
const DELIVERY_USER_KEY = 'delivery_user_info'
const DELIVERY_INFO_KEY = 'delivery_info'
const DELIVERY_TOKEN_KEY = 'delivery_token'
const DELIVERY_ROLE_LIST = ['delivery', 'Deliverer', 'deliverer', 'service_staff', 'care_worker'] as Array<string>
let redirectingToDeliveryLogin = false
function hasText(value: string | null): boolean {
return value != null && value !== ''
}
function shouldShowToast(enabled: boolean | null): boolean {
return enabled == null || enabled === true
}
function shouldRedirect(enabled: boolean | null): boolean {
return enabled == null || enabled === true
}
function getCurrentRoute(): string {
try {
const pages = getCurrentPages() as Array<UTSJSONObject>
if (pages.length === 0) {
return ''
}
const currentPage = pages[pages.length - 1]
const route = currentPage['route']
if (route != null) {
return '/' + route
}
} catch (e) {}
return ''
}
function buildFailureResult(message: string, userInfo: UserProfile | null = null): DeliveryAuthResult {
return {
ok: false,
message,
userInfo,
deliveryInfo: null
}
}
function parseUserInfo(raw: string): UserProfile | null {
try {
return JSON.parse(raw) as UserProfile
} catch (e) {
return null
}
}
function parseDeliveryInfo(raw: string): DeliveryInfoType | null {
try {
return JSON.parse(raw) as DeliveryInfoType
} catch (e) {
return null
}
}
function persistUserInfo(userInfo: UserProfile): void {
uni.setStorageSync(DELIVERY_USER_KEY, JSON.stringify(userInfo))
}
function persistDeliveryInfo(info: DeliveryInfoType): void {
uni.setStorageSync(DELIVERY_INFO_KEY, JSON.stringify(info))
}
export function setDeliveryInfo(info: DeliveryInfoType): void {
persistDeliveryInfo(info)
}
export function clearDeliveryInfo(): void {
uni.removeStorageSync(DELIVERY_INFO_KEY)
}
export function saveDeliverySession(token: string, userInfo: UserProfile, deliveryInfo: DeliveryInfoType | null): void {
AkReq.setToken(token, '', Date.now() + 24 * 60 * 60 * 1000)
uni.setStorageSync(DELIVERY_TOKEN_KEY, token)
persistUserInfo(userInfo)
setIsLoggedIn(true)
setUserProfile(userInfo)
if (deliveryInfo != null) {
persistDeliveryInfo(deliveryInfo)
} else {
uni.removeStorageSync(DELIVERY_INFO_KEY)
}
}
export function getToken(): string {
const stored = uni.getStorageSync(DELIVERY_TOKEN_KEY) as string | null
if (stored != null && stored != '') {
return stored
}
const token = AkReq.getToken()
return token != null ? token : ''
}
export function getUserInfo(): UserProfile | null {
const raw = uni.getStorageSync(DELIVERY_USER_KEY) as string | null
if (!hasText(raw)) {
return null
}
return parseUserInfo(raw as string)
}
async function resolveUserInfo(): Promise<UserProfile | null> {
const cached = getUserInfo()
if (cached != null) {
return cached
}
try {
const profile = await getCurrentUser()
if (profile != null) {
persistUserInfo(profile)
}
return profile
} catch (e) {
return null
}
}
export function getDeliveryInfo(): DeliveryInfoType | null {
const raw = uni.getStorageSync(DELIVERY_INFO_KEY) as string | null
if (!hasText(raw)) {
return null
}
return parseDeliveryInfo(raw as string)
}
export function isLoggedIn(): boolean {
if (hasText(getToken()) && getUserInfo() != null) {
return true
}
try {
const session = supa.getSession()
return session != null && session.user != null
} catch (e) {
return false
}
}
export function isDelivererRole(userInfo: UserProfile | null): boolean {
if (userInfo == null) {
return false
}
const role = userInfo.role != null ? userInfo.role : ''
for (let i = 0; i < DELIVERY_ROLE_LIST.length; i++) {
if (role == DELIVERY_ROLE_LIST[i]) {
return true
}
}
return false
}
export async function checkDeliveryAccount(userInfo: UserProfile): Promise<DeliveryInfoType | null> {
const userId = userInfo.id != null ? userInfo.id : ''
if (!hasText(userId)) {
return null
}
return await getDeliveryProfileByUserId(userId)
}
export function clearDeliveryAuth(): void {
try {
AkReq.clearToken()
} catch (e) {}
uni.removeStorageSync(DELIVERY_TOKEN_KEY)
uni.removeStorageSync(DELIVERY_USER_KEY)
uni.removeStorageSync('user_id')
clearDeliveryInfo()
setIsLoggedIn(false)
setUserProfile({ username: '', email: '' } as UserProfile)
}
export async function logoutDelivery(): Promise<void> {
clearDeliveryAuth()
try {
await supa.signOut()
} catch (e) {}
}
function getRedirectTarget(explicitRedirect: string | null): string {
if (hasText(explicitRedirect)) {
return explicitRedirect as string
}
const currentRoute = getCurrentRoute()
if (hasText(currentRoute) && currentRoute !== DELIVERY_LOGIN_PATH) {
return currentRoute
}
return DELIVERY_HOME_PATH
}
export function redirectToDeliveryLogin(redirect?: string): void {
const currentRoute = getCurrentRoute()
if (currentRoute == DELIVERY_LOGIN_PATH) {
return
}
if (redirectingToDeliveryLogin) {
return
}
redirectingToDeliveryLogin = true
let targetUrl = DELIVERY_LOGIN_TARGET
const redirectTarget = getRedirectTarget(redirect != null ? redirect : null)
if (hasText(redirectTarget)) {
targetUrl = DELIVERY_LOGIN_TARGET + '&redirect=' + encodeURIComponent(redirectTarget)
}
uni.reLaunch({
url: targetUrl,
complete: () => {
setTimeout(() => {
redirectingToDeliveryLogin = false
}, 300)
}
})
}
export function goDeliveryHome(): void {
uni.reLaunch({ url: DELIVERY_HOME_PATH })
}
export function isCurrentDeliveryPage(): boolean {
return getCurrentRoute().startsWith('/pages/mall/delivery/')
}
export function handleDeliveryUnauthorized(message?: string, redirect?: string): void {
clearDeliveryAuth()
redirectToDeliveryLogin(redirect)
if (message != null && message != '') {
uni.showToast({ title: message, icon: 'none' })
}
}
function handleFailure(message: string, options?: DeliveryAuthOptions, userInfo: UserProfile | null = null): DeliveryAuthResult {
clearDeliveryAuth()
if (shouldShowToast(options?.toastOnFail ?? null) && hasText(message)) {
uni.showToast({ title: message, icon: 'none' })
}
if (shouldRedirect(options?.redirectOnFail ?? null)) {
redirectToDeliveryLogin(getRedirectTarget(options?.redirect ?? null))
}
return buildFailureResult(message, userInfo)
}
export async function requireDeliveryAuth(options?: DeliveryAuthOptions): Promise<DeliveryAuthResult> {
const currentRoute = getCurrentRoute()
const onLoginPage = currentRoute == DELIVERY_LOGIN_PATH
const effectiveOptions: DeliveryAuthOptions = {
redirectOnFail: onLoginPage ? false : options?.redirectOnFail,
toastOnFail: options?.toastOnFail,
redirect: options?.redirect,
message: options?.message
}
if (!isLoggedIn()) {
return handleFailure(options?.message != null ? options.message : '请先登录服务人员账号', effectiveOptions)
}
const userInfo = await resolveUserInfo()
if (userInfo == null) {
return handleFailure('登录状态已失效,请重新登录', effectiveOptions)
}
if (!isDelivererRole(userInfo)) {
return handleFailure('当前账号不是上门服务人员账号', effectiveOptions, userInfo)
}
const deliveryInfo = await checkDeliveryAccount(userInfo)
if (deliveryInfo == null) {
return handleFailure('当前账号未绑定服务人员档案', effectiveOptions, userInfo)
}
if (deliveryInfo.status == 'disabled' || deliveryInfo.status == 'locked' || deliveryInfo.status == 'suspended') {
return handleFailure('账号不可接单', effectiveOptions, userInfo)
}
if (deliveryInfo.usesMock && (!hasText(deliveryInfo.organizationId) || !hasText(deliveryInfo.organizationName))) {
return handleFailure('当前账号未绑定服务机构', effectiveOptions, userInfo)
}
if (deliveryInfo.usesMock && deliveryInfo.certificateStatus == 'expired') {
return handleFailure('资质已过期,请联系管理员', effectiveOptions, userInfo)
}
persistUserInfo(userInfo)
persistDeliveryInfo(deliveryInfo)
return {
ok: true,
message: '',
userInfo,
deliveryInfo
}
}