feat:持有相关数据隐藏完善
This commit is contained in:
@@ -59,6 +59,7 @@ export default function FundCard({
|
|||||||
onToggleCollapse,
|
onToggleCollapse,
|
||||||
onToggleTrendCollapse,
|
onToggleTrendCollapse,
|
||||||
layoutMode = 'card', // 'card' | 'drawer',drawer 时前10重仓与业绩走势以 Tabs 展示
|
layoutMode = 'card', // 'card' | 'drawer',drawer 时前10重仓与业绩走势以 Tabs 展示
|
||||||
|
masked = false,
|
||||||
}) {
|
}) {
|
||||||
const holding = holdings[f?.code];
|
const holding = holdings[f?.code];
|
||||||
const profit = getHoldingProfit?.(f, holding) ?? null;
|
const profit = getHoldingProfit?.(f, holding) ?? null;
|
||||||
@@ -246,7 +247,9 @@ export default function FundCard({
|
|||||||
>
|
>
|
||||||
持仓金额 {layoutMode !== 'drawer' && <SettingsIcon width="12" height="12" style={{ opacity: 0.7 }} />}
|
持仓金额 {layoutMode !== 'drawer' && <SettingsIcon width="12" height="12" style={{ opacity: 0.7 }} />}
|
||||||
</span>
|
</span>
|
||||||
<span className="value">¥{profit.amount.toFixed(2)}</span>
|
<span className="value">
|
||||||
|
{masked ? '******' : `¥${profit.amount.toFixed(2)}`}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat" style={{ flexDirection: 'column', gap: 4 }}>
|
<div className="stat" style={{ flexDirection: 'column', gap: 4 }}>
|
||||||
<span className="label">当日收益</span>
|
<span className="label">当日收益</span>
|
||||||
@@ -262,7 +265,9 @@ export default function FundCard({
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{profit.profitToday != null
|
{profit.profitToday != null
|
||||||
? `${profit.profitToday > 0 ? '+' : profit.profitToday < 0 ? '-' : ''}¥${Math.abs(profit.profitToday).toFixed(2)}`
|
? masked
|
||||||
|
? '******'
|
||||||
|
: `${profit.profitToday > 0 ? '+' : profit.profitToday < 0 ? '-' : ''}¥${Math.abs(profit.profitToday).toFixed(2)}`
|
||||||
: '--'}
|
: '--'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -288,14 +293,18 @@ export default function FundCard({
|
|||||||
profit.profitTotal > 0 ? 'up' : profit.profitTotal < 0 ? 'down' : ''
|
profit.profitTotal > 0 ? 'up' : profit.profitTotal < 0 ? 'down' : ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{profit.profitTotal > 0 ? '+' : profit.profitTotal < 0 ? '-' : ''}
|
{masked
|
||||||
{percentModes?.[f.code]
|
? '******'
|
||||||
? `${Math.abs(
|
: <>
|
||||||
holding?.cost * holding?.share
|
{profit.profitTotal > 0 ? '+' : profit.profitTotal < 0 ? '-' : ''}
|
||||||
? (profit.profitTotal / (holding.cost * holding.share)) * 100
|
{percentModes?.[f.code]
|
||||||
: 0,
|
? `${Math.abs(
|
||||||
).toFixed(2)}%`
|
holding?.cost * holding?.share
|
||||||
: `¥${Math.abs(profit.profitTotal).toFixed(2)}`}
|
? (profit.profitTotal / (holding.cost * holding.share)) * 100
|
||||||
|
: 0,
|
||||||
|
).toFixed(2)}%`
|
||||||
|
: `¥${Math.abs(profit.profitTotal).toFixed(2)}`}
|
||||||
|
</>}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -56,9 +56,11 @@ export default function GroupSummary({
|
|||||||
groupName,
|
groupName,
|
||||||
getProfit,
|
getProfit,
|
||||||
stickyTop,
|
stickyTop,
|
||||||
|
masked,
|
||||||
|
onToggleMasked,
|
||||||
}) {
|
}) {
|
||||||
const [showPercent, setShowPercent] = useState(true);
|
const [showPercent, setShowPercent] = useState(true);
|
||||||
const [isMasked, setIsMasked] = useState(false);
|
const [isMasked, setIsMasked] = useState(masked ?? false);
|
||||||
const [isSticky, setIsSticky] = useState(false);
|
const [isSticky, setIsSticky] = useState(false);
|
||||||
const rowRef = useRef(null);
|
const rowRef = useRef(null);
|
||||||
const [assetSize, setAssetSize] = useState(24);
|
const [assetSize, setAssetSize] = useState(24);
|
||||||
@@ -74,6 +76,12 @@ export default function GroupSummary({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof masked === 'boolean') {
|
||||||
|
setIsMasked(masked);
|
||||||
|
}
|
||||||
|
}, [masked]);
|
||||||
|
|
||||||
const summary = useMemo(() => {
|
const summary = useMemo(() => {
|
||||||
let totalAsset = 0;
|
let totalAsset = 0;
|
||||||
let totalProfitToday = 0;
|
let totalProfitToday = 0;
|
||||||
@@ -185,7 +193,13 @@ export default function GroupSummary({
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className="fav-button"
|
className="fav-button"
|
||||||
onClick={() => setIsMasked((value) => !value)}
|
onClick={() => {
|
||||||
|
if (onToggleMasked) {
|
||||||
|
onToggleMasked();
|
||||||
|
} else {
|
||||||
|
setIsMasked((value) => !value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
aria-label={isMasked ? '显示资产' : '隐藏资产'}
|
aria-label={isMasked ? '显示资产' : '隐藏资产'}
|
||||||
style={{
|
style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ function SortableRow({ row, children, isTableDragging, disabled }) {
|
|||||||
* @param {string} [props.sortBy] - 排序方式,'default' 时长按行触发拖拽排序
|
* @param {string} [props.sortBy] - 排序方式,'default' 时长按行触发拖拽排序
|
||||||
* @param {(oldIndex: number, newIndex: number) => void} [props.onReorder] - 拖拽排序回调
|
* @param {(oldIndex: number, newIndex: number) => void} [props.onReorder] - 拖拽排序回调
|
||||||
* @param {(row: any) => Object} [props.getFundCardProps] - 给定行返回 FundCard 的 props;传入后点击基金名称将用底部弹框展示卡片视图
|
* @param {(row: any) => Object} [props.getFundCardProps] - 给定行返回 FundCard 的 props;传入后点击基金名称将用底部弹框展示卡片视图
|
||||||
|
* @param {boolean} [props.masked] - 是否隐藏持仓相关金额
|
||||||
*/
|
*/
|
||||||
export default function MobileFundTable({
|
export default function MobileFundTable({
|
||||||
data = [],
|
data = [],
|
||||||
@@ -126,6 +127,7 @@ export default function MobileFundTable({
|
|||||||
getFundCardProps,
|
getFundCardProps,
|
||||||
blockDrawerClose = false,
|
blockDrawerClose = false,
|
||||||
closeDrawerRef,
|
closeDrawerRef,
|
||||||
|
masked = false,
|
||||||
}) {
|
}) {
|
||||||
const [isNameSortMode, setIsNameSortMode] = useState(false);
|
const [isNameSortMode, setIsNameSortMode] = useState(false);
|
||||||
|
|
||||||
@@ -559,7 +561,7 @@ export default function MobileFundTable({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{holdingAmountDisplay}
|
{masked ? '******' : holdingAmountDisplay}
|
||||||
{hasDca && <span className="dca-indicator">定</span>}
|
{hasDca && <span className="dca-indicator">定</span>}
|
||||||
{isUpdated && <span className="updated-indicator">✓</span>}
|
{isUpdated && <span className="updated-indicator">✓</span>}
|
||||||
</span>
|
</span>
|
||||||
@@ -754,10 +756,10 @@ export default function MobileFundTable({
|
|||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
||||||
<FitText maxFontSize={14} minFontSize={10}>
|
<FitText maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasProfit ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
</span>
|
</span>
|
||||||
{percentStr ? (
|
{percentStr && !masked ? (
|
||||||
<span className={`${cls} estimate-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} estimate-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
@@ -784,10 +786,10 @@ export default function MobileFundTable({
|
|||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
||||||
<FitText maxFontSize={14} minFontSize={10}>
|
<FitText maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasProfit ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
</span>
|
</span>
|
||||||
{percentStr && !isUpdated ? (
|
{percentStr && !isUpdated && !masked ? (
|
||||||
<span className={`${cls} today-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} today-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
@@ -813,10 +815,10 @@ export default function MobileFundTable({
|
|||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
<span className={cls} style={{ display: 'block', width: '100%', fontWeight: 700 }}>
|
||||||
<FitText maxFontSize={14} minFontSize={10}>
|
<FitText maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasTotal ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
</span>
|
</span>
|
||||||
{percentStr ? (
|
{percentStr && !masked ? (
|
||||||
<span className={`${cls} holding-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} holding-profit-percent`} style={{ display: 'block', width: '100%', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ function SortableRow({ row, children, isTableDragging, disabled }) {
|
|||||||
* @param {React.MutableRefObject<(() => void) | null>} [props.closeDialogRef] - 注入关闭弹框的方法,用于确认删除时关闭
|
* @param {React.MutableRefObject<(() => void) | null>} [props.closeDialogRef] - 注入关闭弹框的方法,用于确认删除时关闭
|
||||||
* @param {boolean} [props.blockDialogClose] - 为 true 时阻止点击遮罩关闭弹框(如删除确认弹框打开时)
|
* @param {boolean} [props.blockDialogClose] - 为 true 时阻止点击遮罩关闭弹框(如删除确认弹框打开时)
|
||||||
* @param {number} [props.stickyTop] - 表头固定时的 top 偏移(与 MobileFundTable 一致,用于适配导航栏、筛选栏等)
|
* @param {number} [props.stickyTop] - 表头固定时的 top 偏移(与 MobileFundTable 一致,用于适配导航栏、筛选栏等)
|
||||||
|
* @param {boolean} [props.masked] - 是否隐藏持仓相关金额
|
||||||
*/
|
*/
|
||||||
export default function PcFundTable({
|
export default function PcFundTable({
|
||||||
data = [],
|
data = [],
|
||||||
@@ -149,6 +150,7 @@ export default function PcFundTable({
|
|||||||
closeDialogRef,
|
closeDialogRef,
|
||||||
blockDialogClose = false,
|
blockDialogClose = false,
|
||||||
stickyTop = 0,
|
stickyTop = 0,
|
||||||
|
masked = false,
|
||||||
}) {
|
}) {
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor, {
|
useSensor(PointerSensor, {
|
||||||
@@ -678,9 +680,9 @@ export default function PcFundTable({
|
|||||||
return (
|
return (
|
||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasProfit ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
{percentStr ? (
|
{percentStr && !masked ? (
|
||||||
<span className={`${cls} estimate-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} estimate-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
@@ -736,7 +738,7 @@ export default function PcFundTable({
|
|||||||
>
|
>
|
||||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>
|
<div style={{ flex: '1 1 0', minWidth: 0 }}>
|
||||||
<FitText style={{ fontWeight: 700 }} maxFontSize={14} minFontSize={10}>
|
<FitText style={{ fontWeight: 700 }} maxFontSize={14} minFontSize={10}>
|
||||||
{info.getValue() ?? '—'}
|
{masked ? '******' : (info.getValue() ?? '—')}
|
||||||
</FitText>
|
</FitText>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@@ -774,9 +776,9 @@ export default function PcFundTable({
|
|||||||
return (
|
return (
|
||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasProfit ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
{percentStr && !isUpdated ? (
|
{percentStr && !isUpdated && !masked ? (
|
||||||
<span className={`${cls} today-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} today-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
@@ -806,9 +808,9 @@ export default function PcFundTable({
|
|||||||
return (
|
return (
|
||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
<FitText className={cls} style={{ fontWeight: 700, display: 'block' }} maxFontSize={14} minFontSize={10}>
|
||||||
{amountStr}
|
{masked && hasTotal ? '******' : amountStr}
|
||||||
</FitText>
|
</FitText>
|
||||||
{percentStr ? (
|
{percentStr && !masked ? (
|
||||||
<span className={`${cls} holding-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
<span className={`${cls} holding-profit-percent`} style={{ display: 'block', fontSize: '0.75em', opacity: 0.9, fontWeight: 500 }}>
|
||||||
<FitText maxFontSize={11} minFontSize={9}>
|
<FitText maxFontSize={11} minFontSize={9}>
|
||||||
{percentStr}
|
{percentStr}
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ export default function HomePage() {
|
|||||||
|
|
||||||
// 视图模式
|
// 视图模式
|
||||||
const [viewMode, setViewMode] = useState('card'); // card, list
|
const [viewMode, setViewMode] = useState('card'); // card, list
|
||||||
|
// 全局隐藏金额状态(影响分组汇总、列表和卡片)
|
||||||
|
const [maskAmounts, setMaskAmounts] = useState(false);
|
||||||
|
|
||||||
// 用户认证状态
|
// 用户认证状态
|
||||||
const [user, setUser] = useState(null);
|
const [user, setUser] = useState(null);
|
||||||
@@ -3925,6 +3927,8 @@ export default function HomePage() {
|
|||||||
groupName={getGroupName()}
|
groupName={getGroupName()}
|
||||||
getProfit={getHoldingProfit}
|
getProfit={getHoldingProfit}
|
||||||
stickyTop={navbarHeight + filterBarHeight + (isMobile ? -14 : 0)}
|
stickyTop={navbarHeight + filterBarHeight + (isMobile ? -14 : 0)}
|
||||||
|
masked={maskAmounts}
|
||||||
|
onToggleMasked={() => setMaskAmounts((v) => !v)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{currentTab !== 'all' && currentTab !== 'fav' && (
|
{currentTab !== 'all' && currentTab !== 'fav' && (
|
||||||
@@ -4019,6 +4023,7 @@ export default function HomePage() {
|
|||||||
onCustomSettingsChange={triggerCustomSettingsSync}
|
onCustomSettingsChange={triggerCustomSettingsSync}
|
||||||
closeDialogRef={fundDetailDialogCloseRef}
|
closeDialogRef={fundDetailDialogCloseRef}
|
||||||
blockDialogClose={!!fundDeleteConfirm}
|
blockDialogClose={!!fundDeleteConfirm}
|
||||||
|
masked={maskAmounts}
|
||||||
getFundCardProps={(row) => {
|
getFundCardProps={(row) => {
|
||||||
const fund = row?.rawFund || (row ? { code: row.code, name: row.fundName } : null);
|
const fund = row?.rawFund || (row ? { code: row.code, name: row.fundName } : null);
|
||||||
if (!fund) return {};
|
if (!fund) return {};
|
||||||
@@ -4047,6 +4052,7 @@ export default function HomePage() {
|
|||||||
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||||
onToggleCollapse: toggleCollapse,
|
onToggleCollapse: toggleCollapse,
|
||||||
onToggleTrendCollapse: toggleTrendCollapse,
|
onToggleTrendCollapse: toggleTrendCollapse,
|
||||||
|
masked: maskAmounts,
|
||||||
layoutMode: 'drawer',
|
layoutMode: 'drawer',
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
@@ -4122,9 +4128,11 @@ export default function HomePage() {
|
|||||||
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||||
onToggleCollapse: toggleCollapse,
|
onToggleCollapse: toggleCollapse,
|
||||||
onToggleTrendCollapse: toggleTrendCollapse,
|
onToggleTrendCollapse: toggleTrendCollapse,
|
||||||
|
masked: maskAmounts,
|
||||||
layoutMode: 'drawer',
|
layoutMode: 'drawer',
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
masked={maskAmounts}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
@@ -4165,6 +4173,7 @@ export default function HomePage() {
|
|||||||
}
|
}
|
||||||
onToggleCollapse={toggleCollapse}
|
onToggleCollapse={toggleCollapse}
|
||||||
onToggleTrendCollapse={toggleTrendCollapse}
|
onToggleTrendCollapse={toggleTrendCollapse}
|
||||||
|
masked={maskAmounts}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user