UNPKG

mr-component

Version:
344 lines (326 loc) 12.7 kB
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;