HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

使用 Hbuilder自定义注释代码块

类似于Eclipse里面那种的快速方法注释的功能我在Hbuilder中并没有找到,但是HB提供了自定义各种类型文件代码块的功能,我们可以利用这一功能来自定义注释,之前用了很久,但是后来重装系统就麻烦了半天给重写了一遍,这次就放在这里,以便日后查阅
工具 -> 扩展代码块 -> 自定义PHP代码块

  #个人自定义代码块  
  snippet "/*多行注释*/" do |s|  
    today = Time.new  
    now = today.strftime("%Y年%m月%d日")  
    s.trigger = 'zhushi'  
    s.expansion = "/**  
 * ${1:方法名}   
 * ${2: }  
 * @param ${3: }  
 * @return $0  
 * @version 1.0  
 * @author 您的大名 #{now}  
 * */"  
  end

这个日期嘛,是有问题的,按照phpDoc来说应该是没有这个属性的,但是我们项目中经常会遇到一个方法时常更新的情况,这时候后期维护就有必要填这个日期的,这里的问题就是:写完后日期固定了。。。如果想每天都更新的话,就需要每次都打开这个文件,修改下然后再保存,我想应该是做了缓存所以不能动态实时更新时间的。虽然麻烦了点,不过一点点一次就当签到得了。不需要日期的删掉它就可以了

继续阅读 »

类似于Eclipse里面那种的快速方法注释的功能我在Hbuilder中并没有找到,但是HB提供了自定义各种类型文件代码块的功能,我们可以利用这一功能来自定义注释,之前用了很久,但是后来重装系统就麻烦了半天给重写了一遍,这次就放在这里,以便日后查阅
工具 -> 扩展代码块 -> 自定义PHP代码块

  #个人自定义代码块  
  snippet "/*多行注释*/" do |s|  
    today = Time.new  
    now = today.strftime("%Y年%m月%d日")  
    s.trigger = 'zhushi'  
    s.expansion = "/**  
 * ${1:方法名}   
 * ${2: }  
 * @param ${3: }  
 * @return $0  
 * @version 1.0  
 * @author 您的大名 #{now}  
 * */"  
  end

这个日期嘛,是有问题的,按照phpDoc来说应该是没有这个属性的,但是我们项目中经常会遇到一个方法时常更新的情况,这时候后期维护就有必要填这个日期的,这里的问题就是:写完后日期固定了。。。如果想每天都更新的话,就需要每次都打开这个文件,修改下然后再保存,我想应该是做了缓存所以不能动态实时更新时间的。虽然麻烦了点,不过一点点一次就当签到得了。不需要日期的删掉它就可以了

收起阅读 »

基于 MUI 构建一个具有 90 +页面的APP应用,欢迎star

mui

前言

mui是一款接近原生App体验的前端框架,只需要掌握前端技术就可以开发APP应用,官方有提供功能比较全面的demo版本,
但在实战中总会遇到一些不可避免但坑,对于没有接触过mui的开发者,难免会浪费很多时间在踩坑上。

该项目以mui为开发框架,artTemplate.js作为js模版引擎,没有繁琐的配置和编译过程,拿来就可以上手,适合刚接触mui的同学参考和学习

项目运行

项目地址

git clone https://github.com/EasyTuan/mui-kidApp.git  

打开HBuider,打开项目

右键项目=>转换为移动App

运行=>真机运行(需要usb连接手机)

注:服务器到期,接口服务不再支持,能正常登陆和退出,不影响正常功能但预览和学习

目标功能

  • [x] 定位功能 -- 完成
  • [x] 选择城市 -- 完成
  • [x] 展示所选地址附近商家列表 -- 完成
  • [x] 在高德地图中寻找店铺 -- 完成
  • [x] 搜索文章,赛事 -- 完成
  • [x] 商家列表页 -- 完成
  • [x] 店铺评价页面 -- 完成
  • [x] 单张卡牌详情页面 -- 完成
  • [x] 商家详情页 -- 完成
  • [x] 登录、注册 -- 完成
  • [x] 三方微信、QQ登陆 -- 完成
  • [x] 修改密码 -- 完成
  • [x] 个人中心 -- 完成
  • [x] 发送短信、语音验证 -- 完成
  • [x] 赛事列表 -- 完成
  • [x] 赛事详情 -- 完成
  • [x] 添加、删除、修改收货地址 -- 完成
  • [x] 帐户信息 -- 完成
  • [x] 服务中心 -- 完成
  • [x] 红包 -- 完成
  • [x] 上传头像 -- 完成
  • [x] 卡牌对战发起 -- 完成

业务介绍

入口地址为 html/main.html

目录结构

├── css                     //css样式文件  
├── fonts                   //字体图标  
├── html                        //页面  
├── images                  //图片  
├── js                      //js  
│    └── lib                        //js第三方库  
├── unpackage               //App图标、启动页  
└── manifest.json           //App配置文件  

说明

如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^

或者您可以 "follow" 一下,我会不断开源更多的有趣的项目

如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR

继续阅读 »

前言

mui是一款接近原生App体验的前端框架,只需要掌握前端技术就可以开发APP应用,官方有提供功能比较全面的demo版本,
但在实战中总会遇到一些不可避免但坑,对于没有接触过mui的开发者,难免会浪费很多时间在踩坑上。

该项目以mui为开发框架,artTemplate.js作为js模版引擎,没有繁琐的配置和编译过程,拿来就可以上手,适合刚接触mui的同学参考和学习

项目运行

项目地址

git clone https://github.com/EasyTuan/mui-kidApp.git  

打开HBuider,打开项目

右键项目=>转换为移动App

运行=>真机运行(需要usb连接手机)

注:服务器到期,接口服务不再支持,能正常登陆和退出,不影响正常功能但预览和学习

目标功能

  • [x] 定位功能 -- 完成
  • [x] 选择城市 -- 完成
  • [x] 展示所选地址附近商家列表 -- 完成
  • [x] 在高德地图中寻找店铺 -- 完成
  • [x] 搜索文章,赛事 -- 完成
  • [x] 商家列表页 -- 完成
  • [x] 店铺评价页面 -- 完成
  • [x] 单张卡牌详情页面 -- 完成
  • [x] 商家详情页 -- 完成
  • [x] 登录、注册 -- 完成
  • [x] 三方微信、QQ登陆 -- 完成
  • [x] 修改密码 -- 完成
  • [x] 个人中心 -- 完成
  • [x] 发送短信、语音验证 -- 完成
  • [x] 赛事列表 -- 完成
  • [x] 赛事详情 -- 完成
  • [x] 添加、删除、修改收货地址 -- 完成
  • [x] 帐户信息 -- 完成
  • [x] 服务中心 -- 完成
  • [x] 红包 -- 完成
  • [x] 上传头像 -- 完成
  • [x] 卡牌对战发起 -- 完成

业务介绍

入口地址为 html/main.html

目录结构

├── css                     //css样式文件  
├── fonts                   //字体图标  
├── html                        //页面  
├── images                  //图片  
├── js                      //js  
│    └── lib                        //js第三方库  
├── unpackage               //App图标、启动页  
└── manifest.json           //App配置文件  

说明

如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^

或者您可以 "follow" 一下,我会不断开源更多的有趣的项目

如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR

收起阅读 »

分享 html5plus 的 native.d.ts 文件

HTML5+ Native.JS

Typescript of native.js

安装

npm install --save-dev native.d.ts

使用

import 'native.d.ts';

document.addEventListener('plusready', runApp, false);

function runApp {
// use plus.*
}

仓库地址

Github : https://github.com/ymzuiku/native.d.ts

继续阅读 »

Typescript of native.js

安装

npm install --save-dev native.d.ts

使用

import 'native.d.ts';

document.addEventListener('plusready', runApp, false);

function runApp {
// use plus.*
}

仓库地址

Github : https://github.com/ymzuiku/native.d.ts

收起阅读 »

封装一个简单实用的 plusready 方法

HTML5+ plus is not defined plusready plus

如果有小伙伴看过 mui.js 的源码的话,对于以下代码就不会陌生。

var plusReady = function (callback) {  
    if (window.plus) {  
        callback();  
    } else {  
        document.addEventListener('plusready', callback);  
    }  
};

这个方法,是用来确保 5+ API 扩展成功了,在这个方法的回调中调用 5+ 扩展 API,不会出现 plus is not defined 错误。

因为 Android 和 iOS 的一些机制不同,再加上不同的 ROM 和 Webview 都会对 5+ 扩展 API 的注入生效有所影响。
因此,实际应用中判定扩展完成,并不能单靠 plusready 事件。

情况一
在页面加载完成之前就已经触发了 plusready 事件,window.plus 扩展对象已经存在了。这时候,是不会重复触发 plusready 事件了。因此,在页面中是监听不到 plusready 事件了。也就有了先判定 window.plus 是否存在的逻辑。

情况二
页面加载后,扩展 API 加载完成,触发 plusready 事件。此时,是可以在页面中监听到 plusready 事件的。因此,就有了监听 plusready 事件触发的逻辑。

考虑到以上这些情况,就可以确保在这个 plusReady 的回调中,调用扩展的 window.plus 对象不会出现未定义的情况。

但是依旧有特殊的情况,那就是页面中本身引入了其它框架或者自己定义了 window.plus 对象,约定的原生能力扩展对象 window.plus 被占用了。
应当避免这种情况的发生,即便是引入其它库,也是可以修改其源码来处理的。
前面提到了,5+ 扩展 API 注入的时机是不确定的,因此如果只是单一的将已存在的 window.plus 对象重新赋值给其它变量,也会造成一定的隐患。

plusReady(function () {  
    alert(plus.runtime.appid);  
});
继续阅读 »

如果有小伙伴看过 mui.js 的源码的话,对于以下代码就不会陌生。

var plusReady = function (callback) {  
    if (window.plus) {  
        callback();  
    } else {  
        document.addEventListener('plusready', callback);  
    }  
};

这个方法,是用来确保 5+ API 扩展成功了,在这个方法的回调中调用 5+ 扩展 API,不会出现 plus is not defined 错误。

因为 Android 和 iOS 的一些机制不同,再加上不同的 ROM 和 Webview 都会对 5+ 扩展 API 的注入生效有所影响。
因此,实际应用中判定扩展完成,并不能单靠 plusready 事件。

情况一
在页面加载完成之前就已经触发了 plusready 事件,window.plus 扩展对象已经存在了。这时候,是不会重复触发 plusready 事件了。因此,在页面中是监听不到 plusready 事件了。也就有了先判定 window.plus 是否存在的逻辑。

情况二
页面加载后,扩展 API 加载完成,触发 plusready 事件。此时,是可以在页面中监听到 plusready 事件的。因此,就有了监听 plusready 事件触发的逻辑。

考虑到以上这些情况,就可以确保在这个 plusReady 的回调中,调用扩展的 window.plus 对象不会出现未定义的情况。

但是依旧有特殊的情况,那就是页面中本身引入了其它框架或者自己定义了 window.plus 对象,约定的原生能力扩展对象 window.plus 被占用了。
应当避免这种情况的发生,即便是引入其它库,也是可以修改其源码来处理的。
前面提到了,5+ 扩展 API 注入的时机是不确定的,因此如果只是单一的将已存在的 window.plus 对象重新赋值给其它变量,也会造成一定的隐患。

plusReady(function () {  
    alert(plus.runtime.appid);  
});
收起阅读 »

uni-app导航栏开发指南

导航栏 uniapp

看示例,这里的功能比文档里写的多:https://ext.dcloud.net.cn/plugin?id=1765

本文虽长,但值得看完。可避免开发中的很多坑

uni-app 自带原生导航栏,在pages.json里配置。
原生导航的体验更好,渲染新页面时,原生导航栏的渲染无需等待新页面dom加载,可以在新页面进入动画开始时就渲染。

原生导航还可以避免滚动条通顶,并方便的控制原生下拉刷新。
通过pages.json的配置,可以简单的、跨端的、高性能的开发业务。

但原生导航栏的扩展能力有限的。尤其是微信下,没有提供太多导航栏的配置。
在App下,pages.json里每个页面的app-plus下可以设置titleNView等更多参数,可以得到比微信小程序更丰富的扩展性。
另外,开发者也可以在必要时取消原生导航栏,使用view自行绘制导航栏。

原生导航栏的通用配置

原生导航栏的配置,均在pages.json里,每个page下面的style配置中的navigationBar各个参数配置,即为通用配置,小程序、app、h5均生效。参考https://uniapp.dcloud.io/collocation/pages?id=style

全局取消原生导航栏

在pages.json的globalStyle里,有个navigationStyle设置,默认是default,即带有原生导航栏。
也可以设置为custom。
在设为custom后,所有页面都没有原生导航。
但在微信小程序里,右上角始终都有一个胶囊按钮。
很多微信小游戏界面上也没原生导航栏,但有胶囊按钮。
一般App里不会使用这个参数配置。建议个别页面单独设置不使用原生导航,具体见下。

单独去除原生导航栏

支持通过如下方法取消单独一个页面的原生导航栏。但小程序右上角胶囊按钮仍然去不掉。页面配置 navigationStyle 为 custom:

{  
    "path" : "pages/log/log",  
    "style" : {  
        "navigationStyle":"custom"  
    }  
}

原生导航栏在App侧的扩展

微信小程序的设计里,没有给原生导航提供太多自定义能力。在开发App时是不够用的。
pages.json里,每个page下面的style下面还有一个子扩展节点:app-plus。
这个节点定义了在5+App环境下,也即iOS、Android环境下,增强的配置。
其中有一个子节点titleNView,这个是5+规范里webview页面的原生导航窗体规范。
参考https://uniapp.dcloud.io/collocation/pages?id=app-plus

App去除导航栏后改变状态栏样式

App因为默认为沉浸式,去除导航栏后,页面顶部会直通到状态栏的区域,可能出现如下需求:

  • 改变状态栏文字颜色:设置该页面的 navigationBarTextStyle 属性,可取值为 black/white。如果想单独设置颜色,App端可使用plus.navigator.setStatusBarStyle设置。部分低端Android手机(4.4)自身不支持设置状态栏前景色。
  • 改变状态栏背景颜色:通过绘制一个占位的view固定放在状态栏位置,设置此view的背景颜色,即可达到想要的效果,uni-app提供了一个状态栏高度的css变量,具体参考:http://uniapp.dcloud.io/frame?id=css%E5%8F%98%E9%87%8F

以下为示例:

<!-- #ifdef APP-PLUS -->  
<view class="status_bar">  
    <view class="top_view"></view>  
</view>  
<!-- #endif -->
.status_bar {  
    height: var(--status-bar-height);  
    width: 100%;  
    background-color: #F8F8F8;  
}  
.top_view {  
    height: var(--status-bar-height);  
    width: 100%;  
    position: fixed;  
    background-color: #F8F8F8;  
    top: 0;  
    z-index: 999;  
}

给原生导航栏添加自定义按钮

注意:按钮的点击事件需要在页面监听onNavigationBarButtonTap事件

页面监听代码如下:

export default {  
    data() {  
        return {}  
    },  
    onNavigationBarButtonTap() {  
        console.log("点击了自定义按钮");  
    }  
}  

pages.json配置如下:

{  
    "path": "pages/log/log",  
    "style": {  
        "navigationBarTitleText": "hello",  
        "app-plus": {  
            "titleNView": {  
                "buttons": [{  
                    "text": "\ue534",  
                    "fontSrc": "/static/uni.ttf",  
                    "fontSize": "22px"  
                }]  
            }  
        }  
    }  
}

buttons的text推荐使用字体图标。
如果按钮使用的汉字或英文较长,推荐把字体改小一点,或者调节按钮宽度等值。
配置button的背景颜色为透明:background:'rgba(0,0,0,0)'

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

原生导航栏自定义按钮带红点和角标

{  
    "path" : "nav-dot/nav-dot",  
    "style" : {  
        "navigationBarTitleText" : "导航栏带红点和角标",  
        "app-plus" : {  
            "titleNView" : {  
                "buttons" : [  
                    {  
                        "text" : "消息",  
                        "fontSize" : "14",  
                        "redDot" : true  
                    },  
                    {  
                        "text" : "关注",  
                        "fontSize" : "14",  
                        "badgeText" : "12"  
                    }  
                ]  
            }  
        }  
    }  
}

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

原生导航栏自定义按钮带下拉选择(城市选择)

{  
    "path" : "nav-city-dropdown/nav-city-dropdown",  
    "style" : {  
        "navigationBarTitleText" : "导航栏带城市选择",  
        "app-plus" : {  
            "titleNView" : {  
                "buttons" : [  
                    {  
                        "text" : "北京市",  
                        "fontSize" : "14",  
                        "select" : true,  
                        "width" : "auto"  
                    }  
                ]  
            }  
        }  
    }  
}

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

导航栏上的原生搜索框

原生导航栏支持放置原生搜索框,可点击直接弹出软键盘,也可以点击后跳转到新页面搜索。
因代码较多,此处不列,请参考hello uni-app的模板-顶部导航标题栏示例。
如需动态修改searchInput,或者获取searchInput的placehold,参考uni-app动态修改App端导航栏

配置原生导航栏的透明渐变

原生导航栏还支持透明渐变效果,页面刚载入时没有导航标题,页面内容通顶到状态栏里,页面向下滚动后标题栏渐变出现。

{  
    "path": "pages/log/log",  
    "style": {  
        "navigationBarTitleText": "hello",  
        "app-plus": {  
            "titleNView": {  
                "type": "transparent"  
            }  
        }  
    }  
}

实际上可用的titleNView设置还有很多,详细的api见http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewTitleNViewStyles

透明渐变的导航栏的button图标有一个默认的灰色背景圈,防止背景图和按钮前景颜色相同导致按钮无法看清。如果要去掉这个灰色背景图,可以配置button的背景颜色为透明:background:'rgba(0,0,0,0)'

原生导航栏绘制图片

titleNView新版配置可以直接配图片,还支持Gif图。但这里提供一个黑科技写法,通过在titleNView里配置tags,可以实现导航栏绘制图片的效果:

{  
    "path" : "nav-image/nav-image",  
    "style" : {  
        "app-plus" : {  
            "titleNView" : {  
                "titleText" : "",  
                "tags" : [  
                    {  
                        "tag" : "img",  
                        "src" : "/static/nav.png",  
                        "position" : {  
                            "left" : "auto",  
                            "top" : "auto",  
                            "width" : "110px",  
                            "height" : "26px"  
                        }  
                    }  
                ]  
            }  
        }  
    }  
}

通过配置 tags 除了可以绘制图片,还可以绘制更多丰富的内容,如:richtext(富文本)、font(文本)、input(输入框)、rect(矩形区域)。详情参考:titleNViewtags

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

通过setStyle方式动态修改原生导航栏样式

如果需要js动态修改导航栏,uni有跨端的api可修改标题、背景色、前景色。这部分是app、小程序、h5都支持的,参考https://uniapp.dcloud.io/api/ui/navigationbar

对于app侧扩展的设置,比如自己添加的buttons,则需使用plus的js api来动态设置。在App端可以通过得到webview对象,通过setStyle方法重新设置,包括修改webview对象的titleNview属性,以达到修改标题栏按钮文字及样式的功能。
具体参考:https://ask.dcloud.net.cn/article/35374

App侧使用subnvue自行绘制原生导航

nvue其实是weex上补充了uni的api。
uni-app支持使用nvue页面,也就是weex原生引擎,绘制顶部的原生导航栏。
在hello uni-app的API-界面示例中,有subnvue示例,里面顶部导航栏是渐变色的,这就是subnvue的原生导航栏。

在pages.json的配置如下:

{  
    "path": "subnvue/subnvue",  
    "style": {  
        "app-plus": {  
            "titleNView": false,  
            "subNVues": [{  
                "id": "nav",  
                "path": "subnvue/subnvue/nav",  
                "type": "navigationBar"  
            }]  
        }  
    }  
}

更新:从HBuilderX2.6.3起,titleNView直接支持了背景图、渐变色,不再需要通过subnvue的方式了。而且性能比subnvue更好。

App侧使用plus.nativeObj.view自定义原生导航栏

注意:从HBuilderX 1.9.10起提供了subnvue,比使用plus.nativeObj.view自定义原生导航栏更加方便。详见上一节。

titleNView提供的配置,虽然比微信多不少,但有时仍然无法满足某些场景的需求,比如在titleNView中画一个选项卡。
此时有3种处理方式。1. 使用plus.nativeObj.view的api自定义titleNView。2. 页面采用nvue,即weex方式制作。3. 取消原生导航,使用view自行绘制(见上)。
本节先说方式1. 使用plus.nativeObj.view
plus.nativeObj是5+引擎提供的轻量原生渲染引擎,其中plus.nativeObj.view一个自定义性很强的对象,以下简称nview。
规范文档是:www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View
nview是一个基于canvas理念的绘制引擎,在一块画布上自行绘制、覆盖、擦除。
nview可以画出任何界面、线条、矩形、文字、图片、包括原生的input输入框。
其实我们所看到的各种界面对象控件,在计算机底层都是绘图引擎基于draw字、draw图、draw线条来做的。
与weex相比,nview并不够强,nview没有dom概念,不支持内部滚动。
其实titleNView,包括原生tabbar、cover-view,他们的底层实现都是基于nview的。

获取当前页面的titleNView对象,参考http://ask.dcloud.net.cn/article/35036
同时上述参考文章中还有一个给titleNView的右上角画一个小红点的例子。

开发者制作的示例,如何给原生导航栏顶部画一个原生input:http://ask.dcloud.net.cn/article/35201

取消原生导航栏后,使用前端标签组件模拟绘制导航栏

不管是全局取消原生导航栏,还是在App下某个页面取消原生导航,如果还想自己绘制一些个性化的title,往往会使用view组件。
尤其是App的首页,顶部经常有各种特殊设置,此时需要自己使用前端技术来绘制导航。

导航栏应该是由状态栏和标题栏构成,状态栏的高度为 var(--status-bar-height) 此变量为uni-app框架提供仅在在css生效,标题栏的高度设为88px,整个状态栏的高度应为: calc(var(--status-bar-height) + 88px)
(upx主要针对宽度,高度无所谓还可以使用px)

.title-contents{  
    height: calc(var(--status-bar-height) + 88px);  
}  
.status{  
    height: var(--status-bar-height);  
}  
.titles{  
    height: 88px;  
}

状态栏和标题栏都应固定在页面顶部,需设置 position:fixed,标题栏的top应为状态栏的高度

.top-view{  
    width: 100%;  
    position: fixed;  
    top: 0;  
}  
.titles{  
    top: var(--status-bar-height);  
}

绘制的返回箭头需要绑定点击事件,返回上一个页面

<view class="titleLeftButton" @click="backButton"></view>  

methods:{  
    backButton(){  
        uni.navigateBack()  
    }  
}

以下为导航栏组件的部分代码

<template>  
    <view class="title-contents">  
        <view class="top-view status" :style="{background:statusColor}"></view>  
        <view class="_top titles" :style="{background:statusColor}">  
            <view class="titleLeftButton" @click="backButton" v-if="showLeftButton"></view>  
            <view class="titleText" :class="titleClass">{{titleText}}</view>  
            <view class="titleRightButton" @click="rightButton" v-if="showRightButton"></view>  
        </view>  
    </view>  
</template>  
<script>  
    export default {  
        props:{  
            titleText:{  
                type:String,  
                default:""  
            },  
            statusColor:{  
                type:String,  
                default:"#8F8F94"  
            },  
            showLeftButton:{  
                type:Boolean,  
                default:true  
            },  
            showRightButton:{  
                type:Boolean,  
                default:false  
            }  
        },  
        methods:{  
            backButton(){  
                uni.navigateBack()  
            },  
            ...  
        }  
    }  
</script>  
<style>  
    ...  
    .top-view{  
        width: 100%;  
        position: fixed;  
        top: 0;  
    }  
</style>  

Ps:若页面不需要标题栏,只需一个状态栏的view占位,那么只需在页面添加一个view即可不需要引入外部组件以免影响性能。

<view class="status-contents">  
    <view class="status top-view"></view>  
</view>
//css  
.status-contents{  
    height: var(--status-bar-height);  
}  
.top-view{  
    width: 100%;  
    position: fixed;  
    top: 0;  
}  
.status{  
    height:var(--status-bar-height);  
}

uni ui里有前端实现的自定义导航栏组件,推荐不要自己写,直接用写好的组件,https://ext.dcloud.net.cn/plugin?id=52,hello uni-app的uni ui中也有示例。

注意事项

取消原生导航栏后,自己使用HTML自定义组件模拟导航栏,会有很多性能体验问题:

  1. 加载不如原生导航快
  2. 下拉刷新无法从自定义的导航栏组件下面下拉。除非使用前端做下拉刷新,但性能不如自带的原生下拉刷新。
  3. 必须取消页面的bounce效果,否则滚动到顶时再拖屏幕,在iOS上发现title也被拖下来了。
  4. 滚动条会通顶
    所以除非不得以,不要取消原生导航栏。
    如必须使用,注意如下几点:
  5. 涉及到导航栏高度的css尽量放置在App.vue里面以提高渲染速度(css渲染顺序:先渲染App.vue里面的css,再渲染页面css)
  6. 如果是深色造成闪屏,需要在pages.json的titleNView下配置webview的背景色
  7. 状态栏颜色应设置默认颜色,若非必要,不建议修改其颜色
  8. 减少在组件中使用 :style="" 的使用以提高性能
  9. 下拉刷新使用circle方式,并设置offset,让下拉刷新的圈从指定位置开始下拉,具体见pages.json配置文档

有个高频场景是App“首页”的title自定义,如果实现的效果很个性化,那么使用plus.nativeObj.view的方案会过于复杂,由于首页并不存在新页面进入立即渲染的压力,所以App首页如果要大幅定制,推荐使用前端view绘制,而不是使用plus.nativeObj.view。

如果把自定义导航封装成组件,虽然多个页面引入方便,但性能下降,因为这种自定义组件的加载是晚于页面基本元素的,会导致新页面进入动画时无法渲染title。
所以导航条这种要求在动画期渲染的东西,尽量不要使用自定义组件方式。

在hello uni-app示例中有各种导航栏的源码。
在扩展ui中有前端自定义导航栏。
在模板中有各种原生的导航栏。
大多数情况复制这些代码就够了。

继续阅读 »

看示例,这里的功能比文档里写的多:https://ext.dcloud.net.cn/plugin?id=1765

本文虽长,但值得看完。可避免开发中的很多坑

uni-app 自带原生导航栏,在pages.json里配置。
原生导航的体验更好,渲染新页面时,原生导航栏的渲染无需等待新页面dom加载,可以在新页面进入动画开始时就渲染。

原生导航还可以避免滚动条通顶,并方便的控制原生下拉刷新。
通过pages.json的配置,可以简单的、跨端的、高性能的开发业务。

但原生导航栏的扩展能力有限的。尤其是微信下,没有提供太多导航栏的配置。
在App下,pages.json里每个页面的app-plus下可以设置titleNView等更多参数,可以得到比微信小程序更丰富的扩展性。
另外,开发者也可以在必要时取消原生导航栏,使用view自行绘制导航栏。

原生导航栏的通用配置

原生导航栏的配置,均在pages.json里,每个page下面的style配置中的navigationBar各个参数配置,即为通用配置,小程序、app、h5均生效。参考https://uniapp.dcloud.io/collocation/pages?id=style

全局取消原生导航栏

在pages.json的globalStyle里,有个navigationStyle设置,默认是default,即带有原生导航栏。
也可以设置为custom。
在设为custom后,所有页面都没有原生导航。
但在微信小程序里,右上角始终都有一个胶囊按钮。
很多微信小游戏界面上也没原生导航栏,但有胶囊按钮。
一般App里不会使用这个参数配置。建议个别页面单独设置不使用原生导航,具体见下。

单独去除原生导航栏

支持通过如下方法取消单独一个页面的原生导航栏。但小程序右上角胶囊按钮仍然去不掉。页面配置 navigationStyle 为 custom:

{  
    "path" : "pages/log/log",  
    "style" : {  
        "navigationStyle":"custom"  
    }  
}

原生导航栏在App侧的扩展

微信小程序的设计里,没有给原生导航提供太多自定义能力。在开发App时是不够用的。
pages.json里,每个page下面的style下面还有一个子扩展节点:app-plus。
这个节点定义了在5+App环境下,也即iOS、Android环境下,增强的配置。
其中有一个子节点titleNView,这个是5+规范里webview页面的原生导航窗体规范。
参考https://uniapp.dcloud.io/collocation/pages?id=app-plus

App去除导航栏后改变状态栏样式

App因为默认为沉浸式,去除导航栏后,页面顶部会直通到状态栏的区域,可能出现如下需求:

  • 改变状态栏文字颜色:设置该页面的 navigationBarTextStyle 属性,可取值为 black/white。如果想单独设置颜色,App端可使用plus.navigator.setStatusBarStyle设置。部分低端Android手机(4.4)自身不支持设置状态栏前景色。
  • 改变状态栏背景颜色:通过绘制一个占位的view固定放在状态栏位置,设置此view的背景颜色,即可达到想要的效果,uni-app提供了一个状态栏高度的css变量,具体参考:http://uniapp.dcloud.io/frame?id=css%E5%8F%98%E9%87%8F

以下为示例:

<!-- #ifdef APP-PLUS -->  
<view class="status_bar">  
    <view class="top_view"></view>  
</view>  
<!-- #endif -->
.status_bar {  
    height: var(--status-bar-height);  
    width: 100%;  
    background-color: #F8F8F8;  
}  
.top_view {  
    height: var(--status-bar-height);  
    width: 100%;  
    position: fixed;  
    background-color: #F8F8F8;  
    top: 0;  
    z-index: 999;  
}

给原生导航栏添加自定义按钮

注意:按钮的点击事件需要在页面监听onNavigationBarButtonTap事件

页面监听代码如下:

export default {  
    data() {  
        return {}  
    },  
    onNavigationBarButtonTap() {  
        console.log("点击了自定义按钮");  
    }  
}  

pages.json配置如下:

{  
    "path": "pages/log/log",  
    "style": {  
        "navigationBarTitleText": "hello",  
        "app-plus": {  
            "titleNView": {  
                "buttons": [{  
                    "text": "\ue534",  
                    "fontSrc": "/static/uni.ttf",  
                    "fontSize": "22px"  
                }]  
            }  
        }  
    }  
}

buttons的text推荐使用字体图标。
如果按钮使用的汉字或英文较长,推荐把字体改小一点,或者调节按钮宽度等值。
配置button的背景颜色为透明:background:'rgba(0,0,0,0)'

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

原生导航栏自定义按钮带红点和角标

{  
    "path" : "nav-dot/nav-dot",  
    "style" : {  
        "navigationBarTitleText" : "导航栏带红点和角标",  
        "app-plus" : {  
            "titleNView" : {  
                "buttons" : [  
                    {  
                        "text" : "消息",  
                        "fontSize" : "14",  
                        "redDot" : true  
                    },  
                    {  
                        "text" : "关注",  
                        "fontSize" : "14",  
                        "badgeText" : "12"  
                    }  
                ]  
            }  
        }  
    }  
}

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

原生导航栏自定义按钮带下拉选择(城市选择)

{  
    "path" : "nav-city-dropdown/nav-city-dropdown",  
    "style" : {  
        "navigationBarTitleText" : "导航栏带城市选择",  
        "app-plus" : {  
            "titleNView" : {  
                "buttons" : [  
                    {  
                        "text" : "北京市",  
                        "fontSize" : "14",  
                        "select" : true,  
                        "width" : "auto"  
                    }  
                ]  
            }  
        }  
    }  
}

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

导航栏上的原生搜索框

原生导航栏支持放置原生搜索框,可点击直接弹出软键盘,也可以点击后跳转到新页面搜索。
因代码较多,此处不列,请参考hello uni-app的模板-顶部导航标题栏示例。
如需动态修改searchInput,或者获取searchInput的placehold,参考uni-app动态修改App端导航栏

配置原生导航栏的透明渐变

原生导航栏还支持透明渐变效果,页面刚载入时没有导航标题,页面内容通顶到状态栏里,页面向下滚动后标题栏渐变出现。

{  
    "path": "pages/log/log",  
    "style": {  
        "navigationBarTitleText": "hello",  
        "app-plus": {  
            "titleNView": {  
                "type": "transparent"  
            }  
        }  
    }  
}

实际上可用的titleNView设置还有很多,详细的api见http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewTitleNViewStyles

透明渐变的导航栏的button图标有一个默认的灰色背景圈,防止背景图和按钮前景颜色相同导致按钮无法看清。如果要去掉这个灰色背景图,可以配置button的背景颜色为透明:background:'rgba(0,0,0,0)'

原生导航栏绘制图片

titleNView新版配置可以直接配图片,还支持Gif图。但这里提供一个黑科技写法,通过在titleNView里配置tags,可以实现导航栏绘制图片的效果:

{  
    "path" : "nav-image/nav-image",  
    "style" : {  
        "app-plus" : {  
            "titleNView" : {  
                "titleText" : "",  
                "tags" : [  
                    {  
                        "tag" : "img",  
                        "src" : "/static/nav.png",  
                        "position" : {  
                            "left" : "auto",  
                            "top" : "auto",  
                            "width" : "110px",  
                            "height" : "26px"  
                        }  
                    }  
                ]  
            }  
        }  
    }  
}

通过配置 tags 除了可以绘制图片,还可以绘制更多丰富的内容,如:richtext(富文本)、font(文本)、input(输入框)、rect(矩形区域)。详情参考:titleNViewtags

以上代码在hello uni-app的模板-顶部导航标题栏中有示例。

通过setStyle方式动态修改原生导航栏样式

如果需要js动态修改导航栏,uni有跨端的api可修改标题、背景色、前景色。这部分是app、小程序、h5都支持的,参考https://uniapp.dcloud.io/api/ui/navigationbar

对于app侧扩展的设置,比如自己添加的buttons,则需使用plus的js api来动态设置。在App端可以通过得到webview对象,通过setStyle方法重新设置,包括修改webview对象的titleNview属性,以达到修改标题栏按钮文字及样式的功能。
具体参考:https://ask.dcloud.net.cn/article/35374

App侧使用subnvue自行绘制原生导航

nvue其实是weex上补充了uni的api。
uni-app支持使用nvue页面,也就是weex原生引擎,绘制顶部的原生导航栏。
在hello uni-app的API-界面示例中,有subnvue示例,里面顶部导航栏是渐变色的,这就是subnvue的原生导航栏。

在pages.json的配置如下:

{  
    "path": "subnvue/subnvue",  
    "style": {  
        "app-plus": {  
            "titleNView": false,  
            "subNVues": [{  
                "id": "nav",  
                "path": "subnvue/subnvue/nav",  
                "type": "navigationBar"  
            }]  
        }  
    }  
}

更新:从HBuilderX2.6.3起,titleNView直接支持了背景图、渐变色,不再需要通过subnvue的方式了。而且性能比subnvue更好。

App侧使用plus.nativeObj.view自定义原生导航栏

注意:从HBuilderX 1.9.10起提供了subnvue,比使用plus.nativeObj.view自定义原生导航栏更加方便。详见上一节。

titleNView提供的配置,虽然比微信多不少,但有时仍然无法满足某些场景的需求,比如在titleNView中画一个选项卡。
此时有3种处理方式。1. 使用plus.nativeObj.view的api自定义titleNView。2. 页面采用nvue,即weex方式制作。3. 取消原生导航,使用view自行绘制(见上)。
本节先说方式1. 使用plus.nativeObj.view
plus.nativeObj是5+引擎提供的轻量原生渲染引擎,其中plus.nativeObj.view一个自定义性很强的对象,以下简称nview。
规范文档是:www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View
nview是一个基于canvas理念的绘制引擎,在一块画布上自行绘制、覆盖、擦除。
nview可以画出任何界面、线条、矩形、文字、图片、包括原生的input输入框。
其实我们所看到的各种界面对象控件,在计算机底层都是绘图引擎基于draw字、draw图、draw线条来做的。
与weex相比,nview并不够强,nview没有dom概念,不支持内部滚动。
其实titleNView,包括原生tabbar、cover-view,他们的底层实现都是基于nview的。

获取当前页面的titleNView对象,参考http://ask.dcloud.net.cn/article/35036
同时上述参考文章中还有一个给titleNView的右上角画一个小红点的例子。

开发者制作的示例,如何给原生导航栏顶部画一个原生input:http://ask.dcloud.net.cn/article/35201

取消原生导航栏后,使用前端标签组件模拟绘制导航栏

不管是全局取消原生导航栏,还是在App下某个页面取消原生导航,如果还想自己绘制一些个性化的title,往往会使用view组件。
尤其是App的首页,顶部经常有各种特殊设置,此时需要自己使用前端技术来绘制导航。

导航栏应该是由状态栏和标题栏构成,状态栏的高度为 var(--status-bar-height) 此变量为uni-app框架提供仅在在css生效,标题栏的高度设为88px,整个状态栏的高度应为: calc(var(--status-bar-height) + 88px)
(upx主要针对宽度,高度无所谓还可以使用px)

.title-contents{  
    height: calc(var(--status-bar-height) + 88px);  
}  
.status{  
    height: var(--status-bar-height);  
}  
.titles{  
    height: 88px;  
}

状态栏和标题栏都应固定在页面顶部,需设置 position:fixed,标题栏的top应为状态栏的高度

.top-view{  
    width: 100%;  
    position: fixed;  
    top: 0;  
}  
.titles{  
    top: var(--status-bar-height);  
}

绘制的返回箭头需要绑定点击事件,返回上一个页面

<view class="titleLeftButton" @click="backButton"></view>  

methods:{  
    backButton(){  
        uni.navigateBack()  
    }  
}

以下为导航栏组件的部分代码

<template>  
    <view class="title-contents">  
        <view class="top-view status" :style="{background:statusColor}"></view>  
        <view class="_top titles" :style="{background:statusColor}">  
            <view class="titleLeftButton" @click="backButton" v-if="showLeftButton"></view>  
            <view class="titleText" :class="titleClass">{{titleText}}</view>  
            <view class="titleRightButton" @click="rightButton" v-if="showRightButton"></view>  
        </view>  
    </view>  
</template>  
<script>  
    export default {  
        props:{  
            titleText:{  
                type:String,  
                default:""  
            },  
            statusColor:{  
                type:String,  
                default:"#8F8F94"  
            },  
            showLeftButton:{  
                type:Boolean,  
                default:true  
            },  
            showRightButton:{  
                type:Boolean,  
                default:false  
            }  
        },  
        methods:{  
            backButton(){  
                uni.navigateBack()  
            },  
            ...  
        }  
    }  
</script>  
<style>  
    ...  
    .top-view{  
        width: 100%;  
        position: fixed;  
        top: 0;  
    }  
</style>  

Ps:若页面不需要标题栏,只需一个状态栏的view占位,那么只需在页面添加一个view即可不需要引入外部组件以免影响性能。

<view class="status-contents">  
    <view class="status top-view"></view>  
</view>
//css  
.status-contents{  
    height: var(--status-bar-height);  
}  
.top-view{  
    width: 100%;  
    position: fixed;  
    top: 0;  
}  
.status{  
    height:var(--status-bar-height);  
}

uni ui里有前端实现的自定义导航栏组件,推荐不要自己写,直接用写好的组件,https://ext.dcloud.net.cn/plugin?id=52,hello uni-app的uni ui中也有示例。

注意事项

取消原生导航栏后,自己使用HTML自定义组件模拟导航栏,会有很多性能体验问题:

  1. 加载不如原生导航快
  2. 下拉刷新无法从自定义的导航栏组件下面下拉。除非使用前端做下拉刷新,但性能不如自带的原生下拉刷新。
  3. 必须取消页面的bounce效果,否则滚动到顶时再拖屏幕,在iOS上发现title也被拖下来了。
  4. 滚动条会通顶
    所以除非不得以,不要取消原生导航栏。
    如必须使用,注意如下几点:
  5. 涉及到导航栏高度的css尽量放置在App.vue里面以提高渲染速度(css渲染顺序:先渲染App.vue里面的css,再渲染页面css)
  6. 如果是深色造成闪屏,需要在pages.json的titleNView下配置webview的背景色
  7. 状态栏颜色应设置默认颜色,若非必要,不建议修改其颜色
  8. 减少在组件中使用 :style="" 的使用以提高性能
  9. 下拉刷新使用circle方式,并设置offset,让下拉刷新的圈从指定位置开始下拉,具体见pages.json配置文档

有个高频场景是App“首页”的title自定义,如果实现的效果很个性化,那么使用plus.nativeObj.view的方案会过于复杂,由于首页并不存在新页面进入立即渲染的压力,所以App首页如果要大幅定制,推荐使用前端view绘制,而不是使用plus.nativeObj.view。

如果把自定义导航封装成组件,虽然多个页面引入方便,但性能下降,因为这种自定义组件的加载是晚于页面基本元素的,会导致新页面进入动画时无法渲染title。
所以导航条这种要求在动画期渲染的东西,尽量不要使用自定义组件方式。

在hello uni-app示例中有各种导航栏的源码。
在扩展ui中有前端自定义导航栏。
在模板中有各种原生的导航栏。
大多数情况复制这些代码就够了。

收起阅读 »

【申精】swiper + scroll-view 实现下拉刷新

uniapp

各位D友大家好,相信大家对uniapp都非常的喜欢,非常好的设计,能省去我们很多的开发成本。但是因为有一些是不尽人意的,比如我们想要实现的和原生效果接近的滑动tab 下拉刷新,官方给出的示例中无法支持下拉刷新。在此我放出一个的解决方案,可以实现我们要的效果。但是毕竟是投机取巧,还是希望官方可以出个单独的插件。闲话少说,开始~

首先我们知道 原生下拉刷新的出发是根据page的scrollTop触发的。当scrollTop为0时才开始触发。那么,我们就可以根据这个来实现了

第一步,页面构建完成之后开始计算你的scroll-view需要的高度,scroll-view tabList 的高度要求超出屏幕可视高度1个标准单位(太多体验不好)。

第二步,添加scroll-view 的scroll事件,获取scrollTop值。判断当scrollTop大于0的时候调用pageScrollTo方法将page 的 scroll 拉至1
这样scroll-view在下拉的时候就不会触发系统下拉刷新的动作

第三步,添加scroll-view 的scrolltoupper事件并设置属性upper-threshold=0,事件触发时调用pageScrollTo方法将page 的 scroll 拉至0就能正常的使用下拉刷新了。

第四步,在tab切换时也判断当前scroll的scrollTop,然后调整当前tab的page scrollTop。

至此,swiper scroll-view 下拉刷新 就完成了,是不是很简单。

缺点:头部tabBar会上下1个标准单位的跳动(不过能接受,不是很影响)
下面贴出我的代码:

效果演示:

继续阅读 »

各位D友大家好,相信大家对uniapp都非常的喜欢,非常好的设计,能省去我们很多的开发成本。但是因为有一些是不尽人意的,比如我们想要实现的和原生效果接近的滑动tab 下拉刷新,官方给出的示例中无法支持下拉刷新。在此我放出一个的解决方案,可以实现我们要的效果。但是毕竟是投机取巧,还是希望官方可以出个单独的插件。闲话少说,开始~

首先我们知道 原生下拉刷新的出发是根据page的scrollTop触发的。当scrollTop为0时才开始触发。那么,我们就可以根据这个来实现了

第一步,页面构建完成之后开始计算你的scroll-view需要的高度,scroll-view tabList 的高度要求超出屏幕可视高度1个标准单位(太多体验不好)。

第二步,添加scroll-view 的scroll事件,获取scrollTop值。判断当scrollTop大于0的时候调用pageScrollTo方法将page 的 scroll 拉至1
这样scroll-view在下拉的时候就不会触发系统下拉刷新的动作

第三步,添加scroll-view 的scrolltoupper事件并设置属性upper-threshold=0,事件触发时调用pageScrollTo方法将page 的 scroll 拉至0就能正常的使用下拉刷新了。

第四步,在tab切换时也判断当前scroll的scrollTop,然后调整当前tab的page scrollTop。

至此,swiper scroll-view 下拉刷新 就完成了,是不是很简单。

缺点:头部tabBar会上下1个标准单位的跳动(不过能接受,不是很影响)
下面贴出我的代码:

效果演示:

收起阅读 »

PHP编程中使用CURL发送HTTP请求的基本流程

PHP

  在PHP编程中,有时候需要编程技术人员使用CURL的PHP扩展完成一个HTTP请求的发送,对于这个操作来说,很多初学者都会遇到很多苦难,那么下面就来为大家讲解一下。一般有以下几个步骤:

  1. 初始化连接句柄;

  2. 设置CURL选项;

  3. 执行并获取结果;

  4. 释放VURL连接句柄。

  下面的程序片段是使用CURL发送HTTP的典型过程

  上述代码中使用到了四个函数

  · curl_init() 和 curl_close() 分别是初始化CURL连接和关闭CURL连接,都比较简单。

  · curl_exec() 执行CURL请求,如果没有错误发生,该函数的返回是对应URL返回的数据,以字符串表示满意;如果发生错误,该函数返回 FALSE。需要注意的是,判断输出是否为FALSE用的是全等号,这是为了区分返回空串和出错的情况。

  · CURL函数库里最重要的函数是curl_setopt(),它可以通过设定CURL函数库定义的选项来定制HTTP请求。上述代码片段中使用了三个重要的选项:

  1. CURLOPT_URL 指定请求的URL;

  2. CURLOPT_RETURNTRANSFER 设置为1表示稍后执行的curl_exec函数的返回是URL的返回字符串,而不是把返回字符串定向到标准输出并返回TRUE;

  CURLLOPT_HEADER设置为0表示不返回HTTP头部信息。

  获取CURL请求的输出信息

  在curl_exec()函数执行之后,可以使用curl_getinfo()函数获取CURL请求输出的相关信息,示例代码如下:

  上述代码中curl_getinfo返回的是一个关联数组,包含以下数据:

  · url:网络地址。

  · content_type:内容编码。

  · http_code:HTTP状态码。

  · header_size:header的大小。

  · request_size:请求的大小。

  · filetime:文件创建的时间。

  · ssl_verify_result:SSL验证结果。

  · redirect_count:跳转计数。

  · total_time:总耗时。

  · namelookup_time:DNS查询耗时。

  · connect_time:等待连接耗时。

  · pretransfer_time:传输前准备耗时。

  · size_uplpad:上传数据的大小。

  · size_download:下载数据的大小。

  · speed_download:下载速度。

  · speed_upload:上传速度。

  · download_content_length:下载内容的长度。

  · upload_content_length:上传内容的长度。

  · starttransfer_time:开始传输的时间表。

  · redirect_time:重定向耗时。

  curl_getinfo()函数还有一个可选择参数$opt,通过这个参数可以设置一些常量,对应到上术这个字段,如果设置了第二个参数,那么返回的只有指定的信息。例如设置$opt为CURLINFO_TOTAL_TIME,则curl_getinfo()函数只返回total_time,即总传输消耗的时间,在只需要关注某些传输信息时,设置$opt参数很有意义。

  使用CURL发送GET请求

  如何使用CURL来发送GET请求,发送GET请求的关键是拼装格式正确的URL。请求地址和GET数据由一个“?”分割,然后GET变量的名称和值用“=”分隔,各个GET名称和值由“&”连接。PHP为我们提供了一个函数专门用来拼装GET请求和数据部分——http_build_query,该函数接受一个关联数组,返回由该关联数据描述的GET请求字符串。使用这个函数,结合CURL发送HTTP请求的一般流程,我们封闭了一个发送GET请求的函数——doCurlGetRequest,具体代码如下:

  使用CURL发送POST请求

  可以使用CURL提供的选项CURLOPT_POSTFIELDS,设置该选项为POST字符串数据就可以把请求放在正文中。同样我们实现了一个发送POST请求的函数——doCurlPostRequest,代码如下:

  好了,现在大家应该清楚如何操作了吧,如果还是存在问题的话可以咨询留言。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

继续阅读 »

  在PHP编程中,有时候需要编程技术人员使用CURL的PHP扩展完成一个HTTP请求的发送,对于这个操作来说,很多初学者都会遇到很多苦难,那么下面就来为大家讲解一下。一般有以下几个步骤:

  1. 初始化连接句柄;

  2. 设置CURL选项;

  3. 执行并获取结果;

  4. 释放VURL连接句柄。

  下面的程序片段是使用CURL发送HTTP的典型过程

  上述代码中使用到了四个函数

  · curl_init() 和 curl_close() 分别是初始化CURL连接和关闭CURL连接,都比较简单。

  · curl_exec() 执行CURL请求,如果没有错误发生,该函数的返回是对应URL返回的数据,以字符串表示满意;如果发生错误,该函数返回 FALSE。需要注意的是,判断输出是否为FALSE用的是全等号,这是为了区分返回空串和出错的情况。

  · CURL函数库里最重要的函数是curl_setopt(),它可以通过设定CURL函数库定义的选项来定制HTTP请求。上述代码片段中使用了三个重要的选项:

  1. CURLOPT_URL 指定请求的URL;

  2. CURLOPT_RETURNTRANSFER 设置为1表示稍后执行的curl_exec函数的返回是URL的返回字符串,而不是把返回字符串定向到标准输出并返回TRUE;

  CURLLOPT_HEADER设置为0表示不返回HTTP头部信息。

  获取CURL请求的输出信息

  在curl_exec()函数执行之后,可以使用curl_getinfo()函数获取CURL请求输出的相关信息,示例代码如下:

  上述代码中curl_getinfo返回的是一个关联数组,包含以下数据:

  · url:网络地址。

  · content_type:内容编码。

  · http_code:HTTP状态码。

  · header_size:header的大小。

  · request_size:请求的大小。

  · filetime:文件创建的时间。

  · ssl_verify_result:SSL验证结果。

  · redirect_count:跳转计数。

  · total_time:总耗时。

  · namelookup_time:DNS查询耗时。

  · connect_time:等待连接耗时。

  · pretransfer_time:传输前准备耗时。

  · size_uplpad:上传数据的大小。

  · size_download:下载数据的大小。

  · speed_download:下载速度。

  · speed_upload:上传速度。

  · download_content_length:下载内容的长度。

  · upload_content_length:上传内容的长度。

  · starttransfer_time:开始传输的时间表。

  · redirect_time:重定向耗时。

  curl_getinfo()函数还有一个可选择参数$opt,通过这个参数可以设置一些常量,对应到上术这个字段,如果设置了第二个参数,那么返回的只有指定的信息。例如设置$opt为CURLINFO_TOTAL_TIME,则curl_getinfo()函数只返回total_time,即总传输消耗的时间,在只需要关注某些传输信息时,设置$opt参数很有意义。

  使用CURL发送GET请求

  如何使用CURL来发送GET请求,发送GET请求的关键是拼装格式正确的URL。请求地址和GET数据由一个“?”分割,然后GET变量的名称和值用“=”分隔,各个GET名称和值由“&”连接。PHP为我们提供了一个函数专门用来拼装GET请求和数据部分——http_build_query,该函数接受一个关联数组,返回由该关联数据描述的GET请求字符串。使用这个函数,结合CURL发送HTTP请求的一般流程,我们封闭了一个发送GET请求的函数——doCurlGetRequest,具体代码如下:

  使用CURL发送POST请求

  可以使用CURL提供的选项CURLOPT_POSTFIELDS,设置该选项为POST字符串数据就可以把请求放在正文中。同样我们实现了一个发送POST请求的函数——doCurlPostRequest,代码如下:

  好了,现在大家应该清楚如何操作了吧,如果还是存在问题的话可以咨询留言。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

收起阅读 »

APP不适配iphoneX【解决方法】

iphonex

背景:
上个月打包好的app,在苹果商城上架被拒。原因:app不适配iphoneX。
因为iphoneX去除Home按键指示器,审核时底部样式缺失,该app不适配iphonex(ps:在查找了相关资料处理后,又重新打包审核,目前app上架中)。

解决方法:
manifest.json配置文件 ----> ‘代码视图’ ----> 'plus'下添加代码(添加安全区域):
"safearea":{
"background":"#fff",
"bottom":{
"offset":"auto"
}
},

保存后,重新打包审核即可。

继续阅读 »

背景:
上个月打包好的app,在苹果商城上架被拒。原因:app不适配iphoneX。
因为iphoneX去除Home按键指示器,审核时底部样式缺失,该app不适配iphonex(ps:在查找了相关资料处理后,又重新打包审核,目前app上架中)。

解决方法:
manifest.json配置文件 ----> ‘代码视图’ ----> 'plus'下添加代码(添加安全区域):
"safearea":{
"background":"#fff",
"bottom":{
"offset":"auto"
}
},

保存后,重新打包审核即可。

收起阅读 »

双标题,如何禁用原生标题栏【解决方法】

原生标题 wap2app

说明:
首先说明,官方建议隐藏HTML的头header,而不是隐藏wap2app的原生头。
因为wap2app的原生头渲染更快,页面加载时不会出现整屏白屏的情况。

情景:
但是wap站的header中已存在相关的逻辑,功能全部移到原生标题栏上很是麻烦。因此,我们为了解决双标题问题,需要禁止原生标题栏。

如何隐藏?
sitemap.json如下:
{
"global": {
"webviewParameter": {
"titleNView": false, //禁用原生标题栏
"statusbar": {
//系统状态栏样式(前景色)
"style": "dark",
"background": "#F7F7F7"
},
"appendCss": "",
"appendJs": ""
},
"easyConfig": {
"quit":{
"toast":{
"showFeedback": false
}
},
"open": {
"animation": {//窗口切换动画配置 参考文档 【http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/12750】 -> open.animation
"type": "pop-in", //窗口动画类型 默认为 slide-in-right
"duration": 300
}
}
}
},
"pages": [
{
"webviewId": "W2Ahello.wap2app.dcloud.io",//首页
"matchUrls": [
{
"href": "http://hello.wap2app.dcloud.io"
}, {
"href": "http://hello.wap2app.dcloud.io"
}
],
"webviewParameter": {
"titleNView": false,
"statusbar": {
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
//若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;
"background": "#f7f7f7"
}
}
},
{//未适配的公共页面,可拦截原生下载和头部导航栏, 注:通配符的规则+放在最后一个节点才能达到适配所有未适配的公共页面效果,适配规则优先级为自上而下查找匹配规则
"webviewId": "common",
"matchUrls": [
{
"hostname": "R:.",
"pathname": "R:.
"
}
],
"webviewParameter": {
"titleNView":false,
"statusbar": {
"style":"dark",
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
"background": "#F7F7F7"
}
},
"easyConfig": {
"quit":{
"toast":{
"showFeedback": false
}
},
"open": {
"animation": {//窗口切换动画配置 参考文档 【http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/12750】 -> open.animation
"type": "pop-in", //窗口动画类型 默认为 slide-in-right
"duration": 300
}
}
}

    }  
]  

}

继续阅读 »

说明:
首先说明,官方建议隐藏HTML的头header,而不是隐藏wap2app的原生头。
因为wap2app的原生头渲染更快,页面加载时不会出现整屏白屏的情况。

情景:
但是wap站的header中已存在相关的逻辑,功能全部移到原生标题栏上很是麻烦。因此,我们为了解决双标题问题,需要禁止原生标题栏。

如何隐藏?
sitemap.json如下:
{
"global": {
"webviewParameter": {
"titleNView": false, //禁用原生标题栏
"statusbar": {
//系统状态栏样式(前景色)
"style": "dark",
"background": "#F7F7F7"
},
"appendCss": "",
"appendJs": ""
},
"easyConfig": {
"quit":{
"toast":{
"showFeedback": false
}
},
"open": {
"animation": {//窗口切换动画配置 参考文档 【http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/12750】 -> open.animation
"type": "pop-in", //窗口动画类型 默认为 slide-in-right
"duration": 300
}
}
}
},
"pages": [
{
"webviewId": "W2Ahello.wap2app.dcloud.io",//首页
"matchUrls": [
{
"href": "http://hello.wap2app.dcloud.io"
}, {
"href": "http://hello.wap2app.dcloud.io"
}
],
"webviewParameter": {
"titleNView": false,
"statusbar": {
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
//若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;
"background": "#f7f7f7"
}
}
},
{//未适配的公共页面,可拦截原生下载和头部导航栏, 注:通配符的规则+放在最后一个节点才能达到适配所有未适配的公共页面效果,适配规则优先级为自上而下查找匹配规则
"webviewId": "common",
"matchUrls": [
{
"hostname": "R:.",
"pathname": "R:.
"
}
],
"webviewParameter": {
"titleNView":false,
"statusbar": {
"style":"dark",
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
"background": "#F7F7F7"
}
},
"easyConfig": {
"quit":{
"toast":{
"showFeedback": false
}
},
"open": {
"animation": {//窗口切换动画配置 参考文档 【http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/12750】 -> open.animation
"type": "pop-in", //窗口动画类型 默认为 slide-in-right
"duration": 300
}
}
}

    }  
]  

}

收起阅读 »

侃一侃WebSocket

WEBSOCKET

今天不讲太多具体的技术,随便侃一侃websocket,想到哪说哪。

uniapp websocket体验demo:https://ext.dcloud.net.cn/plugin?id=1334

和comet相比
相比comet技术,websocket不仅节约了header的问题(websocket的head信息只有短短的2个字节)。更加重要的是是通信的稳定性,comet在遇到网络问题之后,想要在不刷新页面的情况下恢复通信,非常困难,而websocket中提供了onclose函数来处理断开网络后的情况,这为我们与服务器的通信提供了可靠的保障。在、github上有一个js库
(https://github.com/joewalnes/reconnecting-websocket)就是通过这种方式来处理websocket断网重连。
当然这么好用的websocket也不是没有它的问题,websocket目前来看最大的问题是浏览器的支持(幸好大部分的服务器软件在比较新的版本中都已经支持了websocket),ie直到10才开始支持这种协议,而且每个浏览器最近在升级浏览器的时候,都会对websocket做出细微的调整。而且,想象你打开一个页面,当这个页面打开websocket连接并且执行一个内部IP地址的端口扫描,如果端口扫描发现了内部网络上发现了一个开启的80端口,一个隧道就可能通过你的浏览器建立。这样做很可能最终绕过防火墙,并且允许访问内部内容。所以安全问题,也是websocket现在面临的一大隐患。
WebSocket是HTML5出的协议,也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)。
首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP请求合并为一个,但是 Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充。有交集,但是并不是全部。
另外Html5是指的一系列新的API,或者说新规范,新技术。Http协议本身只有1.0和1.1,而且跟Html本身没有直接关系。通俗来说,你可以用HTTP协议传输非Html数据,就是这样。再简单来说,层级不一样。
WebSocket的协议是持久化的,而HTTP是非持久化的协议。
今天说到这里,关于WebSocket的下次我们接着聊。www.goeasy.io 这家是专门做WebSocket的,有兴趣可以关注一下。

继续阅读 »

今天不讲太多具体的技术,随便侃一侃websocket,想到哪说哪。

uniapp websocket体验demo:https://ext.dcloud.net.cn/plugin?id=1334

和comet相比
相比comet技术,websocket不仅节约了header的问题(websocket的head信息只有短短的2个字节)。更加重要的是是通信的稳定性,comet在遇到网络问题之后,想要在不刷新页面的情况下恢复通信,非常困难,而websocket中提供了onclose函数来处理断开网络后的情况,这为我们与服务器的通信提供了可靠的保障。在、github上有一个js库
(https://github.com/joewalnes/reconnecting-websocket)就是通过这种方式来处理websocket断网重连。
当然这么好用的websocket也不是没有它的问题,websocket目前来看最大的问题是浏览器的支持(幸好大部分的服务器软件在比较新的版本中都已经支持了websocket),ie直到10才开始支持这种协议,而且每个浏览器最近在升级浏览器的时候,都会对websocket做出细微的调整。而且,想象你打开一个页面,当这个页面打开websocket连接并且执行一个内部IP地址的端口扫描,如果端口扫描发现了内部网络上发现了一个开启的80端口,一个隧道就可能通过你的浏览器建立。这样做很可能最终绕过防火墙,并且允许访问内部内容。所以安全问题,也是websocket现在面临的一大隐患。
WebSocket是HTML5出的协议,也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)。
首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP请求合并为一个,但是 Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充。有交集,但是并不是全部。
另外Html5是指的一系列新的API,或者说新规范,新技术。Http协议本身只有1.0和1.1,而且跟Html本身没有直接关系。通俗来说,你可以用HTTP协议传输非Html数据,就是这样。再简单来说,层级不一样。
WebSocket的协议是持久化的,而HTTP是非持久化的协议。
今天说到这里,关于WebSocket的下次我们接着聊。www.goeasy.io 这家是专门做WebSocket的,有兴趣可以关注一下。

收起阅读 »

实力解决微信支付问题~

微信支付

关于微信支付的时候,一直提示-1的问题,我也是整理了半天,才弄出来个原因,

首先,准备工作要做好,要保证:
1、menifest.json中配置了微信的appid
2、服务端请求prepareid正确返回;
3、服务端返回数据格式与官方一致:
4、android版云打包,数字签名,与微信开放平台配置一致(不会的用百度);
这四个要保证

一、确保APP端代码没有问题
先保证用官方的基座然后模拟器测试,可以正常调起微信支付,这一点是为了保证APP里面的代码是正常的,
因为微信支付不能真机调试,而且我用自定义基座也不能正常更新,不知道是不是BUG
官方文档:支付插件配置
注意:此文章里面,官方中微信接口的链接改成这个:http://demo.dcloud.net.cn/payment/wxpayv3.HBuilder/?total=

二、将APP端请求的代码改成自己的
如果你是用上面的文档的代码的话,将WXPAYSERVER的值改成自己的服务器接口链接,然后自己证书打包安装在手机上

然后就是处理服务器端就可以了,此时安利几个工具:Fiddler(抓包)、PostMan(模拟请求)以及一款可以内网穿透的工具(如Ngrok)
有了上面三个工具,可以开心愉快的测试了

三、服务器端处理
我用的是TP5,但是其他的也一样,使用的是微信的SDK;
这一点,咱官方也是有一个github文档微信支付示例
关于这一点,如果你只按上面的文档来的话,你不会成功的,因为微信支付有两个点:1、先生成prepareid(预订单),2、根据prepareid再进行一次签名才可以返回给app!
1、生成预订单:
使用微信的SDK,要在config中配置四个参数:APPID、MCHID、KEY、APPSECRET,四个参数是什么意思在SDK中有,注意,key这个参数在下面也要使用到
我的是这样的:

        $wxOrderData = new \WxPayUnifiedOrder();  
        $wxOrderData->SetOut_trade_no($this->orderNo); //这个换成自己的订单号  
        $wxOrderData->SetTrade_type('APP');//这个参数是固定的,必须是APP  
        $wxOrderData->SetTotal_fee($orderPrice * 100); //这个是支付金额(单位是分)  
        $wxOrderData->SetBody('XXX商城'); //这个自己随意  
        $wxOrderData->SetNotify_url( $backUrl ); //这个回调,这个地址也是你自己的  
        $result = \WxPayApi::unifiedOrder($wxOrderData); //此时$result就是返回的prepareid的信息  
        // 请先确保这里请求成功,成功的话是预订单这个$result ['prepay_id'],然后调用$this->sign($result ['prepay_id']);,返回的数组就是要向app返回的信息
 2、生成签名并返回详细信息  
   之前做过小程序支付,也有这一步,于是就将小程序的代码复制过来了,结果失败,就一直没找到原因,直到我看到微信APP开发文档的时候,有这么一句话:不好意思,刚才去找了一下,,,,找不到了,反正就是签名是由五个参数生成的:timestamp、appid、partnerid、prepayid、noncestr、package,这五个少一个都不行!
    private function sign($prepayid) //$prepayid这个参数就是第1步里面获取的预订单id  
    {  
        $time = (string)time();  
        $rand = md5(time() . mt_rand(0, 1000));  
        $data = [];  
        $data['timestamp'] = $time;  
        $data['appid'] = '这是你的appid';  
        $data['partnerid'] = '这是你的商户号';  
        $data['prepayid'] = $prepayid;  
        $data['noncestr'] = $rand;  
        $data['package'] = 'Sign=WXPay';  //介个是固定的  

        $sign = $this->MakeSign( $data );  

        $data['sign'] = $sign;  
        return $data;  //这个数组就是返回给app的信息  
    }  
    private function ToUrlParams($data)  
    {  
        $buff = "";  
        foreach ($data as $k => $v)  
        {  
            if($k != "sign" && $v != "" && !is_array($v)){  
                $buff .= $k . "=" . $v . "&";  
            }  
        }  

        $buff = trim($buff, "&");  
        return $buff;  
    }  
    private function MakeSign( $data )  
    {  
        //签名步骤一:按字典序排序参数  
        ksort($data);  
        $string = $this->ToUrlParams($data);  
        //签名步骤二:在string后加入KEY  
        $string = $string . "&key=你的key";  //注意,敲黑板了,这里还要加上在config中配置过的key  
        //签名步骤三:MD5加密  
        $string = md5($string);  
        //签名步骤四:所有字符转为大写  
        $result = strtoupper($string);  
        return $result;  
    }

四、对比官方返回的参数,官方返回的参数是下面这样的:

{  
    "appid": "wx0411fa6a39d61297",  
    "noncestr": "9p5hdwtt0jsoYw22",    
    "package": "Sign=WXPay",   
    "partnerid": "1230636401",  
    "prepayid": "wx121809269549694a9dde5a333322923488",  
    "timestamp": 1534068566,  
    "sign": "19174B7A2EE5463007FFFF8298F4538E"  
}
  可以将自己的返回信息和上面的进行对比,发现是一样的,都是7个参数,且参数都一样  
 注:有的时候,第一次拉取成功了,但是并没有支付而是返回了,然后再拉取的时候会报错,因为订单号重复了,这时候有抓包的工具的话,是可以看到prepayid是null,因为预订单是有时效的,这个需要自己在做一下判断。  
 还有一个注意点:plus.payment.request发起支付的时候,接收到的参数是json格式的字符串而不是对象,这点要注意一下,因为我封装了ajax请求,默认将json格式转为对象,所以在用的时候要将参数再转为字符串  

以上是我自己的经验,有啥问题大家都可以分享一下。

继续阅读 »

关于微信支付的时候,一直提示-1的问题,我也是整理了半天,才弄出来个原因,

首先,准备工作要做好,要保证:
1、menifest.json中配置了微信的appid
2、服务端请求prepareid正确返回;
3、服务端返回数据格式与官方一致:
4、android版云打包,数字签名,与微信开放平台配置一致(不会的用百度);
这四个要保证

一、确保APP端代码没有问题
先保证用官方的基座然后模拟器测试,可以正常调起微信支付,这一点是为了保证APP里面的代码是正常的,
因为微信支付不能真机调试,而且我用自定义基座也不能正常更新,不知道是不是BUG
官方文档:支付插件配置
注意:此文章里面,官方中微信接口的链接改成这个:http://demo.dcloud.net.cn/payment/wxpayv3.HBuilder/?total=

二、将APP端请求的代码改成自己的
如果你是用上面的文档的代码的话,将WXPAYSERVER的值改成自己的服务器接口链接,然后自己证书打包安装在手机上

然后就是处理服务器端就可以了,此时安利几个工具:Fiddler(抓包)、PostMan(模拟请求)以及一款可以内网穿透的工具(如Ngrok)
有了上面三个工具,可以开心愉快的测试了

三、服务器端处理
我用的是TP5,但是其他的也一样,使用的是微信的SDK;
这一点,咱官方也是有一个github文档微信支付示例
关于这一点,如果你只按上面的文档来的话,你不会成功的,因为微信支付有两个点:1、先生成prepareid(预订单),2、根据prepareid再进行一次签名才可以返回给app!
1、生成预订单:
使用微信的SDK,要在config中配置四个参数:APPID、MCHID、KEY、APPSECRET,四个参数是什么意思在SDK中有,注意,key这个参数在下面也要使用到
我的是这样的:

        $wxOrderData = new \WxPayUnifiedOrder();  
        $wxOrderData->SetOut_trade_no($this->orderNo); //这个换成自己的订单号  
        $wxOrderData->SetTrade_type('APP');//这个参数是固定的,必须是APP  
        $wxOrderData->SetTotal_fee($orderPrice * 100); //这个是支付金额(单位是分)  
        $wxOrderData->SetBody('XXX商城'); //这个自己随意  
        $wxOrderData->SetNotify_url( $backUrl ); //这个回调,这个地址也是你自己的  
        $result = \WxPayApi::unifiedOrder($wxOrderData); //此时$result就是返回的prepareid的信息  
        // 请先确保这里请求成功,成功的话是预订单这个$result ['prepay_id'],然后调用$this->sign($result ['prepay_id']);,返回的数组就是要向app返回的信息
 2、生成签名并返回详细信息  
   之前做过小程序支付,也有这一步,于是就将小程序的代码复制过来了,结果失败,就一直没找到原因,直到我看到微信APP开发文档的时候,有这么一句话:不好意思,刚才去找了一下,,,,找不到了,反正就是签名是由五个参数生成的:timestamp、appid、partnerid、prepayid、noncestr、package,这五个少一个都不行!
    private function sign($prepayid) //$prepayid这个参数就是第1步里面获取的预订单id  
    {  
        $time = (string)time();  
        $rand = md5(time() . mt_rand(0, 1000));  
        $data = [];  
        $data['timestamp'] = $time;  
        $data['appid'] = '这是你的appid';  
        $data['partnerid'] = '这是你的商户号';  
        $data['prepayid'] = $prepayid;  
        $data['noncestr'] = $rand;  
        $data['package'] = 'Sign=WXPay';  //介个是固定的  

        $sign = $this->MakeSign( $data );  

        $data['sign'] = $sign;  
        return $data;  //这个数组就是返回给app的信息  
    }  
    private function ToUrlParams($data)  
    {  
        $buff = "";  
        foreach ($data as $k => $v)  
        {  
            if($k != "sign" && $v != "" && !is_array($v)){  
                $buff .= $k . "=" . $v . "&";  
            }  
        }  

        $buff = trim($buff, "&");  
        return $buff;  
    }  
    private function MakeSign( $data )  
    {  
        //签名步骤一:按字典序排序参数  
        ksort($data);  
        $string = $this->ToUrlParams($data);  
        //签名步骤二:在string后加入KEY  
        $string = $string . "&key=你的key";  //注意,敲黑板了,这里还要加上在config中配置过的key  
        //签名步骤三:MD5加密  
        $string = md5($string);  
        //签名步骤四:所有字符转为大写  
        $result = strtoupper($string);  
        return $result;  
    }

四、对比官方返回的参数,官方返回的参数是下面这样的:

{  
    "appid": "wx0411fa6a39d61297",  
    "noncestr": "9p5hdwtt0jsoYw22",    
    "package": "Sign=WXPay",   
    "partnerid": "1230636401",  
    "prepayid": "wx121809269549694a9dde5a333322923488",  
    "timestamp": 1534068566,  
    "sign": "19174B7A2EE5463007FFFF8298F4538E"  
}
  可以将自己的返回信息和上面的进行对比,发现是一样的,都是7个参数,且参数都一样  
 注:有的时候,第一次拉取成功了,但是并没有支付而是返回了,然后再拉取的时候会报错,因为订单号重复了,这时候有抓包的工具的话,是可以看到prepayid是null,因为预订单是有时效的,这个需要自己在做一下判断。  
 还有一个注意点:plus.payment.request发起支付的时候,接收到的参数是json格式的字符串而不是对象,这点要注意一下,因为我封装了ajax请求,默认将json格式转为对象,所以在用的时候要将参数再转为字符串  

以上是我自己的经验,有啥问题大家都可以分享一下。

收起阅读 »

PHP编程之收入支出明细表实现技术

PHP

  账户金额明细表是统计用户所花的每笔金额和用户所在这个系统所赚的每笔金额,通俗的讲也就是收入和支出。但是很多编程技术人员在刚开始的时候,不知道如何去实现,往往或出现有收入记录却无支出记录,或者是相反的情况,所以对于这个问题,下面专业的郑州app开发公司燚轩科技就来为大家分析讲解一下。

  1、客户所在本系统消费的金额所产生的提成,写入本记录表中。php代码如下:
if(I('pay_state')==2 && I('state')==3){
$money=$info['money']/100;
$uid=$info['uid'];
$update['authe_uid']=$info['uid'];
$user=M('user');
$list=$user->where("uid=$uid")->find();
$sale_uid=$list['sale_uid'];
$update['sale_uid']=$list['sale_uid'];
$bili=M('sys')->where("id=1")->find();
$bi=$bili['sale_rate']/100;
$put_money=$money$bi/100;
$update['money']=$put_money
100;
$update['real_money']=$put_money100;
$update['time']=time();
$update['state']=1;
$update['type']=2;
$sale_user=M('sale_user');
$sale=$sale_user->where("sale_uid=$sale_uid")->find();
$up['tal_money']=$sale['tal_money']+$put_money
100;
$sale_user->where("sale_uid=$sale_uid")->save($up); }
  2、平台给销售代理定时发放的金额,写入本记录表中。php代码如下:
public function dopay_money(){
if(I("bank_card")==''){
error("打款账号不能为空");die;
}
if(I("money_num")==''){
error("打款单号不能为空");die;
}
if(I("money")==''){
error("打款金额不能为空");die;
}
if(I("money")>I("tal_money")){
error("账户总金额不足");die;
}
$bank_card=I("bank_card");
$money_num=I("money_num");
$money=I("money");
$sale_uid=I("sale_uid");
$info=M("sys")->where("id=1")->find();
$min_money=$info['min_money']/100;
if($money<$min_money){
error("打款金额最低为".$min_money."元");
}
$sale_user=M("sale_user");
$moneyb=M("money");
$userinfo=$sale_user->where("sale_uid=$sale_uid")->find();
$data['tal_money']=$userinfo['tal_money']-$money*100;

if($sale_user->where("sale_uid=$sale_uid")->save($data)){  
  $da['sale_uid']=$sale_uid;  
  $da['money']=$money*100;  
  $da['real_money']=$money*100;  
  $da['time']=time();  
  $da['state']=2;  
  $da['type']=1;  
  $da['bank_card']=$bank_card;  
  $da['money_num']=$money_num;  
  if($moneyb->add($da)){  
    success("成功",U("Oasys/sale"));  
  }else{  
    error("失败");  
  }  
}  

}
  好了,看到这里相信大家都知道该如何去做了,那么如果大家还是存在一些细节问题的话,可以留言咨询,我们看到后会第一时间回复。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

继续阅读 »

  账户金额明细表是统计用户所花的每笔金额和用户所在这个系统所赚的每笔金额,通俗的讲也就是收入和支出。但是很多编程技术人员在刚开始的时候,不知道如何去实现,往往或出现有收入记录却无支出记录,或者是相反的情况,所以对于这个问题,下面专业的郑州app开发公司燚轩科技就来为大家分析讲解一下。

  1、客户所在本系统消费的金额所产生的提成,写入本记录表中。php代码如下:
if(I('pay_state')==2 && I('state')==3){
$money=$info['money']/100;
$uid=$info['uid'];
$update['authe_uid']=$info['uid'];
$user=M('user');
$list=$user->where("uid=$uid")->find();
$sale_uid=$list['sale_uid'];
$update['sale_uid']=$list['sale_uid'];
$bili=M('sys')->where("id=1")->find();
$bi=$bili['sale_rate']/100;
$put_money=$money$bi/100;
$update['money']=$put_money
100;
$update['real_money']=$put_money100;
$update['time']=time();
$update['state']=1;
$update['type']=2;
$sale_user=M('sale_user');
$sale=$sale_user->where("sale_uid=$sale_uid")->find();
$up['tal_money']=$sale['tal_money']+$put_money
100;
$sale_user->where("sale_uid=$sale_uid")->save($up); }
  2、平台给销售代理定时发放的金额,写入本记录表中。php代码如下:
public function dopay_money(){
if(I("bank_card")==''){
error("打款账号不能为空");die;
}
if(I("money_num")==''){
error("打款单号不能为空");die;
}
if(I("money")==''){
error("打款金额不能为空");die;
}
if(I("money")>I("tal_money")){
error("账户总金额不足");die;
}
$bank_card=I("bank_card");
$money_num=I("money_num");
$money=I("money");
$sale_uid=I("sale_uid");
$info=M("sys")->where("id=1")->find();
$min_money=$info['min_money']/100;
if($money<$min_money){
error("打款金额最低为".$min_money."元");
}
$sale_user=M("sale_user");
$moneyb=M("money");
$userinfo=$sale_user->where("sale_uid=$sale_uid")->find();
$data['tal_money']=$userinfo['tal_money']-$money*100;

if($sale_user->where("sale_uid=$sale_uid")->save($data)){  
  $da['sale_uid']=$sale_uid;  
  $da['money']=$money*100;  
  $da['real_money']=$money*100;  
  $da['time']=time();  
  $da['state']=2;  
  $da['type']=1;  
  $da['bank_card']=$bank_card;  
  $da['money_num']=$money_num;  
  if($moneyb->add($da)){  
    success("成功",U("Oasys/sale"));  
  }else{  
    error("失败");  
  }  
}  

}
  好了,看到这里相信大家都知道该如何去做了,那么如果大家还是存在一些细节问题的话,可以留言咨询,我们看到后会第一时间回复。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。

收起阅读 »