From fa4c7baec36d58b4bdca66159ece743b5a45a9c8 Mon Sep 17 00:00:00 2001
From: rk <94314517@qq.com>
Date: 星期四, 11 六月 2026 10:15:45 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 app/pages/login/login.vue |  200 +++++++++++++++++++++++++++++++++++++------------
 1 files changed, 151 insertions(+), 49 deletions(-)

diff --git a/app/pages/login/login.vue b/app/pages/login/login.vue
index 0e9baba..6345df0 100644
--- a/app/pages/login/login.vue
+++ b/app/pages/login/login.vue
@@ -1,57 +1,80 @@
 <template>
-	<view class="login-page">
-		<image class="login-page__bg" src="/static/image/login_bg@2x.png" mode="aspectFill"></image>
-		<view></view>
-
-		<view class="login-page__content">
-			<view class="login-card">
-				<view class="login-card__tabs">
-					<view
-						v-for="item in tabs"
-						:key="item.value"
-						class="login-card__tab"
-						:style="{
-							backgroundImage: returnBackgroundImg(item.value, activeTab === item.value)
-						}"
-						:class="{ 'login-card__tab--active': activeTab === item.value }"
-						@click="activeTab = item.value"
-					>
-						<text class="login-card__tab-text">{{ item.label }}</text>
-						<view v-if="activeTab === item.value" class="login-card__tab-line"></view>
-					</view>
-				</view>
-
-				<view class="login-card__form">
-					<view v-if="activeTab === 'account'" class="login-card__group">
-						<view class="login-card__field">
-							<input v-model="form.telephone" class="login-card__input" type="number" placeholder="璇疯緭鍏ユ墜鏈哄彿" placeholder-style="color: #c5cad4;" />
-						</view>
-						<view class="login-card__field">
-							<input v-model="form.password" class="login-card__input" password placeholder="璇疯緭鍏ュ瘑鐮�" placeholder-style="color: #c5cad4;" />
+	<view>
+		<view class="login-page">
+			<image class="login-page__bg" src="/static/image/login_bg@2x.png" mode="aspectFill"></image>
+			<view></view>
+		
+			<view class="login-page__content">
+				<view class="login-card">
+					<view class="login-card__tabs">
+						<view
+							v-for="item in tabs"
+							:key="item.value"
+							class="login-card__tab"
+							:style="{
+								backgroundImage: returnBackgroundImg(item.value, activeTab === item.value)
+							}"
+							:class="{ 'login-card__tab--active': activeTab === item.value }"
+							@click="activeTab = item.value"
+						>
+							<text class="login-card__tab-text">{{ item.label }}</text>
+							<view v-if="activeTab === item.value" class="login-card__tab-line"></view>
 						</view>
 					</view>
-
-					<view v-else class="login-card__group">
-						<view class="login-card__field">
-							<input v-model="form.telephone" class="login-card__input" type="number" placeholder="璇疯緭鍏ユ墜鏈哄彿" placeholder-style="color: #c5cad4;" />
+		
+					<view class="login-card__form">
+						<view v-if="activeTab === 'account'" class="login-card__group">
+							<view class="login-card__field">
+								<input v-model="form.telephone" class="login-card__input" type="number" placeholder="璇疯緭鍏ユ墜鏈哄彿" placeholder-style="color: #c5cad4;" />
+							</view>
+							<view class="login-card__field">
+								<input v-model="form.password" class="login-card__input" password placeholder="璇疯緭鍏ュ瘑鐮�" placeholder-style="color: #c5cad4;" />
+							</view>
 						</view>
-						<view class="login-card__field login-card__field--code">
-							<input v-model="form.code" class="login-card__input" type="number" placeholder="璇疯緭鍏ラ獙璇佺爜" placeholder-style="color: #c5cad4;" />
-							<text class="login-card__code-btn" @click="sendCode">{{ countdown > 0 ? countdown + 's' : '鑾峰彇楠岃瘉鐮�' }}</text>
+		
+						<view v-else class="login-card__group">
+							<view class="login-card__field">
+								<input v-model="form.telephone" class="login-card__input" type="number" placeholder="璇疯緭鍏ユ墜鏈哄彿" placeholder-style="color: #c5cad4;" />
+							</view>
+							<view class="login-card__field login-card__field--code">
+								<input v-model="form.code" class="login-card__input" type="number" placeholder="璇疯緭鍏ラ獙璇佺爜" placeholder-style="color: #c5cad4;" />
+								<text class="login-card__code-btn" @click="sendCode">{{ countdown > 0 ? countdown + 's' : '鑾峰彇楠岃瘉鐮�' }}</text>
+							</view>
+						</view>
+		
+						<button class="login-card__submit" hover-class="login-card__submit--hover" @click="login">鐧诲綍</button>
+					</view>
+		
+					<view class="login-card__agreement" @click="toggleAgreement">
+						<view class="login-card__agreement-icon" :class="{ 'login-card__agreement-icon--checked': isAgreed }">
+							<text v-if="isAgreed" class="login-card__check">鉁�</text>
+						</view>
+						<view class="login-card__agreement-text">
+							<text>鐧诲綍鍗充唬琛ㄦ偍鍚屾剰</text>
+							<text class="login-card__agreement-link" @click.stop="openAgreement('driverPrivacyPolicy', '骞冲彴杞︿富鏈嶅姟鍗忚')">銆婂钩鍙拌溅涓绘湇鍔″崗璁��</text>
+							<text class="login-card__agreement-link" @click.stop="openAgreement('driverPrivacyPolicy', '璺戣吙杈句汉鏈嶅姟鍗忚')">銆婅窇鑵胯揪浜烘湇鍔″崗璁��</text>
+							<text class="login-card__agreement-link" @click.stop="openAgreement('driverPrivacyPolicy', '鍙告満闅愮鏀跨瓥')">銆婂徃鏈洪殣绉佹斂绛栥��</text>
 						</view>
 					</view>
-
-					<button class="login-card__submit" hover-class="login-card__submit--hover" @click="login">鐧诲綍</button>
-				</view>
-
-				<view class="login-card__agreement" @click="toggleAgreement">
-					<view class="login-card__agreement-icon" :class="{ 'login-card__agreement-icon--checked': isAgreed }">
-						<text v-if="isAgreed" class="login-card__check">鉁�</text>
-					</view>
-					<text class="login-card__agreement-text">鐧诲綍鍗充唬琛ㄦ偍鍚屾剰<text>銆婄敤鎴峰崗璁��</text>鍙�<text>銆婄敤鎴烽殣绉佹斂绛栥��</text></text>
 				</view>
 			</view>
 		</view>
+		<u-popup :show="showPrivacyPopup" mode="center" :mask-click="false" round="24">
+			<view class="privacy-popup">
+				<text class="privacy-popup__title">闅愮鏀跨瓥</text>
+				<view class="privacy-popup__content">
+					<text>鏈簲鐢ㄥ皧閲嶅苟淇濇姢鎵�鏈夌敤鎴风殑涓汉闅愮鏉冦�備负浜嗙粰鎮ㄦ彁渚涙洿鍑嗙‘銆佹洿鏈変釜鎬у寲鐨勬湇鍔★紝鏈簲鐢ㄤ細鎸夌収闅愮鏀跨瓥鐨勮瀹氫娇鐢ㄥ拰鎶湶鎮ㄧ殑涓汉淇℃伅銆傚彲闃呰</text>
+					<text class="privacy-popup__link" @click="openAgreement('ownerServiceAgreement', '骞冲彴杞︿富鏈嶅姟鍗忚')">銆婂钩鍙拌溅涓绘湇鍔″崗璁��</text>
+					<text class="privacy-popup__link" @click="openAgreement('errandServiceAgreement', '璺戣吙杈句汉鏈嶅姟鍗忚')">銆婅窇鑵胯揪浜烘湇鍔″崗璁��</text>
+					<text class="privacy-popup__link" @click="openAgreement('driverPrivacyPolicy', '鍙告満闅愮鏀跨瓥')">銆婇殣绉佹斂绛栥��</text>
+					<text>銆�</text>
+				</view>
+				<view class="privacy-popup__actions">
+					<button class="privacy-popup__button privacy-popup__button--ghost" @click="rejectPrivacyPolicy">涓嶅悓鎰忓苟閫�鍑篈PP</button>
+					<button class="privacy-popup__button privacy-popup__button--primary" @click="agreePrivacyPolicy">鍚屾剰</button>
+				</view>
+			</view>
+		</u-popup>
 	</view>
 </template>
 
@@ -72,6 +95,7 @@
 					code: ''
 				},
 				isAgreed: false,
+				showPrivacyPopup: false,
 				countdown: 0,
 				countdownTimer: null
 			};
@@ -82,7 +106,9 @@
 		onLoad() {
 			if (this.token) {
 				uni.switchTab({ url: '/pages/index/index' })
+				return
 			}
+			this.showPrivacyPopup = !uni.getStorageSync('login_privacy_policy_agreed')
 		},
 		methods: {
 			returnBackgroundImg(value, active) {
@@ -95,6 +121,23 @@
 				} else if (value === 'code' && active) {
 					return "url('/static/image/login_ic_code_sel@2x.png')"
 				}
+			},
+			openAgreement(type, title) {
+				uni.navigateTo({
+					url: `/pages/agreement/agreement?type=${type}&title=${encodeURIComponent(title)}`
+				});
+			},
+			agreePrivacyPolicy() {
+				uni.setStorageSync('login_privacy_policy_agreed', true)
+				this.showPrivacyPopup = false
+				uni.$emit('privacyAgreed')
+			},
+			rejectPrivacyPolicy() {
+				if (typeof plus !== 'undefined' && plus.runtime) {
+					plus.runtime.quit()
+					return
+				}
+				uni.exitProgram && uni.exitProgram()
 			},
 			toggleAgreement() {
 				this.isAgreed = !this.isAgreed;
@@ -154,6 +197,7 @@
 								if (user.code === 200) {
 									console.log('verifyDetail success:', user)
 									uni.showToast({ title: '鐧诲綍鎴愬姛', icon: 'success' });
+									uni.$emit('loginSuccessStartLocationPolling');
 									this.$store.commit('setUserInfo', user.data);
 									setTimeout(() => {
 										uni.switchTab({ url: '/pages/index/index' });
@@ -185,6 +229,7 @@
 								if (user.code === 200) {
 									console.log('verifyDetail success:', user)
 									uni.showToast({ title: '鐧诲綍鎴愬姛', icon: 'success' });
+									uni.$emit('loginSuccessStartLocationPolling');
 									this.$store.commit('setUserInfo', user.data);
 									setTimeout(() => {
 										uni.switchTab({ url: '/pages/index/index' });
@@ -257,8 +302,6 @@
 			align-items: center;
 			justify-content: center;
 			height: 100rpx;
-			border-bottom-left-radius: 28rpx;
-			border-bottom-right-radius: 28rpx;
 			background-repeat: no-repeat;
 			background-size: 100% 100%;
 			position: relative;
@@ -397,11 +440,70 @@
 		}
 
 		&__agreement-text {
+			display: flex;
+			flex-wrap: wrap;
 			font-size: 24rpx;
 			line-height: 1.6;
 			color: #555555;
-			text {
-				color: #106EFA;
+		}
+
+		&__agreement-link {
+			color: #106EFA;
+		}
+	}
+
+	.privacy-popup {
+		width: 620rpx;
+		padding: 48rpx 36rpx 36rpx;
+		background: #ffffff;
+		border-radius: 24rpx;
+		box-sizing: border-box;
+
+		&__title {
+			display: block;
+			text-align: center;
+			font-size: 34rpx;
+			font-weight: 600;
+			color: #222222;
+		}
+
+		&__content {
+			margin-top: 28rpx;
+			font-size: 28rpx;
+			line-height: 1.7;
+			color: #555555;
+		}
+
+		&__link {
+			color: #106efa;
+		}
+
+		&__actions {
+			margin-top: 40rpx;
+			display: flex;
+			gap: 20rpx;
+		}
+
+		&__button {
+			flex: 1;
+			height: 88rpx;
+			line-height: 88rpx;
+			border-radius: 44rpx;
+			font-size: 28rpx;
+			padding: 0;
+
+			&::after {
+				border: 0;
+			}
+
+			&--ghost {
+				background: #f3f6fb;
+				color: #5d6675;
+			}
+
+			&--primary {
+				background: #106efa;
+				color: #ffffff;
 			}
 		}
 	}

--
Gitblit v1.9.3