@@ -1,5 +1,41 @@
< template >
< view class = "page-container" >
<!-- 人员选项卡区域 -- >
< view class = "tabs-container" >
< view class = "tabs-header" >
< view class = "tabs-title" >
< text class = "title-text" > 报名人员 < / text >
< view class = "header-actions" >
< view class = "person-counter" >
< text class = "counter-text" > { { formData . userList . length } } 人 < / text >
< / view >
< view class = "header-add-btn" @click ="addNewUser" >
< t -icon name = "add" size = "16px" > < / t-icon >
< / view >
< / view >
< / view >
< / view >
< scroll-view scroll -x = " true " class = "tabs-scroll-view" show -scrollbar = " false " >
< view class = "tabs" >
< view
v-for = "(user, index) in formData.userList"
:key = "index"
class = "tab"
: class = "{ active: activeTabIndex === index }"
@click ="switchTab(index)"
>
< view class = "tab-content" >
< view class = "tab-icon" v-if = "activeTabIndex === index" >
< t -icon name = "user" size = "16px" > < / t-icon >
< / view >
< text class = "tab-text" > { { user . userName || ` 人员 ${ index + 1 } ` } } < / text >
< / view >
< / view >
< / view >
< / scroll-view >
< view class = "tabs-indicator" > < / view >
< / view >
< view class = "form-area" >
< t-form
ref = "formRef"
@@ -9,6 +45,7 @@
label -align = " left "
scroll -to -first -error = " auto "
labelWidth = "90px"
:requiredMark = "true"
>
<!-- < view class = "form-block" > -- >
<!-- < view class = "form-block-title" > -- >
@@ -29,20 +66,19 @@
< view class = "form-block" >
< view class = "form-block-title" >
< t-icon name = "usergroup" > < / t-icon >
报名人员信息
< / view >
< view v-for = "( user,index) in formData.userList" :key="index" class="user-card " >
< view class = "user-card-header " >
< view class = "user-card-header-title" >
< span > { { index + 1 } } < / span >
< / view >
< view class = "remove" @click ="removeUser(index)" >
< text > 报名人员信息 < / text >
< text class = "form-subtitle" > { { activeTabIndex + 1 } } / { { formData . userList . length } } < / text >
< view class = "user-actions " >
< view class = "remove-user" @click ="removeUser(activeTabIndex)" v-if = "formData.userList.length > 1 ">
< t -icon name = "delete" size = "18px" > < / t-icon >
< / view >
< / view >
< / view >
<!-- 所有人员的表单 , 使用v - show控制显示 -- >
< view v-for = "(user, index) in formData.userList" :key="index" class="form-fields-container" v-show="activeTabIndex === index" >
< t -form -item label = "姓名" :name = "`userList[${index}].userName`"
: rules = "[{required:true,message: '请输入姓名'}]" >
: rules = "[{required:true,message: '请输入姓名'}]" >
< t-input v-model = "user.userName" borderless placeholder="请输入内容" > < / t -input >
< / t-form-item >
< t-form-item label = "性别" :name = "`userList[${index}].sex`" : rules = "[{required:true,message: '请选择性别'}]" >
@@ -51,47 +87,65 @@
< t-radio :block = "false" label = "女" value = "女" / >
< / t-radio-group >
< / t-form-item >
< t-form-item label = "单位名称" >
< t-input v-model = "user.unitName" borderless placeholder="请输入单位名称" readonly > < / t-input >
< / t-form-item >
< t-form-item label = "职务" :name = "`userList[${index}].position`"
: rules = "[{required:true,message: '请输入职务'}]" >
: rules = "[{required:true,message: '请输入职务'}]" >
< t-input v-model = "user.position" borderless placeholder="请输入职务" > < / t -input >
< / t-form-item >
< t-form-item label = "身份证号" :name = "`userList[${index}].idCard`"
: rules = "[{required:true,message: '请输入身份证号码'},{idcard:true, message: '请输入正确的身份证号码'}]" >
: rules = "[{required:true,message: '请输入身份证号码'},{idcard:true, message: '请输入正确的身份证号码'}]" >
< t-input v-model = "user.idCard" borderless placeholder="请输入身份证号码" > < / t -input >
< / t-form-item >
< t-form-item label = "联系电话" :name = "`userList[${index}].phone`"
: rules = "[{required:true,message: '请输入联系电话'},{telnumber:true, message: '请输入正确的联系电话'}]" >
: rules = "[{required:true,message: '请输入联系电话'},{telnumber:true, message: '请输入正确的联系电话'}]" >
< t-input v-model = "user.phone" borderless placeholder="请输入联系电话" > < / t -input >
< / t-form-item >
< t-form-item label = "是否住宿" :name = "`userList[${index}].isStay`"
: rules = "[{required:true,message: '请选择是否住宿'}]" >
: rules = "[{required:true,message: '请选择是否住宿'}]" >
< t-radio-group v-model = "user.isStay" class="radio-box" >
< t -radio :block = "false" name = "radio" :value = "true" label = "是" / >
< t-radio :block = "false" name = "radio" :value = "false" label = "否" / >
< / t-radio-group >
< / t-form-item >
< t-form-item label = "是否联系人" :name = "`userList[${index}].isContacts`"
: rules = "[{required:true,message: '请选择是否为联系人'}]" >
: rules = "[{required:true,message: '请选择是否为联系人'}]" >
< t-radio-group v-model = "user.isContacts" class="radio-box" >
< t -radio :block = "false" name = "radio" :value = "true" label = "是" / >
< t-radio :block = "false" name = "radio" :value = "false" label = "否" / >
< / t-radio-group >
< / t-form-item >
< t-form-item label = "展示才艺" :name = "`userList[${index}].isShowSkill`" : rules = "[{required:true,message: '请选择是否展示才艺'}]" >
< t-radio-group v-model = "user.isShowSkill" class="radio-box" >
< t -radio :block = "false" name = "radio" :value = "true" label = "是" / >
< t-radio :block = "false" name = "radio" :value = "false" label = "否" / >
< / t-radio-group >
< / t-form-item >
< template v-if = "`userList[${index}].isShowSkill`" >
< t -form -item label = "才艺名称" :name = "`userList[${index}].skillName`" : rules = "[{required:user.isShowSkill===true,message: '请填写才艺名称'}]" >
< t-input v-model = "user.skillName" borderless placeholder="请输入才艺名称" > < / t -input >
< / t-form-item >
< t-form-item label = "所需器材" :name = "`userList[${index}].equip`" : rules = "[{required:user.isShowSkill===true,message: '请填写才艺所需器材'}]" >
< t-input v-model = "user.equip" borderless placeholder="请填写才艺所需器材" > < / t -input >
< / t-form-item >
< / template >
< t-form-item label = "参加嘉年华" :name = "`userList[${index}].isParty`" : rules = "[{required:true,message: '请选择是否参加嘉年华'}]" >
< t-radio-group v-model = "user.isParty" class="radio-box" >
< t -radio :block = "false" name = "radio" :value = "true" label = "是" / >
< t-radio :block = "false" name = "radio" :value = "false" label = "否" / >
< / t-radio-group >
< / t-form-item >
< / view >
< / view >
< / t-form >
< / view >
<!-- 悬浮添加按钮 -- >
< view class = "float-add-btn" @click ="formData.userList.push({})" >
< t -icon name = "plus" size = "24px" color = "#fff" > < / t-icon >
< / view >
< view class = "footer" >
< view class = "agreement-checkbox" >
< t-checkbox label = "多选" icon = "rectangle" v -model :checked = "agreementChecked" default -checked >
< label > 我已阅读并同意
< text class = "agreement-link" > 《 参赛承诺书 》 < / text >
< text class = "agreement-link" @click ="showAgreementPopup" > 《 参赛承诺书 》 < / text >
< / label >
< / t -checkbox >
< / view >
@@ -112,12 +166,32 @@
:steps = "guideSteps"
>
< / t-guide >
< / view >
<!-- 协议确认弹窗 -- >
< t-popup v -model :visible = "agreementPopupVisible" placement = "center" :close-on-overlay-click = "false" >
< view class = "agreement-popup" >
< view class = "agreement-popup-header" >
< text class = "agreement-popup-title" > 参赛条款与免责声明 < / text >
< / view >
< view class = "agreement-popup-content" >
< view class = "agreement-popup-text" >
<!-- 阅读并同意本承诺书内容 , 点击 "确定并报名" 即表示您已充分理解并接受所有条款 , 承担相应法律责任 。 -- >
< rich-text :nodes = "agreementContent" > < / rich-text >
< / view >
< / view >
< view class = "agreement-popup-footer" >
< t-button variant = "outline" block @click ="closeAgreementPopup" class = "agreement-btn" > 取消 < / t-button >
< t-button theme = "primary" block :disabled = "!canConfirmAgreement" @click ="confirmAgreement" class = "agreement-btn" >
{ { canConfirmAgreement ? '确定并报名' : ` 请阅读( ${ agreementCountdown } 秒) ` } }
< / t-button >
< / view >
< / view >
< / t-popup >
< / template >
< script setup >
import { ref } from 'vue'
import { ref , computed } from 'vue'
import { useRequest } from '@/utils/request' ;
import { Dialog , Toast } from "tdesign-mobile-vue" ;
import { onLoad } from "@dcloudio/uni-app" ;
@@ -126,19 +200,84 @@ import {useUserStore} from "@/store";
const request = useRequest ( )
const userStore = useUserStore ( )
// 当前选中的选项卡索引
const activeTabIndex = ref ( 0 )
// 切换选项卡
function switchTab ( index ) {
activeTabIndex . value = index
}
// 添加新用户
function addNewUser ( ) {
formData . value . userList . push ( {
userName : '' ,
sex : null ,
unitName : userStore ? . userInfo ? . unit ? . name ,
position : null ,
idCard : null ,
phone : null ,
isStay : null ,
isContacts : false ,
isShowSkill : false ,
skillName : null ,
equip : null ,
isParty : false
} )
// 切换到新添加的用户选项卡
setTimeout ( ( ) => {
activeTabIndex . value = formData . value . userList . length - 1
// 滚动到最右边
scrollToRight ( )
} , 10 )
}
// 滚动到指定选项卡
function scrollToTab ( index ) {
const query = uni . createSelectorQuery ( )
query . selectAll ( '.tab' ) . boundingClientRect ( )
query . select ( '.tabs-scroll-view' ) . boundingClientRect ( )
query . exec ( ( res ) => {
if ( res && res [ 0 ] && res [ 0 ] [ index ] && res [ 1 ] ) {
const tabElement = res [ 0 ] [ index ]
const scrollView = res [ 1 ]
const scrollLeft = tabElement . left - scrollView . left - ( scrollView . width / 2 ) + ( tabElement . width / 2 )
uni . pageScrollTo ( {
scrollLeft : scrollLeft > 0 ? scrollLeft : 0 ,
duration : 300
} )
}
} )
}
// 滚动到最右边
function scrollToRight ( ) {
const query = uni . createSelectorQuery ( )
query . select ( '.tabs-scroll-view' ) . boundingClientRect ( )
query . exec ( ( res ) => {
if ( res && res [ 0 ] ) {
const scrollView = res [ 0 ]
const scrollWidth = scrollView . scrollWidth
const clientWidth = scrollView . width
const scrollLeft = scrollWidth - clientWidth
if ( scrollLeft > 0 ) {
uni . pageScrollTo ( {
scrollLeft : scrollLeft ,
duration : 300
} )
}
}
} )
}
// 引导部分
const guideCurrent = ref ( - 1 )
const guideSteps = [
{
element : ( ) => document . querySelector ( '.float -add-btn' ) ,
element : ( ) => document . querySelector ( '.header -add-btn' ) ,
title : '添加活动报名人员' ,
placement : 'top'
} ,
{
element : ( ) => document . querySelector ( '.t-form' ) ,
title : '填写报名信息' ,
placement : 'top'
} ,
{
element : ( ) => document . querySelector ( '.footer' ) ,
title : '提交报名信息' ,
@@ -152,25 +291,52 @@ const isSignUp = ref(null)
const agreementChecked = ref ( false )
const formRef = ref ( null )
const formData = ref ( {
userList : [ { } ]
userList : [ ]
} )
// 协议弹窗相关
const agreementPopupVisible = ref ( false )
const agreementCountdown = ref ( 5 )
const countdownTimer = ref ( null )
const canConfirmAgreement = ref ( false )
const agreementContent = ref ( null )
onLoad ( ( option ) => {
onLoad ( async ( option ) => {
if ( option . id ) {
actId . value = option . id
formData . value . activityId = option . id
listSignUpUser ( )
getIsSignUp ( )
await listSignUpUser ( )
await getIsSignUp ( )
await getAgreement ( )
// 没报名进行引导
if ( formData . value . userList . length === 0 ) {
if ( ! formData . value . userList || formData . value . userList . length === 0 ) {
guideCurrent . value = 0
//formData.value.unitName = userStore.userInfo?.unit.name
// 默认是本人的信息
formData . value . userList . push ( {
userName : userStore . userInfo . userName ,
sex : userStore . userInfo . sex ,
unitName : userStore ? . userInfo ? . unit ? . name ,
position : null ,
idCard : userStore . userInfo . idCard ,
phone : userStore . userInfo . phone ,
isStay : null
} )
}
} else {
Toast ( { message : 'ID不存在' , theme : 'error' } ) ;
}
} )
// 查询参赛承诺书
async function getAgreement ( ) {
try {
const { code , data } = await request . get ( '/client/activity/agreement/' + actId . value )
if ( code === 0 && data ) {
agreementContent . value = data
}
} catch ( e ) {
console . error ( e )
}
}
// 查询报名人员信息
async function listSignUpUser ( ) {
@@ -216,28 +382,86 @@ async function validaForm() {
// 承诺书
async function validateAgreement ( ) {
return new Promise ( ( resolve , reject ) => {
if ( agreementChecked . value ) {
resolve ( true )
return
}
// Always show the popup regardless of checkbox state
// if (agreementChecked.value) {
// resolve(true)
// return
// }
Dialog . confirm ( {
title : '提示' ,
content : '参赛条款与免责声明:阅读并同意本承诺书内容,点击"确定并报名"即表示您已充分理解并接受所有条款,承担相应法律责任。' ,
confirmBtn : '确定并报名' ,
cancelBtn : '取消' ,
onConfirm : ( ) => {
agreementChecked . value = true
resolve ( true )
} ,
onCancel : ( ) => {
agreementChecked . value = false
resolve ( false )
}
} )
// 重置倒计时
agreementCountdown . value = 5
canConfirmAgreement . value = false
// 显示弹窗
agreementPopupVisible . value = true
// 启动倒计时
startAgreementCountdown ( resolve )
} )
}
// 启动协议倒计时
function startAgreementCountdown ( resolvePromise ) {
// 清除可能存在的旧计时器
if ( countdownTimer . value ) {
clearInterval ( countdownTimer . value )
}
// 设置新的计时器
countdownTimer . value = setInterval ( ( ) => {
agreementCountdown . value --
if ( agreementCountdown . value <= 0 ) {
// 倒计时结束,允许确认
clearInterval ( countdownTimer . value )
canConfirmAgreement . value = true
}
} , 1000 )
// 保存 Promise 的 resolve 函数,以便在确认或取消时使用
window . _resolveAgreementPromise = resolvePromise
}
// 确认协议
function confirmAgreement ( ) {
// 只有在倒计时结束后才能确认
if ( ! canConfirmAgreement . value ) return
// 关闭弹窗
agreementPopupVisible . value = false
// 清除计时器
if ( countdownTimer . value ) {
clearInterval ( countdownTimer . value )
}
// 标记已同意协议
agreementChecked . value = true
// 解析 Promise
if ( window . _resolveAgreementPromise ) {
window . _resolveAgreementPromise ( true )
window . _resolveAgreementPromise = null
}
}
// 关闭协议弹窗
function closeAgreementPopup ( ) {
// 关闭弹窗
agreementPopupVisible . value = false
// 清除计时器
if ( countdownTimer . value ) {
clearInterval ( countdownTimer . value )
}
// 解析 Promise 为 false(未同意)
if ( window . _resolveAgreementPromise ) {
window . _resolveAgreementPromise ( false )
window . _resolveAgreementPromise = null
}
}
// 提交表单
async function onSubmit ( ) {
const formRes = await validaForm ( )
@@ -287,12 +511,177 @@ async function removeUser(index) {
Toast ( '至少需要一个报名人员' )
return
}
formData . value . userList . splice ( index , 1 )
Dialog . confirm ( {
title : '提示' ,
content : '确定要删除该报名人员吗?' ,
confirmBtn : '确定' ,
cancelBtn : '取消' ,
onConfirm : ( ) => {
formData . value . userList . splice ( index , 1 )
// 如果删除的是当前选中的选项卡,则选中第一个选项卡
if ( index === activeTabIndex . value ) {
activeTabIndex . value = 0
}
// 如果删除的是前面的选项卡,则当前选中的选项卡索引减1
else if ( index < activeTabIndex . value ) {
activeTabIndex . value --
}
}
} )
}
// 显示协议弹窗
function showAgreementPopup ( ) {
// 重置倒计时
agreementCountdown . value = 5
canConfirmAgreement . value = false
// 显示弹窗
agreementPopupVisible . value = true
// 启动倒计时
startAgreementCountdown ( ( ) => {
// 这里不需要处理,因为协议弹窗会自动显示
} )
}
< / script >
< style scoped lang = "less" >
. tabs - container {
flex - shrink : 0 ;
background - color : # fff ;
box - shadow : 0 2 px 10 px rgba ( 0 , 0 , 0 , 0.05 ) ;
position : relative ;
border - bottom : 1 px solid rgba ( 0 , 0 , 0 , 0.05 ) ;
}
. tabs - header {
padding : 10 px 16 px 5 px ;
}
. tabs - title {
display : flex ;
align - items : center ;
justify - content : space - between ;
margin - bottom : 5 px ;
}
. title - text {
font - size : 16 px ;
font - weight : 500 ;
color : # 333 ;
}
. header - actions {
display : flex ;
align - items : center ;
}
. person - counter {
background - color : # f45a5a ;
border - radius : 12 px ;
padding : 2 px 10 px ;
margin - right : 8 px ;
}
. counter - text {
color : # fff ;
font - size : 12 px ;
font - weight : 500 ;
}
. header - add - btn {
width : 28 px ;
height : 28 px ;
border - radius : 50 % ;
background : linear - gradient ( 135 deg , # f45a5a , # ff7676 ) ;
color : # fff ;
display : flex ;
align - items : center ;
justify - content : center ;
box - shadow : 0 2 px 6 px rgba ( 244 , 90 , 90 , 0.25 ) ;
transition : transform 0.2 s ease ;
}
. header - add - btn : active {
transform : scale ( 0.92 ) ;
}
. tabs - scroll - view {
width : 100 % ;
white - space : nowrap ;
overflow - x : auto ;
scrollbar - width : none ;
- ms - overflow - style : none ;
}
. tabs - scroll - view : : - webkit - scrollbar {
display : none ;
}
. tabs {
display : flex ;
padding : 10 px 12 px ;
align - items : center ;
}
. tab {
display : inline - flex ;
align - items : center ;
justify - content : center ;
min - width : 90 px ;
height : 35 px ;
padding : 0 14 px ;
margin : 0 5 px ;
font - size : 14 px ;
color : # 666 ;
background - color : # f8f8f8 ;
border - radius : 19 px ;
transition : all 0.25 s ease ;
position : relative ;
border : 1 px solid transparent ;
}
. tab - content {
display : flex ;
align - items : center ;
justify - content : center ;
white - space : nowrap ;
overflow : hidden ;
text - overflow : ellipsis ;
max - width : 100 % ;
}
. tab - icon {
margin - right : 4 px ;
display : flex ;
align - items : center ;
}
. tab - text {
white - space : nowrap ;
overflow : hidden ;
text - overflow : ellipsis ;
}
. tab . active {
color : # fff ;
background - color : # f45a5a ;
box - shadow : 0 3 px 8 px rgba ( 244 , 90 , 90 , 0.25 ) ;
font - weight : 500 ;
}
. tabs - indicator {
position : absolute ;
bottom : - 1 px ;
left : 0 ;
width : 100 % ;
height : 2 px ;
background : linear - gradient ( 90 deg , transparent , rgba ( 244 , 90 , 90 , 0.3 ) , transparent ) ;
}
. act - info {
position : fixed ;
top : 44 px ;
@@ -340,6 +729,7 @@ async function removeUser(index) {
flex : 1 ;
overflow - y : auto ;
margin - bottom : 130 px ;
padding - top : 10 px ;
}
. form - block {
@@ -347,6 +737,7 @@ async function removeUser(index) {
background : white ;
margin - bottom : 10 px ;
box - shadow : 0 1 px 3 px rgba ( 0 , 0 , 0 , 0.05 ) ;
border - radius : 8 px ;
. form - block - title {
font - size : 16 px ;
@@ -355,83 +746,45 @@ async function removeUser(index) {
color : # 333 ;
display : flex ;
align - items : center ;
justify - content : flex - start ;
. t - icon {
margin - right : 5 px ;
color : var ( -- td - brand - color ) ;
}
}
}
. user - card {
background : white ;
margin - bottom : 20 px ;
position : relative ;
border - left : 3 px solid # e74c3c ;
padding - left : 12 px ;
. user - card - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
margin - bottom : 15 px ;
. user - card - header - title {
font - weight : 500 ;
color : # 333 ;
font - size : 15 px ;
display : flex ;
align - items : center ;
span {
display : flex ;
justify - content : center ;
align - items : center ;
width : 24 px ;
height : 24 px ;
background - color : # e74c3c ;
color : white ;
border - radius : 50 % ;
font - size : 14 px ;
margin - right : 8 px ;
}
}
. remove {
color : # e74c3c ;
//font-size: 14px;
display : flex ;
align - items : center ;
background : none ;
border : none ;
cursor : pointer ;
. form - subtitle {
font - size : 12 px ;
color : # 999 ;
margin - left : 8 px ;
font - weight : normal ;
}
}
}
. float - add - btn {
position : fixed ;
right : 32 rpx ;
bottom : 160 rpx ;
width : 110 rpx ;
height : 110 rpx ;
border - radius : 50 % ;
background - color : # e74c3c ;
. form - fields - container {
animation : fadeIn 0.3 s ease ;
}
@ keyframes fadeIn {
from { opacity : 0.6 ; }
to { opacity : 1 ; }
}
. user - actions {
display : flex ;
align - items : center ;
justify - content : center ;
z - index : 100 ;
transition : transform 0.2 s ;
margin - left : auto ;
}
. float - add - btn : active {
transform : scale ( 0.95 ) ;
. remove - user {
padding : 5 px ;
color : # f45a5a ;
cursor : pointer ;
}
. radio - box {
width : 100 % ;
display : flex ;
column - gap : 20 px ;
}
. footer {
@@ -439,12 +792,95 @@ async function removeUser(index) {
bottom : 0 ;
left : 0 ;
right : 0 ;
padding : 0 16 px 16 px ;
background - color : white ;
box - shadow : 0 - 1 px 5 px rgba ( 0 , 0 , 0 , 0.1 ) ;
z - index : 10 ;
max - width : 750 px ;
margin : 0 auto ;
width : 100 % ;
padding : 16 px ;
background : white ;
box - shadow : 0 - 2 px 10 px rgba ( 0 , 0 , 0 , 0.05 ) ;
z - index : 99 ;
}
. agreement - checkbox {
margin - bottom : 16 px ;
display : flex ;
align - items : center ;
font - size : 14 px ;
color : # 666 ;
}
. agreement - link {
color : var ( -- td - brand - color ) ;
}
. quick - nav {
position : fixed ;
right : 16 px ;
bottom : 140 px ;
display : flex ;
flex - direction : column ;
gap : 10 px ;
z - index : 90 ;
}
. quick - nav - btn {
width : 40 px ;
height : 40 px ;
border - radius : 50 % ;
background - color : rgba ( 244 , 90 , 90 , 0.9 ) ;
color : white ;
display : flex ;
align - items : center ;
justify - content : center ;
box - shadow : 0 2 px 8 px rgba ( 0 , 0 , 0 , 0.15 ) ;
transition : transform 0.2 s ease , background - color 0.2 s ease ;
}
. quick - nav - btn : active {
transform : scale ( 0.95 ) ;
background - color : rgba ( 244 , 90 , 90 , 1 ) ;
}
/* 协议弹窗样式 */
. agreement - popup {
width : 85 vw ;
max - width : 320 px ;
background - color : # fff ;
border - radius : 16 px ;
overflow : hidden ;
box - shadow : 0 4 px 20 px rgba ( 0 , 0 , 0 , 0.1 ) ;
}
. agreement - popup - header {
padding : 20 px 16 px 10 px ;
text - align : center ;
border - bottom : 1 px solid # f0f0f0 ;
}
. agreement - popup - title {
font - size : 18 px ;
font - weight : 600 ;
color : # 333 ;
}
. agreement - popup - content {
padding : 20 px 16 px ;
max - height : 60 vh ;
overflow - y : auto ;
}
. agreement - popup - text {
font - size : 15 px ;
line - height : 1.5 ;
color : # 666 ;
padding : 0 16 px ;
}
. agreement - popup - footer {
padding : 16 px ;
display : flex ;
gap : 10 px ;
border - top : 1 px solid # f0f0f0 ;
}
. agreement - btn {
height : 44 px ;
}
< / style >