From 57ba10399668bc436c3e155c6e67899465c13fdd Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Fri, 1 Aug 2025 15:53:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7ID?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=BB=84=E4=BB=B6=E5=92=8C=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建UserIDDisplay组件,支持ID显示和复制功能,增强用户交互体验。 - 更新MeView中的头像样式,调整尺寸和边框,提升视觉效果。 - 修改OptimizedDynamicCardView以使用新组件,确保一致性和复用性。 - 新增icon_copy图标资源,支持复制功能的视觉反馈。 - 更新AppSettingView中的布局,优化用户界面体验。 --- issues/MeView头像和ID显示优化.md | 54 ++++++++++++++ yana/Assets.xcassets/Common/Contents.json | 6 ++ .../Common/icon_copy.imageset/Contents.json | 21 ++++++ .../Common/icon_copy.imageset/复制@3x.png | Bin 0 -> 646 bytes yana/Views/AppSettingView.swift | 35 +++------ .../Components/OptimizedDynamicCardView.swift | 9 ++- yana/Views/Components/UserIDDisplay.swift | 68 ++++++++++++++++++ yana/Views/MeView.swift | 8 +-- 8 files changed, 165 insertions(+), 36 deletions(-) create mode 100644 issues/MeView头像和ID显示优化.md create mode 100644 yana/Assets.xcassets/Common/Contents.json create mode 100644 yana/Assets.xcassets/Common/icon_copy.imageset/Contents.json create mode 100644 yana/Assets.xcassets/Common/icon_copy.imageset/复制@3x.png create mode 100644 yana/Views/Components/UserIDDisplay.swift diff --git a/issues/MeView头像和ID显示优化.md b/issues/MeView头像和ID显示优化.md new file mode 100644 index 0000000..dd4f755 --- /dev/null +++ b/issues/MeView头像和ID显示优化.md @@ -0,0 +1,54 @@ +# MeView头像和ID显示优化 + +## 需求分析 +1. 头像尺寸从80x80改为130x130 +2. 头像外层添加白色边框(2px) +3. "ID: xxxx"中的数字不使用逗号分割 +4. 在ID右侧添加"icon_icon"图片(14x14) +5. 点击整体复制ID数字 +6. 抽象为独立组件,便于项目内复用 + +## 实施计划 + +### 文件结构 +- ✅ 创建:`yana/Views/Components/UserIDDisplay.swift` +- ✅ 修改:`yana/Views/MeView.swift` +- ✅ 修改:`yana/Views/Components/OptimizedDynamicCardView.swift` + +### 核心组件设计 +1. **UserIDDisplay组件**: + - 参数:uid (Int), fontSize (CGFloat), textColor (Color) + - 功能:显示"ID: xxx",右侧复制图标,点击复制ID + - 样式:数字不使用逗号分割 + - 反馈:点击后显示"已复制"提示 + +2. **头像样式调整**: + - 尺寸:130x130 + - 边框:白色2px + +### 实施步骤 +1. ✅ 创建UserIDDisplay组件 +2. ✅ 修改MeView中的头像和ID显示 +3. ✅ 更新OptimizedDynamicCardView使用新组件 + +### 技术要点 +- 使用UIPasteboard进行复制功能 +- 使用现有的icon_copy图片资源 +- 添加复制成功反馈动画 +- 保持与现有代码风格一致 + +## 完成状态 +- [x] UserIDDisplay组件创建 +- [x] MeView头像样式更新 +- [x] MeView ID显示组件化 +- [x] OptimizedDynamicCardView组件更新 +- [x] 复制功能实现 +- [x] 视觉反馈实现 + +## 测试要点 +1. 头像尺寸和边框显示正确 +2. ID显示格式正确(无逗号分割) +3. 复制图标显示正确 +4. 点击复制功能正常 +5. 复制成功反馈显示 +6. 组件在不同场景下复用正常 \ No newline at end of file diff --git a/yana/Assets.xcassets/Common/Contents.json b/yana/Assets.xcassets/Common/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/yana/Assets.xcassets/Common/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/yana/Assets.xcassets/Common/icon_copy.imageset/Contents.json b/yana/Assets.xcassets/Common/icon_copy.imageset/Contents.json new file mode 100644 index 0000000..98c8800 --- /dev/null +++ b/yana/Assets.xcassets/Common/icon_copy.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "复制@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/yana/Assets.xcassets/Common/icon_copy.imageset/复制@3x.png b/yana/Assets.xcassets/Common/icon_copy.imageset/复制@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..df5b1384d6a96de37c068e8507f574d7660969cd GIT binary patch literal 646 zcmV;10(t$3P)Px%KuJVFR9Hvtn9oZaK@`WoFKUbswgek5{SU;yz)Q`kLeWi^vM1Y9PxWLe*q*8< zD@c3Ni=J9fOIfo9p*_W3{0qeYpqEAwL%^8CJQ+0-f9xi+8C`^#+rpbSpZ(6vci&sW zBN_BaIH5sR@03ABR zGlZV%G65L?PXP4FEk-qfOAHin8lSeT7ysqvUqlCjIy*Z9y~Tqc1iTKD{N@}6ex;1$ zn@lECkUmq^4K&sP3b#Z6m`A)2LgQs zxDU)LwQ6P7w(YXaB97xEz ztIWtY-5`e8lxe>7b%V%2g&Xw66N?~v4^WN4pDc6Yo8L{14Ak$EY0yqg)z9W+>`!lf ztI}H0rW)ciM??#v1|`B;wQ@WYrYP~VA!TRO^}KOH?5fNIvjd`HCl{z0Lxg93#;y$X zq6I1cR9QH;ekzrL3RSMRB4nJ`rgEe1S9~Z16-=Tf=`S8WKSg7h07Hh8nah6VoN`bZ zFqznU2aTddY1=N}rBD=2UntNh+UQWAx830We@ui16|fKatEVeanH%11tOo5?!JG57 gqFPba3aHL^2E<9UI`)KT6951J07*qoM6N<$g2wqKVgLXD literal 0 HcmV?d00001 diff --git a/yana/Views/AppSettingView.swift b/yana/Views/AppSettingView.swift index de5be64..04fbc90 100644 --- a/yana/Views/AppSettingView.swift +++ b/yana/Views/AppSettingView.swift @@ -57,12 +57,8 @@ struct AppSettingView: View { WithPerceptionTracking { let baseView = GeometryReader { geometry in ZStack { - // 背景图片 - Image("bg") - .resizable() - .aspectRatio(contentMode: .fill) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .clipped() + // 背景颜色 + Color(hex: 0x0C0527) .ignoresSafeArea(.all) VStack(spacing: 0) { @@ -248,7 +244,7 @@ struct AppSettingView: View { .aspectRatio(contentMode: .fill) .foregroundColor(.gray) } - .frame(width: 100, height: 100) + .frame(width: 120, height: 120) .clipShape(Circle()) // 相机图标覆盖 @@ -266,7 +262,7 @@ struct AppSettingView: View { ) } } - .frame(width: 100, height: 100) + .frame(width: 120, height: 120) } } } @@ -280,7 +276,6 @@ struct AppSettingView: View { VStack(spacing: 0) { // 昵称设置 SettingRow( - icon: "person", title: LocalizedString("appSetting.nickname", comment: "昵称"), subtitle: store.userInfo?.nick ?? LocalizedString("app_settings.not_set", comment: "未设置"), action: { @@ -297,7 +292,6 @@ struct AppSettingView: View { WithPerceptionTracking { VStack(spacing: 0) { SettingRow( - icon: "hand.raised", title: LocalizedString("appSetting.personalInfoPermissions", comment: "个人信息与权限"), subtitle: "", action: { store.send(.personalInfoPermissionsTapped) } @@ -305,10 +299,9 @@ struct AppSettingView: View { Divider() .background(Color.white.opacity(0.2)) - .padding(.leading, 50) + .padding(.leading, 16) SettingRow( - icon: "questionmark.circle", title: LocalizedString("appSetting.help", comment: "帮助"), subtitle: "", action: { store.send(.helpTapped) } @@ -316,10 +309,9 @@ struct AppSettingView: View { Divider() .background(Color.white.opacity(0.2)) - .padding(.leading, 50) + .padding(.leading, 16) SettingRow( - icon: "trash", title: LocalizedString("appSetting.clearCache", comment: "清除缓存"), subtitle: "", action: { store.send(.clearCacheTapped) } @@ -327,10 +319,9 @@ struct AppSettingView: View { Divider() .background(Color.white.opacity(0.2)) - .padding(.leading, 50) + .padding(.leading, 16) SettingRow( - icon: "arrow.clockwise", title: LocalizedString("appSetting.checkUpdates", comment: "检查更新"), subtitle: "", action: { store.send(.checkUpdatesTapped) } @@ -338,10 +329,9 @@ struct AppSettingView: View { Divider() .background(Color.white.opacity(0.2)) - .padding(.leading, 50) + .padding(.leading, 16) SettingRow( - icon: "person.crop.circle.badge.minus", title: LocalizedString("appSetting.deactivateAccount", comment: "注销账号"), subtitle: "", action: { store.send(.deactivateAccountTapped) } @@ -349,10 +339,9 @@ struct AppSettingView: View { Divider() .background(Color.white.opacity(0.2)) - .padding(.leading, 50) + .padding(.leading, 16) SettingRow( - icon: "info.circle", title: LocalizedString("appSetting.aboutUs", comment: "关于我们"), subtitle: "", action: { store.send(.aboutUsTapped) } @@ -385,7 +374,6 @@ struct AppSettingView: View { // MARK: - 设置行组件 struct SettingRow: View { - let icon: String let title: String let subtitle: String let action: (() -> Void)? @@ -395,11 +383,6 @@ struct SettingRow: View { action?() }) { HStack(spacing: 16) { - Image(systemName: icon) - .font(.system(size: 18)) - .foregroundColor(.white) - .frame(width: 24) - HStack { Text(title) .font(.system(size: 16)) diff --git a/yana/Views/Components/OptimizedDynamicCardView.swift b/yana/Views/Components/OptimizedDynamicCardView.swift index 3ec8fbd..66139b9 100644 --- a/yana/Views/Components/OptimizedDynamicCardView.swift +++ b/yana/Views/Components/OptimizedDynamicCardView.swift @@ -43,7 +43,7 @@ struct OptimizedDynamicCardView: View { } // 内容层 - VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 10) { // 用户信息 HStack(alignment: .top) { // 头像 @@ -69,9 +69,7 @@ struct OptimizedDynamicCardView: View { .font(.system(size: 16, weight: .medium)) .foregroundColor(.white) .allowsHitTesting(false) // 不拦截点击事件 - Text("ID: \(moment.uid)") - .font(.system(size: 12)) - .foregroundColor(.white.opacity(0.6)) + UserIDDisplay(uid: moment.uid, fontSize: 12, textColor: .white.opacity(0.6)) .allowsHitTesting(false) // 不拦截点击事件 } Spacer() @@ -102,7 +100,8 @@ struct OptimizedDynamicCardView: View { let urls = images.map { $0.resUrl ?? "" } onImageTap(urls, tappedIndex) } - .padding(.bottom, images.count == 2 ? 46 : 0) // 两张图片时增加底部间距 + .padding(.leading, 40 + 8) + .padding(.bottom, images.count == 2 ? 30 : 0) // 两张图片时增加底部间距 .allowsHitTesting(true) // 图片网格需要响应点击事件 } diff --git a/yana/Views/Components/UserIDDisplay.swift b/yana/Views/Components/UserIDDisplay.swift new file mode 100644 index 0000000..a386fbe --- /dev/null +++ b/yana/Views/Components/UserIDDisplay.swift @@ -0,0 +1,68 @@ +import SwiftUI + +struct UserIDDisplay: View { + let uid: Int + let fontSize: CGFloat + let textColor: Color + + @State private var showCopiedFeedback: Bool = false + + init(uid: Int, fontSize: CGFloat = 14, textColor: Color = .white.opacity(0.7)) { + self.uid = uid + self.fontSize = fontSize + self.textColor = textColor + } + + var body: some View { + HStack(spacing: 4) { + Text("ID: \(String(uid))") + .font(.system(size: fontSize)) + .foregroundColor(textColor) + + Image("icon_copy") + .resizable() + .frame(width: 14, height: 14) + .foregroundColor(textColor) + } + .onTapGesture { + copyToClipboard() + } + .overlay( + Group { + if showCopiedFeedback { + Text("已复制") + .font(.system(size: 12)) + .foregroundColor(.white) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background(Color.black.opacity(0.7)) + .cornerRadius(4) + .offset(y: -30) + .transition(.opacity) + } + } + ) + } + + private func copyToClipboard() { + UIPasteboard.general.string = String(uid) + + withAnimation(.easeInOut(duration: 0.2)) { + showCopiedFeedback = true + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + withAnimation(.easeInOut(duration: 0.2)) { + showCopiedFeedback = false + } + } + } +} + +#Preview { + VStack(spacing: 20) { + UserIDDisplay(uid: 123456789) + UserIDDisplay(uid: 987654321, fontSize: 16, textColor: .black) + } + .padding() +} \ No newline at end of file diff --git a/yana/Views/MeView.swift b/yana/Views/MeView.swift index 8edfe11..f21a0c7 100644 --- a/yana/Views/MeView.swift +++ b/yana/Views/MeView.swift @@ -98,11 +98,11 @@ struct MeView: View { .aspectRatio(contentMode: .fill) .foregroundColor(.gray) } - .frame(width: 80, height: 80) + .frame(width: 130, height: 130) .clipShape(Circle()) .overlay( Circle() - .stroke(Color.white.opacity(0.3), lineWidth: 2) + .stroke(Color.white, lineWidth: 2) ) // 用户昵称 @@ -111,9 +111,7 @@ struct MeView: View { .foregroundColor(.white) // 用户ID - Text("ID: \(store.userInfo?.uid ?? 0)") - .font(.system(size: 14)) - .foregroundColor(.white.opacity(0.7)) + UserIDDisplay(uid: store.userInfo?.uid ?? 0) } .padding(.horizontal, 32) }