鴻蒙NEXT開發案例:隨機密碼生成

zhongcx發表於2024-11-20

【引言】

本案例將實現一個隨機密碼生成器。使用者可以自定義密碼的長度以及包含的字元型別(大寫字母、小寫字母、數字、特殊字元),最後透過點選按鈕生成密碼,並提供一鍵複製功能。

【環境準備】

•作業系統:Windows 10
•開發工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
•目標裝置:華為Mate60 Pro
•開發語言:ArkTS
•框架:ArkUI
•API版本:API 12

【專案結構】

本專案主要由一個入口元件PasswordGeneratorPage和一個可觀察的類PasswordOption組成。PasswordOption類用於定義密碼選項,包括選項名稱、字符集、是否選中和是否啟用的狀態。

1. PasswordOption類

@ObservedV2
class PasswordOption {
  name: string; // 選項名稱
  characters: string; // 該選項對應的字符集
  @Trace selected: boolean = true; // 是否選中,預設為true
  @Trace enabled: boolean = true; // 是否啟用,預設為true

  constructor(name: string, characters: string) {
    this.name = name;
    this.characters = characters;
  }
}

2. PasswordGeneratorPage元件

該元件包含密碼選項、密碼長度設定、生成密碼和複製密碼的功能。

@Entry
@Component
struct PasswordGeneratorPage {
  @State options: PasswordOption[] = [
    new PasswordOption("大寫字母", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
    new PasswordOption("小寫字母", "abcdefghijklmnopqrstuvwxyz"),
    new PasswordOption("數字", "0123456789"),
    new PasswordOption("特殊字元", "!@#$%^&*()_+-=[]{}|;:,.<>?"),
  ];
  @State passwordLength: number = 10; // 預設密碼長度
  @State generatedPassword: string = ''; // 生成的密碼

  // 生成密碼的方法
  generatePassword() {
    let characterSet = '';
    for (let option of this.options) {
      if (option.selected) {
        characterSet += option.characters;
      }
    }
    let password = '';
    for (let i = 0; i < this.passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * characterSet.length);
      password += characterSet[randomIndex];
    }
    this.generatedPassword = password;
  }

  // 複製到剪貼簿的方法
  copyToClipboard(text: string) {
    const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text);
    const systemPasteboard = pasteboard.getSystemPasteboard();
    systemPasteboard.setData(pasteboardData);
    promptAction.showToast({ message: '已複製' });
  }

  // 構建頁面佈局的方法
  build() {
    // 頁面佈局程式碼...
  }
}

功能實現

1. 生成密碼

使用者可以選擇不同的字符集(大寫字母、小寫字母、數字、特殊字元),並設定密碼長度。點選“生成密碼”按鈕後,系統將根據選中的選項生成隨機密碼。

2. 複製密碼

生成的密碼可以透過點選“複製”按鈕複製到剪貼簿,使用者將收到“已複製”的提示。

使用者介面

使用者介面採用了簡潔的設計,包含標題、密碼長度設定、選項選擇、生成密碼按鈕和複製按鈕。透過動態生成選項的UI元素,使用者可以方便地選擇所需的字符集。

總結

本文介紹瞭如何使用鴻蒙NEXT框架開發一個隨機密碼生成器。透過簡單的程式碼實現,我們可以快速構建出實用的功能。希望這個案例能為你的開發提供靈感和幫助。

【完整程式碼】

// 匯入剪貼簿服務
import { pasteboard } from '@kit.BasicServicesKit';
// 匯入彈窗提示服務
import { promptAction } from '@kit.ArkUI';

// 使用裝飾器定義一個可觀察的類,用於密碼選項
@ObservedV2
class PasswordOption {
  name: string; // 選項名稱
  characters: string; // 該選項對應的字符集
  // 定義是否選中,預設為true
  @Trace selected: boolean = true;
  // 定義是否啟用,預設為true
  @Trace enabled: boolean = true;

  // 建構函式,初始化name和characters
  constructor(name: string, characters: string) {
    this.name = name;
    this.characters = characters;
  }
}

// 使用裝飾器定義一個入口元件
@Entry
@Component
struct PasswordGeneratorPage {
  // 定義密碼選項陣列
  @State options: PasswordOption[] = [
    new PasswordOption("大寫字母", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
    new PasswordOption("小寫字母", "abcdefghijklmnopqrstuvwxyz"),
    new PasswordOption("數字", "0123456789"),
    new PasswordOption("特殊字元", "!@#$%^&*()_+-=[]{}|;:,.<>?"),
  ];
  // 定義密碼長度狀態,預設值為10
  @State passwordLength: number = 10;
  // 基礎間距
  @State baseSpacing: number = 30;
  // 生成的密碼
  @State generatedPassword: string = '';
  // 是否啟用複製按鈕
  @State isCopyButtonEnabled: boolean = false;
  // 主題色
  @State primaryColor: string = '#71dec7';
  // 字型顏色
  @State fontColor: string = "#2e2e2e";

  // 生成密碼的方法
  generatePassword() {
    let characterSet = ''; // 初始化字符集合
    // 遍歷所有選項,如果選項被選中則加入字符集合
    for (let option of this.options) {
      if (option.selected) {
        characterSet += option.characters
      }
    }
    let password = ''; // 初始化密碼字串
    // 根據密碼長度生成隨機密碼
    for (let i = 0; i < this.passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * characterSet.length);
      password += characterSet[randomIndex];
    }
    this.generatedPassword = password; // 更新生成的密碼
  }

  // 複製到剪貼簿的方法
  copyToClipboard(text: string) {
    const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text); // 建立剪貼簿資料
    const systemPasteboard = pasteboard.getSystemPasteboard(); // 獲取系統剪貼簿
    systemPasteboard.setData(pasteboardData); // 將資料放入剪下板
    promptAction.showToast({ message: '已複製' }); // 顯示覆製成功的提示
  }

  // 檢查選項選擇狀態的方法
  checkOptionsSelection() {
    let selectedCount = 0; // 記錄已選中的選項數量
    let lastSelectedIndex = 0; // 記錄最後一個選中的選項索引
    // 遍歷所有選項
    for (let i = 0; i < this.options.length; i++) {
      this.options[i].enabled = true; // 預設啟用所有選項
      if (this.options[i].selected) {
        lastSelectedIndex = i; // 更新最後一個選中的選項索引
        selectedCount++; // 增加選中計數
      }
    }
    // 如果只有一個選項被選中,則禁用該選項防止其被取消選中
    if (selectedCount === 1) {
      this.options[lastSelectedIndex].enabled = false;
    }
  }

  // 構建頁面佈局的方法
  build() {
    Column() {
      // 標題欄
      Text("隨機密碼生成")
        .width('100%')// 設定寬度為100%
        .height(54)// 設定高度為54
        .fontSize(18)// 設定字型大小
        .fontWeight(600)// 設定字型粗細
        .backgroundColor(Color.White)// 設定背景顏色
        .textAlign(TextAlign.Center)// 設定文字居中對齊
        .fontColor(this.fontColor); // 設定字型顏色

      // 密碼長度設定部分
      Column() {
        Row() {
          Text(`密碼長度:`)// 密碼長度標籤
            .fontWeight(600)
            .fontSize(18)
            .fontColor(this.fontColor);
          Text(`${this.passwordLength}`)// 顯示當前密碼長度
            .fontWeight(600)
            .fontSize(18)
            .fontColor(this.primaryColor);
        }
        .margin({ top: `${this.baseSpacing}lpx`, left: `${this.baseSpacing}lpx` });

        // 滑動條設定密碼長度
        Row() {
          Text('4').fontColor(this.fontColor).width(20);
          Slider({
            value: this.passwordLength, // 當前值
            min: 4, // 最小值
            max: 32, // 最大值
            style: SliderStyle.InSet // 滑動條樣式
          })
            .layoutWeight(1)// 佈局權重
            .blockColor(Color.White)// 滑塊顏色
            .trackColor('#EBEBEB')// 軌道顏色
            .trackThickness(30)// 軌道厚度
            .blockSize({ width: 55, height: 55 })// 滑塊大小
            .selectedColor(this.primaryColor)// 選中顏色
            .onChange((value: number, mode: SliderChangeMode) => {
              this.passwordLength = value; // 更新密碼長度
              console.info('value:' + value + 'mode' + mode.toString); // 列印日誌
            });
          Text('32').fontColor(this.fontColor).width(20);
        }.margin({
          left: `${this.baseSpacing}lpx`,
          right: `${this.baseSpacing}lpx`,
          top: `${this.baseSpacing}lpx`,
        });

        // 選項設定部分
        Text('選項')
          .fontWeight(600)
          .fontSize(18)
          .fontColor(this.fontColor)
          .margin({ left: `${this.baseSpacing}lpx`, top: `${this.baseSpacing}lpx`, bottom: `${this.baseSpacing}lpx` });

        // 動態生成每個選項的UI元素
        ForEach(this.options, (option: PasswordOption, index: number) => {
          Row() {
            Text(option.name)// 選項名稱
              .fontWeight(400)
              .fontSize(16)
              .fontColor(this.fontColor)
              .layoutWeight(1);
            Toggle({ type: ToggleType.Switch, isOn: option.selected })// 切換按鈕
              .width('100lpx')
              .height('50lpx')
              .enabled(option.enabled)// 是否啟用切換
              .selectedColor(this.primaryColor)
              .onChange((isOn: boolean) => {
                option.selected = isOn; // 更新選項狀態
                this.checkOptionsSelection(); // 檢查選項選擇狀態
              });
          }
          .width('100%')
          .padding({
            left: `${this.baseSpacing}lpx`,
            right: `${this.baseSpacing}lpx`,
            top: `${this.baseSpacing / 3}lpx`,
            bottom: `${this.baseSpacing / 3}lpx`
          })
          .hitTestBehavior(HitTestMode.Block)
          .onClick(() => {
            if (option.enabled) {
              option.selected = !option.selected; // 切換選項狀態
            }
          });
        });

        // 生成密碼按鈕
        Text('生成密碼')
          .fontColor(Color.White)
          .backgroundColor(this.primaryColor)
          .height(54)
          .textAlign(TextAlign.Center)
          .borderRadius(10)
          .fontSize(18)
          .width(`${650 - this.baseSpacing * 2}lpx`)
          .margin({
            top: `${this.baseSpacing}lpx`,
            left: `${this.baseSpacing}lpx`,
            right: `${this.baseSpacing}lpx`,
            bottom: `${this.baseSpacing}lpx`
          })
          .clickEffect({ level: ClickEffectLevel.HEAVY, scale: 0.8 })// 點選效果
          .onClick(() => {
            this.generatePassword(); // 生成密碼
          });
      }
      .width('650lpx')
      .margin({ top: 20 })
      .backgroundColor(Color.White)
      .borderRadius(10)
      .alignItems(HorizontalAlign.Start);

      // 顯示生成的密碼
      Column() {
        Text(`密碼結果:`)
          .fontWeight(600)
          .fontSize(18)
          .fontColor(this.fontColor)
          .margin({
            top: `${this.baseSpacing}lpx`,
            left: `${this.baseSpacing}lpx`,
          });
        Text(`${this.generatedPassword}`)// 顯示生成的密碼
          .width('650lpx')
          .fontColor(this.primaryColor)
          .fontSize(18)
          .textAlign(TextAlign.Center)
          .padding({ left: 5, right: 5 })
          .margin({
            top: `${this.baseSpacing / 3}lpx`
          });

        // 複製按鈕
        Text('複製')
          .enabled(this.generatedPassword ? true : false)// 只有生成了密碼才啟用複製按鈕
          .fontColor(Color.White)
          .backgroundColor(this.primaryColor)
          .height(54)
          .textAlign(TextAlign.Center)
          .borderRadius(10)
          .fontSize(18)
          .width(`${650 - this.baseSpacing * 2}lpx`)
          .margin({
            top: `${this.baseSpacing}lpx`,
            left: `${this.baseSpacing}lpx`,
            right: `${this.baseSpacing}lpx`,
            bottom: `${this.baseSpacing}lpx`
          })
          .clickEffect({ level: ClickEffectLevel.HEAVY, scale: 0.8 })
          .onClick(() => {
            this.copyToClipboard(this.generatedPassword); // 複製密碼
          });
      }
      .width('650lpx')
      .backgroundColor(Color.White)
      .borderRadius(10)
      .margin({ top: `${this.baseSpacing}lpx` })
      .alignItems(HorizontalAlign.Start);
    }
    .height('100%')
    .width('100%')
    .backgroundColor("#f2f3f5"); // 頁面背景顏色
  }
}

  

相關文章