【OpenHarmony/HarmonyOs 】ArkTS 个性化身份系统:用工厂模式生成角色预置导航

前言

同一个导航应用面对不同用户时,默认内容不应该完全相同。开发者想看 GitHub,设计师常用 Figma,学生更需要课程平台。LinkOS 链界在首次启动时让用户选择身份,再根据身份提供预置入口,这是一种低成本但效果明显的个性化方案。👤

一、先定义稳定的数据协议1111

角色并不只是名称和图标,还包含描述、主题色、特性标签与默认网址:

export interface RolePreset {
  id: string;
  name: string;
  desc: string;
  themeColor: string;
  icon: string;
  features: string[];
  defaultUrls: UrlItem[];
}

字段设计的意义如下:

字段 用途
id 持久化和业务判断,不受显示语言影响
namedesc 面向用户的角色说明
themeColor 卡片选中态或主题定制
icon 角色的视觉识别符号
features 展示角色能获得的内容方向
defaultUrls 该角色的初始化网址集合

id 一定要稳定。例如显示名称以后可从“开发者”改为“软件开发”,但 developer 不应改变,否则历史数据将无法匹配。

二、使用工厂统一生产预置数据

export class RoleFactory {
  static getPresets(): RolePreset[] {
    return [
      {
        id: 'developer',
        name: '开发者',
        desc: '代码改变世界',
        themeColor: '#615FFF',
        icon: '💻',
        features: ['技术社区', '工具导航', '效率提升'],
        defaultUrls: [
          {
            id: 'd1',
            title: 'GitHub',
            url: 'https://github.com',
            categoryId: 'dev',
            sort: 1,
            createdAt: 0,
            updatedAt: 0
          }
        ]
      }
    ];
  }
}

工厂的好处是页面不关心预置从哪里来。现在可以返回本地常量,未来也可以加载资源文件、远程配置或 Cloud DB。页面只依赖 RolePreset[] 这一协议。

三、角色选择页的 ArkUI 实现

@Entry
@Component
struct WelcomePage {
  private roles: RolePreset[] = RoleFactory.getPresets();
  @State selectedRoleId: string = '';

  build() {
    Grid() {
      ForEach(this.roles, (role: RolePreset) => {
        GridItem() {
          Column() {
            Text(role.icon).fontSize(34)
            Text(role.name).fontSize(13).margin({ top: 12 })
          }
          .border({
            width: 1,
            color: this.selectedRoleId === role.id
              ? '#DAB2FF' : '#E5E7EB'
          })
          .onClick(() => this.selectRole(role))
        }
      })
    }
    .columnsTemplate('1fr 1fr')
    .columnsGap(12)
    .rowsGap(12)
  }
}

Grid 很适合角色选择,因为卡片尺寸统一且用户需要快速扫描。手机上使用两列,平板可根据断点切换三列或四列。选中态不要只依赖颜色,正式产品还可增加对勾图标,以改善无障碍体验。

四、从角色到首页推荐

角色选择后的推荐过程可以拆成三步:

  1. 保存角色 ID,而不是保存整份角色对象。
  2. 首页出现时重新从工厂寻找对应角色。
  3. 合并角色默认网址、兴趣推荐与用户自定义网址。
const roleId = await storage.get(StorageKeys.USER_ROLE_ID, '') as string;
const role = RoleFactory.getPresets().find(item => item.id === roleId);
const defaultSites = role ? role.defaultUrls : [];

只保存 ID 可以减少冗余,也能让应用升级预置内容后自动生效。但这又带来一个产品决策:新版新增的网址是否自动出现在老用户首页?

比较稳妥的策略是:

  • 角色预置作为只读推荐源,可随版本更新;
  • 用户主动收藏后复制到自定义集合;
  • 用户隐藏某个推荐时,记录一个 hiddenPresetIds 集合;
  • 自定义站点永远不被版本更新覆盖。

五、“自定义”角色为什么重要

预置列表中保留 custom 角色,并让 defaultUrls 为空:

{
  id: 'custom',
  name: '自定义',
  desc: '从零开始',
  themeColor: '#9E9E9E',
  icon: '🛠️',
  features: ['完全自由定制', '从零配置', '极简模式'],
  defaultUrls: []
}

个性化不是“系统替用户做完所有决定”。对有明确偏好的高级用户,空白模板反而更友好。提供自定义角色也让推荐系统保留了退出机制。

六、时间字段与预置数据版本

示例中的预置网址时间为 0,表示它们不是用户创建的数据。若未来做云同步,建议补充:

interface RolePreset {
  id: string;
  version: number;
  defaultUrls: UrlItem[];
}

应用记录用户已应用的预置版本。升级时可以计算新增项,而不是粗暴覆盖整份列表。若用户已经编辑过某个网址,应以用户数据为准。

七、国际化与资源化

当前角色名称直接写在 ArkTS 中,原型阶段直观,但正式产品应将显示文本迁移到资源:

Text($r('app.string.role_developer'))

角色模型可以保存资源名或由 ViewModel 转换显示文本。这样语言切换时无需复制整套业务数据,也避免中文文本成为业务主键。

八、可继续扩展的方向

  • 🧠 允许多选兴趣,对角色推荐进行二次加权;
  • 📈 根据打开次数调整站点顺序,但保留用户手动置顶;
  • ☁️ 用 Remote Config 动态下发预置版本;
  • 🏷️ 将一个网站映射到多个标签,而不是单一分类;
  • 🔄 支持“工作、学习、旅行”等场景模式快速切换。

九、总结

角色预置系统的核心并不是堆一组网址,而是建立“稳定 ID + 数据协议 + 推荐源 + 用户覆盖”的边界。工厂模式让预置数据与页面解耦,Preferences 只保存用户选择,自定义集合保留用户所有权。这样的小型架构,已经能支撑一个可持续迭代的个性化入口系统。🚀

img

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐