From 4099ec636ed61f9a42e81f494c64dc6bb7415fff Mon Sep 17 00:00:00 2001 From: gentpan Date: Wed, 16 Sep 2026 18:52:04 +0500 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=A0=8F=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E7=B4=A7=E5=87=91=E6=8E=92=E7=89=88=EF=BC=9A?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E5=8D=A1=E7=89=87=E5=BA=95=E8=89=B2=E6=94=B9?= =?UTF-8?q?=E7=BB=86=E5=88=86=E9=9A=94=E7=BA=BF=EF=BC=8C=E7=BA=AF=E5=87=80?= =?UTF-8?q?=E5=BA=A6=E4=B8=8E=20DNS=20=E9=BB=98=E8=AE=A4=E6=94=B6=E8=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 isPopover 环境值,PopoverRootView 打开;Card 在弹窗里不画灰底,只在顶部画一条细分隔线,上下 8pt、行距 6pt;PageScroll 在弹窗里区块间不再留间距 - 弹窗顶栏的两个按钮改用 24pt 的 MiniIconButton - 网络弹窗:IP 纯净度、DNS 默认收起成一行(CollapsedSection,显示分数等级 / 正在使用的 DNS),点开后标题栏右侧有收起按钮;展开状态存在 AppSettings.expandedPopoverSections,变化时刷新弹窗高度 - 流量图高度 72pt → 56pt,连接探测改为 30 列 2 行 - 网络弹窗 1519pt → 952pt,其余弹窗矮 9%~21%;主窗口详情页不变 --- CHANGELOG.md | 1 + .../Sources/Localization/Translations.swift | 2 + .../OpenStatsUI/AppKit/AppController.swift | 1 + .../OpenStatsUI/Design/Components.swift | 25 +++++++- .../OpenStatsUI/Popover/NetworkPopover.swift | 63 ++++++++++++++++--- .../OpenStatsUI/Popover/PopoverRootView.swift | 53 +++++++++++++++- .../OpenStatsUI/State/AppSettings.swift | 12 ++++ README.md | 5 +- README.zh-CN.md | 5 +- project.yml | 2 +- 10 files changed, 153 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9eba7c..5e2aa57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ #### 样式 - 主窗口在 macOS 26 上改用液态玻璃:侧边栏是一块浮在窗口里的玻璃面板,红绿灯按钮落在面板里,选中项垫一块淡蓝色圆角底并随切换滑动;顶栏右侧“在菜单栏显示”一组收进玻璃胶囊。主按钮是蓝色玻璃胶囊、次要按钮与图标按钮是透明玻璃,风扇模式等快捷切换是玻璃胶囊,开关换成系统开关(拖动时滑块变成玻璃)。设置分组与数据卡片保持实色,与系统设置一致。macOS 14、15 上保持原来的样式。 +- 菜单栏弹窗改为紧凑排版,参照 Stats:区块不再是灰底卡片,改成一条细分隔线隔开,行距收紧,顶栏按钮缩小;网络弹窗的 IP 纯净度与 DNS 默认收起成一行(纯净度显示分数与等级,DNS 显示正在使用的地址),点一下展开、标题栏右侧的箭头收起,状态会记住;流量图变矮,连接探测改为两行细格。网络弹窗从约 1520pt 降到约 950pt,其他弹窗矮了一到两成。主窗口的详情页保持原样,照常完整显示。 - 连接探测只用来看网络通不通:格子通了是绿色、不通是红色(不再用橙色表示延迟偏高),固定 60 格,弹窗排成 3 行、主窗口排成 2 行;去掉格子下面的延迟、抖动、丢包三项。打开网络详情时固定每秒探测一次,「设置 · 网络」里的“探测间隔”选项随之去掉,后台低频探测仍是每 10 秒。 - 分段切换改为苹果标准样式:灰色圆角底槽,各段等宽铺满,选中的一段是实心蓝色、白字,切换时蓝块滑过去;网络详情的 IPv4 / IPv6 切换同样是灰底蓝选中。 diff --git a/Packages/OpenStatsKit/Sources/Localization/Translations.swift b/Packages/OpenStatsKit/Sources/Localization/Translations.swift index 8b1f6bb..0b9cf02 100644 --- a/Packages/OpenStatsKit/Sources/Localization/Translations.swift +++ b/Packages/OpenStatsKit/Sources/Localization/Translations.swift @@ -412,6 +412,7 @@ npm 缓存 npm Cache 屏幕保持常亮 Keep display on 屏幕可按设置关闭,下载、编译等后台任务继续运行 The display can turn off as usual while downloads and builds keep running 屏幕和系统都不会因闲置而关闭或休眠 Neither the display nor the system sleeps when idle +展开{} Expand {} 峰值 Peak 峰值 {} Peak {} 工具 Tools @@ -553,6 +554,7 @@ npm 缓存 npm Cache 搜索名称、PID 或用户 Search name, PID or user 搜索应用 Search apps 撤销 Undo +收起 Collapse 改回开机后累计 Back to since-boot totals 政府 Government 教育网 Education diff --git a/Packages/OpenStatsKit/Sources/OpenStatsUI/AppKit/AppController.swift b/Packages/OpenStatsKit/Sources/OpenStatsUI/AppKit/AppController.swift index 4cf67c8..8396f64 100644 --- a/Packages/OpenStatsKit/Sources/OpenStatsUI/AppKit/AppController.swift +++ b/Packages/OpenStatsKit/Sources/OpenStatsUI/AppKit/AppController.swift @@ -183,6 +183,7 @@ public final class AppController: NSObject, NSApplicationDelegate { _ = model.settings.colorizeHighLoad _ = model.settings.useFahrenheit _ = model.settings.hiddenPopoverSections + _ = model.settings.expandedPopoverSections _ = model.keepAwake.isActive _ = model.settings.appearance _ = model.isNetworkDetailVisible diff --git a/Packages/OpenStatsKit/Sources/OpenStatsUI/Design/Components.swift b/Packages/OpenStatsKit/Sources/OpenStatsUI/Design/Components.swift index c3d85ef..718d092 100644 --- a/Packages/OpenStatsKit/Sources/OpenStatsUI/Design/Components.swift +++ b/Packages/OpenStatsKit/Sources/OpenStatsUI/Design/Components.swift @@ -7,6 +7,8 @@ extension EnvironmentValues { @Entry var isSnapshot = false /// 在主窗口里显示指标详情:显示全部区块,图表更高 @Entry var isDetailPage = false + /// 菜单栏弹窗:区块去掉卡片底色,用细分隔线隔开,排得更紧凑 + @Entry var isPopover = false } // MARK: - 卡片 @@ -15,8 +17,23 @@ struct Card: View { var padding: CGFloat = DS.Space.s4 var spacing: CGFloat = DS.Space.s3 @ViewBuilder var content: Content + @Environment(\.isPopover) private var isPopover var body: some View { + if isPopover { + // 菜单栏弹窗:不画卡片,区块顶上一条细分隔线,上下各留一点空,行距收紧 + VStack(alignment: .leading, spacing: min(spacing, DS.Space.s1 + DS.Space.s1 / 2)) { + content + } + .padding(.vertical, DS.Space.s2) + .frame(maxWidth: .infinity, alignment: .topLeading) + .overlay(alignment: .top) { HairlineDivider() } + } else { + cardBody + } + } + + private var cardBody: some View { VStack(alignment: .leading, spacing: spacing) { content } @@ -833,11 +850,15 @@ struct DSSlider: View { struct PageScroll: View { @Environment(\.isSnapshot) private var isSnapshot + @Environment(\.isPopover) private var isPopover @ViewBuilder var content: Content var body: some View { - let stack = VStack(alignment: .leading, spacing: DS.Space.s3) { content } - .padding(DS.Space.s3) + // 弹窗里区块之间靠分隔线隔开,不再额外留间距 + let stack = VStack(alignment: .leading, spacing: isPopover ? 0 : DS.Space.s3) { content } + .padding(.horizontal, DS.Space.s3) + .padding(.top, isPopover ? 0 : DS.Space.s3) + .padding(.bottom, isPopover ? DS.Space.s1 : DS.Space.s3) if isSnapshot { stack } else { diff --git a/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/NetworkPopover.swift b/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/NetworkPopover.swift index dab2833..31868c1 100644 --- a/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/NetworkPopover.swift +++ b/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/NetworkPopover.swift @@ -75,7 +75,7 @@ private struct TrafficHistorySection: View { .monospacedDigit() }) { MirroredRateChart(upload: upload, download: download, - height: isDetailPage ? DS.Size.chartHeight * 3 : DS.Size.chartHeight + DS.Space.s6) + height: isDetailPage ? DS.Size.chartHeight * 3 : DS.Size.chartHeight + DS.Space.s2) } } @@ -104,9 +104,8 @@ private struct ProbeSection: View { } }) { if settings.probeEnabled { - // 只用来看网络通不通:60 格是最近 60 次探测,主窗口里更宽,排成两行 - let columns = isDetailPage ? 30 : 20 - ProbeGrid(samples: network.probes.elements, columns: columns, rows: NetworkController.probeCapacity / columns) + // 只用来看网络通不通:60 格是最近 60 次探测,排成两行细格 + ProbeGrid(samples: network.probes.elements, columns: NetworkController.probeCapacity / 2, rows: 2) } else { HStack { Text(tr("定时 ping 一个地址,记录网络是否通畅")).dsFont(.xs).foregroundStyle(DS.Palette.textSecondary) @@ -335,11 +334,35 @@ private struct AddressSection: View { /// cleanip.io 给出的纯净度评分与风险标记 private struct PuritySection: View { @Environment(AppModel.self) private var model + @Environment(\.isPopover) private var isPopover /// 标题行里“查看完整报告”链接的三种长度 enum ReportStyle { case full, short, icon } var body: some View { + // 菜单栏弹窗里默认收起成一行,只显示分数与等级 + if isPopover, !model.settings.isExpanded(.networkPurity) { + let summary = collapsedSummary + CollapsedSection(title: PopoverSection.networkPurity.title, summary: summary.text, summaryColor: summary.color) { + withAnimation(DS.Motion.quick) { model.settings.setExpanded(.networkPurity, true) } + } + } else { + card + } + } + + private var collapsedSummary: (text: String, color: Color) { + let network = model.network + if let purity = network.publicAddresses?.purity { + return ("\(purity.score) \(purity.grade)", DS.Grade.color(for: purity.score)) + } + if !model.settings.publicIPLookup { return (tr("查询已关闭"), DS.Palette.textTertiary) } + if network.isLookingUpPublic { return (tr("正在查询…"), DS.Palette.textTertiary) } + return ("—", DS.Palette.textTertiary) + } + + @ViewBuilder + private var card: some View { let settings = model.settings let network = model.network let addresses = network.publicAddresses @@ -419,8 +442,15 @@ private struct PuritySection: View { ReportLink(url: url, style: report).padding(.leading, DS.Space.s1) } Spacer(minLength: 0) - RefreshButton(loading: network.isLookingUpPublic, help: tr("强制刷新:忽略缓存,立即重新查询公网 IP 与归属地")) { - network.lookUpPublicAddresses(force: true) + if isPopover { + RefreshButton(loading: network.isLookingUpPublic, help: tr("强制刷新:忽略缓存,立即重新查询公网 IP 与归属地")) { + network.lookUpPublicAddresses(force: true) + } + .collapseButton(.networkPurity, settings: model.settings) + } else { + RefreshButton(loading: network.isLookingUpPublic, help: tr("强制刷新:忽略缓存,立即重新查询公网 IP 与归属地")) { + network.lookUpPublicAddresses(force: true) + } } } } @@ -461,10 +491,25 @@ private struct PuritySection: View { private struct DNSSection: View { @Environment(AppModel.self) private var model + @Environment(\.isPopover) private var isPopover @State private var editingManual = false @State private var manualText = "" var body: some View { + // 菜单栏弹窗里默认收起成一行,只显示正在使用的 DNS + if isPopover, !model.settings.isExpanded(.networkDNS) { + let servers = model.network.details?.dnsServers ?? [] + CollapsedSection(title: PopoverSection.networkDNS.title, + summary: servers.first.map { servers.count > 1 ? "\($0) +\(servers.count - 1)" : $0 } ?? "—") { + withAnimation(DS.Motion.quick) { model.settings.setExpanded(.networkDNS, true) } + } + } else { + card + } + } + + @ViewBuilder + private var card: some View { let network = model.network let maintenance = model.maintenance let physical = network.details?.physical @@ -472,7 +517,11 @@ private struct DNSSection: View { let matched = DNSPreset.matching(manual) SectionCard(title: PopoverSection.networkDNS.title, trailing: { - if let physical { Text(verbatim: physical.serviceName) } + if isPopover { + Text(verbatim: physical?.serviceName ?? "").collapseButton(.networkDNS, settings: model.settings) + } else if let physical { + Text(verbatim: physical.serviceName) + } }) { InfoRow(label: tr("正在使用")) { Text(verbatim: network.details.map { $0.dnsServers.isEmpty ? "—" : $0.dnsServers.joined(separator: "\n") } ?? "—") diff --git a/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/PopoverRootView.swift b/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/PopoverRootView.swift index 87a6d3e..2ce1f4e 100644 --- a/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/PopoverRootView.swift +++ b/Packages/OpenStatsKit/Sources/OpenStatsUI/Popover/PopoverRootView.swift @@ -27,6 +27,7 @@ struct PopoverRootView: View { } } .frame(maxWidth: .infinity, maxHeight: isSnapshot ? nil : .infinity, alignment: .top) + .environment(\.isPopover, true) } .frame(width: DS.Size.popoverWidth) .frame(maxHeight: isSnapshot ? nil : .infinity, alignment: .top) @@ -55,8 +56,8 @@ private struct PopoverHeader: View { if item == .memory { PurgeMemoryButton() } // 左边的按钮用该指标自己的图标,点进主窗口里它的页面;右边的齿轮进总设置 let page = PanelTab(item: item) - IconButton(systemName: page.symbol, help: tr("在主窗口打开“\(page.title)”")) { model.openMainWindow(page) } - IconButton(systemName: "gearshape", help: tr("设置")) { model.openSettings() } + MiniIconButton(systemName: page.symbol, help: tr("在主窗口打开“\(page.title)”")) { model.openMainWindow(page) } + MiniIconButton(systemName: "gearshape", help: tr("设置")) { model.openSettings() } } } } @@ -117,6 +118,54 @@ extension View { } } +/// 弹窗里默认收起的区块:只占一行,左边标题、右边摘要,点一下展开 +struct CollapsedSection: View { + let title: String + let summary: String + var summaryColor: Color = DS.Palette.textPrimary + let expand: () -> Void + + var body: some View { + Card { + Button(action: expand) { + HStack(spacing: DS.Space.s2) { + Text(title) + .dsFont(.xs, weight: .semibold) + .foregroundStyle(DS.Palette.textSecondary) + .lineLimit(1) + .fixedSize() + Spacer(minLength: DS.Space.s2) + Text(verbatim: summary) + .dsFont(.xs, weight: .medium) + .foregroundStyle(summaryColor) + .monospacedDigit() + .lineLimit(1) + .truncationMode(.middle) + Image(systemName: "chevron.down") + .font(.system(size: DS.TextSize.xs.rawValue, weight: .semibold)) + .foregroundStyle(DS.Palette.textTertiary) + } + .frame(height: DS.Size.segmentHeight) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + .help(tr("展开\(title)")) + } + } +} + +extension View { + /// 弹窗里可收起区块的收起按钮,放在标题栏最右边 + func collapseButton(_ section: PopoverSection, settings: AppSettings) -> some View { + HStack(spacing: DS.Space.s1) { + self + MiniIconButton(systemName: "chevron.up", help: tr("收起")) { + withAnimation(DS.Motion.quick) { settings.setExpanded(section, false) } + } + } + } +} + /// 左侧标签、右侧数值的一行 struct InfoRow: View { let label: String diff --git a/Packages/OpenStatsKit/Sources/OpenStatsUI/State/AppSettings.swift b/Packages/OpenStatsKit/Sources/OpenStatsUI/State/AppSettings.swift index eb6f9ca..1059ea1 100644 --- a/Packages/OpenStatsKit/Sources/OpenStatsUI/State/AppSettings.swift +++ b/Packages/OpenStatsKit/Sources/OpenStatsUI/State/AppSettings.swift @@ -428,6 +428,10 @@ public final class AppSettings { public var hiddenPopoverSections: Set { didSet { defaults.set(hiddenPopoverSections.map(\.rawValue).sorted(), forKey: Keys.hiddenPopoverSections) } } + /// 弹窗里默认收起、被用户展开的区块(IP 纯净度、DNS);只影响菜单栏弹窗,主窗口始终完整显示 + public var expandedPopoverSections: Set { + didSet { defaults.set(expandedPopoverSections.map(\.rawValue).sorted(), forKey: Keys.expandedPopoverSections) } + } public var probeEnabled: Bool { didSet { defaults.set(probeEnabled, forKey: Keys.probeEnabled) } } @@ -518,6 +522,7 @@ public final class AppSettings { appearance = defaults.string(forKey: Keys.appearance).flatMap(AppearanceMode.init(rawValue:)) ?? .system cleanPrefersTrash = defaults.bool(forKey: Keys.cleanPrefersTrash) menuBarLayout = defaults.string(forKey: Keys.menuBarLayout).flatMap(MenuBarLayout.init(rawValue:)) ?? .separate + expandedPopoverSections = Set((defaults.stringArray(forKey: Keys.expandedPopoverSections) ?? []).compactMap(PopoverSection.init(rawValue:))) hiddenPopoverSections = defaults.stringArray(forKey: Keys.hiddenPopoverSections) .map { Set($0.compactMap(PopoverSection.init(rawValue:))) } ?? PopoverSection.hiddenByDefault probeEnabled = defaults.object(forKey: Keys.probeEnabled) as? Bool ?? true @@ -558,6 +563,12 @@ public final class AppSettings { func isVisible(_ section: PopoverSection) -> Bool { !hiddenPopoverSections.contains(section) } + func isExpanded(_ section: PopoverSection) -> Bool { expandedPopoverSections.contains(section) } + + func setExpanded(_ section: PopoverSection, _ expanded: Bool) { + if expanded { expandedPopoverSections.insert(section) } else { expandedPopoverSections.remove(section) } + } + func setVisible(_ section: PopoverSection, _ visible: Bool) { if visible { hiddenPopoverSections.remove(section) } else { hiddenPopoverSections.insert(section) } } @@ -582,6 +593,7 @@ public final class AppSettings { static let cleanPrefersTrash = "cleanPrefersTrash" static let menuBarLayout = "menuBarLayout" static let hiddenPopoverSections = "hiddenPopoverSections" + static let expandedPopoverSections = "expandedPopoverSections" static let probeEnabled = "probeEnabled" static let probeInBackground = "probeInBackground" static let probeTarget = "probeTarget" diff --git a/README.md b/README.md index a238f0c..2281fc7 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,15 @@ system language by default; switch it in Settings → General → Language. -Latest release **0.3.2** (2026-09-16) · **4** changes in development · [full changelog](CHANGELOG.md) (kept in Chinese) +Latest release **0.3.2** (2026-09-16) · **5** changes in development · [full changelog](CHANGELOG.md) (kept in Chinese)
-2026-09-16 · Unreleased · 3 style · 1 added +2026-09-16 · Unreleased · 4 style · 1 added **Style** - 主窗口在 macOS 26 上改用液态玻璃:侧边栏是一块浮在窗口里的玻璃面板,红绿灯按钮落在面板里,选中项垫一块淡蓝色圆角底并随切换滑动;顶栏右侧“在菜单栏显示”一组收进玻璃胶囊。主按钮是蓝色玻璃胶囊、次要按钮与图标按钮是透明玻璃,风扇模式等快捷切换是玻璃胶囊,开关换成系统开关(拖动时滑块变成玻璃)。设置分组与数据卡片保持实色,与系统设置一致。macOS 14、15 上保持原来的样式。 +- 菜单栏弹窗改为紧凑排版,参照 Stats:区块不再是灰底卡片,改成一条细分隔线隔开,行距收紧,顶栏按钮缩小;网络弹窗的 IP 纯净度与 DNS 默认收起成一行(纯净度显示分数与等级,DNS 显示正在使用的地址),点一下展开、标题栏右侧的箭头收起,状态会记住;流量图变矮,连接探测改为两行细格。网络弹窗从约 1520pt 降到约 950pt,其他弹窗矮了一到两成。主窗口的详情页保持原样,照常完整显示。 - 连接探测只用来看网络通不通:格子通了是绿色、不通是红色(不再用橙色表示延迟偏高),固定 60 格,弹窗排成 3 行、主窗口排成 2 行;去掉格子下面的延迟、抖动、丢包三项。打开网络详情时固定每秒探测一次,「设置 · 网络」里的“探测间隔”选项随之去掉,后台低频探测仍是每 10 秒。 - 分段切换改为苹果标准样式:灰色圆角底槽,各段等宽铺满,选中的一段是实心蓝色、白字,切换时蓝块滑过去;网络详情的 IPv4 / IPv6 切换同样是灰底蓝选中。 diff --git a/README.zh-CN.md b/README.zh-CN.md index 6a45f88..bfb066c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -55,14 +55,15 @@ CPU 不分性能核与能效核,部分功耗与频率读数可能不显示。 -最新版本 **0.3.2**(2026-09-16) · 开发中 **4** 项改动尚未发布 · [完整更新日志](CHANGELOG.md) +最新版本 **0.3.2**(2026-09-16) · 开发中 **5** 项改动尚未发布 · [完整更新日志](CHANGELOG.md)
-2026-09-16 · 未发布 · 样式 3 · 新增 1 +2026-09-16 · 未发布 · 样式 4 · 新增 1 **样式** - 主窗口在 macOS 26 上改用液态玻璃:侧边栏是一块浮在窗口里的玻璃面板,红绿灯按钮落在面板里,选中项垫一块淡蓝色圆角底并随切换滑动;顶栏右侧“在菜单栏显示”一组收进玻璃胶囊。主按钮是蓝色玻璃胶囊、次要按钮与图标按钮是透明玻璃,风扇模式等快捷切换是玻璃胶囊,开关换成系统开关(拖动时滑块变成玻璃)。设置分组与数据卡片保持实色,与系统设置一致。macOS 14、15 上保持原来的样式。 +- 菜单栏弹窗改为紧凑排版,参照 Stats:区块不再是灰底卡片,改成一条细分隔线隔开,行距收紧,顶栏按钮缩小;网络弹窗的 IP 纯净度与 DNS 默认收起成一行(纯净度显示分数与等级,DNS 显示正在使用的地址),点一下展开、标题栏右侧的箭头收起,状态会记住;流量图变矮,连接探测改为两行细格。网络弹窗从约 1520pt 降到约 950pt,其他弹窗矮了一到两成。主窗口的详情页保持原样,照常完整显示。 - 连接探测只用来看网络通不通:格子通了是绿色、不通是红色(不再用橙色表示延迟偏高),固定 60 格,弹窗排成 3 行、主窗口排成 2 行;去掉格子下面的延迟、抖动、丢包三项。打开网络详情时固定每秒探测一次,「设置 · 网络」里的“探测间隔”选项随之去掉,后台低频探测仍是每 10 秒。 - 分段切换改为苹果标准样式:灰色圆角底槽,各段等宽铺满,选中的一段是实心蓝色、白字,切换时蓝块滑过去;网络详情的 IPv4 / IPv6 切换同样是灰底蓝选中。 diff --git a/project.yml b/project.yml index dce0561..26ff626 100644 --- a/project.yml +++ b/project.yml @@ -13,7 +13,7 @@ settings: SWIFT_VERSION: "6.0" MARKETING_VERSION: "0.3.2" # 构建号四位数字,每次 make build 加一;营销版本只在发布时用 Scripts/version.sh patch / minor 修改 - CURRENT_PROJECT_VERSION: "0068" + CURRENT_PROJECT_VERSION: "0070" MACOSX_DEPLOYMENT_TARGET: "14.0" # 本地开发使用 ad-hoc 签名;发布时改为 Developer ID(见 docs/PLAN.md) CODE_SIGN_STYLE: Manual