From cc96979c3f24b8b11c96de40a03433ca1a6b6908 Mon Sep 17 00:00:00 2001
From: liangzai <2440983361@qq.com>
Date: Mon, 13 Jan 2025 19:31:32 +0800
Subject: [PATCH] temp
---
.hbuilderx/launch.json | 9 +
index.html | 43 +-
manifest.config.ts | 2 +-
native-js使用教程.txt | 1658 +++++++++++++++++
pages.config.ts | 2 +-
src/App.vue | 5 +-
src/app.scss | 8 +
src/components.d.ts | 4 +
src/components/WebviewPage.vue | 44 +-
src/layouts/home.vue | 7 +-
src/layouts/page-bak.vue | 20 -
src/layouts/page.vue | 34 +-
src/manifest.json | 7 +-
src/pages.json | 49 +-
src/pages/ai.vue | 76 +-
src/pages/complaint.vue | 17 +
src/pages/example.vue | 21 +-
src/pages/index.vue | 219 ++-
src/pages/inquire.vue | 10 +-
src/pages/list_lawsuit.vue | 9 +-
src/pages/list_marriage.vue | 9 +-
src/pages/list_risk.vue | 9 +-
src/pages/list_verify.vue | 9 +-
src/pages/me.vue | 94 +-
src/pages/privacyPolicy.vue | 9 +-
src/pages/report.vue | 9 +-
src/pages/result.vue | 186 --
src/pages/service.vue | 17 +
src/pages/userAgreement.vue | 9 +-
src/plugins/urlLauncher/index.js | 17 +
.../urlLauncher/ios/urlLauncherPlugin.h | 7 +
.../urlLauncher/ios/urlLauncherPlugin.m | 28 +
src/uni-pages.d.ts | 3 +-
src/utils/request.js | 6 +-
vite.config.ts | 5 +
35 files changed, 2315 insertions(+), 346 deletions(-)
create mode 100644 .hbuilderx/launch.json
create mode 100644 native-js使用教程.txt
delete mode 100644 src/layouts/page-bak.vue
create mode 100644 src/pages/complaint.vue
delete mode 100644 src/pages/result.vue
create mode 100644 src/pages/service.vue
create mode 100644 src/plugins/urlLauncher/index.js
create mode 100644 src/plugins/urlLauncher/ios/urlLauncherPlugin.h
create mode 100644 src/plugins/urlLauncher/ios/urlLauncherPlugin.m
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..15db785
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,9 @@
+{
+ "version" : "1.0",
+ "configurations" : [
+ {
+ "playground" : "standard",
+ "type" : "uni-app:app-ios"
+ }
+ ]
+}
diff --git a/index.html b/index.html
index f4960b1..8af8247 100644
--- a/index.html
+++ b/index.html
@@ -1,21 +1,28 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ 全能查 - 婚恋评估、司法涉诉查询、婚姻状态、判决书查询工具
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/manifest.config.ts b/manifest.config.ts
index 4e5c4eb..52050ca 100644
--- a/manifest.config.ts
+++ b/manifest.config.ts
@@ -1,7 +1,7 @@
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
export default defineManifestConfig({
- 'name': 'qnc-app',
+ 'name': '全能查-司法涉诉_婚恋信息_企业查询平台-学宇思科技',
'appid': '__UNI__CC3DA09',
'description': '',
'versionName': '1.0.0',
diff --git a/native-js使用教程.txt b/native-js使用教程.txt
new file mode 100644
index 0000000..020d580
--- /dev/null
+++ b/native-js使用教程.txt
@@ -0,0 +1,1658 @@
+概述
+Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。 如果说Node.js把js扩展到服务器世界,那么Native.js则把js扩展到手机App的原生世界。 HTML/JS/Css全部语法只有7万多,而原生语法有几十万,Native.js大幅提升了HTML5的能力。 NJS突破了浏览器的功能限制,也不再需要像Hybrid那样由原生语言开发插件才能补足浏览器欠缺的功能。 NJS编写的代码,最终需要在HBuilder里打包发行为App安装包,或者在支持Native.js技术的浏览器里运行。目前Native.js技术不能在普通手机浏览器里直接运行。
+
+NJS大幅扩展了HTML5的能力范围,原本只有原生或Hybrid App的原生插件才能实现的功能如今可以使用JS实现。
+NJS大幅提升了App开发效率,将iOS、Android、Web的3个工程师组队才能完成的App,变为1个web工程师就搞定。
+NJS不再需要配置原生开发和编译环境,调试、打包均在HBuilder里进行。没有mac和xcode一样可以开发iOS应用。
+如果不熟悉原生API也没关系,我们汇总了很多NJS的代码示例,复制粘贴就可以用。http://ask.dcloud.net.cn/article/114
+再次强调,Native.js不是一个js库,不需要下载引入到页面的script中,也不像nodejs那样有单独的运行环境,Native.js的运行环境是集成在5+runtime里的,使用HBuilder打包的app或流应用都可以直接使用Native.js。
+
+注意事项:
+Uni-app不支持Native.js执行UI相关操作的API调用及webview相关API调用。将失效无法正常使用。Uni-app不推荐使用Native.js
+
+技术要求
+由于NJS是直接调用Native API,需要对Native API有一定了解,知道所需要的功能调用了哪些原生API,能看懂原生代码并参考原生代码修改为JS代码。 否则只能直接copy别人写好的NJS代码。
+
+开始使用
+判断平台
+Native API具有平台依赖性,所以需要通过以下方式判断当前的运行平台:
+
+function judgePlatform(){
+ switch ( plus.os.name ) {
+ case "Android":
+ // Android平台: plus.android.*
+ break;
+ case "iOS":
+ // iOS平台: plus.ios.*
+ break;
+ default:
+ // 其它平台
+ break;
+ }
+}
+复制代码
+类型转换
+在NJS中调用Native API或从Native API返回数据到NJS时会自动转换数据类型。
+
+类型转换表
+类型 Objective-C Java JavaScript
+基本数据 byte/short/int/long/float/double/... byte/short/int/long/float/double/... Number
+字符 char char String
+字符串 NSString/@"" String/"" String
+数组 @[1,2,3]/NSArray new XXX[] InstanceObject
+类 @interface class ClassObject
+对象(实例) * * InstanceObject
+空对象 nil null null
+其它 Protocol Interface Object(JSON)
+其他转换
+Android原生应用的主Activity对象 转为plus.android.runtimeMainActivity() Android的主Activity对象是启动应用时自动创建的,不是代码创建,此时通过plus.android.runtimeMainActivity()方法获取该Activity对象
+Objective-C方法冒号剔除 [pos setPositionX:(int)x Y:(int)y;] 转为 pos.setPositionXY(x,y); OC语法中方法的定义格式为: “(返回值类型) 函数名: (参数1类型) 形参1 参数2名称: (参数2类型) 形参2” 方法的完整名称为: “函数名:参数2名称:”。 如:“(void)setPositionX:(int)x Y:(int)y;”,方法的完整名称为“setPositionX:Y:”,调用时语法为:“[pos setPositionX:x Y:y];”。 在JS语法中函数名称不能包含“:”字符,所以OC对象的方法名映射成NJS对象方法名时将其中的“:”字符自动删除,上面方法名映射为“setPositionXY”,在NJS调用的语法为:“pos.setPositionXY(x,y);”。
+文件路径转换 Web开发里使用的image/1.png是该web工程的相对路径,而原生API中经常需要使用绝对路径,比如/sdcard/apptest/image/1.png,此时使用这个扩展方法来完成转换:plus.io.convertLocalFileSystemURL("image/1.png")
+概念
+类对象
+由于JavaScript中本身没有类的概念,为了使用Native API层的类,在NJS中引入了类对象(ClassObject)的概念,用于对Native中的类进行操作,如创建类的实例对象、访问类的静态属性、调用类的静态方法等。其原型如下:
+
+Interface ClassObject {
+ function Object plusGetAttribute( String name );
+ function void plusSetAttribute( String name, Object value );
+}
+复制代码
+获取类对象 在iOS平台我们可以通过plus.ios.importClass(name)方法导入类对象,参数name为类的名称;在Android平台我们可以通过plus.android.importClass(name)方法导入类对象,其参数name为类的名称,必须包含完整的命名空间。
+
+示例:
+
+// iOS平台导入NSNotificationCenter类
+var NSNotificationCenter = plus.ios.importClass("NSNotificationCenter");
+
+// Android平台导入Intent类
+var Intent = plus.android.importClass("android.content.Intent");
+复制代码
+获取类对象后,可以通过类对象“.”操作符获取类的静态常量属性、调用类的静态方法,类的静态非常量属性需通过plusGetAttribute、plusSetAttribute方法操作。
+
+实例对象
+在JavaScript中,所有对象都是Object,为了操作Native层类的实例对象,在NJS中引入了实例对象(InstanceObject)的概念,用于对Native中的对象进行操作,如操作对象的属性、调用对象的方法等。其原型如下:
+
+Interface InstanceObject {
+ function Object plusGetAttribute( String name );
+ function void plusSetAttribute( String name, Object value );
+}
+复制代码
+获取实例对象 有两种方式获取类的实例对象,一种是调用Native API返回值获取,另一种是通过new操作符来创建导入的类对象的实例,如下:
+
+// iOS平台导入NSDictionary类
+var NSDictionary = plus.ios.importClass("NSDictionary");
+// 创建NSDictionary的实例对象
+var ns = new NSDictionary();
+
+// Android平台导入Intent类
+var Intent = plus.android.importClass("android.content.Intent");
+// 创建Intent的实例对象
+var intent = new Intent();
+复制代码
+获取实例对象后,可以通过实例对象“.”操作符获取对象的常量属性、调用对象的成员方法,实例对象的非常量属性则需通过plusGetAttribute、plusSetAttribute方法操作。
+
+操作对象的属性方法
+常量属性 获取对象后就可以通过“.”操作符获取对象的常量属性,如果是类对象则获取的是类的静态常量属性,如果是实例对象则获取的是对象的成员常量属性。
+
+非常量属性 如果Native层对象的属性值在原生环境下被更改,此时使用“.”操作符获取到对应NJS对象的属性值就可能不是实时的属性值,而是该Native层对象被映射为NJS对象那一刻的属性值。 为获取获取Native层对象的实时属性值,需调用NJS对象的plusGetAttribute(name)方法,参数name为属性的名称,返回值为属性的值。调用NJS对象的plusSetAttribute(name,value)方法设置Native层对象的非常量属性值,参数name为属性的名称,value为要设置新的属性值。 注意:使用plusGetAttribute(name)方法也可以获取Native层对象的常量属性值,但不如直接使用“.”操作符来获取性能高。
+
+方法 获取对象后可以通过“.”操作符直接调用Native层方法,如果是类对象调用的是Native层类的静态方法,如果是实例对象调用的是Native层对象的成员方法。 注意:在iOS平台由于JS语法的原因,Objective-C方法名称中的“:”字符转成NJS对象的方法名称后将会被忽略,因此在NJS中调用的方法名需去掉所有“:”字符。
+
+类的继承 Objective-C和Java中类如果存在继承自基类,在NJS中对应的对象会根据继承关系递归将所有基类的公有方法一一换成NJS对象的方法,所有基类的公有属性也可以通过其plusGetAttribute、plusSetAttribute方法访问。
+
+开始写NJS
+使用NJS调用Native API非常简单,基本步骤如下:
+
+导入要使用到的类;
+创建类的实例对象(或者调用类的静态方法创建);
+调用实例对象的方法;
+以下例子使用NJS调用iOS和Android的原生弹出提示框(类似但不同于js的alert)。
+
+Android
+以下代码在Android平台展示调用Native API显示系统提示框。 首先是Android原生 Java代码,用于比对参考:
+
+import android.app.AlertDialog;
+//...
+// 创建提示框构造对象,Builder是AlertDialog的内部类。参数this指代Android的主Activity对象,该对象启动应用时自动生成
+AlertDialog.Builder dlg = new AlertDialog.Builder(this);
+// 设置提示框标题
+dlg.setTitle("自定义标题");
+// 设置提示框内容
+dlg.setMessage("使用NJS的原生弹出框,可自定义弹出框的标题、按钮");
+// 设置提示框按钮
+dlg.setPositiveButton("确定(或者其他字符)", null);
+// 显示提示框
+dlg.show();
+//...
+复制代码
+Native.js代码:
+
+/**
+ * 在Android平台通过NJS显示系统提示框
+ */
+function njsAlertForAndroid(){
+ // 导入AlertDialog类
+ var AlertDialog = plus.android.importClass("android.app.AlertDialog");
+ // 创建提示框构造对象,构造函数需要提供程序全局环境对象,通过plus.android.runtimeMainActivity()方法获取
+ var dlg = new AlertDialog.Builder(plus.android.runtimeMainActivity());
+ // 设置提示框标题
+ dlg.setTitle("自定义标题");
+ // 设置提示框内容
+ dlg.setMessage("使用NJS的原生弹出框,可自定义弹出框的标题、按钮");
+ // 设置提示框按钮
+ dlg.setPositiveButton("确定(或者其他字符)",null);
+ // 显示提示框
+ dlg.show();
+}
+//...
+复制代码
+注意:NJS代码中创建提示框构造对象要求传入程序全局环境对象,可通过plus.android.runtimeMainActivity()方法获取应用的主Activity对象,它是HTML5+应用运行期自动创建的程序全局环境对象。
+
+Android设备上运行效果图: Android Native.js示例运行效果图 `注意:其实HTML5+规范已经封装过原生提示框消息API:plus.ui.alert( message, alertCB, title, buttonCapture)。此处NJS的示例仅为了开发者方便理解,实际使用时调用plus.ui.alert更简单,性能也更高。**
+
+iOS
+以下代码在iOS平台展示调用Native API显示系统提示对话框。 iOS原生Objective-C代码,用于比对参考:
+
+#import
+//...
+// 创建UIAlertView类的实例对象
+UIAlertView *view = [UIAlertView alloc];
+// 设置提示对话上的内容
+[view initWithTitle:@"自定义标题" // 提示框标题
+ message:@"使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容
+ delegate:nil // 点击提示框后的通知代理对象,nil类似js的null,意为不设置
+ cancelButtonTitle:@"确定(或者其他字符)" // 提示框上取消按钮的文字
+ otherButtonTitles:nil]; // 提示框上其它按钮的文字,设置为nil表示不显示
+// 调用show方法显示提示对话框,在OC中使用[]语法调用对象的方法
+[view show];
+//...
+复制代码
+Native.js代码:
+
+/**
+ * 在iOS平台通过NJS显示系统提示框
+ */
+function njsAlertForiOS(){
+ // 导入UIAlertView类
+ var UIAlertView = plus.ios.importClass("UIAlertView");
+ // 创建UIAlertView类的实例对象
+ var view = new UIAlertView();
+ // 设置提示对话上的内容
+ view.initWithTitlemessagedelegatecancelButtonTitleotherButtonTitles("自定义标题" // 提示框标题
+ , "使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容
+ , null // 操作提示框后的通知代理对象,暂不设置
+ , "确定(或者其他字符)" // 提示框上取消按钮的文字
+ , null ); // 提示框上其它按钮的文字,设置为null表示不显示
+ // 调用show方法显示提示对话框,在JS中使用()语法调用对象的方法
+ view.show();
+}
+//...
+复制代码
+注意:在OC语法中方法的定义格式为: “(返回值类型) 函数名: (参数1类型) 形参1 参数2名称: (参数2类型) 形参2” 方法的完整名称为: “函数名:参数2名称:”。 如:“(void)setPositionX:(int)x Y:(int)y;”,方法的完整名称为“setPositionX:Y:” 调用时语法为:“[pos setPositionX:x Y:y];”。 在JS语法中函数名称不能包含“:”字符,所以OC对象的方法名映射成NJS对象方法名时将其中的“:”字符自动删除,上面方法名映射为“setPositionXY”,在NJS调用的语法为:“pos.setPositionXY(x,y);”。 iOS设备上运行效果图: iOS Native.js示例运行效果图 `注意:其实HTML5+规范已经封装过原生提示框消息API:plus.ui.alert( message, alertCB, title, buttonCapture)。此处NJS的示例仅为了开发者方便理解,实际使用时调用plus.ui.alert更简单、性能也更高。
+
+在HBuilder自带的Hello H5+模板应用中“Native.JS”(plus/njs.html)页面有完整的源代码,可真机运行查看效果。
+
+常用API
+API on Android
+为了能更好的理解NJS调用Java Native API,我们在Android平台用Java实现以下测试类,将在会后面API说明中的示例来调用。 文件NjsHello.java代码如下:
+
+package io.dcloud;
+
+// 定义类NjsHello
+public class NjsHello {
+ // 静态常量
+ public static final int CTYPE = 1;
+ // 静态变量
+ public static int count;
+ // 成员常量
+ public final String BIRTHDAY = "2013-01-13";
+ // 成员变量
+ String name; //定义属性name
+ NjsHelloEvent observer;
+ public void updateName( String newname ) { //定义方法updateName
+ name = newname;
+ }
+ public void setEventObserver( NjsHelloEvent newobserver ) {
+ observer = newobserver;
+ }
+ public void test() { //定义方法test
+ System.out.printf( "My name is: %s", name );
+ observer.onEventInvoked( name );
+ }
+ public static void testCount() {
+ System.out.printf( "Static count is:%d", count );
+ }
+ static{ // 初始化类的静态变量
+ NjsHello.count = 0;
+ }
+}
+复制代码
+文件NjsHelloEvent.java代码如下:
+
+package io.dcloud;
+
+// 定义接口NjsHelloEvent
+public interface NjsHelloEvent {
+ public void onEventInvoked( String name );
+}
+复制代码
+注:此NjsHello示例仅为了说明原生代码与NJS代码之间的映射关系,以下示例代码无法直接在HBuilder里真机运行,必须在以后HBuilder开放自定义打包后方可把NjsHello类打入app并被NJS调用。实际使用中,这种需要并非必要,大多数情况可以通过直接写NJS代码调用操作系统API,而无需由原生语言二次封装类供JS调用。
+
+plus.android.importClass
+导入Java类对象,方法原型如下:
+
+ClassObject plus.android.importClass( String classname );
+复制代码
+导入类对象后,就可以通过“.”操作符直接调用对象(类对象/实例对象)的常量和方法。 classname:要导入的Java类名,必须是完整的命名空间(使用"."分割),如果指定的类名不存在,则导入类失败,返回null。
+
+注意:导入类对象可以方便的使用“.”操作符来调用对象的属性和方法,但也会消耗较多的系统资源。因此导入过多的类对象会影响性能,此时可以使用“高级API”中提供的方法在不导入类对象的情况下调用Native API。
+
+示例:
+
+导入类对象 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 创建NjsHello的实例对象
+var hello = new NjsHello();
+// ...
+复制代码
+ClassObject
+调用plus.android.importClass()方法导入类并返回ClassObject类对象,通过该类对象,可以创建类的实例对象。在Java中类的静态方法会转换成NJS类对象的方法,可通过类对象的“.”操作符调用;类的静态常量会转换为NJS类对象的属性,可通过类对象的“.”操作符访问;类的静态属性则需通过NJS类对象的plusGetAttribute、plusSetAttribute方法操作。 示例:
+
+导入类后获取类的静态常量属性 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 获取类的静态常量属性
+ int type = NjsHello.CTYPE;
+ System.out.printf( "NjsHello Final's value: %d", type ); // 输出“NjsHello Final's value: 1”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 获取类的静态常量属性
+var type = NjsHello.CTYPE;
+console.log( "NjsHello Final's value: "+type ); // 输出“NjsHello Final's value: 1”
+// ...
+复制代码
+导入类后调用类的静态方法 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 调用类的静态方法
+ NjsHello.testCount();
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 调用类的静态方法
+NjsHello.testCount();
+// ...
+复制代码
+ClassObject.plusGetAttribute
+获取类对象的静态属性值,方法原型如下:
+
+Object classobject.plusGetAttribute( String name );
+复制代码
+导入类对象后,就可以调用其plusGetAttribute方法获取类的静态属性值。
+
+name:要获取的静态属性名称,如果指定的属性名称不存在,则获取属性失败,返回null。
+注意:如果导入的类对象中存在“plusGetAttribute”同名的静态方法,则必须通过plus.android.invoke()方法调用。
+
+示例:
+
+导入类后获取类的静态属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 获取类的静态属性
+ int count = NjsHello.count;
+ System.out.printf( "NjsHello Static's value: %d", count ); // 输出“NjsHello Static's value: 0”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 获取类的静态属性
+var count = NjsHello.plusGetAttribute( "count" );
+console.log( "NjsHello Static's value: "+count ); // 输出“NjsHello Static's value: 0”
+// ...
+复制代码
+ClassObject.plusSetAttribute
+设置类对象的静态属性值,方法原型如下:
+
+void classobject.plusSetAttribute( String name, Object value );
+复制代码
+导入类对象后,就可以调用其plusSetAttribute方法设置类的静态属性值。
+
+name:要设置的静态属性名称,如果指定的属性名称不存在,则设置属性失败,返回null。
+value:要设置的属性值,其类型必须与Native层类对象的静态属性区配,否则设置操作不生效,将保留以前的值。
+注意:如果导入的类对象中存在“plusSetAttribute”同名的静态方法,则必须通过plus.android.invoke()方法调用。
+
+示例:
+
+导入类后设置类的静态属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 设置类的静态属性值
+ NjsHello.count = 2;
+ System.out.printf( "NjsHello Static's value: %d", NjsHello.count ); // 输出“NjsHello Static's value: 2”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 设置类的静态属性值
+NjsHello.plusSetAttribute( "count", 2 );
+console.log( "NjsHello Static's value: "+NjsHello.plusGetAttribute( "count" ) ); // 输出“NjsHello Static's value: 2”
+// ...
+复制代码
+InstanceObject
+NJS中实例对象与Java中的对象对应,调用plus.android.importClass()方法导入类后,通过new操作符可创建该类的实例对象,或直接调用plus.android.newObject方法创建类的实例对象,也可通过调用Native API返回实例对象。在Java中对象的方法会转换成NJS实例对象的方法,可通过实例对象的“.”操作符调用;对象的常量属性会转换NJS实例对象的属性,可通过实例对象的“.”操作符访问。对象的非常量属性则必须通过NJS实例对象的plusGetAttribute、plusSetAttribute方法操作。 示例:
+
+导入类创建实例对象,调用对象的方法 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建NjsHello的实例对象
+ NjsHello hello = new NjsHello();
+ // 调用对象的方法
+ hello.updateName( "Tester" );
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 创建NjsHello的实例对象
+var hello = new NjsHello();
+// 调用对象的方法
+hello.updateName( "Tester" );
+// ...
+复制代码
+导入类创建实例对象,获取对象的常量属性 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建NjsHello的实例对象
+ NjsHello hello = new NjsHello();
+ // 访问对象的常量属性
+ String birthday = hello.BIRTHDAY;
+ System.out.printf( "NjsHello Object Final's value: %s", birthday ); // 输出“NjsHello Object Final's value: 2013-01-13”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 创建NjsHello的实例对象
+var hello = new NjsHello();
+// 访问对象的常量属性
+var birthday = hello.BIRTHDAY;
+console.log( "NjsHello Object Final's value: "+birthday ); // 输出“NjsHello Object Final's value: 2013-01-13”
+// ...
+复制代码
+InstanceObject.plusGetAttribute
+获取实例对象的属性值,方法原型如下:
+
+Object instancebject.plusGetAttribute( String name );
+复制代码
+获取实例对象后,就可以调用其plusGetAttribute方法获取对象的属性值。 name:要获取对象的属性名称,如果指定的属性名称不存在,则获取属性失败,返回null。
+
+注意:如果实例对象中存在“plusGetAttribute”同名的方法,则必须通过plus.android.invoke()方法调用。
+
+示例:
+
+导入类创建实例对象,获取对象的属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ hello.updateName( "Tester" );
+ // 获取其name属性值
+ String name = hello.name;
+ System.out.printf( "NjsHello Object's name: %s", name ); // 输出“NjsHello Object's name: Tester”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+hello.updateName( "Tester" );
+// 获取其name属性值
+var name = hello.plusGetAttribute( "name" );
+console.log( "NjsHello Object's name: "+name ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+InstanceObject.plusSetAttribute
+设置类对象的静态属性值,方法原型如下:
+
+void instanceobject.plusSetAttribute( String name, Object value );
+复制代码
+导入类对象后,就可以调用其plusSetAttribute方法设置类的静态属性值。
+
+name:要设置的静态属性名称,如果指定的属性名称不存在,则设置属性失败,返回null。
+value:要设置的属性值,其类型必须与Native层类对象的静态属性区配,否则设置操作不生效,将保留以前的值。
+注意:如果导入的类对象中存在“plusSetAttribute”同名的静态方法,则必须通过plus.android.invoke()方法调用。
+
+示例:
+
+导入类创建实例对象,设置对象的属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ // 设置其name属性值
+ hello.name = "Tester";
+ System.out.printf( "NjsHello Object's name: %s", hello.name ); // 输出“NjsHello Object's name: Tester”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var Hello = plus.android.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+// 设置其name属性值
+hello.plusSetAttribute( "name", "Tester" );
+console.log( "NjsHello Object's name: "+hello.plusGetAttribute("name") ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+plus.android.implements
+在Java中可以通过定义新类并实现Interface的接口,并创建出新类对象作为其它接口的参数,在NJS中则可快速创建对应的Interface对象,方法原型如下: Object plus.android.implements( String name, Object obj );
+
+此方法创建Native层中Java的接口实现对象,作为调用其它Native API的参数。
+
+name:接口的名称,必须是完整的命名空间(使用"."分割),如果不存在此接口,则创建接口实现对象失败,返回null。
+obj:JSON对象类型,接口实现方法的定义,JSON对象中key值为接口方法的名称;value值为Function,方法参数必须与接口中方法定义的参数区配。
+示例:
+
+Test类中实现接口NjsHelloEvent的方法,并调用NjsHello对象的test方法触发接口中函数的运行。 Java代码:
+import io.dcloud.NjsHello;
+import io.dcloud.NjsHelloEvent;
+//...
+// Test类实现NjsHelloEvent接口
+public class Test implements NjsHelloEvent {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ // 调用updateName方法
+ hello.updateName( "Tester" );
+ // 设置监听对象
+ hello.setEventObserver( this );
+ // 调用test方法,触发接口事件
+ hello.test(); // 触发onEventInvoked函数运行
+ //...
+}
+// 实现接口NjsHelloEvent的onEventInvoked方法
+@Override
+public void onEventInvoked( String name ) {
+ System.out.printf( "Invoked Object's name is: %s", name );
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.android.importClass("io.dcloud.NjsHello");
+// 实现接口“NjsHelloEvent”对象
+var hevent = plus.android.implements( "io.dcloud.NjsHelloEvent", {
+ "onEventInvoked":function( name ){
+ console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”
+ }
+} );
+// 创建对象的实例
+var hello = new NjsHello();
+// 调用updateName方法
+hello.updateName( "Tester" );
+// 设置监听对象
+hello.setEventObserver( hevent );
+// 调用test方法,触发代理事件
+hello.test(); // 触发上面定义的匿名函数运行
+// ...
+复制代码
+plus.android.runtimeMainActivity
+获取运行期环境主Activity实例对象,方法原型如下:
+
+InstanceObject plus.android.runtimeMainActivity();
+复制代码
+此方法将获取程序的主Activity的实例对象,它是Html5+运行期环境主组件,用于处理与用户交互的各种事件,也是应用程序全局环境android.app.Activity的实现对象。android.app.Activity是一个特殊的类,需要在原生开发环境中注册后才能使用,所以使用new操作符创建对象无实际意义。
+
+示例:
+
+调用Activity的startActivity方法来拨打电话 Java代码:
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+//...
+// 获取主Activity对象的实例
+Activity main = context;
+// 创建Intent
+Uri uri = Uri.parse("tel:10086");
+Intent call = new Intent("android.intent.action.CALL",uri);
+// 调用startActivity方法拨打电话
+main.startActivity(call);
+//...
+复制代码
+NJS代码:
+
+// 导入Activity、Intent类
+var Intent = plus.android.importClass("android.content.Intent");
+var Uri = plus.android.importClass("android.net.Uri");
+// 获取主Activity对象的实例
+var main = plus.android.runtimeMainActivity();
+// 创建Intent
+var uri = Uri.parse("tel:10086");
+var call = new Intent("android.intent.action.CALL",uri);
+// 调用startActivity方法拨打电话
+main.startActivity( call );
+// ...
+复制代码
+plus.android.currentWebview
+获取当前Webview窗口对象的native层实例对象,方法原型如下:
+
+InstanceObject plus.android.currentWebview();
+复制代码
+Android平台完整Java类名为android.webkit.Webview,完整API请参考Android开发文档android.webkit.Webview。
+
+示例:
+
+调用Webview的loadUrl方法跳转页面 Java代码:
+import android.webkit.Webview;
+//...
+// 获取Webview对象
+Webview wv = this;
+// 跳转页面
+wv.loadUrl("http://www.dcloud.io/");
+//...
+复制代码
+NJS代码:
+
+// 导入Webview类
+var Webview = plus.android.importClass("android.webkit.Webview");
+// 当前Webview对象的实例
+var wv = plus.android.currentWebview();
+// 跳转页面
+wv.loadUrl("http://www.dcloud.io/");
+// ...
+复制代码
+完整API文档参考:HTML5+ API - Native.js for Android
+
+API on iOS
+为了能更好的理解NJS调用Objective-C Native API,我们在iOS平台用Objective-C实现以下测试类,将会在后面API说明中的示例来调用。 头文件njshello.h代码如下:
+
+// 定义协议
+@protocol NjsHelloEvent
+@required
+-(void) onEventInvoked:(NSString*)name;
+@end
+// -------------------------------------------------------------
+// 定义类NjsHello
+@interface NjsHello : NSObject {
+ NSString *_name;
+ id _delegate;
+}
+@property (nonatomic,retain) NSString *name;
+@property (nonatomic,retain) id delegate;
+-(void)updateName:(NSString*)newname;
+-(void)setEventObserver:(id)delegate;
+-(void)test;
++(void)testCount;
+@end
+复制代码
+实现文件njshello.m源代码如下:
+
+#import "njshello.h"
+// 实现类NjsHello
+@implementation NjsHello
+@synthesize name=_name;
+-(void)updateName:(NSString*)newname{
+ _name = [newname copy];
+}
+-(void)setEventObserver:(id)delegate{
+ _delegate = delegate;
+}
+-(void)test{
+ NSLog(@"My name is: %@",_name);
+ [[self delegate]onEventInvoked:name];
+}
+-(void)dealloc{
+ [_name release];
+ [supper dealloc];
+}
++(void)testCount{
+ NSLog( @"Static test count" );
+}
+@end
+复制代码
+plus.ios.importClass
+导入Objective-C类对象,方法原型如下:
+
+ClassObject plus.ios.importClass( String classname );
+复制代码
+导入类对象后,就可以通过“.”操作符直接调用对象(类对象/实例对象)的常量和方法。通过“.”操作符号调用方法时,不需要使用“:”来分割方法名。
+
+classname:要导入的Objective-C类名,如果指定的类名不存在,则导入类失败,返回null。
+注意:导入类对象可以方便的使用“.”操作符来调用对象的属性和方法,但也会消耗较多的系统资源。因此导入过多的类对象会影响性能,此时可以使用“高级API”中提供的方法在不导入类对象的情况下调用Native API。 示例:
+
+导入类并创建实例对象 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // ...
+}
+// ...
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+// ...
+复制代码
+ClassObject
+调用plus.ios.importClass()方法导入类并返回ClassObject类对象,通过该类对象,可以创建类的实例对象。在Objective-C中类的静态方法会转换成NJS类对象的方法,可通过类对象的“.”操作符调用;
+
+注意:由于Objective-C中类没有静态变量,而是通过定义全局变量来实现,目前NJS中无法访问全局变量的值。对于全局常量,在NJS中也无法访问,对于原类型常量可在文档中找到其具体的值,在JS代码中直接赋值;对于非原类型常量目前还无法访问。
+
+示例:
+
+导入类后调用类的静态方法 Objective-C代码:
+#import "njshello.h"
+// ...
+int main( int argc, char *argv[] )
+{
+ // 调用类的静态方法
+ [NjsHello testCount];
+ // ...
+}
+// ...
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 调用类的静态方法
+NjsHello.testCount();
+// ...
+复制代码
+InstanceObject
+NJS中实例对象与Objective-C中的对象对应,调用plus.ios.importClass()方法导入类后,通过new操作符可创建该类的实例对象,或直接调用plus.ios.newObject方法创建类的实例对象,也可通过调用Native API返回实例对象。在Objective-C中对象的方法会转换成NJS实例对象的方法,可通过实例对象的“.”操作符调用;对象的属性则必须通过NJS实例对象的plusGetAttribute、plusSetAttribute方法操作。
+
+示例:
+
+导入类创建实例对象,调用对象的方法 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // ...
+}
+// ...
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+// ...
+复制代码
+InstanceObject.plusGetAttribute
+获取实例对象的属性值,方法原型如下:
+
+Object instancebject.plusGetAttribute( String name );
+复制代码
+获取实例对象后,就可以调用其plusGetAttribute方法获取对象的属性值。
+
+name:要获取对象的属性名称,如果指定的属性名称不存在,则获取属性失败,返回null。
+注意:如果实例对象中存在“plusGetAttribute”同名的方法,则只能通过plus.ios.invoke()方法调用。
+
+示例:
+
+导入类创建实例对象,获取对象的属性值 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ [hello updateName:@"Tester"];
+ // 获取其name属性值
+ NSString* name = hello.name;
+ NSLog(@"NjsHello Object's name: %@",name); // 输出“NjsHello Object's name: Tester”
+ // ...
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+hello.updateName( "Tester" );
+// 获取其name属性值
+var name = hello.plusGetAttribute( "name" );
+console.log( "NjsHello Object’s name: "+name ); // 输出“NjsHello Object’s name: Tester”
+// ...
+复制代码
+InstanceObject.plusSetAttribute
+设置类对象的静态属性值,方法原型如下:
+
+void instanceobject.plusSetAttribute( String name, Object value );
+复制代码
+导入类对象后,就可以调用其plusSetAttribute方法设置类的静态属性值。
+
+name:要设置的静态属性名称,如果指定的属性名称不存在,则设置属性失败,返回null。
+value:要设置的属性值,其类型必须与Native层类对象的静态属性区配,否则设置操作不生效,将保留以前的值。
+注意:如果导入的类对象中存在“plusSetAttribute”同名的静态方法,则只能通过plus.android.invoke()方法调用。
+
+示例:
+
+导入类创建实例对象,设置对象的属性值 Java代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // 设置其name属性值
+ hello.name = @"Tester";
+ NSLog(@"NjsHello Object's name: %@",hello.name); // 输出“NjsHello Object's name: Tester”
+ // ...
+}
+//...
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+// 设置其name属性值
+hello.plusSetAttribute( "name", "Tester" );
+console.log( "NjsHello Object’s name: "+hello.plusGetAttribute("name") ); // 输出“NjsHello Object’s name: Tester”
+// ...
+复制代码
+plus.ios.implements
+在Objective-C中可以通过定义新类并实现Protocol的协议,并创建出新类对象作为代理对象,在NJS中则可实现协议快速创建代理对象,方法原型如下:
+
+Object plus.ios.implements( String name, Object obj );
+复制代码
+此方法返回一个NJS实例对象,映射到Native层中的代理对象,其父类为“NSObject”,并且实现obj中指定的协议方法。通常作为调用其它Native API的参数。
+
+name:协议的名称,也可以是自定的字符串名称用于定义一个代理。
+obj:JSON对象类型,代理实现方法的定义,JSON对象中key值为协议中定义的方法名称,必须保留方法名称中的“:”字符;value值为Function,方法参数必须与协议中定义方法的参数区配。
+示例:
+
+实现一个代理,并调用test方法触发调用代理的方法 Objective-C代码:
+#import "njshello.h"
+// 定义代理类NjsDelegate
+@interface NjsDelegate: NSObject {
+ -(void) onEventInvoked:(NSString*)name;
+}
+@end
+// -------------------------------------------------------------
+// 实现代理类NjsDelegate
+@implementation NjsDelegate
+-(void) onEventInvoked:(NSString*)name{
+ NSLog(@"Invoked Object's name:%@",name); // 输出“Invoked Object’s name: Tester”
+}
+@end
+// -------------------------------------------------------------
+// 主函数
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // 调用updateName方法
+ [hello updateName:@"Tester"];
+ // 创建代理对象
+ NjsDelegate* delegate = [[NjsDelegate alloc] init];
+ // 设置监听对象
+ [hello setEventObserver:delegate];
+ // 调用test方法,触发代理事件
+ [hello test]; // 触发上面代理对象定义的onEventInvoked运行
+ // ...
+}
+复制代码
+在NJS中不需要创建新的类对象,调用plus.ios.implements实现协议接口即可创建出代理对象,代码如下:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 实现协议“NjsHelloEvent”的代理
+var hevent = plus.ios.implements( "NjsHelloEvent", {
+ "onEventInvoked:":function( name ){
+ console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”
+ }
+} );
+// 调用updateName方法
+hello.updateName( "Tester" );
+// 设置监听对象
+hello.setEventObserver( hevent );
+// 调用test方法,触发代理事件
+hello.test(); // 触发上面代理对象定义的匿名函数运行
+// ...
+复制代码
+plus.ios.deleteObject
+释放NJS中实例对象中映射的Native对象,方法原型如下:
+
+void plus.ios.deleteObject( Object obj );
+复制代码
+NJS中所有的实例对象(InstanceObject)都可以通过此方法释放,会将Native层的对象使用的资源进行释放。
+
+obj:要释放的实例对象,如果obj对象不是有效的实例对象,则不执行对象的是否资源操作。
+注意:此方法是可选的,如果不调用此方法释放实例对象,则在页面关闭时会自动释放所有对象;若对象占用较多的系统资源,则在业务逻辑处理完成时应该主动调用此方法释放资源,以提到程序的运行效率。
+
+示例:
+
+创建实例对象使用完成后,显式操作销毁对象 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // 调用updateName方法
+ [hello updateName:@"Tester"];
+ // ...
+ // 使用完后销毁对象的实例
+ [hello release];
+}
+复制代码
+NJS代码:
+
+// 导入测试类NjsHello
+var NjsHello = plus.ios.importClass("NjsHello");
+// 创建对象的实例
+var hello = new NjsHello();
+// 调用updateName方法
+hello.updateName( "Tester" );
+// ...
+// 使用完后销毁对象的实例
+plus.ios.deleteObject( hello );
+复制代码
+plus.ios.currentWebview
+获取当前Webview窗口对象的native层UIWebview实例对象,方法原型如下:
+
+InstanceObject plus.ios.currentWebview();
+复制代码
+UIWebview对象的API请参考Apple开发文档UIWebview
+
+示例:
+
+创建实例对象使用完成后,显式操作销毁对象 Objective-C代码:
+// 获取当前Webview对象的实例
+UIWebview* wv=self;
+// 创建请求对象
+NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.dcloud.io/"]];
+// 跳转页面
+[web loadRequest:req];
+// 释放对象
+// 系统自动回收
+// ...
+复制代码
+NJS代码:
+
+// 导入UIWebview、NSURLRequest、NSURL类
+var Webview = plus.ios.importClass("UIWebview");
+var NSURLRequest = plus.ios.import('NSURLRequest');
+var NSURL = plus.ios.import('NSURL');
+// 获取当前Webview对象的实例
+var wv = plus.ios.currentWebview();
+// 创建请求对象
+var req = NSURLRequest.requestWithURL(NSURL.URLWithString('http://www.dcloud.io/'));
+// 跳转页面
+plus.ios.invoke(wv,"loadRequest:",req);
+// 释放对象(可选)
+plus.ios.deleteObject(req);
+plus.ios.deleteObject(wv);
+// ...
+复制代码
+完整API文档参考:HTML5+ API - Native.js for iOS
+
+完整业务演示
+Android
+在Android手机桌面上创建快捷方式图标,这是原本只有原生程序才能实现的功能。即使使用Hybrid方案,也需要原生工程师来配合写插件。 下面我们演示如何直接使用js在Android手机桌面创建快捷方式,在HelloH5+应用中Native.JS页面中“Shortcut (Android)”可以查看运行效果。 这段代码是使用原生Java实现的创建快捷方式的代码,用于参考比对:
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+// 创建桌面快捷方式
+void createShortcut(){
+ // 获取主Activity
+ Activity main = this;
+ // 创建快捷方式意图
+ Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
+ // 设置快捷方式的名称
+ shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, "HelloH5+");
+ // 设置不可重复创建
+ shortcut.putExtra("duplicate",false);
+ // 设置快捷方式图标
+ Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/icon.png");
+ shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
+ // 设置快捷方式启动执行动作
+ Intent action = new Intent(Intent.ACTION_MAIN);
+ action.setComponent( main.getComponentName() );
+ shortcut.putExtra( Intent.EXTRA_SHORTCUT_INTENT, action );
+ // 广播创建快捷方式
+ main.sendBroadcast(shortcut);
+}
+复制代码
+使用NJS实现时首先导入需要使用到的android.content.Intent、android.graphics.BitmapFactory类,按照Java代码中的方法对应转换成JavaScript代码。 其中快捷方式图标是通过解析本地png文件进行设置,在JavaScript中需要使用plus.io.* API转换成本地路径传递给Native API,完整代码如下:
+
+var Intent=null,BitmapFactory=null;
+var main=null;
+document.addEventListener( "plusready", function() {//"plusready"事件触发时执行plus对象的方法
+ // ...
+ if ( plus.os.name == "Android" ) {
+ // 导入要用到的类对象
+ Intent = plus.android.importClass("android.content.Intent");
+ BitmapFactory = plus.android.importClass("android.graphics.BitmapFactory");
+ // 获取主Activity
+ main = plus.android.runtimeMainActivity();
+ }
+}, false);
+/**
+ * 创建桌面快捷方式
+ */
+function createShortcut(){
+ // 创建快捷方式意图
+ var shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
+ // 设置快捷方式的名称
+ shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, "测试快捷方式");
+ // 设置不可重复创建
+ shortcut.putExtra("duplicate",false);
+ // 设置快捷方式图标
+ var iconPath = plus.io.convertLocalFileSystemURL("/icon.png"); // 将相对路径资源转换成系统绝对路径
+ var bitmap = BitmapFactory.decodeFile(iconPath);
+ shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON,bitmap);
+ // 设置快捷方式启动执行动作
+ var action = new Intent(Intent.ACTION_MAIN);
+ action.setClassName(main.getPackageName(), 'io.dcloud.PandoraEntry');
+ shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT,action);
+ // 广播创建快捷方式
+ main.sendBroadcast(shortcut);
+ console.log( "桌面快捷方式已创建完成!" );
+}
+复制代码
+注意:提交到云平台打包时需要添加Android权限才能在桌面创建快捷方式,在HBuilder工程中双击应用的“manifest.json”文件,切换到“代码视图”中在plus->distribute->google->permissions节点下添加权限数据:
+
+"google": {
+ // ...
+ "permissions": [
+""
+ ]
+}
+复制代码
+如下图所示:
+
+manifest.json中Android权限 permissions
+
+iOS
+在iOS手机上登录game center,一个游戏中心服务,这是原本只有原生程序才能实现的功能。即使使用Hybrid方案,也需要原生工程师来配合写插件。 下面我们演示如何直接使用js在iOS手机上登录game center,在HelloH5+应用中Native.JS页面中的“Game Center (iOS)”可以查看运行效果。 注意手机未开通game center则无法登陆,请先点击iOS自带的game center进行配置。 这段代码是使用原生Objective-C实现的登录game center的代码,用于参考比对。原生Objective-C代码的头文件Test.h中代码如下:
+
+@interface Test: NSObject
+// 游戏玩家登录状态监听函数
+- (void)authenticationChanged:(NSNotification*)notification;
+// 获取游戏玩家状态信息
+- (void)playerInformation:(GKPlayer *)player;
+// 登录到游戏中心
+- (void)loginGamecenter;
+// 停止监听登录游戏状态变化
+- (void)logoutGamecenter;
+@end
+
+实现文件Test.m中代码如下:
+@implementation Test
+// 游戏玩家登录状态监听函数
+- (void)authenticationChanged:(NSNotification*)notification
+{
+ // 获取游戏玩家共享实例对象
+ GKLocalPlayer *player = notification.object;
+ if ( player.isAuthenticated ) {
+ // 玩家已登录认证,获取玩家信息
+ [self playerInformation:player];
+ } else {
+ // 玩家未登录认证,提示用户登录
+ NSLog(@"请登录!");
+ }
+ // 释放使用的对象
+ [player release];
+}
+// 获取游戏玩家状态信息
+- (void)playerInformation:(GKPlayer *)player
+{
+ // 获取游戏玩家的名称
+ NSLog(@"Name: %@",player.displayName);
+}
+
+// 登录到游戏中心
+- (void)loginGamecenter
+{
+ // 监听用户登录状态变更事件
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self
+ selector:@selector(authenticationChanged)
+ name:@"GKPlayerAuthenticationDidChangeNotificationName"
+ object:nil];
+ // 获取游戏玩家共享实例对象
+ GKLocalPlayer *localplayer = [GKLocalPlayer localPlayer];
+ // 判断游戏玩家是否已经登录认证
+ if ( localplayer.isAuthenticated ) {
+ // 玩家已登录认证,获取玩家信息
+ [self playerInformation:localplayer];
+ } else {
+ // 玩家未登录认证,发起认证请求
+ [localplayer authenticateWithCompletionHandler:nil];
+ NSLog(@"登录中...");
+ }
+ // 释放使用的对象
+ [localplayer release];
+ [nc release];
+}
+
+// 停止监听登录游戏状态变化
+- (void)logoutGamecenter
+{
+ // 取消监听用户登录状态变化
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc removeObserver:self
+ name:@"GKPlayerAuthenticationDidChangeNotificationName"
+ object:nil];
+ // 释放使用的对象
+ [nc release];
+}
+@end
+复制代码
+使用NJS实现时可以按照Objective-C代码中的方法对应转换成JavaScript代码,最关键的代码是loginGamecenter方法中对用户登录状态的监听,需调用NSNotificationCenter对象的“addObserver:selector:name:object”方法,
+
+addObserver:后要求传入一个实例对象用于查找selector参数中指定的方法,在Objective-C中通常将对象自身(self)传入,但在NJS中没有此概念,因此需使用plus.ios.implements方法来创建一个新的对象: var delegate = plus.ios.implements("NSObject",{"authenticationChanged:":authenticationChanged}); 第一个参数“NSObject”表示对象的类型,第二个参数中的JSON对象表明对象拥有的方法,“authenticationChanged”方法是delegate对象的方法。
+selector:后要传入一个类函数指针,在Objective-C中通过“@selector”指令可选择函数指针,在NJS中则需使用plus.ios.newObject方法来创建一个函数对象: plus.ios.newObject("@selector","authenticationChanged:") 第一个参数需固定值为“@selector”,表示创建的是类函数指针对象,第二个参数。 在"plusready"事件中导入GKLocalPlayer和NSNotificationCenter类,并调用登录方法longinGamecenter()。
+完整JavaScript代码如下:
+
+// 处理"plusready"事件
+var bLogin=false;
+document.addEventListener( "plusready", function() {
+ // ...
+ if ( plus.os.name == "iOS" ) {
+ GKLocalPlayer = plus.ios.importClass("GKLocalPlayer");
+ NSNotificationCenter = plus.ios.importClass("NSNotificationCenter");
+ longinGamecenter();
+ } else {
+ alert("欢迎您");
+ bLogin = true;
+ setTimeout( function(){
+ plus.ui.toast( "此平台不支持Game Center功能!" );
+ }, 500 );
+ }
+}, false);
+
+var GKLocalPlayer=null,NSNotificationCenter=null;
+var delegate=null;
+
+// 游戏玩家登录状态监听函数
+function authenticationChanged( notification ){
+ // 获取游戏玩家共享实例对象
+ var player = notification.plusGetAttribute("object");
+ if ( player.plusGetAttribute("isAuthenticated") ) {
+ // 玩家已登录认证,获取玩家信息
+ playerInformation(player);
+ bLogin = true;
+ } else {
+ // 玩家未登录认证,提示用户登录
+ alert("请登录");
+ bLogin = false;
+ }
+ // 释放使用的对象
+ plus.ios.deleteObject(player);
+}
+
+// 获取游戏玩家状态信息
+function playerInformation( player ){
+ var name = player.plusGetAttribute("displayName");
+ alert( name+" 已登录!" );
+}
+
+// 登录到游戏中心
+function longinGamecenter(){
+ if ( bLogin ){
+ return;
+ }
+ // 监听用户登录状态变更事件
+ var nc = NSNotificationCenter.defaultCenter();
+ delegate = plus.ios.implements("NSObject",{"authenticationChanged:":authenticationChanged});
+ nc.addObserverselectornameobject(delegate,
+ plus.ios.newObject("@selector","authenticationChanged:"),
+ "GKPlayerAuthenticationDidChangeNotificationName",
+ null);
+ // 获取游戏玩家共享实例对象
+ var localplayer = GKLocalPlayer.localPlayer();
+ // 判断游戏玩家是否已经登录认证
+ if ( localplayer.isAuthenticated() ) { // localplayer.plusGetAttribute("isAuthenticated")
+ // 玩家已登录认证,获取玩家信息
+ playerInformation( localplayer );
+ bLogin = true;
+ } else {
+ // 玩家未登录认证,发起认证请求
+ localplayer.authenticateWithCompletionHandler(null);
+ alert( "登录中..." );
+ }
+ // 释放使用的对象
+ plus.ios.deleteObject(localplayer);
+ plus.ios.deleteObject(nc);
+}
+
+// 停止监听登录游戏状态变化
+function stopGamecenterObserver()
+{
+ // 取消监听用户登录状态变化
+ var nc = NSNotificationCenter.defaultCenter();
+ nc.removeObservernameobject(delegate,"GKPlayerAuthenticationDidChangeNotificationName",null);
+ plus.ios.deleteObject(nc);
+ plus.ios.deleteObject(delegate);
+ delegate = null;
+}
+复制代码
+注意
+
+提交到云平台打包时需要添加Game Center API的系统库(framework)才能正确调用,在HBuilder工程中双击应用的“manifest.json”文件,切换到“代码视图”中在plus->distribute->apple->frameworks节点下添加要引用的系统Framework:
+"apple": {
+ "devices": "universal",
+ "frameworks": [
+ "GameKit.framework"
+ ]
+}
+复制代码
+,如下图所示: HBuilder frameworks 2. 正式发布提交到AppStore时,在配置苹果开发者网站上配置App ID需要选中“Game Center”服务: Game Center
+
+##开发注意和建议用途 Native.js的运行性能仍然不比纯原生应用;JS与Native之间的数据交换效率并不如在js内部的数据交换效率;基于如上原因,有几点开发建议:
+
+以标准web 代码为主,当遇到web能力不足的时候,调用Native.js。
+以标准web 代码为主,当遇到web性能不足的时候,需要分析, if ((原生进行运算的效率-js与原生通讯的损耗)>纯web的效率){ 使用Native.js }else{ 还应该使用纯js }
+应避免把程序设计为在短时间内并发触发Native.js代码
+##调试 使用safari和chrome的控制台调试HBuilder的5+App时,一样可以调试NJS对象,即可以在浏览器控制台中查看各种原生对象的属性和方法,如下图所示,57行设了断点,watch了Intent对象,并在右边展开了该对象的所有属性方法: Chrome Debug 关于如何在浏览器控制台调试HBuilder的5+App,请参考HBuilder的5+App开发入门教程。
+
+##开发资源 iOS 官方在线文档:https://developer.apple.com/library/ios/navigation/ Android 官方在线文档:https://developer.android.com/reference/packages.html 演讲视频:http://v.youku.com/v_show/id_XNzYzNTcwNDI4.html
+
+##高级API 有前述的常用API,已经可以完成各项业务开发。此处补充的高级API,是在熟悉NJS后,为了提升性能而使用的API。高级API无法直接用“.”操作符使用原生对象的方法,在debug时也无法watch原生对象,但高级API性能高于常规API。 虽然导入类对象(plus.android.importClass和plus.ios.importClass)后,可以方便的通过“.”操作符来访问对象的常量、调用对象的方法,但导入类对象也需要消耗较多的系统资源,所以在实际开发时应该尽可能的减少导入类对象,以提高程序效率。可以参考以下依据进行判断:
+
+如导入的类特别复杂,继承自很多基类,方法和属性特别多则考虑不导入类;
+对导入类是否需要频繁操作,若导入类仅是为了实例化,并作为调用其它API的参数,则不应该导入类;
+在同一页面中是否导入了很多类?如果导入太多则需要考虑减少导入类的数目。
+如果我们不导入类对象则无法通过new操作符实例化类对象,这时可通过plus.ios.newObject()、plus.android.newObject()方法来创建实例对象,如下:
+
+// iOS平台创建NSDictionary的实例对象
+var ns = plus.ios.newObject( "NSDictionary" );
+
+// Android平台创建Intent的实例对象
+var intent = plus.android.newObject( "android.content.Intent" );
+复制代码
+API on Android
+plus.android.newObject
+不导入类对象直接创建类的实例对象,方法原型如下:
+
+InstanceObject plus.android.newObject( String classname, Object...args );
+复制代码
+此方法对Native层中对类进行实例化操作,创建一个类的实体并返回NJS层的实例对象。相比导入类对象后使用new操作符创建对象效率要高。
+
+classname:要创建实例对象的类名,类名必须是完整的命名空间,使用“.”分隔符(如“android.app.AlertDialog”),如果需要创建内部类对象需要使用“$”分割符(如“android.app.AlertDialog$Builder”)。如果指定的类名不存在,则创建对象失败,返回null。
+args:调用类构造函数的参数,其类型和数目必须与Native层Java类构造函数区配,否则无法创建类对象,将返回null。
+注意:由于没有导入类对象,所以通过此方法创建的实例对象无法通过“.”操作符直接调用对象的方法,而必须使用plus.android.invoke方法来调用。
+
+示例:
+
+不导入类创建实例对象 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 创建对象的实例
+var hello = plus.android.newObject( "io.dcloud.NjsHello" );
+// ...
+复制代码
+plus.android.getAttribute
+不导入类对象,则无法通过类对象并访问类的静态属性,需调用以下方法获取类的静态属性值,方法原型如下:
+
+Object plus.android.getAttribute( String|Object obj, String name );
+复制代码
+此方法也可以获取类对象或实例对象的属性值,如果是类对象获取的则是类的静态属性,如果是实例对象则获取的是对象的非静态属性。
+
+obj:若是String类型,表示要获取静态属性值的类名,类名必须是完整的命名空间(使用"."分割);若是ClassObject类型,表示要获取静态属性的类对象;若是InstanceObject类型,表示要获取属性值的实例对象。
+name:要获取的属性名称,如果指定的属性名称不存在,则获取属性失败,返回null。
+注意:同样导入类对象后也可以调用此方法,obj参数类型为ClassObject时,其作用与ClassObject.plusSetAttribute方法一致。obj参数类型为InstanceObject时,其作用与InstanceObject.plusSetAttribute方法一致。
+
+示例:
+
+不导入类对象获取类的静态常量属性 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 获取类的静态常量属性
+ int type = NjsHello.CTYPE;
+ System.out.printf( "NjsHello Final's value: %d", type ); // 输出“NjsHello Final's value: 1”
+ // 获取类的静态属性
+ int count = NjsHello.count;
+ System.out.printf( "NjsHello Static's value: %d", count ); // 输出“NjsHello Static's value: 0”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 访问类的静态常量属性
+var type = plus.android.getAttribute( "io.dcloud.NjsHello", "CTYPE" );
+console.log( "NjsHello Final's value: "+type ); // 输出“NjsHello Final's value: 1”
+// ...
+复制代码
+不导入类对象,创建实例对象,并获取其name属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ // 获取其name属性值
+ String name = hello.name;
+ System.out.printf( "NjsHello Object's name: %s", name ); // 输出“NjsHello Object's name: Tester”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 创建对象的实例
+var hello = plus.android.newObject( "io.dcloud.NjsHello" );
+// 获取其name属性值
+var name = plus.android.getAttribute( hello, "name" );
+console.log( "NjsHello Object's name: "+name ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+plus.android.setAttribute
+若没有导入类对象,则无法通过类对象设置类的静态属性值,需调用以下方法设置类的静态属性值,方法原型如下:
+
+void plus.android.setAttribute( String|Object obj, String name, Object value );
+复制代码
+此方法也可以设置类对象或实例对象的属性值,如果是类对象设置的则是类的静态属性,如果是实例对象则设置的是对象的非静态属性。
+
+obj:若是String类型,表示要设置静态属性值的类名,类名必须是完整的命名空间(使用"."分割);若是ClassObject类型,表示要设置静态属性的类对象;若是InstanceObject类型,表示要设置属性值的实例对象。
+name:要设置的属性名称,如果指定的属性名称不存在,则设置属性失败,返回null。
+value:要设置的属性值,其类型必须与Native层obj对象的属性区配,否则设置操作不生效,将保留以前的值。
+注意:同样导入类对象后也可以调用此方法,obj参数类型为ClassObject时,其作用与ClassObject.plusSetAttribute方法一致。obj参数类型为InstanceObject时,其作用与InstanceObject.plusSetAttribute方法一致。
+
+示例:
+
+不导入类对象设置类的静态属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 设置类的静态属性值
+ NjsHello.count = 2;
+ System.out.printf( "NjsHello Static's value: %d", NjsHello.count ); // 输出“NjsHello Static's value: 2”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 设置类的静态属性值
+plus.android.setAttribute( "io.dcloud.NjsHello", "count", 2 );
+console.log( "NjsHello Static's value: "+plus.android.getAttribute("io.dcloud.NjsHello","count") ); // 输出“NjsHello Static's value: 2”
+// ...
+复制代码
+导入类对象,创建实例对象,并设置其name属性值 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ // 设置其name属性值
+ hello.name = "Tester";
+ System.out.printf( "NjsHello Object's name: %s", hello.name ); // 输出“NjsHello Object's name: Tester”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 创建对象的实例
+var hello = plus.android.newObject( "io.dcloud.NjsHello" );
+// 设置其name属性值
+plus.android.setAttribute( hello, "name", "Tester" );
+console.log( "NjsHello Object's name: "+hello.plusGetAttribute("name") ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+plus.android.invoke
+若没有导入类对象,则无法通过实例对象的“.”操作符调用其成员方法,需通过以下方法调用实例对象的成员方法,方法原型如下:
+
+Object plus.android.invoke( String|Object obj, String name, Object... args );
+复制代码
+此方法也可以调用类对象或实例对象的方法,如果是类对象则调用的是类的静态方法,如果是实例对象则调用的是对象的普通成员方法。函数返回值是调用Native层方法运行后的返回值,Native对象的方法无返回值则返回undefined。
+
+obj:若是String类型,表示要调用静态方法的类名,类名必须包含完整的包名;若是ClassObject类型,表示要调用静态方法的类对象;若是InstanceObject类型,表示要调用成员方法的实例对象。
+name:要调用的方法名称,如果指定的方法不存在,则调用方法失败,返回值为null。
+args:调用方法的参数,其类型和数目必须与Native层对象方法的函数区配,否则无法调用对象的方法,将返回null。
+注意:同样导入类对象后也可以调用此方法,其作用与通过类对象或实例对象的“.”操作符调用方法作用一致。
+
+示例: 1.不导入类对象,调用类的静态方法 Java代码:
+
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 调用类的静态方法
+ NjsHello.testCount();
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 调用类的静态方法
+plus.android.invoke( "io.dcloud.NjsHello", "testCount" );
+// ...
+复制代码
+不导入类对象,创建实例对象,并调用其updateNmae方法 Java代码:
+import io.dcloud.NjsHello;
+//...
+public class Test {
+public static void main( String args[] ) {
+ // 创建对象的实例
+ NjsHello hello = new NjsHello();
+ // 调用updateName方法
+ hello.updateName( "Tester" );
+ System.out.printf( "NjsHello Object's name: %s", name ); // 输出“NjsHello Object's name: Tester”
+ //...
+}
+//...
+}
+复制代码
+NJS代码:
+
+// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello
+// 创建对象的实例
+var hello = plus.android.newObject( "io.dcloud.NjsHello" );
+// 调用updateName方法
+plus.android.invoke( hello, "updateName", "Tester" );
+console.log( "NjsHello Object's name: "+hello.getAttribute("name") ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+完整API文档参考:HTML5+ API - Native.js for Android
+
+API on iOS
+plus.ios.newObject
+不导入类对象直接创建类的实例对象,方法原型如下:
+
+InstanceObject plus.ios.newObject( String classname, Object..args );
+复制代码
+此方法会在Native层中对类进行实例化操作,创建一个类的实体并返回NJS层的类实例对象。相比导入类对象后使用new操作符创建对象效率要高。
+
+classname:要创建实例对象的类名,如果指定的类名不存在,则创建对象失败,返回null。
+args:调用类构造函数的参数,其类型和数目必须与Native层对象构造函数区配,否则无法创建类对象,将返回null。
+注意:由于没有导入类对象,所以通过此方法创建的实例对象无法通过“.”操作符直接调用对象的方法,而必须使用plus.ios.invoke方法来调用。classname参数值为“@selector”表示需要创建一个函数指针对象,与Objective-C中的@selector指令功能相似,args参数为函数的名称,此时函数的名称需要包含“:”字符。
+
+示例:
+
+不导入类创建实例对象 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // ...
+}
+复制代码
+NJS代码:
+
+// 未导入“NjsHello”类
+// 创建对象的实例
+var hello = plus.ios.newObject( "NjsHello" );
+// ...
+复制代码
+plus.ios.invoke
+若没有导入类对象,则无法通过实例对象的“.”操作符调用其成员方法,需通过以下方法调用实例对象的成员方法,方法原型如下:
+
+Object plus.ios.invoke( String|Object obj, String name, Object... args );
+复制代码
+此方法也可以调用类对象或实例对象的方法,如果是类对象则调用的是类的静态方法,如果是实例对象则调用的是对象的普通成员方法。函数返回值是调用Native层方法运行后的返回值,Native对象的方法无返回值则返回undefined。
+
+obj:若是String类型,表示要调用静态方法的类名,类名必须包含完整的包名;若是ClassObject类型,表示要调用静态方法的类对象;若是InstanceObject类型,表示要调用成员方法的实例对象。
+name:要调用的方法名称,必须保留方法名称中的“:”字符,如果指定的方法不存在,则调用方法失败,返回值为null。
+args:调用方法的参数,其类型和数目必须与Native层对象方法的函数区配,否则无法调用对象的方法,将返回null。
+注意:同样导入类对象后也可以调用此方法,其作用与通过类对象或实例对象的“.”操作符调用方法作用一致。
+
+示例:
+
+不导入类创建实例对象,并调用updateName方法 Objective-C代码:
+#import "njshello.h"
+int main( int argc, char *argv[] )
+{
+ // 创建对象的实例
+ NjsHello* hello = [[NjsHello alloc] init];
+ // 调用updateName方法
+ [hello updateName:@"Tester"];
+ NSLog(@"NjsHello Object's name: %@",hello.name); // 输出“NjsHello Object's name: Tester”
+ // ...
+}
+复制代码
+NJS代码:
+
+// 未导入“NjsHello”类
+// 创建对象的实例
+var hello = plus.ios.newObject( "NjsHello" );
+// 调用updateName方法
+plus.ios.invoke( hello, "updateName", "Tester" );
+console.log( "NjsHello Object's name: "+hello.getAttribute("name") ); // 输出“NjsHello Object's name: Tester”
+// ...
+复制代码
+完整API文档参考:HTML5+ API - Native.js for iOS
+
+性能优化
+调整代码结构优化
+前面章节中我们介绍如何通过NJS调用Native API来显示系统提示框,在真机运行时会发现第一次调用时会有0.5s左右的延时,再次调用则不会延时。这是因为NJS中导入类对象操作会花费较长的时间,再次调用时由于类对象已经导入过,会能很快执行完毕。因此可以调整代码结构进行优化,在页面打开后触发的“plusready”事件中进行类对象的导入操作,从而避免第一次调用的延时。
+
+Android平台调整NJS代码结构如下:
+
+// 保存Android导入对象和全局环境对象
+var AlertDialog=null,mainActivity=null;
+// H5+事件处理
+document.addEventListener("plusready",function(){
+ switch ( plus.os.name ) {
+ case "Android":
+ // 程序全局环境对象,内部自动导入Activity类
+ mainActivity = plus.android.runtimeMainActivity();
+ // 导入AlertDialog类
+ AlertDialog = plus.android.importClass("android.app.AlertDialog");
+ break;
+ default:
+ break;
+ }
+},false);
+//...
+/**
+ * 在Android平台通过NJS显示系统提示框
+ */
+function njsAlertForAndroid(){
+ // 创建提示框构造对象,构造函数需要提供程序全局环境对象,通过plus.android.runtimeMainActivity()方法获取
+ var dlg = new AlertDialog.Builder(mainActivity);
+ // 设置提示框标题
+ dlg.setTitle("自定义标题");
+ // 设置提示框内容
+ dlg.setMessage("使用NJS的原生弹出框,可自定义弹出框的标题、按钮");
+ // 设置提示框按钮
+ dlg.setPositiveButton("确定(或者其他字符)",null);
+ // 显示提示框
+ dlg.show();
+}
+//...
+复制代码
+iOS平台调整NJS代码结构如下:
+
+// 保存iOS平台导入的类对象
+var UIAlertView=null;
+// H5+事件处理
+document.addEventListener("plusready",function(){
+ switch ( plus.os.name ) {
+ case "iOS":
+ // 导入UIAlertView类
+ UIAlertView = plus.ios.importClass("UIAlertView");
+ break;
+ default:
+ break;
+ }
+},false);
+//...
+/**
+ * 在iOS平台通过NJS显示系统提示框
+ */
+function njsAlertForiOS(){
+ // 创建UIAlertView类的实例对象
+ var view = new UIAlertView();
+ // 设置提示对话上的内容
+ view.initWithTitlemessagedelegatecancelButtonTitleotherButtonTitles("自定义标题" // 提示框标题
+ , "使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容
+ , null // 操作提示框后的通知代理对象,暂不设置
+ , "确定(或者其他字符)" // 提示框上取消按钮的文字
+ , null ); // 提示框上其它按钮的文字,设置为null表示不显示
+ // 调用show方法显示提示对话框
+ view.show();
+}
+//...
+复制代码
+使用高级API优化
+前面章节中我们提到导入类对象会消耗较多的系统资源,导入过多的类对象会影响性能。在高级API中提供一组接口可以在不导入类对象的情况下调用Native API,从而提升代码运行性能。
+
+Android平台使用高级API优化代码如下:
+
+// 保存Android导入对象和全局环境对象
+var mainActivity=null;
+// H5+事件处理
+document.addEventListener("plusready",function(){
+ switch ( plus.os.name ) {
+ case "Android":
+ // 程序全局环境对象,内部自动导入Activity类
+ mainActivity = plus.android.runtimeMainActivity();
+ break;
+ default:
+ break;
+ }
+},false);
+//...
+/**
+ * 在Android平台通过NJS显示系统提示框
+ */
+function njsAlertForAndroid(){
+ // 由于Builder类是android.app.AlertDialog类的内部类,这里需要使用$符号分割
+ var dlg = plus.android.newObject("android.app.AlertDialog$Builder",mainActivity);
+ // 设置提示框标题
+ plus.android.invoke(dlg,"setTitle","自定义标题");
+ // 设置提示框内容
+ plus.android.invoke(dlg,"setMessage","使用NJS的原生弹出框,可自定义弹出框的标题、按钮");
+ // 设置提示框按钮
+ plus.android.invoke(dlg,"setPositiveButton","确定(或者其他字符)",null);
+ // 显示提示框
+ plus.android.invoke(dlg,"show");
+}
+//...
+复制代码
+iOS平台使用高级API优化代码如下:
+
+/**
+ * 在iOS平台通过NJS显示系统提示框
+ */
+function njsAlertForiOS(){
+ // 创建UIAlertView类的实例对象
+ var view = plus.ios.newObject("UIAlertView");
+ // 设置提示对话上的内容,这里的方法名称中必须包含':'字符
+ plus.ios.invoke(view,"initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:"
+ ,"自定义标题" // 提示框标题
+ , "使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容
+ , null // 操作提示框后的通知代理对象,暂不设置
+ , "确定(或者其他字符)" // 提示框上取消按钮的文字
+ , null ); // 提示框上其它按钮的文字,设置为null表示不显示
+ // 调用show方法显示提示对话框,在JS中使用()语法调用对象的方法
+ plus.ios.invoke(view,"show");
+}
+//...
diff --git a/pages.config.ts b/pages.config.ts
index 0cdc2ee..890d067 100644
--- a/pages.config.ts
+++ b/pages.config.ts
@@ -9,7 +9,7 @@ export default defineUniPages({
backgroundTextStyle: '@bgTxtStyle',
navigationBarBackgroundColor: '#ffffff',
navigationBarTextStyle: '@navTxtStyle',
- navigationBarTitleText: '全能查',
+ navigationBarTitleText: '',
navigationStyle: 'default',
},
})
diff --git a/src/App.vue b/src/App.vue
index ddf6775..64a6dda 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,8 +1,7 @@
diff --git a/src/app.scss b/src/app.scss
index b7fba8e..ff5cc1f 100644
--- a/src/app.scss
+++ b/src/app.scss
@@ -42,3 +42,11 @@ html.dark {
display: none; /* Chrome, Safari, and Edge */
}
+.disclaimer {
+ padding: 10px;
+ font-size: 12px;
+ color: #999;
+ text-align: center;
+ border-top: 1px solid #e0e0e0;
+ padding-bottom: 40px;
+}
diff --git a/src/components.d.ts b/src/components.d.ts
index c416ca9..9482876 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -15,8 +15,12 @@ declare module 'vue' {
LExpandCollapse: typeof import('./components/LExpandCollapse.vue')['default']
LTable: typeof import('./components/LTable.vue')['default']
LTitle: typeof import('./components/LTitle.vue')['default']
+ WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
+ WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default']
WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
+ WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
+ WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
WdLoadmore: typeof import('wot-design-uni/components/wd-loadmore/wd-loadmore.vue')['default']
WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
diff --git a/src/components/WebviewPage.vue b/src/components/WebviewPage.vue
index 3c5f947..1b39c65 100644
--- a/src/components/WebviewPage.vue
+++ b/src/components/WebviewPage.vue
@@ -16,9 +16,11 @@ onMounted(() => {
})
})
const token = uni.getStorageSync('token') // 从本地缓存中获取 token
-
+// const baseUrl = `${window.location.origin}/app`
+const baseUrl = 'https://www.quannengcha.com/app'
+// const baseUrl = 'http://localhost:5678'
const webviewUrl = computed(() => {
- const url = new URL(props.webviewSrc)
+ const url = new URL(baseUrl + props.webviewSrc)
if (token) {
url.searchParams.set('token', token) // 在 URL 中添加 token 参数
}
@@ -26,30 +28,46 @@ const webviewUrl = computed(() => {
})
const isLoading = ref(true) // 控制加载动画显示状态
+const processedMessages = new Set() // 存储已处理的消息ID
// 页面加载完成时,隐藏加载动画
-function handleLoaded(e) {
- console.log('webview loaded', e)
+function handleLoaded() {
isLoading.value = false
}
// 监听消息事件,隐藏加载动画
window.addEventListener('message', (event) => {
- const data = event.data
- if (data.hello || data.wappalyzer)
+ const message = event.data
+ const action = message?.action
+ const messageId = message?.messageId
+ const data = message?.data
+ if (message.hello || message.wappalyzer)
+ return
+ if (!action)
+ return
+ if (processedMessages.has(messageId)) {
return
- console.log('message', data)
-
- if (data?.loaded) {
- console.log('loaded')
- isLoading.value = false
}
- else if (data?.type === 'payment') {
+ processedMessages.add(messageId)
+ if (action === 'loaded') {
+ if (data)
+ isLoading.value = false
+ }
+ else if (action === 'navigateTo') {
+ uni.navigateTo(data)
+ }
+ else if (action === 'redirectTo') {
+ uni.redirectTo(data)
+ }
+ else if (action === 'navigateBack') {
+ uni.navigateBack(data)
+ }
+ else if (action === 'payment') {
payment(data)
}
})
function payment(data) {
- window.location.href = data.data
+ window.location.href = data
}
diff --git a/src/layouts/home.vue b/src/layouts/home.vue
index 4df19a5..4da3bbc 100644
--- a/src/layouts/home.vue
+++ b/src/layouts/home.vue
@@ -29,6 +29,11 @@ onMounted(() => {
const pageName = currentPage.split('/').pop()
tabbar.value = pageName
})
+function toComplaint() {
+ uni.navigateTo({
+ url: '/pages/complaint',
+ })
+}
-
-
-
-
-
-
-
-
-
-
diff --git a/src/layouts/page.vue b/src/layouts/page.vue
index 2c75e60..11c6297 100644
--- a/src/layouts/page.vue
+++ b/src/layouts/page.vue
@@ -1,4 +1,36 @@
@@ -6,5 +38,5 @@
diff --git a/src/manifest.json b/src/manifest.json
index 611c189..b7e4704 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,5 +1,5 @@
{
- "name": "qnc-app",
+ "name": "全能查-司法涉诉_婚恋信息_企业查询平台-学宇思科技",
"appid": "__UNI__CC3DA09",
"description": "",
"versionName": "1.0.0",
@@ -63,6 +63,11 @@
"enable": false
},
"vueVersion": "3",
+ "plugins": {
+ "urlLauncher": {
+ "path": "plugins/urlLauncher"
+ }
+ },
"h5": {
"darkmode": false,
"themeLocation": "theme.json"
diff --git a/src/pages.json b/src/pages.json
index 990149c..e542eed 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -16,9 +16,17 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/complaint",
+ "type": "page",
+ "layout": "page",
+ "title": "投诉服务"
+ },
{
"path": "pages/example",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "示例报告"
},
{
"path": "pages/history_query",
@@ -28,23 +36,33 @@
},
{
"path": "pages/inquire",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "报告查询"
},
{
"path": "pages/list_lawsuit",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "司法涉诉"
},
{
"path": "pages/list_marriage",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "婚姻评估"
},
{
"path": "pages/list_risk",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "风险评估"
},
{
"path": "pages/list_verify",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "验证工具"
},
{
"path": "pages/login",
@@ -65,20 +83,27 @@
},
{
"path": "pages/privacyPolicy",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "隐私政策"
},
{
"path": "pages/report",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "报告结果"
},
{
- "path": "pages/result",
+ "path": "pages/service",
"type": "page",
- "layout": "page"
+ "layout": "page",
+ "title": "客户服务"
},
{
"path": "pages/userAgreement",
- "type": "page"
+ "type": "page",
+ "layout": "page",
+ "title": "用户协议"
}
],
"globalStyle": {
@@ -88,7 +113,7 @@
"backgroundTextStyle": "@bgTxtStyle",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "@navTxtStyle",
- "navigationBarTitleText": "全能查",
+ "navigationBarTitleText": "",
"navigationStyle": "default"
},
"subPackages": []
diff --git a/src/pages/ai.vue b/src/pages/ai.vue
index 33e5bb7..6f4e506 100644
--- a/src/pages/ai.vue
+++ b/src/pages/ai.vue
@@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue'
const userMessage = ref('')
const messages = ref([
- { sender: 'ai', text: 'Welcome! How can I assist you today?' },
+ { sender: 'ai', text: '欢迎!请问有什么可以帮助您的吗?' },
])
function sendMessage() {
@@ -12,42 +12,62 @@ function sendMessage() {
messages.value.push({ sender: 'user', text: userMessage.value })
- // Simulate AI response (for example purposes)
+ // AI 统一回复(中文套话)
setTimeout(() => {
messages.value.push({
sender: 'ai',
- text: `I'm here to assist with your questions: "${userMessage.value}"`,
+ text: '感谢您的提问!我们会尽力为您提供帮助。',
})
}, 1000)
userMessage.value = ''
}
+const safeAreaTop = ref(44)
+onShow(() => {
+ uni.getSystemInfo({
+ success: (res) => {
+ if (res.safeArea && res.safeArea.top) {
+ safeAreaTop.value = res.safeArea.top // 设置安全区顶部距离
+ }
+ },
+ })
+})
-
-
-
-
- AI: {{ message.text }}
-
-
- User: {{ message.text }}
+
+
+
+
+
+ {{ message.text }}
+
+
+ {{ message.text }}
+
+
+
+
+ 发送
+
+
-
-
-
- 发送
-
-
+
+
+
+ 备案号:琼ICP备2024038584号-2
+
+
+ 海南省学宇思网络科技有限公司版权所有
+
@@ -62,16 +82,6 @@ function sendMessage() {
// #endif
}
-
-// .chat-window {
-// flex-grow: 1;
-// overflow-y: auto;
-// overflow-x: hidden;
-// }
-
-// .input-area {
-// flex-shrink: 0;
-// }
diff --git a/src/pages/complaint.vue b/src/pages/complaint.vue
new file mode 100644
index 0000000..6ce6a09
--- /dev/null
+++ b/src/pages/complaint.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ {
+ "layout": "page",
+ "title": "投诉服务"
+ }
+
diff --git a/src/pages/example.vue b/src/pages/example.vue
index 19f3516..e3654d8 100644
--- a/src/pages/example.vue
+++ b/src/pages/example.vue
@@ -1,10 +1,29 @@
+
+
+ {
+ "layout": "page",
+ "title": "示例报告"
+ }
+
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 60eb453..39e8350 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -1,8 +1,10 @@
-
+
@@ -114,6 +321,14 @@ function toHistory() {
+
+
+ 备案号:琼ICP备2024038584号-2
+
+
+ 海南省学宇思网络科技有限公司版权所有
+
+
-
-
- {
- "layout": "page"
- }
-
diff --git a/src/pages/service.vue b/src/pages/service.vue
new file mode 100644
index 0000000..4437da7
--- /dev/null
+++ b/src/pages/service.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ {
+ "layout": "page",
+ "title": "客户服务"
+ }
+
diff --git a/src/pages/userAgreement.vue b/src/pages/userAgreement.vue
index 35ed885..1488028 100644
--- a/src/pages/userAgreement.vue
+++ b/src/pages/userAgreement.vue
@@ -1,10 +1,17 @@
+
+
+ {
+ "layout": "page",
+ "title": "用户协议"
+ }
+
diff --git a/src/plugins/urlLauncher/index.js b/src/plugins/urlLauncher/index.js
new file mode 100644
index 0000000..a1300d7
--- /dev/null
+++ b/src/plugins/urlLauncher/index.js
@@ -0,0 +1,17 @@
+function launch(url) {
+ return new Promise((resolve, reject) => {
+ // 调用原生插件的 launch 方法
+ uni.requireNativePlugin('urlLauncher').launch({ url }, (res) => {
+ if (res.success) {
+ resolve()
+ }
+ else {
+ reject(res.message)
+ }
+ })
+ })
+}
+
+export default {
+ launch,
+}
diff --git a/src/plugins/urlLauncher/ios/urlLauncherPlugin.h b/src/plugins/urlLauncher/ios/urlLauncherPlugin.h
new file mode 100644
index 0000000..e95358d
--- /dev/null
+++ b/src/plugins/urlLauncher/ios/urlLauncherPlugin.h
@@ -0,0 +1,7 @@
+#import
+#import
+#import
+#import
+
+@interface UrlLauncherPlugin : NSObject
+@end
diff --git a/src/plugins/urlLauncher/ios/urlLauncherPlugin.m b/src/plugins/urlLauncher/ios/urlLauncherPlugin.m
new file mode 100644
index 0000000..f4e176b
--- /dev/null
+++ b/src/plugins/urlLauncher/ios/urlLauncherPlugin.m
@@ -0,0 +1,28 @@
+#import "urlLauncherPlugin.h"
+
+@implementation UrlLauncherPlugin
+
+// 实现插件的启动方法
+- (void)launch:(NSDictionary*)arguments callback:(UniReturnValueCallback)callback {
+ NSString *urlString = arguments[@"url"];
+ if (!urlString) {
+ callback(@{@"success": @(NO), @"message": @"URL is missing"});
+ return;
+ }
+
+ NSURL *url = [NSURL URLWithString:urlString];
+ if (!url) {
+ callback(@{@"success": @(NO), @"message": @"Invalid URL"});
+ return;
+ }
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
+ SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:url];
+ [rootVC presentViewController:safariVC animated:YES completion:^{
+ callback(@{@"success": @(YES)});
+ }];
+ });
+}
+
+@end
diff --git a/src/uni-pages.d.ts b/src/uni-pages.d.ts
index 14498bb..58e878e 100644
--- a/src/uni-pages.d.ts
+++ b/src/uni-pages.d.ts
@@ -6,6 +6,7 @@
interface NavigateToOptions {
url: "/pages/index" |
"/pages/ai" |
+ "/pages/complaint" |
"/pages/example" |
"/pages/history_query" |
"/pages/inquire" |
@@ -17,7 +18,7 @@ interface NavigateToOptions {
"/pages/me" |
"/pages/privacyPolicy" |
"/pages/report" |
- "/pages/result" |
+ "/pages/service" |
"/pages/userAgreement";
}
interface RedirectToOptions extends NavigateToOptions {}
diff --git a/src/utils/request.js b/src/utils/request.js
index fec6bd3..0579246 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -1,8 +1,4 @@
-let BASE_URL = '/api/v1'
-
-// #ifdef APP || MP-WEIXIN
-BASE_URL = 'https://6m4685017o.goho.co/api/v1'
-// #endif
+const BASE_URL = '/api/v1'
function request(options) {
return new Promise((resolve, reject) => {
diff --git a/vite.config.ts b/vite.config.ts
index cb6ca92..45b653a 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -46,6 +46,11 @@ export default async () => {
changeOrigin: true,
// rewrite: path => path.replace(/^\/api/, ''), // 将请求路径中的 '/api' 替换为空
},
+ // '/api/v1': {
+ // target: 'http://www.quannengcha.com', // 本地接口地址
+ // changeOrigin: true,
+ // // rewrite: path => path.replace(/^\/api/, ''), // 将请求路径中的 '/api' 替换为空
+ // },
},
},
})