Files
medical-mall/utils/homecareAuth.uts
2026-06-10 20:20:47 +08:00

256 lines
8.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { AkReq } from '@/uni_modules/ak-req/index.uts'
import supa from '@/components/supadb/aksupainstance.uts'
const HOMECARE_API_BASE = 'http://localhost:4001'
const HOMECARE_TOKEN_KEY = 'homecare_auth_token'
const HOMECARE_USER_KEY = 'homecare_auth_user'
export type HomecareLoginResult = {
success: boolean
message: string
token: string | null
user: UTSJSONObject | null
}
export type HomecarePrecheckResult = {
success: boolean
message: string
distanceMeters: number | null
allowedRadiusMeters: number
canCheckin: boolean
reasonCode: string
workerLocationAccepted: boolean
serviceLocationReady: boolean
}
export const reasonCodeMap: UTSJSONObject = new UTSJSONObject({
OK: '已进入允许签到范围',
OUT_OF_RADIUS: '当前距离服务地点较远,请到达服务地址附近后再签到',
SERVICE_LOCATION_MISSING: '当前工单缺少服务地址坐标,请联系管理员处理',
WORK_ORDER_NOT_ASSIGNABLE: '当前工单未分配或状态不允许签到',
WORKER_NOT_MATCHED: '当前账号不是该工单的服务人员',
COORDINATE_TYPE_INVALID: '定位坐标类型异常,请重新定位',
SLA_CONFIG_MISSING: '签到规则配置缺失,请联系管理员处理'
})
export function getReasonText(code: string): string {
const text = reasonCodeMap.getString(code)
return text != null && text !== '' ? text : '未知原因: ' + code
}
export function getHomecareToken(): string {
const stored = uni.getStorageSync(HOMECARE_TOKEN_KEY) as string | null
return stored != null ? stored : ''
}
export function getHomecareUser(): UTSJSONObject | null {
const raw = uni.getStorageSync(HOMECARE_USER_KEY) as string | null
if (raw == null || raw === '') {
return null
}
try {
return JSON.parse(raw) as UTSJSONObject
} catch (e) {
return null
}
}
export function saveHomecareToken(token: string): void {
uni.setStorageSync(HOMECARE_TOKEN_KEY, token)
}
export function saveHomecareUser(user: UTSJSONObject): void {
uni.setStorageSync(HOMECARE_USER_KEY, JSON.stringify(user))
}
export function clearHomecareAuth(): void {
uni.removeStorageSync(HOMECARE_TOKEN_KEY)
uni.removeStorageSync(HOMECARE_USER_KEY)
}
export async function emailLogin(email: string, password: string): Promise<HomecareLoginResult> {
try {
const reqData = new UTSJSONObject()
reqData.set('email', email)
reqData.set('password', password)
const res = await AkReq.request({
url: HOMECARE_API_BASE + '/auth/email-login',
method: 'POST',
data: reqData,
contentType: 'application/json'
})
if (res.status >= 200 && res.status < 300 && res.data != null) {
const dataObj = res.data as UTSJSONObject
const dataInner = dataObj.getJSON('data')
if (dataInner != null) {
const token = dataInner.getString('token')
const user = dataInner.getJSON('user')
if (token != null && token !== '') {
saveHomecareToken(token)
if (user != null) {
saveHomecareUser(user)
}
return {
success: true,
message: '登录成功',
token: token,
user: user
}
}
}
}
let msg = '登录失败'
if (res.data != null) {
const dataObj = res.data as UTSJSONObject
const m = dataObj.getString('msg')
if (m != null && m !== '') {
msg = m
}
}
return {
success: false,
message: msg,
token: null,
user: null
}
} catch (error) {
console.error('emailLogin error:', error)
return {
success: false,
message: '网络错误,请检查网络连接',
token: null,
user: null
}
}
}
export async function checkinPrecheck(
workOrderId: string,
latitude: number,
longitude: number,
accuracy: number
): Promise<HomecarePrecheckResult> {
console.warn('[CHECKIN RPC] ========== checkinPrecheck START ==========')
console.warn('[CHECKIN RPC] 参数: workOrderId=', workOrderId, ' lat=', latitude, ' lng=', longitude, ' accuracy=', accuracy)
try {
// 获取当前用户 ID
console.warn('[CHECKIN RPC] 步骤 1: 获取 session')
const session = supa.getSession()
console.warn('[CHECKIN RPC] session:', session)
const workerId = session != null && session.user != null ? session.user.getString('id') : ''
console.warn('[CHECKIN RPC] workerId:', workerId)
if (workerId == '' || workerId == null) {
console.warn('[CHECKIN RPC] 未登录,返回 NOT_LOGGED_IN')
return { distanceMeters: null, allowedRadiusMeters: 0, canCheckin: false, reasonCode: 'NOT_LOGGED_IN' }
}
// 构建 RPC 参数
console.warn('[CHECKIN RPC] 步骤 2: 构建 RPC 参数')
const rpcParams = {
p_work_order_id: workOrderId,
p_worker_id: workerId,
p_latitude: latitude,
p_longitude: longitude,
p_coordinate_type: 'gcj02',
p_accuracy: accuracy,
p_location_scene: 'CHECKIN_PRECHECK'
} as UTSJSONObject
console.warn('[CHECKIN RPC] RPC 参数:', JSON.stringify(rpcParams))
// 直接调用 Supabase RPC不需要本地后端
console.warn('[CHECKIN RPC] 步骤 3: 调用 supa.rpc')
const rpcResponse = await supa.rpc('rpc_homecare_checkin_precheck', rpcParams)
console.warn('[CHECKIN RPC] RPC 原始返回类型:', rpcResponse.constructor.name)
console.warn('[CHECKIN RPC] RPC 原始返回:', rpcResponse)
// supa.rpc() 返回 AkReqResponse需要从 data 字段提取 UTSJSONObject
let result: UTSJSONObject | null = null
if (rpcResponse != null) {
// 检查是否是 AkReqResponse 包装
if ('data' in rpcResponse) {
const respData = (rpcResponse as any).data
console.warn('[CHECKIN RPC] 检测到 AkReqResponse提取 data 字段')
if (respData != null && respData.constructor.name == 'UTSJSONObject') {
result = respData as UTSJSONObject
console.warn('[CHECKIN RPC] 成功提取 UTSJSONObject')
} else {
console.warn('[CHECKIN RPC] data 字段不是 UTSJSONObject:', respData)
// 尝试直接当作 UTSJSONObject
if (respData != null) {
result = respData as UTSJSONObject
}
}
} else {
// 直接就是 UTSJSONObject
console.warn('[CHECKIN RPC] 直接当作 UTSJSONObject')
result = rpcResponse as UTSJSONObject
}
}
console.warn('[CHECKIN RPC] 最终 result:', result)
if (result != null) {
console.warn('[CHECKIN RPC] 解析结果字段')
const distanceMetersRaw = result.getNumber('distanceMeters')
const distanceMeters = distanceMetersRaw != null ? distanceMetersRaw : null
const allowedRadiusMetersRaw = result.getNumber('allowedRadiusMeters')
const allowedRadiusMeters = allowedRadiusMetersRaw != null ? allowedRadiusMetersRaw : 0
const canCheckinRaw = result.get('canCheckin')
const canCheckin = canCheckinRaw === true
const reasonCode = result.getString('reasonCode') ?? ''
const workerLocationAcceptedRaw = result.get('workerLocationAccepted')
const workerLocationAccepted = workerLocationAcceptedRaw === true
const serviceLocationReadyRaw = result.get('serviceLocationReady')
const serviceLocationReady = serviceLocationReadyRaw === true
console.warn('[CHECKIN RPC] 解析结果: distance=', distanceMeters, ' radius=', allowedRadiusMeters, ' canCheckin=', canCheckin, ' reason=', reasonCode)
return {
success: canCheckin,
message: getReasonText(reasonCode),
distanceMeters: distanceMeters,
allowedRadiusMeters: allowedRadiusMeters,
canCheckin: canCheckin,
reasonCode: reasonCode,
workerLocationAccepted: workerLocationAccepted,
serviceLocationReady: serviceLocationReady
}
}
console.warn('[CHECKIN RPC] RPC 返回 null返回默认错误')
return {
success: false,
message: '预校验返回空结果',
distanceMeters: null,
allowedRadiusMeters: 0,
canCheckin: false,
reasonCode: 'UNKNOWN',
workerLocationAccepted: false,
serviceLocationReady: false
}
} catch (error) {
console.warn('[CHECKIN RPC] ========== 捕获异常 ==========')
console.warn('[CHECKIN RPC] 异常类型:', error instanceof Error ? 'Error' : typeof error)
console.warn('[CHECKIN RPC] 异常信息:', error)
console.warn('[CHECKIN RPC] ========== checkinPrecheck END (ERROR) ==========')
// RPC 失败时返回详细错误
const errMsg = error instanceof Error ? error.message : String(error)
return {
success: false,
message: '预校验失败: ' + errMsg,
distanceMeters: null,
allowedRadiusMeters: 0,
canCheckin: false,
reasonCode: 'RPC_ERROR',
workerLocationAccepted: false,
serviceLocationReady: false
}
}
}