197 lines
4.3 KiB
Vue
197 lines
4.3 KiB
Vue
<script setup>
|
|
import { ref, computed, watch } from 'vue'
|
|
import account from '@/static/images/login/account.png'
|
|
import password from '@/static/images/login/password.png'
|
|
import phone from '@/static/images/login/phone.png'
|
|
import invitation from '@/static/images/login/invitation.png'
|
|
import email from '@/static/images/login/email.png'
|
|
import codeIcon from '@/static/images/login/code.png'
|
|
import viewPassword from '@/static/images/login/view.png'
|
|
import concealPassword from '@/static/images/login/conceal.png'
|
|
|
|
const name = defineModel({
|
|
type: String,
|
|
default: ''
|
|
})
|
|
|
|
const isCode = defineModel('code', {
|
|
type: Boolean,
|
|
default: false
|
|
})
|
|
|
|
/** 倒计时 */
|
|
const countdown = ref(0)
|
|
|
|
/** 启动倒计时 */
|
|
const startCountdown = () => {
|
|
countdown.value = 60
|
|
const timer = setInterval(() => {
|
|
if (countdown.value > 0) {
|
|
countdown.value--
|
|
} else {
|
|
isCode.value = false
|
|
clearInterval(timer)
|
|
}
|
|
}, 1000)
|
|
}
|
|
|
|
watch(
|
|
() => isCode.value,
|
|
v => {
|
|
if (v) {
|
|
startCountdown()
|
|
} else {
|
|
countdown.value = 0
|
|
}
|
|
}
|
|
)
|
|
|
|
const props = defineProps({
|
|
/**
|
|
* 输入框状态类型
|
|
* text: 文本
|
|
* password: 密码
|
|
* number: 数字
|
|
* tel: 手机号
|
|
* email: 邮箱
|
|
*/
|
|
type: {
|
|
type: String,
|
|
default: 'text'
|
|
},
|
|
/**
|
|
* 输入框图标
|
|
* 1: 手机号/邮箱
|
|
* 2: 密码
|
|
* 3: 手机号
|
|
* 4: 邀请码
|
|
* 5: 邮箱
|
|
* 6: 验证码
|
|
*/
|
|
icon: {
|
|
type: String,
|
|
default: '1'
|
|
},
|
|
placeholder: {
|
|
type: String,
|
|
default: '请输入'
|
|
}
|
|
})
|
|
|
|
const emits = defineEmits(['onGetCode'])
|
|
|
|
/** 切换查看密码状态 */
|
|
const showPassword = ref(false)
|
|
|
|
const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #D9D9D9; font-size: 28rpx; font-style: normal; text-transform: none;`
|
|
|
|
const leftIcon = computed(() => {
|
|
switch (props.icon) {
|
|
case '1':
|
|
return account
|
|
case '2':
|
|
return password
|
|
case '3':
|
|
return phone
|
|
case '4':
|
|
return invitation
|
|
case '5':
|
|
return email
|
|
case '6':
|
|
return codeIcon
|
|
default:
|
|
return account
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<view class="cb-input">
|
|
<image :src="leftIcon" mode="heightFix" class="left-icon"></image>
|
|
<input
|
|
v-if="props.type === 'password'"
|
|
v-model="name"
|
|
:password="!showPassword"
|
|
:placeholder-style="placeholderStyle"
|
|
:placeholder="props.placeholder"
|
|
class="input-box"
|
|
/>
|
|
<input
|
|
v-else
|
|
v-model="name"
|
|
:type="props.type"
|
|
:placeholder-style="placeholderStyle"
|
|
:placeholder="props.placeholder"
|
|
class="input-box"
|
|
/>
|
|
<text
|
|
v-if="props.icon === '6'"
|
|
:class="{ 'text-decoration': isCode }"
|
|
class="right-text"
|
|
@click="!isCode && emits('onGetCode')"
|
|
>
|
|
{{ isCode ? `${countdown}秒后重新获取` : '获取验证码' }}
|
|
</text>
|
|
<image
|
|
v-if="props.type === 'password'"
|
|
:src="showPassword ? viewPassword : concealPassword"
|
|
mode="heightFix"
|
|
class="right-icon"
|
|
@click="showPassword = !showPassword"
|
|
></image>
|
|
</view>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.cb-input + .cb-input {
|
|
margin-top: 48rpx;
|
|
}
|
|
.cb-input {
|
|
width: calc(100% - 64rpx);
|
|
height: 96rpx;
|
|
background: #f9f9f9;
|
|
border-radius: 128rpx;
|
|
padding: 0 32rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
.left-icon,
|
|
.right-icon {
|
|
flex-shrink: 0;
|
|
height: 48rpx;
|
|
}
|
|
.left-icon {
|
|
margin-right: 16rpx;
|
|
}
|
|
.input-box {
|
|
width: 100%;
|
|
font-family: PingFang SC, PingFang SC;
|
|
font-weight: 500;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
font-style: normal;
|
|
text-transform: none;
|
|
}
|
|
.right-icon {
|
|
margin-left: 16rpx;
|
|
}
|
|
|
|
.right-text {
|
|
flex-shrink: 0;
|
|
margin-left: 16rpx;
|
|
width: 140rpx;
|
|
color: #00d9c5;
|
|
font-family: PingFang SC, PingFang SC;
|
|
font-weight: 500;
|
|
font-size: 28rpx;
|
|
font-style: normal;
|
|
text-transform: none;
|
|
}
|
|
|
|
.text-decoration {
|
|
width: 202rpx;
|
|
text-align: right;
|
|
color: #d9d9d9;
|
|
}
|
|
}
|
|
</style>
|