HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

微信开放平台申请应用获取appkey

分享插件 appsecret
  1. 首先登陆微信开放平台
  2. 点击“创建移动应用”
  3. 填写“应用名称”“应用简介”并上传应用的图标文件,填写完成后点击“下一步”
  4. 选择支持的应用平台,并填写相应的平台信息
    IOS平台
    appstore下载地址在应用上传到appstroe上后填写。
    Android平台
    应用签名:安卓应用的唯一签名,签名方法可参考(给Android应用签名),使用Dcloud公用证书时打包时,可填写公用的应用签名,应用签名MD5值为(59201CF6589202CB2CDAB26752472112)。
    应用包名:用户使用HBuilder打安卓应用包时设置的包名,应当与打包时使用的包名一致。

提示: 设置提交后需要等待微信人工审核完成才能获取应用的Appkey和appsecret

继续阅读 »
  1. 首先登陆微信开放平台
  2. 点击“创建移动应用”
  3. 填写“应用名称”“应用简介”并上传应用的图标文件,填写完成后点击“下一步”
  4. 选择支持的应用平台,并填写相应的平台信息
    IOS平台
    appstore下载地址在应用上传到appstroe上后填写。
    Android平台
    应用签名:安卓应用的唯一签名,签名方法可参考(给Android应用签名),使用Dcloud公用证书时打包时,可填写公用的应用签名,应用签名MD5值为(59201CF6589202CB2CDAB26752472112)。
    应用包名:用户使用HBuilder打安卓应用包时设置的包名,应当与打包时使用的包名一致。

提示: 设置提交后需要等待微信人工审核完成才能获取应用的Appkey和appsecret

收起阅读 »

腾讯微博appkey申请方法

分享插件
  1. 首先登陆腾讯微博开放平台
  2. 点击页面上的“管理中心”
  3. 点击页面上的“创建应用”
  4. 在弹出框中选择“无线应用”然后点击确定
  5. 在创建应用页面填写应用信息,如应用名,应用的网址分类和支持的平台等信息然后点击提交,用户在填写应用网址时应当注意,应用网址需要和在manifest文件填写的“redirect_url”字段一致。
  6. 应用创建成功后和可获得这个应用的appkey和 AppSecret信息,将他们分别填入plus->distribute->plugins->share->tencent的appkey和appsecret属性下即可
继续阅读 »
  1. 首先登陆腾讯微博开放平台
  2. 点击页面上的“管理中心”
  3. 点击页面上的“创建应用”
  4. 在弹出框中选择“无线应用”然后点击确定
  5. 在创建应用页面填写应用信息,如应用名,应用的网址分类和支持的平台等信息然后点击提交,用户在填写应用网址时应当注意,应用网址需要和在manifest文件填写的“redirect_url”字段一致。
  6. 应用创建成功后和可获得这个应用的appkey和 AppSecret信息,将他们分别填入plus->distribute->plugins->share->tencent的appkey和appsecret属性下即可
收起阅读 »

web API图片上传

最近研究了下webapi服务器下图片的上传功能,屁话不多说,直接看代码吧

 public Task<HttpResponseMessage> PostFormData()  
        {  
            // Check if the request contains multipart/form-data.  
            // 检查该请求是否含有multipart/form-data  
            if (!Request.Content.IsMimeMultipartContent())  
            {  
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);  
            }  

            string root = HttpContext.Current.Server.MapPath("~/userImage");  
            var provider = new MultipartFormDataStreamProvider(root);  

            // Read the form data and return an async task.  
            // 读取表单数据,并返回一个async任务  
            var task = Request.Content.ReadAsMultipartAsync(provider).  
                ContinueWith<HttpResponseMessage>(t =>  
                {  
                    if (t.IsFaulted || t.IsCanceled)  
                    {  
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);  
                    }  

                    // This illustrates how to get the file names.  
                    // 以下描述了如何获取文件名  
                    foreach (MultipartFileData file in provider.FileData)  
                    {  
                        //新文件夹路径  
                        string newRoot = root + "\\" + provider.FormData.GetValues(1)[0].ToString();  
                        if (!Directory.Exists(newRoot))  
                        {  
                            Directory.CreateDirectory(newRoot);  
                        }  
                        Trace.WriteLine(file.Headers.ContentDisposition.FileName);  
                        Trace.WriteLine("Server file path: " + file.LocalFileName);  
                        if (File.Exists(file.LocalFileName))   
                        {  
                            //原文件名称  
                            string fileName = file.Headers.ContentDisposition.FileName.Substring(1, file.Headers.ContentDisposition.FileName.Length - 2);  
                            //新文件名称   随机数  
                            string newFileName = provider.FormData.GetValues(0)[0] + "." + fileName.Split(new char[] { '.' })[1];  
                            File.Move(file.LocalFileName, newRoot + "\\" + newFileName);  
                        }  
                    }  
                    return Request.CreateResponse(HttpStatusCode.OK);  
                });  

            return task;  
        }

这个也是在网上找的资料,在此基础上添加了修改文件名功能,图片会保存在userimage文件夹下的子目录(如没有userimage就手动创建个),子目录的名称为客户端task.addData("","")添加的内容,文件名为客户端生成的随机数.

继续阅读 »

最近研究了下webapi服务器下图片的上传功能,屁话不多说,直接看代码吧

 public Task<HttpResponseMessage> PostFormData()  
        {  
            // Check if the request contains multipart/form-data.  
            // 检查该请求是否含有multipart/form-data  
            if (!Request.Content.IsMimeMultipartContent())  
            {  
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);  
            }  

            string root = HttpContext.Current.Server.MapPath("~/userImage");  
            var provider = new MultipartFormDataStreamProvider(root);  

            // Read the form data and return an async task.  
            // 读取表单数据,并返回一个async任务  
            var task = Request.Content.ReadAsMultipartAsync(provider).  
                ContinueWith<HttpResponseMessage>(t =>  
                {  
                    if (t.IsFaulted || t.IsCanceled)  
                    {  
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);  
                    }  

                    // This illustrates how to get the file names.  
                    // 以下描述了如何获取文件名  
                    foreach (MultipartFileData file in provider.FileData)  
                    {  
                        //新文件夹路径  
                        string newRoot = root + "\\" + provider.FormData.GetValues(1)[0].ToString();  
                        if (!Directory.Exists(newRoot))  
                        {  
                            Directory.CreateDirectory(newRoot);  
                        }  
                        Trace.WriteLine(file.Headers.ContentDisposition.FileName);  
                        Trace.WriteLine("Server file path: " + file.LocalFileName);  
                        if (File.Exists(file.LocalFileName))   
                        {  
                            //原文件名称  
                            string fileName = file.Headers.ContentDisposition.FileName.Substring(1, file.Headers.ContentDisposition.FileName.Length - 2);  
                            //新文件名称   随机数  
                            string newFileName = provider.FormData.GetValues(0)[0] + "." + fileName.Split(new char[] { '.' })[1];  
                            File.Move(file.LocalFileName, newRoot + "\\" + newFileName);  
                        }  
                    }  
                    return Request.CreateResponse(HttpStatusCode.OK);  
                });  

            return task;  
        }

这个也是在网上找的资料,在此基础上添加了修改文件名功能,图片会保存在userimage文件夹下的子目录(如没有userimage就手动创建个),子目录的名称为客户端task.addData("","")添加的内容,文件名为客户端生成的随机数.

收起阅读 »

深入理解高度。获取屏幕、webview、软键盘高度

Native.JS Webview 软键盘 输入法 高度

如果没有手动调整过webview的高度的话,默认情况下,屏幕的高度=顶部状态栏的高度+webview的高度。
如果软键盘打开,则屏幕的高度=顶部状态栏的高度+webview的高度+软键盘的高度。
HTML5 规范目前没有提供状态栏高度和软键盘高度的直接的查询方法,不过有了Native.js,我们还是能查询到所有这些高度的数值。

背景知识介绍:

手机屏幕有真实的物理分辨率,比如小米note的高度是1920px。  
但在网页里,一个10px的字体,并不会小的看不清,因为webview提供了逻辑分辨率的概念。  
如果不在meta里设置,默认下小米note的放大系数scale是3,就是会放大3倍显示。  
也就是对于HTML而言,小米note的高度是1920/3=640px。  
如果网页是全屏的,没有顶部状态栏,那么一个640px高的div将撑满屏幕高度。  

获取屏幕、顶部状态栏和软键盘的高度

1. 屏幕的高度

获取屏幕的高度很简单,HTML自带了screen.height,直接就可以得到屏幕的整体高度,单位是px,物理分辨率值(不是HTML的逻辑分辨率)。  
HTML5Plus里提供了plus.screen.resolutionHeight方法,也是屏幕高度,但这个值是逻辑分辨率的高度。参考[http://html5plus.org/doc/zh_cn/device.html#plus.screen](http://html5plus.org/doc/zh_cn/device.html#plus.screen)  
screen.height = plus.screen.resolutionHeight*plus.screen.scale  

2. 获取webview高度

虽然webview的getStyle可以得到webview的高度,但开发者如果不手动设置的话,默认值是100%,这个值对本文探讨的问题没有意义。我们需要px的物理高度。  
在Android里通过如下js代码可以得到webview的高度:plus.android.invoke(plus.android.currentWebview(),"getHeight")   
这是一段Native.js代码,由于Android的webview原生对象就有getHeight()方法,所以就可以直接这样调用。  
当然webview原生对象还有很多方法属性都可以调,具体参阅[Native.js入门](http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/88)  
图1(此图中,物理分辨率是蓝色字体,逻辑分辨率是黑色字体) 对于iOS,就没必要使用Native.js这么复杂的技术了,iOS的屏幕高度是固定的几个,直接判断屏幕高度和设备型号就可以了。

3. 获取状态栏高度

顶部状态栏比较复杂,如果webview设了全屏,那么状态栏高度就为0。  
如果设置了沉浸式状态栏,状态栏透明了,虽然状态栏存在理论高度,但webview高度是全屏的。  
plus.navigator.getStatusbarHeight(),这个api专门获取状态栏高度。  

4. 获取输入法高度

当弹出输入法时,在Android上,webview的高度会自动减少,留出空间给软键盘。  
那么输入法高度=屏幕高度-状态栏高度-webview高度  
在小米note上,默认输入法高度是 863px。  
图2(此图中,物理分辨率是蓝色字体,逻辑分辨率是黑色字体)

5. 流应用任务栏高度

在流应用环境中,比如iOS流应用,会有一个流应用任务栏,这个任务栏的出现会挤压webview的高度。  
如果开发者要设置一个元素居底,请使用bottom方法,而不是通过屏幕高度-webview高度设top,以避免出现流应用任务栏时高度错位。  

说说HTML里的几个高度

其实HTML自己也提供了很多高度相关的api,除了screen.height还有document.body.clientHeight,document.body.scrollHeight,感觉也很容易混淆。  
document.body.clientHeight是网页内容区的有效高度,符合盒模型。document.body.scrollHeight是网页可滚动区域的高度。  
如图2所示:  
- 此时document.body.clientHeight小于webview高度,而document.body.scrollHeight等于webview高度,即document.body.scrollHeight=plus.android.invoke(plus.android.currentWebview(),"getHeight") 。  
- 如果数字不是1-5,而是1-10,那么document.body.clientHeight会继续增加,但内容不够多,不会滚动,document.body.scrollHeight不变,仍是webview高度。  
- 如果网页内容非常多,数字到了40,那document.body.clientHeight会继续增加,并且只要发生了滚动,则document.body.clientHeight=document.body.scrollHeight  

其他相关知识。

  • 监控软键盘是否弹出,Android上可以使用HTML自带的resize事件。
    但是要判断横竖屏,因为横竖屏切换也会造成resize,所以高度变而宽度不变,就是软键盘弹出或消失了。
  • 强制弹出键盘,也有Native.js示例,http://ask.dcloud.net.cn/question/2324
  • hello uni-app和hello mui都有聊天示例模板,有底部输入框跟随键盘顶起的示例,可以参考下。
继续阅读 »

如果没有手动调整过webview的高度的话,默认情况下,屏幕的高度=顶部状态栏的高度+webview的高度。
如果软键盘打开,则屏幕的高度=顶部状态栏的高度+webview的高度+软键盘的高度。
HTML5 规范目前没有提供状态栏高度和软键盘高度的直接的查询方法,不过有了Native.js,我们还是能查询到所有这些高度的数值。

背景知识介绍:

手机屏幕有真实的物理分辨率,比如小米note的高度是1920px。  
但在网页里,一个10px的字体,并不会小的看不清,因为webview提供了逻辑分辨率的概念。  
如果不在meta里设置,默认下小米note的放大系数scale是3,就是会放大3倍显示。  
也就是对于HTML而言,小米note的高度是1920/3=640px。  
如果网页是全屏的,没有顶部状态栏,那么一个640px高的div将撑满屏幕高度。  

获取屏幕、顶部状态栏和软键盘的高度

1. 屏幕的高度

获取屏幕的高度很简单,HTML自带了screen.height,直接就可以得到屏幕的整体高度,单位是px,物理分辨率值(不是HTML的逻辑分辨率)。  
HTML5Plus里提供了plus.screen.resolutionHeight方法,也是屏幕高度,但这个值是逻辑分辨率的高度。参考[http://html5plus.org/doc/zh_cn/device.html#plus.screen](http://html5plus.org/doc/zh_cn/device.html#plus.screen)  
screen.height = plus.screen.resolutionHeight*plus.screen.scale  

2. 获取webview高度

虽然webview的getStyle可以得到webview的高度,但开发者如果不手动设置的话,默认值是100%,这个值对本文探讨的问题没有意义。我们需要px的物理高度。  
在Android里通过如下js代码可以得到webview的高度:plus.android.invoke(plus.android.currentWebview(),"getHeight")   
这是一段Native.js代码,由于Android的webview原生对象就有getHeight()方法,所以就可以直接这样调用。  
当然webview原生对象还有很多方法属性都可以调,具体参阅[Native.js入门](http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/88)  
图1(此图中,物理分辨率是蓝色字体,逻辑分辨率是黑色字体) 对于iOS,就没必要使用Native.js这么复杂的技术了,iOS的屏幕高度是固定的几个,直接判断屏幕高度和设备型号就可以了。

3. 获取状态栏高度

顶部状态栏比较复杂,如果webview设了全屏,那么状态栏高度就为0。  
如果设置了沉浸式状态栏,状态栏透明了,虽然状态栏存在理论高度,但webview高度是全屏的。  
plus.navigator.getStatusbarHeight(),这个api专门获取状态栏高度。  

4. 获取输入法高度

当弹出输入法时,在Android上,webview的高度会自动减少,留出空间给软键盘。  
那么输入法高度=屏幕高度-状态栏高度-webview高度  
在小米note上,默认输入法高度是 863px。  
图2(此图中,物理分辨率是蓝色字体,逻辑分辨率是黑色字体)

5. 流应用任务栏高度

在流应用环境中,比如iOS流应用,会有一个流应用任务栏,这个任务栏的出现会挤压webview的高度。  
如果开发者要设置一个元素居底,请使用bottom方法,而不是通过屏幕高度-webview高度设top,以避免出现流应用任务栏时高度错位。  

说说HTML里的几个高度

其实HTML自己也提供了很多高度相关的api,除了screen.height还有document.body.clientHeight,document.body.scrollHeight,感觉也很容易混淆。  
document.body.clientHeight是网页内容区的有效高度,符合盒模型。document.body.scrollHeight是网页可滚动区域的高度。  
如图2所示:  
- 此时document.body.clientHeight小于webview高度,而document.body.scrollHeight等于webview高度,即document.body.scrollHeight=plus.android.invoke(plus.android.currentWebview(),"getHeight") 。  
- 如果数字不是1-5,而是1-10,那么document.body.clientHeight会继续增加,但内容不够多,不会滚动,document.body.scrollHeight不变,仍是webview高度。  
- 如果网页内容非常多,数字到了40,那document.body.clientHeight会继续增加,并且只要发生了滚动,则document.body.clientHeight=document.body.scrollHeight  

其他相关知识。

  • 监控软键盘是否弹出,Android上可以使用HTML自带的resize事件。
    但是要判断横竖屏,因为横竖屏切换也会造成resize,所以高度变而宽度不变,就是软键盘弹出或消失了。
  • 强制弹出键盘,也有Native.js示例,http://ask.dcloud.net.cn/question/2324
  • hello uni-app和hello mui都有聊天示例模板,有底部输入框跟随键盘顶起的示例,可以参考下。
收起阅读 »

自动+手动在线升级

升级 更新

文章在这
贴错了
http://ask.dcloud.net.cn/question/5022

文章在这
贴错了
http://ask.dcloud.net.cn/question/5022

手动检测版本更新的代码

更新 升级

官方提供了自动检测更新的代码,我这里稍微更改了一下,可以手动检测更新。

不过建议使用App资源在线升级更新
我这里也提供了自动+手动的App资源在线升级

<ul class="mui-table-view" style="margin-top: 25px;">  
                <li class="mui-table-view-cell">  
                    <a id="onlineupgrade">  
                    在线升级 <span class="mui-pull-right" id="supgrade" style="color: red;display: none;">  
                        New  
                    </span>  
                    </a>  
                </li>  
            </ul>
    mui.plusReady(function() {  

            var supgrade = document.getElementById("supgrade");  

                //有新版本显示提示  
            mui.initUpdate(function() {  
                supgrade.style.display = "inline-block";  
            });  
            document.getElementById("onlineupgrade").addEventListener('tap', function() {  
                if (supgrade.style.display != "none") {  
                    mui.initUpdate();  
                }  
            });  
        });
(function($) {  
    //正式上线了请更改app更新地址  
    var server = "http://www.dcloud.io/helloh5/update.json", //获取升级描述文件服务器地址  
        localDir = "update",  
        localFile = "update.json", //本地保存升级描述目录和文件名  
        keyUpdate = "updateCheck", //取消升级键名  
        keyAbort = "updateAbort", //忽略版本键名  
        checkInterval = 3600000, //升级检查间隔,单位为ms,1小时为60*60*1000=3600000, 如果每次启动需要检查设置值为0  
        dir = null;  

    /**  
     * 准备升级操作  
     * 创建升级文件保存目录  
     * @param{Function} 有回调函数是手动检查折升级  
     */  
    $.initUpdate = function(callback) {  

        // 打开doc根目录  
        plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {  
            fs.root.getDirectory(localDir, {  
                create: true  
            }, function(entry) {  
                dir = entry;  
                checkUpdate(callback);  
            }, function(e) {  
                console.log("准备升级操作,打开update目录失败:" + e.message);  
            });  
        }, function(e) {  
            console.log("准备升级操作,打开doc目录失败:" + e.message);  
        });  
    }  

    /**  
     * 检测程序升级  
     * @author liuyf  2015-04-27  
     * @description 手动检测是否升级  是否已过期等标记在手动下无效  
     *  
     * @param{Function} 有回调函数是手动检查折升级  
     * */  
    function checkUpdate(callback) {  
        // 判断升级检测是否过期  
        var lastcheck = plus.storage.getItem(keyUpdate);  
        if (lastcheck) {  
            // 取消已过期,删除取消标记  
            plus.storage.removeItem(keyUpdate);  
        }  
        // 读取本地升级文件]  
        dir.getFile(localFile, {  
            create: false  
        }, function(fentry) {  
            fentry.file(function(file) {  
                var reader = new plus.io.FileReader();  
                reader.onloadend = function(e) {  
                    //检测升级的时候不删除本地升级文件  
                    if (!callback) {  
                        fentry.remove();  
                    }  
                    var data = null;  
                    try {  
                        data = JSON.parse(e.target.result);  
                    } catch (e) {  
                        console.log("读取本地升级文件,数据格式错误!");  
                    }  
                    checkUpdateData(data, callback);  
                }  
                reader.readAsText(file);  
            }, function(e) {  
                console.log("读取本地升级文件,获取文件对象失败:" + e.message);  
                fentry.remove();  
            });  
        }, function(e) {  
            // 失败表示文件不存在,从服务器获取升级数据  
            getUpdateData();  
        });  
    }  

    /**  
     * 检查升级数据  
     * @author liuyf 2015-04-27  
     * @description 手动升级 是否存在版本号等逻辑应舍弃  
     * @param{Function} 有回调函数是手动检查升级  
     */  
    function checkUpdateData(j, callback) {  
        //当前客户端版本号  
        var curVer = plus.runtime.version,  
            inf = j[plus.os.name];  

        if (inf) {  
            var srvVer = inf.version;  
            // 判断是否需要升级  
            if (compareVersion(curVer, srvVer)) {  
                if (!callback) {  
                    // 提示用户是否升级  
                    plus.ui.confirm(inf.note, function(i) {  
                        if (0 == i)  
                            plus.runtime.openURL(inf.url);  
                        else {  
                            plus.storage.setItem(keyUpdate, (new Date()).getTime().toString());  
                        }  
                    }, inf.title, ["立即更新", "取  消"]);  
                } else {  
                    callback();  
                }  
            }  
        }  
    }  

    /**  
     * 从服务器获取升级数据,并存储到本地;  
     */  
    function getUpdateData() {  
        mui.getJSON(server, {}, function(data) {  
            //appid一致,才将服务器上的版本数据保存到本地  
            if (data.appid == plus.runtime.appid) {  
                // 保存到本地文件中  
                dir.getFile(localFile, {  
                    create: true  
                }, function(fentry) {;  
                    fentry.createWriter(function(writer) {  
                        writer.onerror = function() {  
                            console.log("获取升级数据,保存文件失败!");  
                        }  
                        writer.write(data);  
                    }, function(e) {  
                        console.log("获取升级数据,创建写文件对象失败:" + e.message);  
                    });  
                }, function(e) {  
                    console.log("获取升级数据,打开保存文件失败:" + e.message);  
                });  
            }  
        });  
    }  

    /**  
     * 比较版本大小,如果新版本nv大于旧版本ov则返回true,否则返回false  
     * @param {String} ov  
     * @param {String} nv  
     * @return {Boolean}  
     */  
    function compareVersion(ov, nv) {  
        if (!ov || !nv || ov == "" || nv == "") {  
            return false;  
        }  
        var b = false,  
            ova = ov.split(".", 4),  
            nva = nv.split(".", 4);  
        for (var i = 0; i < ova.length && i < nva.length; i++) {  
            var so = ova[i],  
                no = parseInt(so),  
                sn = nva[i],  
                nn = parseInt(sn);  
            if (nn > no || sn.length > so.length) {  
                return true;  
            } else if (nn < no) {  
                return false;  
            }  
        }  
        if (nva.length > ova.length && 0 == nv.indexOf(ov)) {  
            return true;  
        }  
    }  
})(mui);
继续阅读 »

官方提供了自动检测更新的代码,我这里稍微更改了一下,可以手动检测更新。

不过建议使用App资源在线升级更新
我这里也提供了自动+手动的App资源在线升级

<ul class="mui-table-view" style="margin-top: 25px;">  
                <li class="mui-table-view-cell">  
                    <a id="onlineupgrade">  
                    在线升级 <span class="mui-pull-right" id="supgrade" style="color: red;display: none;">  
                        New  
                    </span>  
                    </a>  
                </li>  
            </ul>
    mui.plusReady(function() {  

            var supgrade = document.getElementById("supgrade");  

                //有新版本显示提示  
            mui.initUpdate(function() {  
                supgrade.style.display = "inline-block";  
            });  
            document.getElementById("onlineupgrade").addEventListener('tap', function() {  
                if (supgrade.style.display != "none") {  
                    mui.initUpdate();  
                }  
            });  
        });
(function($) {  
    //正式上线了请更改app更新地址  
    var server = "http://www.dcloud.io/helloh5/update.json", //获取升级描述文件服务器地址  
        localDir = "update",  
        localFile = "update.json", //本地保存升级描述目录和文件名  
        keyUpdate = "updateCheck", //取消升级键名  
        keyAbort = "updateAbort", //忽略版本键名  
        checkInterval = 3600000, //升级检查间隔,单位为ms,1小时为60*60*1000=3600000, 如果每次启动需要检查设置值为0  
        dir = null;  

    /**  
     * 准备升级操作  
     * 创建升级文件保存目录  
     * @param{Function} 有回调函数是手动检查折升级  
     */  
    $.initUpdate = function(callback) {  

        // 打开doc根目录  
        plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {  
            fs.root.getDirectory(localDir, {  
                create: true  
            }, function(entry) {  
                dir = entry;  
                checkUpdate(callback);  
            }, function(e) {  
                console.log("准备升级操作,打开update目录失败:" + e.message);  
            });  
        }, function(e) {  
            console.log("准备升级操作,打开doc目录失败:" + e.message);  
        });  
    }  

    /**  
     * 检测程序升级  
     * @author liuyf  2015-04-27  
     * @description 手动检测是否升级  是否已过期等标记在手动下无效  
     *  
     * @param{Function} 有回调函数是手动检查折升级  
     * */  
    function checkUpdate(callback) {  
        // 判断升级检测是否过期  
        var lastcheck = plus.storage.getItem(keyUpdate);  
        if (lastcheck) {  
            // 取消已过期,删除取消标记  
            plus.storage.removeItem(keyUpdate);  
        }  
        // 读取本地升级文件]  
        dir.getFile(localFile, {  
            create: false  
        }, function(fentry) {  
            fentry.file(function(file) {  
                var reader = new plus.io.FileReader();  
                reader.onloadend = function(e) {  
                    //检测升级的时候不删除本地升级文件  
                    if (!callback) {  
                        fentry.remove();  
                    }  
                    var data = null;  
                    try {  
                        data = JSON.parse(e.target.result);  
                    } catch (e) {  
                        console.log("读取本地升级文件,数据格式错误!");  
                    }  
                    checkUpdateData(data, callback);  
                }  
                reader.readAsText(file);  
            }, function(e) {  
                console.log("读取本地升级文件,获取文件对象失败:" + e.message);  
                fentry.remove();  
            });  
        }, function(e) {  
            // 失败表示文件不存在,从服务器获取升级数据  
            getUpdateData();  
        });  
    }  

    /**  
     * 检查升级数据  
     * @author liuyf 2015-04-27  
     * @description 手动升级 是否存在版本号等逻辑应舍弃  
     * @param{Function} 有回调函数是手动检查升级  
     */  
    function checkUpdateData(j, callback) {  
        //当前客户端版本号  
        var curVer = plus.runtime.version,  
            inf = j[plus.os.name];  

        if (inf) {  
            var srvVer = inf.version;  
            // 判断是否需要升级  
            if (compareVersion(curVer, srvVer)) {  
                if (!callback) {  
                    // 提示用户是否升级  
                    plus.ui.confirm(inf.note, function(i) {  
                        if (0 == i)  
                            plus.runtime.openURL(inf.url);  
                        else {  
                            plus.storage.setItem(keyUpdate, (new Date()).getTime().toString());  
                        }  
                    }, inf.title, ["立即更新", "取  消"]);  
                } else {  
                    callback();  
                }  
            }  
        }  
    }  

    /**  
     * 从服务器获取升级数据,并存储到本地;  
     */  
    function getUpdateData() {  
        mui.getJSON(server, {}, function(data) {  
            //appid一致,才将服务器上的版本数据保存到本地  
            if (data.appid == plus.runtime.appid) {  
                // 保存到本地文件中  
                dir.getFile(localFile, {  
                    create: true  
                }, function(fentry) {;  
                    fentry.createWriter(function(writer) {  
                        writer.onerror = function() {  
                            console.log("获取升级数据,保存文件失败!");  
                        }  
                        writer.write(data);  
                    }, function(e) {  
                        console.log("获取升级数据,创建写文件对象失败:" + e.message);  
                    });  
                }, function(e) {  
                    console.log("获取升级数据,打开保存文件失败:" + e.message);  
                });  
            }  
        });  
    }  

    /**  
     * 比较版本大小,如果新版本nv大于旧版本ov则返回true,否则返回false  
     * @param {String} ov  
     * @param {String} nv  
     * @return {Boolean}  
     */  
    function compareVersion(ov, nv) {  
        if (!ov || !nv || ov == "" || nv == "") {  
            return false;  
        }  
        var b = false,  
            ova = ov.split(".", 4),  
            nva = nv.split(".", 4);  
        for (var i = 0; i < ova.length && i < nva.length; i++) {  
            var so = ova[i],  
                no = parseInt(so),  
                sn = nva[i],  
                nn = parseInt(sn);  
            if (nn > no || sn.length > so.length) {  
                return true;  
            } else if (nn < no) {  
                return false;  
            }  
        }  
        if (nva.length > ova.length && 0 == nv.indexOf(ov)) {  
            return true;  
        }  
    }  
})(mui);
收起阅读 »

IOS离线打包的那些梗,搞定了真高兴!

这几天要发布新版本,打开Hbuilder准备在线打包,然后上次发布的悲剧重演,试过所有的p12证书之后,还是报错。
于是拿脑袋砸墙5分钟--------疼!
想起来前几天好不容易下到的xcode6.3(之前测试过离线,demo怎么跑都跑不出来,后来找个高手才发现,我的xcode是4.2的,离线打包必须要xcode 5.0,然后下了起码10个xcode的img,才找到个好用的),不如离线打包吧!
就这么愉快的决定了,于是就有了下面的各种梗:

> 我的操作步骤是这样的:
1.下载最新的官方包 HTML 5+ SDK 更新日志

  1. 拷贝官方的项目出来
  2. 按照官方的要求修改必要的参数 (附官方的说明:iOS离线打包秘籍
  3. 联真机测试 (我的以前弄的,请百度之)
  4. 打包测试 (菜单位置Product->Archive)
  5. 提交审核

1.manifest.json的各种错误

一定要检查json的格式是否正确,我碰到的情况是用apple自己带的编辑器(不是xcode)编辑了之后,居然json就破了
这是xcode报错的内容截图没保留,大概的内容是有关键字(jsonvalue)的,要是你碰到这个问题,请检查manifest.json。
必须要对的地方如下图:

要是你改错了,哪怕是各双引号,那就是这样的:


友情提示:
1.拷贝demo里的过来用,再改改,因为云端打包需要的参数都在里面,但离线打包的时候是不需要的

  1. 直接用xcode改,防止编码问题,双引号一直不对的话,请用ctrl+C和ctrl+V
  2. 网上有json检查工具,看填写的是否完整
    4.要是你的入口文件不是index.html,请别忘记修改哦

2. xcode闪退(这个奇葩问题请翻到最后)

真是奇葩~
真是奇葩~~
真是奇葩~~~
真是奇葩~~~~
真是奇葩~

3. input点选出来的是英文菜单

想象中的菜单是这样的:


现实是这样的:

解决的办法是这样的:
需要添加一行对中文的支持,就是图中用红框框出来的部分

4. 头部的样式设置错误

想象中的样子是这样的:

现实是这样的:

解决的办法是这样的:
需要添加一行,就是图中用红框框出来的部分,注意选成no
官方的状态栏设置的介绍navigator用于管理浏览器运行环境信息

5. 精简文件大小

好不容易Archive过了,才发现文件真大啊,居然又30多MB
就不停的去除库,对IOS的开发不了解,我看着不爽就删除,不敢瞎说,只知道库还是很大的

6. 64位支持

看到这个界面的时候我好高兴啊,但是苹果叔叔却不停的跳提示


解决的办法是这样的,看到红框的部分了嘛?改成no就行了

7. PUSH的问题

这个问题,是在一路绿灯之后,好高兴啊,去developer center写新版本特点了,然后...


苹果给我发了一封邮件,内容如下:

于是又开始了一路的排除bug
解决的办法是把这部分的代码注释掉

百度地图的部分也可以注释掉(要是你没用到的话)

-----------------------------奇葩故事分隔线-----------------------------

终于到最后的了,我们讲讲奇葩的故事

事情发生在1号房APP真机调试正常之后,当时的状况如下:

1号房APP:真机运行正常,打包时候xcode闪退
Hello5Demo:真机运行正常,打包正常
新建空项目:真机运行正常,打包正常

先是修改xcode里的参数无数,一点结果也没有,xcode一如既往的闪退,我那个胸闷啊。
不过大神就是大神,很淡定的说:“我们再找个人问问”,于是又出现一位美女大神,也很淡定,发布APP无数,看了几个参数之后,淡淡的说:“把你写的东西都删了~~”
当时,我说就听到这话的当时,我的下巴掉下来了,心里默念“那我不都白写了,我的青春啊~~”
“再把你写的一部分一部分的加进去~~”
好吧,我承认淡定有时候要人命啊!

接下来就是纯体力的活动:
开始清空Pandora/apps/yihaofang/www/目录下的所有文件
打包正常....
加入根目录下的独立文件
打包正常....
加入css目录
打包正常....
加入js目录
打包正常....
加入img目录
打包正常....
加入html目录
xcode闪退!

原因找到了,但是,但是这个目录没法用话,我的APP还是白写了
继续革命啊
清空html目录
xcode闪退!

到这里的时候,我看到大神们也露出了惊讶的表情,难道一个目录的名称会导致xcode闪退!
大神冷静了一下说:“改各文件夹名看看”
改目录名为htmla
打包正常....
在htmla中加入所有文件
打包正常....

幸福的泪花在我眼眶中打转(请原谅我的文艺青年本质),这就行啦?!
于是我作出了一个重要的决定
把htmla改成html
打包正常....

这就是这朵奇葩,详细原因不知道,只知道是奇葩~~
-----------------------------奇葩故事分隔线-----------------------------

其他会遇到的问题
各种证书的问题,因为之前发布过一次,这次发布就没有这么多的问题,隐约记得当时也是鸡毛一地
重点看下面这篇文章,仔细操作就能过
iOS证书(.p12)和描述文件(.mobileprovision)申请

最后,特别感谢几位朋友,排名不分先后
Hbuiler:有了这么方便的工具,web工程师转做APP也是妥妥的
两位大神:没有你们,也许很久之后1号房才能上线
Hbuilder热心回答我问题的 DCloud-App-Array(colour), DCloud_iOS_XTY(我)

继续阅读 »

这几天要发布新版本,打开Hbuilder准备在线打包,然后上次发布的悲剧重演,试过所有的p12证书之后,还是报错。
于是拿脑袋砸墙5分钟--------疼!
想起来前几天好不容易下到的xcode6.3(之前测试过离线,demo怎么跑都跑不出来,后来找个高手才发现,我的xcode是4.2的,离线打包必须要xcode 5.0,然后下了起码10个xcode的img,才找到个好用的),不如离线打包吧!
就这么愉快的决定了,于是就有了下面的各种梗:

> 我的操作步骤是这样的:
1.下载最新的官方包 HTML 5+ SDK 更新日志

  1. 拷贝官方的项目出来
  2. 按照官方的要求修改必要的参数 (附官方的说明:iOS离线打包秘籍
  3. 联真机测试 (我的以前弄的,请百度之)
  4. 打包测试 (菜单位置Product->Archive)
  5. 提交审核

1.manifest.json的各种错误

一定要检查json的格式是否正确,我碰到的情况是用apple自己带的编辑器(不是xcode)编辑了之后,居然json就破了
这是xcode报错的内容截图没保留,大概的内容是有关键字(jsonvalue)的,要是你碰到这个问题,请检查manifest.json。
必须要对的地方如下图:

要是你改错了,哪怕是各双引号,那就是这样的:


友情提示:
1.拷贝demo里的过来用,再改改,因为云端打包需要的参数都在里面,但离线打包的时候是不需要的

  1. 直接用xcode改,防止编码问题,双引号一直不对的话,请用ctrl+C和ctrl+V
  2. 网上有json检查工具,看填写的是否完整
    4.要是你的入口文件不是index.html,请别忘记修改哦

2. xcode闪退(这个奇葩问题请翻到最后)

真是奇葩~
真是奇葩~~
真是奇葩~~~
真是奇葩~~~~
真是奇葩~

3. input点选出来的是英文菜单

想象中的菜单是这样的:


现实是这样的:

解决的办法是这样的:
需要添加一行对中文的支持,就是图中用红框框出来的部分

4. 头部的样式设置错误

想象中的样子是这样的:

现实是这样的:

解决的办法是这样的:
需要添加一行,就是图中用红框框出来的部分,注意选成no
官方的状态栏设置的介绍navigator用于管理浏览器运行环境信息

5. 精简文件大小

好不容易Archive过了,才发现文件真大啊,居然又30多MB
就不停的去除库,对IOS的开发不了解,我看着不爽就删除,不敢瞎说,只知道库还是很大的

6. 64位支持

看到这个界面的时候我好高兴啊,但是苹果叔叔却不停的跳提示


解决的办法是这样的,看到红框的部分了嘛?改成no就行了

7. PUSH的问题

这个问题,是在一路绿灯之后,好高兴啊,去developer center写新版本特点了,然后...


苹果给我发了一封邮件,内容如下:

于是又开始了一路的排除bug
解决的办法是把这部分的代码注释掉

百度地图的部分也可以注释掉(要是你没用到的话)

-----------------------------奇葩故事分隔线-----------------------------

终于到最后的了,我们讲讲奇葩的故事

事情发生在1号房APP真机调试正常之后,当时的状况如下:

1号房APP:真机运行正常,打包时候xcode闪退
Hello5Demo:真机运行正常,打包正常
新建空项目:真机运行正常,打包正常

先是修改xcode里的参数无数,一点结果也没有,xcode一如既往的闪退,我那个胸闷啊。
不过大神就是大神,很淡定的说:“我们再找个人问问”,于是又出现一位美女大神,也很淡定,发布APP无数,看了几个参数之后,淡淡的说:“把你写的东西都删了~~”
当时,我说就听到这话的当时,我的下巴掉下来了,心里默念“那我不都白写了,我的青春啊~~”
“再把你写的一部分一部分的加进去~~”
好吧,我承认淡定有时候要人命啊!

接下来就是纯体力的活动:
开始清空Pandora/apps/yihaofang/www/目录下的所有文件
打包正常....
加入根目录下的独立文件
打包正常....
加入css目录
打包正常....
加入js目录
打包正常....
加入img目录
打包正常....
加入html目录
xcode闪退!

原因找到了,但是,但是这个目录没法用话,我的APP还是白写了
继续革命啊
清空html目录
xcode闪退!

到这里的时候,我看到大神们也露出了惊讶的表情,难道一个目录的名称会导致xcode闪退!
大神冷静了一下说:“改各文件夹名看看”
改目录名为htmla
打包正常....
在htmla中加入所有文件
打包正常....

幸福的泪花在我眼眶中打转(请原谅我的文艺青年本质),这就行啦?!
于是我作出了一个重要的决定
把htmla改成html
打包正常....

这就是这朵奇葩,详细原因不知道,只知道是奇葩~~
-----------------------------奇葩故事分隔线-----------------------------

其他会遇到的问题
各种证书的问题,因为之前发布过一次,这次发布就没有这么多的问题,隐约记得当时也是鸡毛一地
重点看下面这篇文章,仔细操作就能过
iOS证书(.p12)和描述文件(.mobileprovision)申请

最后,特别感谢几位朋友,排名不分先后
Hbuiler:有了这么方便的工具,web工程师转做APP也是妥妥的
两位大神:没有你们,也许很久之后1号房才能上线
Hbuilder热心回答我问题的 DCloud-App-Array(colour), DCloud_iOS_XTY(我)

收起阅读 »

分享图片压缩上传demo,可以选择一张或多张图片也可以拍摄照片

图片裁剪 图片压缩

2016-08-05更新:
下方的代码是比较OLD的了,是通过js进行图片的剪切 旋转 再生成,效率较低。
后来又整合了一个利用native.js本地接口的压缩代码 ,链接在这
。页面中有详细的说明,需要的童鞋们可以参考以下。

代码整合了
1.多串君

  1. 伟子
    两个人的demo,
    其中resize原来的filereader在5 中更改为plus.io.FileReader()方不报错。
    如有错误,请不吝批评指正。

更新日志:
2015-05-09 1020450921@qq.com
1.修复了ios下无法获取图片宽高的问题:
ios下不在img.onload中是获取不到文件对象的。

  1. 新增了最大宽度(高度)的判别,按比例压缩。
    具体代码如下:

    
    <!DOCTYPE html>  
    <html>  
    
    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <link href="http://ask.dcloud.net.cn/../../../css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            body {  
                background-color: #efeff4;  
            }  
            .mui-content {} .mui-content a {  
                color: #8F8F94;  
            }  
            .mui-content a.active {  
                color: #007aff;  
            }  
            .mui-title {  
                font-family: simhei;  
            }  
            .btn_1 {  
                position: absolute;  
                bottom: 100px;  
                left: 10px;  
                right: 10px;  
            }  
            .btn_2 {  
                position: absolute;  
                bottom: 20px;  
                left: 10px;  
                right: 10px;  
            }  
            .mui-btn-block {  
                width: 90%;  
                margin: 0 auto;  
            }  
            body {  
                overflow: hidden;  
            }  
            .showimg {  
                margin: 20px 10px auto 10px;  
                text-align: center;  
            }  
        </style>  
    </head>  
    
    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">上传身份证照片</h1>  
            <a class="mui-pull-right mui-icon mui-icon-upload" onclick="imgupgrade()"></a>  
        </header>  
        <!--  
    作者:1020450921@qq.com  
    时间:2015-04-24  
    描述:参考 http://ask.dcloud.net.cn/question/2089  
    -->  
        <div class="mui-content">  
            <div class="showimg">  
    
            </div>  
            <button type="button" class="mui-btn mui-btn-primary mui-btn-block  btn_1" onclick="galleryImgs()">从相册中选择图片</button>  
            <br>  
            <button type="button" class="mui-btn mui-btn-success mui-btn-block btn_2" onclick="cameraimages()">拍照</button>  
        </div>  
    </body>  
    <script src="../../../js/mui.min.js"></script>  
    <script src="../../../js/binaryajax.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../../../js/exif.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../../../js/canvasResize.js" type="text/javascript" charset="utf-8"></script>  
    
    <script type="text/javascript">  
        mui.init();  
        mui.plusReady(function() {})  
    
               //上传单张图片  
        function galleryImg() {  
            //每次拍摄或选择图片前清空数组对象  
            f1.splice(0, f1.length);  
            document.getElementsByClassName("showimg")[0].innerHTML = null;  
            // 从相册中选择图片  
            mui.toast("从相册中选择一张图片");  
            plus.gallery.pick(function(path) {  
                showImg(path);  
            }, function(e) {  
                mui.toast("取消选择图片");  
            }, {  
                filter: "image",  
                multiple: false  
            });  
        }  
    
        function galleryImgs() {  
                //每次拍摄或选择图片前清空数组对象  
                f1.splice(0, f1.length);  
                document.getElementsByClassName("showimg")[0].innerHTML = null;  
                // 从相册中选择图片  
                mui.toast("从相册中选择不超过两张图片");  
                plus.gallery.pick(function(e) {  
                    if (e.files.length != 2) {  
                        mui.toast('请选择身份证正面和背面照片共两张');  
                        return false;  
                    }  
                    for (var i in e.files) {  
                        showImg(e.files[i]);  
                    }  
                }, function(e) {  
                    mui.toast("取消选择图片");  
                }, {  
                    filter: "image",  
                    multiple: true  
                });  
            }  
            // 拍照添加文件  
    
        function cameraimages() {  
                //每次拍摄或选择图片前清空数组对象  
                f1.splice(0, f1.length);  
                document.getElementsByClassName("showimg")[0].innerHTML = null;  
                var cmr = plus.camera.getCamera();  
                cmr.captureImage(function(p) {  
                    plus.io.resolveLocalFileSystemURL(p, function(entry) {  
                        var localurl = entry.toLocalURL(); //把拍照的目录路径,变成本地url路径,例如file:///........之类的。  
                        showImg(localurl);  
                    });  
                }, function(e) {  
                    mui.toast("很抱歉,获取失败 "   e);  
                });  
            }  
            // 全局数组对象,添加文件,用于压缩上传使用  
        var f1 = new Array();  

function showImg(url) {
// 兼容以“file:”开头的情况
if (0 != url.toString().indexOf("file://")) {
url = "file://" + url;
}
var div = document.getElementsByClassName("showimg")[0];
var img = new Image();
img.src = url; // 传过来的图片路径在这里用。
img.onclick = function() {
plus.runtime.openFile(url);
};
img.onload = function() {
var tmph = img.height;
var tmpw = img.width;
var isHengTu = tmpw > tmph;
var max = Math.max(tmpw, tmph);
var min = Math.min(tmpw, tmph);
var bili = min / max;
if (max > 1200) {
max = 1200;
min = Math.floor(bili * max);
}
tmph = isHengTu ? min : max;
tmpw = isHengTu ? max : min;
img.style.border = "1px solid rgb(200,199,204)";
img.style.margin = "10px";
img.style.width = "150px";
img.style.height = "150px";
img.onload = null;
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.file(function(file) {
console.log(file.size + '--' + file.name);
canvasResize(file, {
width: tmpw,
height: tmph,
crop: false,
quality: 50, //压缩质量
rotate: 0,
callback: function(data, width, height) {
f1.push(data);
img.src = data;
div.appendChild(img);
plus.nativeUI.closeWaiting();
}
});
});
},
function(e) {
plus.nativeUI.closeWaiting();
console.log(e.message);
});
};
};

    function imgupgrade() {  
            mui.toast('后台联调时启用上传功能');  
            return;  
            var wt = plus.nativeUI.showWaiting();  
            var url = '后台地址';  
            var dataType = 'json';  
            //发送数据    
            var data = {  
                files1: f1 //base64数据          
            };  
            mui.post(url, data, success, dataType);  
        }  
        //成功响应的回调函数  
    var success = function(response) {  
        plus.nativeUI.closeWaiting();  
        if (response != null) {  
            alert("上传成功");  
        }  
    }  
</script>  

</html>



伟子的js代码我放在了附件中。
继续阅读 »

2016-08-05更新:
下方的代码是比较OLD的了,是通过js进行图片的剪切 旋转 再生成,效率较低。
后来又整合了一个利用native.js本地接口的压缩代码 ,链接在这
。页面中有详细的说明,需要的童鞋们可以参考以下。

代码整合了
1.多串君

  1. 伟子
    两个人的demo,
    其中resize原来的filereader在5 中更改为plus.io.FileReader()方不报错。
    如有错误,请不吝批评指正。

更新日志:
2015-05-09 1020450921@qq.com
1.修复了ios下无法获取图片宽高的问题:
ios下不在img.onload中是获取不到文件对象的。

  1. 新增了最大宽度(高度)的判别,按比例压缩。
    具体代码如下:

    
    <!DOCTYPE html>  
    <html>  
    
    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <link href="http://ask.dcloud.net.cn/../../../css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            body {  
                background-color: #efeff4;  
            }  
            .mui-content {} .mui-content a {  
                color: #8F8F94;  
            }  
            .mui-content a.active {  
                color: #007aff;  
            }  
            .mui-title {  
                font-family: simhei;  
            }  
            .btn_1 {  
                position: absolute;  
                bottom: 100px;  
                left: 10px;  
                right: 10px;  
            }  
            .btn_2 {  
                position: absolute;  
                bottom: 20px;  
                left: 10px;  
                right: 10px;  
            }  
            .mui-btn-block {  
                width: 90%;  
                margin: 0 auto;  
            }  
            body {  
                overflow: hidden;  
            }  
            .showimg {  
                margin: 20px 10px auto 10px;  
                text-align: center;  
            }  
        </style>  
    </head>  
    
    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">上传身份证照片</h1>  
            <a class="mui-pull-right mui-icon mui-icon-upload" onclick="imgupgrade()"></a>  
        </header>  
        <!--  
    作者:1020450921@qq.com  
    时间:2015-04-24  
    描述:参考 http://ask.dcloud.net.cn/question/2089  
    -->  
        <div class="mui-content">  
            <div class="showimg">  
    
            </div>  
            <button type="button" class="mui-btn mui-btn-primary mui-btn-block  btn_1" onclick="galleryImgs()">从相册中选择图片</button>  
            <br>  
            <button type="button" class="mui-btn mui-btn-success mui-btn-block btn_2" onclick="cameraimages()">拍照</button>  
        </div>  
    </body>  
    <script src="../../../js/mui.min.js"></script>  
    <script src="../../../js/binaryajax.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../../../js/exif.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../../../js/canvasResize.js" type="text/javascript" charset="utf-8"></script>  
    
    <script type="text/javascript">  
        mui.init();  
        mui.plusReady(function() {})  
    
               //上传单张图片  
        function galleryImg() {  
            //每次拍摄或选择图片前清空数组对象  
            f1.splice(0, f1.length);  
            document.getElementsByClassName("showimg")[0].innerHTML = null;  
            // 从相册中选择图片  
            mui.toast("从相册中选择一张图片");  
            plus.gallery.pick(function(path) {  
                showImg(path);  
            }, function(e) {  
                mui.toast("取消选择图片");  
            }, {  
                filter: "image",  
                multiple: false  
            });  
        }  
    
        function galleryImgs() {  
                //每次拍摄或选择图片前清空数组对象  
                f1.splice(0, f1.length);  
                document.getElementsByClassName("showimg")[0].innerHTML = null;  
                // 从相册中选择图片  
                mui.toast("从相册中选择不超过两张图片");  
                plus.gallery.pick(function(e) {  
                    if (e.files.length != 2) {  
                        mui.toast('请选择身份证正面和背面照片共两张');  
                        return false;  
                    }  
                    for (var i in e.files) {  
                        showImg(e.files[i]);  
                    }  
                }, function(e) {  
                    mui.toast("取消选择图片");  
                }, {  
                    filter: "image",  
                    multiple: true  
                });  
            }  
            // 拍照添加文件  
    
        function cameraimages() {  
                //每次拍摄或选择图片前清空数组对象  
                f1.splice(0, f1.length);  
                document.getElementsByClassName("showimg")[0].innerHTML = null;  
                var cmr = plus.camera.getCamera();  
                cmr.captureImage(function(p) {  
                    plus.io.resolveLocalFileSystemURL(p, function(entry) {  
                        var localurl = entry.toLocalURL(); //把拍照的目录路径,变成本地url路径,例如file:///........之类的。  
                        showImg(localurl);  
                    });  
                }, function(e) {  
                    mui.toast("很抱歉,获取失败 "   e);  
                });  
            }  
            // 全局数组对象,添加文件,用于压缩上传使用  
        var f1 = new Array();  

function showImg(url) {
// 兼容以“file:”开头的情况
if (0 != url.toString().indexOf("file://")) {
url = "file://" + url;
}
var div = document.getElementsByClassName("showimg")[0];
var img = new Image();
img.src = url; // 传过来的图片路径在这里用。
img.onclick = function() {
plus.runtime.openFile(url);
};
img.onload = function() {
var tmph = img.height;
var tmpw = img.width;
var isHengTu = tmpw > tmph;
var max = Math.max(tmpw, tmph);
var min = Math.min(tmpw, tmph);
var bili = min / max;
if (max > 1200) {
max = 1200;
min = Math.floor(bili * max);
}
tmph = isHengTu ? min : max;
tmpw = isHengTu ? max : min;
img.style.border = "1px solid rgb(200,199,204)";
img.style.margin = "10px";
img.style.width = "150px";
img.style.height = "150px";
img.onload = null;
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.file(function(file) {
console.log(file.size + '--' + file.name);
canvasResize(file, {
width: tmpw,
height: tmph,
crop: false,
quality: 50, //压缩质量
rotate: 0,
callback: function(data, width, height) {
f1.push(data);
img.src = data;
div.appendChild(img);
plus.nativeUI.closeWaiting();
}
});
});
},
function(e) {
plus.nativeUI.closeWaiting();
console.log(e.message);
});
};
};

    function imgupgrade() {  
            mui.toast('后台联调时启用上传功能');  
            return;  
            var wt = plus.nativeUI.showWaiting();  
            var url = '后台地址';  
            var dataType = 'json';  
            //发送数据    
            var data = {  
                files1: f1 //base64数据          
            };  
            mui.post(url, data, success, dataType);  
        }  
        //成功响应的回调函数  
    var success = function(response) {  
        plus.nativeUI.closeWaiting();  
        if (response != null) {  
            alert("上传成功");  
        }  
    }  
</script>  

</html>



伟子的js代码我放在了附件中。
收起阅读 »

App资源在线差量升级更新

update wgt wgtu 升级 差量升级

官方已发布APP升级中心,支持原生APP整包升级和wgt资源包升级。详见

5+应用可使用以下方式进行升级

本文重点介绍5+应用资源差量升级,相对App资源独立升级,因为只需要下载更新的资源文件,所以升级包体积更小,升级速度会更快。
注意:需HBuilder5.7.0以上版本才有此功能

生成移动App资源差量升级包

顾名思义,差量升级包是针对某个历史版本到新版本的差量,所以对于升级服务器来讲需要保留所有历史版本,并且分别生成每个历史版本到新版本的差量升级包。
目前HBuilder IDE并未提供版本控制系统,所以需要按照以下规则手动生成差量升级包:

  • 差量升级包文件格式为wgtu
    在HTML5+移动App支持的差量升级包文件后缀名必须是wgtu,它是标准的zip压缩文件,可以使用任何zip工具对wgtu目录进行压缩,并修改文件后缀名称为wgtu。
  • wgtu目录结构
名称 类型 说明
www 目录 保存需要更新的数据文件,其下的目录结构与应用的目录结构一致,其下必须包含manifest.json文件,否则认为更新文件非法,不执行升级操作
update.xml 文件 保存应用升级操作的配置信息,参考update.xml文件格式
  • update.xml文件格式(注意:文件名必须全部小写)
    update.xml为标准的xml文件格式,定义wgtu文件升级配置信息,其文件格式如下:
元素名称 父元素 类型 描述 必须
wgtu 根节点
appid wgtu 属性 升级应用的appid
basis wgtu 节点 基础应用信息
version basis 属性 基础应用的版本信息(旧版本的版本号
remove wgtu 节点 升级需要删除的文件/目录列表
item remove 节点 需要删除的项
path item 属性 需要删除的项的路径,相对于应用根目录,如“image/a.png”表示image目录下的a.png文件。如果是目录则以‘/’结尾,如“res/img/”表示res目录下的img目录,删除时包括下的所有内容。
  • wgtu示例
    应用升级前的版本1.0,其应用目录结构为:

    应用升级后的版本1.1,其应用目录结构为:

    差量升级包wgtu文件的目录结构为(不包括最外层wgtu目录):

    应用升级更新文件manifest.json、index.html,新增detail.html、image/new.png,删除image/icon5.png。
    其中update.xml中的内容为:
    <?xml version="1.0" encoding="utf-8" standalone="no"?>  
    <wgtu appid="TEST" >  
    <basis version="1.0" />  
    <remove>  
    <item path="image/icon5.png" />  
    </remove>  
    </wgtu>

应用中差量更新资源

下载wgtu文件并更新:

    var url='http://demo.dcloud.net.cn/helloh5/update/HelloH5.wgtu';  
    plus.nativeUI.showWaiting("升级中...");  
    var dtask = plus.downloader.createDownload( url, {method:"GET"}, function(d,status){  
        if ( status == 200 ) {   
            console.log( "Download wgtu success: " + d.filename );  
            plus.runtime.install(d.filename,{},function(){  
                plus.nativeUI.closeWaiting();  
                plus.nativeUI.alert("Update wgtu success, restart now!",function(){  
                    plus.runtime.restart();  
                });  
            },function(e){  
                plus.nativeUI.closeWaiting();  
                alert("Update wgtu failed: "+e.message);  
            });  
        } else {  
            plus.nativeUI.closeWaiting();  
             alert( "Download wgtu failed: " + status );   
        }   
    } );  
    dtask.addEventListener('statechanged',function(d,status){  
        console.log("statechanged: "+d.state);  
    });  
    dtask.start();

注意

  1. wgtu包中的update.xml文件名称必须全部小写,并且和www在同一级目录中
  2. wgtu包中www目录下必须包含manifest.json文件,并且里面不能包含注释(HBuilder中默认带注释,需要手动删除所有注释)
  3. update.xml中的appid值是应用的AppID(如“H5F6AE111”),不是程序的包名(如“io.dcloud.H5F6AE1111”)
  4. wgtu包必须是使用zip格式压缩的文件(不能使用如rar等其它压缩格式)

App store应用更新说明
应用资源更新肯定是违反apple政策的,但目前看起来它也不管。你在官网案例那里下载Appstore版本的那些app,大多启动后都会提示更新,反正也都没下架。如果你不是很大的公司,apple不会理睬你。如果你是大公司,建议不要做整体更新,每次更新几个页面,也不要提示更新后需要重启,这样会安全点。

感谢 @大裤子 反馈建议更新补充文档,wgtu更新经验分享:http://ask.dcloud.net.cn/question/6353

继续阅读 »

官方已发布APP升级中心,支持原生APP整包升级和wgt资源包升级。详见

5+应用可使用以下方式进行升级

本文重点介绍5+应用资源差量升级,相对App资源独立升级,因为只需要下载更新的资源文件,所以升级包体积更小,升级速度会更快。
注意:需HBuilder5.7.0以上版本才有此功能

生成移动App资源差量升级包

顾名思义,差量升级包是针对某个历史版本到新版本的差量,所以对于升级服务器来讲需要保留所有历史版本,并且分别生成每个历史版本到新版本的差量升级包。
目前HBuilder IDE并未提供版本控制系统,所以需要按照以下规则手动生成差量升级包:

  • 差量升级包文件格式为wgtu
    在HTML5+移动App支持的差量升级包文件后缀名必须是wgtu,它是标准的zip压缩文件,可以使用任何zip工具对wgtu目录进行压缩,并修改文件后缀名称为wgtu。
  • wgtu目录结构
名称 类型 说明
www 目录 保存需要更新的数据文件,其下的目录结构与应用的目录结构一致,其下必须包含manifest.json文件,否则认为更新文件非法,不执行升级操作
update.xml 文件 保存应用升级操作的配置信息,参考update.xml文件格式
  • update.xml文件格式(注意:文件名必须全部小写)
    update.xml为标准的xml文件格式,定义wgtu文件升级配置信息,其文件格式如下:
元素名称 父元素 类型 描述 必须
wgtu 根节点
appid wgtu 属性 升级应用的appid
basis wgtu 节点 基础应用信息
version basis 属性 基础应用的版本信息(旧版本的版本号
remove wgtu 节点 升级需要删除的文件/目录列表
item remove 节点 需要删除的项
path item 属性 需要删除的项的路径,相对于应用根目录,如“image/a.png”表示image目录下的a.png文件。如果是目录则以‘/’结尾,如“res/img/”表示res目录下的img目录,删除时包括下的所有内容。
  • wgtu示例
    应用升级前的版本1.0,其应用目录结构为:

    应用升级后的版本1.1,其应用目录结构为:

    差量升级包wgtu文件的目录结构为(不包括最外层wgtu目录):

    应用升级更新文件manifest.json、index.html,新增detail.html、image/new.png,删除image/icon5.png。
    其中update.xml中的内容为:
    <?xml version="1.0" encoding="utf-8" standalone="no"?>  
    <wgtu appid="TEST" >  
    <basis version="1.0" />  
    <remove>  
    <item path="image/icon5.png" />  
    </remove>  
    </wgtu>

应用中差量更新资源

下载wgtu文件并更新:

    var url='http://demo.dcloud.net.cn/helloh5/update/HelloH5.wgtu';  
    plus.nativeUI.showWaiting("升级中...");  
    var dtask = plus.downloader.createDownload( url, {method:"GET"}, function(d,status){  
        if ( status == 200 ) {   
            console.log( "Download wgtu success: " + d.filename );  
            plus.runtime.install(d.filename,{},function(){  
                plus.nativeUI.closeWaiting();  
                plus.nativeUI.alert("Update wgtu success, restart now!",function(){  
                    plus.runtime.restart();  
                });  
            },function(e){  
                plus.nativeUI.closeWaiting();  
                alert("Update wgtu failed: "+e.message);  
            });  
        } else {  
            plus.nativeUI.closeWaiting();  
             alert( "Download wgtu failed: " + status );   
        }   
    } );  
    dtask.addEventListener('statechanged',function(d,status){  
        console.log("statechanged: "+d.state);  
    });  
    dtask.start();

注意

  1. wgtu包中的update.xml文件名称必须全部小写,并且和www在同一级目录中
  2. wgtu包中www目录下必须包含manifest.json文件,并且里面不能包含注释(HBuilder中默认带注释,需要手动删除所有注释)
  3. update.xml中的appid值是应用的AppID(如“H5F6AE111”),不是程序的包名(如“io.dcloud.H5F6AE1111”)
  4. wgtu包必须是使用zip格式压缩的文件(不能使用如rar等其它压缩格式)

App store应用更新说明
应用资源更新肯定是违反apple政策的,但目前看起来它也不管。你在官网案例那里下载Appstore版本的那些app,大多启动后都会提示更新,反正也都没下架。如果你不是很大的公司,apple不会理睬你。如果你是大公司,建议不要做整体更新,每次更新几个页面,也不要提示更新后需要重启,这样会安全点。

感谢 @大裤子 反馈建议更新补充文档,wgtu更新经验分享:http://ask.dcloud.net.cn/question/6353

收起阅读 »

segment分段选择页面根据传入的querystring 激活相应的分段

具体需求描述是这样的:父页面有两个链接需要导向segment页并根据传入的querystring激活不同的段落。
使用原始的url带参的方式,没有使用自定义扩展参数的方式,不过建议使用自定义扩展参数的方式。

mui.openwindow({  
     extras:{  
      'x_id':'10'//自定义扩展参数,可以用来处理页面间传值  
    }  
})

在B页面这样去获取

var self=plus.webview.currentWebview();  
var id=self.x_id;

具体的实现代码如下:
父页面html,打开链接依然使用mui.openwindow.

<ul>  
                    <li><a class="mui-inline" href="http://ask.dcloud.net.cn/myxx.html?model=item1mobile" style="color:rgb(0, 0, 0) ;">商家XX</a></li>  
                    <li>20</li>  
                </ul>  
                <ul>  
                    <li ><a class="mui-inline" href="http://ask.dcloud.net.cn/myxx.html?model=item2mobile" style="color:rgb(0, 0, 0) ;">个人XX</a></li>  
                    <li>10</li>  
                </ul>

子页面:

<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title>我的XX</title>  
        <link href="http://ask.dcloud.net.cn/../css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .mui-segmented-control .mui-control-item {  
                line-height: 28px;  
            }  
            .mui-title {  
                font-family: simhei;  
            }  
            .gray_color {  
                color: #8f8f94;  
                font-size: 0.8em;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">我的XX</h1>  
        </header>  
        <div class="mui-content">  
            <div class="mui-content-padded tab_title" style="margin: 0.65em 3em;">  
                <div id="segmentedControl" class="mui-segmented-control">  
                    <a class="mui-control-item mui-active" href="#item1mobile">  

                        商家XX  
                    </a>  
                    <a class="mui-control-item" href="#item2mobile">  

                        个人XX  

                    </a>  
                </div>  
            </div>  

            <div id="item1mobile" class="mui-control-content mui-active">  
                <ul class="mui-table-view">  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月19日XXXXX<span class='mui-pull-right gray_color'>3月18号</span>  
                                <p class='mui-ellipsis'>您在日历XXX中设定的XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月15日XXX<span class='mui-pull-right gray_color'>3月14号</span>  
                                <p class='mui-ellipsis'>您在XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月11日XXX<span class='mui-pull-right gray_color'>3月10号</span>  
                                <p class='mui-ellipsis'>您在日历XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                </ul>  
            </div>  
            <div id="item2mobile" class="mui-control-content">  
                <ul class="mui-table-view">  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                订单消息<span class='mui-pull-right gray_color'>4月12号</span>  
                                <p class='mui-ellipsis'>xxxxxxxx</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                订单消息<span class='mui-pull-right gray_color'>4月10号</span>  
                                <p class='mui-ellipsis'>xxxxxxx</p>  
                            </div>  
                        </a>  
                    </li>  
                </ul>  
            </div>  
        </div>  
        <script src="../js/mui.min.js"></script>  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
            mui.plusReady(function() {  
                               //我使用plus,有时候会报undefined错误  
                console.log(plus.webview.currentWebview().id)  
            })  
             mui.ready(function() {  
                var urlx = this.document.URL.toString();  
                var modelx = "item1mobile";  
                if (urlx.lastIndexOf('?') != -1) {  
                    modelx = urlx.substr(urlx.lastIndexOf('?')   1, urlx.length).split('=')[1];  
                }  
                var ar = document.getElementById("segmentedControl").querySelectorAll(".mui-control-item");  
                var reg = new RegExp('(\\s|^)'   'mui-active'   '(\\s|$)');  
                var item1 = document.getElementById("item1mobile");  
                var item2 = document.getElementById("item2mobile");  
                //重置  
                ar[0].className = ar[0].className.replace(reg, '');  
                ar[1].className = ar[1].className.replace(reg, '');  
                item1.className = item1.className.replace(reg, '');  
                item1.className = item2.className.replace(reg, '');  
                if (modelx == "item1mobile") {  
                    ar[0].className  = " mui-active";  
                    ar[1].className = ar[1].className.replace(reg, '');  
                    item1.className  = " mui-active";  
                    item2.className = item2.className.replace(reg, '');  
                } else {  
                    ar[0].className = ar[0].className.replace(reg, '');  
                    ar[1].className  = " mui-active";  
                    item2.className  = " mui-active";  
                    item1.className = item1.className.replace(reg, '');  
                }  
            });  
        </script>  
    </body>  

</html>
继续阅读 »

具体需求描述是这样的:父页面有两个链接需要导向segment页并根据传入的querystring激活不同的段落。
使用原始的url带参的方式,没有使用自定义扩展参数的方式,不过建议使用自定义扩展参数的方式。

mui.openwindow({  
     extras:{  
      'x_id':'10'//自定义扩展参数,可以用来处理页面间传值  
    }  
})

在B页面这样去获取

var self=plus.webview.currentWebview();  
var id=self.x_id;

具体的实现代码如下:
父页面html,打开链接依然使用mui.openwindow.

<ul>  
                    <li><a class="mui-inline" href="http://ask.dcloud.net.cn/myxx.html?model=item1mobile" style="color:rgb(0, 0, 0) ;">商家XX</a></li>  
                    <li>20</li>  
                </ul>  
                <ul>  
                    <li ><a class="mui-inline" href="http://ask.dcloud.net.cn/myxx.html?model=item2mobile" style="color:rgb(0, 0, 0) ;">个人XX</a></li>  
                    <li>10</li>  
                </ul>

子页面:

<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title>我的XX</title>  
        <link href="http://ask.dcloud.net.cn/../css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .mui-segmented-control .mui-control-item {  
                line-height: 28px;  
            }  
            .mui-title {  
                font-family: simhei;  
            }  
            .gray_color {  
                color: #8f8f94;  
                font-size: 0.8em;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">我的XX</h1>  
        </header>  
        <div class="mui-content">  
            <div class="mui-content-padded tab_title" style="margin: 0.65em 3em;">  
                <div id="segmentedControl" class="mui-segmented-control">  
                    <a class="mui-control-item mui-active" href="#item1mobile">  

                        商家XX  
                    </a>  
                    <a class="mui-control-item" href="#item2mobile">  

                        个人XX  

                    </a>  
                </div>  
            </div>  

            <div id="item1mobile" class="mui-control-content mui-active">  
                <ul class="mui-table-view">  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月19日XXXXX<span class='mui-pull-right gray_color'>3月18号</span>  
                                <p class='mui-ellipsis'>您在日历XXX中设定的XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月15日XXX<span class='mui-pull-right gray_color'>3月14号</span>  
                                <p class='mui-ellipsis'>您在XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                3月11日XXX<span class='mui-pull-right gray_color'>3月10号</span>  
                                <p class='mui-ellipsis'>您在日历XXX即将到来</p>  
                            </div>  
                        </a>  
                    </li>  
                </ul>  
            </div>  
            <div id="item2mobile" class="mui-control-content">  
                <ul class="mui-table-view">  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                订单消息<span class='mui-pull-right gray_color'>4月12号</span>  
                                <p class='mui-ellipsis'>xxxxxxxx</p>  
                            </div>  
                        </a>  
                    </li>  
                    <li class="mui-table-view-cell mui-media">  
                        <a href="javascript:void(0);">  
                            <img class="mui-media-object mui-pull-left" src="../images/content.jpg">  
                            <div class="mui-media-body">  
                                订单消息<span class='mui-pull-right gray_color'>4月10号</span>  
                                <p class='mui-ellipsis'>xxxxxxx</p>  
                            </div>  
                        </a>  
                    </li>  
                </ul>  
            </div>  
        </div>  
        <script src="../js/mui.min.js"></script>  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
            mui.plusReady(function() {  
                               //我使用plus,有时候会报undefined错误  
                console.log(plus.webview.currentWebview().id)  
            })  
             mui.ready(function() {  
                var urlx = this.document.URL.toString();  
                var modelx = "item1mobile";  
                if (urlx.lastIndexOf('?') != -1) {  
                    modelx = urlx.substr(urlx.lastIndexOf('?')   1, urlx.length).split('=')[1];  
                }  
                var ar = document.getElementById("segmentedControl").querySelectorAll(".mui-control-item");  
                var reg = new RegExp('(\\s|^)'   'mui-active'   '(\\s|$)');  
                var item1 = document.getElementById("item1mobile");  
                var item2 = document.getElementById("item2mobile");  
                //重置  
                ar[0].className = ar[0].className.replace(reg, '');  
                ar[1].className = ar[1].className.replace(reg, '');  
                item1.className = item1.className.replace(reg, '');  
                item1.className = item2.className.replace(reg, '');  
                if (modelx == "item1mobile") {  
                    ar[0].className  = " mui-active";  
                    ar[1].className = ar[1].className.replace(reg, '');  
                    item1.className  = " mui-active";  
                    item2.className = item2.className.replace(reg, '');  
                } else {  
                    ar[0].className = ar[0].className.replace(reg, '');  
                    ar[1].className  = " mui-active";  
                    item2.className  = " mui-active";  
                    item1.className = item1.className.replace(reg, '');  
                }  
            });  
        </script>  
    </body>  

</html>
收起阅读 »

C#配置支付宝信息

支付宝 Payment

参考支付宝官方的demo配置的方法,亲测可行.

        public object GetPayInfo(string _amount)//_amount:付款金额  
        {  
            string orderInfo = OrderInfo(_amount);  
            // 对订单做RSA 签名  
            string sign = RSAFromPkcs8.sign(orderInfo, Config.Private_key, Config.Input_charset); //支付宝提供的Config.cs  
            //仅需对sign做URL编码  
            sign = HttpUtility.UrlEncode(sign, Encoding.UTF8);  
            string payInfo = orderInfo + "&sign=\"" + sign + "\"&"  
                + getSignType();  
            return payInfo;  
        }  
        public string OrderInfo(string price)  
        {              
            Dictionary<string, string> payinfo = new Dictionary<string, string>();  
            payinfo.Add("service", "\"mobile.securitypay.pay\"");  
            payinfo.Add("partner", "\"" + Config.Partner + "\"");  
            payinfo.Add("seller_id", "\"" + Config.SELLER + "\"");  
            payinfo.Add("out_trade_no", "\"" + DateTime.Now.ToString("yyyyMMddHHmmssfff")+ "\"");  
            payinfo.Add("subject", "\"****\"");  
            payinfo.Add("body", "\"*****\"");  
            payinfo.Add("total_fee", "\"" + price.ToString() + "\"");  
            payinfo.Add("notify_url", "\"***********"");  
            payinfo.Add("payment_type", "\"1\"");  
            payinfo.Add("_input_charset", "\"UTF-8\"");  
            payinfo.Add("it_b_pay", "\"30m\"");              
            return Core.CreateLinkString(payinfo);  
        }  
         public String getSignType()  
        {  
            return "sign_type=\"RSA\"";  
        }

HB中的方法

                   function topay(rate) {  
                if (w) {  
                    return;  
                }  
                //检查是否请求订单中  
                w = plus.nativeUI.showWaiting();  
                mui.getJSON("http://************/api/Pay", {  
                    _amount: rate  
                }, function(data) {  
                    w.close();  
                    w = null;  
                    if (data) {  
                        plus.payment.request(pays["alipay"], data, function(result) {                             
                                        plus.nativeUI.alert("支付成功:感谢您的支持。", function() {  
                                            mui.back();  
                                        }, "****");                                   
                        }, function(error) {  
                            if (error.code == 62001) {  
                                mui.toast("您放弃支付.");  
                                mui.back();  
                            } else {  
                                plus.nativeUI.alert("支付失败", null, "请前往会员中心再次对该订单尝试支付,支付失败:" + error.code);  
                            }  
                        });  
                    }  
                });  
            }
继续阅读 »

参考支付宝官方的demo配置的方法,亲测可行.

        public object GetPayInfo(string _amount)//_amount:付款金额  
        {  
            string orderInfo = OrderInfo(_amount);  
            // 对订单做RSA 签名  
            string sign = RSAFromPkcs8.sign(orderInfo, Config.Private_key, Config.Input_charset); //支付宝提供的Config.cs  
            //仅需对sign做URL编码  
            sign = HttpUtility.UrlEncode(sign, Encoding.UTF8);  
            string payInfo = orderInfo + "&sign=\"" + sign + "\"&"  
                + getSignType();  
            return payInfo;  
        }  
        public string OrderInfo(string price)  
        {              
            Dictionary<string, string> payinfo = new Dictionary<string, string>();  
            payinfo.Add("service", "\"mobile.securitypay.pay\"");  
            payinfo.Add("partner", "\"" + Config.Partner + "\"");  
            payinfo.Add("seller_id", "\"" + Config.SELLER + "\"");  
            payinfo.Add("out_trade_no", "\"" + DateTime.Now.ToString("yyyyMMddHHmmssfff")+ "\"");  
            payinfo.Add("subject", "\"****\"");  
            payinfo.Add("body", "\"*****\"");  
            payinfo.Add("total_fee", "\"" + price.ToString() + "\"");  
            payinfo.Add("notify_url", "\"***********"");  
            payinfo.Add("payment_type", "\"1\"");  
            payinfo.Add("_input_charset", "\"UTF-8\"");  
            payinfo.Add("it_b_pay", "\"30m\"");              
            return Core.CreateLinkString(payinfo);  
        }  
         public String getSignType()  
        {  
            return "sign_type=\"RSA\"";  
        }

HB中的方法

                   function topay(rate) {  
                if (w) {  
                    return;  
                }  
                //检查是否请求订单中  
                w = plus.nativeUI.showWaiting();  
                mui.getJSON("http://************/api/Pay", {  
                    _amount: rate  
                }, function(data) {  
                    w.close();  
                    w = null;  
                    if (data) {  
                        plus.payment.request(pays["alipay"], data, function(result) {                             
                                        plus.nativeUI.alert("支付成功:感谢您的支持。", function() {  
                                            mui.back();  
                                        }, "****");                                   
                        }, function(error) {  
                            if (error.code == 62001) {  
                                mui.toast("您放弃支付.");  
                                mui.back();  
                            } else {  
                                plus.nativeUI.alert("支付失败", null, "请前往会员中心再次对该订单尝试支付,支付失败:" + error.code);  
                            }  
                        });  
                    }  
                });  
            }
收起阅读 »

这几天对HBuilder使用的感想

mui

HBuilder,刚推出来过后不久,我就开始尝鲜,使用的时候让我感觉很是惊艳,自动提示的让我很满足,什么link 、script、meta标签,刷刷就出来了,这个必须点赞。后来继续尝试WEB 、APP开发,发现能上传自动帮我打包,感觉很轻松,因为我尝试过配置Phongap的环境,一个android,就有些麻烦,更何况还有IOS的。
接着,我用HBuilder来编写PC端的网页,也把这个工具推荐给了我同事们使用,大家都觉得挺好的。
过了一段时间,今年,领导让给写一个APP,我说用原生来开发吧(我这时已经会Android开发了),领导say no,用HTML 5开发,要兼容IOS、Android、WP、微信(微信是一个超级APP,可以算是一个小平台了),另外我给你安排一个专家,帮你做好微信支付、二维码扫描等等功能,我说不用,我知道一个工具,并集成了UI、还有很多开发好的功能,领导很满意,让我先开发一个DEMO出来。
清明节3天假,我第一天就写的差不多了,迅速写好了DEMO大部分工作,也在我的IOS手机上调试完毕,完成度大概80%,遗留了一些优化的工作(不要小瞧这部分),很顺利,很开心。于是在我的Android(小米2s)机器上,我第二天继续调试,我擦!,怎么各种各样的情况出现了,首先领导很重视的二维码扫描功能,我在这部Android机上调了半天,硬是识别不出来,后来是我手不小心抖了下,才发现只有小抖几下才识别的出来。这个我在问答部分也提了,得到官方回复,他们的小米2上是正常的,我不知道会不会与“S”有关系,在二维码扫描方面,扫描速度还是有点不行~~
接着我继续界面的跳转,我比较郁闷,原生Anroid有singleTop、singleTask模式的,我就想让webview重复利用下,例如 首页,我肯定不想让它重复打开吧。查下API,找到了plus.webview.show 方法,不行,IOS的显示不出来,找到了webview.show方法(我想这个两个方法实现逻辑是一样的),结果IOS都无法显示出来,Android到挺正常的,继续查openClosed,IOS的还是不好使,偶那个神哪!在问答区,我发出了提问,官方回复使用zindex,OK,果然能显示出来!但是接着我再首页打开新的页面,mygod,出了个圈圈,就不见踪影,明白了,新打开的界面没有继承打开者zindex属性,得,我只好重新下openWindow方法,将currentWebview,的zindex赋值给要打开的页面,结果还是不行,我想明白了我要取的是topWebview的zindex, 只好查API,没有获取topWebView的方法,得,将show()方法也重写下,并自己记录下topWebview,IOS正常了,达到我要的效果了。
在Android上来试试,Y的,Android倒不干了,使用webview.getStyle.zindex,发现,额,程序刚开始运行的时候得到undifined,而IOS得到的是0。算了算了,给重写的函数加两个判断分支,如果是android,执行原来的方法。呼,脑子终于清静了。
四天的时间,其实还算是挺快的。但是挺有点烦人的。webview的show方法,官方说下一版修复。恩,我也觉得应该将这方面的栈结果顺序维护好。我使用过plus.webview.all()函数,好像如果用show方法,在被show的之后的webview 貌似没被清空。
时间紧迫,我还没对这些缺陷做准确的验证,再提出来。
因此,希望官方提供一个专门的缺陷报告填写页过来,问答的方式 不是感觉很严谨呵。另外,mui的js源码也阅读了下,额,API不够用,当然可以自己写,但是官方的理解肯定深刻一些。5+部分的可否给一些原理图神马的。HB整体的发展路线图、蓝图,也能给一个,让大家也讨论下,让小伙伴们都参加进来,给予意见吧。
我还是挺喜欢HB的,但是这些或多或少的问题能得到解决。

继续阅读 »

HBuilder,刚推出来过后不久,我就开始尝鲜,使用的时候让我感觉很是惊艳,自动提示的让我很满足,什么link 、script、meta标签,刷刷就出来了,这个必须点赞。后来继续尝试WEB 、APP开发,发现能上传自动帮我打包,感觉很轻松,因为我尝试过配置Phongap的环境,一个android,就有些麻烦,更何况还有IOS的。
接着,我用HBuilder来编写PC端的网页,也把这个工具推荐给了我同事们使用,大家都觉得挺好的。
过了一段时间,今年,领导让给写一个APP,我说用原生来开发吧(我这时已经会Android开发了),领导say no,用HTML 5开发,要兼容IOS、Android、WP、微信(微信是一个超级APP,可以算是一个小平台了),另外我给你安排一个专家,帮你做好微信支付、二维码扫描等等功能,我说不用,我知道一个工具,并集成了UI、还有很多开发好的功能,领导很满意,让我先开发一个DEMO出来。
清明节3天假,我第一天就写的差不多了,迅速写好了DEMO大部分工作,也在我的IOS手机上调试完毕,完成度大概80%,遗留了一些优化的工作(不要小瞧这部分),很顺利,很开心。于是在我的Android(小米2s)机器上,我第二天继续调试,我擦!,怎么各种各样的情况出现了,首先领导很重视的二维码扫描功能,我在这部Android机上调了半天,硬是识别不出来,后来是我手不小心抖了下,才发现只有小抖几下才识别的出来。这个我在问答部分也提了,得到官方回复,他们的小米2上是正常的,我不知道会不会与“S”有关系,在二维码扫描方面,扫描速度还是有点不行~~
接着我继续界面的跳转,我比较郁闷,原生Anroid有singleTop、singleTask模式的,我就想让webview重复利用下,例如 首页,我肯定不想让它重复打开吧。查下API,找到了plus.webview.show 方法,不行,IOS的显示不出来,找到了webview.show方法(我想这个两个方法实现逻辑是一样的),结果IOS都无法显示出来,Android到挺正常的,继续查openClosed,IOS的还是不好使,偶那个神哪!在问答区,我发出了提问,官方回复使用zindex,OK,果然能显示出来!但是接着我再首页打开新的页面,mygod,出了个圈圈,就不见踪影,明白了,新打开的界面没有继承打开者zindex属性,得,我只好重新下openWindow方法,将currentWebview,的zindex赋值给要打开的页面,结果还是不行,我想明白了我要取的是topWebview的zindex, 只好查API,没有获取topWebView的方法,得,将show()方法也重写下,并自己记录下topWebview,IOS正常了,达到我要的效果了。
在Android上来试试,Y的,Android倒不干了,使用webview.getStyle.zindex,发现,额,程序刚开始运行的时候得到undifined,而IOS得到的是0。算了算了,给重写的函数加两个判断分支,如果是android,执行原来的方法。呼,脑子终于清静了。
四天的时间,其实还算是挺快的。但是挺有点烦人的。webview的show方法,官方说下一版修复。恩,我也觉得应该将这方面的栈结果顺序维护好。我使用过plus.webview.all()函数,好像如果用show方法,在被show的之后的webview 貌似没被清空。
时间紧迫,我还没对这些缺陷做准确的验证,再提出来。
因此,希望官方提供一个专门的缺陷报告填写页过来,问答的方式 不是感觉很严谨呵。另外,mui的js源码也阅读了下,额,API不够用,当然可以自己写,但是官方的理解肯定深刻一些。5+部分的可否给一些原理图神马的。HB整体的发展路线图、蓝图,也能给一个,让大家也讨论下,让小伙伴们都参加进来,给予意见吧。
我还是挺喜欢HB的,但是这些或多或少的问题能得到解决。

收起阅读 »