| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <template>
- <view class="login-container">
- <!-- 顶部高级渐变背景 -->
- <view class="gradient-bg"></view>
- <view class="content-wrapper">
- <!-- Logo 区域 -->
- <view class="logo-section">
- <view class="logo-outer">
- <image class="logo-img" :src="assets.logo" mode="aspectFill"></image>
- </view>
- <text class="app-title">ERP 智能下单系统</text>
- <text class="app-subtitle">简洁 · 高效 · 数字化管理</text>
- </view>
- <!-- 按钮区域 -->
- <view class="action-section">
- <button class="main-btn" @click="startLoginFlow">
- <image class="btn-icon" :src="assets.wechat" mode="aspectFit"></image>
- <text>授权手机号码登录</text>
- </button>
- <view class="agreement-box">
- <label class="checkbox-label" @click="toggleAgreed">
- <checkbox :checked="isAgreed" color="#C1001C" style="transform:scale(0.7)" />
- <text class="agreement-text">我已阅读并同意
- <text class="link" @click.stop="showProtocol('user')">《用户协议》</text> 与
- <text class="link" @click.stop="showProtocol('privacy')">《隐私政策》</text>
- </text>
- </label>
- </view>
- </view>
- <!-- 页脚 -->
- <view class="footer-section">
- <text>© 2026 ERP Order System. All Rights Reserved.</text>
- </view>
- </view>
- <!-- 全局遮罩 -->
- <view class="global-mask" v-if="activeModal" @click="closeAllModals"></view>
- <!-- 1. 协议拦截确认弹窗 -->
- <view class="confirm-modal center-card" v-if="activeModal === 'confirm'">
- <view class="card-title">服务协议提示</view>
- <view class="card-body">请您阅读并同意我们的协议内容,以便为您提供更安全的服务体验。</view>
- <view class="card-footer-btns">
- <view class="btn-item cancel" @click="activeModal = ''">拒绝</view>
- <view class="btn-item agree" @click="agreeAndClose">同意并继续</view>
- </view>
- </view>
- <!-- 2. 头像昵称授权弹窗 (原生能力适配) -->
- <view class="simulated-profile-pop bottom-pop" v-if="activeModal === 'profile'">
- <view class="pop-header-bar">
- <text class="pop-cancel" @click="activeModal = ''">取消</text>
- <text class="pop-main-title">获取头像昵称</text>
- <text class="pop-done" @click="activeModal = 'phone'">保存</text>
- </view>
- <view class="profile-edit-content">
- <view class="avatar-edit-box">
- <!-- 使用微信原生头像选择能力 -->
- <button class="avatar-wrapper-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
- <image class="current-avatar" :src="userAvatar || 'https://img.icons8.com/color/144/user.png'"></image>
- <view class="camera-icon">
- <image src="https://img.icons8.com/ios-glyphs/30/999999/camera.png" mode="aspectFit"></image>
- </view>
- </button>
- <text class="edit-hint">点击修改头像</text>
- </view>
- <view class="nickname-edit-box">
- <text class="label">昵称</text>
- <!-- 使用微信原生昵称填写能力 -->
- <input class="nickname-input" type="nickname" :value="userName" placeholder="请输入昵称" @blur="onNicknameBlur" @input="onNicknameChange" />
- </view>
- <view class="auth-notice-box">
- <text class="notice-text">授权后,开发者将获得您的头像和昵称,用于展示您的个人资料。</text>
- </view>
- </view>
- <view class="bottom-action">
- <button class="confirm-btn-fixed" @click="activeModal = 'phone'">确定</button>
- </view>
- </view>
- <!-- 3. 模拟手机号授权 -->
- <view class="phone-auth-pop bottom-pop" v-if="activeModal === 'phone'">
- <view class="p-header">
- <image class="p-mini-logo" :src="assets.logo" mode="aspectFill"></image>
- <text class="p-app-name">ERP 智能下单系统 申请</text>
- </view>
- <view class="p-body">
- <text class="p-title">获取您的手机号</text>
- <view class="p-number-card">
- <view class="p-card-left">
- <text class="p-real-num">138****8888</text>
- <text class="p-num-hint">微信绑定号码</text>
- </view>
- <icon type="success" size="18" color="#C1001C" />
- </view>
- <text class="p-other-link">使用其他手机号码</text>
- </view>
- <view class="p-footer-btns">
- <button class="p-btn-fixed p-deny" @click="activeModal = ''">拒绝</button>
- <button class="p-btn-fixed p-allow" @click="completeLogin">允许</button>
- </view>
- </view>
- <!-- 4. 协议富文本弹窗 (样式专项修复) -->
- <view class="protocol-modal center-card" v-if="activeModal === 'protocol'">
- <view class="p-pop-header">
- <text class="p-pop-title">{{ currentProtocol.title }}</text>
- <text class="p-pop-close" @click="activeModal = ''">×</text>
- </view>
- <scroll-view scroll-y class="p-pop-scroll">
- <view class="rich-text-wrapper">
- <rich-text :nodes="currentProtocol.content"></rich-text>
- </view>
- </scroll-view>
- <view class="p-pop-footer">
- <button class="p-pop-btn" @click="activeModal = ''">我已了解</button>
- </view>
- </view>
- </view>
- </template>
- <script>
- import assets from '@/utils/assets.js';
- export default {
- data() {
- return {
- assets, isAgreed: false, activeModal: '',
- userAvatar: '', userName: '微信用户',
- redirectUrl: '',
- currentProtocol: { title: '', content: '' },
- protocols: {
- user: { title: '用户服务协议', content: '<div style="line-height:1.8;"><h4 style="margin-bottom:10px;">服务内容</h4><p>欢迎使用ERP系统,我们将为您提供高效的下单管理服务。本协议旨在明确双方权利与义务...</p></div>' },
- privacy: { title: '隐私政策', content: '<div style="line-height:1.8;"><h4 style="margin-bottom:10px;">隐私保护</h4><p>我们非常重视您的个人信息保护。我们会按照法律法规要求,采取相应的安全保护措施...</p></div>' }
- }
- }
- },
- onLoad(options) {
- if (options.redirect) {
- this.redirectUrl = decodeURIComponent(options.redirect);
- }
- },
- methods: {
- toggleAgreed() { this.isAgreed = !this.isAgreed; },
- startLoginFlow() {
- if (!this.isAgreed) this.activeModal = 'confirm';
- else this.activeModal = 'profile';
- },
- agreeAndClose() {
- this.isAgreed = true;
- this.activeModal = '';
- },
- completeLogin() {
- uni.showLoading({ title: '登录中...' });
- uni.setStorageSync('isLogin', true);
- setTimeout(() => {
- uni.hideLoading();
- this.activeModal = '';
- const targetUrl = this.redirectUrl || '/pages/index/index';
- uni.reLaunch({ url: targetUrl });
- }, 1000);
- },
- onChooseAvatar(e) {
- this.userAvatar = e.detail.avatarUrl;
- // 这里通常需要将临时路径上传到服务器
- },
- onNicknameBlur(e) {
- this.userName = e.detail.value;
- },
- onNicknameChange(e) {
- this.userName = e.detail.value;
- },
- showProtocol(type) { this.currentProtocol = this.protocols[type]; this.activeModal = 'protocol'; },
- closeAllModals() { this.activeModal = ''; }
- }
- }
- </script>
- <style scoped>
- /* 基础容器 */
- .login-container { width: 100%; min-height: 100vh; background: #fff; position: relative; display: flex; flex-direction: column; }
- .gradient-bg { position: absolute; top: 0; left: 0; right: 0; height: 600rpx; background: linear-gradient(180deg, rgba(193, 0, 28, 0.12) 0%, rgba(255, 255, 255, 0) 100%); z-index: 1; }
- .content-wrapper { position: relative; z-index: 2; flex: 1; display: flex; flex-direction: column; padding: 0 80rpx; box-sizing: border-box; }
- .logo-section { display: flex; flex-direction: column; align-items: center; margin-top: 360rpx; margin-bottom: 120rpx; }
- .logo-outer { width: 200rpx; height: 200rpx; background: #fff; border-radius: 48rpx; box-shadow: 0 40rpx 80rpx rgba(193, 0, 28, 0.35), 0 10rpx 30rpx rgba(0, 0, 0, 0.1), inset 0 4rpx 10rpx rgba(255,255,255,0.8); display: flex; align-items: center; justify-content: center; overflow: hidden; margin-bottom: 40rpx; }
- .logo-img { width: 100%; height: 100%; }
- .app-title { font-size: 48rpx; font-weight: bold; color: #1a1a1a; letter-spacing: 2rpx; }
- .app-subtitle { font-size: 26rpx; color: #999; margin-top: 10rpx; letter-spacing: 6rpx; }
- .main-btn { width: 100%; height: 100rpx; background: linear-gradient(135deg, #C1001C 0%, #FF4D4F 100%); border-radius: 50rpx; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 32rpx; font-weight: bold; box-shadow: 0 12rpx 30rpx rgba(193, 0, 28, 0.2); border: none; margin-bottom: 40rpx; }
- .btn-icon { width: 48rpx; height: 48rpx; margin-right: 16rpx; }
- .agreement-text { font-size: 24rpx; color: #999; }
- .link { color: #C1001C; margin: 0 4rpx; font-weight: 500; }
- .footer-section { margin-top: auto; padding-bottom: 60rpx; text-align: center; font-size: 20rpx; color: #dcdcdc; }
- /* 弹窗通用基础 */
- .global-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 998; }
- .center-card { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 620rpx; background: #fff; border-radius: 32rpx; z-index: 1000; box-shadow: 0 30rpx 80rpx rgba(0,0,0,0.15); padding: 50rpx 40rpx; display: flex; flex-direction: column; }
- .bottom-pop { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-radius: 40rpx 40rpx 0 0; z-index: 1001; padding: 40rpx; padding-bottom: calc(50rpx + env(safe-area-inset-bottom)); box-shadow: 0 -10rpx 40rpx rgba(0,0,0,0.05); }
- /* 按钮对齐辅助 */
- button { display: flex !important; align-items: center !important; justify-content: center !important; padding: 0 !important; line-height: normal !important; }
- button::after { border: none; }
- /* 协议拦截弹窗 */
- .card-title { font-size: 38rpx; font-weight: bold; text-align: center; margin-bottom: 30rpx; }
- .card-body { font-size: 28rpx; color: #666; line-height: 1.6; text-align: center; margin-bottom: 50rpx; }
- .card-footer-btns { display: flex; gap: 24rpx; }
- .btn-item { flex: 1; height: 90rpx; border-radius: 45rpx; font-size: 30rpx; display: flex !important; align-items: center !important; justify-content: center !important; text-align: center; line-height: 90rpx; }
- .btn-item.cancel { background: #f8f8f8; color: #999; }
- .btn-item.agree { background: #C1001C; color: #fff; font-weight: bold; }
- /* 协议内容弹窗专项修复 */
- .p-pop-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30rpx; }
- .p-pop-title { font-size: 36rpx; font-weight: bold; color: #1a1a1a; }
- .p-pop-close { font-size: 48rpx; color: #ccc; padding: 10rpx; }
- .p-pop-scroll { max-height: 55vh; margin-bottom: 30rpx; }
- .rich-text-wrapper { padding: 10rpx 0; color: #444; font-size: 28rpx; }
- .p-pop-footer { padding-top: 20rpx; }
- .p-pop-btn { width: 100%; height: 90rpx; background: #C1001C; color: #fff; border-radius: 45rpx; font-size: 30rpx; font-weight: bold; }
- /* 头像授权弹窗 */
- .pop-header-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 60rpx; }
- .pop-cancel { font-size: 30rpx; color: #999; }
- .pop-main-title { font-size: 32rpx; font-weight: bold; }
- .pop-done { font-size: 30rpx; color: #C1001C; font-weight: bold; }
- .profile-edit-content { display: flex; flex-direction: column; align-items: center; }
- .avatar-wrapper-btn {
- width: 170rpx; height: 170rpx; border-radius: 85rpx; background: #f8f8f8;
- position: relative; margin-bottom: 24rpx; padding: 0 !important; overflow: visible;
- display: flex !important; align-items: center; justify-content: center;
- border: none;
- }
- .current-avatar { width: 100%; height: 100%; border-radius: 85rpx; border: 4rpx solid #fff; box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.05); }
- .camera-icon {
- position: absolute; bottom: 0; right: 0; background: #fff; width: 56rpx; height: 56rpx;
- border-radius: 28rpx; display: flex; align-items: center; justify-content: center;
- box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.12); z-index: 5;
- }
- .camera-icon image { width: 30rpx; height: 30rpx; }
- .edit-hint { font-size: 24rpx; color: #999; margin-bottom: 70rpx; width: 100%; text-align: center; display: block; }
- .nickname-edit-box { width: 100%; display: flex; align-items: center; padding: 36rpx 0; border-top: 1rpx solid #f0f0f0; border-bottom: 1rpx solid #f0f0f0; margin-bottom: 40rpx; }
- .nickname-edit-box .label { width: 130rpx; font-size: 32rpx; }
- .nickname-input { flex: 1; font-size: 32rpx; }
- .notice-text { font-size: 24rpx; color: #bfbfbf; text-align: center; display: block; margin-bottom: 60rpx; }
- .confirm-btn-fixed { width: 100%; height: 96rpx; background: #C1001C; color: #fff; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
- /* 手机号授权弹窗 */
- .p-header { display: flex; align-items: center; margin-bottom: 50rpx; }
- .p-mini-logo { width: 44rpx; height: 44rpx; border-radius: 8rpx; margin-right: 16rpx; }
- .p-app-name { font-size: 28rpx; color: #7f7f7f; }
- .p-title { font-size: 40rpx; font-weight: bold; color: #000; margin-bottom: 44rpx; display: block; }
- .p-number-card { background: #fbfbfb; padding: 36rpx; border-radius: 20rpx; display: flex; justify-content: space-between; align-items: center; margin-bottom: 30rpx; border: 1rpx solid #f0f0f0; }
- .p-real-num { font-size: 36rpx; font-weight: bold; color: #1a1a1a; display: block; }
- .p-num-hint { font-size: 24rpx; color: #999; }
- .p-other-link { font-size: 28rpx; color: #576b95; display: block; margin-bottom: 60rpx; }
- .p-footer-btns { display: flex; gap: 30rpx; }
- .p-btn-fixed { flex: 1; height: 96rpx; border-radius: 16rpx; font-size: 32rpx; border: none; }
- .p-deny { background: #f2f2f2; color: #C1001C; }
- .p-allow { background: #C1001C; color: #fff; font-weight: bold; }
- </style>
|