:参赛者池的增删改与空状态处理)
一、参赛者池不是一个临时字符串数组对局创建通常分为基础设置、参与人员和生成对阵三步。参与人员页既支持手工添加也支持快捷生成和接龙导入还要允许删除、清空、返回保存与继续生成。若每个入口维护一份自己的数组页面显示、草稿人数和最终对阵很快就会不一致。参赛者池应当是对局草稿的一个可观察切片页面使用副本编辑每次变更后写回同一个草稿生成对局前再次读取草稿并校验。这样返回上一步、改变场地或轮次时人员列表仍是同一个事实源。二、保存时重建草稿而不是只改人数人员变更后要同时更新名单和participantCount但不能覆盖对局名称、场地、轮次和配对模式。构造一个新草稿对象可以清楚表达哪些字段来自旧状态、哪些字段由当前页面负责。Component export struct ParticipantPoolPage { State participants: string[] [] State nameInput: string State chainInput: string StorageLink(SessionStore.KEY_ACTIVE_DRAFT) draftRef: SessionDraft SessionStore.loadDraft() aboutToAppear(): void { this.participants SessionStore.loadDraft().participants.slice() } save(): void { const draft SessionStore.loadDraft() const next: SessionDraft { name: draft.name, participantCount: this.participants.length, courtCount: draft.courtCount, roundCount: draft.roundCount, pairingMode: draft.pairingMode, participants: this.participants.slice(), participantRefs: draft.participantRefs } SessionStore.saveDraft(next) } }slice()让新数组获得新引用ArkUI 能可靠观察到变化也避免其他页面持有的引用被原地修改。三、添加入口统一执行归一化与去重手工添加应先去除首尾空格并拒绝重复。快捷添加也不能直接覆盖数组而是在副本中逐一补齐不存在的默认名称。所有入口最终都调用同一个保存动作。addName(name: string): void { const value name.trim() if (value.length 0 || this.participants.indexOf(value) 0) { return } const next this.participants.slice() next.push(value) this.participants next this.save() } addQuick(count: number): void { const next this.participants.slice() for (let index 1; index count; index) { const name 球友${index} if (next.indexOf(name) 0) { next.push(name) } } this.participants next this.save() }快捷入口是演示和临时开局的效率工具不应绕过去重与保存规则。以后替换为常用球友选择器时也只需改变输入来源。四、接龙导入只合并新增姓名文本解析器返回有序去重名单但页面当前可能已经包含手工添加的人。导入时应在副本中再次去重只加入新增项并将实际解析数量反馈给用户。importChain(): void { const parsed ChainTextParser.parse(this.chainInput) const next this.participants.slice() parsed.forEach((name: string) { if (next.indexOf(name) 0) { next.push(name) } }) this.participants next this.save() Feedback.toast(已导入 ${parsed.length} 人) } confirm(): void { this.save() router.back() }提示中的解析数量和真正新增数量可以进一步拆开显示。例如解析出 8 人、其中 2 人已存在就提示“识别 8 人新增 6 人”能帮助用户发现重复报名。五、删除与清空采用不同风险等级删除单人是可见、局部的动作可以直接更新清空会一次移除全部人员需要确认。空数组时再次清空则只给提示不弹无意义的确认框。removeAt(index: number): void { if (index 0 || index this.participants.length) return const next this.participants.slice() next.splice(index, 1) this.participants next this.save() } clearAll(): void { if (this.participants.length 0) { Feedback.toast(暂无可清空人员) return } Feedback.confirm({ title: 清空人员, message: 将删除已添加的全部参与人员是否继续, cancelText: 取消, confirmText: 清空 }, () { this.participants [] this.save() Feedback.toast(已清空参与人员) }) }确认回调内再次保存确保用户取消时状态完全不变。六、空状态要提供恢复入口空状态不是一行“暂无数据”就结束。它应说明为什么为空并把用户带回添加动作。列表非空时则展示计数、删除入口和生成对阵按钮。Builder ParticipantContent() { if (this.participants.length 0) { Column() { Image($r(app.media.empty_participants)) .width(120) .height(120) Text(还没有参与人员) Text(可以手工添加也可以粘贴群接龙) Button(添加第一位球友) .onClick(() this.focusNameInput()) } } else { Flex({ wrap: FlexWrap.Wrap }) { ForEach(this.participants, (name: string, index: number) { ParticipantChip({ name, onRemove: () this.removeAt(index) }) }, (name: string) name) } } }稳定姓名可以作为列表键如果允许同名球友则需要为参与者增加独立 ID不能再用姓名键和姓名去重。引入独立 ID 后显示名修改不再等同于删除再新增已关联的用户头像、云端账号和历史统计也能继续指向同一个人。多人协作编辑时还应给草稿增加版本号提交变更携带读取时的版本服务端只接受基于当前版本的更新版本不一致时先拉取最新名单再让用户选择合并或覆盖。这样可以避免两台设备同时增删人员造成后一次保存静默覆盖前一次结果。七、生成对局前处理编辑风险新建对局至少需要四人并且名称不能与其他对局重复。编辑已有对局时人员变化会重新生成对阵如果已经录入比分必须明确提示这些比分将被清空不能静默覆盖。createSession(): void { this.save() const draft SessionStore.loadDraft() if (draft.participants.length 4) { Feedback.toast(至少添加 4 名参与者) return } const editingId SessionStore.getEditSession() const current SessionStore.findSummary(editingId) if (current ! undefined current.finishedMatchCount 0) { Feedback.confirm({ title: 保存对局修改, message: 保存后会重新生成对阵并清空当前比分是否继续, cancelText: 取消, confirmText: 继续保存 }, () this.updateSession(editingId, draft)) return } if (editingId.length 0) { this.updateSession(editingId, draft) return } const session SessionStore.create(draft) this.syncCreatedSession(session.id) }状态允许动作保护措施0 人添加、导入显示空状态禁止生成1–3 人继续增删提示至少需要 4 人4 人以上生成对局同名检查、均分提示编辑未计分对局更新并重排保留确认后的草稿编辑已计分对局高风险更新明示比分将清空并二次确认八、验证增删改与状态恢复验收需要关注“页面显示、草稿内容、最终对局”三层是否同步。只看标签数量正确还不够返回基础设置后再次进入也应恢复相同名单。用例操作通过信号空输入输入空格后添加人数不变无空标签重复姓名连续添加同一姓名只保留一个快捷添加先手工添加球友1再添加 6 人球友1 不重复总人数正确接龙合并当前 2 人导入含 1 个重复的名单只合并新增姓名单人删除删除中间项顺序保持人数同步减少清空取消点击清空后取消名单和草稿均不变返回恢复保存返回再进入人员顺序与数量一致已计分编辑修改名单并保存先出现重排风险确认HarmonyOS 组件状态和存储链接的使用边界可参考状态管理概述。当页面和草稿共享状态时仍应通过明确方法更新避免多个组件直接原地修改同一数组。九、总结参赛者池的稳定性来自三个原则单一草稿是真相源所有增删入口都使用副本更新并立即保存高风险编辑必须显式确认。空状态提供恢复入口生成前执行人数与对局约束返回页面后再验证状态恢复。这样临场报名变化可以被安全吸收也不会悄悄破坏已经产生的对阵和比分。