Skip to content

Commit 24b5778

Browse files
committed
统计信息
1 parent b38ecf2 commit 24b5778

9 files changed

Lines changed: 191 additions & 276 deletions

File tree

V2rayU.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
669DCEAD2E3D9C440085278B /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669DCEAC2E3D9C400085278B /* AboutView.swift */; };
8383
66A078BC2D008A3700490469 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = 66A078BB2D008A3700490469 /* SwiftyBeaver */; };
8484
66B1B5312D282DAB0032DD09 /* V2rayMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B1B5302D282D990032DD09 /* V2rayMetrics.swift */; };
85-
66B1B5332D2913000032DD09 /* ProfileStatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B1B5322D2913000032DD09 /* ProfileStatModel.swift */; };
8685
66B1B5562D2979BC0032DD09 /* V2rayUTool in CopyFiles */ = {isa = PBXBuildFile; fileRef = 66B1B54C2D2979060032DD09 /* V2rayUTool */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
8786
66B1B55A2D297B140032DD09 /* install.sh in Resources */ = {isa = PBXBuildFile; fileRef = 66B1B5592D297B140032DD09 /* install.sh */; };
8887
66B1B5742D297BF70032DD09 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 66B1B5732D297BF70032DD09 /* GoogleService-Info.plist */; };
@@ -229,7 +228,6 @@
229228
669DCEA52E3D908C0085278B /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
230229
669DCEAC2E3D9C400085278B /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
231230
66B1B5302D282D990032DD09 /* V2rayMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2rayMetrics.swift; sourceTree = "<group>"; };
232-
66B1B5322D2913000032DD09 /* ProfileStatModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileStatModel.swift; sourceTree = "<group>"; };
233231
66B1B54C2D2979060032DD09 /* V2rayUTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = V2rayUTool; sourceTree = BUILT_PRODUCTS_DIR; };
234232
66B1B5592D297B140032DD09 /* install.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install.sh; sourceTree = "<group>"; };
235233
66B1B55D2D297B590032DD09 /* appdmg.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = appdmg.json; sourceTree = "<group>"; };
@@ -331,7 +329,6 @@
331329
662CC3CD2D1BED9B006E8450 /* Models */ = {
332330
isa = PBXGroup;
333331
children = (
334-
66B1B5322D2913000032DD09 /* ProfileStatModel.swift */,
335332
662CC3CA2D1BED9B006E8450 /* ProfileModel.swift */,
336333
662CC3CB2D1BED9B006E8450 /* RoutingModel.swift */,
337334
662CC3CC2D1BED9B006E8450 /* SubModel.swift */,
@@ -780,7 +777,6 @@
780777
662CC4012D1BED9B006E8450 /* RouingList.swift in Sources */,
781778
662CC43F2D1C4CE9006E8450 /* ImportHandler.swift in Sources */,
782779
663814B12E0195F700F5FCF3 /* SubscriptionSync.swift in Sources */,
783-
66B1B5332D2913000032DD09 /* ProfileStatModel.swift in Sources */,
784780
66EB6C172E37C84100A12DB3 /* HttpServer.swift in Sources */,
785781
66E94B322D26B95D003745B5 /* LanguageLabel.swift in Sources */,
786782
66E94B332D26B95D003745B5 /* Common.swift in Sources */,

V2rayU/Base/Util.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,19 @@ func getSpeedColor(latency: Double) -> NSColor {
252252
return NSColor.systemRed
253253
}
254254
}
255+
256+
extension Int64 {
257+
var humanSize: String {
258+
let units = ["B", "KB", "MB", "GB", "TB"]
259+
var value = Double(self)
260+
var index = 0
261+
if value < 1024 {
262+
return ""
263+
}
264+
while value >= 1024 && index < units.count - 1 {
265+
value /= 1024
266+
index += 1
267+
}
268+
return String(format: "%.2f %@", value, units[index])
269+
}
270+
}

V2rayU/Database/Database.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Foundation
99
import GRDB
1010
import os.log
1111

12-
// db 实例
12+
// db 实例
1313
final class AppDatabase: Sendable {
1414
/// Access to the database.
1515
///

V2rayU/Database/Migrate.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ extension AppDatabase {
2020

2121
// 注册所有模型的迁移逻辑
2222
ProfileDTO.registerMigrations(in: &migrator)
23-
ProfileStatModel.registerMigrations(in: &migrator)
2423
SubDTO.registerMigrations(in: &migrator)
2524
RoutingDTO.registerMigrations(in: &migrator)
2625

V2rayU/Database/Models/ProfileModel.swift

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
3535
var publicKey: String = "" // publicKey(reality): reality
3636
var shortId: String = "" // shortId(reality): reality
3737
var spiderX: String = "" // spiderX(reality): reality
38+
// 统计
39+
var totalUp: Int64 = 0 // 总上传
40+
var totalDown: Int64 = 0 // 总下载
41+
var todayUp: Int64 = 0 // 今日上传
42+
var todayDown: Int64 = 0 // 今日下载
43+
var lastUpdate: Date = Date() // 最后更新时间
3844

3945
// Identifiable 协议的要求
4046
var id: String {
@@ -49,7 +55,7 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
4955

5056
// 对应编码的 `CodingKeys` 枚举
5157
enum CodingKeys: String, CodingKey {
52-
case uuid, remark, speed, sort, `protocol`, subid, address, port, password, alterId, encryption, network, headerType, host, path, security, allowInsecure, flow, sni, alpn, fingerprint, publicKey, shortId, spiderX
58+
case uuid, remark, speed, sort, `protocol`, subid, address, port, password, alterId, encryption, network, headerType, host, path, security, allowInsecure, flow, sni, alpn, fingerprint, publicKey, shortId, spiderX, totalUp, totalDown, todayUp, todayDown, lastUpdate
5359
}
5460

5561
// 提供默认值的初始化器
@@ -103,6 +109,10 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
103109
self.publicKey = publicKey
104110
self.shortId = shortId
105111
self.spiderX = spiderX
112+
self.totalUp = 0
113+
self.totalDown = 0
114+
self.todayUp = 0
115+
self.todayDown = 0
106116
}
107117

108118
// 自定义表名
@@ -136,6 +146,12 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
136146
static let publicKey = Column(CodingKeys.publicKey)
137147
static let shortId = Column(CodingKeys.shortId)
138148
static let spiderX = Column(CodingKeys.spiderX)
149+
// 统计
150+
static let totalUp = Column(CodingKeys.totalUp)
151+
static let totalDown = Column(CodingKeys.totalDown)
152+
static let todayUp = Column(CodingKeys.todayUp)
153+
static let todayDown = Column(CodingKeys.todayDown)
154+
static let lastUpdate = Column(CodingKeys.lastUpdate)
139155
}
140156

141157
// 定义迁移
@@ -144,7 +160,7 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
144160
migrator.registerMigration("createProfileTable") { db in
145161
try db.create(table: databaseTableName) { t in
146162
t.column(Columns.uuid.name, .text).notNull().primaryKey()
147-
t.column(Columns.remark.name, .text).notNull()
163+
t.column(Columns.remark.name, .text).notNull().defaults(to: "")
148164
t.column(Columns.speed.name, .integer).notNull()
149165
t.column(Columns.sort.name, .integer).notNull()
150166
t.column(Columns.protocol.name, .text).notNull()
@@ -167,6 +183,12 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
167183
t.column(Columns.publicKey.name, .text)
168184
t.column(Columns.shortId.name, .text)
169185
t.column(Columns.spiderX.name, .text)
186+
// 统计
187+
t.column(Columns.totalUp.name, .integer).notNull().defaults(to: 0)
188+
t.column(Columns.totalDown.name, .integer).notNull().defaults(to: 0)
189+
t.column(Columns.todayUp.name, .integer).notNull().defaults(to: 0)
190+
t.column(Columns.todayDown.name, .integer).notNull().defaults(to: 0)
191+
t.column(Columns.lastUpdate.name, .datetime).defaults(to: "CURRENT_DATETIME")
170192
}
171193
}
172194
}
@@ -181,6 +203,73 @@ struct ProfileDTO: Codable, Identifiable, Equatable, Hashable, Transferable, Tab
181203
logger.info("save error: \(error)")
182204
}
183205
}
206+
207+
/// 更新 `profile_stat` 表中指定 `uuid` 的统计数据
208+
static func update_stat(uuid: String, up: Int, down: Int, lastUpdate: Date) throws {
209+
let sql = """
210+
UPDATE profile
211+
SET
212+
todayUp = todayUp + ?,
213+
todayDown = todayDown + ?,
214+
totalUp = totalUp + ?,
215+
totalDown = totalDown + ?,
216+
lastUpdate = ?
217+
WHERE uuid = ?
218+
"""
219+
do {
220+
let dbWriter = AppDatabase.shared.dbWriter
221+
try dbWriter.write { db in
222+
try db.execute(
223+
sql: sql,
224+
arguments: [up, down, up, down, lastUpdate, uuid]
225+
)
226+
}
227+
} catch {
228+
logger.info("update_stat error: \(error)")
229+
}
230+
}
231+
232+
/// 清空 `profile_stat` 表中指定 `uuid` 的今日数据
233+
/// 如果 `lastUpdate` 日期非今天,则将 `todayUp` 和 `todayDown` 清零,并更新 `lastUpdate` 为当前时间
234+
/// - Parameters:
235+
/// - uuid: 唯一标识符
236+
static func clearTodayData(uuid: String) throws {
237+
// 获取当前日期的开始时间(00:00:00)
238+
let calendar = Calendar.current
239+
let todayStart = calendar.startOfDay(for: Date())
240+
do {
241+
let dbReader = AppDatabase.shared.reader
242+
return try dbReader.read { db in
243+
let sql = "SELECT lastUpdate FROM profile WHERE uuid = ?"
244+
// 查询指定 `uuid` 的 `lastUpdate`
245+
guard let lastUpdate: Date = try Date.fetchOne(db, sql: sql, arguments: [uuid]) else {
246+
// 如果未查询到记录,直接返回
247+
return
248+
}
249+
// 如果 `lastUpdate` 小于今日开始时间,表示非今天,需要清空今日数据
250+
if lastUpdate < todayStart {
251+
do {
252+
let dbWriter = AppDatabase.shared.dbWriter
253+
return try dbWriter.write { db in
254+
try db.execute(
255+
sql: """
256+
UPDATE profile
257+
SET todayUp = 0, todayDown = 0, lastUpdate = ?
258+
WHERE uuid = ?
259+
""",
260+
arguments: [Date(), uuid]
261+
)
262+
}
263+
} catch {
264+
logger.info("getFastOne error: \(error)")
265+
}
266+
}
267+
}
268+
} catch {
269+
logger.info("clearTodayData error: \(error)")
270+
return
271+
}
272+
}
184273
}
185274

186275
// MARK: - UI Model (SwiftUI 绑定)

0 commit comments

Comments
 (0)