2 Nam Trung Yên - Hà Nội +84.914.799.931 app@appteng.app

Phát triển giao diện ứng dụng của riêng bạn

Hướng dẫn tại đây bao gồm mọi thứ cần thiết để bắt đầu Thiết kế giao diện ứng dụng của riêng bạn vận hành trên nền tảng AppTeng, bao gồm cấu trúc để cập nhật thường xuyên và đóng gói giao diện.

Giao diện ứng dụng là gì ?

Giao diện ứng dụng là các hiển thị mặt ngoài của ứng dụng, nơi người dùng sẽ có cảm nhận đầu tiên về các vị trí Module, Tính năng, Màu sắc, Văn bản.....trong ứng dụng của bạn. Giao diện hợp lý, màu sắc bắt mắt, trang nhã sẽ giúp ứng dụng của bạn thu hút người dùng hơn rất nhiều.

Giao diện còn mang lại sự thoải mái, tiện nghi trong các trải nghiệm ứng dụng cho người dùng ứng dụng của bạn.

Kiến thức bạn cần có:

- Ý tưởng về giao diện ứng dụng của riêng bạn.

- Kiến thức về HTML - CSS - JavaScrip

Bắt đầu thôi.

Trước hết, bạn cần xác định 2 tên gọi cho Gói và Code (giới hạn trong 50 ký tự).

Ví dụ:

- Tên gói: GiaodienA

- Tên Code: giao_dien_a

Hai tên gọi này nhằm đảm bảo giao diện của riêng bạn sẽ không xung đột với các giao diện khác đã có sẵn trên hệ thống của chúng tôi.

Lưu ý: Giao diện của bạn phải tương thích với tất cả độ phân giải của các thiết bị di động (Smartphone và Máy tính bảng) và điều hướng của các thiết bị.

Dưới đây là cấu trúc đầy đủ và tối thiểu cần phải có cho giao diện:

GiaodienA.zip
├─ resources
│  ├─ db
│  │  └─ data
│  │     └─ giao_dien_a.php
│  ├─ design
│  │  └─ desktop
│  │     ├─ flat /** Flat design */
│  │     │  └─ images
│  │     │     └─ customization
│  │     │        └─ layout
│  │     │           └─ homepage
│  │     │              └─ giao_dien_a.png
│  │     └─ appteng /** AppTeng design */
│  │        └─ images
│  │           └─ customization
│  │              └─ layout
│  │                 └─ homepage
│  │                    └─ giao_dien_a.png
│  └─ var
│     └─ apps
│        └─ modules
│           └─ layout
│              └─ home
│                 └─ giao_dien_a
│                    ├─ hooks.js
│                    ├─ style.css
│                    └─ view.html
├─ init.php
├─ package.json
└─ [...]

package.json

Các package.json được sử dụng trong quá trình cài đặt để truy xuất các yêu cầu, tác vụ hoạt động trong quá trình Cài đặt / Cập nhật / Nâng cấp giao diện ứng dụng của riêng bạn.

{
  "name": "GiaodienA",
  "description": "Mô tả GiaodienA",
  "type": "layout",
  "version": "1.0",
  "release_note": {
    "url": "https://appteng.com/giao-dien-a.html",
    "show": true
  },
  "dependencies": {
    "system": {
      "type": "appteng",
      "version": "5.9.6"
    }
  }
}

 

Trường Bắt buộc hoặc Không Mô tả
name Bắt buộc Tên gói giao diện (không chèn khoảng trắng và số)
description Bắt buộc Mô tả giao diện
type Bắt buộc Bắt buộc nhập layout
version Bắt buộc Phiên bản giao diện cho các cập nhật trong tương lai.
release_note Không url: Liên kết tới mô tả HTML phương thức hợp lệ khi cài đặt / show (true/false): để bắt buộc hiển thị hoặc không.
dependencies Bắt buộc version*: tối thiểu 5.9.6 type: appteng (tối thiểu khi cài đặt)

 Lưu ý: Phiên bản hiện tại của AppTeng là 5.9.6

Bootstrap

Lưu ý: Chúng tôi sẽ không còn sử dụng bootstrap.php khi AppTeng phát triển tới phiên bản 7.0

AppTeng sử dụng bootstrap.php cho việc cài đặt, cập nhật và vận hành giao diện ứng dụng: 

<?php
/**
 * @deprecated từ AppTeng 7.0, thực hiện theo Init.
 */
class GiaodienA_Bootstrap {

    public static function init($bootstrap) {
        # Đăng ký
        # Đường dẫn cho giao diện ứng dụng phải là "/appteng/local/modules/GiaodienA/resources/var/apps/"
        AppTeng_Assets::registerAssets(
            "GiaodienA", 
            "/appteng/local/modules/GiaodienA/resources/var/apps/"
        );

        # Liên kết javascript tới index.html
        # Các đường dẫn này cần chính xác so với các đường dẫn trước đó:
        # "/appteng/local/modules/GiaodienA/resources/var/apps/"
        AppTeng_Assets::addJavascripts(array(
            "modules/layout/home/giao_dien_a/hooks.js",
        ));

        # Liên kết stylesheets tới index.html
        # Các đường dẫn này cần chính xác so với các đường dẫn trước đó:
        # "/appteng/local/modules/GiaodienA/resources/var/apps/"
        AppTeng_Assets::addStylesheets(array(
            "modules/layout/home/giao_dien_a/style.css",
        ));

        # Đăng ký và Tuỳ chỉnh cho Tuỳ chọn Giao diện
        AppTeng_Feature::registerLayoutOptionsCallbacks("giao_dien_a", "GiaodienA_Form_GiaodienA", function($datas) {
            $options = array();

            return $options;
        });
    }
}

Init

- Cú pháp init mới sẽ có sẵn từ AppTeng 7.0, cú pháp mới này nhằm tránh xung đột với các lớp bootstrap đã tồn tại trước đó.

- Từ AppTeng 7.0 sẽ sử dụng init.php cho việc cài đặt, cập nhật và vận hành giao diện ứng dụng:

- Cú pháp và phương pháp được sử dụng bên trong Init vẫn giữ nguyên như với các file bootstrap trước đó.

<?php

$init = function($bootstrap) {
    # Đăng ký
    # Đường dẫn cho giao diện ứng dụng phải là "/appteng/local/modules/GiaodienA/resources/var/apps/"
    AppTeng_Assets::registerAssets(
        "MyAwesomeLayout", 
        "/appteng/local/modules/GiaodienA/resources/var/apps/"
    );

    # Liên kết javascript tới index.html
    # Các đường dẫn này cần chính xác so với các đường dẫn trước đó:
    # "/appteng/local/modules/GiaodienA/resources/var/apps/"
    AppTeng_Assets::addJavascripts(array(
        "modules/layout/home/giao_dien_a/hooks.js",
    ));

    # Liên kết stylesheets tới index.html
    # Các đường dẫn này cần chính xác so với các đường dẫn trước đó:
    # "/appteng/local/modules/GiaodienA/resources/var/apps/"
    AppTeng_Assets::addStylesheets(array(
        "modules/layout/home/giao_dien_a/style.css",
    ));

    # Đăng ký và Tuỳ chỉnh cho Tuỳ chọn Giao diện
    AppTeng_Feature::registerLayoutOptionsCallbacks("giao_dien_a", "GiaodienA_Form_GiaodienA", function($datas) {
        $options = array();

        return $options;
    });
};

$bootstrap sẽ tham chiếu đến Zend Bootstrap nếu bạn cần phải liên kết nó. 

Icon và Kích thước Hình ảnh

Nếu giao diện riêng của bạn cần hình ảnh với các tỷ lệ tùy chỉnh để giới thiệu tính năng, bạn có thể thực hiện chức năng gọi lại trong file init.php như dưới đây:

AppTeng_Feature::registerRatioCallback("giao_dien_a", function($position) {
    $sizes = array(
        "width" => 800,
        "height" => 400,
    );

    return $sizes;
});

giao_dien-a: Là tên code giao diện ứng dụng của bạn.

$position: là vị trí của hình ảnh hoặc icon, như vậy bạn có thể có các kích thước khác nhau cho các vị trí khác nhau trong giao diện của riêng bạn.

Dữ liệu:

- Các file sau sẽ được lưu trữ ngay lập tức vào Cơ sở dữ liệu tại thời điểm Tạo hoặc Cập nhật giao diện ứng dụng.

- Nếu muốn thay đổi các dữ liệu trong quá trình cập nhật ứng dụng, bạn sẽ cần thay đổi các giá trị tại file này.

Lưu ý quan trọng: Tên code giao diện ứng dụng không được phép thay đổi, vì như thế sẽ khiến hệ thống tạo giao diện ứng dụng khác.

<?php
/** Giao diện ứng dụng của riêng bạn với AppTeng */
$default_options = AppTeng_Json::encode(array(
    "borders" => "border-right",
    "borders" => "border-left",
    "borders" => "border-top",
    "label" => "label-left",
    "textTransform" => "title-lowcase",
));

# GiaodienA
$datas = array(
    'name'                       => 'GiaodienA',
    'visibility'                 => Application_Model_Layout_Homepage::VISIBILITY_HOMEPAGE,
    'code'                       => 'giao_dien_a',
    /** Hình ảnh giới thiệu tại [...]/resources/design/desktop/[flat|appteng]/images/  */
    'preview'                    => '/customization/layout/homepage/giao_dien_a.png',
    'use_more_button'            => 1,
    'use_horizontal_scroll'      => 0,
    'number_of_displayed_icons'  => 8,
    'position'                   => "bottom",
    "order"                      => 1200,
    "is_active"                  => 1,
    "use_subtitle"               => 1,
    "use_homepage_slider"        => 1,
    "options"                    => $default_options,
);

$layout = new Application_Model_Layout_Homepage();
$layout
    ->setData($datas)
    ->insertOrUpdate(array("code"));

# Sao chép nội dung tại thời điểm cài đặt
# đường dẫn hệ thống tại `AppTeng_Assets::registerAssets`
AppTeng_Assets::copyAssets("/appteng/local/modules/GiaodienA/resources/var/apps/"); 

Các thông tin:

Trường Bắt buộc hoặc Không Mô tả
 name  Bắt buộc  Tên gói giao diện ứng dụng của bạn: Giao diện A
 visibility   Bắt buộc  VISIBILITY_HOMEPAGE, VISIBILITY_ALWAYS, VISIBILITY_TOGGLE
 code  Bắt buộc   Tên code giao diện ứng dụng của bạn: giao_dien_a
 preview Bắt buộc   Hình ảnh giới thiệu giao diện ứng dụng
 use_more_button  Bắt buộc  Tính năng hoạt động của giao diện, do vậy bắt buộc có nút more_button
 use_horizontal_scroll Bắt buộc   -
 number_of_displayed_icons Bắt buộc   Số lượng tính năng được sử dụng với use_more_button hiển thị trong features.overview.options
 position Bắt buộc   Vị trí các menu: bottom, left, right (phía dưới, bên phải, bên trái)
 order  Bắt buộc   Thứ tự giao diện ứng dụng trong Bảng danh sách (đặt > 1000)
 is_active Bắt buộc Đặt là 1
 use_subtitle Bắt buộc Tiêu đề nhỏ của giao diện ứng dụng. 
 use_homepage_slider Không Giao diện ứng dụng có được thiết kế cho phép hoạt động với homepageslider không.
 options Không Tuỳ chọn mặc định cho giao diện ứng dụng.

Các tuỳ chọn hiển thị (Visibility)

VISOMITY HOMEPAGE: Chỉ hiển thị giao diện bên ngoài ứng dụng.

VISIBILITY ALWAYS:  Giao diện sẽ được hiển thị ở khắp mọi nơi (nên cân nhắc khi sử dụng giao diện này với ứng dụng có sử dụng Module Âm thanh)

VISIBILITY_TOGGLE: Giao diện với thanh Menu chuyển đổi các cạnh bên.

Cấu trúc giao diện

Giao diện riêng của bạn nói chung sẽ bao gồm 3 hoặc 4 file:

- view.html: Hiển thị giao diện chính

- style.css: Tất cả các css trong giao diện của bạn.

- hooks.js: File này chứa tất cả các liên kết giúp cho Ionic biết những gì cần tải và cách sắp xếp các tính năng.

- modal.html (nếu cần thiết): Sử dụng file này nếu cần phải tùy chỉnh riêng. Nếu không bạn nên sử dụng một trong các chế độ có sẵn của chúng tôi.

 1. File view.html:

<div class="layout giao_dien_a">
    <ul id="container">
        <li class="item homepage-custom"
            ng-class="{ 'background-transparent' : tabbar_is_transparent, 'no-border' : tabbar_is_transparent }"
            ng-show="tabbar_is_visible"
            tabbar-items
            ng-repeat="feature in features.overview.options"
            option="feature"
            go-to-url="goTo(feature);">

            <img ng-src="{{ feature.icon_url }}" />
            <h2>{{ feature.name }}</h2>
            <p ng-if="feature.subtitle">{{ feature.subtitle }}</p>
        </li>
    </ul>
</div> 

Giao diện chính của ứng dụng (trang chủ) của bạn cần được thêm vào trong thẻ <div> với ít nhất hai lớp đầu tiên là layout và giao_dien_a

Các thông số:

Phần tử Bắt buộc hay Không Mô tả
tabbar-items Bắt buộc  Điều hướng click tới các phần tử
option="feature" Bắt buộc Tuỳ chọn vị trí hiện tại
go-to-url="goTo(feature);" Bắt buộc Tuỳ chọn này sẽ không còn được hỗ trợ khi phát hành AppTeng 7.0
ng-show="tabbar_is_visible" Bắt buộc Điều kiện sử dụng khi giao diện luôn hiển thị.
ng-class="[...]" Bắt buộc Được sử dụng với tuỳ chọn trong TAB Màu sắc > Trang chủ > Trong suốt (giá trị 0) để xoá đường viền và nền.

 Các phần tử cũng sử dụng các lớp CSS để liên kết tới màu sắc của giao diện khi ứng dụng được tuỳ chọn sử dụng màu cụ thể:

 

Lớp Bắt buộc hoặc Không
item Bắt buộc
homepage-custom Bắt buộc

2. File style.css

CSS dưới đây là ví dụ được đưa ra với khung giao diện cơ bản với giao_dien_a

.layout.giao_dien_a {
    position: absolute;
    bottom: 5vh;
    width: 100%;
}

.layout.giao_dien_a li.item {
    height: 28px;
    width: 150px;
    border-radius: 0 14px 14px 0;
    padding: 0;
    -o-transform: rotate(-7deg);
    -ms-transform: rotate(-7deg);
    -webkit-transform: rotate(-7deg);
    transform: rotate(-7deg);
    margin-left: -4vw;
    margin-top: 1px;
    border-width: 0px;
}

.layout.giao_dien_a li.item img {
    float: left;
    height: 80%;
    margin: 2% 0 0 10%;
}

.layout.giao_dien_a li.item h2 {
    float: left;
}

3. File hooks.js

File hooks.js là dịch vụ Angular, được nạp khi sử dụng các tùy chọn giao diện, cho phép bạn thao tác với các tính năng.

/**
 *
 * Ví dụ cho GiaodienA
 *
 * Tất cả các chức năng sau được yêu cầu để giao diện hoạt động
 */
App.service('giao_dien_a', function ($rootScope, HomepageLayout) {

    var service = {};

    var _features;

    /**
     * Phải trả lại kết quả là mẫu hợp lệ
     *
     * @returns {string}
     */
    service.getTemplate = function() {
        return "modules/layout/home/giao_dien_a/view.html";
    };

    /**
     * Phải trả lại kết quả là mẫu hợp lệ
     *
     * @returns {string}
     */
    service.getModalTemplate = function() {
        return "templates/home/l10/modal.html";
    };

    /**
     * onResize được sử dụng cho css/js khi định hướng trả kết quả thay đổi.
     */
    service.onResize = function() {
        /** Giữ nguyên cái này */
    };

    /**
     * Thao tác với tính năng của phần tử
     *
     * Ví dụ:
     * - Có thể sắp xếp lại các tính năng.
     * - Có thể push/place với "more_button"
     *
     * @param features
     * @param more_button
     * @returns {*}
     */
    service.features = function(features, more_button) {
        /** Lưu giữ bản sao các tính năng trong liên kết */
        _features = features;

        /** Đặt têm nút ở cuối */
        features.overview.options.push(more_button);

        return features;
    };

    return service;

});

Các thông số

 Hàm Mô tả 
 service.getTemplate  Trả lại đường dẫn đến File giao diện
 service.getModalTemplate  Trả lại đường dẫn đến File modal.html
 service.onResize  Được sử dụng khi điều hướng thiết bị thay đổi và trang chủ được hiển thị liên tục.
 service.features  Được sử dụng khi tác với các tính năng.

 Lưu ý: Modal mặc định là templates/home/l10/modal.html & templates/home/modal/view.html

Các đối tượng có sẵn trong dịch vụ Liên kết hook

features

"features": {
  "layoutCode": "giao_dien_a",
  /** các tính năng trong ứng dụng của bạn, xem [Option](#option) */
  "options": [...]
}

Các tính năng được xác định bởi limit

features.overview

"features.overview": {
  "layoutCode": "my_awesome_layout",
  /** an array of every features in your application see [Option](#option) */
  "options": [...]
}

Tuỳ chọn

Ví dụ về tùy chọn / tính năng cho thông tin

{
  "value_id": "6",
  "id": 6,
  "layout_id": "1",
  "code": "calendar",
  "name": "Calendar",
  "is_active": "1",
  "url": "https://appteng.com/57c7f8764a65a/event/mobile_list/index/value_id/6",
  "path": "/57c7f8764a65a/event/mobile_list/index/value_id/6",
  "icon_url": "https://appteng.com/var/cache/images/e9dcc367471a70a23261056b1129a198.png",
  "icon_is_colorable": "1",
  "is_locked": null,
  "is_link": false,
  "use_my_account": "0",
  "use_nickname": "0",
  "use_ranking": "0",
  "custom_fields": [],
  "position": "5"
}

Các dịch vụ khác: service.features = function(features, more_button)

Trong ví dụ dưới đây, chúng tôi đặt more_button ở vị trí thứ ba trong features.overview.options

[...]
    /**
     * Ví dụ với giao diện có 5 tính năng (bao gồm more_button) & và modal
     */
    service.features = function(features, more_button) {
        if(features.overview.options >= 4) {

            var third_option = features.overview.options[2];
            var fourth_option = features.overview.options[3];

            /** Đặt thêm nút ở vị trí thứ ba (vị trí giữa giao diện) */
            features.overview.options[2] = more_button;
            features.overview.options[3] = third_option;
            features.overview.options[4] = fourth_option;

            /** Loại bỏ lựa chọn thứ 4 cho modal */
            features.options = features.options.slice(4, features.options.length);

        } else {
            features.overview.options.push(more_button);
        }

        return features;
    };
[...]

Ví dụ tiếp theo dưới đây được sử dụng để tạo các vị trí khối cho đối tượng:

[...]
    service.features = function(features, more_button) {
        _features = features;

        var more_options = features.options.slice(12);
        var chunks = new Array();
        var i, j, temparray, chunk = 2;
        for (i = 0, j = more_options.length; i < j; i += chunk) {
            temparray = more_options.slice(i, i + chunk);
            chunks.push(temparray);
        }
        features.chunks = chunks;

        return features;
    };
[...]

Tuỳ chọn giao diện

Nếu muốn thêm tùy chọn tùy chỉnh vào giao diện của riêng bạn, bạn phải tạo Form tuỳ chọn và thêm nó trong init

GiaodienA.zip
└─ Form
   └─ MyAwesomeLayout.php

Liên kết (hook) init

# Register a custom form for the Layout Options
Siberian_Feature::registerLayoutOptionsCallbacks("my_awesome_layout", "MyAwesomeLayout_Form_MyAwesomeLayout", function($datas) {
    $options = array();

    return $options;
});

Form tuỳ chọn

Dưới đây là một ví dụ đơn giản về Form tuỳ chọn có thể xem .

(Ảnh)

Dưới đây là code cho ví dụ trên:

<?php

class GiaodienA_Form_GiaodienA extends AppTeng_Form_Options_Abstract {


    public function init() {
        parent::init();

        /** Liên kết với tạo Form */
        self::addClass("create", $this);
        self::addClass("form-layout-options", $this);

        $label = $this->addSimpleSelect("label", __("Title position"), array(
            "label-left" => __("Left"),
            "label-right" => __("Right"),
        ));

        $textTransform = $this->addSimpleSelect("textTransform", __("Title case"), array(
            "title-lowcase" => __("Lower case"),
            "title-uppercase" => __("Upper case"),
        ));

        $borders = $this->addSimpleMultiCheckbox("borders", __("Display Borders"), array(
            "border-left" => __("Left"),
            "border-right" => __("Right"),
            "border-top" => __("Top"),
            "border-bottom" => __("Bottom"),
        ));

        $this->addNav("submit", __("Save"), false, false);

        self::addClass("btn-sm", $this->getDisplayGroup("submit")->getElement(__("Save")));

    }

}

Form của bạn phải kế thừa lớp AppTeng_Form_Options_Abstract

Sau đó bạn có thể thêm vào các tuỳ chọn của bạn.

style.css

Ví dụ về view.html & style.css

Ở đây trong style.css chúng ta đang sử dụng các lớp có cùng tên với các giá trị Form bên dưới, đây là một cách để thực hiện nó.

[...]
.layout.giao_dien_a.label-right {
    text-align: right;
}
.layout.giao_dien_a.label-left {
    text-align: left;
}

.layout.giao_dien_a.title-lowcase {
    text-transform: inherit;
}
.layout.giao_dien_a.title-uppercase {
    text-transform: uppercase;
}
[...]

view.html

Và sau đó với view.html

<div class="layout giao_dien_a">
    <ion-scroll direction="y" scrollbar-y="false" class="scroll-view ionic-scroll">
        <div ng-repeat="feature in features.options">
            <a tabbar-items class="item item-avatar item-avatar-square homepage-custom border-custom {{ features.layoutOptions.borders.join(' ') }}" option="feature" go-to-url="goTo(feature)" ng-class="{ 'no-border': tabbar_is_transparent }">
                <img ng-src="{{ feature.icon_url }}" />
                <h2 class="{{ features.layoutOptions.label+' '+features.layoutOptions.textTransform }}">{{ feature.name }}</h2>
                <span ng-if="feature.code == 'push_notification' && push_badge" class="badge badge-assertive">{{ push_badge }}</span>
            </a>
        </div>
    </ion-scroll>
</div>

Ở đây chúng ta đang sử dụng một javascript "join" đơn giản để nối tất cả các tùy chọn có cùng tên lớp.

Đối với đa lựa chọn

{{ features.layoutOptions.borders.join(' ') }}

Và đối với các lựa chọn đơn giản, chúng tôi chỉ lặp lại lớp hoặc các lớp

{{ features.layoutOptions.label+' '+features.layoutOptions.textTransform }}

Sử dụng các tuỳ chọn nâng cao

Trong giao diện swiper, chúng tôi đang sử dụng các tùy chọn để cấu hình đối tượng javascript Slider

Dưới đây là ví dụ về cách chúng tôi thực hiện điều đó.

Hãy chú ý trong File hooks.js, trong hàm onResize

/**
 * onResize được sử dụng cho css/js khi định hướng trả kết quả thay đổi.
 */
service.onResize = function() {

    var options = _features.layoutOptions;
    /** Giữ nguyên cái này */
    var time_out = ($rootScope.isOverview) ? 1000 : 200;

    $timeout(function() {
        if(swipe_instance != null && typeof swipe_instance.destroy == "function") {
            swipe_instance.destroy(true, false);
        }
        swipe_instance = new Swiper('.layout.layout_siberian_swipe .swiper-container', {
            direction: 'vertical',
            loop: (options.loop == "1") ? true : false,
            effect: 'coverflow',
            centeredSlides: true,
            initialSlide: (options.backcurrent == "1") ? service.last_index : 0,
            slidesPerView: 'auto',
            loopedSlides: 6,
            coverflow: {
                rotate: options.angle,
                stretch: options.stretch,
                depth: options.depth,
                modifier: 1,
                slideShadows : false
            }
        });

    }, time_out);
};

Chúng tôi đã lưu _features trong các tính năng, và do đó có thể sử dụng nó.

Tuy nhiên bạn cũng có thể truy cập các tuỳ chọn cho giao diện ở đây:

HomepageLayout.layoutOptions

Đóng gói giao diện ứng dụng

Khi bạn đã hoàn tất giao diện riêng của bạn, đã đến lúc đóng gói!

Nén zip tất cả các file trong thư mục gốc giao diện của bạn và bạn đã hoàn tất!

Gửi File nén .zip cho chúng tôi tới This email address is being protected from spambots. You need JavaScript enabled to view it.. Ban kỹ thuật AppTeng sẽ kiểm tra sự phù hợp của nó trên nền tảng thử nghiệm, nếu đạt tiêu chuẩn, chúng tôi sẽ kích hoạt nó cho bạn.