完善登录逻辑和个人资料完善
This commit is contained in:
@@ -185,7 +185,15 @@
|
||||
<view class="tabbar-safe-area"></view>
|
||||
</scroll-view>
|
||||
|
||||
<view v-if="currentCartType == 'goods' && cartItems.length > 0" class="fixed-cart-settlement-bar">
|
||||
<view v-if="!isLoggedIn" class="guest-login-bar cart-guest-login-bar">
|
||||
<view class="guest-login-left">
|
||||
<image class="guest-login-avatar" src="/static/images/default.png" mode="aspectFit" />
|
||||
<text class="guest-login-text">登录后可同步购物车中的商品</text>
|
||||
</view>
|
||||
<button class="guest-login-btn" @click.stop="goCartLogin">立即登录</button>
|
||||
</view>
|
||||
|
||||
<view v-if="isLoggedIn && currentCartType == 'goods' && cartItems.length > 0" class="fixed-cart-settlement-bar">
|
||||
<view class="settlement-inner">
|
||||
<view class="settlement-left">
|
||||
<view class="select-all" @click="toggleSelectAll">
|
||||
@@ -337,6 +345,7 @@ const recommendPageSize = ref<number>(8)
|
||||
const recommendHasMore = ref<boolean>(true)
|
||||
const recommendInitialized = ref<boolean>(false)
|
||||
const loading = ref<boolean>(false)
|
||||
const isLoggedIn = ref<boolean>(false)
|
||||
const statusBarHeight = ref(0)
|
||||
const isManageMode = ref(false)
|
||||
const updatingItems = ref<Set<string>>(new Set()) // Track items being updated to prevent race conditions
|
||||
@@ -540,6 +549,9 @@ const emptyTitle = computed((): string => {
|
||||
})
|
||||
|
||||
const emptyDesc = computed((): string => {
|
||||
if (!isLoggedIn.value && currentCartType.value == 'goods') {
|
||||
return '登录后可同步购物车中的商品,换设备也能继续查看'
|
||||
}
|
||||
if (currentCartType.value == 'service') {
|
||||
return '可切换筛选条件,或等待服务购物车正式接入'
|
||||
}
|
||||
@@ -552,6 +564,15 @@ const emptyDesc = computed((): string => {
|
||||
return '快去挑选喜欢的商品吧'
|
||||
})
|
||||
|
||||
function refreshLoginState(): void {
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
isLoggedIn.value = userId != null && userId !== ''
|
||||
}
|
||||
|
||||
function goCartLogin(): void {
|
||||
goToLogin('/pages/main/cart')
|
||||
}
|
||||
|
||||
const showEmptyShoppingBtn = computed((): boolean => {
|
||||
return currentCartType.value == 'goods'
|
||||
})
|
||||
@@ -829,6 +850,15 @@ function onRecommendScroll(event: any): void {
|
||||
// 加载数据
|
||||
const loadCartData = async () => {
|
||||
loading.value = true
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
if (userId == null || userId === '') {
|
||||
isLoggedIn.value = false
|
||||
cartItems.value = []
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
isLoggedIn.value = true
|
||||
|
||||
try {
|
||||
// 获取会员折扣信息
|
||||
@@ -892,6 +922,7 @@ const loadCartData = async () => {
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
refreshLoginState()
|
||||
loadCartData()
|
||||
})
|
||||
|
||||
@@ -1692,6 +1723,68 @@ const goToCheckout = () => {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.guest-login-bar {
|
||||
position: fixed;
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
bottom: calc(var(--window-bottom) + 12px);
|
||||
height: 48px;
|
||||
padding: 0 8px 0 10px;
|
||||
border-radius: 24px;
|
||||
background-color: rgba(45, 38, 42, 0.72);
|
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.cart-guest-login-bar {
|
||||
background-color: rgba(55, 41, 43, 0.76);
|
||||
}
|
||||
|
||||
.guest-login-left {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.guest-login-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
margin-right: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.guest-login-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
lines: 1;
|
||||
}
|
||||
|
||||
.guest-login-btn {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 14px;
|
||||
border-radius: 16px;
|
||||
background-color: #ff4d31;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.guest-login-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 购物车商品列表 */
|
||||
.cart-list {
|
||||
background-color: transparent; /* 背景透明,因为每个店铺有自己的卡片 */
|
||||
@@ -2491,7 +2584,7 @@ const goToCheckout = () => {
|
||||
}
|
||||
|
||||
.tabbar-safe-area {
|
||||
height: 150px;
|
||||
height: 166px;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@@ -205,6 +205,14 @@
|
||||
<view class="profile-bottom-safe"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view v-if="!isLoggedIn" class="guest-login-bar">
|
||||
<view class="guest-login-left">
|
||||
<image class="guest-login-avatar" src="/static/images/default.png" mode="aspectFit" />
|
||||
<text class="guest-login-text">登录一下,康养权益和订单记录同步保存~</text>
|
||||
</view>
|
||||
<button class="guest-login-btn" @click.stop="goProfileLogin">立即登录</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -332,6 +340,7 @@ export default {
|
||||
recommendBottomLocked: false,
|
||||
recommendViewportHeight: 0,
|
||||
pageWindowHeight: 0,
|
||||
isLoggedIn: false,
|
||||
guessLoadMoreKey: 0,
|
||||
statusBarHeight: 0,
|
||||
isAndroidApp: false,
|
||||
@@ -362,6 +371,7 @@ export default {
|
||||
},
|
||||
onLoad() {
|
||||
this.initPage()
|
||||
this.refreshLoginState()
|
||||
this.loadUserProfile()
|
||||
this.loadOrders()
|
||||
|
||||
@@ -370,6 +380,7 @@ export default {
|
||||
uni.$on('authChanged', this.handleAuthChanged)
|
||||
},
|
||||
onShow() {
|
||||
this.refreshLoginState()
|
||||
this.refreshData()
|
||||
},
|
||||
onUnload() {
|
||||
@@ -413,6 +424,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refreshLoginState() {
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
this.isLoggedIn = userId != null && userId !== ''
|
||||
},
|
||||
|
||||
toRecommendScrollJson(value: any | null): UTSJSONObject | null {
|
||||
if (value == null) {
|
||||
return null
|
||||
@@ -851,6 +867,7 @@ export default {
|
||||
return 'height:' + this.pageWindowHeight + 'px;min-height:' + this.pageWindowHeight + 'px;'
|
||||
},
|
||||
async loadUserProfile() {
|
||||
this.refreshLoginState()
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
if (userId == null || userId === '') {
|
||||
this.resetGuestProfileState()
|
||||
@@ -969,6 +986,7 @@ export default {
|
||||
},
|
||||
|
||||
refreshData() {
|
||||
this.refreshLoginState()
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
if (userId == null || userId === '') {
|
||||
this.resetGuestProfileState()
|
||||
@@ -1391,13 +1409,17 @@ export default {
|
||||
editProfile() {
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
if (userId == null || userId === '') {
|
||||
goToLogin('/pages/user/profile')
|
||||
this.goProfileLogin()
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/profile'
|
||||
})
|
||||
},
|
||||
|
||||
goProfileLogin() {
|
||||
goToLogin('/pages/main/profile')
|
||||
},
|
||||
|
||||
// 跳转设置
|
||||
goToSettings() {
|
||||
@@ -1667,6 +1689,7 @@ export default {
|
||||
},
|
||||
|
||||
handleAuthChanged(data: any) {
|
||||
this.refreshLoginState()
|
||||
let payload: UTSJSONObject | null = null
|
||||
|
||||
if (data instanceof UTSJSONObject) {
|
||||
@@ -1687,6 +1710,11 @@ export default {
|
||||
}
|
||||
|
||||
const loggedIn = payload.getBoolean('loggedIn')
|
||||
if (loggedIn === true) {
|
||||
this.refreshData()
|
||||
return
|
||||
}
|
||||
|
||||
if (loggedIn === false) {
|
||||
this.resetGuestProfileState()
|
||||
}
|
||||
@@ -2492,7 +2520,65 @@ export default {
|
||||
}
|
||||
|
||||
.profile-bottom-safe {
|
||||
height: 90px;
|
||||
height: 156px;
|
||||
}
|
||||
|
||||
.guest-login-bar {
|
||||
position: fixed;
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
bottom: calc(var(--window-bottom) + 12px);
|
||||
height: 48px;
|
||||
padding: 0 8px 0 10px;
|
||||
border-radius: 24px;
|
||||
background-color: rgba(45, 38, 42, 0.72);
|
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.guest-login-left {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.guest-login-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
margin-right: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.guest-login-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
lines: 1;
|
||||
}
|
||||
|
||||
.guest-login-btn {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 14px;
|
||||
border-radius: 16px;
|
||||
background-color: #ff6a4d;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.guest-login-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.pending {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<text class="empty-text">未找到评估信息</text>
|
||||
</view>
|
||||
<view v-else>
|
||||
<ServicePanel title="上门评估" subtitle="先用 mock 表单承接风险等级、护理等级和评估结论。">
|
||||
<ServicePanel title="上门评估" subtitle="基于真实服务单补充风险等级、护理等级和评估结论。">
|
||||
<ServiceInfoList
|
||||
:items="[
|
||||
{ label: '服务单号:', value: detail.caseNo },
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<text class="empty-text">未找到服务方案</text>
|
||||
</view>
|
||||
<view v-else>
|
||||
<ServicePanel title="服务方案" subtitle="先用 mock 数据完成计划频次、周期和执行说明。">
|
||||
<ServicePanel title="服务方案" subtitle="基于真实服务单补充频次、周期和执行说明。">
|
||||
<ServiceInfoList
|
||||
:items="[
|
||||
{ label: '服务单号:', value: detail.caseNo },
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
<script setup lang="uts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import ServicePageScaffold from '@/components/homeService/ServicePageScaffold.uvue'
|
||||
import ServicePanel from '@/components/homeService/ServicePanel.uvue'
|
||||
import ServiceStatusTag from '@/components/homeService/ServiceStatusTag.uvue'
|
||||
@@ -193,6 +193,10 @@ onLoad((options) => {
|
||||
}
|
||||
loadData()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<ServicePageScaffold title="到岗签到" fallback-url="/pages/mall/merchant/home-service/tasks">
|
||||
<ServicePanel title="到岗签到" subtitle="先用 mock 方式记录签到结果、到岗说明和留痕提示。">
|
||||
<ServicePanel title="到岗签到" subtitle="记录真实签到结果、到岗说明和执行留痕提示。">
|
||||
<text class="info">任务编号:{{ taskNo }}</text>
|
||||
<text class="info">当前状态:{{ taskStatus }}</text>
|
||||
<view class="block">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<ServicePageScaffold title="异常上报" fallback-url="/pages/mall/merchant/home-service/tasks">
|
||||
<ServicePanel title="异常上报" subtitle="先完成异常类型、说明和调度通知的 mock 处理。">
|
||||
<ServicePanel title="异常上报" subtitle="提交真实异常类型、说明和调度协同信息。">
|
||||
<text class="info">任务编号:{{ taskNo }}</text>
|
||||
<view class="block">
|
||||
<text class="label">异常类型</text>
|
||||
|
||||
@@ -70,6 +70,10 @@ async function handleAdvance() {
|
||||
goCheckIn()
|
||||
return
|
||||
}
|
||||
if (detail.value != null && detail.value.status != 'serving') {
|
||||
uni.showToast({ title: '当前任务无需更新', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const result = await advanceWorkerTask(taskId.value)
|
||||
if (result != null) {
|
||||
detail.value = result
|
||||
|
||||
@@ -237,7 +237,7 @@ onLoad((opts) => {
|
||||
uni.setNavigationBarTitle({ title: '服务人员登录' })
|
||||
} else {
|
||||
loginMode.value = 'consumer'
|
||||
uni.setNavigationBarTitle({ title: '用户登录' })
|
||||
uni.setNavigationBarTitle({ title: '登录' })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -499,6 +499,7 @@ const handleLogin = async () => {
|
||||
clearDeliveryAuth()
|
||||
throw new Error(authResult.message != '' ? authResult.message : '服务人员登录失败')
|
||||
}
|
||||
uni.$emit('authChanged', { loggedIn: true })
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
setTimeout(() => {
|
||||
const redirect = redirectPath.value
|
||||
@@ -543,6 +544,7 @@ const handleLogin = async () => {
|
||||
setUserProfile(adminProfile)
|
||||
// uni.setStorageSync('merchant_id', 'admin') // mock removed
|
||||
|
||||
uni.$emit('authChanged', { loggedIn: true })
|
||||
uni.showToast({ title: '管理员登录成功', icon: 'success' })
|
||||
setTimeout(() => {
|
||||
goTargetHome()
|
||||
@@ -649,6 +651,7 @@ const handleLogin = async () => {
|
||||
// 已移除对 shared storage user_id 的依赖
|
||||
const currentSession = supa.getSession()
|
||||
|
||||
uni.$emit('authChanged', { loggedIn: true })
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
|
||||
// 获取并上报推送 CID(若可用)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,11 @@ CREATE TABLE IF NOT EXISTS public.ak_users (
|
||||
bio text,
|
||||
avatar_url text,
|
||||
preferred_language text,
|
||||
health_goal text,
|
||||
service_address text,
|
||||
emergency_contact text,
|
||||
chronic_notes text,
|
||||
care_preference text,
|
||||
role text,
|
||||
school_id text,
|
||||
grade_id text,
|
||||
@@ -44,6 +49,11 @@ COMMENT ON COLUMN public.ak_users.weight_kg IS '体重(公斤)';
|
||||
COMMENT ON COLUMN public.ak_users.bio IS '个人简介';
|
||||
COMMENT ON COLUMN public.ak_users.avatar_url IS '头像地址';
|
||||
COMMENT ON COLUMN public.ak_users.preferred_language IS '偏好语言';
|
||||
COMMENT ON COLUMN public.ak_users.health_goal IS '健康目标';
|
||||
COMMENT ON COLUMN public.ak_users.service_address IS '常住服务地址';
|
||||
COMMENT ON COLUMN public.ak_users.emergency_contact IS '紧急联系人';
|
||||
COMMENT ON COLUMN public.ak_users.chronic_notes IS '慢病或过敏备注';
|
||||
COMMENT ON COLUMN public.ak_users.care_preference IS '护理偏好';
|
||||
COMMENT ON COLUMN public.ak_users.role IS '角色(如 customer/merchant/admin 等)';
|
||||
COMMENT ON COLUMN public.ak_users.school_id IS '学校ID(可选)';
|
||||
COMMENT ON COLUMN public.ak_users.grade_id IS '年级ID(可选)';
|
||||
|
||||
@@ -10,10 +10,17 @@ export type UserProfile ={
|
||||
bio?: string;
|
||||
avatar_url?: string;
|
||||
preferred_language?: string;
|
||||
health_goal?: string;
|
||||
service_address?: string;
|
||||
emergency_contact?: string;
|
||||
chronic_notes?: string;
|
||||
care_preference?: string;
|
||||
role?:string;
|
||||
school_id?: string; // 所属学校ID
|
||||
grade_id?: string; // 所属年级ID
|
||||
class_id?: string; // 所属班级ID
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
// 语言选项类型 - 对应 ak_languages 表
|
||||
|
||||
Reference in New Issue
Block a user