Files
Stockbar/StockMonitor/Views/ProfitSummaryView.swift
vgearenandClaude Opus 4.6 592ad90f61 v1.2.5: Add watchlist (观察仓) feature with virtual portfolio support
- New Watchlist model: named virtual portfolios with per-stock cost/shares
- Watchlists persisted to watchlists.json, active ID in settings
- AppState: effective cost/shares/PnL methods that respect active watchlist
- Settings: create/delete/switch watchlists, edit writes to active watchlist
- ProfitSummaryView shows active watchlist name
- UI alignment fixes for toggle and text field padding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 11:31:59 +08:00

46 lines
2.1 KiB
Swift

import SwiftUI
struct ProfitSummaryView: View {
@EnvironmentObject var appState: AppState
private static let timeFmt: DateFormatter = {
let f = DateFormatter(); f.dateFormat = "HH:mm:ss"; return f
}()
var body: some View {
if appState.hasPnLData {
HStack {
VStack(alignment: .leading, spacing: 1) {
Text(appState.activeWatchlistName == "真实持仓" ? "持仓盈亏" : "[\(appState.activeWatchlistName)]盈亏")
.font(.system(size: 10)).foregroundColor(.secondary)
if let t = appState.lastUpdateTime {
Text("更新:\(Self.timeFmt.string(from: t))\(appState.hasError ? " ⚠" : "")")
.font(.system(size: 9))
.foregroundColor(appState.hasError ? .yellow : .secondary)
}
}
Spacer()
VStack(alignment: .trailing, spacing: 2) {
let sym = appState.displayCurrency.symbol
let daily = appState.totalDailyPnL
let sign1 = daily >= 0 ? "+" : "-"
let dailyPct = appState.totalDailyPnLPercent
Text("日\(sign1)\(sym)\(String(format: "%.2f", abs(daily))) \(String(format: "%.2f%%", dailyPct))")
.font(.system(size: 12, weight: .medium))
.foregroundColor(appState.pnlColor(daily))
let pnl = appState.totalPnL
let sign2 = pnl >= 0 ? "+" : "-"
let pnlPct = appState.totalPnLPercent
Text("浮\(sign2)\(sym)\(String(format: "%.2f", abs(pnl))) \(String(format: "%.2f%%", pnlPct))")
.font(.system(size: 12, weight: .medium))
.foregroundColor(appState.pnlColor(pnl))
}
}
.padding(.horizontal, 8)
.padding(.vertical, 5)
.background(Color.primary.opacity(0.04))
.cornerRadius(6)
}
}
}