394 lines
15 KiB
Swift
394 lines
15 KiB
Swift
//
|
|
// MemberInfoVC.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import UIKit
|
|
import ObjectMapper
|
|
import RxSwift
|
|
|
|
final class MemberInfoVC: BaseViewController {
|
|
|
|
private var rootView: MemberInfoView!
|
|
private var members: [GroupMemberModel]
|
|
private var selectedUserId: String
|
|
private var groupModel: GroupModel?
|
|
private var isLoadingRelations = false
|
|
|
|
init(members: [GroupMemberModel], selectedUserId: String, groupModel: GroupModel?) {
|
|
self.members = members
|
|
self.selectedUserId = selectedUserId
|
|
self.groupModel = groupModel
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
convenience init(userInfo: [String: Any]) {
|
|
let rawMembers = userInfo["members"]
|
|
let membersJson: [[String: Any]]
|
|
if let arr = rawMembers as? [[String: Any]] {
|
|
membersJson = arr
|
|
} else if let arr = rawMembers as? [Any] {
|
|
membersJson = arr.compactMap { $0 as? [String: Any] }
|
|
} else {
|
|
membersJson = []
|
|
}
|
|
let members = membersJson.compactMap { GroupMemberModel(JSON: $0) }
|
|
let selected = (userInfo["userId"] as? String) ?? members.first?.user_id ?? ""
|
|
let group = (userInfo["groupJson"] as? [String: Any]).flatMap { GroupModel(JSON: $0) }
|
|
self.init(members: members, selectedUserId: selected, groupModel: group)
|
|
}
|
|
|
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
|
|
|
override func loadView() {
|
|
rootView = MemberInfoView(frame: UIScreen.main.bounds)
|
|
view = rootView
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
rootView.memberCV.dataSource = self
|
|
rootView.memberCV.delegate = self
|
|
bind()
|
|
refreshDetail()
|
|
rootView.memberCV.reloadData()
|
|
}
|
|
|
|
private func bind() {
|
|
rootView.navView.onBackTapped = { [weak self] in
|
|
self?.navigationController?.popViewController(animated: true)
|
|
}
|
|
}
|
|
|
|
private func refreshDetail() {
|
|
let member = members.first { $0.user_id == selectedUserId }
|
|
let isSelf = selectedUserId == AppContextManager.shared.userId
|
|
let joinText: String = {
|
|
guard let date = member?.joinDate else { return "**" }
|
|
let f = DateFormatter()
|
|
f.dateFormat = "yyyy-MM-dd"
|
|
return f.string(from: date)
|
|
}()
|
|
let commonGroupsRow = makeCommonGroupsRow(member: member)
|
|
|
|
if isSelf {
|
|
let sexText: String = {
|
|
switch AppContextManager.shared.sex {
|
|
case 1: return "男"
|
|
case 2: return "女"
|
|
case 0: return "保密"
|
|
default: return "未设置"
|
|
}
|
|
}()
|
|
rootView.renderRows([
|
|
MemberInfoRow(title: "头像", value: "", kind: .avatar, avatarURL: member?.head_pic) { [weak self] in
|
|
self?.editAvatar()
|
|
},
|
|
MemberInfoRow(title: "昵称", value: member?.nick_name ?? "", kind: .disclosure) { [weak self] in
|
|
self?.editNickname()
|
|
},
|
|
MemberInfoRow(title: "性别", value: sexText, kind: .disclosure) { [weak self] in
|
|
self?.editGender()
|
|
},
|
|
MemberInfoRow(title: "添加时间", value: joinText, kind: .text),
|
|
commonGroupsRow
|
|
])
|
|
} else {
|
|
rootView.renderRows([
|
|
MemberInfoRow(title: "昵称", value: member?.nick_name ?? "", kind: .text),
|
|
MemberInfoRow(title: "备注", value: member?.remark ?? "", kind: .disclosure) { [weak self] in
|
|
self?.editRemark()
|
|
},
|
|
MemberInfoRow(title: "关系", value: relationText(for: member), kind: .disclosure) { [weak self] in
|
|
self?.editRelation()
|
|
},
|
|
MemberInfoRow(title: "性别", value: "保密", kind: .text),
|
|
MemberInfoRow(title: "添加时间", value: joinText, kind: .text),
|
|
commonGroupsRow
|
|
])
|
|
}
|
|
}
|
|
|
|
private func makeCommonGroupsRow(member: GroupMemberModel?) -> MemberInfoRow {
|
|
let groups = resolvedCommonGroups(for: member)
|
|
let firstName = groups.first?.group_name.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
let visibleName = firstName.isEmpty ? "--" : firstName
|
|
let showsMore = groups.count > 1
|
|
let action: (() -> Void)? = showsMore ? { [weak self] in
|
|
self?.showCommonGroups(groups)
|
|
} : nil
|
|
return MemberInfoRow(
|
|
title: "共同圈子",
|
|
value: visibleName,
|
|
kind: .tag,
|
|
showsMoreTags: showsMore,
|
|
action: action
|
|
)
|
|
}
|
|
|
|
private func resolvedCommonGroups(for member: GroupMemberModel?) -> [CommonGroupModel] {
|
|
var groups = CommonGroupModel.deduplicated(member?.common_groups ?? [])
|
|
let groupInfos = groupModel?.groups ?? []
|
|
|
|
for index in groups.indices where groups[index].group_name.isEmpty {
|
|
groups[index].group_name = groupInfos.first {
|
|
$0.group_key == groups[index].group_key
|
|
}?.name ?? "未知圈子"
|
|
}
|
|
|
|
let currentGroup = groupInfos.first { $0.group_key == groupModel?.default_group_key }
|
|
?? groupInfos.first
|
|
if let currentGroup, !currentGroup.group_key.isEmpty {
|
|
if let index = groups.firstIndex(where: { $0.group_key == currentGroup.group_key }) {
|
|
var group = groups.remove(at: index)
|
|
if group.group_name.isEmpty || group.group_name == "未知圈子" {
|
|
group.group_name = currentGroup.name
|
|
}
|
|
groups.insert(group, at: 0)
|
|
} else {
|
|
groups.insert(
|
|
CommonGroupModel(groupKey: currentGroup.group_key, groupName: currentGroup.name),
|
|
at: 0
|
|
)
|
|
}
|
|
}
|
|
return CommonGroupModel.deduplicated(groups)
|
|
}
|
|
|
|
private func editAvatar() {
|
|
let current = AppContextManager.shared.head_pic
|
|
let vc = AvatarIconListVC(iconIndex: current)
|
|
vc.onSelectIcon = { [weak self] index in
|
|
self?.requestSetHeadPic(index: index)
|
|
}
|
|
navigationController?.pushViewController(vc, animated: true)
|
|
}
|
|
|
|
private func editNickname() {
|
|
let current = AppContextManager.shared.name
|
|
let vc = TextInputViewController(
|
|
title: "昵称",
|
|
maxLength: 10,
|
|
initialText: current
|
|
) { [weak self] text in
|
|
self?.requestSetNickName(text)
|
|
}
|
|
present(vc, animated: true)
|
|
}
|
|
|
|
private func relationText(for member: GroupMemberModel?) -> String {
|
|
RelationStore.shared.name(for: member?.extra.relation_idx ?? "") ?? "未绑定"
|
|
}
|
|
|
|
private func editRemark() {
|
|
guard let member = members.first(where: { $0.user_id == selectedUserId }) else { return }
|
|
let vc = TextInputViewController(
|
|
title: "备注",
|
|
maxLength: 10,
|
|
initialText: member.remark
|
|
) { [weak self] text in
|
|
self?.requestEditRemark(text)
|
|
}
|
|
present(vc, animated: true)
|
|
}
|
|
|
|
private func requestEditRemark(_ remark: String) {
|
|
let trimmed = remark.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !trimmed.isEmpty,
|
|
let member = members.first(where: { $0.user_id == selectedUserId }) else { return }
|
|
let groupKey = groupModel?.default_group_key ?? ""
|
|
guard !groupKey.isEmpty else {
|
|
DLToast.show(text: "圈子信息缺失")
|
|
return
|
|
}
|
|
|
|
DLToast.showLoading()
|
|
GroupService.operate(
|
|
opType: "editmateinfo",
|
|
requestData: [
|
|
"group_key": groupKey,
|
|
"user_id": member.user_id,
|
|
"nick_name": trimmed
|
|
]
|
|
).subscribe(onNext: { [weak self] _ in
|
|
DLToast.show(text: "修改成功")
|
|
guard let self,
|
|
let index = self.members.firstIndex(where: { $0.user_id == self.selectedUserId }) else { return }
|
|
self.members[index].remark = trimmed
|
|
self.rootView.memberCV.reloadData()
|
|
self.refreshDetail()
|
|
}, onError: { error in
|
|
DLToast.dismiss()
|
|
DLToast.show(text: error.localizedDescription)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func editRelation() {
|
|
if RelationStore.shared.list.isEmpty {
|
|
guard !isLoadingRelations else { return }
|
|
isLoadingRelations = true
|
|
DLToast.showLoading()
|
|
RelationStore.shared.preload { [weak self] result in
|
|
MainAsync {
|
|
guard let self else { return }
|
|
self.isLoadingRelations = false
|
|
DLToast.dismiss()
|
|
switch result {
|
|
case .success:
|
|
self.presentRelationPicker()
|
|
case let .failure(error):
|
|
DLToast.showError(text: error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
presentRelationPicker()
|
|
}
|
|
|
|
private func presentRelationPicker() {
|
|
guard presentedViewController == nil else { return }
|
|
let current = members.first { $0.user_id == selectedUserId }?.extra.relation_idx ?? ""
|
|
let pop = RelationSelectPopVC(currentIdx: current) { [weak self] idx in
|
|
self?.requestEditRelation(idx)
|
|
}
|
|
present(pop, animated: true)
|
|
}
|
|
|
|
private func requestEditRelation(_ idx: String) {
|
|
guard let member = members.first(where: { $0.user_id == selectedUserId }) else { return }
|
|
let groupKey = groupModel?.default_group_key ?? ""
|
|
guard !groupKey.isEmpty else {
|
|
DLToast.show(text: "圈子信息缺失")
|
|
return
|
|
}
|
|
let nick = member.remark.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let nickName = nick.isEmpty ? member.nick_name : nick
|
|
DLToast.showLoading()
|
|
GroupService.operate(
|
|
opType: "editmateinfo",
|
|
requestData: [
|
|
"group_key": groupKey,
|
|
"user_id": member.user_id,
|
|
"nick_name": nickName,
|
|
"extra": ["relation_idx": idx]
|
|
]
|
|
).subscribe(onNext: { [weak self] _ in
|
|
DLToast.show(text: "设置成功")
|
|
guard let self, let index = self.members.firstIndex(where: { $0.user_id == self.selectedUserId }) else { return }
|
|
self.members[index].extra.relation_idx = idx
|
|
self.refreshDetail()
|
|
}, onError: { error in
|
|
DLToast.dismiss()
|
|
DLToast.show(text: error.localizedDescription)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func editGender() {
|
|
let pop = GenderSelectPopVC(currentSex: AppContextManager.shared.sex) { [weak self] sex in
|
|
self?.requestSetGender(sex)
|
|
}
|
|
present(pop, animated: true)
|
|
}
|
|
|
|
private func requestSetHeadPic(index: Int) {
|
|
DLToast.showLoading()
|
|
UserService.setHeadPic(index: index).subscribe(onNext: { [weak self] _ in
|
|
DLToast.show(text: "更换成功")
|
|
self?.applyLocalMemberChange(headPic: "\(index)", nickName: nil)
|
|
self?.syncUserConfig()
|
|
}, onError: { error in
|
|
DLToast.dismiss()
|
|
DLToast.show(text: error.localizedDescription)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func requestSetNickName(_ name: String) {
|
|
let trimmed = name.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !trimmed.isEmpty else { return }
|
|
DLToast.showLoading()
|
|
UserService.setNickName(nick: trimmed).subscribe(onNext: { [weak self] _ in
|
|
DLToast.show(text: "修改成功")
|
|
self?.applyLocalMemberChange(headPic: nil, nickName: trimmed)
|
|
self?.syncUserConfig()
|
|
}, onError: { error in
|
|
DLToast.dismiss()
|
|
DLToast.show(text: error.localizedDescription)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func requestSetGender(_ sex: Int) {
|
|
DLToast.showLoading()
|
|
UserService.setGender(sex: sex).subscribe(onNext: { [weak self] _ in
|
|
DLToast.show(text: "修改成功")
|
|
if var account = AppContextManager.shared.account {
|
|
account.sex = sex
|
|
AppContextManager.shared.saveAccount(account)
|
|
}
|
|
self?.refreshDetail()
|
|
self?.syncUserConfig()
|
|
}, onError: { error in
|
|
DLToast.dismiss()
|
|
DLToast.show(text: error.localizedDescription)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func applyLocalMemberChange(headPic: String?, nickName: String?) {
|
|
if let index = members.firstIndex(where: { $0.user_id == selectedUserId }) {
|
|
if let headPic {
|
|
members[index].head_pic = headPic
|
|
}
|
|
if let nickName {
|
|
members[index].nick_name = nickName
|
|
}
|
|
}
|
|
if var account = AppContextManager.shared.account {
|
|
if let headPic { account.head_pic = headPic }
|
|
if let nickName { account.name = nickName }
|
|
AppContextManager.shared.saveAccount(account)
|
|
}
|
|
rootView.memberCV.reloadData()
|
|
refreshDetail()
|
|
}
|
|
|
|
private func syncUserConfig() {
|
|
UserService.userInfo().subscribe(onNext: { response in
|
|
if let model = response.model {
|
|
AppContextManager.shared.saveAccount(model)
|
|
}
|
|
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
|
|
}, onError: { _ in
|
|
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
|
|
}).disposed(by: disposeBag)
|
|
}
|
|
|
|
private func showCommonGroups(_ groups: [CommonGroupModel]) {
|
|
guard groups.count > 1 else { return }
|
|
let popup = CommonGroupsPopVC(groups: groups, groupInfos: groupModel?.groups ?? [])
|
|
present(popup, animated: true)
|
|
}
|
|
}
|
|
|
|
extension MemberInfoVC: UICollectionViewDataSource, UICollectionViewDelegate {
|
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
members.count
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
let cell: GroupMemberListCell = collectionView.dequeueReusableCell(for: indexPath)
|
|
let model = members[indexPath.item]
|
|
cell.configure(
|
|
model: model,
|
|
isCurrentUser: model.user_id == AppContextManager.shared.userId,
|
|
isSelected: model.user_id == selectedUserId
|
|
)
|
|
return cell
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
selectedUserId = members[indexPath.item].user_id
|
|
collectionView.reloadData()
|
|
refreshDetail()
|
|
}
|
|
}
|