HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于IOS缓存本地图片读取显示空白的问题解决办法

uniapp

说一下我的应用场景:
网络加载图片太多,所以考虑使用本地缓存。图片下载到本地后使用本地路径。
用到的接口:

// 检查本地是否已经存储  
plus.io.resolveLocalFileSystemURL  

// 下载文件  
plus.downloader.createDownload  

// 下载失败删除文件  
plus.io.resolveLocalFileSystemURL

存储地址使用:_downloads/xxx.jpg

得到的结果如楼主一样,安卓可以读取本地文件,iOS返回空白。

在群里问了半天,最后群主说建议使用uni的API
尝试方法:

// 下载文件  
uni.downloadFile(OBJECT)  

// 保存文件  
uni.saveFile(OBJECT)

通过这种方法,确实可以显示图片,但是有一个问题,就是无法自定义文件名,
下载的临时路径,文件名是使用时间戳命名的,存储到本地后也只能是这个文件名,如果我们要监测缓存,就需要去维护一个网络图片与本地图片的map关系,而且缓存删除更新,都需要更新这个map文件,相对复杂。

思考:为什么uni.saveFile返回的路径可以显示,是不是ios的相对路径不一样?

通过打印,发现uni.saveFile存储到路径在_doc/目录下,尝试把存储路径从_downloads改为_doc后,发现,问题解决了!
原来如此。

相关文档 相对路径URL

继续阅读 »

说一下我的应用场景:
网络加载图片太多,所以考虑使用本地缓存。图片下载到本地后使用本地路径。
用到的接口:

// 检查本地是否已经存储  
plus.io.resolveLocalFileSystemURL  

// 下载文件  
plus.downloader.createDownload  

// 下载失败删除文件  
plus.io.resolveLocalFileSystemURL

存储地址使用:_downloads/xxx.jpg

得到的结果如楼主一样,安卓可以读取本地文件,iOS返回空白。

在群里问了半天,最后群主说建议使用uni的API
尝试方法:

// 下载文件  
uni.downloadFile(OBJECT)  

// 保存文件  
uni.saveFile(OBJECT)

通过这种方法,确实可以显示图片,但是有一个问题,就是无法自定义文件名,
下载的临时路径,文件名是使用时间戳命名的,存储到本地后也只能是这个文件名,如果我们要监测缓存,就需要去维护一个网络图片与本地图片的map关系,而且缓存删除更新,都需要更新这个map文件,相对复杂。

思考:为什么uni.saveFile返回的路径可以显示,是不是ios的相对路径不一样?

通过打印,发现uni.saveFile存储到路径在_doc/目录下,尝试把存储路径从_downloads改为_doc后,发现,问题解决了!
原来如此。

相关文档 相对路径URL

收起阅读 »

Koa nuxt最佳实践前篇

微信小程序 小程序 nodejs node.js

从demo快速上手

首先我们下载demo

git clone https://github.com/doodooke/doodoo-nuxt-demo.git

进入目录安装依赖和启动

yarn install && npm run dev

访问浏览器http://127.0.0.1:3000

继续阅读 »

从demo快速上手

首先我们下载demo

git clone https://github.com/doodooke/doodoo-nuxt-demo.git

进入目录安装依赖和启动

yarn install && npm run dev

访问浏览器http://127.0.0.1:3000

收起阅读 »

tap点击一次出现2次效果的原因

点击事件 重复点击 连续点击

这个原因有几种,网上看了一下基本上都是说应用了2次js文件
但是我都代码应用了一次 还是出现了这个情况
仔细检查了一下发现了这个问题

mui('.mui-content').on('tap', '.ArticleJump', function() {

});

如果代码存在2个mui-conten类 mui-conten包裹了mui-conten 就会出现2次或者多少次点击效果

继续阅读 »

这个原因有几种,网上看了一下基本上都是说应用了2次js文件
但是我都代码应用了一次 还是出现了这个情况
仔细检查了一下发现了这个问题

mui('.mui-content').on('tap', '.ArticleJump', function() {

});

如果代码存在2个mui-conten类 mui-conten包裹了mui-conten 就会出现2次或者多少次点击效果

收起阅读 »

多多客小程序开源版一步安装教程

node.js 微信小程序 小程序

一步安装教程

打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

执行命令

wget https://gitee.com/doodooke/doodoo/raw/master/shell/oneStepInstall.sh && chmod 755 ./oneStepInstall.sh && ./oneStepInstall.sh

1、检测环境

2、自动下载

3、安装依赖

4、系统配置

5、自动启动

继续阅读 »

一步安装教程

打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

执行命令

wget https://gitee.com/doodooke/doodoo/raw/master/shell/oneStepInstall.sh && chmod 755 ./oneStepInstall.sh && ./oneStepInstall.sh

1、检测环境

2、自动下载

3、安装依赖

4、系统配置

5、自动启动

收起阅读 »

多多客小程序开源版8步快速安装教程(图文版)

nodejs node node.js 微信小程序 小程序

1、首先我们打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

2、进入下载的代码目录,打开命令行

3、执行命令安装依赖yarn

4、创建数据库,配置数据库连接

5、执行命令启动项目npm run dev

6、打开浏览器访问http://127.0.0.1:3000,点击开源版下载

7、下载提示完成,执行命令npm run dev重启,打开浏览器访问http://127.0.0.1:3000

8、安装完成,配置.env和.env.web既可以配置完成,系统启动。

继续阅读 »

1、首先我们打开 https://gitee.com/doodooke/doodoo,下载zip压缩包

2、进入下载的代码目录,打开命令行

3、执行命令安装依赖yarn

4、创建数据库,配置数据库连接

5、执行命令启动项目npm run dev

6、打开浏览器访问http://127.0.0.1:3000,点击开源版下载

7、下载提示完成,执行命令npm run dev重启,打开浏览器访问http://127.0.0.1:3000

8、安装完成,配置.env和.env.web既可以配置完成,系统启动。

收起阅读 »

ios离线打包 集成 视频压缩功能

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

第一步
1.在HBuilder-Hello目录下新建compressVideo文件夹,在改文件夹下新建文件SendVideoView.h和SendVideoView.m

2.SendVideoView.h代码

#include "PGPlugin.h"  
#include "PGMethod.h"  

@interface SendVideoView : PGPlugin  
    - (void)compression:(PGMethod*)commands;  
    - (CGFloat)fileSize:(NSURL*)path;  
    -(NSString *)getNowTimeTimestamp;  
@end  

3.SendVideoView.m代码

#import "SendVideoView.h"  
#import <AssetsLibrary/AssetsLibrary.h>  
#import <AVFoundation/AVFoundation.h>  

@implementation SendVideoView  
-(NSString *)getNowTimeTimestamp{  

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

    [formatter setDateStyle:NSDateFormatterMediumStyle];  

    [formatter setTimeStyle:NSDateFormatterShortStyle];  

    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

    //设置时区,这个对于时间的处理有时很重要  

    NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

    [formatter setTimeZone:timeZone];  

    NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

    NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

    return timeSp;  

}  
//计算压缩大小  
- (CGFloat)fileSize:(NSURL*)path  
{  
    return [[NSData dataWithContentsOfURL:path] length]/1024.00 /1024.00;  
}  
//压缩  
- (void)compression:(PGMethod*)commands  
{  
    NSString* parameter0 = [commands.arguments objectAtIndex:0];  
    NSLog(@"parameter=%@",parameter0);  
    NSString* callFunc = [commands.arguments objectAtIndex:1];  
    NSURL * url = [NSURL URLWithString:parameter0];  
     NSLog(@"第一个参数=%@",parameter0);  
      NSLog(@"压缩前大小 %f MB",[self fileSize:url]);  
    //    创建AVAsset对象  
    AVAsset* asset = [AVAsset assetWithURL:url];  
    /*   创建AVAssetExportSession对象  
     压缩的质量  
     AVAssetExportPresetLowQuality   最low的画质最好不要选择实在是看不清楚  
     AVAssetExportPresetMediumQuality  使用到压缩的话都说用这个  
     AVAssetExportPresetHighestQuality  最清晰的画质  

     */  
    AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];  
    //优化网络  
    session.shouldOptimizeForNetworkUse = YES;  
    //转换后的格式  

    //拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密  

    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];  
    //判断文件是否存在,如果已经存在删除  
    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];  
    //设置输出路径  
    session.outputURL = [NSURL fileURLWithPath:path];  

    //设置输出类型  这里可以更改输出的类型 具体可以看文档描述  
    session.outputFileType = AVFileTypeMPEG4;  

    [session exportAsynchronouslyWithCompletionHandler:^{  
        NSLog(@"%@",[NSThread currentThread]);  

        //压缩完成  

        if (session.status==AVAssetExportSessionStatusCompleted) {  
            //在主线程中刷新UI界面,弹出控制器通知用户压缩完成  
            dispatch_async(dispatch_get_main_queue(), ^{  
                NSString* pResultString = [@"file://" stringByAppendingPathComponent:path];  
                NSLog(@"path=%@",path);  
                PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString:pResultString];  
                [self toCallback:callFunc withReslut:[result toJSONString]];  
                NSFileManager* fileManager=[NSFileManager defaultManager];  
                // 删除沙盒中的视频  
                BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[parameter0 substringFromIndex:7]];  
                if(blHave){  
                    BOOL blDele= [fileManager removeItemAtPath:[parameter0 substringFromIndex:7] error:nil];  
                }  
                // 以下调试时开起  
//                NSLog(@"导出完成");  
//                NSLog(@"压缩完毕,压缩后大小 %f MB",[self fileSize:session.outputURL]);  
            });  

        }  

    }];     

}  

@end

第二步
1.打开PandoraApi.bundle下的feature.plist文件

  1. feature.plist文件里加入
    <key>compressVideo</key>
    <dict>
    <key>class</key>
    <string>SendVideoView</string>
    <key>global</key>
    <true/>
    <key>autostart</key>
    <string>YES</string>
    </dict>

第三步
在html 页面 用JS通过 Native.js,调用原生类
var _BARCODE = 'compressVideo'
var B = window.plus.bridge
var compressVideo = {

compression: function (path, successCallback) {  
  var success = typeof successCallback !== 'function' ? null : function (args) {  
      successCallback(args)  
    },  
    callbackID = B.callbackId(success, null)  
  return B.exec(_BARCODE, 'compression', [path, callbackID])  
}  

}

window.plus.compressVideo = compressVideo

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)
安卓版的视频压缩,改天有空了再写出来

继续阅读 »

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

第一步
1.在HBuilder-Hello目录下新建compressVideo文件夹,在改文件夹下新建文件SendVideoView.h和SendVideoView.m

2.SendVideoView.h代码

#include "PGPlugin.h"  
#include "PGMethod.h"  

@interface SendVideoView : PGPlugin  
    - (void)compression:(PGMethod*)commands;  
    - (CGFloat)fileSize:(NSURL*)path;  
    -(NSString *)getNowTimeTimestamp;  
@end  

3.SendVideoView.m代码

#import "SendVideoView.h"  
#import <AssetsLibrary/AssetsLibrary.h>  
#import <AVFoundation/AVFoundation.h>  

@implementation SendVideoView  
-(NSString *)getNowTimeTimestamp{  

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

    [formatter setDateStyle:NSDateFormatterMediumStyle];  

    [formatter setTimeStyle:NSDateFormatterShortStyle];  

    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

    //设置时区,这个对于时间的处理有时很重要  

    NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

    [formatter setTimeZone:timeZone];  

    NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

    NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

    return timeSp;  

}  
//计算压缩大小  
- (CGFloat)fileSize:(NSURL*)path  
{  
    return [[NSData dataWithContentsOfURL:path] length]/1024.00 /1024.00;  
}  
//压缩  
- (void)compression:(PGMethod*)commands  
{  
    NSString* parameter0 = [commands.arguments objectAtIndex:0];  
    NSLog(@"parameter=%@",parameter0);  
    NSString* callFunc = [commands.arguments objectAtIndex:1];  
    NSURL * url = [NSURL URLWithString:parameter0];  
     NSLog(@"第一个参数=%@",parameter0);  
      NSLog(@"压缩前大小 %f MB",[self fileSize:url]);  
    //    创建AVAsset对象  
    AVAsset* asset = [AVAsset assetWithURL:url];  
    /*   创建AVAssetExportSession对象  
     压缩的质量  
     AVAssetExportPresetLowQuality   最low的画质最好不要选择实在是看不清楚  
     AVAssetExportPresetMediumQuality  使用到压缩的话都说用这个  
     AVAssetExportPresetHighestQuality  最清晰的画质  

     */  
    AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];  
    //优化网络  
    session.shouldOptimizeForNetworkUse = YES;  
    //转换后的格式  

    //拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密  

    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];  
    //判断文件是否存在,如果已经存在删除  
    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];  
    //设置输出路径  
    session.outputURL = [NSURL fileURLWithPath:path];  

    //设置输出类型  这里可以更改输出的类型 具体可以看文档描述  
    session.outputFileType = AVFileTypeMPEG4;  

    [session exportAsynchronouslyWithCompletionHandler:^{  
        NSLog(@"%@",[NSThread currentThread]);  

        //压缩完成  

        if (session.status==AVAssetExportSessionStatusCompleted) {  
            //在主线程中刷新UI界面,弹出控制器通知用户压缩完成  
            dispatch_async(dispatch_get_main_queue(), ^{  
                NSString* pResultString = [@"file://" stringByAppendingPathComponent:path];  
                NSLog(@"path=%@",path);  
                PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString:pResultString];  
                [self toCallback:callFunc withReslut:[result toJSONString]];  
                NSFileManager* fileManager=[NSFileManager defaultManager];  
                // 删除沙盒中的视频  
                BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[parameter0 substringFromIndex:7]];  
                if(blHave){  
                    BOOL blDele= [fileManager removeItemAtPath:[parameter0 substringFromIndex:7] error:nil];  
                }  
                // 以下调试时开起  
//                NSLog(@"导出完成");  
//                NSLog(@"压缩完毕,压缩后大小 %f MB",[self fileSize:session.outputURL]);  
            });  

        }  

    }];     

}  

@end

第二步
1.打开PandoraApi.bundle下的feature.plist文件

  1. feature.plist文件里加入
    <key>compressVideo</key>
    <dict>
    <key>class</key>
    <string>SendVideoView</string>
    <key>global</key>
    <true/>
    <key>autostart</key>
    <string>YES</string>
    </dict>

第三步
在html 页面 用JS通过 Native.js,调用原生类
var _BARCODE = 'compressVideo'
var B = window.plus.bridge
var compressVideo = {

compression: function (path, successCallback) {  
  var success = typeof successCallback !== 'function' ? null : function (args) {  
      successCallback(args)  
    },  
    callbackID = B.callbackId(success, null)  
  return B.exec(_BARCODE, 'compression', [path, callbackID])  
}  

}

window.plus.compressVideo = compressVideo

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)
安卓版的视频压缩,改天有空了再写出来

收起阅读 »

IOS离线打包集成 阿里云 短视频sdk

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

1.基础版: 只有录制和裁剪功能,

  1. 标准版:可以修改UI
  2. 专业版: 很复杂的功能

可以参考,阿里云SDK说明

阿里云短视频基础版

如何没有离线打包过的,可以参考,官方最新的AS 打包教程:
ios离线打包教程

第一步
先下载ios短视频基础版SDK,详见sdk下载页面
1.开发者打开工程,选中目标target,依次选择”General”->”Embededed Binaries”,点击”+”号,点击“Add Other…”,导入QUCore-ThirdParty.framework和AliyunVideoSDK.framework。
2.同时,还需依赖libz.tbd、libc++.tbd、libiconv.tbd、libresolv.tbd、ImageIO.framework、CoreMedia.framework、CoreVideo.framework、SystemConfiguration.framework、Photos.framework、OpenAL.framework、VideoToolbox.framework请一并加上。截图如下

3.配置 Build Setting -- Build Options -- Enable Bitcode 选项为NO

4.配置 Build Setting -- Linking -- Other Linker Flags 添加 -ObjC选项

第二步
1.在HBuilder-Hello下新建文件夹recoredVideo 并在该文件夹下新建RecordVideo.h和RecordVideo.m文件

2.RecordVideo.h代码

include "PGPlugin.h"

include "PGMethod.h"

import <AliyunVideoSDK/AliyunVideoBase.h>

@interface RecordVideo : PGPlugin

  • (void)record:(PGMethod*)commands;
  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath;
    -(NSString
    )getNowTimeTimestamp;
    @end

3.RecordVideo.m代码

import "RecordVideo.h"

import <AliyunVideoSDK/AliyunVideoSDK.h>

import <AliyunVideoSDK/AliyunVideoRecordParam.h>

import <AliyunVideoSDK/AliyunVideoUIConfig.h>

import <AliyunVideoSDK/AliyunVideoBase.h>

import <AliyunVideoSDK/AliyunVideoCropParam.h>

import <AssetsLibrary/AssetsLibrary.h>

@interface RecordVideo()
@property (nonatomic,strong) NSString *callFunc;
@end

@implementation RecordVideo

  • (void)record:(PGMethod)commands
    {
    AliyunVideoUIConfig
    config = [[AliyunVideoUIConfig alloc] init];
    config.hiddenFlashButton = NO;
    config.imageBundleName = @"QPSDK";
    config.hiddenImportButton = YES;
    [[AliyunVideoBase shared] registerWithAliyunIConfig:config];

    NSString parameter0 = [commands.arguments objectAtIndex:0];
    self.callFunc = [commands.arguments objectAtIndex:1];
    NSData
    data= [parameter0 dataUsingEncoding:NSUTF8StringEncoding];
    NSError error = nil;
    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSDictionary
    dict = (NSDictionary )jsonObject;
    AliyunVideoRecordParam
    quVideo = [[AliyunVideoRecordParam alloc] init];
    quVideo.maxDuration = [[dict objectForKey:@"setMaxDuration"] doubleValue];
    quVideo.minDuration = [[dict objectForKey:@"setMinDuration"] doubleValue];
    quVideo.videoQuality = AliyunVideoQualityHight;
    quVideo.torchMode = AliyunCameraTorchModeOff;
    quVideo.size = AliyunVideoVideoSize540P;
    quVideo.gop = [[dict objectForKey:@"setGop"] intValue];
    quVideo.beautifyStatus = [[dict objectForKey:@"setBeautyStatus"] boolValue];
    quVideo.beautifyValue = [[dict objectForKey:@"setBeautyLevel"] intValue];
    quVideo.position = AliyunCameraPositionBack;
    NSString path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];
    quVideo.outputPath = path;
    UIViewController
    recordViewController = [[AliyunVideoBase shared] createRecordViewControllerWithRecordParam:quVideo];
    [AliyunVideoBase shared].delegate = (id)self;
    [self.rootViewController.navigationController pushViewController:recordViewController animated:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }

  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath {
    NSLog(@"录制完成 %@", videoPath);
    ALAssetsLibrary
    library = [[ALAssetsLibrary alloc] init];
    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:videoPath]
    completionBlock:^(NSURL assetURL, NSError error) {
    NSString path = [@"file://" stringByAppendingPathComponent:videoPath];
    NSDictionary
    dict = [NSDictionary dictionaryWithObjectsAndKeys:@"000000",@"code",path,@"path",nil];
    PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsDictionary:dict];
    [self toCallback:self.callFunc withReslut:[result toJSONString]];
    dispatch_async(dispatch_get_main_queue(), ^{
    [recordVC.navigationController popViewControllerAnimated:YES];
    });
    }];
    }

-(void)videoBaseRecordVideoExit {
NSLog(@"退出录制");
[self.rootViewController.navigationController popViewControllerAnimated:YES];
}

-(NSString *)getNowTimeTimestamp{

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

[formatter setDateStyle:NSDateFormatterMediumStyle];  

[formatter setTimeStyle:NSDateFormatterShortStyle];  

[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

//设置时区,这个对于时间的处理有时很重要  

NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

[formatter setTimeZone:timeZone];  

NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

return timeSp;  

}
@end

第三步
1.打开PandoraApi.bundle下的feature.plist文件

2.feature.plist文件里加入
<key>RecordVideo</key>
<dict>
<key>class</key>
<string>RecordVideo</string>
<key>global</key>
<true/>
<key>autostart</key>
<string>YES</string>
</dict>

然后在html 页面 用JS通过 Native.js,调用原生类
var RecordVideoIos = function (options) {
this.options = this.extend(
{
setResolutionMode: '540p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 80, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'NO', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}, options)
this.init()
}

RecordVideoIos.prototype = {
init: function () {
this.event()
},
event: function () {
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k]
}
return obj
},
open: function (fn) {
let B = window.plus.bridge
let success = typeof fn !== 'function' ? null : function (args) {
fn(args)
}
let callbackID = B.callbackId(success, null)
return B.exec('RecordVideo', 'record', [JSON.stringify(this.options), callbackID])
}
}

const option = {
setResolutionMode: '720p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 60, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'OFF', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}

var recordVideoIos = new RecordVideoIos(option)
if (plus.os.name != 'Android') {
window.plus.recordVideo = recordVideoIos
}

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)

继续阅读 »

要想实现更多功能 适应更多应用场景 肯定是要选择离线打包的

1.基础版: 只有录制和裁剪功能,

  1. 标准版:可以修改UI
  2. 专业版: 很复杂的功能

可以参考,阿里云SDK说明

阿里云短视频基础版

如何没有离线打包过的,可以参考,官方最新的AS 打包教程:
ios离线打包教程

第一步
先下载ios短视频基础版SDK,详见sdk下载页面
1.开发者打开工程,选中目标target,依次选择”General”->”Embededed Binaries”,点击”+”号,点击“Add Other…”,导入QUCore-ThirdParty.framework和AliyunVideoSDK.framework。
2.同时,还需依赖libz.tbd、libc++.tbd、libiconv.tbd、libresolv.tbd、ImageIO.framework、CoreMedia.framework、CoreVideo.framework、SystemConfiguration.framework、Photos.framework、OpenAL.framework、VideoToolbox.framework请一并加上。截图如下

3.配置 Build Setting -- Build Options -- Enable Bitcode 选项为NO

4.配置 Build Setting -- Linking -- Other Linker Flags 添加 -ObjC选项

第二步
1.在HBuilder-Hello下新建文件夹recoredVideo 并在该文件夹下新建RecordVideo.h和RecordVideo.m文件

2.RecordVideo.h代码

include "PGPlugin.h"

include "PGMethod.h"

import <AliyunVideoSDK/AliyunVideoBase.h>

@interface RecordVideo : PGPlugin

  • (void)record:(PGMethod*)commands;
  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath;
    -(NSString
    )getNowTimeTimestamp;
    @end

3.RecordVideo.m代码

import "RecordVideo.h"

import <AliyunVideoSDK/AliyunVideoSDK.h>

import <AliyunVideoSDK/AliyunVideoRecordParam.h>

import <AliyunVideoSDK/AliyunVideoUIConfig.h>

import <AliyunVideoSDK/AliyunVideoBase.h>

import <AliyunVideoSDK/AliyunVideoCropParam.h>

import <AssetsLibrary/AssetsLibrary.h>

@interface RecordVideo()
@property (nonatomic,strong) NSString *callFunc;
@end

@implementation RecordVideo

  • (void)record:(PGMethod)commands
    {
    AliyunVideoUIConfig
    config = [[AliyunVideoUIConfig alloc] init];
    config.hiddenFlashButton = NO;
    config.imageBundleName = @"QPSDK";
    config.hiddenImportButton = YES;
    [[AliyunVideoBase shared] registerWithAliyunIConfig:config];

    NSString parameter0 = [commands.arguments objectAtIndex:0];
    self.callFunc = [commands.arguments objectAtIndex:1];
    NSData
    data= [parameter0 dataUsingEncoding:NSUTF8StringEncoding];
    NSError error = nil;
    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSDictionary
    dict = (NSDictionary )jsonObject;
    AliyunVideoRecordParam
    quVideo = [[AliyunVideoRecordParam alloc] init];
    quVideo.maxDuration = [[dict objectForKey:@"setMaxDuration"] doubleValue];
    quVideo.minDuration = [[dict objectForKey:@"setMinDuration"] doubleValue];
    quVideo.videoQuality = AliyunVideoQualityHight;
    quVideo.torchMode = AliyunCameraTorchModeOff;
    quVideo.size = AliyunVideoVideoSize540P;
    quVideo.gop = [[dict objectForKey:@"setGop"] intValue];
    quVideo.beautifyStatus = [[dict objectForKey:@"setBeautyStatus"] boolValue];
    quVideo.beautifyValue = [[dict objectForKey:@"setBeautyLevel"] intValue];
    quVideo.position = AliyunCameraPositionBack;
    NSString path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[self getNowTimeTimestamp] stringByAppendingString: @".mp4"]];
    quVideo.outputPath = path;
    UIViewController
    recordViewController = [[AliyunVideoBase shared] createRecordViewControllerWithRecordParam:quVideo];
    [AliyunVideoBase shared].delegate = (id)self;
    [self.rootViewController.navigationController pushViewController:recordViewController animated:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }

  • (void)videoBase:(AliyunVideoBase )base recordCompeleteWithRecordViewController:(UIViewController )recordVC videoPath:(NSString )videoPath {
    NSLog(@"录制完成 %@", videoPath);
    ALAssetsLibrary
    library = [[ALAssetsLibrary alloc] init];
    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:videoPath]
    completionBlock:^(NSURL assetURL, NSError error) {
    NSString path = [@"file://" stringByAppendingPathComponent:videoPath];
    NSDictionary
    dict = [NSDictionary dictionaryWithObjectsAndKeys:@"000000",@"code",path,@"path",nil];
    PDRPluginResult *result = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsDictionary:dict];
    [self toCallback:self.callFunc withReslut:[result toJSONString]];
    dispatch_async(dispatch_get_main_queue(), ^{
    [recordVC.navigationController popViewControllerAnimated:YES];
    });
    }];
    }

-(void)videoBaseRecordVideoExit {
NSLog(@"退出录制");
[self.rootViewController.navigationController popViewControllerAnimated:YES];
}

-(NSString *)getNowTimeTimestamp{

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;  

[formatter setDateStyle:NSDateFormatterMediumStyle];  

[formatter setTimeStyle:NSDateFormatterShortStyle];  

[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ------ ----设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制  

//设置时区,这个对于时间的处理有时很重要  

NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];  

[formatter setTimeZone:timeZone];  

NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式  

NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];  

return timeSp;  

}
@end

第三步
1.打开PandoraApi.bundle下的feature.plist文件

2.feature.plist文件里加入
<key>RecordVideo</key>
<dict>
<key>class</key>
<string>RecordVideo</string>
<key>global</key>
<true/>
<key>autostart</key>
<string>YES</string>
</dict>

然后在html 页面 用JS通过 Native.js,调用原生类
var RecordVideoIos = function (options) {
this.options = this.extend(
{
setResolutionMode: '540p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 80, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'NO', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}, options)
this.init()
}

RecordVideoIos.prototype = {
init: function () {
this.event()
},
event: function () {
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k]
}
return obj
},
open: function (fn) {
let B = window.plus.bridge
let success = typeof fn !== 'function' ? null : function (args) {
fn(args)
}
let callbackID = B.callbackId(success, null)
return B.exec('RecordVideo', 'record', [JSON.stringify(this.options), callbackID])
}
}

const option = {
setResolutionMode: '720p', // 录制 设置录制分辨率,目前支持360p,480p,540p,720p
setRatioMode: '1/1', // 录制 设置视频比例,目前支持1/1 ,3/4, 9/16
setRecordMode: 'AUTO', // 录制 设置录制模式,目前支持按录:PRESS,点录:TOUCH和混合模式:AUTO
setBeautyLevel: 60, // 录制 设置美颜度,1-100,比率
setBeautyStatus: true, // 录制 设置美颜开关
setCameraType: 'BACK', // 录制 设置前后置摄像头, 后:BACK ,前:FRONT
setFlashType: 'OFF', // 录制 设置闪光灯模式,开:NO, 关:OFF, 自动:AUTO
setNeedClip: true, // 录制 设置是否需要支持片段录制
setMaxDuration: 15, // 录制 设置最大录制时长 单位秒
setMinDuration: 2, // 录制 设置最小录制时长 单位秒
setVideoQuality: 'HD', // 录制设置视频质量 4个级别, 低:LD ,中:SD ,高:HD ,极高:SSD
setGop: 125, // 设置关键帧间隔,建议:1-300之间
setMinVideoDuration: 5, // 裁剪 设置过滤的视频最小长度 单位秒
setMaxVideoDuration: 15, // 裁剪 设置过滤的视频最大长度 单位秒
setMinCropDuration: 2, // 裁剪 设置视频最小裁剪时间 单位毫秒
setFrameRate: 25, // 裁剪 设置帧率
setNeedRecord: false, // 设置是否需要开放录制入口,即选择视频的页面,多出一个录制按钮
setResulutionMode: '540p', // 设置裁剪分辨率,目前支持360p,480p,540p,720p
setCropMode: 'cpu' // 设置裁剪方式,是否使用gpu进行裁剪,不设置则默认使用cpu来裁剪
}

var recordVideoIos = new RecordVideoIos(option)
if (plus.os.name != 'Android') {
window.plus.recordVideo = recordVideoIos
}

就这么多了,不懂的可以加群864017187(dcloud混合开发交流群)

收起阅读 »

打开文件(ctrl+o)最好默认打开当前文件目录

打开文件(ctrl+o)最好默认打开当前文件目录, 这样特方便

打开文件(ctrl+o)最好默认打开当前文件目录, 这样特方便

GraceUI6.0 正式发布

uniapp graceUI

2022年06月13日 GraceUI 6.0 版本正式发布

GraceUI 是一款成熟完善的、为uni-app量身打造的优秀的UI框架!经过近4年的维护已经成为组件多、界面丰富、运行稳定的 uni-app 专业UI框架 !
GraceUI 第一版发布于2018年9月,4年多来我们一直坚持收集反馈,高效、高频更新!从1.0到6.0 GraceUI 已经变得更加丰富、兼容性更好~
在此也感谢近万名使用者的一路相伴,感谢你们的支持与反馈~
官网 : https://www.graceui.com/

1. 丰富的组件及样式

GraceUI 的组件、样式、布局、界面非常丰富,总量 150+!您可以使用他们快速的完成应用页面的布局~

1.1 基础布局组件及样式

页面布局 · Flex布局 · 元素定位 · 文本颜色 · 背景样式 · 阴影效果 · 圆角边框 · 文本样式 · 内置图标 · 样式动画

1.2 常用布局

宫格布局 · 头部导航 · 底部导航 · 切换导航 · 吸顶容器 · 动态吸顶 · 通用列表 · 滑动列表 · 新闻列表 · 评论列表 · 图文卡片 · 名片卡片 · 滚动区域 · 遮罩弹层 · 局部选项卡 · 全屏选项卡 · 分段切换 · 折叠面板 · 普通表格 · 数据表格 · 分类展示 · 横向公告 · 返回顶部 · 弹出菜单 · 功能菜单 · 时间轴 · 侧边抽屉 · 图标分类 · 横向日期

1.3 加载组件

加载组件 · 全屏加载 · 下拉刷新 · 刷新组件 · 上拉加载

1.4 常用组件

徽章组件 · 标签组件 · 滚动公告 · 无缝滚动 · 按钮组件 · 进度按钮 · 搜索组件 · 星级评价 · 通用标题 · 倒计时 · 轮播组件 · 日历时间 · 区间滑块 · 进度圆环 · 城市选择 · 地区联动 · 步骤提示 · 链接组件 · 优惠券组件 · 为空展示 · 图片选择 · 多图上传 · 头像群组 · 数值动画 · 日期时间选择 · 时间段选择器

1.5 对话框组件

顶部消息框 · 模态对话框 · 底部对话框 · 底部消息框

1.6 表单相关

表单元素 · 表单验证 · 数值框 · 数字键盘 · 可选标签 · 点选按钮 · 下拉选择

1.7 文章相关

文本编辑器 · 编辑器解析 · 富文本加强 · 展开全文

1.8 JS 工具库

时间转换 · 网络请求 · 随机数值 · md5转换 · 系统信息

1.9 常用界面库

搜索界面 · 登录注册 · 个人中心 · 购物车 · 订单中心 · 图片剪裁 · 商品详情 · 图片懒加载 · 骨架加载 · 抽奖活动 · 瀑布流 · 选择问卷 · 地址列表 · 添加地址 · 证件上传 · 滚动推荐 · 短信验证 · 排行榜 · 商城套装 · 即时通讯

2. 强大的版本支持 业界首款成熟的基于uni-app 的 nvue UI 框架

GraceUI 6.0 基于 vue3.0 同时支持 nvue,为app端更流畅的体验提供了极大的便利~
nvue 普通版本基本同步,想优化您的app?添加一个 .nuve 复制 vue 代码即可迅速完成~

3. 更好的兼容性、更稳定

GraceUI 自发布以来已经有上万名使用者,在开发的过程中不断给我们最真实的反馈,我们更是以积极的心态面对每一个反馈,及时确认问题并及时修正(最快10分钟哦)~经过一年多的 "锤炼",GraceUI 变得极度稳定、兼容性极好~ 感谢每一份反馈,感谢每一位支持者~

您不需要费力的去布局,有 GraceUI 就够了 ^_^

4. Grace.JS 化繁为简,只为热爱 ~

Grace.js 是 GraceUI 框架的 js 框架,目标是 " 简化您的 uni-app 及 微信小程序 api 操作,同时提供丰富、好用的 js 工具,大幅度提高您的开发效率" 。

5. 收费说明

GraceUI 6.0 版本售价 299元
收费只是最基本的维护开销,不是"赚钱的买卖",我们更认为是您的一种信任,对于我们更多的是责任!所以这里不是淘宝,不是简单的交易!我们希望得到正向的反馈、正向的帮助,不断完善,最终成为"组件多、稳定性好" 的UI框架!
一次性收费永久免费更新 ~

官网 :

https://www.graceui.com/

继续阅读 »

2022年06月13日 GraceUI 6.0 版本正式发布

GraceUI 是一款成熟完善的、为uni-app量身打造的优秀的UI框架!经过近4年的维护已经成为组件多、界面丰富、运行稳定的 uni-app 专业UI框架 !
GraceUI 第一版发布于2018年9月,4年多来我们一直坚持收集反馈,高效、高频更新!从1.0到6.0 GraceUI 已经变得更加丰富、兼容性更好~
在此也感谢近万名使用者的一路相伴,感谢你们的支持与反馈~
官网 : https://www.graceui.com/

1. 丰富的组件及样式

GraceUI 的组件、样式、布局、界面非常丰富,总量 150+!您可以使用他们快速的完成应用页面的布局~

1.1 基础布局组件及样式

页面布局 · Flex布局 · 元素定位 · 文本颜色 · 背景样式 · 阴影效果 · 圆角边框 · 文本样式 · 内置图标 · 样式动画

1.2 常用布局

宫格布局 · 头部导航 · 底部导航 · 切换导航 · 吸顶容器 · 动态吸顶 · 通用列表 · 滑动列表 · 新闻列表 · 评论列表 · 图文卡片 · 名片卡片 · 滚动区域 · 遮罩弹层 · 局部选项卡 · 全屏选项卡 · 分段切换 · 折叠面板 · 普通表格 · 数据表格 · 分类展示 · 横向公告 · 返回顶部 · 弹出菜单 · 功能菜单 · 时间轴 · 侧边抽屉 · 图标分类 · 横向日期

1.3 加载组件

加载组件 · 全屏加载 · 下拉刷新 · 刷新组件 · 上拉加载

1.4 常用组件

徽章组件 · 标签组件 · 滚动公告 · 无缝滚动 · 按钮组件 · 进度按钮 · 搜索组件 · 星级评价 · 通用标题 · 倒计时 · 轮播组件 · 日历时间 · 区间滑块 · 进度圆环 · 城市选择 · 地区联动 · 步骤提示 · 链接组件 · 优惠券组件 · 为空展示 · 图片选择 · 多图上传 · 头像群组 · 数值动画 · 日期时间选择 · 时间段选择器

1.5 对话框组件

顶部消息框 · 模态对话框 · 底部对话框 · 底部消息框

1.6 表单相关

表单元素 · 表单验证 · 数值框 · 数字键盘 · 可选标签 · 点选按钮 · 下拉选择

1.7 文章相关

文本编辑器 · 编辑器解析 · 富文本加强 · 展开全文

1.8 JS 工具库

时间转换 · 网络请求 · 随机数值 · md5转换 · 系统信息

1.9 常用界面库

搜索界面 · 登录注册 · 个人中心 · 购物车 · 订单中心 · 图片剪裁 · 商品详情 · 图片懒加载 · 骨架加载 · 抽奖活动 · 瀑布流 · 选择问卷 · 地址列表 · 添加地址 · 证件上传 · 滚动推荐 · 短信验证 · 排行榜 · 商城套装 · 即时通讯

2. 强大的版本支持 业界首款成熟的基于uni-app 的 nvue UI 框架

GraceUI 6.0 基于 vue3.0 同时支持 nvue,为app端更流畅的体验提供了极大的便利~
nvue 普通版本基本同步,想优化您的app?添加一个 .nuve 复制 vue 代码即可迅速完成~

3. 更好的兼容性、更稳定

GraceUI 自发布以来已经有上万名使用者,在开发的过程中不断给我们最真实的反馈,我们更是以积极的心态面对每一个反馈,及时确认问题并及时修正(最快10分钟哦)~经过一年多的 "锤炼",GraceUI 变得极度稳定、兼容性极好~ 感谢每一份反馈,感谢每一位支持者~

您不需要费力的去布局,有 GraceUI 就够了 ^_^

4. Grace.JS 化繁为简,只为热爱 ~

Grace.js 是 GraceUI 框架的 js 框架,目标是 " 简化您的 uni-app 及 微信小程序 api 操作,同时提供丰富、好用的 js 工具,大幅度提高您的开发效率" 。

5. 收费说明

GraceUI 6.0 版本售价 299元
收费只是最基本的维护开销,不是"赚钱的买卖",我们更认为是您的一种信任,对于我们更多的是责任!所以这里不是淘宝,不是简单的交易!我们希望得到正向的反馈、正向的帮助,不断完善,最终成为"组件多、稳定性好" 的UI框架!
一次性收费永久免费更新 ~

官网 :

https://www.graceui.com/

收起阅读 »

支付宝接口调用经验分享

支付宝这里,mui + plus+ 的api调用,会遇到很多的问题,下面是实际遇到的一些前提:

  1. 官网demo 给出的服务器 版本是 老版本的 支付宝服务api
  2. 官网给出的git 服务器版本项目中,有新版本,老版本两个版本的api都有
  3. 实际在测试过程中,可能使用的是沙箱账号或者是真实生产账号

最基本的部分我这里就不提了,出现异常的会有这几个部分,也就是你无论如何都找不到什么错误,但他偏偏错了的时候,可以参考下这几个原因:

  1. 如果使用沙箱账号,是无论如何都不会成功的。。我后来考虑应该是 plus.payment.request 这里是调用的正式支付宝的服务器,除非这里也提供一个沙箱服务器调用的版本,否则两者就相当于一个用正式服务器,一个用沙箱服务器,完全两套东西。。。注意: 支付宝的沙箱和正式生产服务器是两个不同的地址
  2. 使用沙箱账号的时候,可能报多种错误: [payment支付宝:62001]用户中途取消支付操作 ;; [payment支付宝:62009]未知错误;
继续阅读 »

支付宝这里,mui + plus+ 的api调用,会遇到很多的问题,下面是实际遇到的一些前提:

  1. 官网demo 给出的服务器 版本是 老版本的 支付宝服务api
  2. 官网给出的git 服务器版本项目中,有新版本,老版本两个版本的api都有
  3. 实际在测试过程中,可能使用的是沙箱账号或者是真实生产账号

最基本的部分我这里就不提了,出现异常的会有这几个部分,也就是你无论如何都找不到什么错误,但他偏偏错了的时候,可以参考下这几个原因:

  1. 如果使用沙箱账号,是无论如何都不会成功的。。我后来考虑应该是 plus.payment.request 这里是调用的正式支付宝的服务器,除非这里也提供一个沙箱服务器调用的版本,否则两者就相当于一个用正式服务器,一个用沙箱服务器,完全两套东西。。。注意: 支付宝的沙箱和正式生产服务器是两个不同的地址
  2. 使用沙箱账号的时候,可能报多种错误: [payment支付宝:62001]用户中途取消支付操作 ;; [payment支付宝:62009]未知错误;
收起阅读 »

高性能手机app前端开发Hello MUI框架模板

hellomui mui

一款高性能手机app前端开发Hello MUI框架模板,MUI不依赖任何第三方JS库,压缩后的JS和CSS文件仅有100+K和60+K。MUI以iOS平台UI为基础,补充部分Android平台特有的UI控件。

下载地址:http://www.sucaihuo.com/templates/3694.html
更多MUI模板:http://www.sucaihuo.com/search.html?keyword=mui&mtype=1

继续阅读 »

一款高性能手机app前端开发Hello MUI框架模板,MUI不依赖任何第三方JS库,压缩后的JS和CSS文件仅有100+K和60+K。MUI以iOS平台UI为基础,补充部分Android平台特有的UI控件。

下载地址:http://www.sucaihuo.com/templates/3694.html
更多MUI模板:http://www.sucaihuo.com/search.html?keyword=mui&mtype=1

收起阅读 »

郑州app制作的常见开发模式都分哪些呢

5 App开发 移动APP

  可以看到,在每一天不管是个人来讲还是单位来讲都有许许多多的郑州app制作和郑州app定制的需求,面对这些大量的制作需求,在现实当中可以采用两种不同的方式来进行制作,不同的方式当然具有不同的特点和优势,下面就来详细的跟大家分析解答一下吧。

  一、找专业开发公司

  如果在实际制作的过程当中,选择了这样的一种制作方式,那么就可以更加的省事了。因为选择这样的一种制作方式专业开发公司会为我们提供一整套的完整的解决方案。这一整套的方案不仅仅包括了前期的市场调查以及用户调研,还包括了手机app的整个设计方案,整个功能的设计分布,如何实现客户的目标功能,而且还包括了手机app制作完成之后的一些后期的推广和宣传工作。

  在进行完了这一系列的工作之后,专业开发公司还会根据他们的工作情况来为计算出一个制作的价格,根据所制作手机app的具体情况,项目的复杂程度,制作的价格会在几十万到几百万不等,不管怎样,选择这种制作方式都是非常的方便快捷的,只需要等待成果的验收情况即可。

  二、团队项目整体承包的方式

  这样的一种方式在目前也是采用得比较多的一种方式,这种方式一般都是设计师与开发工程师来共同合作完成的,采用这样的一种制作方式也会为我们提供一整套的设计解决方案,但是采用这样的一种方式在前期调研和后期的推广方面不会有。一般来说都会按照整体的风格设计报价加上各个功能模块的嵌入整合为一个整体的报价。采用这样的一种方式一般的制作费用大概是在几万到几十万元不等,具体的价格要根据手机app的具体制作难易程度来进行确定。

  一般来说,海外的一些开发者和设计师们他们都更倾向与采用时薪的方法来计算制作的整体费用,但采用这样的一种方式无疑会增加制作的整体成本,因此国内的一些客户们并不喜欢这样的一种计算价格的方式,一般也不会选择这样的方式来计算制作总体价格。
本文由专业的郑州app开发公司燚轩科技整理发布,如需转载请注明出处。

继续阅读 »

  可以看到,在每一天不管是个人来讲还是单位来讲都有许许多多的郑州app制作和郑州app定制的需求,面对这些大量的制作需求,在现实当中可以采用两种不同的方式来进行制作,不同的方式当然具有不同的特点和优势,下面就来详细的跟大家分析解答一下吧。

  一、找专业开发公司

  如果在实际制作的过程当中,选择了这样的一种制作方式,那么就可以更加的省事了。因为选择这样的一种制作方式专业开发公司会为我们提供一整套的完整的解决方案。这一整套的方案不仅仅包括了前期的市场调查以及用户调研,还包括了手机app的整个设计方案,整个功能的设计分布,如何实现客户的目标功能,而且还包括了手机app制作完成之后的一些后期的推广和宣传工作。

  在进行完了这一系列的工作之后,专业开发公司还会根据他们的工作情况来为计算出一个制作的价格,根据所制作手机app的具体情况,项目的复杂程度,制作的价格会在几十万到几百万不等,不管怎样,选择这种制作方式都是非常的方便快捷的,只需要等待成果的验收情况即可。

  二、团队项目整体承包的方式

  这样的一种方式在目前也是采用得比较多的一种方式,这种方式一般都是设计师与开发工程师来共同合作完成的,采用这样的一种制作方式也会为我们提供一整套的设计解决方案,但是采用这样的一种方式在前期调研和后期的推广方面不会有。一般来说都会按照整体的风格设计报价加上各个功能模块的嵌入整合为一个整体的报价。采用这样的一种方式一般的制作费用大概是在几万到几十万元不等,具体的价格要根据手机app的具体制作难易程度来进行确定。

  一般来说,海外的一些开发者和设计师们他们都更倾向与采用时薪的方法来计算制作的整体费用,但采用这样的一种方式无疑会增加制作的整体成本,因此国内的一些客户们并不喜欢这样的一种计算价格的方式,一般也不会选择这样的方式来计算制作总体价格。
本文由专业的郑州app开发公司燚轩科技整理发布,如需转载请注明出处。

收起阅读 »