835 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			835 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Vue
		
	
	
	
<!--
 | 
						||
 * @Descripttion: 自助购票页面
 | 
						||
 * @version: 1.0.0
 | 
						||
 * @Author: Assistant
 | 
						||
 * @Date: 2025-01-22
 | 
						||
-->
 | 
						||
<template>
 | 
						||
  <view class="buy-ticket-container">
 | 
						||
    <!-- 内容区域 -->
 | 
						||
    <view class="content-area">
 | 
						||
      <!-- 提示信息 -->
 | 
						||
      <view class="tip-banner">
 | 
						||
        <view class="tip-icon">
 | 
						||
          <u-icon name="info-circle" size="16" color="#f56c6c"></u-icon>
 | 
						||
        </view>
 | 
						||
        <text class="tip-text">自助购票请填写以下信息:</text>
 | 
						||
      </view>
 | 
						||
 | 
						||
      <!-- 购票人信息列表 -->
 | 
						||
      <view class="buyer-list">
 | 
						||
        <view
 | 
						||
          class="buyer-item"
 | 
						||
          v-for="(buyer, index) in buyerList"
 | 
						||
          :key="index"
 | 
						||
        >
 | 
						||
          <view class="buyer-header">
 | 
						||
            <text class="buyer-title">购票人信息{{ index + 1 }}</text>
 | 
						||
            <view
 | 
						||
              class="delete-btn"
 | 
						||
              v-if="buyerList.length > 1"
 | 
						||
              @click="removeBuyer(index)"
 | 
						||
            >
 | 
						||
              <u-icon name="trash" size="16" color="#999"></u-icon>
 | 
						||
            </view>
 | 
						||
          </view>
 | 
						||
 | 
						||
          <view class="form-section">
 | 
						||
            <!-- 姓名 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>姓名</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.name"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  maxlength="20"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 联系方式 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>联系方式</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.phone"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  type="number"
 | 
						||
                  maxlength="11"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 证件号码 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>证件号码</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.idCard"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  maxlength="18"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 性别 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>性别</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <picker
 | 
						||
                  :value="buyer.sexIndex"
 | 
						||
                  :range="sexOptions"
 | 
						||
                  @change="onSexChange($event, index)"
 | 
						||
                >
 | 
						||
                  <view class="picker-input">
 | 
						||
                    <text
 | 
						||
                      class="picker-text"
 | 
						||
                      :class="{ placeholder: buyer.sexIndex === -1 }"
 | 
						||
                    >
 | 
						||
                      {{
 | 
						||
                        buyer.sexIndex !== -1
 | 
						||
                          ? sexOptions[buyer.sexIndex]
 | 
						||
                          : '请选择'
 | 
						||
                      }}
 | 
						||
                    </text>
 | 
						||
                    <u-icon name="arrow-down" size="12" color="#999"></u-icon>
 | 
						||
                  </view>
 | 
						||
                </picker>
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 服装尺寸 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>服装尺寸</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.clothSize"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  maxlength="10"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 同住人 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label">
 | 
						||
                <text>同住人</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.cohabitant"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  maxlength="20"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
 | 
						||
            <!-- 紧急联系方式 -->
 | 
						||
            <view class="form-item">
 | 
						||
              <view class="label required">
 | 
						||
                <text>紧急联系方式</text>
 | 
						||
              </view>
 | 
						||
              <view class="input-wrapper">
 | 
						||
                <input
 | 
						||
                  class="form-input"
 | 
						||
                  v-model="buyer.emergencyPhone"
 | 
						||
                  placeholder="请输入"
 | 
						||
                  type="number"
 | 
						||
                  maxlength="11"
 | 
						||
                />
 | 
						||
              </view>
 | 
						||
            </view>
 | 
						||
          </view>
 | 
						||
        </view>
 | 
						||
      </view>
 | 
						||
 | 
						||
      <!-- 添加购票人按钮 -->
 | 
						||
      <view class="add-buyer-btn" @click="addBuyer">
 | 
						||
        <u-icon name="plus" size="16" color="#666"></u-icon>
 | 
						||
        <text class="add-text">继续添加购票人</text>
 | 
						||
      </view>
 | 
						||
 | 
						||
      <!-- 提交按钮 -->
 | 
						||
      <view class="submit-wrapper">
 | 
						||
        <button
 | 
						||
          class="submit-btn"
 | 
						||
          :class="{ disabled: submitting }"
 | 
						||
          :disabled="submitting"
 | 
						||
          @click="handleSubmit"
 | 
						||
        >
 | 
						||
          {{ submitting ? '提交中...' : '提交' }}
 | 
						||
        </button>
 | 
						||
      </view>
 | 
						||
    </view>
 | 
						||
 | 
						||
    <!-- 支付密码弹窗 -->
 | 
						||
    <u-popup
 | 
						||
      :show="showPayPwdModal"
 | 
						||
      mode="center"
 | 
						||
      border-radius="16"
 | 
						||
      width="320px"
 | 
						||
      height="auto"
 | 
						||
    >
 | 
						||
      <view class="pay-pwd-modal">
 | 
						||
        <view class="modal-header">
 | 
						||
          <view class="header-icon">
 | 
						||
            <u-icon name="lock" size="24" color="#005bac"></u-icon>
 | 
						||
          </view>
 | 
						||
          <text class="modal-title">输入支付密码</text>
 | 
						||
          <text class="modal-subtitle">请输入您的支付密码以完成购票</text>
 | 
						||
        </view>
 | 
						||
        <view class="modal-body">
 | 
						||
          <view class="pwd-input-wrapper">
 | 
						||
            <input
 | 
						||
              class="pwd-input"
 | 
						||
              v-model="payPassword"
 | 
						||
              placeholder="请输入支付密码"
 | 
						||
              type="password"
 | 
						||
              @input="onPayPwdInput"
 | 
						||
              @focus="onPwdFocus"
 | 
						||
              @blur="onPwdBlur"
 | 
						||
            />
 | 
						||
            <view
 | 
						||
              class="input-border"
 | 
						||
              :class="{ focused: pwdInputFocused }"
 | 
						||
            ></view>
 | 
						||
          </view>
 | 
						||
        </view>
 | 
						||
        <view class="modal-footer">
 | 
						||
          <view class="btn-group">
 | 
						||
            <button class="modal-btn cancel-btn" @click="closePayPwdModal">
 | 
						||
              取消
 | 
						||
            </button>
 | 
						||
            <button
 | 
						||
              class="modal-btn confirm-btn"
 | 
						||
              :class="{ disabled: !isPayPwdValid }"
 | 
						||
              :disabled="!isPayPwdValid"
 | 
						||
              @click="confirmPayPwd"
 | 
						||
            >
 | 
						||
              确认支付
 | 
						||
            </button>
 | 
						||
          </view>
 | 
						||
        </view>
 | 
						||
      </view>
 | 
						||
    </u-popup>
 | 
						||
  </view>
 | 
						||
</template>
 | 
						||
 | 
						||
<script>
 | 
						||
import { buyTicket } from '@/config/ticket.js'
 | 
						||
 | 
						||
export default {
 | 
						||
  data() {
 | 
						||
    return {
 | 
						||
      activityId: '',
 | 
						||
      activityName: '',
 | 
						||
      price: '',
 | 
						||
      buyerList: [
 | 
						||
        {
 | 
						||
          name: '',
 | 
						||
          phone: '',
 | 
						||
          idCard: '',
 | 
						||
          sexIndex: 0,
 | 
						||
          sex: 1,
 | 
						||
          clothSize: '',
 | 
						||
          cohabitant: '',
 | 
						||
          emergencyPhone: '',
 | 
						||
        },
 | 
						||
      ],
 | 
						||
      sexOptions: ['男', '女'],
 | 
						||
      submitting: false,
 | 
						||
      showPayPwdModal: false,
 | 
						||
      payPassword: '',
 | 
						||
      pwdInputFocused: false,
 | 
						||
    }
 | 
						||
  },
 | 
						||
  computed: {
 | 
						||
    // 支付密码是否有效(非空且为纯数字)
 | 
						||
    isPayPwdValid() {
 | 
						||
      return this.payPassword.length > 0 && /^\d+$/.test(this.payPassword)
 | 
						||
    },
 | 
						||
  },
 | 
						||
  onLoad(options) {
 | 
						||
    if (options.activityId) {
 | 
						||
      this.activityId = options.activityId
 | 
						||
    }
 | 
						||
    if (options.activityName) {
 | 
						||
      this.activityName = decodeURIComponent(options.activityName)
 | 
						||
    }
 | 
						||
    if (options.price) {
 | 
						||
      this.price = options.price
 | 
						||
    }
 | 
						||
  },
 | 
						||
  methods: {
 | 
						||
    // 返回上一页
 | 
						||
    goBack() {
 | 
						||
      uni.navigateBack()
 | 
						||
    },
 | 
						||
 | 
						||
    // 性别选择变化
 | 
						||
    onSexChange(e, index) {
 | 
						||
      const sexIndex = e.detail.value
 | 
						||
      this.buyerList[index].sexIndex = sexIndex
 | 
						||
      this.buyerList[index].sex = sexIndex == 0 ? 1 : 2 // 1-男,2-女
 | 
						||
    },
 | 
						||
 | 
						||
    // 添加购票人
 | 
						||
    addBuyer() {
 | 
						||
      this.buyerList.push({
 | 
						||
        name: '',
 | 
						||
        phone: '',
 | 
						||
        idCard: '',
 | 
						||
        sexIndex: 0,
 | 
						||
        sex: 1,
 | 
						||
        clothSize: '',
 | 
						||
        cohabitant: '',
 | 
						||
        emergencyPhone: '',
 | 
						||
      })
 | 
						||
    },
 | 
						||
 | 
						||
    // 删除购票人
 | 
						||
    removeBuyer(index) {
 | 
						||
      uni.showModal({
 | 
						||
        title: '提示',
 | 
						||
        content: '确定删除该购票人信息吗?',
 | 
						||
        success: res => {
 | 
						||
          if (res.confirm) {
 | 
						||
            this.buyerList.splice(index, 1)
 | 
						||
          }
 | 
						||
        },
 | 
						||
      })
 | 
						||
    },
 | 
						||
 | 
						||
    // 验证表单
 | 
						||
    validateForm() {
 | 
						||
      for (let i = 0; i < this.buyerList.length; i++) {
 | 
						||
        const buyer = this.buyerList[i]
 | 
						||
 | 
						||
        if (!buyer.name.trim()) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的姓名不能为空`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (!buyer.phone.trim()) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的联系方式不能为空`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (!buyer.idCard.trim()) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的证件号码不能为空`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (buyer.sexIndex === -1 || (!buyer.sex && buyer.sex !== 0)) {
 | 
						||
          uni.$u.toast(`请选择购票人${i + 1}的性别`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (!buyer.clothSize.trim()) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的服装尺寸不能为空`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (!buyer.emergencyPhone.trim()) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的紧急联系方式不能为空`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
 | 
						||
        if (buyer.emergencyPhone === buyer.phone) {
 | 
						||
          uni.$u.toast(`购票人${i + 1}的紧急联系方式不能与联系方式相同`)
 | 
						||
          return false
 | 
						||
        }
 | 
						||
      }
 | 
						||
 | 
						||
      return true
 | 
						||
    },
 | 
						||
 | 
						||
    // 处理提交按钮点击
 | 
						||
    handleSubmit() {
 | 
						||
      if (!this.validateForm()) {
 | 
						||
        return
 | 
						||
      }
 | 
						||
      console.log('支付弹窗?')
 | 
						||
      // 显示支付密码弹窗
 | 
						||
      this.showPayPwdModal = true
 | 
						||
      this.payPassword = ''
 | 
						||
    },
 | 
						||
 | 
						||
    // 关闭支付密码弹窗
 | 
						||
    closePayPwdModal() {
 | 
						||
      this.showPayPwdModal = false
 | 
						||
      this.payPassword = ''
 | 
						||
    },
 | 
						||
 | 
						||
    // 支付密码输入处理
 | 
						||
    onPayPwdInput(e) {
 | 
						||
      // 只允许输入数字
 | 
						||
      this.payPassword = e.detail.value.replace(/[^\d]/g, '')
 | 
						||
    },
 | 
						||
 | 
						||
    // 密码输入框获得焦点
 | 
						||
    onPwdFocus() {
 | 
						||
      this.pwdInputFocused = true
 | 
						||
    },
 | 
						||
 | 
						||
    // 密码输入框失去焦点
 | 
						||
    onPwdBlur() {
 | 
						||
      this.pwdInputFocused = false
 | 
						||
    },
 | 
						||
 | 
						||
    // 确认支付密码
 | 
						||
    confirmPayPwd() {
 | 
						||
      if (!this.isPayPwdValid) {
 | 
						||
        uni.$u.toast('请输入正确的支付密码')
 | 
						||
        return
 | 
						||
      }
 | 
						||
 | 
						||
      this.showPayPwdModal = false
 | 
						||
      this.submitOrder()
 | 
						||
    },
 | 
						||
 | 
						||
    // 提交订单
 | 
						||
    async submitOrder() {
 | 
						||
      if (!this.validateForm()) {
 | 
						||
        return
 | 
						||
      }
 | 
						||
 | 
						||
      this.submitting = true
 | 
						||
 | 
						||
      try {
 | 
						||
        // 构造提交数据
 | 
						||
        const orderData = {
 | 
						||
          payPwd: this.payPassword,
 | 
						||
          pkTicket: this.activityId,
 | 
						||
          ticketParamList: this.buyerList.map(buyer => ({
 | 
						||
            buyName: buyer.name,
 | 
						||
            phone: buyer.phone,
 | 
						||
            idCard: buyer.idCard,
 | 
						||
            sex: buyer.sex,
 | 
						||
            clothSize: buyer.clothSize,
 | 
						||
            cohabitant: buyer.cohabitant || '',
 | 
						||
            emergencyPhone: buyer.emergencyPhone,
 | 
						||
          })),
 | 
						||
        }
 | 
						||
 | 
						||
        const res = await buyTicket(orderData)
 | 
						||
 | 
						||
        if (res.code === 200) {
 | 
						||
          uni.showToast({
 | 
						||
            title: '购票成功',
 | 
						||
            icon: 'success',
 | 
						||
            duration: 2000,
 | 
						||
          })
 | 
						||
 | 
						||
          setTimeout(() => {
 | 
						||
            // 返回门票列表页面,并切换到我的门票tab
 | 
						||
            uni.navigateBack({
 | 
						||
              delta: 1,
 | 
						||
            })
 | 
						||
          }, 2000)
 | 
						||
        } else {
 | 
						||
          uni.$u.toast(res.msg || '购票失败,请重试')
 | 
						||
        }
 | 
						||
      } catch (error) {
 | 
						||
        console.error('购票失败:', error)
 | 
						||
        uni.$u.toast('购票失败,请重试')
 | 
						||
      } finally {
 | 
						||
        this.submitting = false
 | 
						||
      }
 | 
						||
    },
 | 
						||
  },
 | 
						||
}
 | 
						||
</script>
 | 
						||
 | 
						||
<style lang="scss" scoped>
 | 
						||
.buy-ticket-container {
 | 
						||
  min-height: 100vh;
 | 
						||
  background: #f8f8f8;
 | 
						||
}
 | 
						||
 | 
						||
.custom-navbar {
 | 
						||
  position: fixed;
 | 
						||
  top: 0;
 | 
						||
  left: 0;
 | 
						||
  right: 0;
 | 
						||
  z-index: 999;
 | 
						||
  background: #fff;
 | 
						||
  padding-top: var(--status-bar-height);
 | 
						||
  border-bottom: 1px solid #eee;
 | 
						||
 | 
						||
  .navbar-content {
 | 
						||
    display: flex;
 | 
						||
    align-items: center;
 | 
						||
    height: 44px;
 | 
						||
    padding: 0 16px;
 | 
						||
 | 
						||
    .back-btn {
 | 
						||
      width: 40px;
 | 
						||
      height: 40px;
 | 
						||
      display: flex;
 | 
						||
      align-items: center;
 | 
						||
      justify-content: center;
 | 
						||
    }
 | 
						||
 | 
						||
    .navbar-title {
 | 
						||
      flex: 1;
 | 
						||
      text-align: center;
 | 
						||
      font-size: 18px;
 | 
						||
      font-weight: 600;
 | 
						||
      color: #333;
 | 
						||
    }
 | 
						||
 | 
						||
    .placeholder {
 | 
						||
      width: 40px;
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.content-area {
 | 
						||
  margin-top: 10rpx;
 | 
						||
  padding: 24rpx;
 | 
						||
  padding-bottom: 200rpx;
 | 
						||
}
 | 
						||
 | 
						||
.tip-banner {
 | 
						||
  background: #fff5f5;
 | 
						||
  border: 1px solid #ffebee;
 | 
						||
  border-radius: 8px;
 | 
						||
  padding: 12px 16px;
 | 
						||
  margin-bottom: 16px;
 | 
						||
  display: flex;
 | 
						||
  align-items: center;
 | 
						||
 | 
						||
  .tip-icon {
 | 
						||
    margin-right: 8px;
 | 
						||
  }
 | 
						||
 | 
						||
  .tip-text {
 | 
						||
    font-size: 14px;
 | 
						||
    color: #f56c6c;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.buyer-list {
 | 
						||
  .buyer-item {
 | 
						||
    background: #fff;
 | 
						||
    border-radius: 12px;
 | 
						||
    margin-bottom: 16px;
 | 
						||
    overflow: hidden;
 | 
						||
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
 | 
						||
 | 
						||
    .buyer-header {
 | 
						||
      display: flex;
 | 
						||
      align-items: center;
 | 
						||
      justify-content: space-between;
 | 
						||
      padding: 16px;
 | 
						||
      border-bottom: 1px solid #f5f5f5;
 | 
						||
 | 
						||
      .buyer-title {
 | 
						||
        font-size: 16px;
 | 
						||
        font-weight: 600;
 | 
						||
        color: #333;
 | 
						||
      }
 | 
						||
 | 
						||
      .delete-btn {
 | 
						||
        width: 32px;
 | 
						||
        height: 32px;
 | 
						||
        display: flex;
 | 
						||
        align-items: center;
 | 
						||
        justify-content: center;
 | 
						||
        background: #f8f8f8;
 | 
						||
        border-radius: 16px;
 | 
						||
      }
 | 
						||
    }
 | 
						||
 | 
						||
    .form-section {
 | 
						||
      padding: 16px;
 | 
						||
 | 
						||
      .form-item {
 | 
						||
        display: flex;
 | 
						||
        align-items: center;
 | 
						||
        margin-bottom: 20px;
 | 
						||
 | 
						||
        &:last-child {
 | 
						||
          margin-bottom: 0;
 | 
						||
        }
 | 
						||
 | 
						||
        .label {
 | 
						||
          width: 100px;
 | 
						||
          font-size: 14px;
 | 
						||
          color: #333;
 | 
						||
          position: relative;
 | 
						||
 | 
						||
          &.required::before {
 | 
						||
            content: '*';
 | 
						||
            color: #f56c6c;
 | 
						||
            position: absolute;
 | 
						||
            left: -10px;
 | 
						||
          }
 | 
						||
        }
 | 
						||
 | 
						||
        .input-wrapper {
 | 
						||
          flex: 1;
 | 
						||
 | 
						||
          .form-input {
 | 
						||
            width: 100%;
 | 
						||
            height: 44px;
 | 
						||
            background: #f8f8f8;
 | 
						||
            border-radius: 8px;
 | 
						||
            border: none;
 | 
						||
            padding: 0 16px;
 | 
						||
            font-size: 14px;
 | 
						||
            color: #333;
 | 
						||
            box-sizing: border-box;
 | 
						||
            &::placeholder {
 | 
						||
              color: #c0c0c0;
 | 
						||
            }
 | 
						||
          }
 | 
						||
 | 
						||
          .picker-input {
 | 
						||
            display: flex;
 | 
						||
            align-items: center;
 | 
						||
            justify-content: space-between;
 | 
						||
            width: 100%;
 | 
						||
            height: 44px;
 | 
						||
            background: #f8f8f8;
 | 
						||
            box-sizing: border-box;
 | 
						||
            border-radius: 8px;
 | 
						||
            padding: 0 16px;
 | 
						||
 | 
						||
            .picker-text {
 | 
						||
              font-size: 14px;
 | 
						||
              color: #333;
 | 
						||
 | 
						||
              &.placeholder {
 | 
						||
                color: #c0c0c0;
 | 
						||
              }
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.add-buyer-btn {
 | 
						||
  display: flex;
 | 
						||
  align-items: center;
 | 
						||
  justify-content: center;
 | 
						||
  background: #fff;
 | 
						||
  border-radius: 12px;
 | 
						||
  padding: 16px;
 | 
						||
  margin-bottom: 24px;
 | 
						||
  border: 2px dashed #e0e0e0;
 | 
						||
 | 
						||
  .add-text {
 | 
						||
    font-size: 14px;
 | 
						||
    color: #666;
 | 
						||
    margin-left: 8px;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.submit-wrapper {
 | 
						||
  position: fixed;
 | 
						||
  bottom: 0;
 | 
						||
  left: 0;
 | 
						||
  right: 0;
 | 
						||
  background: #fff;
 | 
						||
  padding: 16px;
 | 
						||
  border-top: 1px solid #eee;
 | 
						||
 | 
						||
  .submit-btn {
 | 
						||
    width: 100%;
 | 
						||
    height: 96r px;
 | 
						||
    background: #005bac;
 | 
						||
    color: #fff;
 | 
						||
    border: none;
 | 
						||
    border-radius: 48rpx;
 | 
						||
    font-size: 32rpx;
 | 
						||
    font-weight: 600;
 | 
						||
 | 
						||
    &.disabled {
 | 
						||
      background: #ccc;
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
/* 支付密码弹窗样式 */
 | 
						||
.pay-pwd-modal {
 | 
						||
  background: #fff;
 | 
						||
  border-radius: 16rpx;
 | 
						||
  overflow: hidden;
 | 
						||
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
 | 
						||
 | 
						||
  .modal-header {
 | 
						||
    padding: 40rpx 40rpx 20rpx;
 | 
						||
    text-align: center;
 | 
						||
    background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
 | 
						||
 | 
						||
    .header-icon {
 | 
						||
      width: 48px;
 | 
						||
      height: 48px;
 | 
						||
      background: rgba(0, 91, 172, 0.1);
 | 
						||
      border-radius: 24px;
 | 
						||
      display: flex;
 | 
						||
      align-items: center;
 | 
						||
      justify-content: center;
 | 
						||
      margin: 0 auto 16px;
 | 
						||
    }
 | 
						||
 | 
						||
    .modal-title {
 | 
						||
      font-size: 18px;
 | 
						||
      font-weight: 600;
 | 
						||
      color: #333;
 | 
						||
      display: block;
 | 
						||
      margin-bottom: 8px;
 | 
						||
    }
 | 
						||
 | 
						||
    .modal-subtitle {
 | 
						||
      font-size: 14px;
 | 
						||
      color: #666;
 | 
						||
      display: block;
 | 
						||
      line-height: 1.4;
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  .modal-body {
 | 
						||
    padding: 24rpx;
 | 
						||
 | 
						||
    .pwd-input-wrapper {
 | 
						||
      position: relative;
 | 
						||
      margin-bottom: 16rpx;
 | 
						||
 | 
						||
      .pwd-input {
 | 
						||
        width: 100%;
 | 
						||
        height: 80rpx;
 | 
						||
        background: #f8f9fa;
 | 
						||
        border-radius: 24rpx;
 | 
						||
        border: none;
 | 
						||
        padding: 0 20rpx;
 | 
						||
        font-size: 24rpx;
 | 
						||
        color: #333;
 | 
						||
        text-align: center;
 | 
						||
        letter-spacing: 4rpx;
 | 
						||
        box-sizing: border-box;
 | 
						||
        transition: all 0.3s ease;
 | 
						||
 | 
						||
        &::placeholder {
 | 
						||
          color: #c0c0c0;
 | 
						||
          letter-spacing: normal;
 | 
						||
        }
 | 
						||
 | 
						||
        &:focus {
 | 
						||
          background: #fff;
 | 
						||
          outline: none;
 | 
						||
        }
 | 
						||
      }
 | 
						||
 | 
						||
      .input-border {
 | 
						||
        position: absolute;
 | 
						||
        top: 0;
 | 
						||
        left: 0;
 | 
						||
        right: 0;
 | 
						||
        bottom: 0;
 | 
						||
        border: 2px solid transparent;
 | 
						||
        border-radius: 12px;
 | 
						||
        pointer-events: none;
 | 
						||
        transition: all 0.3s ease;
 | 
						||
 | 
						||
        &.focused {
 | 
						||
          border-color: #005bac;
 | 
						||
          box-shadow: 0 0 0 4px rgba(0, 91, 172, 0.1);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
 | 
						||
    .pwd-strength {
 | 
						||
      .strength-dots {
 | 
						||
        display: flex;
 | 
						||
        justify-content: center;
 | 
						||
        gap: 8px;
 | 
						||
 | 
						||
        .dot {
 | 
						||
          width: 8px;
 | 
						||
          height: 8px;
 | 
						||
          border-radius: 4px;
 | 
						||
          background: #e9ecef;
 | 
						||
          transition: all 0.3s ease;
 | 
						||
 | 
						||
          &.active {
 | 
						||
            background: #005bac;
 | 
						||
            transform: scale(1.2);
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  .modal-footer {
 | 
						||
    padding: 0 24px 24px;
 | 
						||
 | 
						||
    .btn-group {
 | 
						||
      display: flex;
 | 
						||
      gap: 12px;
 | 
						||
 | 
						||
      .modal-btn {
 | 
						||
        flex: 1;
 | 
						||
        height: 48rpx;
 | 
						||
        border: none;
 | 
						||
        border-radius: 24rpx;
 | 
						||
        font-size: 24rpx;
 | 
						||
        font-weight: 500;
 | 
						||
        transition: all 0.3s ease;
 | 
						||
        display: flex;
 | 
						||
        align-items: center;
 | 
						||
        justify-content: center;
 | 
						||
 | 
						||
        &.cancel-btn {
 | 
						||
          background: #f8f9fa;
 | 
						||
          color: #666;
 | 
						||
 | 
						||
          &:active {
 | 
						||
            background: #e9ecef;
 | 
						||
          }
 | 
						||
        }
 | 
						||
 | 
						||
        &.confirm-btn {
 | 
						||
          background: #005bac;
 | 
						||
          color: #fff;
 | 
						||
          font-weight: 600;
 | 
						||
 | 
						||
          &:active {
 | 
						||
            background: #004494;
 | 
						||
          }
 | 
						||
 | 
						||
          &.disabled {
 | 
						||
            background: #e9ecef;
 | 
						||
            color: #adb5bd;
 | 
						||
            cursor: not-allowed;
 | 
						||
 | 
						||
            &:active {
 | 
						||
              background: #e9ecef;
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
</style>
 |