vue3+Element-plus el-input 输入框组件二次封装(支持金额、整数、电话、小数、身份证、小数点位数控制,金额显示中文提示等功能)

news2024/9/21 12:57:54

一、效果图

在这里插入图片描述

二、组件集成了以下功能

1、输入金额--支持千分号显示、可设置`decimalLimit`来调整小数点位数
2、金额鼠标移入提示中文--标签添加`isTip`开启中文提示则不允许开启千分号显示`showThousands`
3、输入手机号--设置`inputType=phone`
4、输入整数---设置`inputType=integer`
5、输入数字(含小数点)---设置`inputType=decimal`
6、输入身份证号---设置`inputType=idCard`
7、格式化输入内容--`formatter`的情况下显示值,我们通常同时使用 `parser`
8、支持el-input的所有功能

三、参数配置

1、代码示例:

<t-input v-model="inputVlaue" />

2、配置参数(Attributes)继承 el-input Attributes

参数说明类型默认值
v-model绑定值string-
placeholderplaceholder提示语string‘请输入’
decimalLimit小数点位数 (小数、金额类型时生效)Number2
appendTitle插槽append显示文案(金额类型时生效)string‘元’
showThousands是否显示千分号(小数、金额类型时生效)Booleanfalse
isTip是否提示金额中文(金额类型时生效)Booleanfalse
inputType特性类型标注(文字:text,金额:amount,电话:phone,整数:integer,小数:decimal,身份证:idCard’)stringtext

3、继承 el-input 事件、插槽、方法

四、源码

<template>
  <el-tooltip effect="dark" placement="bottom-start" v-if="isTip && !showThousands">
    <template #content>
      {{ currencyFilter(modelValue) }}<br />
      {{ digitUppercase(modelValue) }}
    </template>
    <el-input
      v-model="internalValue"
      v-bind="{ placeholder, clearable: true, ...$attrs }"
      @blur="handleBlur"
    >
      <template v-for="(index, name) in slots" v-slot:[name]="data">
        <slot :name="name" v-bind="data" />
      </template>
      <template #append v-if="$slots.append || inputType === 'amount'">
        <span v-if="inputType === 'amount'">{{ appendTitle }}</span>
        <slot v-else name="append" />
      </template>
    </el-input>
  </el-tooltip>
  <el-input
    v-model="internalValue"
    v-bind="{ placeholder, clearable: true, ...$attrs }"
    @blur="handleBlur"
    v-else
  >
    <template v-for="(index, name) in slots" v-slot:[name]="data">
      <slot :name="name" v-bind="data" />
    </template>
    <template #append v-if="$slots.append || inputType === 'amount'">
      <span v-if="inputType === 'amount'">{{ appendTitle }}</span>
      <slot v-else name="append" />
    </template>
  </el-input>
</template>

<script setup lang="ts" name="TInput">
import { ElMessage } from "element-plus"
import { computed, useSlots } from "vue"
const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: ""
  },
  placeholder: {
    type: String,
    default: "请输入"
  },
  // 小数、金额类型时,小数点后最多几位
  decimalLimit: {
    type: Number,
    default: 2
  },
  // inputType含有文字:text、金额:amount、电话:phone、整数:integer、小数:decimal、身份证:idCard类型
  inputType: {
    type: String,
    default: "text"
  },
  appendTitle: {
    type: String,
    default: "元"
  },
  // 是否显示千分号
  showThousands: {
    type: Boolean,
    default: false
  },
  // 是否显示金额中文提示
  isTip: {
    type: Boolean,
    default: false
  }
})
const emits = defineEmits(["update:modelValue"])
const slots = useSlots()
let internalValue = computed({
  get() {
    return props.modelValue
  },
  set(val) {
    // console.log(777, val)
    emits("update:modelValue", val)
  }
})

const handleBlur = () => {
  let formattedValue = internalValue.value

  const formatValue = (value, formatter) => {
    if (formatter) {
      return formatter(value)
    }
    return value
  }

  switch (props.inputType) {
    case "amount":
    case "decimal":
      formattedValue = formatValue(Number(internalValue.value), value =>
        formatAmount(value, props.decimalLimit)
      )
      break
    case "phone":
      formattedValue = formatValue(internalValue.value.toString(), validatePhone)
      break
    case "integer":
      formattedValue = formatValue(internalValue.value.toString(), validateInteger)
      break
    case "idCard":
      formattedValue = formatValue(internalValue.value.toString(), validateIdCard)
      break
    default:
      formattedValue = internalValue.value
  }

  internalValue.value = formattedValue
}

// 手机号码校验
const validatePhone = (value: string) => {
  const phoneReg = /^1[3456789]\d{9}$/
  if (phoneReg.test(value as string)) {
    return value
  } else {
    ElMessage.error("请输入正确的手机号码")
    return ""
  }
}
// 身份证号码校验
const validateIdCard = (value: string) => {
  const idCardReg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  if (idCardReg.test(value as string)) {
    return value
  } else {
    ElMessage.error("请输入正确的身份证号码")
    return ""
  }
}
// 整数校验
const validateInteger = (value: string) => {
  const integerReg = /^\d+$/
  if (integerReg.test(value as string)) {
    return value
  } else {
    ElMessage.error("请输入正确的整数")
    return ""
  }
}
// 小数、金额类型转换
const formatAmount = (value: number, decimalLimit: number) => {
  if (!value) {
    ElMessage.error(`请输入正确的${props.inputType == "amount" ? "金额" : "数字"}`)
    return ""
  }
  // 格式化千分号
  if (props.showThousands) {
    const val = value
      .toFixed(decimalLimit)
      .toString()
      .replace(/\B(?=(\d{3})+(?!\d))/g, ",")
    return val
  } else {
    return value.toFixed(decimalLimit)
  }
}
/**
 * 数字金额格式过滤 10000 => "¥10,000.00"
 * @param {number} num 被转换数字
 * @param {number} n 保留小数位
 */
const currencyFilter = (num: any, n: number = 2) => {
  const reg = /((^[1-9]\d*)|^0)(\.\d+)?$/
  if (!reg.test(num)) {
    return ""
  } else {
    n = n > 0 && n <= 20 ? n : 2
    if (num || num === 0) {
      num = parseFloat((num + "").replace(/^\d\.-/g, "")).toFixed(n) + ""
      const l = num.split(".")[0].split("").reverse()
      const r = num.split(".")[1]
      let t = ""
      for (let i = 0; i < l.length; i++) {
        t += l[i] + ((i + 1) % 3 === 0 && i + 1 !== l.length ? "," : "")
      }
      return num ? "¥ " + t.split("").reverse().join("") + "." + r : ""
    } else {
      return ""
    }
  }
}
/**
 * 数字金额格式过滤(转汉字大写) 12000.34 => "壹万贰千叁角肆分"
 * @param {number} num 被转换数字
 */
const digitUppercase = (num: any) => {
  const reg = /((^[1-9]\d*)|^0)(\.\d{0,2}){0,1}$/
  if (!reg.test(num)) {
    return "请输入正确的金额格式"
  } else {
    let fraction = ["角", "分"]
    let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]
    let unit = [
      ["元", "万", "亿", "兆"],
      ["", "拾", "佰", "仟"]
    ]
    let head = num < 0 ? "欠" : ""
    num = Math.abs(num)
    let s = ""
    fraction.forEach((item, index) => {
      s += (digit[Math.floor(num * 10 * Math.pow(10, index)) % 10] + item).replace(/零./, "")
    })
    s = s || "整"
    num = Math.floor(num)
    for (let i = 0; i < unit[0].length && num > 0; i++) {
      let p = ""
      for (let j = 0; j < unit[1].length && num > 0; j++) {
        p = digit[num % 10] + unit[1][j] + p
        num = Math.floor(num / 10)
      }
      s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s
    }
    return (
      head +
      s
        .replace(/(零.)*零元/, "元")
        .replace(/(零.)+/g, "零")
        .replace(/^整$/, "零元整")
    )
  }
}
</script>

四、组件地址

gitHub组件地址

gitee码云组件地址

五、相关文章

基于ElementUi&antdUi再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2152380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

14.1.2-float浮动练习

文章目录 1. 目标2. 实现 1. 目标 只通过float来做下面的布局&#xff08;不使用flex&#xff09;。 2. 实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widt…

Autosar Dcm开发-诊断2E或31服务实现pending功能

文章目录 前言Dcm规范功能实现总结前言 项目开发过程中,有需求在31服务(Routine)收到请求时,等待应用层反馈执行完后再进行响应。所以pending一段时间,本文介绍该功能的实现。 Dcm规范 以Routine为例,其服务包含以下返回状态 0:E_OK,服务成功执行 1:E_NOT_OK,服务…

【大屏方案】可视化综合展示系统解决方案(Word原件2024)

2.系统架构设计 2.1.系统架构图 2.2.关键技术 2.3.接口及要求 3.系统功能设计 3.1.功能清单列表 3.2.数据源管理 3.3.数据集管理 3.4.视图管理 3.5.仪表盘管理 3.6.移动端设计 3.1.系统权限设计 3.2.数据查询过程设计 软件资料清单列表部分文档清单&#xff1a;工作安排任务书&…

滑动条QSlider

可以在一个范围内拖动。 常用属性和方法 值 包括当前值、最大值、最小值 // 获取和设置当前值 int value() const; void setValue(int);// 获取和设置最大值 int maximum() const; void setMaximum(int);// 获取和设置最小值 int minimum() const; void setMinimum(int);//…

关于 NLP 深度学习的核心流程

基本流程实现的先后顺序&#xff08;每一步都包含很多技术点&#xff09;&#xff1a; 选定语言模型结构 关于语言模型&#xff1a; 作用 判断那一句话相对更合理&#xff0c;相对不合理的会得到较底的分值&#xff1a; 挑选成句概率分值最高的评价指标&#xff1a;PPL&…

一个能同时to B和to C、批发零售一体化的需求分析和系统设计

一些企业纠结自己的模式是to B还是to C&#xff0c;一些企业在to B和to C中转型&#xff0c;还有一些企业在做着to B的业务&#xff0c;也在做to C的代发&#xff0c;这些企业在不停地变更着业务&#xff0c;更换着系统&#xff0c;给企业带来巨大的资金和时间成本&#xff0c;…

ssrf攻击fastcgi复现及环境搭建

目录 一、环境 二、开始操作 一、环境 网上自己找vulhub-master.zip&#xff0c;我这里没用docker&#xff0c;本地自己搭建的 二、开始操作 很明显的ssrf漏洞 很明显我们之前的协议file dict 很明显9000端口是开放的 我们还是用gopherus生成一下 我们环境机上很明显有PEAR…

ESP8266+DHT11+Python制作一个物联网温湿度传感器

ESP8266是一款低功耗、高集成度的Wi-Fi SOC&#xff08;System on Chip&#xff0c;系统级芯片&#xff09;&#xff0c;这款芯片专为物联网&#xff08;IoT&#xff09;应用而设计&#xff0c;常见开发ESP8266的环境可以使用Arduino或者ESP8266 RTOS SDK、NodeMCU&#xff0c;…

乐观锁、悲观锁及死锁

乐观锁、悲观锁 1.概念 悲观锁(悲观锁定)&#xff1a;具有强烈的独占和排他特性。在整个执行过程中&#xff0c;将处于锁定状态。悲观锁在持有数据的时候总会把资源或者数据锁住&#xff0c;这样其他线程想要请求这个资源的时候就会阻塞&#xff0c;直到等到悲观锁把资源释放为…

QFramework v1.0 使用指南 更新篇:20240919. 新增 BindableDictionary

虽然笔者目前还不知道 BindableDictionary 能用在什么使用场景下&#xff0c;但是还是应童鞋的要求实现了 BindableDictionary。 基本使用如下: using System.Linq; using UnityEngine;namespace QFramework.Example {public class BindableDictionaryExample : MonoBehaviou…

《让手机秒变超级电脑!ToDesk云电脑、易腾云、青椒云移动端评测》

前言 科技发展到如今2024年&#xff0c;可以说每一年都在发生翻天覆地的变化。而云上这个词时常都被大家提起&#xff0c;从个人设备连接到云端在如今在也不是梦了。而云电脑这个市场近年来迅速发展&#xff0c;无需购买和维护额外的硬件就可以体验到电脑端顶配的性能和体验&am…

Adams与Matlab通过FMI联合仿真

Adams与Matlab的联合仿真通过Adams/Controls中的接口功能已经很早就实现&#xff0c;具体是通过Adams安装路径下的支持文件&#xff0c;利用Adams/Controls中的导出功能&#xff0c;将Adams模型生成模型文件以及同Matlab的接口文件*.m&#xff0c;然后在Matlab中执行该*.m文件后…

使用SoapUI、Postman工具调用Webservice方法

SoapUI工具更适合调用Webservice使用。 1.使用SoapUI工具调用Webservice 创建“New SOAP Project” 自行定义一个项目名称&#xff0c;输入wsdl地址&#xff1a; 在左侧列表找到方法名&#xff0c;双击“Request 1”, 在请求数据中&#xff0c;添加对应的参数&#xff0c;然…

Linux文件IO(五)-三种进程退出方法及空洞文件

1.三种进程退出方法 return 当程序在执行某个函数出错的时候&#xff0c;如果此函数执行失败会导致后面的步骤不能在进行下去时&#xff0c;应该在出错时终止程序运行&#xff0c;不应该让程序继续运行下去&#xff0c;那么如何退出程序、终止程序运行呢&#xff1f;有过编程…

面试面经|大模型算法岗常见面试题100道

本文提供了一份全面的大模型算法岗位面试题清单&#xff0c;包括基础理论、模型结构、训练微调策略、应用框架、分布式训练和模型推理等方面的知识点&#xff0c;旨在帮助求职者准备相关技术面试。 一、基础篇 1、目前主流的开源模型体系有哪些&#xff1f; Transformer体系&a…

RTX NVIDIA 3090卡配置对应pytorch,CUDA版本,NVIDIA驱动过程及问题整理

买了两块3090卡闲置很长时间了&#xff0c;之前tf 1.12.0版本用习惯了不想转工具。这段时间闲下来转了之后有些环境不适配&#xff0c;在雷神帮助下安装完毕&#xff0c;虽然出了点怪东西&#xff0c;整体还好。 原环境CUDA为11.4 其他配置如下 之前conda install的pytorch实为…

智慧仓储-AI销量预测

1、预测系统技术选型 基础层&#xff1a; Hbase、ClickHouse、Hdfs 用来做数据存储 框架层&#xff1a; 以 Spark RDD、Spark SQL、Hive 为主&#xff0c; MapReduce 程序占一小部分&#xff0c;是原先遗留下来的&#xff0c;目前正逐步替换成 Spark RDD。 选择 Spark 除了对…

【hot100-java】【每日温度】

R8-栈篇 印象题:单调栈的使用 参考本人博客&#xff1a;单调栈 class Solution {public int[] dailyTemperatures(int[] temperatures) {int numtemperatures.length;int [] retnew int[num];Stack<Integer>stnew Stack<>();for (int i0;i<num;i){while(!st.…

vscode 配置rust格式化的正确方法

vscode 配置rust格式化的正确方法&#xff1a; 在settings.json里输入&#xff1a; "[rust]": {"editor.defaultFormatter": "rust-lang.rust-analyzer","editor.formatOnSave": true}

揭露大模型本质,大模型入门必看的12本书!看完我直接跪了

敢不敢用一年时间读完这12本书&#xff0c;模型入门必看的12本书&#xff01;建议收藏&#xff01;&#xff01; 第一本&#xff1a; 《基于GPT-3,ChatGPT,GPT-4等Transformer架构的自然语言处理》 主要内容 了解用于解决复杂语言问题的新技术。将GPT-3与T5、GPT-2和基于BE…