325 lines
8.6 KiB
Plaintext
325 lines
8.6 KiB
Plaintext
import supa from '@/components/supadb/aksupainstance.uts'
|
|
import { HOME_REDIRECT } from '@/ak/config.uts'
|
|
import { AkReq } from '@/uni_modules/ak-req/index.uts'
|
|
import { getCurrentUser, logout, state } from '@/utils/store.uts'
|
|
import type { UserProfile } from '@/types/mall-types.uts'
|
|
|
|
export type MerchantInfo = {
|
|
id: string
|
|
merchant_id: string
|
|
shop_name: string
|
|
shop_logo: string
|
|
shop_banner: string
|
|
description: string
|
|
contact_name: string
|
|
contact_phone: string
|
|
status: number | null
|
|
}
|
|
|
|
export type MerchantAuthOptions = {
|
|
redirectOnFail?: boolean
|
|
toastOnFail?: boolean
|
|
redirect?: string
|
|
message?: string
|
|
}
|
|
|
|
export type MerchantAuthResult = {
|
|
ok: boolean
|
|
message: string
|
|
userInfo: UserProfile | null
|
|
merchantInfo: MerchantInfo | null
|
|
}
|
|
|
|
const MERCHANT_LOGIN_PATH = '/pages/user/login?mode=merchant'
|
|
const MERCHANT_HOME_PATH = HOME_REDIRECT !== '' ? HOME_REDIRECT : '/pages/mall/merchant/index'
|
|
|
|
let redirectingToMerchantLogin = false
|
|
|
|
function hasText(value: string | null): boolean {
|
|
return value != null && value !== ''
|
|
}
|
|
|
|
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 isMerchantRoute(route: string): boolean {
|
|
return route.startsWith('/pages/mall/merchant/')
|
|
}
|
|
|
|
function shouldShowToast(enabled: boolean | null): boolean {
|
|
return enabled == null || enabled === true
|
|
}
|
|
|
|
function shouldRedirect(enabled: boolean | null): boolean {
|
|
return enabled == null || enabled === true
|
|
}
|
|
|
|
function buildMerchantInfo(raw: UTSJSONObject): MerchantInfo {
|
|
return {
|
|
id: raw.getString('id') ?? '',
|
|
merchant_id: raw.getString('merchant_id') ?? '',
|
|
shop_name: raw.getString('shop_name') ?? '',
|
|
shop_logo: raw.getString('shop_logo') ?? '',
|
|
shop_banner: raw.getString('shop_banner') ?? '',
|
|
description: raw.getString('description') ?? '',
|
|
contact_name: raw.getString('contact_name') ?? '',
|
|
contact_phone: raw.getString('contact_phone') ?? '',
|
|
status: raw.getNumber('status')
|
|
}
|
|
}
|
|
|
|
function persistMerchantInfo(info: MerchantInfo): void {
|
|
const payload = new UTSJSONObject()
|
|
payload.set('id', info.id)
|
|
payload.set('merchant_id', info.merchant_id)
|
|
payload.set('shop_name', info.shop_name)
|
|
payload.set('shop_logo', info.shop_logo)
|
|
payload.set('shop_banner', info.shop_banner)
|
|
payload.set('description', info.description)
|
|
payload.set('contact_name', info.contact_name)
|
|
payload.set('contact_phone', info.contact_phone)
|
|
if (info.status != null) {
|
|
payload.set('status', info.status)
|
|
}
|
|
uni.setStorageSync('merchant_info', JSON.stringify(payload))
|
|
if (hasText(info.merchant_id)) {
|
|
uni.setStorageSync('merchant_id', info.merchant_id)
|
|
} else {
|
|
uni.removeStorageSync('merchant_id')
|
|
}
|
|
}
|
|
|
|
function buildFailureResult(message: string, userInfo: UserProfile | null = null): MerchantAuthResult {
|
|
return {
|
|
ok: false,
|
|
message,
|
|
userInfo,
|
|
merchantInfo: null
|
|
}
|
|
}
|
|
|
|
async function fetchMerchantInfoByUserId(userId: string): Promise<MerchantInfo | null> {
|
|
let response = await supa
|
|
.from('ml_shops')
|
|
.select('id, merchant_id, shop_name, shop_logo, shop_banner, description, contact_name, contact_phone, status')
|
|
.eq('merchant_id', userId)
|
|
.limit(1)
|
|
.execute()
|
|
|
|
if (response.error == null && response.data != null) {
|
|
const rows = response.data as Array<UTSJSONObject>
|
|
if (rows.length > 0) {
|
|
return buildMerchantInfo(rows[0])
|
|
}
|
|
}
|
|
|
|
response = await supa
|
|
.from('ml_shops')
|
|
.select('id, merchant_id, shop_name, shop_logo, shop_banner, description, contact_name, contact_phone, status')
|
|
.eq('id', userId)
|
|
.limit(1)
|
|
.execute()
|
|
|
|
if (response.error == null && response.data != null) {
|
|
const rows = response.data as Array<UTSJSONObject>
|
|
if (rows.length > 0) {
|
|
return buildMerchantInfo(rows[0])
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function getRedirectTarget(explicitRedirect: string | null): string {
|
|
if (hasText(explicitRedirect)) {
|
|
return explicitRedirect as string
|
|
}
|
|
const currentRoute = getCurrentRoute()
|
|
if (hasText(currentRoute) && currentRoute !== '/pages/user/login') {
|
|
return currentRoute
|
|
}
|
|
return MERCHANT_HOME_PATH
|
|
}
|
|
|
|
function handleFailure(message: string, options?: MerchantAuthOptions, userInfo: UserProfile | null = null): MerchantAuthResult {
|
|
clearAuth()
|
|
if (shouldShowToast(options?.toastOnFail ?? null) && hasText(message)) {
|
|
uni.showToast({ title: message, icon: 'none' })
|
|
}
|
|
if (shouldRedirect(options?.redirectOnFail ?? null)) {
|
|
redirectToMerchantLogin(getRedirectTarget(options?.redirect ?? null))
|
|
}
|
|
return buildFailureResult(message, userInfo)
|
|
}
|
|
|
|
export function getToken(): string {
|
|
const token = AkReq.getToken()
|
|
return token != null ? token : ''
|
|
}
|
|
|
|
export async function getUserInfo(): Promise<UserProfile | null> {
|
|
try {
|
|
const profile = state.userProfile
|
|
if (profile != null && hasText(profile.id ?? null)) {
|
|
return profile as UserProfile
|
|
}
|
|
} catch (e) {}
|
|
return await getCurrentUser()
|
|
}
|
|
|
|
export function getMerchantInfo(): MerchantInfo | null {
|
|
try {
|
|
const raw = uni.getStorageSync('merchant_info') as string | null
|
|
if (hasText(raw)) {
|
|
const parsed = JSON.parse(raw as string) as UTSJSONObject
|
|
return buildMerchantInfo(parsed)
|
|
}
|
|
} catch (e) {
|
|
console.error('[merchantAuth] 读取 merchant_info 失败:', e)
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function setMerchantInfo(info: MerchantInfo): void {
|
|
persistMerchantInfo(info)
|
|
}
|
|
|
|
export function isLoggedIn(): boolean {
|
|
try {
|
|
const session = supa.getSession()
|
|
const hasSession = session != null && session.user != null
|
|
const storedId = uni.getStorageSync('user_id') as string | null
|
|
const hasStoredId = hasText(storedId)
|
|
return hasSession || hasStoredId
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export function isMerchantRole(userInfo: UserProfile | null): boolean {
|
|
if (userInfo == null) {
|
|
return false
|
|
}
|
|
const role = userInfo.role != null ? userInfo.role : ''
|
|
return role === 'merchant'
|
|
}
|
|
|
|
export async function checkMerchantAccount(userInfo: UserProfile): Promise<MerchantInfo | null> {
|
|
const userId = userInfo.id != null ? userInfo.id : ''
|
|
if (!hasText(userId)) {
|
|
return null
|
|
}
|
|
try {
|
|
return await fetchMerchantInfoByUserId(userId)
|
|
} catch (e) {
|
|
console.error('[merchantAuth] 查询商家信息失败:', e)
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function clearAuth(): void {
|
|
try {
|
|
AkReq.clearToken()
|
|
} catch (e) {}
|
|
uni.removeStorageSync('user_id')
|
|
uni.removeStorageSync('merchant_id')
|
|
uni.removeStorageSync('merchant_info')
|
|
uni.removeStorageSync('merchant_idx_cache')
|
|
try {
|
|
logout()
|
|
} catch (e) {}
|
|
}
|
|
|
|
export function redirectToMerchantLogin(redirect?: string): void {
|
|
const currentRoute = getCurrentRoute()
|
|
if (currentRoute === '/pages/user/login') {
|
|
return
|
|
}
|
|
if (redirectingToMerchantLogin) {
|
|
return
|
|
}
|
|
redirectingToMerchantLogin = true
|
|
let targetUrl = MERCHANT_LOGIN_PATH
|
|
const redirectTarget = getRedirectTarget(redirect != null ? redirect : null)
|
|
if (hasText(redirectTarget)) {
|
|
targetUrl = `${MERCHANT_LOGIN_PATH}&redirect=${encodeURIComponent(redirectTarget)}`
|
|
}
|
|
uni.reLaunch({
|
|
url: targetUrl,
|
|
complete: () => {
|
|
setTimeout(() => {
|
|
redirectingToMerchantLogin = false
|
|
}, 300)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function goMerchantHome(): void {
|
|
uni.reLaunch({ url: MERCHANT_HOME_PATH })
|
|
}
|
|
|
|
export async function requireMerchantAuth(options?: MerchantAuthOptions): Promise<MerchantAuthResult> {
|
|
const currentRoute = getCurrentRoute()
|
|
if (currentRoute === '/pages/user/login') {
|
|
return {
|
|
ok: true,
|
|
message: '',
|
|
userInfo: null,
|
|
merchantInfo: null
|
|
}
|
|
}
|
|
|
|
if (!isLoggedIn()) {
|
|
return handleFailure(options?.message ?? '请先登录商家账号', options)
|
|
}
|
|
|
|
const userInfo = await getUserInfo()
|
|
if (userInfo == null || !hasText(userInfo.id ?? null)) {
|
|
return handleFailure('登录状态已失效,请重新登录', options)
|
|
}
|
|
|
|
if (!isMerchantRole(userInfo)) {
|
|
const message = options?.message != null && options.message !== ''
|
|
? options.message
|
|
: '当前账号不是商家账号'
|
|
return handleFailure(message, options, userInfo)
|
|
}
|
|
|
|
const merchantInfo = await checkMerchantAccount(userInfo)
|
|
if (merchantInfo == null) {
|
|
return handleFailure('当前账号未绑定商家信息', options, userInfo)
|
|
}
|
|
|
|
if (merchantInfo.status != null) {
|
|
if (merchantInfo.status === 0) {
|
|
return handleFailure('当前商家信息待审核', options, userInfo)
|
|
}
|
|
if (merchantInfo.status !== 1) {
|
|
return handleFailure('当前商家状态异常,暂不可登录', options, userInfo)
|
|
}
|
|
}
|
|
|
|
persistMerchantInfo(merchantInfo)
|
|
return {
|
|
ok: true,
|
|
message: '',
|
|
userInfo,
|
|
merchantInfo
|
|
}
|
|
}
|
|
|
|
export function isCurrentMerchantPage(): boolean {
|
|
return isMerchantRoute(getCurrentRoute())
|
|
} |