From 2f528c049f0c4d15f4ef98d4678626bc1a60f209 Mon Sep 17 00:00:00 2001 From: huangzhenbao <17818024429@163.com> Date: Tue, 26 May 2026 17:04:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A6=96=E9=A1=B5=E5=8A=A0?= =?UTF-8?q?=E8=BD=BDskeleton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/home-skeleton/home-skeleton.uvue | 368 ++++++++++++++ components/home/HomeMallContent.uvue | 56 ++- components/home/JdLikeHomeHeader.uvue | 34 +- .../20_rls/delivery/ak_delivery_rls_v2.sql | 29 +- .../20260515_delivery_staff_v2_minimal.sql | 24 + ...26_user_profile_language_preference_fk.sql | 42 ++ pages/main/index.uvue | 167 +++++- pages/user/profile.uvue | 361 ++++++++++--- services/serviceOrderService.uts | 475 ++++++++++++------ 报错信息.txt | 183 +------ 10 files changed, 1329 insertions(+), 410 deletions(-) create mode 100644 components/home-skeleton/home-skeleton.uvue create mode 100644 mall_sql/migrations/20260526_user_profile_language_preference_fk.sql diff --git a/components/home-skeleton/home-skeleton.uvue b/components/home-skeleton/home-skeleton.uvue new file mode 100644 index 00000000..f37082d1 --- /dev/null +++ b/components/home-skeleton/home-skeleton.uvue @@ -0,0 +1,368 @@ + + + + + \ No newline at end of file diff --git a/components/home/HomeMallContent.uvue b/components/home/HomeMallContent.uvue index 5a1375a4..f0893dd3 100644 --- a/components/home/HomeMallContent.uvue +++ b/components/home/HomeMallContent.uvue @@ -100,9 +100,11 @@ @click="emit('select-product', product)" > + @@ -137,11 +139,11 @@ - + 正在加载商品... - + {{ emptyStateDescription }} @@ -168,6 +170,7 @@ import type { MarketingChannel, ChannelProduct, SimpleCategoryChannel } from '@/ const failedProductImageIds = ref([]) const failedChannelImageIds = ref([]) +const loadedProductImageIds = ref([]) type SecondaryCategoryPage = { id: string @@ -199,6 +202,10 @@ const props = defineProps({ type: Array, default: [] as Array }, + pageLoading: { + type: Boolean, + default: false + }, loading: { type: Boolean, default: false @@ -339,11 +346,28 @@ function handleProductImageError(productId: string): void { if (productId == '') { return } + handleProductImageLoad(productId) if (failedProductImageIds.value.indexOf(productId) == -1) { failedProductImageIds.value.push(productId) } } +function handleProductImageLoad(productId: string): void { + if (productId == '') { + return + } + if (loadedProductImageIds.value.indexOf(productId) == -1) { + loadedProductImageIds.value.push(productId) + } +} + +function isProductImageLoaded(productId: string): boolean { + if (productId == '') { + return false + } + return loadedProductImageIds.value.indexOf(productId) != -1 +} + function getProductTitle(product: Product): string { if (product.short_title != null && product.short_title != '') { return product.short_title @@ -777,6 +801,17 @@ function showMarketPrice(product: Product): boolean { background: #f2f2f2; } +.hmall-product-image-placeholder { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: linear-gradient(90deg, #edf0f4 0%, #f9fbfd 48%, #edf0f4 100%); + background-size: 220% 100%; + animation: hmall-image-shimmer 1.35s ease-in-out infinite; +} + .hmall-product-image { position: absolute; top: 0; @@ -784,6 +819,12 @@ function showMarketPrice(product: Product): boolean { width: 100%; height: 100%; border-radius: 18rpx 18rpx 0 0; + opacity: 0; + transition: opacity 220ms ease; +} + +.hmall-product-image-loaded { + opacity: 1; } .hmall-product-image-wrapper-fixed { @@ -795,6 +836,15 @@ function showMarketPrice(product: Product): boolean { background: #ffffff; } +@keyframes hmall-image-shimmer { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -20% 0; + } +} + .hmall-product-body { padding: 14rpx 14rpx 16rpx; background: #ffffff; diff --git a/components/home/JdLikeHomeHeader.uvue b/components/home/JdLikeHomeHeader.uvue index 2b1d1cdf..e7e1fdaa 100644 --- a/components/home/JdLikeHomeHeader.uvue +++ b/components/home/JdLikeHomeHeader.uvue @@ -4,12 +4,10 @@ {{ item.label }} - @@ -121,17 +119,27 @@ function handleSearch() { padding-right: 24rpx; height: 62rpx; box-sizing: border-box; + padding-top: 6rpx; } .jd2-module-item { align-items: center; justify-content: center; - height: 62rpx; - margin-right: 36rpx; + min-width: 132rpx; + height: 56rpx; + margin-right: 20rpx; + padding-left: 24rpx; + padding-right: 24rpx; + border-radius: 999rpx; + background-color: #eceff3; + border-width: 2rpx; + border-style: solid; + border-color: transparent; + box-sizing: border-box; } .jd2-module-item-service { - margin-right: 28rpx; + margin-right: 20rpx; } .jd2-module-text { @@ -155,16 +163,18 @@ function handleSearch() { color: #0f766e; } +.jd2-module-item-active { + border-color: rgba(215, 39, 39, 0.16); + background-color: #fef2f2; + box-shadow: 0 10rpx 22rpx rgba(215, 39, 39, 0.08); +} + .jd2-module-line { - margin-top: 8rpx; - width: 32rpx; - height: 6rpx; - border-radius: 999rpx; - background: #e2231a; + display: none; } .jd2-module-line-service { - background: #16a085; + display: none; } .jd2-search-wrap { diff --git a/docs/sql/20_rls/delivery/ak_delivery_rls_v2.sql b/docs/sql/20_rls/delivery/ak_delivery_rls_v2.sql index f6270a4a..6e552012 100644 --- a/docs/sql/20_rls/delivery/ak_delivery_rls_v2.sql +++ b/docs/sql/20_rls/delivery/ak_delivery_rls_v2.sql @@ -11,6 +11,7 @@ ALTER TABLE public.ml_delivery_stations ENABLE ROW LEVEL SECURITY; -- 清理旧策略 DROP POLICY IF EXISTS delivery_staff_self_select ON public.ml_delivery_staff; +DROP POLICY IF EXISTS delivery_staff_self_update ON public.ml_delivery_staff; DROP POLICY IF EXISTS delivery_stations_select_active ON public.ml_delivery_stations; -- 1. 执行人员本人可直读自己的未删除档案 @@ -28,11 +29,35 @@ CREATE POLICY delivery_staff_self_select ) ); --- 2. 提货点/机构对前台保持只读,仅返回启用且未删除数据 +-- 2. 执行人员本人可更新自己的在线状态等自有档案字段 +CREATE POLICY delivery_staff_self_update + ON public.ml_delivery_staff + FOR UPDATE + TO authenticated + USING ( + deleted_at IS NULL + AND EXISTS ( + SELECT 1 + FROM public.ak_users u + WHERE u.id = ml_delivery_staff.uid + AND u.auth_id = auth.uid() + ) + ) + WITH CHECK ( + deleted_at IS NULL + AND EXISTS ( + SELECT 1 + FROM public.ak_users u + WHERE u.id = ml_delivery_staff.uid + AND u.auth_id = auth.uid() + ) + ); + +-- 3. 提货点/机构对前台保持只读,仅返回启用且未删除数据 CREATE POLICY delivery_stations_select_active ON public.ml_delivery_stations FOR SELECT TO anon, authenticated USING (status = 1 AND deleted_at IS NULL); --- 3. 其余直连写操作默认不开放,管理端统一走 SECURITY DEFINER RPC +-- 4. 其余直连写操作默认不开放,管理端统一走 SECURITY DEFINER RPC diff --git a/mall_sql/migrations/20260515_delivery_staff_v2_minimal.sql b/mall_sql/migrations/20260515_delivery_staff_v2_minimal.sql index 98c29b33..53baa24e 100644 --- a/mall_sql/migrations/20260515_delivery_staff_v2_minimal.sql +++ b/mall_sql/migrations/20260515_delivery_staff_v2_minimal.sql @@ -79,6 +79,7 @@ ALTER TABLE public.ml_delivery_staff ENABLE ROW LEVEL SECURITY; ALTER TABLE public.ml_delivery_stations ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS delivery_staff_self_select ON public.ml_delivery_staff; +DROP POLICY IF EXISTS delivery_staff_self_update ON public.ml_delivery_staff; CREATE POLICY delivery_staff_self_select ON public.ml_delivery_staff FOR SELECT @@ -93,6 +94,29 @@ CREATE POLICY delivery_staff_self_select ) ); +CREATE POLICY delivery_staff_self_update + ON public.ml_delivery_staff + FOR UPDATE + TO authenticated + USING ( + deleted_at IS NULL + AND EXISTS ( + SELECT 1 + FROM public.ak_users u + WHERE u.id = ml_delivery_staff.uid + AND u.auth_id = auth.uid() + ) + ) + WITH CHECK ( + deleted_at IS NULL + AND EXISTS ( + SELECT 1 + FROM public.ak_users u + WHERE u.id = ml_delivery_staff.uid + AND u.auth_id = auth.uid() + ) + ); + DROP POLICY IF EXISTS delivery_stations_select_active ON public.ml_delivery_stations; CREATE POLICY delivery_stations_select_active ON public.ml_delivery_stations diff --git a/mall_sql/migrations/20260526_user_profile_language_preference_fk.sql b/mall_sql/migrations/20260526_user_profile_language_preference_fk.sql new file mode 100644 index 00000000..474cc9ef --- /dev/null +++ b/mall_sql/migrations/20260526_user_profile_language_preference_fk.sql @@ -0,0 +1,42 @@ +begin; + +alter table if exists public.ak_users + drop constraint if exists ak_users_preferred_language_fkey; + +alter table if exists public.ak_users + add constraint ak_users_preferred_language_fkey + foreign key (preferred_language) + references public.ak_languages (id) + on update cascade + on delete set null; + +create index if not exists idx_ak_users_preferred_language + on public.ak_users (preferred_language); + +alter table if exists public.ak_languages enable row level security; + +do $$ +begin + if exists ( + select 1 + from pg_class c + join pg_namespace n on n.oid = c.relnamespace + where n.nspname = 'public' + and c.relname = 'ak_languages' + and c.relkind = 'r' + ) and not exists ( + select 1 + from pg_policies + where schemaname = 'public' + and tablename = 'ak_languages' + and policyname = 'ak_languages_active_select' + ) then + create policy ak_languages_active_select + on public.ak_languages + for select + using (is_active = true); + end if; +end +$$; + +commit; diff --git a/pages/main/index.uvue b/pages/main/index.uvue index 28d53e36..af1c6f83 100644 --- a/pages/main/index.uvue +++ b/pages/main/index.uvue @@ -1,6 +1,7 @@  @@ -228,6 +246,7 @@ import { ref, reactive, onMounted, onUnmounted, computed } from 'vue' import { onShow, onLoad, onHide } from '@dcloudio/uni-app' import HomeMallContent from '@/components/home/HomeMallContent.uvue' import JdLikeHomeHeader from '@/components/home/JdLikeHomeHeader.uvue' +import HomeSkeleton from '@/components/home-skeleton/home-skeleton.uvue' import { fetchHomeServiceCatalog } from '@/services/homeServiceService.uts' import type { HomeServiceCatalogType } from '@/types/home-service.uts' import supabaseService from '@/utils/supabaseService.uts' @@ -246,6 +265,11 @@ const refreshing = ref(false) const loading = ref(false) const isFirstShow = ref(true) const hasMore = ref(true) +const pageLoading = ref(true) +const goodsLoaded = ref(false) +const categoryLoaded = ref(false) +const bannerLoaded = ref(false) +const skeletonExiting = ref(false) const activeSort = ref('recommend') // 默认展示智能推荐 const activeFilter = ref('recommend') const currentPage = ref(1) @@ -598,6 +622,11 @@ const nextPlaceholderKeyword = ref(placeholderKeywords.value.length > 1 ? placeh const placeholderAnimating = ref(false) let placeholderTimer: number = 0 let placeholderAnimationTimer: number = 0 +let skeletonTimer: number = 0 + +const showHomeSkeleton = computed((): boolean => { + return pageLoading.value || skeletonExiting.value +}) const homeEmptyStateTitle = computed((): string => { if (currentFeedCategoryId.value == 'recommend') { @@ -660,6 +689,42 @@ function stopPlaceholderScroll(): void { } } +function resetInitialHomeLoadFlags(): void { + goodsLoaded.value = false + categoryLoaded.value = false + bannerLoaded.value = false +} + +function clearSkeletonTimer(): void { + if (skeletonTimer != 0) { + clearTimeout(skeletonTimer) + skeletonTimer = 0 + } +} + +function beginHomeSkeleton(): void { + clearSkeletonTimer() + pageLoading.value = true + skeletonExiting.value = false +} + +function finishHomeSkeleton(): void { + if (!pageLoading.value) { + return + } + pageLoading.value = false + skeletonExiting.value = true + clearSkeletonTimer() + skeletonTimer = setTimeout(() => { + skeletonExiting.value = false + skeletonTimer = 0 + }, 280) +} + +async function loadHomeBannerData(): Promise { + return +} + function startPlaceholderScroll(): void { try { if (placeholderTimer != 0) { @@ -1910,9 +1975,17 @@ const searchByKeyword = (keyword: string): void => { } // 初始化数据 -const initData = async () => { +type InitDataOptions = { + showSkeleton: boolean +} + +const initData = async (options: InitDataOptions = { showSkeleton: false }) => { logSupaConfig() console.log('[consumer-db] 首页开始加载数据') + resetInitialHomeLoadFlags() + if (options.showSkeleton) { + beginHomeSkeleton() + } // 首先确保用户资料已加载 try { await getCurrentUser() @@ -1920,16 +1993,50 @@ const initData = async () => { } catch (error) { console.error('加载用户资料失败:', error) } - await loadMedicalMallCategories() - await loadBrands() - await loadHotKeywords() - await loadServiceHomeData() - if (await consumeSelectedCategoryFromStorage()) { - await loadRecommendedProducts(defaultLoadLimit) - return + const categoryTask = (async (): Promise => { + try { + await loadMedicalMallCategories() + } finally { + categoryLoaded.value = true + } + })() + const bannerTask = (async (): Promise => { + try { + await loadHomeBannerData() + } finally { + bannerLoaded.value = true + } + })() + const goodsTask = (async (): Promise => { + try { + await categoryTask + if (!(await consumeSelectedCategoryFromStorage())) { + await loadCategoryGoods(currentCategory.value) + } + } finally { + goodsLoaded.value = true + } + })() + const supplementTask = (async (): Promise => { + await Promise.all([ + loadBrands(), + loadHotKeywords(), + loadServiceHomeData() + ]) + try { + await loadRecommendedProducts(defaultLoadLimit) + } catch (error) { + console.error('加载推荐频道商品失败:', error) + recommendedProducts.value = [] + } + })() + try { + await Promise.all([categoryTask, goodsTask, bannerTask, supplementTask]) + } finally { + if (options.showSkeleton && categoryLoaded.value && goodsLoaded.value && bannerLoaded.value) { + finishHomeSkeleton() + } } - await loadCategoryGoods(currentCategory.value) - await loadRecommendedProducts(defaultLoadLimit) } @@ -2035,7 +2142,7 @@ const initPage = () => { // 生命周期 onMounted(() => { initPage() - initData() + void initData({ showSkeleton: true }) startPlaceholderScroll() }) @@ -2085,6 +2192,7 @@ onHide(() => { onUnmounted(() => { stopPlaceholderScroll() + clearSkeletonTimer() }) // 处理滚动事件 @@ -2202,7 +2310,7 @@ const onRefresh = async () => { try { // 重新加载数据 - await initData() + await initData({ showSkeleton: false }) } catch (e) { console.error('刷新数据失败:', e) } finally { @@ -2432,6 +2540,41 @@ const navigateToReminders = () => uni.navigateTo({ url: '/pages/user/reminders' flex-direction: column; } +.home-main-stage { + flex: 1; + min-height: 0; + transition: opacity 260ms ease; +} + +.home-main-stage-hidden { + opacity: 0; +} + +.home-main-stage-visible { + opacity: 1; +} + +.home-skeleton-overlay { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: 1200; + background: #f6f8fb; + transition: opacity 260ms ease; +} + +.home-skeleton-overlay-visible { + opacity: 1; + pointer-events: auto; +} + +.home-skeleton-overlay-leaving { + opacity: 0; + pointer-events: none; +} + .jd-header-fixed { position: fixed; top: 0; diff --git a/pages/user/profile.uvue b/pages/user/profile.uvue index 85548c9f..cf6557c7 100644 --- a/pages/user/profile.uvue +++ b/pages/user/profile.uvue @@ -146,7 +146,7 @@ 语言偏好 - {{ getLanguageText(profile.preferred_language) }} + {{ getPreferredLanguageText() }} @@ -225,8 +225,8 @@ - - {{ getLanguageText(language) }} + + {{ language.label }} @@ -317,19 +317,41 @@ diff --git a/services/serviceOrderService.uts b/services/serviceOrderService.uts index 493d1c0e..6a76a434 100644 --- a/services/serviceOrderService.uts +++ b/services/serviceOrderService.uts @@ -3,6 +3,7 @@ import { getCurrentUserId } from '@/utils/store.uts' import { getCurrentUser } from '@/utils/store.uts' import type { UserAddress } from '@/utils/supabaseService.uts' import type { HomeServiceCatalogType } from '@/types/home-service.uts' +import type { DeliveryServiceRecordType } from '@/types/delivery.uts' import { getServiceOrderStatusText, normalizeServiceOrderStatus, @@ -38,6 +39,25 @@ function buildId(prefix: string): string { return prefix + '-' + String(Date.now()) + '-' + String(Math.floor(Math.random() * 100000)).padStart(5, '0') } +function buildHex(length: number): string { + const chars = '0123456789abcdef' + let result = '' + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)) + } + return result +} + +function buildUuidLike(): string { + const segment1 = buildHex(8) + const segment2 = buildHex(4) + const segment3 = '4' + buildHex(3) + const variants = '89ab' + const segment4 = variants.charAt(Math.floor(Math.random() * variants.length)) + buildHex(3) + const segment5 = buildHex(12) + return segment1 + '-' + segment2 + '-' + segment3 + '-' + segment4 + '-' + segment5 +} + function buildOrderNo(): string { const date = new Date() const y = String(date.getFullYear()) @@ -144,6 +164,17 @@ function safeJsonField(source: any, key: string): string { return JSON.stringify(value) } +function safeFirstJsonField(source: any, keys: Array): string { + const plain = JSON.parse(JSON.stringify(source)) as any + for (let i = 0; i < keys.length; i++) { + const value = plain[keys[i]] + if (value != null) { + return JSON.stringify(value) + } + } + return '' +} + function plainObject(source: any): any { return JSON.parse(JSON.stringify(source)) as any } @@ -168,6 +199,171 @@ function readNumber(source: any, key: string): number { return 0 } +function hasMissingColumnError(error: any, columnName: string): boolean { + if (error == null || columnName == '') { + return false + } + const errorText = JSON.stringify(error).toLowerCase() + return errorText.indexOf('could not find the') >= 0 && errorText.indexOf(columnName.toLowerCase()) >= 0 +} + +function shouldUseCareTaskPath(orderId: string): boolean { + return isUuidLike(orderId) +} + +function isStaffActive(staff: any): boolean { + const plain = plainObject(staff) + if (plain['deleted_at'] != null && String(plain['deleted_at']) != '') { + return false + } + if (plain['is_active'] === false) { + return false + } + return readNumber(staff, 'status') == 1 +} + +function getStaffPriority(staff: any): number { + let score = 0 + const onlineStatus = readString(staff, 'online_status') + if (onlineStatus == 'online') { + score += 30 + } else if (onlineStatus == 'resting' || onlineStatus == '') { + score += 20 + } else if (onlineStatus == 'busy') { + score += 10 + } + if (readString(staff, 'uid') != '') { + score += 5 + } + if (readString(staff, 'station_id') != '') { + score += 1 + } + return score +} + +async function getAutoAssignableStaff(): Promise { + const staffResponse = await supa + .from('ml_delivery_staff') + .select('id, uid, station_id, nickname, phone, status, deleted_at, is_active, online_status, updated_at, created_at') + .eq('status', 1) + .execute() + if (staffResponse.error != null || staffResponse.data == null) { + return null + } + const rawStaffList = staffResponse.data as Array + let selected: any = null + let bestScore = -1 + let bestTime = '' + for (let i = 0; i < rawStaffList.length; i++) { + const staff = rawStaffList[i] + if (!isStaffActive(staff)) { + continue + } + const score = getStaffPriority(staff) + const timeMark = readFirstString(staff, ['updated_at', 'created_at']) + if (selected == null || score > bestScore || (score == bestScore && timeMark > bestTime)) { + selected = staff + bestScore = score + bestTime = timeMark + } + } + return selected +} + +function buildEcServiceRequestPayload(params: CreateServiceOrderParams, userId: string, requestId: string, createdAt: string, appointmentTime: string | null, useAddressSnapshot: boolean): any { + const payload = { + id: requestId, + user_id: userId, + service_catalog_id: params.service.id, + service_name: params.service.name, + service_category: params.service.category, + elder_name: params.recipientName, + elder_phone: params.recipientPhone, + contact_name: params.contactName, + contact_phone: params.contactPhone, + scheduled_at: appointmentTime, + remark: params.remark, + status: 'ORDER_CREATED', + created_at: createdAt, + updated_at: createdAt + } as any + if (useAddressSnapshot) { + payload.address_snapshot = params.address as any + } else { + payload.address_snapshot_json = params.address as any + } + return payload +} + +function buildEcServiceRequestPayloadWithoutAddress(params: CreateServiceOrderParams, userId: string, requestId: string, createdAt: string, appointmentTime: string | null): any { + return { + id: requestId, + user_id: userId, + service_catalog_id: params.service.id, + service_name: params.service.name, + service_category: params.service.category, + elder_name: params.recipientName, + elder_phone: params.recipientPhone, + contact_name: params.contactName, + contact_phone: params.contactPhone, + scheduled_at: appointmentTime, + remark: params.remark, + status: 'ORDER_CREATED', + created_at: createdAt, + updated_at: createdAt + } as any +} + +function buildEcCareTaskPayload(params: CreateServiceOrderParams, userId: string, requestId: string, taskId: string, taskNo: string, createdAt: string, appointmentTime: string | null, useAddressSnapshot: boolean): any { + const payload = { + id: taskId, + task_no: taskNo, + request_id: requestId, + user_id: userId, + service_catalog_id: params.service.id, + service_name: params.service.name, + service_category: params.service.category, + service_snapshot_json: params.service as any, + elder_name: params.recipientName, + elder_phone: params.recipientPhone, + contact_name: params.contactName, + contact_phone: params.contactPhone, + scheduled_at: appointmentTime, + remark: params.remark, + status: 'ORDER_CREATED', + created_at: createdAt, + updated_at: createdAt + } as any + if (useAddressSnapshot) { + payload.address_snapshot = params.address as any + } else { + payload.address_snapshot_json = params.address as any + } + return payload +} + +function buildEcCareTaskPayloadWithoutAddress(params: CreateServiceOrderParams, userId: string, requestId: string, taskId: string, taskNo: string, createdAt: string, appointmentTime: string | null): any { + return { + id: taskId, + task_no: taskNo, + request_id: requestId, + user_id: userId, + service_catalog_id: params.service.id, + service_name: params.service.name, + service_category: params.service.category, + service_snapshot_json: params.service as any, + elder_name: params.recipientName, + elder_phone: params.recipientPhone, + contact_name: params.contactName, + contact_phone: params.contactPhone, + scheduled_at: appointmentTime, + remark: params.remark, + status: 'ORDER_CREATED', + created_at: createdAt, + updated_at: createdAt + } as any +} + function parseTimeline(item: any): ServiceOrderTimelineItemType { return { id: readString(item, 'id'), @@ -231,7 +427,7 @@ function parseEvidenceFile(item: any): ServiceEvidenceFileType { } function parseServiceOrder(item: any, logs: Array, review: ServiceReviewType | null): ServiceOrderType { - const addressSnapshot = safeJsonField(item, 'address_snapshot_json') + const addressSnapshot = safeFirstJsonField(item, ['address_snapshot_json', 'address_snapshot']) const serviceSnapshot = safeJsonField(item, 'service_snapshot_json') const addressObj = plainObject(safeParseObject(addressSnapshot)) const serviceObj = plainObject(safeParseObject(serviceSnapshot)) @@ -354,7 +550,7 @@ function readJsonObjectField(source: any, keys: Array): any { function mapCareTaskRowToLegacyOrderRow(item: any): any { const serviceSnapshotValue = readJsonObjectField(item, ['service_snapshot_json']) - const addressSnapshotValue = readJsonObjectField(item, ['address_snapshot_json']) + const addressSnapshotValue = readJsonObjectField(item, ['address_snapshot', 'address_snapshot_json']) let derivedStatus = readString(item, 'status') if (readFirstString(item, ['accepted_by_family_at']) != '') { derivedStatus = 'ACCEPTED' @@ -478,6 +674,9 @@ function buildLegacyExecutionRecord(taskId: string, records: Array): Servic } async function getCareTaskDetail(taskId: string): Promise { + if (!isUuidLike(taskId)) { + return null + } const taskResponse = await supa.from('ec_care_tasks').select('*').eq('id', taskId).limit(1).execute() if (taskResponse.error != null || taskResponse.data == null) { return null @@ -545,74 +744,54 @@ async function tryCreateCareTask(params: CreateServiceOrderParams): Promise - if (rawStaffList.length > 0) { - const staffObj = rawStaffList[0] - const assignedUserId = readFirstString(staffObj, ['uid', 'id']) - if (assignedUserId != '') { - await supa.from('ec_care_tasks').update({ - status: 'ORDER_ASSIGNED', - assigned_to: assignedUserId, - updated_at: createdAt - }).eq('id', taskId).execute() - await insertWorkOrderEvent(taskId, 'ORDER_CREATED', 'ORDER_ASSIGNED', userId, 'system', 'assign_task', '系统已自动派单') - } + const assignedStaff = await getAutoAssignableStaff() + if (assignedStaff != null) { + const assignedUserId = readString(assignedStaff, 'uid') + if (assignedUserId != '') { + await supa.from('ec_care_tasks').update({ + status: 'ORDER_ASSIGNED', + assigned_to: assignedUserId, + updated_at: createdAt + }).eq('id', taskId).execute() + await insertWorkOrderEvent(taskId, 'ORDER_CREATED', 'ORDER_ASSIGNED', userId, 'system', 'assign_task', '系统已自动派单') } } return await getCareTaskDetail(taskId) @@ -728,22 +907,15 @@ export async function createServiceOrder(params: CreateServiceOrderParams): Prom return null } await insertLegacyStatusLog(orderId, '', 'created', userId, 'consumer', '创建服务订单') - const staffResponse = await supa - .from('ml_delivery_staff') - .select('id, station_id, nickname, phone, status, deleted_at') - .eq('status', 1) - .order('created_at', { ascending: true }) - .execute() - if (staffResponse.data != null) { - const rawStaffList = staffResponse.data as any[] - if (rawStaffList.length > 0) { - const staffObj = plainObject(rawStaffList[0]) + const staffObj = await getAutoAssignableStaff() + if (staffObj != null) { + const plainStaff = plainObject(staffObj) const assignmentId = buildId('sa') await supa.from('hss_service_assignments').insert({ id: assignmentId, order_id: orderId, - staff_id: readString(staffObj, 'id'), - station_id: readString(staffObj, 'station_id') == '' ? null : readString(staffObj, 'station_id'), + staff_id: readString(plainStaff, 'id'), + station_id: readString(plainStaff, 'station_id') == '' ? null : readString(plainStaff, 'station_id'), status: 'assigned', assigned_at: now, created_at: now, @@ -752,11 +924,10 @@ export async function createServiceOrder(params: CreateServiceOrderParams): Prom await supa.from('hss_service_orders').update({ status: 'assigned', current_assignment_id: assignmentId, - current_staff_id: readString(staffObj, 'id'), + current_staff_id: readString(plainStaff, 'id'), updated_at: now }).eq('id', orderId).execute() await insertLegacyStatusLog(orderId, 'created', 'assigned', userId, 'system', '系统已自动派单') - } } return await getLegacyServiceOrderDetail(orderId) } @@ -794,19 +965,94 @@ export async function listConsumerServiceOrders(): Promise { - const careTask = await getCareTaskDetail(orderId) - if (careTask != null) { - return careTask + if (shouldUseCareTaskPath(orderId)) { + const careTask = await getCareTaskDetail(orderId) + if (careTask != null) { + return careTask + } } return await getLegacyServiceOrderDetail(orderId) } +export async function saveServiceRecord(orderId: string, record: DeliveryServiceRecordType): Promise { + const userId = getCurrentUserId() + if (userId == '') { + return null + } + const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null + if (careTask != null) { + const savedAt = nowIso() + const serviceContent = record.serviceContent.length > 0 ? record.serviceContent : record.serviceItems.map(item => item.name) + const serviceSummary = record.serviceSummary != '' ? record.serviceSummary : record.processNote + const healthMetrics = record.healthMetrics as any + const familyConfirmation = record.familyConfirmation as any + const insertResponse = await supa.from('ec_care_records').insert({ + id: buildId('care-record'), + task_id: orderId, + record_type: 'service_record', + created_by: userId, + service_items_json: record.serviceItems as any, + service_content_json: serviceContent as any, + service_summary: serviceSummary, + process_note: record.processNote, + elder_status: record.elderStatus, + health_metrics_json: healthMetrics, + materials_used: record.materialsUsed, + abnormal_note: record.abnormalNote, + photos_json: record.photos as any, + staff_remark: record.staffRemark, + family_confirmation_json: familyConfirmation, + created_at: savedAt, + updated_at: savedAt + }).execute() + if (insertResponse.error != null) { + return null + } + const updateResponse = await supa.from('ec_care_tasks').update({ + updated_at: savedAt + }).eq('id', orderId).execute() + if (updateResponse.error != null) { + return null + } + await insertWorkOrderEvent(orderId, careTask.status, careTask.status, userId, 'staff', 'save_service_record', serviceSummary == '' ? '服务记录已保存' : serviceSummary) + return await getCareTaskDetail(orderId) + } + const current = await getLegacyServiceOrderDetail(orderId) + if (current == null) { + return null + } + const savedAt = nowIso() + const serviceSummary = record.serviceSummary != '' ? record.serviceSummary : record.processNote + const saveResponse = await supa.from('hss_service_execution_records').insert({ + id: buildId('ser'), + order_id: orderId, + checkin_time: current.executionRecord != null ? current.executionRecord.checkin_time : savedAt, + checkin_latitude: current.executionRecord != null ? current.executionRecord.checkin_latitude : 0, + checkin_longitude: current.executionRecord != null ? current.executionRecord.checkin_longitude : 0, + checkin_address: current.executionRecord != null ? current.executionRecord.checkin_address : '', + service_content_json: record.serviceContent.length > 0 ? record.serviceContent as any : record.serviceItems.map(item => item.name) as any, + service_summary: serviceSummary, + completion_images_json: record.photos as any, + signature_image: '', + signature_name: record.familyConfirmation.familyMember, + created_at: savedAt, + updated_at: savedAt + }).execute() + if (saveResponse.error != null) { + return null + } + await supa.from('hss_service_orders').update({ + updated_at: savedAt + }).eq('id', orderId).execute() + return await getLegacyServiceOrderDetail(orderId) +} + export async function confirmServiceOrder(orderId: string, rating: number, content: string, tags: Array): Promise { const userId = getCurrentUserId() if (userId == '') { return null } - const careTask = await getCareTaskDetail(orderId) + const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null if (careTask != null) { const acceptedAt = nowIso() const updateResponse = await supa.from('ec_care_tasks').update({ @@ -870,7 +1116,7 @@ export async function rejectServiceOrderAcceptance(orderId: string, content: str if (userId == '') { return null } - const careTask = await getCareTaskDetail(orderId) + const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null if (careTask != null) { const rejectedAt = nowIso() const updateResponse = await supa.from('ec_care_tasks').update({ @@ -914,75 +1160,4 @@ export async function rejectServiceOrderAcceptance(orderId: string, content: str export async function getCurrentConsumerUser() { return await getCurrentUser() - } - -export async function getOrdersByTab(tab: string): Promise> { - const orders = await listConsumerServiceOrders() - if (tab == 'pending') { - return orders.filter((order) => { - return order.status != 'ACCEPTED' && order.status != 'COMPLETED' && order.status != 'CANCELLED' - }) - } - if (tab == 'history') { - return orders.filter((order) => { - return order.status == 'ACCEPTED' || order.status == 'COMPLETED' || order.status == 'CANCELLED' - }) - } - return orders.filter((order) => { - return order.status != 'ACCEPTED' && order.status != 'COMPLETED' && order.status != 'CANCELLED' - }) - } - -export async function getOrderDetail(orderId: string): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function getDashboard(): Promise { - const orders = await listConsumerServiceOrders() - let pendingCount = 0 - let todayCount = 0 - let completedCount = 0 - for (let i = 0; i < orders.length; i++) { - const order = orders[i] - if (order.status == 'ACCEPTED' || order.status == 'COMPLETED' || order.status == 'CANCELLED') { - completedCount += 1 - } else { - pendingCount += 1 - todayCount += 1 - } - } - return { - pendingCount, - todayCount, - completedCount, - totalCount: orders.length - } as UTSJSONObject - } - -export async function acceptOrder(orderId: string): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function departOrder(orderId: string, _location: any): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function arriveOrder(orderId: string, _location: any): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function checkinOrder(orderId: string, _payload: any): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function startService(orderId: string): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function finishOrder(orderId: string): Promise { - return await getServiceOrderDetail(orderId) - } - -export async function saveServiceRecord(orderId: string, _payload: any): Promise { - return await getServiceOrderDetail(orderId) } \ No newline at end of file diff --git a/报错信息.txt b/报错信息.txt index 1863bc41..275b7d32 100644 --- a/报错信息.txt +++ b/报错信息.txt @@ -1,159 +1,24 @@ -mp.esm.js:529 saveProfile context: {"profileRowId":"b653fded-7d5e-4950-aa0d-725595543e3c","profileId":"b653fded-7d5e-4950-aa0d-725595543e3c","birthday":null,"hasHealthGoal":false,"hasServiceAddress":true} -mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ak_users filter: id=eq.b653fded-7d5e-4950-aa0d-725595543e3c -mp.esm.js:529 [ak-req] PATCH http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c -mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...Tozk | auth-mode: pre-set | prefer: return=representation -uni.api.esm.js:1042 PATCH http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c 400 (Bad Request)(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ uni.api.esm.js:1042 -invokeApi @ uni.api.esm.js:330 -promiseApi @ uni.api.esm.js:889 -(anonymous) @ ak-req.uts:214 -doOnce @ ak-req.uts:213 -_loop$ @ ak-req.uts:328 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -s @ regeneratorRuntime.js?forceSync=true:1 -_ @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -fulfilled @ uni.mp.esm.js:1134 -Promise.then (async) -step @ uni.mp.esm.js:1134 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -request @ ak-req.uts:148 -_callee19$ @ aksupa.uts:1290 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -requestWithAutoRefresh @ aksupa.uts:1289 -_callee14$ @ aksupa.uts:1143 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -update @ aksupa.uts:1119 -_callee$ @ aksupa.uts:477 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -execute @ aksupa.uts:369 -_callee2$ @ profile.uvue:1057 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -saveProfile @ profile.uvue:1015 -callWithErrorHandling @ vue.runtime.esm.js:1356 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1363 -invoke @ vue.runtime.esm.js:6223 -setTimeout (async) -invoker @ vue.runtime.esm.js:6232 -Show 19 more frames -mp.esm.js:529 [ak-req] HTTP error response(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:304 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] status: 400(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:305 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] url: http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:306 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] body: {"code":"22P02","details":null,"hint":null,"message":"invalid input syntax for type uuid: \"zh-CN\""}(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:307 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 saveProfile update ak_users error: {"errSubject":"AppError","errCode":-1,"errMsg":"请求失败: 400"} -mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ak_users filter: id=eq.b653fded-7d5e-4950-aa0d-725595543e3c -mp.esm.js:529 [ak-req] PATCH http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c -mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...Tozk | auth-mode: pre-set | prefer: return=representation -uni.api.esm.js:1042 PATCH http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c 400 (Bad Request)(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ uni.api.esm.js:1042 -invokeApi @ uni.api.esm.js:330 -promiseApi @ uni.api.esm.js:889 -(anonymous) @ ak-req.uts:214 -doOnce @ ak-req.uts:213 -_loop$ @ ak-req.uts:328 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -s @ regeneratorRuntime.js?forceSync=true:1 -_ @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -fulfilled @ uni.mp.esm.js:1134 -Promise.then (async) -step @ uni.mp.esm.js:1134 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -request @ ak-req.uts:148 -_callee19$ @ aksupa.uts:1290 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -requestWithAutoRefresh @ aksupa.uts:1289 -_callee14$ @ aksupa.uts:1143 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -update @ aksupa.uts:1119 -_callee$ @ aksupa.uts:477 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -execute @ aksupa.uts:369 -_callee2$ @ profile.uvue:1071 -s @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -(anonymous) @ regeneratorRuntime.js?forceSync=true:1 -fulfilled @ uni.mp.esm.js:1134 -Promise.then (async) -step @ uni.mp.esm.js:1134 -(anonymous) @ uni.mp.esm.js:1134 -__awaiter @ uni.mp.esm.js:1134 -saveProfile @ profile.uvue:1015 -callWithErrorHandling @ vue.runtime.esm.js:1356 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1363 -invoke @ vue.runtime.esm.js:6223 -setTimeout (async) -invoker @ vue.runtime.esm.js:6232 -mp.esm.js:529 [ak-req] HTTP error response(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:304 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] status: 400(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:305 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] url: http://119.146.131.237:9126/rest/v1/ak_users?id=eq.b653fded-7d5e-4950-aa0d-725595543e3c(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:306 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 [ak-req] body: {"code":"22P02","details":null,"hint":null,"message":"invalid input syntax for type uuid: \"zh-CN\""}(env: Windows,mp,1.06.2504030; lib: 3.16.0) -(anonymous) @ mp.esm.js:529 -__f__ @ uni.api.esm.js:590 -success @ ak-req.uts:307 -(anonymous) @ uni.api.esm.js:946 -mp.esm.js:529 saveProfile fallback update ak_users error: {"errSubject":"AppError","errCode":-1,"errMsg":"请求失败: 400"} \ No newline at end of file +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: uid=eq.67251404-ad43-4118-a6d4-74ca16351427 +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&uid=eq.67251404-ad43-4118-a6d4-74ca16351427 +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] PATCH http://119.146.131.237:9126/rest/v1/ml_delivery_staff?id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: return=representation +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: uid=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&uid=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: uid=eq.67251404-ad43-4118-a6d4-74ca16351427 +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&uid=eq.67251404-ad43-4118-a6d4-74ca16351427 +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] PATCH http://119.146.131.237:9126/rest/v1/ml_delivery_staff?id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: return=representation +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: uid=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&uid=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact +mp.esm.js:529 [AkSupaQueryBuilder] execute - 表: ml_delivery_staff filter: id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] GET http://119.146.131.237:9126/rest/v1/ml_delivery_staff?select=*%2C%20station%3Aml_delivery_stations(id%2C%20name)&limit=1&id=eq.399bc088-ab36-4f68-a993-e34aec421e8c +mp.esm.js:529 [ak-req] apikey: eyJhbG...7890 | Authorization: Bearer eyJhbG...-2B0 | auth-mode: pre-set | prefer: count=exact \ No newline at end of file