From 5f1c22c6a8b3a13f2d77cce7e42ff381ac6050af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=89=E7=A7=8B?= <497055328@qq.com> Date: Thu, 16 Jul 2026 09:06:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E5=86=85=E7=BD=AE=E6=9C=89=E7=BA=BF?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E5=B8=AE=E5=8A=A9=E9=A1=B5=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E9=A3=9E=E4=B9=A6=E5=A4=96=E9=93=BE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 帮助文档改为应用内 WebView 加载本地 HTML,避免依赖外部平台内容。 Co-authored-by: Cursor --- .../WiredCameraTransferHelpDocument.swift | 20 ++ .../Resources/WiredCameraTransferHelp.html | 208 ++++++++++++++++++ .../Setting/AgreementWebViewController.swift | 12 +- ...ravelAlbumCameraImportViewController.swift | 7 +- .../WiredCameraTransferViewController.swift | 10 +- ...WiredCameraTransferHelpDocumentTests.swift | 33 +++ 6 files changed, 284 insertions(+), 6 deletions(-) create mode 100644 suixinkan/Features/TravelAlbum/OTG/Models/WiredCameraTransferHelpDocument.swift create mode 100644 suixinkan/Resources/WiredCameraTransferHelp.html create mode 100644 suixinkanTests/WiredCameraTransferHelpDocumentTests.swift diff --git a/suixinkan/Features/TravelAlbum/OTG/Models/WiredCameraTransferHelpDocument.swift b/suixinkan/Features/TravelAlbum/OTG/Models/WiredCameraTransferHelpDocument.swift new file mode 100644 index 0000000..c364752 --- /dev/null +++ b/suixinkan/Features/TravelAlbum/OTG/Models/WiredCameraTransferHelpDocument.swift @@ -0,0 +1,20 @@ +// +// WiredCameraTransferHelpDocument.swift +// suixinkan +// + +import Foundation + +/// 有线相机传输帮助文档(App 内置 HTML),供传输页与历史导入页打开。 +enum WiredCameraTransferHelpDocument { + /// 导航栏标题。 + static let pageTitle = "帮助文档" + + /// Bundle 内资源名(不含扩展名)。 + static let resourceName = "WiredCameraTransferHelp" + + /// 返回内置帮助页文件 URL;资源缺失时返回 `nil`。 + static func bundledURL(in bundle: Bundle = .main) -> URL? { + bundle.url(forResource: resourceName, withExtension: "html") + } +} diff --git a/suixinkan/Resources/WiredCameraTransferHelp.html b/suixinkan/Resources/WiredCameraTransferHelp.html new file mode 100644 index 0000000..99ac32a --- /dev/null +++ b/suixinkan/Resources/WiredCameraTransferHelp.html @@ -0,0 +1,208 @@ + + + + + + 有线相机传输帮助 + + + +

有线相机传输帮助

+

本说明适用于「随心瞰商家版」iPhone 端旅拍相册的有线相机传输功能,帮助你快速连接相机、导入照片并上传到相册。

+ +

功能简介

+

通过 USB 线将相机连接到 iPhone 后,可在当前旅拍相册中:

+ +
+ 支持品牌 +

当前支持佳能、索尼、尼康等主流相机(具体机型以实际识别结果为准)。连接成功后,状态区会显示相机名称。

+
+ +

使用前准备

+
    +
  1. 使用 iPhone(仅竖屏使用),并确保手机有足够剩余存储空间。
  2. +
  3. 准备原装或质量可靠的 USB 数据线,以及必要的转接头(Lightning / USB-C 按手机接口选择)。
  4. +
  5. 相机开机,并确认电量充足;建议使用相机原厂供电或满电电池。
  6. +
  7. 如需上传,请保持网络畅通(Wi‑Fi 或蜂窝数据)。
  8. +
+ +

连接相机

+
    +
  1. 打开旅拍相册,进入有线传输页面。
  2. +
  3. 用数据线将相机连接到 iPhone。
  4. +
  5. 若系统弹出「是否允许访问相机 / USB 配件」等授权提示,请选择允许
  6. +
  7. 页面状态变为「xxx 已连接」即表示连接成功;若长时间停留在搜索或未连接,可点击重新连接,或拔插数据线后重试。
  8. +
+
+ 注意 +

连接过程中请勿频繁拔插数据线,也不要同时打开电脑读卡软件或其他占用相机 USB 的应用。

+
+ +

传输模式

+
+

边拍边传

+

相机处于可实时传输状态时,新拍照片会自动写入当前相册;若开启对应上传逻辑,则会继续上传到云端。

+
+
+

拍后传输

+

照片会先进入 App 本地列表,不会自动上传。你可使用「批量上传」或「指定上传」按需上传。

+
+

可在页面设置区切换传输模式;切换后对后续新传入的照片生效。

+ +

页面常用操作

+ +

列表支持「全部 / 已上传 / 失败」筛选,失败项可按提示重试。

+ +

索尼相机说明

+

索尼相机在不同 USB 模式下,行为和列表内容会有差异:

+ +
+ 切换提示 +

多数索尼机身路径类似:菜单 → 网络/连接 → USB 连接 → 选择 MTP。具体名称因机型而异,请以相机说明书为准。

+
+ +

常见问题

+

1. 一直显示「未连接 USB」或「正在搜索」?

+ + +

2. 已连接但看不到新拍照片?

+ + +

3. 上传失败怎么办?

+ + +

4. 历史导入打开后没有照片?

+ + +

5. 连接中提示没有权限?

+ + +
+ + + diff --git a/suixinkan/UI/Setting/AgreementWebViewController.swift b/suixinkan/UI/Setting/AgreementWebViewController.swift index 1ac7dea..03c0dd6 100644 --- a/suixinkan/UI/Setting/AgreementWebViewController.swift +++ b/suixinkan/UI/Setting/AgreementWebViewController.swift @@ -7,7 +7,7 @@ import SnapKit import UIKit import WebKit -/// 协议 H5 页面,使用应用内 WebView 展示关于我们、用户协议和隐私政策。 +/// 应用内 WebView 页面,用于展示协议 H5、内置帮助 HTML 等文档内容。 final class AgreementWebViewController: BaseViewController { private let pageTitle: String private let url: URL @@ -37,7 +37,15 @@ final class AgreementWebViewController: BaseViewController { view.addSubview(loadingIndicator) loadingIndicator.hidesWhenStopped = true loadingIndicator.startAnimating() - webView.load(URLRequest(url: url)) + loadContent() + } + + private func loadContent() { + if url.isFileURL { + webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) + } else { + webView.load(URLRequest(url: url)) + } } override func setupConstraints() { diff --git a/suixinkan/UI/TravelAlbum/TravelAlbumCameraImportViewController.swift b/suixinkan/UI/TravelAlbum/TravelAlbumCameraImportViewController.swift index 7225c5e..0343273 100644 --- a/suixinkan/UI/TravelAlbum/TravelAlbumCameraImportViewController.swift +++ b/suixinkan/UI/TravelAlbum/TravelAlbumCameraImportViewController.swift @@ -293,8 +293,11 @@ final class TravelAlbumCameraImportViewController: UIViewController { } @objc private func helpTapped() { - guard let url = URL(string: "https://sharesky.feishu.cn/wiki/CaAhwl3Gnin4Kqk0BVocK3SGnab?from=from_copylink") else { return } - UIApplication.shared.open(url) + guard let url = WiredCameraTransferHelpDocument.bundledURL() else { return } + navigationController?.pushViewController( + AgreementWebViewController(title: WiredCameraTransferHelpDocument.pageTitle, url: url), + animated: true + ) } } diff --git a/suixinkan/UI/TravelAlbum/WiredCameraTransferViewController.swift b/suixinkan/UI/TravelAlbum/WiredCameraTransferViewController.swift index ac9ed3e..e6c2f68 100644 --- a/suixinkan/UI/TravelAlbum/WiredCameraTransferViewController.swift +++ b/suixinkan/UI/TravelAlbum/WiredCameraTransferViewController.swift @@ -777,8 +777,14 @@ final class WiredCameraTransferViewController: BaseViewController { } @objc private func helpTapped() { - guard let url = URL(string: "https://sharesky.feishu.cn/wiki/CaAhwl3Gnin4Kqk0BVocK3SGnab?from=from_copylink") else { return } - UIApplication.shared.open(url) + guard let url = WiredCameraTransferHelpDocument.bundledURL() else { + showToast("帮助文档暂不可用") + return + } + navigationController?.pushViewController( + AgreementWebViewController(title: WiredCameraTransferHelpDocument.pageTitle, url: url), + animated: true + ) } private func presentPhotoPreview(_ item: TravelAlbumOTGPhotoItem) { diff --git a/suixinkanTests/WiredCameraTransferHelpDocumentTests.swift b/suixinkanTests/WiredCameraTransferHelpDocumentTests.swift new file mode 100644 index 0000000..70abd23 --- /dev/null +++ b/suixinkanTests/WiredCameraTransferHelpDocumentTests.swift @@ -0,0 +1,33 @@ +// +// WiredCameraTransferHelpDocumentTests.swift +// suixinkanTests +// + +import XCTest +@testable import suixinkan + +/// 有线相机传输内置帮助文档资源测试。 +final class WiredCameraTransferHelpDocumentTests: XCTestCase { + func testBundledHelpHTMLExists() { + let url = WiredCameraTransferHelpDocument.bundledURL() + XCTAssertNotNil(url) + XCTAssertEqual(url?.pathExtension, "html") + XCTAssertTrue(url?.lastPathComponent.hasPrefix(WiredCameraTransferHelpDocument.resourceName) == true) + } + + func testBundledHelpHTMLContainsCoreSections() throws { + let url = try XCTUnwrap(WiredCameraTransferHelpDocument.bundledURL()) + let html = try String(contentsOf: url, encoding: .utf8) + XCTAssertTrue(html.contains("有线相机传输帮助")) + XCTAssertTrue(html.contains("连接相机")) + XCTAssertTrue(html.contains("边拍边传")) + XCTAssertTrue(html.contains("拍后传输")) + XCTAssertTrue(html.contains("历史导入")) + XCTAssertTrue(html.contains("索尼相机说明")) + XCTAssertTrue(html.contains("常见问题")) + } + + func testPageTitle() { + XCTAssertEqual(WiredCameraTransferHelpDocument.pageTitle, "帮助文档") + } +}