vue3 + element-plus实现金额组件。
金额组件命名MoneyInput.vue,父组件引用MoneyInput.vue时依然可以在父组件进行表单校验并且不需要额外的处理。
参考文章:blog.csdn.net/qq_38571305…
MoneyInput.vue代码
<template>
<el-input
v-model="currentData"
:placeholder="placeholder"
maxlength="18"
@blur="handlerIllegalStr"
:formatter="moneyFormatter"
:parser="moneyParser"
:disabled="disabled"
>
</el-input>
</template>
<script setup lang="ts">
import { ref, watch} from 'vue'
const props = defineProps({
modelValue: {
type: [String, Number],
default: ''
},
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: '请输入'
}
})
const emit = defineEmits(['update:modelValue'])
// 数字格式化
const toNumber = (val) => {
val = val.toString().replace(/[^\d^\.^\-]+/g, "") // 第二步:把不是数字,不是小数点、-的过滤掉
.replace(/^0+(\d)/, "$1") // 第三步:第一位0开头,0后面为数字,则过滤掉,取后面的数字
.replace(/^\./, "0.") // 第四步:如果输入的第一位为小数点,则替换成 0. 实现自动补全
.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".") // 只保留第一个".", 清除多余的"."
// .match(/^\d*(\.?\d{0,9})/g)[0] || ""; // 第五步:最终匹配得到结果 以数字开头,只有一个小数点,而且小数点后面只能有1到9位小数
return val
}
// 处理最后一位非法字符
const handlerIllegalStr = () => {
if(currentData.value===0){
currentData.value = '0.00'
}else if(currentData.value && currentData.value!==''){
currentData.value = toNumber(currentData.value)
currentData.value = Math.round(parseFloat(currentData.value) * 100) / 100
currentData.value = currentData.value.toString()
// console.log(currentData.value.slice(currentData.value.length-2, currentData.value.length-1))
if(currentData.value.indexOf(".") === -1){
currentData.value = currentData.value + '.00'
}else if(currentData.value.slice(currentData.value.length-2, currentData.value.length-1) === "."){
currentData.value = currentData.value + '0'
}
}else{
currentData.value = ''
}
//console.log('ccc_cccccccc',currentData.value)
emit('update:modelValue', currentData.value)
}
// 格式化函数
const moneyFormatter = (num)=>{
num = toNumber(num)
num = num.toString()
let num1 = num.split(".")[0], num2 = num.split(".")[1]
let c = num1.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
// console.log('aaa_cccccccc',currentData.value)
return num.toString().indexOf(".") !== -1 ? (c+"."+ num2) : c
}
// 解析函数
const moneyParser = (num)=>{
num = toNumber(num)
num = num.toString().replace(/,/g, "")
// console.log('bbb_ccccccccc',currentData.value)
emit('update:modelValue', num)
return num
}
const currentData = ref()
currentData.value = props.modelValue
handlerIllegalStr()
watch(
() => props.modelValue,
(newValue) => {
//console.log('watch', props.modelValue)
currentData.value = props.modelValue
}
)
</script>
<style lang="scss" scoped>
</style>
父组件代码
<template>
<div class="wrapper">
<div class="sign-container">
<div class="seal-new-page" >
<el-form
ref="ruleForm"
:model="formData"
:rules="rules"
label-width="160px"
>
<CardView title="合同信息确认" v-if="formData.contractSignWeSignedInfo.isSigned===1">
<template v-for="(item, index) in formData.contractSignBaseInfoList" :key="item.contractSignContractBaseInfo.contractStartTime + index">
<template v-if="item.contractSignContractBaseInfo.isConnectedTransaction==='是'&&item.contractSignContractBaseInfo.isRelated==='是'">
<el-collapse v-model="activeCollapse">
<el-collapse-item :key="index" :name="index">
<template #title>
<div class="title">{{ item.contractSignOtherSignedInfo.counterpartName }}</div>
</template>
<el-row class="mt-20">
<el-col :span="8" :xs="24" :md="12" :lg="8">
<el-form-item label-width="210px" label="关联交易金额(元)" :prop="`contractSignBaseInfoList[${index}][contractSignContractBaseInfo][relatedPartyTransactionAmount]`" :rules="rules.relatedPartyTransactionAmount">
<MoneyInput
v-model="item.contractSignContractBaseInfo.relatedPartyTransactionAmount"
placeholder="请输入"
:disabled="disabled1"
></MoneyInput>
</el-form-item>
</el-col>
<el-col :span="8" :xs="24" :md="12" :lg="8">
<el-form-item label-width="210px" label="统一交易协议执行情况(元)" :prop="`contractSignBaseInfoList[${index}][contractSignContractBaseInfo][agreeTransactionAgreementSituation]`" :rules="rules.agreeTransactionAgreementSituation">
<MoneyInput
v-model="item.contractSignContractBaseInfo.agreeTransactionAgreementSituation"
placeholder="请输入"
:disabled="disabled1"
></MoneyInput>
</el-form-item>
</el-col>
<el-col :span="8" :xs="24" :md="12" :lg="8">
<el-form-item label-width="210px" label="关联交易价格(元)" :prop="`contractSignBaseInfoList[${index}][contractSignContractBaseInfo][relatedPartyTransactionPrice]`" :rules="rules.relatedPartyTransactionPrice">
<MoneyInput
v-model="item.contractSignContractBaseInfo.relatedPartyTransactionPrice"
placeholder="请输入"
:disabled="disabled1"
></MoneyInput>
</el-form-item>
</el-col>
<el-col :span="8" :xs="24" :md="12" :lg="8" v-if="item.contractSignContractBaseInfo.relatedPartyTransactionBusinessType.includes('投资金融产品')">
<el-form-item label-width="210px" label="投资金融产品份额占比(%)" :prop="`contractSignBaseInfoList[${index}][contractSignContractBaseInfo][investmentFinancialProductsProportion]`" :rules="rules.investmentFinancialProductsProportion">
<MoneyInput
v-model="item.contractSignContractBaseInfo.investmentFinancialProductsProportion"
placeholder="请输入"
:disabled="disabled1"
></MoneyInput>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
</el-collapse>
</template>
</template>
</CardView>
</el-form>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onBeforeMount,inject } from 'vue'
import type { FormRules, UploadInstance } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import CardView from '@/components/CardView.vue'
import MoneyInput from '@/components/MoneyInput.vue'
//校验表单
const ruleForm = ref()
const commitNoSign = async () => {
const valid = await ruleForm.value.validate().catch(() => {
ElMessage({
showClose: true,
message: '请确认输入信息是否完整',
type: 'warning'
})
return false
})
if(valid){
let currentData = JSON.parse(JSON.stringify(formData))
formData.contractSignBaseInfoList.forEach((item, index) => {
currentData.contractSignBaseInfoList[index].contractSignContractBaseInfo.contractTermType = ''
currentData.contractSignBaseInfoList[index].contractSignContractBaseInfo.contractStartTime = ''
currentData.contractSignBaseInfoList[index].contractSignContractBaseInfo.contractEndTime = ''
currentData.contractSignBaseInfoList[index].contractSignContractBaseInfo.termDescription = ''
currentData.contractSignBaseInfoList[index].contractSignOtherSignedInfo.legalPersonIdentificationFileName = ''
currentData.contractSignBaseInfoList[index].contractSignOtherSignedInfo.powerOfAttorneyFileName = ''
})
currentData.contractSignWeSignedInfo.contractSignTextFileName = ''
currentData.contractSignWeSignedInfo.powerOfAttorneyFileName = ''
const res = await noSignRelease({
examineGroupId: currentData.examineGroupId,
examineId: currentData.examineId,
id: currentData.id,
version: currentData.version,
remark: currentData.remark,
contractSignBaseInfoList: currentData.contractSignBaseInfoList,
contractSignWeSignedInfo: currentData.contractSignWeSignedInfo,
})
if (res.code == 200) {
ElMessage({
showClose: true,
message: '发布成功',
type: 'success'
})
setTimeout(() => {
router.go(-1)
})
} else {
ElMessage({
showClose: true,
message: res.message,
type: 'warning'
})
}
}
}
</script>