鸿蒙学习实战之路-STG系列(8/11)-守护策略管理完整实战

朋友们,前几篇我们学习了守护策略的添加、修改、查询、删除、启动和停止功能。今天这篇我们就来做一个完整的实战案例,把这些功能整合起来,实现一个完整的守护策略管理系统 o(╯□╰)o

这个实战案例会包含所有策略管理功能,让你能一次性学会如何使用 Screen Time Guard Kit 的守护策略管理能力~

今天这篇,我会手把手带你实现一个完整的守护策略管理系统,全程不超过5分钟(不含你测试的时间)~


一、实战案例概述

我们将实现一个完整的守护策略管理系统,包含以下功能:

1. 核心功能

功能 说明
用户授权 请求和取消用户授权
应用选择 选择要管控的应用
策略管理 添加、修改、查询、删除策略
策略控制 启动和停止策略
状态显示 显示策略运行状态

2. 策略类型支持

  • 起止时间策略(工作日 9:00-18:00)
  • 总时长策略(每天最多 2 小时)
  • 共享时长策略(多个应用共享时长)

3. 限制类型支持

  • 禁止清单(黑名单)
  • 允许清单(白名单)

二、完整实现代码

下面是一个完整的守护策略管理系统实现:

import { guardService, appPicker, TimeGuardExtensionAbility } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';

// TimeGuardExtensionAbility 实现
export default class TimeGuardExtension extends TimeGuardExtensionAbility {
  async onStart(strategyName: string): Promise<void> {
    hilog.info(0x0000, 'TimeGuardExtension', `策略启动: ${strategyName}`);
  }

  async onStop(strategyName: string): Promise<void> {
    hilog.info(0x0000, 'TimeGuardExtension', `策略停止: ${strategyName}`);
  }
}

@Entry
@Component
struct GuardStrategyManagementSystem {
  // 状态变量
  @State authStatus: string = '未知';
  @State selectedTokens: string[] = [];
  @State strategies: guardService.GuardStrategy[] = [];
  @State runningStrategies: Set<string> = new Set();
  @State currentTab: number = 0;
  @State selectedStrategy: guardService.GuardStrategy | null = null;
  @State message: string = '';

  // 策略表单数据
  @State strategyName: string = '';
  @State strategyType: string = 'START_END_TIME_TYPE';
  @State startTime: string = '09:00';
  @State endTime: string = '18:00';
  @State duration: number = 7200; // 2 小时
  @State repeatDays: number[] = [1, 2, 3, 4, 5];
  @State restrictionType: string = 'BLOCKLIST_TYPE';

  // 用户首选项
  private pref: preferences.Preferences | null = null;

  async aboutToAppear() {
    // 初始化用户首选项
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    this.pref = await preferences.getPreferences(context, 'guard_strategy_data');

    // 加载状态
    await this.loadStatus();

    // 检查授权状态
    await this.checkAuthStatus();
  }

  /**
   * 加载保存的状态
   */
  async loadStatus() {
    try {
      if (this.pref) {
        const running = await this.pref.get('running_strategies', '') as string;
        if (running) {
          this.runningStrategies = new Set(JSON.parse(running));
        }
      }
    } catch (err) {
      hilog.error(0x0000, 'GuardStrategyManagementSystem', 'loadStatus failed');
    }
  }

  /**
   * 保存状态
   */
  async saveStatus() {
    try {
      if (this.pref) {
        await this.pref.put('running_strategies', JSON.stringify([...this.runningStrategies]));
        await this.pref.flush();
      }
    } catch (err) {
      hilog.error(0x0000, 'GuardStrategyManagementSystem', 'saveStatus failed');
    }
  }

  /**
   * 检查授权状态
   */
  async checkAuthStatus() {
    try {
      const status = await guardService.getUserAuthStatus();
      this.authStatus = status === guardService.AuthStatus.AUTHORIZED ? '已授权' : '未授权';
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `checkAuthStatus failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 请求用户授权
   */
  async requestAuth() {
    try {
      await guardService.requestUserAuth(
        this.getUIContext().getHostContext() as common.UIAbilityContext
      );
      await this.checkAuthStatus();
      this.message = '授权成功';
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `授权失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `requestUserAuth failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 取消用户授权
   */
  async revokeAuth() {
    try {
      await guardService.revokeUserAuth();
      await this.checkAuthStatus();
      this.message = '取消授权成功';
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `取消授权失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `revokeUserAuth failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 选择应用
   */
  async selectApps() {
    try {
      const tokens = await appPicker.startAppPicker(
        this.getUIContext().getHostContext() as common.UIAbilityContext,
        { appTokens: this.selectedTokens }
      );
      this.selectedTokens = tokens;
      this.message = `已选择 ${tokens.length} 个应用`;
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `selected ${tokens.length} apps`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `选择应用失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `startAppPicker failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 查询所有策略
   */
  async queryStrategies() {
    try {
      const strategies = await guardService.queryGuardStrategies();
      this.strategies = strategies;
      this.message = `查询成功,共 ${strategies.length} 个策略`;
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `found ${strategies.length} strategies`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `查询失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `queryGuardStrategies failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 添加策略
   */
  async addStrategy() {
    if (this.selectedTokens.length === 0) {
      this.message = '请先选择要管控的应用';
      return;
    }

    if (!this.strategyName.trim()) {
      this.message = '请输入策略名称';
      return;
    }

    try {
      const time: guardService.TimeStrategy = {
        type: this.strategyType as guardService.TimeStrategyType,
        startTime: this.startTime,
        endTime: this.endTime,
        duration: this.duration,
        repeat: this.repeatDays
      };

      const appInfo: guardService.AppInfo = {
        appTokens: this.selectedTokens
      };

      const strategy: guardService.GuardStrategy = {
        name: this.strategyName,
        timeStrategy: time,
        appInfo: appInfo,
        appRestrictionType: this.restrictionType as guardService.RestrictionType
      };

      await guardService.addGuardStrategy(strategy);
      this.message = '策略添加成功';
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `addGuardStrategy succeeded: ${this.strategyName}`);
      
      // 刷新策略列表
      await this.queryStrategies();
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `添加失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `addGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 修改策略
   */
  async updateStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择要修改的策略';
      return;
    }

    if (this.selectedTokens.length === 0) {
      this.message = '请先选择要管控的应用';
      return;
    }

    try {
      const time: guardService.TimeStrategy = {
        type: this.strategyType as guardService.TimeStrategyType,
        startTime: this.startTime,
        endTime: this.endTime,
        duration: this.duration,
        repeat: this.repeatDays
      };

      const appInfo: guardService.AppInfo = {
        appTokens: this.selectedTokens
      };

      const strategy: guardService.GuardStrategy = {
        name: this.selectedStrategy.name,
        timeStrategy: time,
        appInfo: appInfo,
        appRestrictionType: this.restrictionType as guardService.RestrictionType
      };

      await guardService.updateGuardStrategy(this.selectedStrategy.name, strategy);
      this.message = '策略修改成功';
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `updateGuardStrategy succeeded: ${this.selectedStrategy.name}`);
      
      // 刷新策略列表
      await this.queryStrategies();
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `修改失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `updateGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 删除策略
   */
  async removeStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择要删除的策略';
      return;
    }

    try {
      await guardService.removeGuardStrategy(this.selectedStrategy.name);
      
      // 从运行列表中移除
      if (this.runningStrategies.has(this.selectedStrategy.name)) {
        this.runningStrategies.delete(this.selectedStrategy.name);
        await this.saveStatus();
      }
      
      this.message = '策略删除成功';
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `removeGuardStrategy succeeded: ${this.selectedStrategy.name}`);
      
      // 刷新策略列表
      await this.queryStrategies();
      this.selectedStrategy = null;
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `删除失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `removeGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 启动策略
   */
  async startStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择策略';
      return;
    }

    if (this.runningStrategies.has(this.selectedStrategy.name)) {
      this.message = '策略已在运行中';
      return;
    }

    try {
      await guardService.startGuardStrategy(this.selectedStrategy.name);
      this.runningStrategies.add(this.selectedStrategy.name);
      await this.saveStatus();
      this.message = '策略启动成功';
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `startGuardStrategy succeeded: ${this.selectedStrategy.name}`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this message = `启动失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `startGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 停止策略
   */
  async stopStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择策略';
      return;
    }

    if (!this.runningStrategies.has(this.selectedStrategy.name)) {
      this.message = '策略未在运行中';
      return;
    }

    try {
      await guardService.stopGuardStrategy(this.selectedStrategy.name);
      this.runningStrategies.delete(this.selectedStrategy.name);
      await this.saveStatus();
      this.message = '策略停止成功';
      hilog.info(0x0000, 'GuardStrategyManagementSystem', 
        `stopGuardStrategy succeeded: ${this.selectedStrategy.name}`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `停止失败: ${message}`;
      hilog.error(0x0000, 'GuardStrategyManagementSystem',
        `stopGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  /**
   * 获取策略描述
   */
  getStrategyDesc(strategy: guardService.GuardStrategy): string {
    const time = strategy.timeStrategy;
    let desc = '';

    if (time.type === guardService.TimeStrategyType.START_END_TIME_TYPE) {
      desc = `${time.startTime}-${time.endTime}`;
    } else if (time.type === guardService.TimeStrategyType.TOTAL_DURATION_TYPE) {
      desc = `总时长: ${Math.floor((time.duration || 0) / 60)} 分钟`;
    } else if (time.type === guardService.TimeStrategyType.SHARED_DURATION_TYPE) {
      desc = `共享时长: ${Math.floor((time.duration || 0) / 60)} 分钟`;
    }

    const repeat = time.repeat || [];
    if (repeat.length > 0) {
      const days = repeat.map(d => ['日', '一', '二', '三', '四', '五', '六'][d - 1]).join('、');
      desc += `${days}`;
    }

    return desc;
  }

  /**
   * 获取限制类型描述
   */
  getRestrictionTypeDesc(type: guardService.RestrictionType): string {
    return type === guardService.RestrictionType.BLOCKLIST_TYPE ? 
      '禁止清单' : '允许清单';
  }

  build() {
    Column() {
      Text('守护策略管理系统')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40 })

      // 消息显示
      Text(this.message)
        .fontSize(14)
        .margin({ top: 10 })
        .fontColor('#666666')

      // 授权状态
      Row() {
        Text('授权状态: ' + this.authStatus)
          .fontSize(16)
          .margin({ top: 20 })
        
        if (this.authStatus === '已授权') {
          Button('取消授权')
            .onClick(() => this.revokeAuth())
            .margin({ left: 10 })
        } else {
          Button('请求授权')
            .onClick(() => this.requestAuth())
            .margin({ left: 10 })
        }
      }
      .margin({ top: 10 })
      .width('100%')
      .padding({ left: 20, right: 20 })
      .backgroundColor('#F5F5F5')
      .borderRadius(8)

      // Tab 切换
      Row() {
        Button('策略管理')
          .onClick(() => { this.currentTab = 0; })
          .backgroundColor(this.currentTab === 0 ? '#007DFF' : '#F5F5F5')
          .fontColor(this.currentTab === 0 ? '#FFFFFF' : '#000000')
          .margin({ right: 10 })

        Button('添加策略')
          .onClick(() => { this.currentTab = 1; })
          .backgroundColor(this.currentTab === 1 ? '#007DFF' : '#F5F5F5')
          .fontColor(this.currentTab === 1 ? '#FFFFFF' : '#000000')
      }
      .margin({ top: 20 })
      .width('80%')

      // Tab 内容
      if (this.currentTab === 0) {
        // 策略管理页面
        Column() {
          // 控制按钮
          Row() {
            Button('刷新')
              .onClick(() => this.queryStrategies())
              .layoutWeight(1)
              .margin({ right: 10 })

            Button('启动')
              .onClick(() => this.startStrategy())
              .layoutWeight(1)
              .margin({ left: 10, right: 10 })

            Button('停止')
              .onClick(() => this.stopStrategy())
              .layoutWeight(1)
              .margin({ left: 10 })
          }
          .margin({ top: 20 })
          .width('80%')

          // 策略列表
          if (this.strategies.length > 0) {
            List() {
              ForEach(this.strategies, (strategy: guardService.GuardStrategy) => {
                ListItem() {
                  Column() {
                    Row() {
                      Text(strategy.name)
                        .fontSize(16)
                        .fontWeight(FontWeight.Bold)
                        .layoutWeight(1)

                      if (this.runningStrategies.has(strategy.name)) {
                        Text('运行中')
                          .fontSize(12)
                          .fontColor('#00FF00')
                          .backgroundColor('#E8F5E9')
                          .padding({ left: 8, right: 8 })
                          .borderRadius(4)
                      } else {
                        Text('未运行')
                          .fontSize(12)
                          .fontColor('#999999')
                          .backgroundColor('#F5F5F5')
                          .padding({ left: 8, right: 8 })
                          .borderRadius(4)
                      }
                    }
                    .width('100%')

                    Row() {
                      Text(this.getStrategyDesc(strategy))
                        .fontSize(14)
                        .fontColor('#666666')
                        .layoutWeight(1)

                      Text(this.getRestrictionTypeDesc(strategy.appRestrictionType))
                        .fontSize(12)
                        .fontColor('#999999')
                    }
                    .width('100%')
                    .margin({ top: 5 })

                    Text(`应用数量: ${strategy.appInfo.appTokens.length}`)
                      .fontSize(12)
                      .fontColor('#999999')
                      .margin({ top: 5 })
                  }
                  .width('100%')
                  .padding(15)
                  .backgroundColor(
                    this.selectedStrategy?.name === strategy.name ? '#E8F5E9' : '#F5F5F5'
                  )
                  .borderRadius(8)
                  .margin({ top: 5 })
                  .onClick(() => {
                    this.selectedStrategy = strategy;
                  })
                }
              })
            }
            .width('100%')
            .height('50%')
            .margin({ top: 20 })
          } else {
            Text('暂无策略,点击"添加策略"创建')
              .fontSize(16)
              .margin({ top: 30 })
              .fontColor('#999999')
          }
        }
        .width('100%')
        .height('100%')
      } else {
        // 添加策略页面
        Scroll() {
          Column() {
            // 策略名称
            Text('策略名称')
              .fontSize(16)
              .margin({ top: 20 })
            
            TextInput({ placeholder: '请输入策略名称' })
              .onChange((value: string) => {
                this.strategyName = value;
              })
              .margin({ top: 10 })
              .width('80%')

            // 策略类型
            Text('策略类型')
              .fontSize(16)
              .margin({ top: 20 })
            
            Row() {
              Button('起止时间')
                .onClick(() => { this.strategyType = 'START_END_TIME_TYPE'; })
                .backgroundColor(this.strategyType === 'START_END_TIME_TYPE' ? '#007DFF' : '#F5F5F5')
                .fontColor(this.strategyType === 'START_END_TIME_TYPE' ? '#FFFFFF' : '#000000')
                .margin({ right: 10 })

              Button('总时长')
                .onClick(() => { this.strategyType = 'TOTAL_DURATION_TYPE'; })
                .backgroundColor(this.strategyType === 'TOTAL_DURATION_TYPE' ? '#007DFF' : '#F5F5F5')
                .fontColor(this.strategyType === 'TOTAL_DURATION_TYPE' ? '#FFFFFF' : '#000000')
              .margin({ right: 10 })

              Button('共享时长')
                .onClick(() => { this.strategyType = 'SHARED_DURATION_TYPE'; })
                .backgroundColor(this.strategyType === 'SHARED_DURATION_TYPE' ? '#007DFF' : '#F5F5F5')
                .fontColor(this.strategyType === 'SHARED_DURATION_TYPE' ? '#FFFFFF' : '#000000')
            }
            .margin({ top: 10 })
            .width('80%')

            // 起止时间
            if (this.strategyType === 'START_END_TIME_TYPE') {
              Text('起止时间')
                .fontSize(16)
                .margin({ top: 20 })
              
              Row() {
                TextInput({ placeholder: '开始时间 (如: 09:00)' })
                  .onChange((value: string) => {
                    this.startTime = value;
                  })
                  .layoutWeight(1)
                  .margin({ right: 10 })

                TextInput({ placeholder: '结束时间 (如: 18:00)' })
                  .onChange((value: string) => {
                    this.endTime = value;
                  })
                  .layoutWeight(1)
                  .margin({ left: 10 })
              }
              .margin({ top: 10 })
              .width('80%')
            }

            // 时长
            if (this.strategyType === 'TOTAL_DURATION_TYPE' || this.strategyType === 'SHARED_DURATION_TYPE') {
              Text('时长 (分钟)')
                .fontSize(16)
                .margin({ top: 20 })
              
              TextInput({ placeholder: '请输入时长(分钟)' })
                .type(InputType.Number)
                .onChange((value: string) => {
                  this.duration = parseInt(value) * 60; // 转换为秒
                })
                .margin({ top: 10 })
                .width('80%')
            }

            // 重复规则
            Text('重复规则')
              .fontSize(16)
              .margin({ top: 20 })
            
            Row() {
              Button('周一')
                .onClick(() => {
                  if (this.repeatDays.includes(1)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 1);
                  } else {
                    this.repeatDays.push(1);
                  }
                })
                .backgroundColor(this.repeatDays.includes(1) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(1) ? '#FFFFFF' : '#000000')
                .margin({ right: 5 })

              Button('周二')
                .onClick(() => {
                  if (this.repeatDays.includes(2)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 2);
                  } else {
                    this.repeatDays.push(2);
                  }
                })
                .backgroundColor(this.repeatDays.includes(2) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(2) ? '#FFFFFF' : '#000000')
                .margin({ left: 5, right: 5 })

              Button('周三')
                .onClick(() => {
                  if (this.repeatDays.includes(3)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 3);
                  } else {
                    this.repeatDays.push(3);
                  }
                })
                .backgroundColor(this.repeatDays.includes(3) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(3) ? '#FFFFFF' : '#000000')
                .margin({ left: 5, right: 5 })

              Button('周四')
                .onClick(() => {
                  if (this.repeatDays.includes(4)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 4);
                  } else {
                    this.repeatDays.push(4);
                  }
                })
                .backgroundColor(this.repeatDays.includes(4) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(4) ? '#FFFFFF' '#000000')
                .margin({ left: 5, right: 5 })

              Button('周五')
                .onClick(() => {
                  if (this.repeatDays.includes(5)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 5);
                  } else {
                    this.repeatDays.push(5);
                  }
                })
                .backgroundColor(this.repeatDays.includes(5) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(5) ? '#FFFFFF' : '#000000')
                .margin({ left: 5, right: 5 })

              Button('周六')
                .onClick(() => {
                  if (this.repeatDays.includes(6)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 6);
                  } else {
                    this.repeatDays.push(6);
                  }
                })
                .backgroundColor(this.repeatDays.includes(6) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(6) ? '#FFFFFF' : '#000000')
                .margin({ left: 5, right: 5 })

              Button('周日')
                .onClick(() => {
                  if (this.repeatDays.includes(7)) {
                    this.repeatDays = this.repeatDays.filter(d => d !== 7);
                  } else {
                    this.repeatDays.push(7);
                  }
                })
                .backgroundColor(this.repeatDays.includes(7) ? '#007DFF' : '#F5F5F5')
                .fontColor(this.repeatDays.includes(7) ? '#FFFFFF' : '#000000')
                .margin({ left: 5 })
            }
            .margin({ top: 10 })
            .width('80%')

            // 限制类型
            Text('限制类型')
              .fontSize(16)
              .margin({ top: 20 })
            
            Row() {
              Button('禁止清单')
                .onClick(() => { this.restrictionType = 'BLOCKLIST_TYPE'; })
                .backgroundColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#007DFF' : '#F5F5F5')
                .fontColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#FFFFFF' : '#000000')
                .margin({ right: 10 })

              Button('允许清单')
                .onClick(() => { this.restrictionType = 'ALLOWLIST_TYPE'; })
                .backgroundColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#007DFF' : '#F5F5F5')
                .fontColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#FFFFFF' : '#000000')
              .margin({ left: 10 })
            }
            .margin({ top: 10 })
            .width('80%')

            // 应用选择
            Text('选择要管控的应用')
              .fontSize(16)
              .margin({ top: 20 })
            
            Button('选择应用')
              .onClick(() => this.selectApps())
              .margin({ top: 10 })
              .width('80%')

            Text(`已选择 ${this.selectedTokens.length} 个应用`)
              .fontSize(14)
              .margin({ top: 5 })
              .fontColor('#666666')

            // 添加按钮
            Button('添加策略')
              .onClick(() => this.addStrategy())
              .margin({ top: 30 })
              .width('80%')
          }
          .width('100%')
          .height('100%')
        }
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

三、功能特点

这个完整的守护策略管理系统具有以下特点:

1. 完整的策略生命周期管理

  • ✅ 添加策略
  • ✅ 修改策略
  • ✅ 查询策略
  • ✅ 删除策略
  • ✅ 启动策略
  • ✅ 停止策略

2. 用户授权管理

  • ✅ 请求用户授权
  • ✅ 取消用户授权
  • ✅ 查看授权状态

3. 应用选择功能

  • ✅ 拉起应用选择页
  • ✅ 保存已选择的应用 Token
  • ✅ 预勾选已选择的应用

4. 策略类型支持

  • ✅ 起止时间策略
  • ✅ 总时长策略
  • ✅ 共享时长策略

5. 限制类型支持

  • ✅ 禁止清单(黑名单)
  • ✅ 允许清单(白名单)

6. 状态显示

  • ✅ 显示策略运行状态
  • 显示授权状态
  • 显示已选择的应用数量

四、使用流程

使用这个系统的完整流程就像这样:

1. 首次使用
    ↓
2. 请求用户授权
    ↓
3. 选择要管控的应用
    ↓
4. 添加策略(选择策略类型、时间规则、限制类型)
    ↓
5. 启动策略
    ↓
6. 策略开始生效
    ↓
7. 随时可以查看、修改、删除、停止策略

五、注意事项

🥦 西兰花警告:

  1. 必须先获得用户授权: 使用任何策略功能之前,必须先请求用户授权
  2. 策略名称必须唯一: 不能有同名的策略,否则会报错
  3. 修改策略名称要一致: 修改策略时,策略名称必须和已存在的策略名称一致
  4. 启动后系统时间锁定: 策略启动后,系统时间会被锁定,不能修改
  5. 管控应用不可卸载: 策略启动后,管控应用会被设置为不可卸载
  6. 不能重复启动/停止: 不能重复启动正在运行的策略,也不能停止未运行的策略
  7. 应用 Token 要保存: 应用 Token 需要保存好,用于后续的管控操作

六、总结

这个完整的守护策略管理系统集成了所有策略管理功能,让你可以方便地管理屏幕时间管控规则。

核心要点:

  1. 完整的策略生命周期管理(增删改查启停)
  2. 用户授权管理
  3. 应用选择功能
  4. 支持多种策略类型和限制类型
  5. 策略状态显示和管理
  6. 数据持久化保存

有了这个系统,你就可以轻松实现家长控制、专注模式等各种屏幕时间管控功能了 _


下一步行动

建议你:

  1. 先测试用户授权功能
  2. 测试应用选择功能
  3. 测试各种策略类型的添加
  4. 测试策略的启动和停止
  5. 测试策略的修改和删除
  6. 根据实际需求调整界面和功能

记住,不教理论,只给你能跑的代码和避坑指南! _


我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐