PowerPopupView.swift 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. //
  2. // PowerPopupView.swift
  3. // RoderickRalph
  4. //
  5. // Created by Neoa on 2025/8/20.
  6. //
  7. import Foundation
  8. import UIKit
  9. struct LoginUserInfo {
  10. let nickName: String
  11. let userId: String
  12. let registryTimeStr: String
  13. let todayAnswerCount: Int
  14. let historyAnswerCount: Int
  15. let headImgURL: String?
  16. let lastLoginTimeStr: String
  17. let answerLogs: [String] // ✅ 新增:作答时间记录
  18. }
  19. protocol PowerPopupViewDelegate: AnyObject {
  20. func powerPopupViewDidTapGetPower(_ view: PowerPopupView)
  21. func powerPopupViewDidClose(_ view: PowerPopupView)
  22. }
  23. class PowerPopupView: UIView, UITableViewDelegate {
  24. weak var delegate: PowerPopupViewDelegate?
  25. // MARK: - UI Components
  26. private let backgroundView: UIView = {
  27. let view = UIView()
  28. view.backgroundColor = UIColor.black.withAlphaComponent(0.5) // Semi-transparent gray background
  29. view.translatesAutoresizingMaskIntoConstraints = false
  30. return view
  31. }()
  32. private let timeLabel: UILabel = {
  33. let label = UILabel()
  34. label.text = ""
  35. label.font = UIFont.systemFont(ofSize: 14)
  36. label.textColor = .white
  37. label.translatesAutoresizingMaskIntoConstraints = false
  38. return label
  39. }()
  40. private let redBGView: UIImageView = {
  41. let iv = UIImageView()
  42. iv.image = UIImage(named: "tqan325")
  43. iv.contentMode = .scaleToFill
  44. iv.translatesAutoresizingMaskIntoConstraints = false
  45. return iv
  46. }()
  47. private let whiteBGView: UIView = {
  48. let view = UIView()
  49. view.backgroundColor = .white
  50. view.layer.cornerRadius = 12
  51. view.translatesAutoresizingMaskIntoConstraints = false
  52. return view
  53. }()
  54. private let redFontView: UIImageView = {
  55. let iv = UIImageView()
  56. iv.image = UIImage(named: "tqan324")
  57. iv.contentMode = .scaleToFill
  58. iv.translatesAutoresizingMaskIntoConstraints = false
  59. return iv
  60. }()
  61. private let softwareNameLabel: UILabel = {
  62. let label = UILabel()
  63. label.text = "青柠檬记账"
  64. label.font = UIFont.systemFont(ofSize: 16)
  65. label.textColor = .white
  66. label.translatesAutoresizingMaskIntoConstraints = false
  67. return label
  68. }()
  69. private let countDownLabel: UILabel = {
  70. let label = UILabel()
  71. label.text = "7s"
  72. label.font = UIFont.systemFont(ofSize: 24)
  73. label.textColor = .white
  74. label.translatesAutoresizingMaskIntoConstraints = false
  75. return label
  76. }()
  77. private let getPowerButton: UIButton = {
  78. let button = UIButton(type: .system)
  79. button.setBackgroundImage(UIImage(named: "tqan323"), for: .normal)
  80. button.setTitle("获取体力", for: .normal)
  81. button.setTitleColor(.white, for: .normal)
  82. button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 24)
  83. button.contentHorizontalAlignment = .center
  84. button.translatesAutoresizingMaskIntoConstraints = false
  85. button.isHidden = true // Initially hidden
  86. return button
  87. }()
  88. private let userInfoBGView: UIImageView = {
  89. let iv = UIImageView()
  90. iv.image = UIImage(named: "tqan326")
  91. iv.contentMode = .scaleToFill
  92. iv.translatesAutoresizingMaskIntoConstraints = false
  93. return iv
  94. }()
  95. private let iconBGView: UIImageView = {
  96. let iv = UIImageView()
  97. iv.image = UIImage(named: "tqan331")
  98. iv.contentMode = .scaleAspectFit
  99. iv.translatesAutoresizingMaskIntoConstraints = false
  100. return iv
  101. }()
  102. private let iconImageView: UIImageView = {
  103. let iv = UIImageView()
  104. iv.image = UIImage(named: "catlogos")
  105. iv.contentMode = .scaleAspectFit
  106. iv.layer.cornerRadius = 24
  107. iv.clipsToBounds = true
  108. iv.translatesAutoresizingMaskIntoConstraints = false
  109. return iv
  110. }()
  111. private let nikNmeLeftLabel: UILabel = {
  112. let label = UILabel()
  113. label.text = "昵 称"
  114. label.font = UIFont.systemFont(ofSize: 12)
  115. label.textColor = UIColor(hexString:"#E28814")
  116. label.translatesAutoresizingMaskIntoConstraints = false
  117. return label
  118. }()
  119. private let nikNmeRightBGView: UIImageView = {
  120. let iv = UIImageView()
  121. iv.image = UIImage(named: "tqan332")
  122. iv.contentMode = .scaleToFill
  123. iv.translatesAutoresizingMaskIntoConstraints = false
  124. return iv
  125. }()
  126. private let nikNmeRightLabel: UILabel = {
  127. let label = UILabel()
  128. label.text = "XXXX"
  129. label.font = UIFont.systemFont(ofSize: 12)
  130. label.textColor = UIColor(hexString:"#E28814")
  131. label.textAlignment = .center
  132. label.translatesAutoresizingMaskIntoConstraints = false
  133. return label
  134. }()
  135. private let roleIDLeftLabel: UILabel = {
  136. let label = UILabel()
  137. label.text = "角色ID"
  138. label.font = UIFont.systemFont(ofSize: 12)
  139. label.textColor = UIColor(hexString:"#E28814")
  140. label.translatesAutoresizingMaskIntoConstraints = false
  141. return label
  142. }()
  143. private let roleIDRightBGView: UIImageView = {
  144. let iv = UIImageView()
  145. iv.image = UIImage(named: "tqan332")
  146. iv.contentMode = .scaleToFill
  147. iv.translatesAutoresizingMaskIntoConstraints = false
  148. return iv
  149. }()
  150. private let roleIDRightLabel: UILabel = {
  151. let label = UILabel()
  152. label.text = "XXXX"
  153. label.font = UIFont.systemFont(ofSize: 12)
  154. label.textColor = UIColor(hexString:"#E28814")
  155. if let image = UIImage(named: "tqan332") {
  156. label.layer.contents = image.cgImage
  157. label.layer.contentsGravity = .resizeAspect // 控制图片显示方式
  158. label.layer.contentsScale = UIScreen.main.scale
  159. }
  160. label.textAlignment = .center
  161. label.translatesAutoresizingMaskIntoConstraints = false
  162. return label
  163. }()
  164. private let registrationTimeLabel: UILabel = {
  165. let label = UILabel()
  166. label.text = "注册时间: 2025-05-26 17:58:48"
  167. label.font = UIFont.systemFont(ofSize: 12)
  168. label.textColor = UIColor(hexString:"#E28814")
  169. label.translatesAutoresizingMaskIntoConstraints = false
  170. return label
  171. }()
  172. private let loginTimeLabel: UILabel = {
  173. let label = UILabel()
  174. label.text = "登录时间: 2025-05-26 17:58:48"
  175. label.font = UIFont.systemFont(ofSize: 12)
  176. label.textColor = UIColor(hexString:"#E28814")
  177. label.translatesAutoresizingMaskIntoConstraints = false
  178. return label
  179. }()
  180. private let todayAnswerLabel: UILabel = {
  181. let label = UILabel()
  182. label.text = "今日答题: XX题"
  183. label.font = UIFont.boldSystemFont(ofSize: 12)
  184. label.textColor = UIColor(hexString:"#E28814")
  185. label.translatesAutoresizingMaskIntoConstraints = false
  186. return label
  187. }()
  188. private let historyAnswerLabel: UILabel = {
  189. let label = UILabel()
  190. label.text = "历史答题: XX题"
  191. label.font = UIFont.boldSystemFont(ofSize: 12)
  192. label.textColor = UIColor(hexString:"#E28814")
  193. label.translatesAutoresizingMaskIntoConstraints = false
  194. return label
  195. }()
  196. private let answerLogBGView: UIImageView = {
  197. let iv = UIImageView()
  198. iv.image = UIImage(named: "tqan326")
  199. iv.contentMode = .scaleToFill
  200. iv.translatesAutoresizingMaskIntoConstraints = false
  201. return iv
  202. }()
  203. private let answerLogLabel: UILabel = {
  204. let label = UILabel()
  205. label.text = "记录"
  206. label.font = UIFont.boldSystemFont(ofSize: 12)
  207. label.textColor = UIColor(hexString:"#E28814")
  208. label.translatesAutoresizingMaskIntoConstraints = false
  209. return label
  210. }()
  211. private let logDivider: UIView = {
  212. let view = UIView()
  213. view.backgroundColor = UIColor(hexString: "#EEEEEE")
  214. view.translatesAutoresizingMaskIntoConstraints = false
  215. return view
  216. }()
  217. private let answerLogListView: UITableView = {
  218. let tableView = UITableView()
  219. tableView.translatesAutoresizingMaskIntoConstraints = false
  220. tableView.isScrollEnabled = false
  221. tableView.isScrollEnabled = true // Enable scrolling if records exceed visible area
  222. tableView.backgroundColor = .clear // Transparent background
  223. tableView.separatorStyle = .none // No separators between rows
  224. tableView.rowHeight = 20 // Adjust the row height if necessary
  225. return tableView
  226. }()
  227. private let closeButton: UIButton = {
  228. let button = UIButton(type: .custom)
  229. button.setImage(UIImage(named: "pqan334"), for: .normal)
  230. button.addTarget(self, action: #selector(closePopup), for: .touchUpInside)
  231. button.translatesAutoresizingMaskIntoConstraints = false
  232. button.isHidden = true // Initially hidden
  233. return button
  234. }()
  235. private var countdownTimer: Timer?
  236. private var secondsRemaining = 7
  237. private var hasRecordedOpenTime = false
  238. private var answerLogs: [String] = [] // ✅ 来自登录返回 answerRecordTimeList
  239. // MARK: - Initialization
  240. init() {
  241. super.init(frame: .zero)
  242. // Register the cell class for the table view
  243. answerLogListView.register(UITableViewCell.self, forCellReuseIdentifier: "AnswerLogCell")
  244. answerLogListView.dataSource = self
  245. answerLogListView.delegate = self
  246. setupUI()
  247. setupConstraints()
  248. setOpenTime()
  249. startCountdown() // Start countdown as soon as the view is initialized
  250. }
  251. override func didMoveToWindow() {
  252. super.didMoveToWindow()
  253. if window != nil && !hasRecordedOpenTime {
  254. setOpenTime()
  255. hasRecordedOpenTime = true
  256. }
  257. }
  258. required init?(coder: NSCoder) {
  259. fatalError("init(coder:) has not been implemented")
  260. }
  261. // MARK: - UI Setup
  262. private func setupUI() {
  263. addSubview(backgroundView)
  264. addSubview(timeLabel)
  265. addSubview(redBGView)
  266. addSubview(whiteBGView)
  267. addSubview(userInfoBGView)
  268. addSubview(iconBGView)
  269. addSubview(iconImageView)
  270. addSubview(nikNmeLeftLabel)
  271. addSubview(nikNmeRightBGView)
  272. addSubview(nikNmeRightLabel)
  273. addSubview(roleIDLeftLabel)
  274. addSubview(roleIDRightBGView)
  275. addSubview(roleIDRightLabel)
  276. addSubview(registrationTimeLabel)
  277. addSubview(loginTimeLabel)
  278. addSubview(todayAnswerLabel)
  279. addSubview(historyAnswerLabel)
  280. addSubview(answerLogBGView)
  281. addSubview(answerLogLabel)
  282. addSubview(logDivider)
  283. addSubview(answerLogListView)
  284. addSubview(closeButton)
  285. addSubview(redFontView)
  286. addSubview(softwareNameLabel)
  287. addSubview(countDownLabel)
  288. addSubview(getPowerButton)
  289. // Prefill software name with selected channel if available
  290. applySavedChannelName()
  291. // 让“获取体力”按钮把点击事件回传给外部
  292. getPowerButton.addTarget(self, action: #selector(handleGetPowerButtonTap), for: .touchUpInside)
  293. }
  294. func configure(with info: LoginUserInfo) {
  295. // Sync software/app name with selected channel
  296. applySavedChannelName()
  297. nikNmeRightLabel.text = info.nickName
  298. roleIDRightLabel.text = info.userId
  299. registrationTimeLabel.text = "注册时间: \(info.registryTimeStr)"
  300. loginTimeLabel.text = "登录时间: \(info.lastLoginTimeStr)"
  301. todayAnswerLabel.text = "今日答题: \(info.todayAnswerCount)题"
  302. historyAnswerLabel.text = "历史答题: \(info.historyAnswerCount)题"
  303. if let urlStr = info.headImgURL, let url = URL(string: urlStr) {
  304. loadImage(into: iconImageView, from: url)
  305. }
  306. // ✅ 写入答题记录并刷新列表
  307. answerLogs = info.answerLogs
  308. answerLogListView.reloadData()
  309. }
  310. // Helper to apply saved channel name to softwareNameLabel
  311. private func applySavedChannelName() {
  312. if let savedChannel = UserDefaults.standard.string(forKey: "selectedChannelName"), !savedChannel.isEmpty {
  313. softwareNameLabel.text = savedChannel
  314. }
  315. }
  316. private static let imageCache = NSCache<NSURL, UIImage>()
  317. private func loadImage(into imageView: UIImageView, from url: URL) {
  318. if let cached = PowerPopupView.imageCache.object(forKey: url as NSURL) {
  319. imageView.image = cached
  320. return
  321. }
  322. URLSession.shared.dataTask(with: url) { data, _, _ in
  323. guard let data = data, let img = UIImage(data: data) else { return }
  324. PowerPopupView.imageCache.setObject(img, forKey: url as NSURL)
  325. DispatchQueue.main.async { imageView.image = img }
  326. }.resume()
  327. }
  328. @objc private func handleGetPowerButtonTap() {
  329. delegate?.powerPopupViewDidTapGetPower(self)
  330. }
  331. private func setupConstraints() {
  332. NSLayoutConstraint.activate([
  333. // Background
  334. backgroundView.topAnchor.constraint(equalTo: topAnchor),
  335. backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor),
  336. backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor),
  337. backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor),
  338. // User Info Container
  339. timeLabel.topAnchor.constraint(equalTo: topAnchor, constant: 142),
  340. timeLabel.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  341. redBGView.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  342. redBGView.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0),
  343. redBGView.widthAnchor.constraint(equalToConstant: 331),
  344. redBGView.heightAnchor.constraint(equalToConstant: 300),
  345. whiteBGView.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  346. whiteBGView.bottomAnchor.constraint(equalTo: redBGView.bottomAnchor, constant: -90),
  347. whiteBGView.widthAnchor.constraint(equalToConstant: 317),
  348. whiteBGView.heightAnchor.constraint(equalToConstant: 307),
  349. redFontView.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  350. redFontView.bottomAnchor.constraint(equalTo: redBGView.bottomAnchor, constant: 0),
  351. redFontView.widthAnchor.constraint(equalToConstant: 331),
  352. redFontView.heightAnchor.constraint(equalToConstant: 133),
  353. softwareNameLabel.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  354. softwareNameLabel.topAnchor.constraint(equalTo: redFontView.topAnchor, constant: 43),
  355. countDownLabel.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  356. countDownLabel.bottomAnchor.constraint(equalTo: redFontView.bottomAnchor, constant: -20),
  357. getPowerButton.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  358. getPowerButton.bottomAnchor.constraint(equalTo: redFontView.bottomAnchor, constant: -20),
  359. getPowerButton.widthAnchor.constraint(equalToConstant: 221),
  360. getPowerButton.heightAnchor.constraint(equalToConstant: 47),
  361. userInfoBGView.topAnchor.constraint(equalTo: whiteBGView.topAnchor, constant: 14),
  362. userInfoBGView.leadingAnchor.constraint(equalTo: whiteBGView.leadingAnchor, constant: 14),
  363. userInfoBGView.trailingAnchor.constraint(equalTo: whiteBGView.trailingAnchor, constant: -14),
  364. userInfoBGView.heightAnchor.constraint(equalToConstant: 133),
  365. iconBGView.topAnchor.constraint(equalTo: userInfoBGView.topAnchor, constant: 12),
  366. iconBGView.leadingAnchor.constraint(equalTo: userInfoBGView.leadingAnchor, constant: 16),
  367. iconBGView.widthAnchor.constraint(equalToConstant: 54),
  368. iconBGView.heightAnchor.constraint(equalToConstant: 54),
  369. iconImageView.centerXAnchor.constraint(equalTo: iconBGView.centerXAnchor, constant: 0),
  370. iconImageView.centerYAnchor.constraint(equalTo: iconBGView.centerYAnchor, constant: 0),
  371. iconImageView.widthAnchor.constraint(equalToConstant: 46),
  372. iconImageView.heightAnchor.constraint(equalToConstant: 46),
  373. nikNmeRightBGView.trailingAnchor.constraint(equalTo: userInfoBGView.trailingAnchor,constant: -16),
  374. nikNmeRightBGView.topAnchor.constraint(equalTo: userInfoBGView.topAnchor,constant: 14),
  375. nikNmeRightBGView.widthAnchor.constraint(equalToConstant: 130),
  376. nikNmeRightBGView.heightAnchor.constraint(equalToConstant: 24),
  377. nikNmeRightLabel.trailingAnchor.constraint(equalTo: userInfoBGView.trailingAnchor,constant: -16),
  378. nikNmeRightLabel.topAnchor.constraint(equalTo: userInfoBGView.topAnchor,constant: 14),
  379. nikNmeRightLabel.widthAnchor.constraint(equalToConstant: 130),
  380. nikNmeRightLabel.heightAnchor.constraint(equalToConstant: 24),
  381. nikNmeLeftLabel.trailingAnchor.constraint(equalTo: nikNmeRightLabel.leadingAnchor,constant: -5),
  382. nikNmeLeftLabel.centerYAnchor.constraint(equalTo: nikNmeRightLabel.centerYAnchor,constant: 0),
  383. roleIDRightBGView.trailingAnchor.constraint(equalTo: nikNmeRightLabel.trailingAnchor,constant: 0),
  384. roleIDRightBGView.topAnchor.constraint(equalTo: nikNmeRightLabel.bottomAnchor,constant: 3),
  385. roleIDRightBGView.widthAnchor.constraint(equalToConstant: 130),
  386. roleIDRightBGView.heightAnchor.constraint(equalToConstant: 24),
  387. roleIDRightLabel.trailingAnchor.constraint(equalTo: nikNmeRightLabel.trailingAnchor,constant: 0),
  388. roleIDRightLabel.topAnchor.constraint(equalTo: nikNmeRightLabel.bottomAnchor,constant: 3),
  389. roleIDRightLabel.widthAnchor.constraint(equalToConstant: 130),
  390. roleIDRightLabel.heightAnchor.constraint(equalToConstant: 24),
  391. roleIDLeftLabel.trailingAnchor.constraint(equalTo: roleIDRightLabel.leadingAnchor,constant: -5),
  392. roleIDLeftLabel.centerYAnchor.constraint(equalTo: roleIDRightLabel.centerYAnchor,constant: 0),
  393. registrationTimeLabel.topAnchor.constraint(equalTo: iconBGView.bottomAnchor,constant: 15),
  394. registrationTimeLabel.leadingAnchor.constraint(equalTo: iconBGView.leadingAnchor,constant: 0),
  395. loginTimeLabel.topAnchor.constraint(equalTo: registrationTimeLabel.bottomAnchor,constant: 3),
  396. loginTimeLabel.leadingAnchor.constraint(equalTo: iconBGView.leadingAnchor,constant: 0),
  397. todayAnswerLabel.topAnchor.constraint(equalTo: userInfoBGView.bottomAnchor,constant: 12),
  398. todayAnswerLabel.leadingAnchor.constraint(equalTo: userInfoBGView.leadingAnchor,constant: 31),
  399. historyAnswerLabel.topAnchor.constraint(equalTo: userInfoBGView.bottomAnchor,constant: 12),
  400. historyAnswerLabel.trailingAnchor.constraint(equalTo: userInfoBGView.trailingAnchor,constant: -31),
  401. answerLogBGView.topAnchor.constraint(equalTo: todayAnswerLabel.bottomAnchor,constant: 12),
  402. answerLogBGView.leadingAnchor.constraint(equalTo: userInfoBGView.leadingAnchor,constant: 0),
  403. answerLogBGView.trailingAnchor.constraint(equalTo: userInfoBGView.trailingAnchor,constant: 0),
  404. answerLogBGView.heightAnchor.constraint(equalToConstant: 90),
  405. answerLogLabel.centerYAnchor.constraint(equalTo: answerLogBGView.centerYAnchor,constant: 0),
  406. answerLogLabel.leadingAnchor.constraint(equalTo: answerLogBGView.leadingAnchor,constant: 18),
  407. logDivider.topAnchor.constraint(equalTo: answerLogBGView.topAnchor,constant: 8),
  408. logDivider.bottomAnchor.constraint(equalTo: answerLogBGView.bottomAnchor,constant: -8),
  409. logDivider.leadingAnchor.constraint(equalTo: answerLogLabel.trailingAnchor,constant: 13),
  410. logDivider.widthAnchor.constraint(equalToConstant: 1),
  411. answerLogListView.topAnchor.constraint(equalTo: answerLogBGView.topAnchor,constant: 5),
  412. answerLogListView.bottomAnchor.constraint(equalTo: answerLogBGView.bottomAnchor,constant: -5),
  413. answerLogListView.leadingAnchor.constraint(equalTo: logDivider.trailingAnchor,constant: 28),
  414. answerLogListView.trailingAnchor.constraint(equalTo: answerLogBGView.trailingAnchor,constant: -30),
  415. closeButton.topAnchor.constraint(equalTo: whiteBGView.topAnchor,constant: -12),
  416. closeButton.trailingAnchor.constraint(equalTo: whiteBGView.trailingAnchor,constant: 12),
  417. closeButton.heightAnchor.constraint(equalToConstant: 24),
  418. closeButton.widthAnchor.constraint(equalToConstant: 24),
  419. ])
  420. }
  421. // MARK: - Countdown Logic
  422. private func startCountdown() {
  423. countDownLabel.text = "\(secondsRemaining)s"
  424. countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
  425. }
  426. @objc private func updateCountdown() {
  427. secondsRemaining -= 1
  428. countDownLabel.text = "\(secondsRemaining)s"
  429. if secondsRemaining == 0 {
  430. countdownTimer?.invalidate() // Stop the countdown
  431. countdownTimer = nil
  432. showButtons() // Show the buttons once countdown reaches 0
  433. }
  434. }
  435. private func showButtons() {
  436. getPowerButton.isHidden = false // Show the 'Get Power' button
  437. closeButton.isHidden = false // Show the 'Close' button
  438. countDownLabel.isHidden = true
  439. }
  440. // MARK: - Actions
  441. @objc private func closePopup() {
  442. delegate?.powerPopupViewDidClose(self)
  443. removeFromSuperview()
  444. }
  445. private func setOpenTime() {
  446. let formatter = DateFormatter()
  447. formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  448. formatter.locale = Locale(identifier: "zh_CN")
  449. formatter.timeZone = .current
  450. timeLabel.text = formatter.string(from: Date())
  451. }
  452. }
  453. extension PowerPopupView: UITableViewDataSource {
  454. // Return number of rows (the number of records)
  455. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  456. return self.answerLogs.count // ✅ 改这里
  457. }
  458. // Configure each cell to display the record
  459. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  460. let cell = tableView.dequeueReusableCell(withIdentifier: "AnswerLogCell") ?? UITableViewCell(style: .default, reuseIdentifier: "AnswerLogCell")
  461. cell.selectionStyle = .none // Disable selection highlight
  462. // Display the answer log in each row
  463. cell.textLabel?.text = self.answerLogs[indexPath.row] // ✅ 改这里
  464. cell.textLabel?.font = UIFont.systemFont(ofSize: 12)
  465. cell.textLabel?.textColor = UIColor(hexString: "#E28814")
  466. cell.backgroundColor = .clear // Transparent background for each cell
  467. return cell
  468. }
  469. }