@wocwin/t-ui-plus
Version:
Page level components developed based on Element Plus.
259 lines (256 loc) • 9.68 kB
JavaScript
import { defineComponent, useAttrs, useSlots, computed, resolveComponent, createBlock, openBlock, withCtx, createVNode, mergeProps, createSlots, renderList, unref, renderSlot, normalizeProps, guardReactiveProps, createElementBlock, toDisplayString, createElementVNode } from 'vue';
import { ElMessage } from 'element-plus';
import '../../../hooks/index.mjs';
import { useLocale } from '../../../hooks/useLocale.mjs';
const _hoisted_1 = { key: 0 };
const _hoisted_2 = { key: 0 };
var _sfc_main = /* @__PURE__ */ defineComponent({
...{
name: "TInput"
},
__name: "index",
props: {
modelValue: { default: "" },
placeholder: { default: "" },
decimalLimit: { default: 2 },
inputType: { default: "text" },
appendTitle: { default: "" },
showThousands: { type: Boolean, default: false },
isTip: { type: Boolean, default: false },
isShowErrorTip: { type: Boolean, default: false },
customErrorTip: { default: "" }
},
emits: ["update:modelValue"],
setup(__props, { emit: __emit }) {
const { t } = useLocale();
const attrs = useAttrs();
const props = __props;
const emits = __emit;
const slots = useSlots();
const REGEX = {
INTEGER: /^\d+$/,
PHONE: /^1[3456789]\d{9}$/,
ID_CARD: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
NUMBER: /((^[1-9]\d*)|^0)(\.\d+)?$/,
NUMBER_DECIMAL: /((^[1-9]\d*)|^0)(\.\d{0,2}){0,1}$/
};
const CHINESE = {
DIGITS: ["\u96F6", "\u58F9", "\u8D30", "\u53C1", "\u8086", "\u4F0D", "\u9646", "\u67D2", "\u634C", "\u7396"],
FRACTIONS: ["\u89D2", "\u5206"],
UNITS: [
["\u5143", "\u4E07", "\u4EBF", "\u5146"],
["", "\u62FE", "\u4F70", "\u4EDF"]
]
};
const showTooltip = computed(() => props.isTip && !props.showThousands);
const showAppend = computed(() => slots.append || props.inputType === "amount");
const placeholderText = computed(() => props.placeholder || t("plus.input.placeholder"));
const appendTitleText = computed(() => props.appendTitle || t("plus.input.appendTitle"));
const inputProps = computed(() => ({
placeholder: placeholderText.value,
clearable: true,
...attrs
}));
const getInputRegex = () => {
if (props.inputType instanceof RegExp) {
return props.inputType;
}
switch (props.inputType) {
case "integer":
return REGEX.INTEGER;
case "phone":
return REGEX.PHONE;
case "idCard":
return REGEX.ID_CARD;
default:
return null;
}
};
const internalValue = computed({
get() {
var _a;
if (props.inputType === "integer" && props.modelValue != null) {
return typeof props.modelValue === "number" ? String(props.modelValue) : props.modelValue;
}
return (_a = props.modelValue) != null ? _a : "";
},
set(val) {
if (props.inputType === "integer") {
if (!val || val === "") {
emits("update:modelValue", null);
} else {
const str = String(val);
const regex = getInputRegex();
emits("update:modelValue", (regex == null ? void 0 : regex.test(str)) ? Number(str) : str);
}
} else {
emits("update:modelValue", val != null ? val : "");
}
}
});
const validate = (value, pattern, errorKey) => {
if (pattern.test(value)) return value;
if (props.isShowErrorTip) {
const errorMsg = props.customErrorTip || (errorKey ? t(errorKey) : t("plus.input.validateError"));
ElMessage.error(errorMsg);
}
return null;
};
const formatAmount = (value) => {
if (!value) {
if (props.isShowErrorTip) {
const msg = t("plus.input.format") + (props.inputType === "amount" ? t("plus.input.amount") : t("plus.input.numbers"));
ElMessage.error(msg);
}
return "";
}
const fixed = value.toFixed(props.decimalLimit);
return props.showThousands ? fixed.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : fixed;
};
const currencyFilter = (num, n = 2) => {
if (!REGEX.NUMBER.test(String(num)) || num == null && num !== 0) return "";
const n2 = n > 0 && n <= 20 ? n : 2;
const numStr = parseFloat(String(num).replace(/^\d\.-/g, "")).toFixed(n2);
const [int, dec] = numStr.split(".");
return `\uFFE5 ${int.replace(/\B(?=(\d{3})+(?!\d))/g, ",")}.${dec}`;
};
const digitUppercase = (num) => {
if (!REGEX.NUMBER_DECIMAL.test(String(num))) return t("plus.input.digitUppercase");
const isNegative = Number(num) < 0;
let absNum = Math.abs(Number(num));
let result = "";
CHINESE.FRACTIONS.forEach((fraction, index) => {
const digit = Math.floor(absNum * 10 * Math.pow(10, index)) % 10;
result += (CHINESE.DIGITS[digit] + fraction).replace(/零./, "");
});
result = result || "\u6574";
let integerPart = Math.floor(absNum);
for (let i = 0; i < CHINESE.UNITS[0].length && integerPart > 0; i++) {
let section = "";
for (let j = 0; j < CHINESE.UNITS[1].length && integerPart > 0; j++) {
section = CHINESE.DIGITS[integerPart % 10] + CHINESE.UNITS[1][j] + section;
integerPart = Math.floor(integerPart / 10);
}
result = section.replace(/(零.)*零$/, "").replace(/^$/, "\u96F6") + CHINESE.UNITS[0][i] + result;
}
return (isNegative ? "\u6B20" : "") + result.replace(/(零.)*零元/, "\u5143").replace(/(零.)+/g, "\u96F6").replace(/^整$/, "\u96F6\u5143\u6574");
};
const handleBlur = () => {
var _a, _b, _c;
const val = internalValue.value;
let formatted = val;
if (props.inputType instanceof RegExp) {
formatted = (_a = validate(String(val || ""), props.inputType)) != null ? _a : "";
internalValue.value = formatted;
return;
}
switch (props.inputType) {
case "amount":
case "decimal":
formatted = formatAmount(Number(val));
break;
case "phone":
formatted = (_b = validate(String(val || ""), REGEX.PHONE, "plus.input.validatePhone")) != null ? _b : "";
break;
case "integer": {
const result = validate(String(val || ""), REGEX.INTEGER, "plus.input.validateInteger");
formatted = result ? Number(result) : null;
break;
}
case "idCard":
formatted = (_c = validate(String(val || ""), REGEX.ID_CARD, "plus.input.validateIdCard")) != null ? _c : "";
break;
}
internalValue.value = formatted;
};
return (_ctx, _cache) => {
const _component_el_input = resolveComponent("el-input");
const _component_el_tooltip = resolveComponent("el-tooltip");
return showTooltip.value ? (openBlock(), createBlock(_component_el_tooltip, {
key: 0,
effect: "dark",
placement: "bottom-start"
}, {
content: withCtx(() => [
createElementVNode(
"div",
null,
toDisplayString(currencyFilter(_ctx.modelValue)),
1
/* TEXT */
),
createElementVNode(
"div",
null,
toDisplayString(digitUppercase(_ctx.modelValue)),
1
/* TEXT */
)
]),
default: withCtx(() => [
createVNode(_component_el_input, mergeProps({
modelValue: internalValue.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => internalValue.value = $event)
}, inputProps.value, { onBlur: handleBlur }), createSlots({
_: 2
/* DYNAMIC */
}, [
renderList(unref(slots), (_, name) => {
return {
name,
fn: withCtx((data) => [
renderSlot(_ctx.$slots, name, normalizeProps(guardReactiveProps(data)))
])
};
}),
showAppend.value ? {
name: "append",
fn: withCtx(() => [
_ctx.inputType === "amount" ? (openBlock(), createElementBlock(
"span",
_hoisted_1,
toDisplayString(appendTitleText.value),
1
/* TEXT */
)) : renderSlot(_ctx.$slots, "append", { key: 1 })
]),
key: "0"
} : void 0
]), 1040, ["modelValue"])
]),
_: 3
/* FORWARDED */
})) : (openBlock(), createBlock(_component_el_input, mergeProps({
key: 1,
modelValue: internalValue.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => internalValue.value = $event)
}, inputProps.value, { onBlur: handleBlur }), createSlots({
_: 2
/* DYNAMIC */
}, [
renderList(unref(slots), (_, name) => {
return {
name,
fn: withCtx((data) => [
renderSlot(_ctx.$slots, name, normalizeProps(guardReactiveProps(data)))
])
};
}),
showAppend.value ? {
name: "append",
fn: withCtx(() => [
_ctx.inputType === "amount" ? (openBlock(), createElementBlock(
"span",
_hoisted_2,
toDisplayString(appendTitleText.value),
1
/* TEXT */
)) : renderSlot(_ctx.$slots, "append", { key: 1 })
]),
key: "0"
} : void 0
]), 1040, ["modelValue"]));
};
}
});
export { _sfc_main as default };