From 0cf99848f09a4185a6f016316f6706f79983421a Mon Sep 17 00:00:00 2001 From: xianyi Date: Tue, 30 Dec 2025 18:04:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=8A=A0=E9=A1=B9=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/exam/ExamAddonPanel.tsx | 238 ++++++++++++++++++++++++- 1 file changed, 229 insertions(+), 9 deletions(-) diff --git a/src/components/exam/ExamAddonPanel.tsx b/src/components/exam/ExamAddonPanel.tsx index ed1df6f..b843183 100644 --- a/src/components/exam/ExamAddonPanel.tsx +++ b/src/components/exam/ExamAddonPanel.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo, useState, useRef } from 'react'; import type { ExamClient } from '../../data/mockData'; import { searchPhysicalExamAddItem, getAddItemCustomerInfo } from '../../api'; import { Button, Input } from '../ui'; +import { cls } from '../../utils/cls'; interface AddonTag { title: string; @@ -31,7 +32,46 @@ export const ExamAddonPanel = ({ client }: ExamAddonPanelProps) => { const debounceTimerRef = useRef(null); const [addonLoading, setAddonLoading] = useState(false); const [addonError, setAddonError] = useState(null); + // 折扣比例(1 = 100%) const [discountRatio, setDiscountRatio] = useState(1); + // 渠道折扣列表 + const [channelDiscounts, setChannelDiscounts] = useState< + { channel_id?: string | null; channel_name?: string | null; discount_rate?: number | null; discount_name?: string | null }[] + >([]); + // 下拉框状态 + const [isDiscountDropdownOpen, setIsDiscountDropdownOpen] = useState(false); + const discountDropdownRef = useRef(null); + // 结算方式:'self' 自费, 'account' 挂账 + const [paymentMethod, setPaymentMethod] = useState<'self' | 'account'>('self'); + const [isPaymentMethodDropdownOpen, setIsPaymentMethodDropdownOpen] = useState(false); + const paymentMethodDropdownRef = useRef(null); + // 挂账公司 + const [accountCompany, setAccountCompany] = useState('圆和'); + const [isAccountCompanyDropdownOpen, setIsAccountCompanyDropdownOpen] = useState(false); + const accountCompanyDropdownRef = useRef(null); + + // 点击外部关闭下拉框 + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (discountDropdownRef.current && !discountDropdownRef.current.contains(event.target as Node)) { + setIsDiscountDropdownOpen(false); + } + if (paymentMethodDropdownRef.current && !paymentMethodDropdownRef.current.contains(event.target as Node)) { + setIsPaymentMethodDropdownOpen(false); + } + if (accountCompanyDropdownRef.current && !accountCompanyDropdownRef.current.contains(event.target as Node)) { + setIsAccountCompanyDropdownOpen(false); + } + }; + + if (isDiscountDropdownOpen || isPaymentMethodDropdownOpen || isAccountCompanyDropdownOpen) { + document.addEventListener('mousedown', handleClickOutside); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [isDiscountDropdownOpen, isPaymentMethodDropdownOpen, isAccountCompanyDropdownOpen]); // 获取体检加项客户信息(用于拿到渠道折扣等信息) useEffect(() => { @@ -42,10 +82,13 @@ export const ExamAddonPanel = ({ client }: ExamAddonPanelProps) => { try { const res = await getAddItemCustomerInfo({ physical_exam_id }); if (res.Status === 200 && res.Data?.listChannelDiscount && res.Data.listChannelDiscount.length > 0) { + setChannelDiscounts(res.Data.listChannelDiscount); const rate = res.Data.listChannelDiscount[0]?.discount_rate; if (typeof rate === 'number' && rate > 0) { setDiscountRatio(rate); } + } else { + setChannelDiscounts([]); } } catch (err) { console.error('获取加项客户信息失败', err); @@ -176,12 +219,103 @@ export const ExamAddonPanel = ({ client }: ExamAddonPanelProps) => { return '渠道价'; }; + // 构建折扣选项列表 + const discountOptions = useMemo(() => { + const options: Array<{ value: number; label: string }> = [ + { value: 1, label: '100%(无折扣)' }, + ]; + channelDiscounts.forEach((item) => { + const rate = typeof item.discount_rate === 'number' && item.discount_rate > 0 ? item.discount_rate : 1; + const percent = Math.round(rate * 100); + const label = item.discount_name || `${percent}%`; + options.push({ value: rate, label }); + }); + return options; + }, [channelDiscounts]); + + // 获取当前选中的标签 + const currentDiscountLabel = useMemo(() => { + const option = discountOptions.find(opt => opt.value === discountRatio); + return option?.label || '100%(无折扣)'; + }, [discountRatio, discountOptions]); + + // 处理折扣选择 + const handleDiscountSelect = (value: number) => { + setDiscountRatio(value); + setIsDiscountDropdownOpen(false); + }; + + // 处理结算方式选择 + const handlePaymentMethodSelect = (value: 'self' | 'account') => { + setPaymentMethod(value); + setIsPaymentMethodDropdownOpen(false); + }; + + // 处理挂账公司选择 + const handleAccountCompanySelect = (value: string) => { + setAccountCompany(value); + setIsAccountCompanyDropdownOpen(false); + }; + + // 结算方式选项 + const paymentMethodOptions: Array<{ value: 'self' | 'account'; label: string }> = [ + { value: 'self', label: '自费' }, + { value: 'account', label: '挂账' }, + ]; + + // 挂账公司选项(可以根据实际需求从接口获取) + const accountCompanyOptions: Array<{ value: string; label: string }> = [ + { value: '圆和', label: '圆和' }, + ]; + return (
{/* 标题和说明 */}
-
-

体检套餐加项选择

+
+
+

体检套餐加项选择

+
+ {/* 折扣比例 */} +
+ + {isDiscountDropdownOpen && ( +
+ {discountOptions.map((option) => ( + + ))} +
+ )} +
+
+
+
{ 已优惠 ¥{discount.toFixed(0)} )}
-
结算方式: 个人支付 (微信 / 支付宝)
+ {/*
结算方式: 个人支付 (微信 / 支付宝)
*/} +
+
+ {/* 结算方式 */} +
+ 结算方式 +
+ + {isPaymentMethodDropdownOpen && ( +
+ {paymentMethodOptions.map((option) => ( + + ))} +
+ )} +
+
+ + {/* 挂账公司 */} + {paymentMethod === 'account' && ( +
+ 挂账公司 +
+ + {isAccountCompanyDropdownOpen && ( +
+ {accountCompanyOptions.map((option) => ( + + ))} +
+ )} +
+
+ )} + +
-
);