用内置有线传输帮助页替换飞书外链。

帮助文档改为应用内 WebView 加载本地 HTML,避免依赖外部平台内容。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-16 09:06:16 +08:00
parent ce6de76055
commit 5f1c22c6a8
6 changed files with 284 additions and 6 deletions

View File

@ -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")
}
}

View File

@ -0,0 +1,208 @@
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>有线相机传输帮助</title>
<style>
:root {
--primary: #0073FF;
--text: #1F2329;
--secondary: #646A73;
--border: #E5E6EB;
--bg: #FFFFFF;
--card: #F7F8FA;
--tip: #EFF6FF;
--warn: #FFF7E8;
--warn-text: #AD6800;
}
* { box-sizing: border-box; }
body {
margin: 0;
padding: 20px 16px 40px;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
font-size: 15px;
line-height: 1.65;
color: var(--text);
background: var(--bg);
-webkit-text-size-adjust: 100%;
}
h1 {
margin: 0 0 8px;
font-size: 22px;
font-weight: 600;
line-height: 1.35;
}
.lead {
margin: 0 0 24px;
color: var(--secondary);
font-size: 14px;
}
h2 {
margin: 28px 0 12px;
padding-left: 10px;
border-left: 3px solid var(--primary);
font-size: 17px;
font-weight: 600;
line-height: 1.4;
}
h3 {
margin: 18px 0 8px;
font-size: 15px;
font-weight: 600;
}
p { margin: 0 0 12px; }
ol, ul {
margin: 0 0 12px;
padding-left: 1.35em;
}
li { margin: 0 0 8px; }
li:last-child { margin-bottom: 0; }
.card {
margin: 12px 0;
padding: 14px 14px 12px;
background: var(--card);
border-radius: 10px;
}
.card p:last-child,
.card ul:last-child,
.card ol:last-child { margin-bottom: 0; }
.tip {
background: var(--tip);
border: 1px solid #D6E7FF;
}
.warn {
background: var(--warn);
border: 1px solid #FFE4BA;
color: var(--warn-text);
}
.label {
display: inline-block;
margin-bottom: 6px;
color: var(--primary);
font-size: 13px;
font-weight: 600;
}
.divider {
margin: 28px 0 0;
border: 0;
border-top: 1px solid var(--border);
}
.footer {
margin-top: 20px;
color: var(--secondary);
font-size: 12px;
}
strong { font-weight: 600; }
</style>
</head>
<body>
<h1>有线相机传输帮助</h1>
<p class="lead">本说明适用于「随心瞰商家版」iPhone 端旅拍相册的有线相机传输功能,帮助你快速连接相机、导入照片并上传到相册。</p>
<h2>功能简介</h2>
<p>通过 USB 线将相机连接到 iPhone 后,可在当前旅拍相册中:</p>
<ul>
<li>边拍边传:拍摄后自动传入 App并可按设置自动上传</li>
<li>拍后传输:先把照片传入 App再手动选择上传</li>
<li>历史导入:从相机内已有照片中挑选导入</li>
<li>相册导入:从手机系统相册导入照片</li>
</ul>
<div class="card tip">
<span class="label">支持品牌</span>
<p>当前支持佳能、索尼、尼康等主流相机(具体机型以实际识别结果为准)。连接成功后,状态区会显示相机名称。</p>
</div>
<h2>使用前准备</h2>
<ol>
<li>使用 <strong>iPhone</strong>(仅竖屏使用),并确保手机有足够剩余存储空间。</li>
<li>准备原装或质量可靠的 USB 数据线以及必要的转接头Lightning / USB-C 按手机接口选择)。</li>
<li>相机开机,并确认电量充足;建议使用相机原厂供电或满电电池。</li>
<li>如需上传请保持网络畅通WiFi 或蜂窝数据)。</li>
</ol>
<h2>连接相机</h2>
<ol>
<li>打开旅拍相册,进入<strong>有线传输</strong>页面。</li>
<li>用数据线将相机连接到 iPhone。</li>
<li>若系统弹出「是否允许访问相机 / USB 配件」等授权提示,请选择<strong>允许</strong></li>
<li>页面状态变为「xxx 已连接」即表示连接成功;若长时间停留在搜索或未连接,可点击<strong>重新连接</strong>,或拔插数据线后重试。</li>
</ol>
<div class="card warn">
<span class="label">注意</span>
<p>连接过程中请勿频繁拔插数据线,也不要同时打开电脑读卡软件或其他占用相机 USB 的应用。</p>
</div>
<h2>传输模式</h2>
<div class="card">
<h3>边拍边传</h3>
<p>相机处于可实时传输状态时,新拍照片会自动写入当前相册;若开启对应上传逻辑,则会继续上传到云端。</p>
</div>
<div class="card">
<h3>拍后传输</h3>
<p>照片会先进入 App 本地列表,不会自动上传。你可使用「批量上传」或「指定上传」按需上传。</p>
</div>
<p>可在页面设置区切换传输模式;切换后对后续新传入的照片生效。</p>
<h2>页面常用操作</h2>
<ul>
<li><strong>重新连接 / 刷新</strong>:未连接时用于重新搜索;已连接时用于刷新当前已传入列表。</li>
<li><strong>历史导入</strong>:相机连接成功后可用,从相机存储中挑选历史照片导入当前相册。</li>
<li><strong>批量上传</strong>:进入多选模式,勾选照片后上传选中项。</li>
<li><strong>指定上传</strong>:可一键上传「所有未上传照片」或「今日拍摄照片」。</li>
<li><strong>相册导入</strong>:从手机系统相册选择图片导入当前旅拍相册。</li>
<li><strong>时间轴</strong>:左侧时间导航可快速定位到某一时间段的照片。</li>
</ul>
<p>列表支持「全部 / 已上传 / 失败」筛选,失败项可按提示重试。</p>
<h2>索尼相机说明</h2>
<p>索尼相机在不同 USB 模式下,行为和列表内容会有差异:</p>
<ul>
<li><strong>边拍边传</strong>:通常需要进入相机支持的远程/PC Remote 类连接模式,以便拍摄后及时传到手机。</li>
<li><strong>历史导入</strong>:若提示无照片或列表为空,请将相机 USB 连接模式切换为 <strong>MTP</strong>(或「仅传照片 / Mass Storage / MTP」等类似选项以机身为准然后重新插拔连接并再次进入历史导入。</li>
</ul>
<div class="card tip">
<span class="label">切换提示</span>
<p>多数索尼机身路径类似:菜单 → 网络/连接 → USB 连接 → 选择 MTP。具体名称因机型而异请以相机说明书为准。</p>
</div>
<h2>常见问题</h2>
<h3>1. 一直显示「未连接 USB」或「正在搜索」</h3>
<ul>
<li>检查数据线与转接头是否支持数据传输(仅充电线无法识别相机)。</li>
<li>确认相机已开机,并处于可被电脑/手机识别的 USB 模式。</li>
<li>尝试拔掉重插,或点击「重新连接」。</li>
<li>重启相机与 App 后再试。</li>
</ul>
<h3>2. 已连接但看不到新拍照片?</h3>
<ul>
<li>确认当前传输出入的是正确的旅拍相册。</li>
<li>边拍边传模式下,请保持本页在前台,并避免同时进行历史导入。</li>
<li>索尼机型请核对 USB/远程模式是否匹配当前用途。</li>
</ul>
<h3>3. 上传失败怎么办?</h3>
<ul>
<li>检查网络是否稳定,必要时切换 WiFi。</li>
<li>确认手机存储空间充足。</li>
<li>在「失败」Tab 中查看失败照片,并重试上传。</li>
</ul>
<h3>4. 历史导入打开后没有照片?</h3>
<ul>
<li>相机存储卡中确实要有可识别的照片文件。</li>
<li>索尼请切换到 MTP 模式后重试。</li>
<li>关闭历史导入页,回到传输页重新连接后再进入。</li>
</ul>
<h3>5. 连接中提示没有权限?</h3>
<ul>
<li>请在系统弹窗中允许访问相机或相关配件。</li>
<li>若曾点过拒绝,可到 iPhone「设置」中为「随心瞰商家版」重新开启相关权限或重新插拔设备触发授权。</li>
</ul>
<hr class="divider" />
<p class="footer">随心瞰商家版 · 有线相机传输帮助。若上述步骤仍无法解决,请保留机型、连接线类型与报错截图,联系客服处理。</p>
</body>
</html>

View File

@ -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,8 +37,16 @@ final class AgreementWebViewController: BaseViewController {
view.addSubview(loadingIndicator)
loadingIndicator.hidesWhenStopped = true
loadingIndicator.startAnimating()
loadContent()
}
private func loadContent() {
if url.isFileURL {
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
} else {
webView.load(URLRequest(url: url))
}
}
override func setupConstraints() {
webView.snp.makeConstraints { make in

View File

@ -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
)
}
}

View File

@ -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) {

View File

@ -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, "帮助文档")
}
}