mr-component
Version:
A library for Mr components
344 lines (326 loc) • 12.7 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import React, { forwardRef, useState, useEffect, useRef } from 'react';
import { Popup, Cell, Button } from 'react-vant';
// 支付选项类型
// 业务支付弹窗属性
var MrPaymentPopup = /*#__PURE__*/forwardRef(function (props, ref) {
// 属性解构,使用安全访问和默认值
var _props$visible = props.visible,
visible = _props$visible === void 0 ? false : _props$visible,
title = props.title,
_props$options = props.options,
options = _props$options === void 0 ? [] : _props$options,
value = props.value,
defaultValue = props.defaultValue,
_props$showBalance = props.showBalance,
showBalance = _props$showBalance === void 0 ? false : _props$showBalance,
_props$showFee = props.showFee,
showFee = _props$showFee === void 0 ? false : _props$showFee,
_props$allowAddCard = props.allowAddCard,
allowAddCard = _props$allowAddCard === void 0 ? false : _props$allowAddCard,
_props$addCardText = props.addCardText,
addCardText = _props$addCardText === void 0 ? 'Add a new card' : _props$addCardText,
confirmButtonText = props.confirmButtonText,
_props$disabled = props.disabled,
disabled = _props$disabled === void 0 ? false : _props$disabled,
_props$position = props.position,
position = _props$position === void 0 ? 'bottom' : _props$position,
_props$round = props.round,
round = _props$round === void 0 ? true : _props$round,
_props$closeable = props.closeable,
closeable = _props$closeable === void 0 ? true : _props$closeable,
_props$closeOnClickOv = props.closeOnClickOverlay,
closeOnClickOverlay = _props$closeOnClickOv === void 0 ? true : _props$closeOnClickOv,
_props$backgroundColo = props.backgroundColor,
backgroundColor = _props$backgroundColo === void 0 ? '#ffffff' : _props$backgroundColo,
_props$borderColor = props.borderColor,
borderColor = _props$borderColor === void 0 ? '#ebedf0' : _props$borderColor,
_props$borderRadius = props.borderRadius,
borderRadius = _props$borderRadius === void 0 ? '16px' : _props$borderRadius,
onClose = props.onClose,
onChange = props.onChange,
onAddCard = props.onAddCard,
onConfirm = props.onConfirm,
className = props.className,
style = props.style;
// 简单的状态管理
var _useState = useState(function () {
return value || defaultValue || '';
}),
selectedValue = _useState[0],
setSelectedValue = _useState[1];
// 挂载状态
var mountedRef = useRef(true);
// 同步外部value变化
useEffect(function () {
if (value !== undefined && mountedRef.current) {
setSelectedValue(value);
}
}, [value]);
// 清理挂载状态
useEffect(function () {
return function () {
mountedRef.current = false;
};
}, []);
// 处理选择变化
var handleChange = function handleChange(newValue, option) {
if (!mountedRef.current) return;
setSelectedValue(newValue);
onChange === null || onChange === void 0 ? void 0 : onChange(newValue, option);
};
// 处理确认
var handleConfirm = function handleConfirm() {
if (!mountedRef.current || !selectedValue) return;
var selectedOption = options.find(function (opt) {
return opt.id === selectedValue;
});
onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(selectedValue, selectedOption);
};
// 渲染图标
var renderIcon = function renderIcon(option) {
var icon = option.icon,
name = option.name;
// 如果是React组件
if (/*#__PURE__*/React.isValidElement(icon)) {
return /*#__PURE__*/React.createElement("div", {
style: {
width: 40,
height: 40,
borderRadius: '50%',
backgroundColor: '#f7f8fa',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}, icon);
}
if (typeof icon === 'string' && icon.trim()) {
var iconStr = icon.trim();
// 如果是emoji或短字符串(1-4个字符)
if (iconStr.length <= 4 && !iconStr.includes('http') && !iconStr.includes('.') && !iconStr.includes('/')) {
return /*#__PURE__*/React.createElement("div", {
style: {
width: 40,
height: 40,
borderRadius: '50%',
backgroundColor: '#f7f8fa',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 20
}
}, iconStr);
}
// 如果是图片URL(包含http、https、或文件扩展名)
if (iconStr.includes('http') || iconStr.includes('https') || iconStr.includes('.png') || iconStr.includes('.jpg') || iconStr.includes('.jpeg') || iconStr.includes('.gif') || iconStr.includes('.svg') || iconStr.includes('.webp') || iconStr.startsWith('/') || iconStr.startsWith('./')) {
return /*#__PURE__*/React.createElement("img", {
src: iconStr,
alt: name || 'Payment icon',
style: {
width: 40,
height: 40,
borderRadius: '50%',
objectFit: 'cover'
},
onError: function onError(e) {
var target = e.target;
target.style.display = 'none';
// 图片加载失败时,可以在这里添加fallback逻辑
console.warn("Failed to load icon: " + iconStr);
},
onLoad: function onLoad() {
// 图片加载成功时的处理
console.log("Icon loaded successfully: " + iconStr);
}
});
}
}
// 默认显示首字母
return /*#__PURE__*/React.createElement("div", {
style: {
width: 40,
height: 40,
borderRadius: '50%',
backgroundColor: '#2c64e3',
// 使用新的primary-6颜色
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#ffffff',
fontSize: 16,
fontWeight: 'bold'
}
}, (name || '?').charAt(0).toUpperCase());
};
// 渲染支付选项
var renderOptions = function renderOptions() {
if (!Array.isArray(options)) return null;
return options.map(function (option, index) {
if (!option || !option.id) return null;
var isSelected = selectedValue === option.id;
var isDisabled = option.disabled;
// 构建标题文本 - 将余额放在标题中
var titleText = option.name || 'Unknown';
if (showBalance && option.balance) {
var balanceText = (option.balance + " " + (option.currency || '')).trim();
titleText = titleText + " (" + balanceText + ")";
}
// 构建描述文本 - 只显示费用和额外信息
var descriptionParts = [];
if (showFee && option.fee) {
descriptionParts.push("Fee: " + option.fee);
}
if (option.extra) {
descriptionParts.push(option.extra);
}
var description = descriptionParts.join(' • ');
return /*#__PURE__*/React.createElement(Cell, {
key: option.id || index,
title: titleText,
label: description || undefined,
icon: renderIcon(option),
isLink: !isDisabled,
center: true,
clickable: !isDisabled,
style: {
backgroundColor: isSelected ? '#eaf0fc' : 'transparent',
// 使用新的primary-1颜色
borderLeft: isSelected ? '3px solid #2c64e3' : '3px solid transparent',
// 使用新的primary-6颜色
opacity: isDisabled ? 0.5 : 1
},
onClick: function onClick() {
if (!isDisabled && option.id) {
handleChange(option.id, option);
}
}
});
});
};
// 渲染添加卡片选项
var renderAddCard = function renderAddCard() {
if (!allowAddCard) return null;
return /*#__PURE__*/React.createElement(Cell, {
title: addCardText,
icon: /*#__PURE__*/React.createElement("div", {
style: {
width: 40,
height: 40,
borderRadius: '50%',
border: '2px solid #2c64e3',
// 使用新的primary-6颜色
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#2c64e3',
// 使用新的primary-6颜色
fontSize: 20,
fontWeight: 'bold'
}
}, "+"),
isLink: true,
center: true,
clickable: true,
onClick: onAddCard
});
};
return /*#__PURE__*/React.createElement(Popup, {
visible: visible,
position: position,
round: round,
closeable: closeable,
closeOnClickOverlay: closeOnClickOverlay,
onClose: onClose,
style: _extends({
backgroundColor: backgroundColor,
width: position === 'bottom' || position === 'top' ? '100%' : undefined,
maxWidth: position === 'bottom' || position === 'top' ? '500px' : undefined,
margin: position === 'bottom' || position === 'top' ? '0 auto' : undefined,
borderRadius: position === 'bottom' ? '16px 16px 0 0' : position === 'top' ? '0 0 16px 16px' : borderRadius,
boxShadow: '0 4px 24px rgba(0,0,0,0.08)'
}, style),
className: "mr-payment-popup-container " + (className || '')
}, /*#__PURE__*/React.createElement("div", {
ref: ref,
className: "mr-payment-popup-content",
style: {
padding: '0',
minHeight: position === 'bottom' ? 'auto' : undefined,
maxHeight: position === 'bottom' ? '80vh' : undefined,
overflow: position === 'bottom' ? 'auto' : undefined
}
}, title && /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-title"
}, title), /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-list"
}, options.map(function (option, index) {
if (!option || !option.id) return null;
var isSelected = selectedValue === option.id;
var isDisabled = option.disabled;
var titleText = option.name || 'Unknown';
if (showBalance && option.balance) {
var balanceText = (option.balance + " " + (option.currency || '')).trim();
titleText = titleText + " (" + balanceText + ")";
}
var descriptionParts = [];
if (showFee && option.fee) {
descriptionParts.push("Fee: " + option.fee);
}
if (option.extra) {
descriptionParts.push(option.extra);
}
var description = descriptionParts.join(' • ');
return /*#__PURE__*/React.createElement("div", {
key: option.id || index,
className: "mr-payment-popup-item" + (isSelected ? ' selected' : '') + (isDisabled ? ' disabled' : ''),
style: {
backgroundColor: isSelected ? '#eaf0fc' : 'transparent',
borderLeft: isSelected ? '3px solid #2c64e3' : '3px solid transparent',
opacity: isDisabled ? 0.5 : 1
},
onClick: function onClick() {
if (!isDisabled && option.id) {
handleChange(option.id, option);
}
}
}, /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-icon"
}, renderIcon(option)), /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-content"
}, /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-title"
}, titleText), description && /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-desc"
}, description)));
}), allowAddCard && /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item mr-payment-popup-add-card",
onClick: onAddCard
}, /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-icon"
}, /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-add-card-icon"
}, "+")), /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-content"
}, /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-item-title"
}, addCardText)))), confirmButtonText && /*#__PURE__*/React.createElement("div", {
className: "mr-payment-popup-footer"
}, /*#__PURE__*/React.createElement(Button, {
type: "primary",
size: "large",
block: true,
disabled: disabled || !selectedValue,
onClick: handleConfirm,
style: {
backgroundColor: disabled || !selectedValue ? '#ccdaf8' : '#2c64e3',
borderColor: disabled || !selectedValue ? '#ccdaf8' : '#2c64e3',
borderRadius: '8px',
border: 'none',
color: '#ffffff',
opacity: 1
}
}, confirmButtonText))));
});
MrPaymentPopup.displayName = 'MrPaymentPopup';
export default MrPaymentPopup;