需求:想要实现一个输入金额的el-input,限制只能输入数字和一个小数点。失焦数字转千分位,聚焦转为数字,超过最大值,红字提示
效果图
失焦
聚焦
报错效果
// 组件limitDialog
<template>
<el-dialog
:visible.sync="isVisible"
title="修改限额"
width="420px"
:before-close="cancel"
>
<el-form :model="formVal" ref="ruleForm" size="small">
<el-form-item
label="单次交易限额"
prop="single_limit"
:rules="[
{
required: true,
message: '请输入单次交易限额',
trigger: 'change',
},
{ validator: singleRule, trigger: 'change' },
]"
>
<el-input
v-model="formVal.single_limit"
v-thousand
maxlength="10"
type="text"
@keypress.native="restrictInput('single_limit', $event)"
@blur="formatOnBlur('single_limit', $event)"
>
<template slot="suffix">{{ otherInfo.currency }}</template>
</el-input>
</el-form-item>
<el-form-item
label="每日限额"
prop="daily_limit"
:rules="[
{
required: true,
message: '请输入每日限额',
trigger: 'change',
},
{ validator: dailyRule, trigger: 'change' },
]"
>
<el-input
v-model="formVal.daily_limit"
maxlength="10"
v-thousand
type="text"
@keypress.native="restrictInput('daily_limit', $event)"
@blur="formatOnBlur('daily_limit', $event)"
>
<template slot="suffix">{{ otherInfo.currency }}</template>
</el-input>
<p class="tip" v-if="type !== 'bath'">
当日已用金额 {{ otherInfo.daily_used }}
{{ otherInfo.currency }}
</p>
</el-form-item>
<el-form-item
label="每月限额"
prop="monthly_limit"
:rules="[
{
required: true,
message: '请输入每月限额',
trigger: 'change',
},
{ validator: monthlyRule, trigger: 'change' },
]"
>
<el-input
v-model="formVal.monthly_limit"
maxlength="10"
v-thousand
type="text"
@keypress.native="restrictInput('monthly_limit', $event)"
@blur="formatOnBlur('monthly_limit', $event)"
>
<template slot="suffix">{{ otherInfo.currency }}</template>
</el-input>
<p class="tip" v-if="type !== 'bath'">
当月已用金额 {{ otherInfo.monthly_used }}
{{ otherInfo.currency }}
</p>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel" size="small">取 消</el-button>
<el-button
type="primary"
@click="handleSave"
size="small"
:loading="isSumbitLoading"
>确 定</el-button
>
</div>
</el-dialog>
</template>
<script>
import { updateCardLimitApi } from "@/services/api/cardManage.js";
import { updateObject } from "@/utils/common";
export default {
data() {
return {
isVisible: false,
isSumbitLoading: false,
formVal: {
single_limit: "",
daily_limit: "",
monthly_limit: "",
id: "",
},
otherInfo: {
currency: "USD",
daily_used: "",
monthly_used: "",
},
type: "bath",
};
},
props: {
selectedList: {
type: Array,
default: () => [],
},
},
methods: {
singleRule(rule, value, callback) {
const numValue = Number(value);
if (numValue > 10000) {
callback(
new Error(
`输入金额不可超过单次限额(10,000.00 ${this.otherInfo.currency})`
)
);
}
this.checkLimit(value, callback);
},
dailyRule(rule, value, callback) {
const numValue = Number(value);
if (numValue > 100000) {
callback(
new Error(
`输入金额不可超过每日限额(100,000.00 ${this.otherInfo.currency})`
)
);
}
this.checkLimit(value, callback);
},
monthlyRule(rule, value, callback) {
const numValue = Number(value);
if (numValue > 500000) {
callback(
new Error(
`输入金额不可超过每月限额(500,000.00 ${this.otherInfo.currency})`
)
);
}
this.checkLimit(value, callback);
},
checkLimit(value, callback) {
const strValue = String(value || "");
if (strValue === "")
return callback(new Error("请输入单次交易限额"));
if (strValue.endsWith("."))
return callback(new Error("不能以小数点结尾"));
const numValue = Number(strValue);
if (isNaN(numValue)) return callback(new Error("请输入有效的数字"));
if (strValue.includes(".") && strValue.split(".")[1].length > 2) {
return callback(new Error("小数点后最多两位"));
}
callback();
},
restrictInput(formKey, event) {
const key = event.key;
const value = String(this.formVal[formKey] || "");
if (event.ctrlKey || event.altKey || key.length > 1) return;
// 只允许数字和小数点,限制多个小数点
const isValidKey = /[0-9.]/.test(key);
const hasDecimal = value.includes(".");
if (!isValidKey || (key === "." && hasDecimal)) {
event.preventDefault();
return;
}
},
formatOnBlur(formKey) {
const strValue = String(this.formVal[formKey] || "");
if (strValue && !isNaN(Number(strValue))) {
this.formVal[formKey] = Number(strValue).toFixed(2);
}
},
init(info, type) {
this.isVisible = true;
this.type = type;
updateObject(this.formVal, info);
updateObject(this.otherInfo, info);
},
handleSave() {
this.isSubmitLoading = true;
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
const { code } = await updateCardLimitApi({
...this.formVal,
id:
this.type === "bath"
? this.selectedList.map((item) => item.id)
: [this.formVal.id],
});
if (code == 0) {
this.$message.success("修改成功");
this.cancel();
this.$emit("reload");
}
}
this.isSumbitLoading = false;
});
},
cancel() {
this.isVisible = false;
this.$refs.ruleForm.resetFields();
updateObject(this.formVal, {
single_limit: "",
daily_limit: "",
monthly_limit: "",
id: "",
});
this.otherInfo.currency = "USD";
},
},
};
</script>
<style lang="scss" scoped>
.dialog-footer {
text-align: right;
}
.tip {
color: #999999;
font-size: 12px;
}
</style>