小程序初始提交
This commit is contained in:
411
cool-unix/uni_modules/cool-ui/components/cl-input/cl-input.uvue
Normal file
411
cool-unix/uni_modules/cool-ui/components/cl-input/cl-input.uvue
Normal file
@@ -0,0 +1,411 @@
|
||||
<template>
|
||||
<view
|
||||
class="cl-input"
|
||||
:class="[
|
||||
pt.className,
|
||||
{
|
||||
'is-dark': isDark,
|
||||
'cl-input--border': border,
|
||||
'cl-input--focus': isFocus,
|
||||
'cl-input--disabled': isDisabled,
|
||||
'cl-input--error': isError
|
||||
}
|
||||
]"
|
||||
@tap="onTap"
|
||||
>
|
||||
<slot name="prepend"></slot>
|
||||
|
||||
<view class="cl-input__icon !pl-0 pr-[12rpx]" v-if="prefixIcon">
|
||||
<cl-icon
|
||||
:name="prefixIcon"
|
||||
:size="pt.prefixIcon?.size ?? 32"
|
||||
:pt="{ className: parseClass([pt.prefixIcon?.className]) }"
|
||||
></cl-icon>
|
||||
</view>
|
||||
|
||||
<input
|
||||
class="cl-input__inner"
|
||||
:class="[
|
||||
{
|
||||
'is-disabled': isDisabled,
|
||||
'is-dark': isDark
|
||||
},
|
||||
ptClassName
|
||||
]"
|
||||
:style="inputStyle"
|
||||
:value="value"
|
||||
:disabled="readonly ?? isDisabled"
|
||||
:type="type"
|
||||
:password="isPassword"
|
||||
:focus="isFocus"
|
||||
:placeholder="placeholder"
|
||||
:placeholder-class="`text-surface-400 ${placeholderClass}`"
|
||||
:maxlength="maxlength"
|
||||
:cursor-spacing="cursorSpacing"
|
||||
:confirm-type="confirmType"
|
||||
:confirm-hold="confirmHold"
|
||||
:adjust-position="adjustPosition"
|
||||
:hold-keyboard="holdKeyboard"
|
||||
@input="onInput"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@confirm="onConfirm"
|
||||
@keyboardheightchange="onKeyboardheightchange"
|
||||
/>
|
||||
|
||||
<view class="cl-input__icon" v-if="suffixIcon">
|
||||
<cl-icon
|
||||
:name="suffixIcon"
|
||||
:size="pt.suffixIcon?.size ?? 32"
|
||||
:pt="{ className: parseClass([pt.prefixIcon?.className]) }"
|
||||
></cl-icon>
|
||||
</view>
|
||||
|
||||
<view class="cl-input__icon" @tap="clear" v-if="showClear">
|
||||
<cl-icon
|
||||
name="close-circle-fill"
|
||||
:size="32"
|
||||
:pt="{ className: '!text-surface-400' }"
|
||||
></cl-icon>
|
||||
</view>
|
||||
|
||||
<view class="cl-input__icon" @tap="showPassword" v-if="password">
|
||||
<cl-icon
|
||||
:name="isPassword ? 'eye-line' : 'eye-off-line'"
|
||||
:size="32"
|
||||
:pt="{ className: '!text-surface-300' }"
|
||||
></cl-icon>
|
||||
</view>
|
||||
|
||||
<slot name="append"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch, type PropType } from "vue";
|
||||
import type { ClInputType, PassThroughProps } from "../../types";
|
||||
import { isDark, parseClass, parsePt } from "@/cool";
|
||||
import type { ClIconProps } from "../cl-icon/props";
|
||||
import { t } from "@/locale";
|
||||
import { useForm, useFormItem, useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-input"
|
||||
});
|
||||
|
||||
// 组件属性定义
|
||||
const props = defineProps({
|
||||
// 透传样式
|
||||
pt: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
// 绑定值
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 输入框类型
|
||||
type: {
|
||||
type: String as PropType<ClInputType>,
|
||||
default: "text"
|
||||
},
|
||||
// 前缀图标
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 后缀图标
|
||||
suffixIcon: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 是否密码框
|
||||
password: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否自动聚焦
|
||||
autofocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否只读
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
// 占位符
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: () => t("请输入")
|
||||
},
|
||||
// 占位符样式类
|
||||
placeholderClass: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 是否显示边框
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否可清除
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 光标与键盘的距离
|
||||
cursorSpacing: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
// 点击键盘确认按钮时是否保持键盘不收起
|
||||
confirmHold: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 设置键盘右下角按钮的文字
|
||||
confirmType: {
|
||||
type: String as PropType<"done" | "go" | "next" | "search" | "send">,
|
||||
default: "done"
|
||||
},
|
||||
// 键盘弹起时,是否自动上推页面
|
||||
adjustPosition: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 最大输入长度
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 140
|
||||
},
|
||||
// 是否保持键盘不收起
|
||||
holdKeyboard: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
// 事件定义
|
||||
const emit = defineEmits([
|
||||
"update:modelValue",
|
||||
"input",
|
||||
"change",
|
||||
"focus",
|
||||
"blur",
|
||||
"confirm",
|
||||
"clear",
|
||||
"keyboardheightchange"
|
||||
]);
|
||||
|
||||
// cl-form 上下文
|
||||
const { disabled } = useForm();
|
||||
|
||||
// cl-form-item 上下文
|
||||
const { isError } = useFormItem();
|
||||
|
||||
// 是否禁用
|
||||
const isDisabled = computed(() => {
|
||||
return disabled.value || props.disabled;
|
||||
});
|
||||
|
||||
// 透传样式类型定义
|
||||
type PassThrough = {
|
||||
className?: string;
|
||||
inner?: PassThroughProps;
|
||||
prefixIcon?: ClIconProps;
|
||||
suffixIcon?: ClIconProps;
|
||||
};
|
||||
|
||||
// 解析透传样式
|
||||
const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
|
||||
// 字号
|
||||
const { ptClassName, getSize } = useSize(() => pt.value.inner?.className ?? "");
|
||||
|
||||
// 输入框样式
|
||||
const inputStyle = computed(() => {
|
||||
const style = {};
|
||||
|
||||
// 字号
|
||||
const fontSize = getSize(null);
|
||||
if (fontSize != null) {
|
||||
style["fontSize"] = fontSize;
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
// 绑定值
|
||||
const value = ref<string>("");
|
||||
|
||||
// 是否聚焦
|
||||
const isFocus = ref<boolean>(props.autofocus);
|
||||
|
||||
// 是否显示清除按钮
|
||||
const showClear = computed(() => {
|
||||
return isFocus.value && props.clearable && value.value != "";
|
||||
});
|
||||
|
||||
// 是否显示密码
|
||||
const isPassword = ref(props.password);
|
||||
|
||||
// 切换密码显示状态
|
||||
function showPassword() {
|
||||
isPassword.value = !isPassword.value;
|
||||
}
|
||||
|
||||
// 获取焦点事件
|
||||
function onFocus(e: UniInputFocusEvent) {
|
||||
isFocus.value = true;
|
||||
emit("focus", e);
|
||||
}
|
||||
|
||||
// 失去焦点事件
|
||||
function onBlur(e: UniInputBlurEvent) {
|
||||
emit("blur", e);
|
||||
|
||||
setTimeout(() => {
|
||||
isFocus.value = false;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// 输入事件
|
||||
function onInput(e: UniInputEvent) {
|
||||
const v1 = e.detail.value;
|
||||
const v2 = value.value;
|
||||
|
||||
value.value = v1;
|
||||
|
||||
emit("update:modelValue", v1);
|
||||
emit("input", e);
|
||||
|
||||
if (v1 != v2) {
|
||||
emit("change", v1);
|
||||
}
|
||||
}
|
||||
|
||||
// 点击确认按钮事件
|
||||
function onConfirm(e: UniInputConfirmEvent) {
|
||||
emit("confirm", e);
|
||||
}
|
||||
|
||||
// 键盘高度变化事件
|
||||
function onKeyboardheightchange(e: UniInputKeyboardHeightChangeEvent) {
|
||||
emit("keyboardheightchange", e);
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
function onTap() {
|
||||
if (isDisabled.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
isFocus.value = true;
|
||||
}
|
||||
|
||||
// 聚焦方法
|
||||
function focus() {
|
||||
setTimeout(() => {
|
||||
isFocus.value = false;
|
||||
|
||||
nextTick(() => {
|
||||
isFocus.value = true;
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// 清除方法
|
||||
function clear() {
|
||||
value.value = "";
|
||||
|
||||
emit("update:modelValue", "");
|
||||
emit("change", "");
|
||||
emit("clear");
|
||||
|
||||
// #ifdef H5
|
||||
focus();
|
||||
// #endif
|
||||
}
|
||||
|
||||
watch(
|
||||
computed(() => props.modelValue),
|
||||
(val: string) => {
|
||||
value.value = val;
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
isFocus,
|
||||
focus,
|
||||
clear
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cl-input {
|
||||
@apply flex flex-row items-center bg-white duration-200;
|
||||
@apply rounded-lg;
|
||||
height: 66rpx;
|
||||
padding: 0 20rpx;
|
||||
transition-property: background-color, border-color;
|
||||
|
||||
&__inner {
|
||||
@apply h-full text-surface-700;
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
|
||||
&.is-dark {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
@apply flex items-center justify-center h-full;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
&--border {
|
||||
@apply border border-solid border-surface-200;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
@apply bg-surface-100 opacity-70;
|
||||
}
|
||||
|
||||
&--focus {
|
||||
&.cl-input--border {
|
||||
@apply border-primary-500;
|
||||
}
|
||||
}
|
||||
|
||||
&--error {
|
||||
@apply border-red-500;
|
||||
}
|
||||
|
||||
&.is-dark {
|
||||
@apply bg-surface-800;
|
||||
|
||||
&.cl-input--border {
|
||||
@apply border-surface-600;
|
||||
|
||||
&.cl-input--focus {
|
||||
@apply border-primary-500;
|
||||
}
|
||||
}
|
||||
|
||||
&.cl-input--disabled {
|
||||
@apply bg-surface-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user