// // FormatLogViewController.swift // Note // // Created by fish on 2026/7/12. // import UIKit class FormatLogViewController: UIViewController { private var textView: UITextView! private var formatButton: UIButton! private var doneButton: UIBarButtonItem! private var pasteButton: UIBarButtonItem! private var resetButton: UIBarButtonItem! private var isFormatted = false private var rightBarButtonMode: RightBarButtonMode = .paste private enum RightBarButtonMode { case paste case reset } override func viewDidLoad() { super.viewDidLoad() title = "格式化日志" navigationItem.largeTitleDisplayMode = .never view.backgroundColor = .systemGroupedBackground setupUI() } private func setupUI() { textView = UITextView() textView.translatesAutoresizingMaskIntoConstraints = false textView.font = UIFont.systemFont(ofSize: 16) textView.backgroundColor = .systemBackground textView.layer.cornerRadius = 12 textView.layer.borderWidth = 0.5 textView.layer.borderColor = UIColor.separator.cgColor textView.textContainerInset = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12) textView.delegate = self view.addSubview(textView) doneButton = UIBarButtonItem(title: "完成", style: .prominent, target: self, action: #selector(didTapDoneButton)) pasteButton = UIBarButtonItem(title: "粘贴文案", style: .plain, target: self, action: #selector(didTapPasteButton)) resetButton = UIBarButtonItem(title: "重置", style: .plain, target: self, action: #selector(didTapResetButton)) updateRightBarButtonItem() formatButton = UIButton(type: .system) formatButton.translatesAutoresizingMaskIntoConstraints = false formatButton.setTitle("格式化", for: .normal) formatButton.titleLabel?.font = UIFont.systemFont(ofSize: 18, weight: .semibold) formatButton.backgroundColor = .systemBlue formatButton.setTitleColor(.white, for: .normal) formatButton.layer.cornerRadius = 12 formatButton.addTarget(self, action: #selector(didTapFormatButton), for: .touchUpInside) view.addSubview(formatButton) NSLayoutConstraint.activate([ textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16), textView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), textView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), textView.bottomAnchor.constraint(equalTo: formatButton.topAnchor, constant: -16), formatButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), formatButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), formatButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16), formatButton.heightAnchor.constraint(equalToConstant: 52) ]) } @objc private func didTapDoneButton() { textView.resignFirstResponder() } @objc private func didTapFormatButton() { guard !trimmedText().isEmpty else { showEmptyAlert() return } if isFormatted { saveToFiles() } else { textView.text = formatLog(textView.text) isFormatted = true formatButton.setTitle("保存到 iCloud", for: .normal) rightBarButtonMode = .reset updateRightBarButtonItem() } } @objc private func didTapPasteButton() { if let string = UIPasteboard.general.string { textView.text = string } } private func trimmedText() -> String { return textView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" } private func showEmptyAlert() { let alert = UIAlertController(title: "提示", message: "请输入内容后再进行格式化", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) } @objc private func didTapResetButton() { textView.text = "" isFormatted = false formatButton.setTitle("格式化", for: .normal) rightBarButtonMode = .paste updateRightBarButtonItem() } private func updateRightBarButtonItem() { if textView.isFirstResponder { navigationItem.rightBarButtonItem = doneButton } else { switch rightBarButtonMode { case .paste: navigationItem.rightBarButtonItem = pasteButton case .reset: navigationItem.rightBarButtonItem = resetButton } } } private func saveToFiles() { let fileName = generateFileName() let fileURL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName) do { try textView.text.write(to: fileURL, atomically: true, encoding: .utf8) let documentPicker = UIDocumentPickerViewController(forExporting: [fileURL], asCopy: true) documentPicker.delegate = self present(documentPicker, animated: true) } catch { print("Failed to write file: \(error)") } } private func generateFileName() -> String { let text = textView.text ?? "" let firstLine = text.components(separatedBy: .newlines).first ?? "" let trimmed = firstLine.trimmingCharacters(in: .whitespaces) let withoutHash = trimmed.replacingOccurrences(of: "^#\\s*", with: "", options: .regularExpression) let cleanName = withoutHash.trimmingCharacters(in: .whitespaces) if cleanName.isEmpty { return "formatted_log_\(Int(Date().timeIntervalSince1970)).md" } return cleanName + ".md" } private func formatLog(_ text: String) -> String { var content = text content = content.replacingOccurrences(of: "# ", with: "") content = content.replacingOccurrences(of: "#", with: "") content = content.replacingOccurrences(of: ";", with: "。") content = content.replacingOccurrences(of: ";", with: "。") content = content.replacingOccurrences(of: ".", with: "。") content = content.replacingOccurrences(of: "(", with: "(") content = content.replacingOccurrences(of: ")", with: ")") content = content.replacingOccurrences(of: "?", with: "?") content = content.replacingOccurrences(of: ",", with: ",") content = content.replacingOccurrences(of: ":", with: ":") content = content.replacingOccurrences(of: "日星期", with: "日 星期") content = "# " + content content = content.replacingOccurrences(of: "一、生活方面", with: "## 一、生活方面") content = content.replacingOccurrences(of: "二、交易方面", with: "## 二、交易方面") content = content.replacingOccurrences(of: "三、工作方面", with: "## 三、工作方面") return content } } extension FormatLogViewController: UITextViewDelegate { func textViewDidBeginEditing(_ textView: UITextView) { updateRightBarButtonItem() } func textViewDidEndEditing(_ textView: UITextView) { updateRightBarButtonItem() } } extension FormatLogViewController: UIDocumentPickerDelegate { func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { // File saved to selected location } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { // User cancelled } }