256 lines
8.2 KiB
Plaintext
256 lines
8.2 KiB
Plaintext
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
|
||
}
|
||
}
|
||
}
|