Skip to content

Commit

Permalink
feat: 新增 codeInput组件
Browse files Browse the repository at this point in the history
  • Loading branch information
yang1206 committed Jul 13, 2023
1 parent 6e19b1a commit 9b9516b
Show file tree
Hide file tree
Showing 15 changed files with 527 additions and 8 deletions.
3 changes: 2 additions & 1 deletion docs/.vitepress/items.ts
Expand Up @@ -19,7 +19,7 @@ export const components = [
{ text: 'Divider 分割线', link: '/components/layout/divider' },
{ text: 'Grid 宫格', link: '/components/layout/grid' },
{ text: 'Layout 布局', link: '/components/layout/layout' },
{ text: 'Sticky 粘性布局', link: '/components/layout/sticky' },
// { text: 'Sticky 粘性布局', link: '/components/layout/sticky' },
],
},
{
Expand Down Expand Up @@ -49,6 +49,7 @@ export const components = [
{ text: 'Form 表单', link: '/components/dentry/form' },
{ text: 'Input 输入框', link: '/components/dentry/input' },
{ text: 'InputNumber 数字输入框', link: '/components/dentry/inputnumber' },
{ text: 'CodeInput 验证码输入框', link: '/components/dentry/codeinput' },
{ text: 'NumberKeyboard 数字键盘', link: '/components/dentry/numberkeyboard' },
{ text: 'Picker 选择器', link: '/components/dentry/picker' },
{ text: 'Radio 单选按钮', link: '/components/dentry/radio' },
Expand Down
113 changes: 113 additions & 0 deletions docs/components/dentry/codeinput.md
@@ -0,0 +1,113 @@
# CodeInput 验证码输入框

### 介绍

一般用于验证用户短信验证码的场景,该组件参考了 uview-ui 的 [验证码输入框](https://www.uviewui.com/components/codeInput.html)

### 基础用法

```html
<template>
<nut-code-input v-model="state.val1" />
</template>
```

### 横线模式

```html
<template>
<nut-code-input v-model="state.val1" mode="line" />
</template>
```

### 设置长度

```html
<template>
<nut-code-input v-model="state.val2" :maxlength="6" />
</template>
```

### 横线间距

```html
<template>
<nut-code-input v-model="state.val2" :space="0" />
</template>
```

### 调整颜色

```html
<template>
<nut-code-input v-model="state.val3" hairline custom-color="#f56c6c" border-color="#f56c6c" />
</template>
```

### 快捷选择-范围选择

```html
<template>
<nut-code-input @change="change" @finish="finish" />
</template>
<script lang="ts">
import { reactive, toRefs } from 'vue';
export default {
setup() {
function change(e: any) {
console.log(`内容改变,当前值为:${e}`)
}
function finish(e: any) {
console.log(`输入结束,当前值为:${e}`)
}
return {
change
finish
};
}
}
</script>
```

## API

### Props

| 参数 | 说明 | 类型 | 默认值 |
|-------------------|---------------------------------------------------|-----------------|-----------------|
| v-model | 输入值,双向绑定 | string | - |
| adjustPosition | 键盘弹起时,是否自动上推页面 | Boolean | `false` |
| maxlength |输入字符个数 | `String \| Number` | `4` |
| dot | 是否用圆点填充 | boolean | `false` |
| mode | 选择样式为边框或者横线 | `box \| line` | `box` |
| hairline | 是否细边框 | Boolean | `false`
| space | 字符间的距离 | `String \| Number` | `10` |
| focus | 是否自动获取焦点 | Boolean | `false` |
| custom-color | 字体颜色 | String | `#606266` |
| font-size | 字体大小,单位rpx | `String \| Number` | `18` |
| size | 输入框的大小,宽等于高 | `String \| Number` | `35` |
| disabledKeyboard | 禁止点击输入框唤起系统键盘 | Boolean | `false` |
| border-color | 边框和线条颜色 | String | `#c9cacc` |
| disabledDot | 是否禁止输入"."符号 | boolean | `true` |

### Events

| 事件名 | 说明 | 回调参数 |
|--------|------------------------------|------------------------------|
| change | 输入内容发生改变时触发,具体见上方说明 | `string` |
| finish | 输入字符个数达maxlength值时触发,见上方说明 | `string` |

## 主题定制

### 样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](/components/basic/configprovider)

| 名称 | 默认值 |
| --------------------------------------- | -------------------------- |
| --nut-code-input-cursor-width | _var(--nut-code-input-cursor-width)_ |
| --nut-code-input-cursor-height| _var(--nut-code-input-cursor-height)_ |
| --nut-code-input-cursor-animation-duration| _1s_ |
| --nut-code-input-cursor-animation-name| _nut-cursor-flicker_ |
| --nut-code-input-content-color| _var(--nut-code-content-color)_ |

13 changes: 12 additions & 1 deletion example/config.json
Expand Up @@ -222,7 +222,7 @@
"cName": "粘性布局",
"type": "component",
"desc": "当组件在屏幕范围内时,会按照正常的布局排列,当组件滚出屏幕范围时,始终会固定在距离屏幕固定的距离处",
"show": true,
"show": false,
"taro": true,
"tarodoc": false,
"author": "szg2008"
Expand Down Expand Up @@ -533,6 +533,17 @@
"desc": "输入框组件",
"author": "gxx158"
},
{
"version": "3.0.0",
"name": "CodeInput",
"taro": true,
"sort": 2,
"cName": "验证码输入框",
"type": "component",
"show": true,
"desc": "验证码输入框组件",
"author": "yang1206"
},
{
"version": "3.0.0",
"name": "Radio",
Expand Down
2 changes: 1 addition & 1 deletion example/src/components.d.ts
Expand Up @@ -30,6 +30,7 @@ declare module '@vue/runtime-core' {
NutCheckbox: typeof import('uniapp-nutui/components/checkbox/checkbox.vue')['default']
NutCheckboxGroup: typeof import('uniapp-nutui/components/checkboxgroup/checkboxgroup.vue')['default']
NutCircleProgress: typeof import('uniapp-nutui/components/circleprogress/circleprogress.vue')['default']
NutCodeInput: typeof import('uniapp-nutui/components/codeinput/codeinput.vue')['default']
NutCol: typeof import('uniapp-nutui/components/col/col.vue')['default']
NutCollapse: typeof import('uniapp-nutui/components/collapse/collapse.vue')['default']
NutCollapseItem: typeof import('uniapp-nutui/components/collapseitem/collapseitem.vue')['default']
Expand All @@ -52,7 +53,6 @@ declare module '@vue/runtime-core' {
NutGiftbox: typeof import('uniapp-nutui/components/giftbox/giftbox.vue')['default']
NutGrid: typeof import('uniapp-nutui/components/grid/grid.vue')['default']
NutGridItem: typeof import('uniapp-nutui/components/griditem/griditem.vue')['default']
NutGuessGift: typeof import('uniapp-nutui/components/guessgift/guessgift.vue')['default']
NutHiteggs: typeof import('uniapp-nutui/components/hiteggs/hiteggs.vue')['default']
NutIcon: typeof import('uniapp-nutui/components/icon/icon.vue')['default']
NutImagePreview: typeof import('uniapp-nutui/components/imagepreview/imagepreview.vue')['default']
Expand Down
2 changes: 1 addition & 1 deletion example/src/pages.json

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions example/src/pages/demo/dentry/codeinput/index.vue
@@ -0,0 +1,74 @@
<script setup lang="ts">
const state = reactive({
val1: '',
val2: '',
val3: '',
val4: '',
})
function change(e: any) {
// eslint-disable-next-line no-console
console.log(`内容改变,当前值为:${e}`)
}
function finish(e: any) {
uni.showToast({
title: `输入结束,当前值为:${e}`,
icon: 'none',
})
}
</script>

<template>
<div class="demo">
<h2 class="title">
基础用法
</h2>
<nut-code-input v-model="state.val1" />

<h2 class="title">
横线模式
</h2>
<nut-code-input v-model="state.val1" mode="line" />
<h2 class="title">
设置长度
</h2>
<nut-code-input v-model="state.val2" :maxlength="6" />

<h2 class="title">
横线间距
</h2>
<nut-code-input v-model="state.val2" :space="0" />
<h2 class="title">
细边框
</h2>
<nut-code-input v-model="state.val2" mode="box" :space="0" :maxlength="4" hairline />

<h2 class="title">
调整颜色
</h2>
<nut-code-input v-model="state.val3" hairline custom-color="#f56c6c" :border-color="`#f56c6c` as any" />

<h2 class="title">
用"●"替代输入内容
</h2>
<nut-code-input v-model="state.val3" dot />

<h2 class="title">
是否自动获取焦点
</h2>
<nut-code-input v-model="state.val4" :focus="true" />

<h2 class="title">
事件演示
</h2>
<nut-code-input @change="change" @finish="finish" />
</div>
</template>

<route lang="json">
{
"style": {
"navigationBarTitleText": "CodeInput"
}
}
</route>
2 changes: 1 addition & 1 deletion example/src/pages/demo/layout/sticky/index.vue
Expand Up @@ -33,10 +33,10 @@ export default defineComponent({
.sticky-demo {
overflow: auto !important;
}
.sticky-container {
width: 100%;
height: 300px;
background-color: #fff;
}
</style>

Expand Down
9 changes: 8 additions & 1 deletion packages/nutui/components/_utils/style.ts
@@ -1,5 +1,5 @@
import { hyphenate } from './common'
import { isString } from './is'
import { isNumber, isString } from './is'

export type NormalizedStyle = Record<string, string | number>

Expand Down Expand Up @@ -36,3 +36,10 @@ export function stringifyStyle(styles: NormalizedStyle | string | undefined): st
}
return ret
}

export function getPx(value: string | number, unit = false) {
if (isNumber(value))
return unit ? `${value}px` : Number(value)

return unit ? `${Number.parseInt(value)}px` : Number.parseInt(value)
}
2 changes: 0 additions & 2 deletions packages/nutui/components/barrage/barrage.ts
@@ -1,7 +1,5 @@
import type { ExtractPropTypes } from 'vue'

const { theme } = uni.getSystemInfoSync()

export const barrageProps = {
danmu: {
type: Array,
Expand Down
90 changes: 90 additions & 0 deletions packages/nutui/components/codeinput/codeinput.ts
@@ -0,0 +1,90 @@
import type { ExtractPropTypes, PropType } from 'vue'
import { isString } from '../_utils'

export const codeinputProps = {
// 键盘弹起时,是否自动上推页面
adjustPosition: {
type: Boolean,
default: true,
},
// 最大输入长度
maxlength: {
type: [String, Number],
default: 4,
},
// 是否用圆点填充
dot: {
type: Boolean,
default: false,
},
// 显示模式,box-盒子模式,line-底部横线模式
mode: {
type: String as PropType<'box' | 'line'>,
default: 'box',
},
// 是否细边框
hairline: {
type: Boolean,
default: false,
},
// 字符间的距离
space: {
type: [String, Number],
default: 10,
},
// 预置值
modelValue: {
type: [String, Number],
default: '',
},
// 是否自动获取焦点
focus: {
type: Boolean,
default: false,
},
// 字体是否加粗
bold: {
type: Boolean,
default: false,
},
// 字体颜色
customColor: {
type: String,
default: '#606266',
},
// 字体大小
fontSize: {
type: [String, Number],
default: 18,
},
// 输入框的大小,宽等于高
size: {
type: [String, Number],
default: 35,
},
// 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
disabledKeyboard: {
type: Boolean,
default: false,
},
// 边框和线条颜色
borderColor: {
type: String,
default: '#c9cacc',
},
// 是否禁止输入"."符号
disabledDot: {
type: Boolean,
default: true,
},
}

export type CodeInputProps = ExtractPropTypes<typeof codeinputProps>

export const codeinputEmits = {
change: (val: string) => isString(val),
input: (val: string) => isString(val),
finish: (val: string) => isString(val),
}

export type CodeInputEmits = typeof codeinputEmits

0 comments on commit 9b9516b

Please sign in to comment.