更新:登录功能
This commit is contained in:
148
uni_modules/wot-design-uni/components/wd-search/index.scss
Normal file
148
uni_modules/wot-design-uni/components/wd-search/index.scss
Normal file
@@ -0,0 +1,148 @@
|
||||
@import '../common/abstracts/_mixin.scss';
|
||||
@import '../common/abstracts/variable.scss';
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(search) {
|
||||
background: $-dark-background4;
|
||||
|
||||
@include e(block) {
|
||||
background-color: $-dark-background;
|
||||
}
|
||||
|
||||
@include e(input) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(cover) {
|
||||
background-color: $-dark-background;
|
||||
}
|
||||
|
||||
@include e(search-icon) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(search-left-icon) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(clear) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(cancel) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include when(light) {
|
||||
background: $-dark-background4;
|
||||
|
||||
.wd-search__block {
|
||||
background: $-dark-background7;
|
||||
}
|
||||
|
||||
.wd-search__cover {
|
||||
background: $-dark-background7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(search) {
|
||||
display: flex;
|
||||
padding: $-search-padding;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
|
||||
@include e(block) {
|
||||
flex: 1;
|
||||
background-color: $-search-input-bg;
|
||||
border-radius: $-search-input-radius;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
@include e(field) {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
@include e(input) {
|
||||
flex: 1;
|
||||
height: $-search-input-height;
|
||||
box-sizing: border-box;
|
||||
padding: $-search-input-padding;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: $-search-input-fs;
|
||||
-webkit-appearance: none;
|
||||
outline: none;
|
||||
color: $-search-input-color;
|
||||
z-index: 0;
|
||||
|
||||
@include lineEllipsis;
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
@include e(cover) {
|
||||
width: 100%;
|
||||
height: $-search-input-height;
|
||||
background-color: $-search-input-bg;
|
||||
line-height: $-search-input-height;
|
||||
font-size: $-search-input-fs;
|
||||
border-radius: $-search-input-radius;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
@include edeep(search-icon) {
|
||||
margin-right: 8px;
|
||||
color: $-search-icon-color;
|
||||
font-size: $-search-icon-size;
|
||||
}
|
||||
@include edeep(search-left-icon) {
|
||||
position: absolute;
|
||||
font-size: $-search-icon-size;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
transform: translateY(-50%);
|
||||
color: $-search-icon-color;
|
||||
}
|
||||
@include e(placeholder-txt) {
|
||||
color: $-search-placeholder-color;
|
||||
font-size: $-search-input-fs;
|
||||
}
|
||||
@include edeep(clear) {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
padding: 6px 9px 6px 7px;
|
||||
color: $-search-cancel-color;
|
||||
}
|
||||
@include edeep(clear-icon) {
|
||||
vertical-align: middle;
|
||||
font-size: $-search-clear-icon-size;
|
||||
}
|
||||
@include e(cancel) {
|
||||
padding: $-search-cancel-padding;
|
||||
height: $-search-input-height;
|
||||
line-height: $-search-input-height;
|
||||
font-size: $-search-cancel-fs;
|
||||
color: $-search-cancel-color;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
@include when(light) {
|
||||
background: $-search-light-bg;
|
||||
|
||||
.wd-search__block {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.wd-search__cover {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
@include when(without-cancel) {
|
||||
padding-right: $-search-side-padding;
|
||||
}
|
||||
}
|
||||
102
uni_modules/wot-design-uni/components/wd-search/types.ts
Normal file
102
uni_modules/wot-design-uni/components/wd-search/types.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-09-01 15:42:04
|
||||
* @LastEditTime: 2024-09-21 15:36:09
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-search\types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import { baseProps, makeBooleanProp, makeNumberProp, makeNumericProp, makeStringProp } from '../common/props'
|
||||
|
||||
export const searchProps = {
|
||||
...baseProps,
|
||||
customInputClass: makeStringProp(''),
|
||||
/**
|
||||
* 输入框内容,双向绑定
|
||||
* 类型: string
|
||||
* 默认值: ''
|
||||
*/
|
||||
modelValue: makeStringProp(''),
|
||||
|
||||
/**
|
||||
* 是否使用输入框右侧插槽
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
* @deprecated 该属性已废弃,将在下一个minor版本被移除,直接使用插槽即可
|
||||
*/
|
||||
useSuffixSlot: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 搜索框占位文本
|
||||
* 类型: string
|
||||
*/
|
||||
placeholder: String,
|
||||
|
||||
/**
|
||||
* 搜索框右侧文本
|
||||
* 类型: string
|
||||
*/
|
||||
cancelTxt: String,
|
||||
|
||||
/**
|
||||
* 搜索框亮色(白色)
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
light: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 是否隐藏右侧文本
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
hideCancel: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 是否禁用搜索框
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 原生属性,设置最大长度。-1 表示无限制
|
||||
* 类型: string / number
|
||||
* 默认值: -1
|
||||
*/
|
||||
maxlength: makeNumberProp(-1),
|
||||
|
||||
/**
|
||||
* placeholder 居左边
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
*/
|
||||
placeholderLeft: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 是否自动聚焦
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
* 最低版本: 0.1.63
|
||||
*/
|
||||
focus: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 是否在点击清除按钮时聚焦输入框
|
||||
* 类型: boolean
|
||||
* 默认值: false
|
||||
* 最低版本: 0.1.63
|
||||
*/
|
||||
focusWhenClear: makeBooleanProp(false),
|
||||
|
||||
/**
|
||||
* 原生属性,指定 placeholder 的样式,目前仅支持color,font-size和font-weight
|
||||
*/
|
||||
placeholderStyle: String,
|
||||
|
||||
/**
|
||||
* 原生属性,指定 placeholder 的样式类
|
||||
*/
|
||||
placeholderClass: makeStringProp('')
|
||||
}
|
||||
187
uni_modules/wot-design-uni/components/wd-search/wd-search.vue
Normal file
187
uni_modules/wot-design-uni/components/wd-search/wd-search.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<view :class="rootClass" :style="customStyle">
|
||||
<view class="wd-search__block">
|
||||
<slot name="prefix"></slot>
|
||||
<view class="wd-search__field">
|
||||
<view v-if="!placeholderLeft" :style="coverStyle" class="wd-search__cover" @click="closeCover">
|
||||
<wd-icon name="search" custom-class="wd-search__search-icon"></wd-icon>
|
||||
<text :class="`wd-search__placeholder-txt ${placeholderClass}`">{{ placeholder || translate('search') }}</text>
|
||||
</view>
|
||||
<wd-icon v-if="showInput || inputValue || placeholderLeft" name="search" custom-class="wd-search__search-left-icon"></wd-icon>
|
||||
<input
|
||||
v-if="showInput || inputValue || placeholderLeft"
|
||||
:placeholder="placeholder || translate('search')"
|
||||
:placeholder-class="`wd-search__placeholder-txt ${placeholderClass}`"
|
||||
:placeholder-style="placeholderStyle"
|
||||
confirm-type="search"
|
||||
v-model="inputValue"
|
||||
:class="['wd-search__input', customInputClass]"
|
||||
@focus="handleFocus"
|
||||
@input="handleInput"
|
||||
@blur="handleBlur"
|
||||
@confirm="handleConfirm"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:focus="isFocused"
|
||||
/>
|
||||
<wd-icon v-if="inputValue" custom-class="wd-search__clear wd-search__clear-icon" name="error-fill" @click="handleClear" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<slot v-if="!hideCancel" name="suffix">
|
||||
<view class="wd-search__cancel" @click="handleCancel">
|
||||
{{ cancelTxt || translate('cancel') }}
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'wd-search',
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { type CSSProperties, computed, onMounted, ref, watch } from 'vue'
|
||||
import { objToStyle, pause } from '../common/util'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { searchProps } from './types'
|
||||
|
||||
const props = defineProps(searchProps)
|
||||
const emit = defineEmits(['update:modelValue', 'change', 'clear', 'search', 'focus', 'blur', 'cancel'])
|
||||
|
||||
const { translate } = useTranslate('search')
|
||||
|
||||
const isFocused = ref<boolean>(false) // 是否聚焦中
|
||||
const showInput = ref<boolean>(false) // 是否显示输入框 用于实现聚焦的hack
|
||||
const inputValue = ref<string>('') // 输入框的值
|
||||
const showPlaceHolder = ref<boolean>(true)
|
||||
const clearing = ref<boolean>(false)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
inputValue.value = newValue
|
||||
if (newValue) {
|
||||
showInput.value = true
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.focus,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
if (props.disabled) return
|
||||
closeCover()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.focus) {
|
||||
closeCover()
|
||||
}
|
||||
})
|
||||
|
||||
const rootClass = computed(() => {
|
||||
return `wd-search ${props.light ? 'is-light' : ''} ${props.hideCancel ? 'is-without-cancel' : ''} ${props.customClass}`
|
||||
})
|
||||
|
||||
const coverStyle = computed(() => {
|
||||
const coverStyle: CSSProperties = {
|
||||
display: inputValue.value === '' && showPlaceHolder.value ? 'flex' : 'none'
|
||||
}
|
||||
|
||||
return objToStyle(coverStyle)
|
||||
})
|
||||
|
||||
async function hackFocus(focus: boolean) {
|
||||
showInput.value = focus
|
||||
await pause()
|
||||
isFocused.value = focus
|
||||
}
|
||||
|
||||
async function closeCover() {
|
||||
if (props.disabled) return
|
||||
await pause(100)
|
||||
showPlaceHolder.value = false
|
||||
hackFocus(true)
|
||||
}
|
||||
|
||||
function handleInput(event: any) {
|
||||
inputValue.value = event.detail.value
|
||||
emit('update:modelValue', event.detail.value)
|
||||
emit('change', {
|
||||
value: event.detail.value
|
||||
})
|
||||
}
|
||||
|
||||
async function handleClear() {
|
||||
inputValue.value = ''
|
||||
if (props.focusWhenClear) {
|
||||
clearing.value = true
|
||||
isFocused.value = false
|
||||
}
|
||||
await pause()
|
||||
if (props.focusWhenClear) {
|
||||
showPlaceHolder.value = false
|
||||
hackFocus(true)
|
||||
} else {
|
||||
showPlaceHolder.value = true
|
||||
hackFocus(false)
|
||||
}
|
||||
emit('change', {
|
||||
value: ''
|
||||
})
|
||||
emit('update:modelValue', '')
|
||||
emit('clear')
|
||||
}
|
||||
|
||||
function handleConfirm({ detail: { value } }: any) {
|
||||
// 组件触发search事件
|
||||
emit('search', {
|
||||
value
|
||||
})
|
||||
}
|
||||
|
||||
function handleFocus() {
|
||||
showPlaceHolder.value = false
|
||||
emit('focus', {
|
||||
value: inputValue.value
|
||||
})
|
||||
}
|
||||
|
||||
async function handleBlur() {
|
||||
// 等待150毫秒,clear执行完毕
|
||||
await pause(150)
|
||||
if (clearing.value) {
|
||||
clearing.value = false
|
||||
return
|
||||
}
|
||||
// 组件触发blur事件
|
||||
showPlaceHolder.value = !inputValue.value
|
||||
showInput.value = !showPlaceHolder.value
|
||||
isFocused.value = false
|
||||
emit('blur', {
|
||||
value: inputValue.value
|
||||
})
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
emit('cancel', {
|
||||
value: inputValue.value
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
Reference in New Issue
Block a user