HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

星援App开发者一审获刑五年,系“蔡徐坤微博转发过亿”幕后推手

法律科普

2018年,“明星蔡徐坤一条微博转发量过亿”事件引发舆论对流量造假的关注。按照当时的微博用户数量,转发量一亿意味着每三个微博用户中就有一人转发了蔡徐坤的微博。人民日报官微评论称:“一亿转发量”,你们也真敢刷。

2019年6月,操纵上述微博刷量事件的幕后推手“星援”APP被查。日前,中国裁判文书网公布了“星援”APP开发者蔡坤苗的判决书,其因提供侵入计算机信息系统程序罪一审获刑五年。

北京市丰台区法院审理查明,2018年1月至2019年3月间,被告人蔡坤苗未获得被害单位北京微梦创科网络技术有限公司授权而自行开发“星援”APP,有偿为他人提供不需要登录新浪微博客户端即可转发微博博文及自动批量转发微博博文的服务。后大量用户以向“星援”APP充值的形式有偿使用该软件,并通过运行上述软件侵入新浪微博服务器。

经鉴定,“星援”APP通过截取新浪微博服务器中对应账号的相关数据,后使用与其截取数据相同的网络数据格式向该服务器提交数据并完成与该服务器的交互,以实现不登录新浪微博客户端即可转发微博博文的功能以及自动批量转发微博博文的功能。经统计,至案发时该软件已有用户使用19万余个控制端微博账号登录,被告人蔡坤苗获取违法所得人民币6253752.86元。

大学肄业的“95后”开发微博刷量APP

北京市丰台区法院公布的判决书显示,“星援”APP的开发者为蔡坤苗,其于1995年5月30日出生于福建省泉州市,大学肄业,系泉州市星援网络科技有限公司法定代表人。蔡坤苗因涉嫌犯破坏计算机信息系统罪,于2019年4月11日被逮捕。

2019年11月27日,北京市丰台区检察院指控被告人蔡坤苗犯提供侵入、非法控制计算机信息系统程序、工具罪,向丰台区法院提起公诉。

法院审理查明

2018年1月至2019年3月间,被告人蔡坤苗未获得北京微梦创科网络技术有限公司授权而自行开发“星援”APP,有偿为他人提供不需要登录新浪微博客户端即可转发微博博文及自动批量转发微博博文的服务。后大量用户以向“星援”APP充值的形式有偿使用该软件,并通过运行上述软件侵入新浪微博服务器。

经鉴定

“星援”APP通过截取新浪微博服务器中对应账号的相关数据,后使用与其截取数据相同的网络数据格式向该服务器提交数据并完成与该服务器的交互,以实现不登录新浪微博客户端即可转发微博博文的功能以及自动批量转发微博博文的功能。经统计,至案发时该软件已有用户使用19万余个控制端微博账号登录,上述控制端账号绑定微博账号×××余万个(原文如此),被告人蔡坤苗获取违法所得人民币6253752.86元。

2019年3月8日,被告人蔡坤苗被北京市公安局丰台分局太平桥派出所民警抓获,其到案后如实供述基本犯罪事实。

北京微梦创科网络技术有限公司员工李某称:“我们发现有一个叫‘星援’的APP破解了新浪微博的技术参数、算法,能对微博进行转发、评论、点赞等,影响了正常业务和系统稳定。2018年5月份的一天,我用手机刷微博时发现一个叫‘星援’的APP。这个APP可以大量转发或者评论同一条微博。我感觉这个APP可能有损我公司的利益,就跟公司领导进行了汇报。我们做了技术分析,直到现在才破解出来。过程中我们也收到用户的投诉,说‘星援’APP影响了微博的正常榜单和内容,同时也影响了系统的稳定和正常运行。”

相关司法鉴定意见书证明

使用新浪微博账号信息登录星援APP,在不登录微博客户端的情况下,可实现转发新浪微博博文的功能。使用新浪微博账号登录星援APP,通过该软件提供的配置界面,在配置相关参数后,可实现自动批量转发新浪微博博文的功能。

上述鉴定意见书显示,星援APP通过绑定微博账号的操作获取到微博用户的账号信息后,请求微博的服务器,从微博服务器返回的请求中获取相应账号的uid等信息,再通过结合密钥和特定算法的方式,生成微博加密数字签名s值,结合其他参数,使用与“新浪微博客户端”转发微博时相同的网络数据格式,将该数据提交给“新浪微博服务器”,该数据被“新浪微博服务器”误认为是“新浪微博客户端”提交的网络数据,进而和星援APP发生了数据交互,从而实现了不需要登陆“新浪微博客户端”即可转发新浪微博博文的功能。该APP还拥有通过绑定多个账号、多次重复请求,同时在转发微博博文时随机生成不同的硬件设备信息,实现自动批量转发新浪微博博文的功能。

17万微博用户绑定了3000万个微博“小号”

被告人蔡坤苗供述:“2018年3月,我自己做了一个名为星援的手机APP软件,并注册了一个网络工作室。2018年8月,我成立了泉州市星援网络科技有限公司,并担任公司法定代表人。”

蔡坤苗供述称,其公司主要经营两款手机应用软件,分别是星援和应援宝。这两款软件均是对接新浪微博的,客户通过这两款软件可以登录自己的微博账号实现批量转发、点赞和评论操作,而且绑定的微博数量没有上限,不用再人工登录每个微博账号进行重复操作。星援、应援宝两款手机软件通过用户的微博账号、密码登陆,登陆的时候不需要再另行注册。这两款软件的用户可以批量操作在软件端绑定的账号,更加快速的进行微博转发(行话叫抡博)、评论、点赞。微博客户端只能使用一个账号登陆进行操作,而星援、应援宝两款软件可以同时登陆多个微博账号进行相关操作。这两款软件在功能上是一样的,只是名字不一样。

蔡坤苗称,星援、应援宝两款软件可以加快明星粉丝,提升转发评论的数据量,满足数据的需求,“我于2019年2月份查看后台数据,星援、应援宝共有微博‘大号’用户17余万个,这17余万用户大约绑定了3000余万个微博‘小号’。‘星援’‘应援宝’一共有微博中的明星群管理员×××余个。微博‘大号’是常用的微博账号,有粉丝的老号。微博‘小号’是新注册或注册时间短的账号,也就是为转发增量而准备的账号。2019年2月份左右,我查了一下银行账户,‘星援’累计充值人民币700余万元,应援宝使用人数比较少,大概充值有10余万元。”

蔡坤苗供述称,他将犯罪所得主要用于买房和公司开销了,“我在泉州城东中骏世界城买了一处住宅,目前还在建设没有交房,费用大约100余万元。我还在泉州城东中骏世界城买了两个底商登记在我父亲蔡某名下,费用大约300万到400万之间,具体多少钱记不清了。其余资金用于日常开销、员工工资支出等。公司人事是陈某,每月工资7000元。UI设计是苏某和一个男孩,每月工资7000元。”

判决书显示

被害单位北京微梦创科网络技术有限公司的诉讼代理人在审理期间提供的证据证明,被告人蔡坤苗恶意开发的“星援”APP在未经北京微梦创科网络技术有限公司授权的情况下自动批量转发微博,大量转发的微博严重干扰了明星势力榜排行的数据,并导致排行系统功能受到实质性的影响;被告人蔡坤苗的行为给北京微梦创科网络技术有限公司造成应急人工支出45986.2元、2018年第四季度的服务器支出10376934元。

不过,法院审理后认为,上述诉讼代理人认为被告人蔡坤苗给被害单位造成经济损失人民币10422920.2元的意见,经查,相关证据均为被害单位单方材料,尚不足以证实与星援APP的关联性,故不予采纳。

北京市丰台区法院审理后认为,被告人蔡坤苗提供专门用于侵入计算机信息系统的程序,情节特别严重,其行为已构成提供侵入计算机信息系统程序罪,应予处罚。鉴于被告人蔡坤苗到案后如实供述基本犯罪事实,故对其予以从轻处罚。

2020年12月31日,被告人蔡坤苗被判犯提供侵入计算机信息系统程序罪,判处有期徒刑五年,并处罚金人民币十万元;继续追缴被告人蔡坤苗违法所得予以没收。

此文章【来源:澎湃新闻】,转载自【北晚新视觉网】,如有不当联系邮箱:pufa@dcloud.io 删除。原文链接

继续阅读 »

2018年,“明星蔡徐坤一条微博转发量过亿”事件引发舆论对流量造假的关注。按照当时的微博用户数量,转发量一亿意味着每三个微博用户中就有一人转发了蔡徐坤的微博。人民日报官微评论称:“一亿转发量”,你们也真敢刷。

2019年6月,操纵上述微博刷量事件的幕后推手“星援”APP被查。日前,中国裁判文书网公布了“星援”APP开发者蔡坤苗的判决书,其因提供侵入计算机信息系统程序罪一审获刑五年。

北京市丰台区法院审理查明,2018年1月至2019年3月间,被告人蔡坤苗未获得被害单位北京微梦创科网络技术有限公司授权而自行开发“星援”APP,有偿为他人提供不需要登录新浪微博客户端即可转发微博博文及自动批量转发微博博文的服务。后大量用户以向“星援”APP充值的形式有偿使用该软件,并通过运行上述软件侵入新浪微博服务器。

经鉴定,“星援”APP通过截取新浪微博服务器中对应账号的相关数据,后使用与其截取数据相同的网络数据格式向该服务器提交数据并完成与该服务器的交互,以实现不登录新浪微博客户端即可转发微博博文的功能以及自动批量转发微博博文的功能。经统计,至案发时该软件已有用户使用19万余个控制端微博账号登录,被告人蔡坤苗获取违法所得人民币6253752.86元。

大学肄业的“95后”开发微博刷量APP

北京市丰台区法院公布的判决书显示,“星援”APP的开发者为蔡坤苗,其于1995年5月30日出生于福建省泉州市,大学肄业,系泉州市星援网络科技有限公司法定代表人。蔡坤苗因涉嫌犯破坏计算机信息系统罪,于2019年4月11日被逮捕。

2019年11月27日,北京市丰台区检察院指控被告人蔡坤苗犯提供侵入、非法控制计算机信息系统程序、工具罪,向丰台区法院提起公诉。

法院审理查明

2018年1月至2019年3月间,被告人蔡坤苗未获得北京微梦创科网络技术有限公司授权而自行开发“星援”APP,有偿为他人提供不需要登录新浪微博客户端即可转发微博博文及自动批量转发微博博文的服务。后大量用户以向“星援”APP充值的形式有偿使用该软件,并通过运行上述软件侵入新浪微博服务器。

经鉴定

“星援”APP通过截取新浪微博服务器中对应账号的相关数据,后使用与其截取数据相同的网络数据格式向该服务器提交数据并完成与该服务器的交互,以实现不登录新浪微博客户端即可转发微博博文的功能以及自动批量转发微博博文的功能。经统计,至案发时该软件已有用户使用19万余个控制端微博账号登录,上述控制端账号绑定微博账号×××余万个(原文如此),被告人蔡坤苗获取违法所得人民币6253752.86元。

2019年3月8日,被告人蔡坤苗被北京市公安局丰台分局太平桥派出所民警抓获,其到案后如实供述基本犯罪事实。

北京微梦创科网络技术有限公司员工李某称:“我们发现有一个叫‘星援’的APP破解了新浪微博的技术参数、算法,能对微博进行转发、评论、点赞等,影响了正常业务和系统稳定。2018年5月份的一天,我用手机刷微博时发现一个叫‘星援’的APP。这个APP可以大量转发或者评论同一条微博。我感觉这个APP可能有损我公司的利益,就跟公司领导进行了汇报。我们做了技术分析,直到现在才破解出来。过程中我们也收到用户的投诉,说‘星援’APP影响了微博的正常榜单和内容,同时也影响了系统的稳定和正常运行。”

相关司法鉴定意见书证明

使用新浪微博账号信息登录星援APP,在不登录微博客户端的情况下,可实现转发新浪微博博文的功能。使用新浪微博账号登录星援APP,通过该软件提供的配置界面,在配置相关参数后,可实现自动批量转发新浪微博博文的功能。

上述鉴定意见书显示,星援APP通过绑定微博账号的操作获取到微博用户的账号信息后,请求微博的服务器,从微博服务器返回的请求中获取相应账号的uid等信息,再通过结合密钥和特定算法的方式,生成微博加密数字签名s值,结合其他参数,使用与“新浪微博客户端”转发微博时相同的网络数据格式,将该数据提交给“新浪微博服务器”,该数据被“新浪微博服务器”误认为是“新浪微博客户端”提交的网络数据,进而和星援APP发生了数据交互,从而实现了不需要登陆“新浪微博客户端”即可转发新浪微博博文的功能。该APP还拥有通过绑定多个账号、多次重复请求,同时在转发微博博文时随机生成不同的硬件设备信息,实现自动批量转发新浪微博博文的功能。

17万微博用户绑定了3000万个微博“小号”

被告人蔡坤苗供述:“2018年3月,我自己做了一个名为星援的手机APP软件,并注册了一个网络工作室。2018年8月,我成立了泉州市星援网络科技有限公司,并担任公司法定代表人。”

蔡坤苗供述称,其公司主要经营两款手机应用软件,分别是星援和应援宝。这两款软件均是对接新浪微博的,客户通过这两款软件可以登录自己的微博账号实现批量转发、点赞和评论操作,而且绑定的微博数量没有上限,不用再人工登录每个微博账号进行重复操作。星援、应援宝两款手机软件通过用户的微博账号、密码登陆,登陆的时候不需要再另行注册。这两款软件的用户可以批量操作在软件端绑定的账号,更加快速的进行微博转发(行话叫抡博)、评论、点赞。微博客户端只能使用一个账号登陆进行操作,而星援、应援宝两款软件可以同时登陆多个微博账号进行相关操作。这两款软件在功能上是一样的,只是名字不一样。

蔡坤苗称,星援、应援宝两款软件可以加快明星粉丝,提升转发评论的数据量,满足数据的需求,“我于2019年2月份查看后台数据,星援、应援宝共有微博‘大号’用户17余万个,这17余万用户大约绑定了3000余万个微博‘小号’。‘星援’‘应援宝’一共有微博中的明星群管理员×××余个。微博‘大号’是常用的微博账号,有粉丝的老号。微博‘小号’是新注册或注册时间短的账号,也就是为转发增量而准备的账号。2019年2月份左右,我查了一下银行账户,‘星援’累计充值人民币700余万元,应援宝使用人数比较少,大概充值有10余万元。”

蔡坤苗供述称,他将犯罪所得主要用于买房和公司开销了,“我在泉州城东中骏世界城买了一处住宅,目前还在建设没有交房,费用大约100余万元。我还在泉州城东中骏世界城买了两个底商登记在我父亲蔡某名下,费用大约300万到400万之间,具体多少钱记不清了。其余资金用于日常开销、员工工资支出等。公司人事是陈某,每月工资7000元。UI设计是苏某和一个男孩,每月工资7000元。”

判决书显示

被害单位北京微梦创科网络技术有限公司的诉讼代理人在审理期间提供的证据证明,被告人蔡坤苗恶意开发的“星援”APP在未经北京微梦创科网络技术有限公司授权的情况下自动批量转发微博,大量转发的微博严重干扰了明星势力榜排行的数据,并导致排行系统功能受到实质性的影响;被告人蔡坤苗的行为给北京微梦创科网络技术有限公司造成应急人工支出45986.2元、2018年第四季度的服务器支出10376934元。

不过,法院审理后认为,上述诉讼代理人认为被告人蔡坤苗给被害单位造成经济损失人民币10422920.2元的意见,经查,相关证据均为被害单位单方材料,尚不足以证实与星援APP的关联性,故不予采纳。

北京市丰台区法院审理后认为,被告人蔡坤苗提供专门用于侵入计算机信息系统的程序,情节特别严重,其行为已构成提供侵入计算机信息系统程序罪,应予处罚。鉴于被告人蔡坤苗到案后如实供述基本犯罪事实,故对其予以从轻处罚。

2020年12月31日,被告人蔡坤苗被判犯提供侵入计算机信息系统程序罪,判处有期徒刑五年,并处罚金人民币十万元;继续追缴被告人蔡坤苗违法所得予以没收。

此文章【来源:澎湃新闻】,转载自【北晚新视觉网】,如有不当联系邮箱:pufa@dcloud.io 删除。原文链接

收起阅读 »

安卓设置系统休眠时间-安卓原生方法

系统设置 安卓
 //获取默认休眠时间  
    @UniJSMethod(uiThread = true)  
    public void GetDormant(final JSCallback callback) {  
        try{  
            Context context = mWXSDKInstance.getContext();  
            int systemGravity = Settings.System.getInt(context.getContentResolver(),android.provider.Settings.System.SCREEN_OFF_TIMEOUT,0);  
            callback.invoke(systemGravity);  
        }catch (Exception ex){  
            callback.invoke(false);  
            Log.e(TAG, "setDormant: "+ex);  
        }  
    }  
    //设置系统休眠时间  
    @UniJSMethod(uiThread = true)  
    public void setDormant(int time,final JSCallback callback) {  
        try{  
            Context context = mWXSDKInstance.getContext();  
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
                if (!Settings.System.canWrite(context)) {  
                    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);  
                    intent.setData(Uri.parse("package:" + context.getPackageName()));  
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
                    context.startActivity(intent);  
                } else {  
                    //有了权限,具体的动作  
                    Settings.System.putInt(context.getContentResolver(),  
                            Settings.System.SCREEN_OFF_TIMEOUT, time);  
                    Uri uri = Settings.System  
                            .getUriFor(Settings.System.SCREEN_OFF_TIMEOUT);  
                    context.getContentResolver().notifyChange(uri, null);  
                    Log.e(TAG, "setDormant: 设置完成" );  
                    callback.invoke(true);  
                }  
            }  
        }catch (Exception ex){  
            callback.invoke(false);  
            Log.e(TAG, "setDormant: "+ex);  
        }  
    }
继续阅读 »
 //获取默认休眠时间  
    @UniJSMethod(uiThread = true)  
    public void GetDormant(final JSCallback callback) {  
        try{  
            Context context = mWXSDKInstance.getContext();  
            int systemGravity = Settings.System.getInt(context.getContentResolver(),android.provider.Settings.System.SCREEN_OFF_TIMEOUT,0);  
            callback.invoke(systemGravity);  
        }catch (Exception ex){  
            callback.invoke(false);  
            Log.e(TAG, "setDormant: "+ex);  
        }  
    }  
    //设置系统休眠时间  
    @UniJSMethod(uiThread = true)  
    public void setDormant(int time,final JSCallback callback) {  
        try{  
            Context context = mWXSDKInstance.getContext();  
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
                if (!Settings.System.canWrite(context)) {  
                    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);  
                    intent.setData(Uri.parse("package:" + context.getPackageName()));  
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
                    context.startActivity(intent);  
                } else {  
                    //有了权限,具体的动作  
                    Settings.System.putInt(context.getContentResolver(),  
                            Settings.System.SCREEN_OFF_TIMEOUT, time);  
                    Uri uri = Settings.System  
                            .getUriFor(Settings.System.SCREEN_OFF_TIMEOUT);  
                    context.getContentResolver().notifyChange(uri, null);  
                    Log.e(TAG, "setDormant: 设置完成" );  
                    callback.invoke(true);  
                }  
            }  
        }catch (Exception ex){  
            callback.invoke(false);  
            Log.e(TAG, "setDormant: "+ex);  
        }  
    }
收起阅读 »

uni-app 屏幕旋转

/
输入参数
portrait-primary:竖屏主方向
portrait-secondary: 竖屏次方向
landscape-primary:横屏主方向
landscape-secondary:横屏次方向
portrait:竖屏方向(primary + secondary)
landscape:横屏方向(primary + secondary)
natural:设备的自然方向
any: 锁定四个方向,即锁定当前屏幕方向
/

plus.screen.lockOrientation('landscape-primary');  
继续阅读 »

/
输入参数
portrait-primary:竖屏主方向
portrait-secondary: 竖屏次方向
landscape-primary:横屏主方向
landscape-secondary:横屏次方向
portrait:竖屏方向(primary + secondary)
landscape:横屏方向(primary + secondary)
natural:设备的自然方向
any: 锁定四个方向,即锁定当前屏幕方向
/

plus.screen.lockOrientation('landscape-primary');  
收起阅读 »

可恶!老年手机里植入木马程序 非法获利6600余万元

法律科普

近日,攀枝花市公安局东区分局成功破获一起非法控制计算机信息系统案件,打掉了三个控制“老年”手机非法获利的犯罪团伙。

去年3月,攀枝花市公安局东区分局接到一条线索,称一名75岁退休老人收到一条诈骗短信,被以刷单的方式诈骗资金6400元,然而这位老人他使用是一款老年手机。

民警发现该手机号向200余个手机发送了380条短信。通过调查发现该手机被植入了控制手机的木马程序,被外部服务器控制向他人发送诈骗短信。发送诈骗短信的电话是攀枝花市东区一居民孙某。经过进一步侦查工作,发现该团伙是以陈某某为首的犯罪团伙,他们在深圳注册了专门的科技公司生产手机,将植入木马功能的老年机销向市场,进行非法控制获取非法利益。该手机一旦被人购买插卡使用,便会主动将手机号码发送给犯罪团伙,并自动与科技公司的后台服务器发生联网,达到控制目标手机的目的。

随后专案组兵分三路,分别前往深圳、浙江、重庆开展收网工作,抓获了涉案人员25人,并起获了大量的后台服务器数据和尚未出售的装有木马的手机2万余部。随后调取后台服务数据显示,涉及受害手机达600余万部,涉案金额达4亿元。受害者遍及全国31个省、直辖市、自治区,犯罪团伙非法获利6600余万元。

民警提醒:部分非正规厂家生产的老年机可能存在被植入木马的隐患,因此我们在购买老年机的时候要选择正规厂商正规的品牌购买,一旦发现自己的资费有问题的时候,要去运营商查看相关情况,以防被不法分子利用。

此文章【来源:四川观察】,转载自【腾讯网】,如有不当联系邮箱:pufa@dcloud.io 删除。原文链接
版权归原作者所有,向原创致敬。

继续阅读 »

近日,攀枝花市公安局东区分局成功破获一起非法控制计算机信息系统案件,打掉了三个控制“老年”手机非法获利的犯罪团伙。

去年3月,攀枝花市公安局东区分局接到一条线索,称一名75岁退休老人收到一条诈骗短信,被以刷单的方式诈骗资金6400元,然而这位老人他使用是一款老年手机。

民警发现该手机号向200余个手机发送了380条短信。通过调查发现该手机被植入了控制手机的木马程序,被外部服务器控制向他人发送诈骗短信。发送诈骗短信的电话是攀枝花市东区一居民孙某。经过进一步侦查工作,发现该团伙是以陈某某为首的犯罪团伙,他们在深圳注册了专门的科技公司生产手机,将植入木马功能的老年机销向市场,进行非法控制获取非法利益。该手机一旦被人购买插卡使用,便会主动将手机号码发送给犯罪团伙,并自动与科技公司的后台服务器发生联网,达到控制目标手机的目的。

随后专案组兵分三路,分别前往深圳、浙江、重庆开展收网工作,抓获了涉案人员25人,并起获了大量的后台服务器数据和尚未出售的装有木马的手机2万余部。随后调取后台服务数据显示,涉及受害手机达600余万部,涉案金额达4亿元。受害者遍及全国31个省、直辖市、自治区,犯罪团伙非法获利6600余万元。

民警提醒:部分非正规厂家生产的老年机可能存在被植入木马的隐患,因此我们在购买老年机的时候要选择正规厂商正规的品牌购买,一旦发现自己的资费有问题的时候,要去运营商查看相关情况,以防被不法分子利用。

此文章【来源:四川观察】,转载自【腾讯网】,如有不当联系邮箱:pufa@dcloud.io 删除。原文链接
版权归原作者所有,向原创致敬。

收起阅读 »

编写微信小程序报渲染层错误[1]

问题:在编写微信小程序用到组件调用时,在子组件内部将props中的属性值动态赋给data中的某个状态值时,报 渲染层错误” Expect END descriptor with depth 1 but get another,
原因:我在组件created生命函数中直接赋的值,在网上查的资料说是微信小程序中不能这样修改数据,得用seData()函数修改。后来定义了个方法,在方法中实现动态赋值,然后在生命函数中调用这个方法就行了

继续阅读 »

问题:在编写微信小程序用到组件调用时,在子组件内部将props中的属性值动态赋给data中的某个状态值时,报 渲染层错误” Expect END descriptor with depth 1 but get another,
原因:我在组件created生命函数中直接赋的值,在网上查的资料说是微信小程序中不能这样修改数据,得用seData()函数修改。后来定义了个方法,在方法中实现动态赋值,然后在生命函数中调用这个方法就行了

收起阅读 »

uni-app mDNS

// #ifdef APP-PLUS   
let vm = this;  
let mServerType = '_http._tcp.'; //服务类型  
let NsdServiceInfo = plus.android.importClass('android.net.nsd.NsdServiceInfo');  
let NsdManager = plus.android.importClass('android.net.nsd.NsdManager');  
let Context = plus.android.importClass('android.content.Context');  
// 导入后可以使用new方法创建类的实例对象  
let nsd_service_info = new NsdServiceInfo();  
let nsd_manager = new NsdManager();  
//获取应用主Activity实例对象系统服务NSD_SERVICE方法  
let mNsdManager = plus.android.runtimeMainActivity().getSystemService(Context.NSD_SERVICE);  
//实列API接口监听回调函数  
let mDiscoveryListener = plus.android.implements('android.net.nsd.NsdManager$DiscoveryListener', {  
    onServiceFound: function(service) {  
        //先发现设备服务再执行连接获取数据  
        //导入service类  
        plus.android.importClass(service);  
        //实列化连接服务接口监听回调函数  
        //注意NsdManager$ResolveListener中间使用$不是“.”  
        let mResolveListener = plus.android.implements('android.net.nsd.NsdManager$ResolveListener', {  
            onServiceResolved: function(services) {  
                //连接服务  
                let name = services.getServiceName();  
                let port = services.getPort();  
                let ip = services.getHost();  
                plus.android.importClass(ip); //导入services.getHost()类  
                ip = ip.getHostAddress();  
                let arry = {  
                    name: name,  
                    port: port,  
                    ip: ip  
                };  
                console.log(arry)  
                if(name == "esp8266"){  
                    mNsdManager.stopServiceDiscovery(mResolveListener);  
                }  
            }  
        });  
        mNsdManager.resolveService(service, mResolveListener); //启动连接服务  
    }  
});  
// 导入mNsdManager Java类对象  
plus.android.importClass(mNsdManager);  
mNsdManager.discoverServices(mServerType, 1, mDiscoveryListener); //启动监听服务(类型,常量,回调函数)参考java discoverServices需要携带的参数类型  

// #endif  
继续阅读 »
// #ifdef APP-PLUS   
let vm = this;  
let mServerType = '_http._tcp.'; //服务类型  
let NsdServiceInfo = plus.android.importClass('android.net.nsd.NsdServiceInfo');  
let NsdManager = plus.android.importClass('android.net.nsd.NsdManager');  
let Context = plus.android.importClass('android.content.Context');  
// 导入后可以使用new方法创建类的实例对象  
let nsd_service_info = new NsdServiceInfo();  
let nsd_manager = new NsdManager();  
//获取应用主Activity实例对象系统服务NSD_SERVICE方法  
let mNsdManager = plus.android.runtimeMainActivity().getSystemService(Context.NSD_SERVICE);  
//实列API接口监听回调函数  
let mDiscoveryListener = plus.android.implements('android.net.nsd.NsdManager$DiscoveryListener', {  
    onServiceFound: function(service) {  
        //先发现设备服务再执行连接获取数据  
        //导入service类  
        plus.android.importClass(service);  
        //实列化连接服务接口监听回调函数  
        //注意NsdManager$ResolveListener中间使用$不是“.”  
        let mResolveListener = plus.android.implements('android.net.nsd.NsdManager$ResolveListener', {  
            onServiceResolved: function(services) {  
                //连接服务  
                let name = services.getServiceName();  
                let port = services.getPort();  
                let ip = services.getHost();  
                plus.android.importClass(ip); //导入services.getHost()类  
                ip = ip.getHostAddress();  
                let arry = {  
                    name: name,  
                    port: port,  
                    ip: ip  
                };  
                console.log(arry)  
                if(name == "esp8266"){  
                    mNsdManager.stopServiceDiscovery(mResolveListener);  
                }  
            }  
        });  
        mNsdManager.resolveService(service, mResolveListener); //启动连接服务  
    }  
});  
// 导入mNsdManager Java类对象  
plus.android.importClass(mNsdManager);  
mNsdManager.discoverServices(mServerType, 1, mDiscoveryListener); //启动监听服务(类型,常量,回调函数)参考java discoverServices需要携带的参数类型  

// #endif  
收起阅读 »

unipush服务端推送PHP版RestAPI V2 的离线/在线推送

unipush

关于unipush的推送还是用个推的文档和SDK,下载个推的SDK整合进PHP框架里,然后开始表演了。刚开始在网上找真的都是老版本的,RestAPI V2 的几乎没有涉及,旧SDK的可能以后都要不支持了,所以建议大家更换新版本的SDK。话不多说,上代码:

$title为推送标题,$content为推送内容,$payload为点击通知加自定义消息,$cid为推送cid,$package为APP包名,"APPKEY","APPID","MasterSecret"这几个要传入你真实的。以下是单推例子,更多推送就不多说了。  
function pushToSingleByCid($title,$content,$payload,$cid,$package){  
    //创建API,APPID等配置参考 环境要求 进行获取  
    $api = new \GTClient_unipush("https://restapi.getui.com","APPKEY","APPID","MasterSecret");  
    //设置推送参数  
    $push = new \GTPushRequest();  
    $osn = date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);  
    $push->setRequestId((string)$osn);  

    $message = new \GTPushMessage();  
      $channel = new \GTPushChannel();  
    $notify = new \GTNotification();  
  $thirdnotify = new \GTThirdNotification();  
   $ups = new \GTUps();  
    $gtAndroid = new \GTAndroid();  
    $notify->setTitle($title);  
    $notify->setBody($content);  

    $thirdnotify->setTitle($title);  
    $thirdnotify->setBody($content);  
    if(is_array($payload))  
    $pj =  json_encode($payload);  
    else  
     $pj = $payload;  
    $notify-> setPayload($pj);  
   $thirdnotify-> setPayload($pj);  

       $intent = "intent:#Intent;launchFlags=0x14000000;action=android.intent.action.oppopush;component={$package}/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title={$title};S.content={$content};S.payload={$pj};end";  
         $notify->setClickType("intent");  
   $thirdnotify->setClickType("intent");  
    $notify->setIntent($intent);  
     $thirdnotify->setIntent($intent);  
    echo  $intent;  

    //点击通知后续动作,目前支持以下后续动作:  
    //1、intent:打开应用内特定页面url:打开网页地址。2、payload:自定义消息内容启动应用。3、payload_custom:自定义消息内容不启动应用。4、startapp:打开应用首页。5、none:纯通知,无后续动作  

  $notify->setIntent($intent);  
     // $notify->setChannelLevel(3);  

 // $touchuan=['title'=>$title,'content'=>$content,'payload'=>$package];  

//$message->setTransmission(json_encode($touchuan));//个推透传  
$message->setNotification($notify);  
 $upsback= $ups->setNotification($thirdnotify);  
 // $upsback= $ups->setTransmission(json_encode($touchuan));//厂商透传  

$gtAndroid->setUps($ups);  
$channel->setAndroid($gtAndroid);  
$push->setPushMessage($message);  

      $push->setPushChannel( $channel);  
    $push->setCid($cid);  
    //处理返回结果  
    $result = $api->pushApi()->pushToSingleByCid($push);  
  // print_r($result);  
}  
继续阅读 »

关于unipush的推送还是用个推的文档和SDK,下载个推的SDK整合进PHP框架里,然后开始表演了。刚开始在网上找真的都是老版本的,RestAPI V2 的几乎没有涉及,旧SDK的可能以后都要不支持了,所以建议大家更换新版本的SDK。话不多说,上代码:

$title为推送标题,$content为推送内容,$payload为点击通知加自定义消息,$cid为推送cid,$package为APP包名,"APPKEY","APPID","MasterSecret"这几个要传入你真实的。以下是单推例子,更多推送就不多说了。  
function pushToSingleByCid($title,$content,$payload,$cid,$package){  
    //创建API,APPID等配置参考 环境要求 进行获取  
    $api = new \GTClient_unipush("https://restapi.getui.com","APPKEY","APPID","MasterSecret");  
    //设置推送参数  
    $push = new \GTPushRequest();  
    $osn = date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);  
    $push->setRequestId((string)$osn);  

    $message = new \GTPushMessage();  
      $channel = new \GTPushChannel();  
    $notify = new \GTNotification();  
  $thirdnotify = new \GTThirdNotification();  
   $ups = new \GTUps();  
    $gtAndroid = new \GTAndroid();  
    $notify->setTitle($title);  
    $notify->setBody($content);  

    $thirdnotify->setTitle($title);  
    $thirdnotify->setBody($content);  
    if(is_array($payload))  
    $pj =  json_encode($payload);  
    else  
     $pj = $payload;  
    $notify-> setPayload($pj);  
   $thirdnotify-> setPayload($pj);  

       $intent = "intent:#Intent;launchFlags=0x14000000;action=android.intent.action.oppopush;component={$package}/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title={$title};S.content={$content};S.payload={$pj};end";  
         $notify->setClickType("intent");  
   $thirdnotify->setClickType("intent");  
    $notify->setIntent($intent);  
     $thirdnotify->setIntent($intent);  
    echo  $intent;  

    //点击通知后续动作,目前支持以下后续动作:  
    //1、intent:打开应用内特定页面url:打开网页地址。2、payload:自定义消息内容启动应用。3、payload_custom:自定义消息内容不启动应用。4、startapp:打开应用首页。5、none:纯通知,无后续动作  

  $notify->setIntent($intent);  
     // $notify->setChannelLevel(3);  

 // $touchuan=['title'=>$title,'content'=>$content,'payload'=>$package];  

//$message->setTransmission(json_encode($touchuan));//个推透传  
$message->setNotification($notify);  
 $upsback= $ups->setNotification($thirdnotify);  
 // $upsback= $ups->setTransmission(json_encode($touchuan));//厂商透传  

$gtAndroid->setUps($ups);  
$channel->setAndroid($gtAndroid);  
$push->setPushMessage($message);  

      $push->setPushChannel( $channel);  
    $push->setCid($cid);  
    //处理返回结果  
    $result = $api->pushApi()->pushToSingleByCid($push);  
  // print_r($result);  
}  
收起阅读 »

基于uniapp+yii2的全套OA办公系统,提供前后端源码,支持多端部署

简介

UNI办公系统主要为国内企业提供办公自动化信息服务,功能如:工作流、工作审批(报修申请、报销申请、领用申请、申购申请、请假申请、出差申请、加班申请、用工申请、接待申请、用车申请);个人中心(公告管理、消息管理、工作日志、我的日程、工作总结);知识管理(新闻动态、管理制度、下载中心等);日常管理(资产管理、车辆管理、档案管理、考勤管理、巡更巡检、合同管理、后勤采购、就餐统计、通讯录);人事管理(员工信息、奖惩管理、社保管理等)、考勤管理(班次管理、排班管理、我的排班、签到签退);巡更巡检(地点管理、巡更班次、巡更计划、我的排班、巡更记录);意见反馈、站点帮助、在线客服、一键换肤等功能模块。

系统前端基于uniapp开发,后端基于php开发;该系统可独立部署在自己的服务器,且支持单企业版和多企业版本;可后台根据用户角色权限控制手机端功能模块的显示;目前已适配H5、微信小程序、安卓和ios,如果在试用或购买后发现问题,欢迎您随时提出。

咨询

作者QQ:21931118 QQ群:1107210028
如您已下载本插件,可加入QQ群一起讨论,作者不承诺技术支持;

演示

  1. 后台演示账号:后台不开源,不免费提供后台账号及接口
  2. 手机端测试版:测试版自己加群下载,账密:18986860001/18986860001(请扫码H5或者安卓,苹果和小程序版不提供测试账号)
  3. 业务合作:加Q私聊
    输入图片说明
  4. 官方网站:unioa插件市场

手机端部分截图

输入图片说明
输入图片说明
输入图片说明
输入图片说明

后台部分截图

安装插件

输入图片说明

已安装插件

输入图片说明

工作流列表

工作流配置

流程状态

输入图片说明

配置审核人员

输入图片说明

支持指定人员审核和指定角色审核

工作流转

输入图片说明

新增流程节点

输入图片说明

待办工作

输入图片说明

已办工作

输入图片说明

如果审核失误,在下一级没有审核的情况下,可点击重审按钮进行重新审核,流程将重新转入申请状态。

审核工作

输入图片说明

创建申请

输入图片说明

查看进度

输入图片说明

如果工作已有人员进行审核,进入工作流转后,用户不能编辑和删除该工作。
企业管理人员可自定义工作类型

班次管理

输入图片说明

排班管理

输入图片说明

我的排班

输入图片说明

签到列表

输入图片说明

新建打卡

输入图片说明

插件市场 总有一款插件适合你!

输入图片说明
输入图片说明
输入图片说明
输入图片说明

开始使用

  1. 将项目导入HBuildX
  2. 修改配置文件config/index.conf.js内配置对应参数
  3. 运行即可体验

发行微信小程序

在HBuildx顶部菜单点击运行->运行到微信小程序
使用微信开发者工具上传版本并审核通过即可

注意:小程序需额外配置服务器域名

发行H5

在HBuildx顶部菜单点击发行->网站-H5手机版
在弹出的对话框中输入网站标题和域名即可,将编译后的资源部署到服务器(虚拟主机)

需注意HBx直接部署网页托管需要最新版,老版本没有这个选项,可以自己到web控制台进行托管。
点击发行,等待项目编译部署即可。
如果您不想购买服务器,那就来uniCloud白嫖一波吧~

发行ios版和安卓版

在HBuildx顶部菜单点击发行->原生App-云打包,
在弹出的对话框中选择证书文件和输入密码即可。

隐私、权限声明

  • 本插件需要申请的系统权限列表:

    1.定位权限 2.拍照权限 3.相册权限

  • 本插件采集的数据、发送的服务器地址、以及数据用途说明:

  • 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

继续阅读 »

简介

UNI办公系统主要为国内企业提供办公自动化信息服务,功能如:工作流、工作审批(报修申请、报销申请、领用申请、申购申请、请假申请、出差申请、加班申请、用工申请、接待申请、用车申请);个人中心(公告管理、消息管理、工作日志、我的日程、工作总结);知识管理(新闻动态、管理制度、下载中心等);日常管理(资产管理、车辆管理、档案管理、考勤管理、巡更巡检、合同管理、后勤采购、就餐统计、通讯录);人事管理(员工信息、奖惩管理、社保管理等)、考勤管理(班次管理、排班管理、我的排班、签到签退);巡更巡检(地点管理、巡更班次、巡更计划、我的排班、巡更记录);意见反馈、站点帮助、在线客服、一键换肤等功能模块。

系统前端基于uniapp开发,后端基于php开发;该系统可独立部署在自己的服务器,且支持单企业版和多企业版本;可后台根据用户角色权限控制手机端功能模块的显示;目前已适配H5、微信小程序、安卓和ios,如果在试用或购买后发现问题,欢迎您随时提出。

咨询

作者QQ:21931118 QQ群:1107210028
如您已下载本插件,可加入QQ群一起讨论,作者不承诺技术支持;

演示

  1. 后台演示账号:后台不开源,不免费提供后台账号及接口
  2. 手机端测试版:测试版自己加群下载,账密:18986860001/18986860001(请扫码H5或者安卓,苹果和小程序版不提供测试账号)
  3. 业务合作:加Q私聊
    输入图片说明
  4. 官方网站:unioa插件市场

手机端部分截图

输入图片说明
输入图片说明
输入图片说明
输入图片说明

后台部分截图

安装插件

输入图片说明

已安装插件

输入图片说明

工作流列表

工作流配置

流程状态

输入图片说明

配置审核人员

输入图片说明

支持指定人员审核和指定角色审核

工作流转

输入图片说明

新增流程节点

输入图片说明

待办工作

输入图片说明

已办工作

输入图片说明

如果审核失误,在下一级没有审核的情况下,可点击重审按钮进行重新审核,流程将重新转入申请状态。

审核工作

输入图片说明

创建申请

输入图片说明

查看进度

输入图片说明

如果工作已有人员进行审核,进入工作流转后,用户不能编辑和删除该工作。
企业管理人员可自定义工作类型

班次管理

输入图片说明

排班管理

输入图片说明

我的排班

输入图片说明

签到列表

输入图片说明

新建打卡

输入图片说明

插件市场 总有一款插件适合你!

输入图片说明
输入图片说明
输入图片说明
输入图片说明

开始使用

  1. 将项目导入HBuildX
  2. 修改配置文件config/index.conf.js内配置对应参数
  3. 运行即可体验

发行微信小程序

在HBuildx顶部菜单点击运行->运行到微信小程序
使用微信开发者工具上传版本并审核通过即可

注意:小程序需额外配置服务器域名

发行H5

在HBuildx顶部菜单点击发行->网站-H5手机版
在弹出的对话框中输入网站标题和域名即可,将编译后的资源部署到服务器(虚拟主机)

需注意HBx直接部署网页托管需要最新版,老版本没有这个选项,可以自己到web控制台进行托管。
点击发行,等待项目编译部署即可。
如果您不想购买服务器,那就来uniCloud白嫖一波吧~

发行ios版和安卓版

在HBuildx顶部菜单点击发行->原生App-云打包,
在弹出的对话框中选择证书文件和输入密码即可。

隐私、权限声明

  • 本插件需要申请的系统权限列表:

    1.定位权限 2.拍照权限 3.相册权限

  • 本插件采集的数据、发送的服务器地址、以及数据用途说明:

  • 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

收起阅读 »

个人发卡网源码内核

源码分享

发卡网源码演示及下载地址:fakaysw.top
<?php

namespace app\admin\controller;

use controller\BasicAdmin;
use think\Db;

class App extends BasicAdmin
{

public function index()  
{  
    if (!$this->request->isPost()) {  
        return $this->fetch();  
    }  

    $version = input('version/s');  
    if(empty($version)){  
        $this->error('请输入版本号');  
    }  
    $data = [  
        'platform' => input('platform/s'),  
        'version' => $version,  
    ];  

    //判断是否已经存在相同的版本号  
    $res = Db::name('app_version')->where($data)->find();  
    if($res){  
        $this->error('已存在相同版本');  
    }  

    $platform = input('platform/s');  
    $url = '';  
    if ($platform == 'android') {  
        $package = getUploadFile('package', true, ['apk']);  

        if (!$package['status']) {  
            $this->error($package['msg']);  
        } else {  
            $url = $package['data']['file'];  
        }  
    } else {  
        $url = input('appstore_url/s');  
    }  

    $data = array_merge($data,[  
        'package' => $url,  
        'create_at' => time(),  
        'create_ip' => $_SERVER['REMOTE_ADDR'],  
        'remark' => input('remark/s')  
    ]);  

    $res = Db::name('app_version')->insert($data);  
    if ($res) {  
        $this->success('新增版本成功');  
    } else {  
        $this->error('新增版本失败');  
    }  
}  

}

<?php

namespace app\admin\controller;

use controller\BasicAdmin;
use service\DataService;
use service\NodeService;
use service\ToolsService;
use think\Request;
use think\Session;
use think\Db;
use think\captcha\Captcha;
use app\common\util\Sms;
use service\LogService;

/**

  • 系统权限管理控制器
  • Class Auth
  • @package app\admin\controller
  • @author Anyon <zoujingli@qq.com>
  • @date 2017/02/15 18:13
    */
    class Auth extends BasicAdmin
    {

    /**

    • 默认数据模型
    • @var string
      */
      public $table = 'SystemAuth';

    /**

    • 权限列表
      */
      public function index()
      {
      $this->title = '系统权限管理';
      return parent::_list($this->table);
      }

    /**

    • 权限授权
    • @return string
      */
      public function apply()
      {
      $auth_id = $this->request->get('id', '0');
      $method = 'apply' . strtolower($this->request->get('action', '0'));
      if (method_exists($this, $method)) {
      return $this->$method($auth_id);
      }
      $this->assign('title', '节点授权');
      return $this->_form($this->table, 'apply');
      }

    /**

    • 读取授权节点
    • @param $auth_id
      */
      protected function _apply_getnode($auth_id)
      {
      $nodes = NodeService::get();
      $checked = Db::name('SystemAuthNode')->where(['auth' => $auth_id])->column('node');
      foreach ($nodes as &$node) {
      $node['checked'] = in_array($node['node'], $checked);
      }
      $all = $this->_apply_filter(ToolsService::arr2tree($nodes, 'node', 'pnode', 'sub'));
      $this->success('获取节点成功!', '', $all);
      }

    /**

    • 保存授权节点
    • @param $auth_id
      */
      protected function _apply_save($auth_id)
      {
      list($data, $post) = [[], $this->request->post()];
      foreach (isset($post['nodes']) ? $post['nodes'] : [] as $node) {
      $data[] = ['auth' => $auth_id, 'node' => $node];
      }
      Db::name('SystemAuthNode')->where(['auth' => $auth_id])->delete();
      Db::name('SystemAuthNode')->insertAll($data);
      LogService::write('系统权限', '节点授权成功');
      $this->success('节点授权更新成功!', '');
      }

    /**

    • 节点数据拼装
    • @param array $nodes
    • @param int $level
    • @return array
      */
      protected function _apply_filter($nodes, $level = 1)
      {
      foreach ($nodes as $key => &$node) {
      if (!empty($node['sub']) && is_array($node['sub'])) {
      $node['sub'] = $this->_apply_filter($node['sub'], $level + 1);
      }
      }
      return $nodes;
      }

    /**

    • 权限添加
      */
      public function add()
      {
      return $this->_form($this->table, 'form');
      }

    /**

    • 权限编辑
      */
      public function edit()
      {
      return $this->_form($this->table, 'form');
      }

    /**

    • 权限禁用
      */
      public function forbid()
      {
      if (DataService::update($this->table)) {
      LogService::write('系统权限', '权限禁用成功');
      $this->success("权限禁用成功!", '');
      }
      $this->error("权限禁用失败,请稍候再试!");
      }

    /**

    • 权限恢复
      */
      public function resume()
      {
      if (DataService::update($this->table)) {
      LogService::write('系统权限', '权限启用成功');
      $this->success("权限启用成功!", '');
      }
      $this->error("权限启用失败,请稍候再试!");
      }

    /**

    • 权限删除
      */
      public function del()
      {
      if (DataService::update($this->table)) {
      $id = $this->request->post('id');
      Db::name('SystemAuthNode')->where(['auth' => $id])->delete();
      LogService::write('系统权限', '权限删除成功');
      $this->success("权限删除成功!", '');
      }
      $this->error("权限删除失败,请稍候再试!");
      }

    /**

    • 谷歌令牌验证
      */
      public function google()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      if(sysconf('is_google_auth') == 0) {
      $this->error('系统未开启谷歌身份验证', '@admin');
      }
      $google_auth = session('google_auth');
      if($google_auth) {
      $this->redirect('@admin');
      }
      $ga = new \Util\Verify\PHPGangsta_GoogleAuthenticator();
      $google_token = Db::name('system_user')->where('id',session('user')['id'])->value('google_secret_key');
      if (!$this->request->isPost()) {
      if($google_token == '') {
      $secret = $ga->createSecret();
      $qrCodeUrl = $ga->getQRCodeGoogleUrl(Request::instance()->domain(), $secret);
      session('google_secret_key', $secret);
      $this->assign('secret', $secret);
      $this->assign('qrCodeUrl', $qrCodeUrl);

      }  
      $this->assign('action_type', $google_token == '' ? 0 : 1);  
      $this->assign('google_token', $google_token);  
      return view();  

      } else {
      $action_type = input('action_type/d', 0);
      $code = $this->request->post('code', '', 'trim');
      if($code == '') {
      $this->error("请输入验证码");
      }
      if($action_type == 0) {//首次绑定
      $google_secret_key = session('google_secret_key');
      if(!$google_secret_key) {
      $this->error("绑定失败,请刷新页面重试");
      }
      $oneCode = $ga->getCode($google_secret_key);
      if($code !== $oneCode) {
      $this->error("验证码错误");
      } else {
      $re = Db::name('system_user')->where(['id'=>session('user')['id']])->update(['google_secret_key'=>$google_secret_key]);
      if(FALSE !== $re) {
      session('google_auth', $oneCode);
      session('google_secret_key', null);
      $this->success("绑定成功", '@admin');
      } else {
      $this->error("绑定失败,请售后重试");
      }
      }
      } else {
      $google_secret_key = Db::name('system_user')->where(['id'=>session('user')['id']])->value('google_secret_key');
      if($google_secret_key == '') {
      $this->error("您未绑定谷歌身份验证器");
      }
      $captcha = $this->request->post('captcha_code', '', 'trim');
      $captchaClass = new Captcha();
      if(!$captchaClass->check($captcha)) {
      $this->error('图形验证码错误!');
      }
      $oneCode = $ga->getCode($google_secret_key);
      if($code != $oneCode) {
      $this->error("身份验证码错误");
      } else {
      session('google_auth', $oneCode);
      LogService::write('系统权限', '绑定谷歌身份验证器成功');
      $this->success("验证通过,正在进入系统...", '@admin');
      }
      }

      }
      }
      public function resetGoogle()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      if(sysconf('is_google_auth') == 0) {
      $this->error('系统未开启谷歌身份验证');
      }
      $mobile = session('user')['phone'];
      $google_auth = session('google_auth');
      if($google_auth) {
      $this->redirect('@admin');
      }
      if (!$this->request->isPost()) {
      if($mobile) {
      $mobile = substr($mobile, 0, 3).'****'.substr($mobile, 7);
      }
      $this->assign('mobile', $mobile);
      return view();
      } else {
      $code = input('sms_code');
      if($code == '') {
      $this->error('请输入验证码');
      }
      $sms=new Sms();
      if(!$sms->verifyCode($mobile, $code,'google_auth')){
      $this->error($sms->getError());
      }
      $re = Db::name('system_user')->where(['id'=>session('user')['id']])->update(['google_secret_key'=>'']);
      if(FALSE !== $re) {
      LogService::write('系统权限', '谷歌身份验证器验证通过');
      $this->success('验证通过,进入下一步...','admin/auth/google');
      } else {
      $this->error("重置失败");
      }
      }
      }

    //生成绑定谷歌身份验证器二维码(测试,部署生产环境时删除!)
    public function bindGoogle()
    {
    $id = input('id/d');
    if(!$id) {
    return false;
    }
    $ga = new \Util\Verify\PHPGangsta_GoogleAuthenticator();
    $google_secret_key = Db::name('system_user')->where(['id'=>$id])->value('google_secret_key');
    if(!$google_secret_key) {
    return false;
    }
    $qrCodeUrl = $ga->getQRCodeGoogleUrl(Request::instance()->domain(), $google_secret_key);
    echo '<img src="'.$qrCodeUrl.'"">';die;
    }

    /**

    • 发送短信验证码
      */
      public function sendSmsCode()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      $mobile=session('user')['phone'];
      if(!is_mobile_number($mobile)){
      $this->error('不是有效的号码!');
      }
      $sms=new Sms();
      $res=$sms->sendCode($mobile, 'google_auth');
      if($res===false){
      $this->error($sms->getError());
      }
      $this->success('已发送验证码,请注意查收!!');
      }
      }
继续阅读 »

发卡网源码演示及下载地址:fakaysw.top
<?php

namespace app\admin\controller;

use controller\BasicAdmin;
use think\Db;

class App extends BasicAdmin
{

public function index()  
{  
    if (!$this->request->isPost()) {  
        return $this->fetch();  
    }  

    $version = input('version/s');  
    if(empty($version)){  
        $this->error('请输入版本号');  
    }  
    $data = [  
        'platform' => input('platform/s'),  
        'version' => $version,  
    ];  

    //判断是否已经存在相同的版本号  
    $res = Db::name('app_version')->where($data)->find();  
    if($res){  
        $this->error('已存在相同版本');  
    }  

    $platform = input('platform/s');  
    $url = '';  
    if ($platform == 'android') {  
        $package = getUploadFile('package', true, ['apk']);  

        if (!$package['status']) {  
            $this->error($package['msg']);  
        } else {  
            $url = $package['data']['file'];  
        }  
    } else {  
        $url = input('appstore_url/s');  
    }  

    $data = array_merge($data,[  
        'package' => $url,  
        'create_at' => time(),  
        'create_ip' => $_SERVER['REMOTE_ADDR'],  
        'remark' => input('remark/s')  
    ]);  

    $res = Db::name('app_version')->insert($data);  
    if ($res) {  
        $this->success('新增版本成功');  
    } else {  
        $this->error('新增版本失败');  
    }  
}  

}

<?php

namespace app\admin\controller;

use controller\BasicAdmin;
use service\DataService;
use service\NodeService;
use service\ToolsService;
use think\Request;
use think\Session;
use think\Db;
use think\captcha\Captcha;
use app\common\util\Sms;
use service\LogService;

/**

  • 系统权限管理控制器
  • Class Auth
  • @package app\admin\controller
  • @author Anyon <zoujingli@qq.com>
  • @date 2017/02/15 18:13
    */
    class Auth extends BasicAdmin
    {

    /**

    • 默认数据模型
    • @var string
      */
      public $table = 'SystemAuth';

    /**

    • 权限列表
      */
      public function index()
      {
      $this->title = '系统权限管理';
      return parent::_list($this->table);
      }

    /**

    • 权限授权
    • @return string
      */
      public function apply()
      {
      $auth_id = $this->request->get('id', '0');
      $method = 'apply' . strtolower($this->request->get('action', '0'));
      if (method_exists($this, $method)) {
      return $this->$method($auth_id);
      }
      $this->assign('title', '节点授权');
      return $this->_form($this->table, 'apply');
      }

    /**

    • 读取授权节点
    • @param $auth_id
      */
      protected function _apply_getnode($auth_id)
      {
      $nodes = NodeService::get();
      $checked = Db::name('SystemAuthNode')->where(['auth' => $auth_id])->column('node');
      foreach ($nodes as &$node) {
      $node['checked'] = in_array($node['node'], $checked);
      }
      $all = $this->_apply_filter(ToolsService::arr2tree($nodes, 'node', 'pnode', 'sub'));
      $this->success('获取节点成功!', '', $all);
      }

    /**

    • 保存授权节点
    • @param $auth_id
      */
      protected function _apply_save($auth_id)
      {
      list($data, $post) = [[], $this->request->post()];
      foreach (isset($post['nodes']) ? $post['nodes'] : [] as $node) {
      $data[] = ['auth' => $auth_id, 'node' => $node];
      }
      Db::name('SystemAuthNode')->where(['auth' => $auth_id])->delete();
      Db::name('SystemAuthNode')->insertAll($data);
      LogService::write('系统权限', '节点授权成功');
      $this->success('节点授权更新成功!', '');
      }

    /**

    • 节点数据拼装
    • @param array $nodes
    • @param int $level
    • @return array
      */
      protected function _apply_filter($nodes, $level = 1)
      {
      foreach ($nodes as $key => &$node) {
      if (!empty($node['sub']) && is_array($node['sub'])) {
      $node['sub'] = $this->_apply_filter($node['sub'], $level + 1);
      }
      }
      return $nodes;
      }

    /**

    • 权限添加
      */
      public function add()
      {
      return $this->_form($this->table, 'form');
      }

    /**

    • 权限编辑
      */
      public function edit()
      {
      return $this->_form($this->table, 'form');
      }

    /**

    • 权限禁用
      */
      public function forbid()
      {
      if (DataService::update($this->table)) {
      LogService::write('系统权限', '权限禁用成功');
      $this->success("权限禁用成功!", '');
      }
      $this->error("权限禁用失败,请稍候再试!");
      }

    /**

    • 权限恢复
      */
      public function resume()
      {
      if (DataService::update($this->table)) {
      LogService::write('系统权限', '权限启用成功');
      $this->success("权限启用成功!", '');
      }
      $this->error("权限启用失败,请稍候再试!");
      }

    /**

    • 权限删除
      */
      public function del()
      {
      if (DataService::update($this->table)) {
      $id = $this->request->post('id');
      Db::name('SystemAuthNode')->where(['auth' => $id])->delete();
      LogService::write('系统权限', '权限删除成功');
      $this->success("权限删除成功!", '');
      }
      $this->error("权限删除失败,请稍候再试!");
      }

    /**

    • 谷歌令牌验证
      */
      public function google()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      if(sysconf('is_google_auth') == 0) {
      $this->error('系统未开启谷歌身份验证', '@admin');
      }
      $google_auth = session('google_auth');
      if($google_auth) {
      $this->redirect('@admin');
      }
      $ga = new \Util\Verify\PHPGangsta_GoogleAuthenticator();
      $google_token = Db::name('system_user')->where('id',session('user')['id'])->value('google_secret_key');
      if (!$this->request->isPost()) {
      if($google_token == '') {
      $secret = $ga->createSecret();
      $qrCodeUrl = $ga->getQRCodeGoogleUrl(Request::instance()->domain(), $secret);
      session('google_secret_key', $secret);
      $this->assign('secret', $secret);
      $this->assign('qrCodeUrl', $qrCodeUrl);

      }  
      $this->assign('action_type', $google_token == '' ? 0 : 1);  
      $this->assign('google_token', $google_token);  
      return view();  

      } else {
      $action_type = input('action_type/d', 0);
      $code = $this->request->post('code', '', 'trim');
      if($code == '') {
      $this->error("请输入验证码");
      }
      if($action_type == 0) {//首次绑定
      $google_secret_key = session('google_secret_key');
      if(!$google_secret_key) {
      $this->error("绑定失败,请刷新页面重试");
      }
      $oneCode = $ga->getCode($google_secret_key);
      if($code !== $oneCode) {
      $this->error("验证码错误");
      } else {
      $re = Db::name('system_user')->where(['id'=>session('user')['id']])->update(['google_secret_key'=>$google_secret_key]);
      if(FALSE !== $re) {
      session('google_auth', $oneCode);
      session('google_secret_key', null);
      $this->success("绑定成功", '@admin');
      } else {
      $this->error("绑定失败,请售后重试");
      }
      }
      } else {
      $google_secret_key = Db::name('system_user')->where(['id'=>session('user')['id']])->value('google_secret_key');
      if($google_secret_key == '') {
      $this->error("您未绑定谷歌身份验证器");
      }
      $captcha = $this->request->post('captcha_code', '', 'trim');
      $captchaClass = new Captcha();
      if(!$captchaClass->check($captcha)) {
      $this->error('图形验证码错误!');
      }
      $oneCode = $ga->getCode($google_secret_key);
      if($code != $oneCode) {
      $this->error("身份验证码错误");
      } else {
      session('google_auth', $oneCode);
      LogService::write('系统权限', '绑定谷歌身份验证器成功');
      $this->success("验证通过,正在进入系统...", '@admin');
      }
      }

      }
      }
      public function resetGoogle()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      if(sysconf('is_google_auth') == 0) {
      $this->error('系统未开启谷歌身份验证');
      }
      $mobile = session('user')['phone'];
      $google_auth = session('google_auth');
      if($google_auth) {
      $this->redirect('@admin');
      }
      if (!$this->request->isPost()) {
      if($mobile) {
      $mobile = substr($mobile, 0, 3).'****'.substr($mobile, 7);
      }
      $this->assign('mobile', $mobile);
      return view();
      } else {
      $code = input('sms_code');
      if($code == '') {
      $this->error('请输入验证码');
      }
      $sms=new Sms();
      if(!$sms->verifyCode($mobile, $code,'google_auth')){
      $this->error($sms->getError());
      }
      $re = Db::name('system_user')->where(['id'=>session('user')['id']])->update(['google_secret_key'=>'']);
      if(FALSE !== $re) {
      LogService::write('系统权限', '谷歌身份验证器验证通过');
      $this->success('验证通过,进入下一步...','admin/auth/google');
      } else {
      $this->error("重置失败");
      }
      }
      }

    //生成绑定谷歌身份验证器二维码(测试,部署生产环境时删除!)
    public function bindGoogle()
    {
    $id = input('id/d');
    if(!$id) {
    return false;
    }
    $ga = new \Util\Verify\PHPGangsta_GoogleAuthenticator();
    $google_secret_key = Db::name('system_user')->where(['id'=>$id])->value('google_secret_key');
    if(!$google_secret_key) {
    return false;
    }
    $qrCodeUrl = $ga->getQRCodeGoogleUrl(Request::instance()->domain(), $google_secret_key);
    echo '<img src="'.$qrCodeUrl.'"">';die;
    }

    /**

    • 发送短信验证码
      */
      public function sendSmsCode()
      {
      if (!session('user')) {
      $this->error('未登录');
      }
      $mobile=session('user')['phone'];
      if(!is_mobile_number($mobile)){
      $this->error('不是有效的号码!');
      }
      $sms=new Sms();
      $res=$sms->sendCode($mobile, 'google_auth');
      if($res===false){
      $this->error($sms->getError());
      }
      $this->success('已发送验证码,请注意查收!!');
      }
      }
收起阅读 »

UNIAPP前端工程师7000-10000

岗位职责:
1.根据工作安排高效、高质地完成代码编写,确保符合规范的前端代码规范;
2.负责公司项目的前端修改调试和开发工作,优化用户交互体验;
3.与设计团队紧密配合,能够实现实现设计师的设计想法;
4.与后端开发团队紧密配合,确保代码有效对接,优化页面前端性能。
任职要求:
1.大专及以上学历,有成熟微信小程序案例,微信公众平台开发项目优先;
2.熟悉各种Web客户端,尤其是主流Web浏览器的开发模式和特性;
3.精通HTML5/JavaScript/CSS3等Web开发技术,对性能优化有经验;
4.熟练微信小程序开发流程以及小程序相关API使用,熟悉微信平台接口及微信小程序功能研发;
5、熟练能用微信小程序的wmpf框架
6、熟练uniapp框架者;
7.具备工程化的前端思维,具备较好的问题分析与解决能力;
8.良好的代码编写习惯,有进取心、求知欲强烈、对工作充满热情!
工作地点:成都市郫都区创客公园
联系方式:可电子邮箱495881410@qq.com

继续阅读 »

岗位职责:
1.根据工作安排高效、高质地完成代码编写,确保符合规范的前端代码规范;
2.负责公司项目的前端修改调试和开发工作,优化用户交互体验;
3.与设计团队紧密配合,能够实现实现设计师的设计想法;
4.与后端开发团队紧密配合,确保代码有效对接,优化页面前端性能。
任职要求:
1.大专及以上学历,有成熟微信小程序案例,微信公众平台开发项目优先;
2.熟悉各种Web客户端,尤其是主流Web浏览器的开发模式和特性;
3.精通HTML5/JavaScript/CSS3等Web开发技术,对性能优化有经验;
4.熟练微信小程序开发流程以及小程序相关API使用,熟悉微信平台接口及微信小程序功能研发;
5、熟练能用微信小程序的wmpf框架
6、熟练uniapp框架者;
7.具备工程化的前端思维,具备较好的问题分析与解决能力;
8.良好的代码编写习惯,有进取心、求知欲强烈、对工作充满热情!
工作地点:成都市郫都区创客公园
联系方式:可电子邮箱495881410@qq.com

收起阅读 »

uniapp 显示 svga

注意hbuilder编译要v3

在manifest.json 文件下设置
"app-plus" : {
"compilerVersion" : 3,
}

具体内容在附件

注意hbuilder编译要v3

在manifest.json 文件下设置
"app-plus" : {
"compilerVersion" : 3,
}

具体内容在附件

uniCloud云数据库增删改查

uniCloud 技术分享

一个H5页面,让你看懂数据库增删改查。

演示网站《电户号查询系统》

写在最前面


我是自学前端的小白,所以只能演示基本的操作,关于复杂的连表增删改查,还没有研究过。 就以这个demo数据库为原型,完成查询、新增、修改、删除的基本操作示例。

1、查询,①在网站初始化时需要调用查询;②用户查询电户号时,需要调用查询;③新增或删除电户信息时,需要比对数据,也需要调用查询。
2、新增,分为①在demo下,再新增_id,并添加字段和值;②在指定_id下指定位置新增。
3、更新,分为①覆盖式更新;②在同一个_id下指定位置更新数据。
4、删除,分为①指定_id全部删除;②在指定_id下,指定位置删除数据。

在云函数写好之后,还需页面调用处理返回的数据,文末有示例。

一、准备云数据库

  • 云数据库有两个,'initial'和'demo',后面有展开数据演示。
  • 'initial',用于初始化页面。
  • 'demo',用于增删改查。

二、编写云函数

  • uniCloud数据库,允许在网页端直接使用uniCloud.callFunction函数调用数据库的数据。
    • 但是,建议使用云函数调用,这样数据更安全。</font>
    • 云函数的主流是路由——自动匹配对应的云函数去处理数据,我还不会,所以就写了五个云函数,在页面要用哪个就调用哪个。

2.1 云函数默认目录。

  • uniCloud/cloudfunctions/云函数名称/云函数名称.js

2.2 uniCloud数据库操作基于mongoDB,可以查询相关文档。

三、获取数据的云函数

await db.collection('demo').field({}).get();

3.1 初始化页面获取数据的方法

  • 初始化页面,需要调用的云数据库,名称initial,展开如下:
{  
    "_id":"603a0b27c9e7be00013b5e33",  
    "ArrList":["沙沟村","大东沟村","罗家坡村","小山岔村","渡口村","七家洼村"]  
}  
    ---------------华丽的---------分割线-------------  
{  
    "_id":"603a120b20be4e000120b8f6",  
    "groupArr": {  
        "0": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "1": ["一变","二变","三变"],  
        "2": ["一变","二变","三变","四变"],  
        "3": ["一变","二变","三变","四变","五变"]  
    --------后面-------还有------内容-------省略------  
    }  
}
  • 初始化云函数,名称也叫initial,代码如下:
  • get()获取的数据存放在data数组中,第一个_id的数据,就是data[0],第二个_id的数据,就是data[1]
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let [str] = event;  
    if(str ==='initial'){  
        let res = await db.collection('initial').field({_id:0,ArrList:1,'groupArr.0':1}).get();  
       //get()获取的数据存放在data数组中,第一个`_id`数据,就是data[0]        
        let cunList = res.data[0].ArrList;  
        //get()获取的数据存放在data数组中,第二个`_id`数据,就是data[1]  
        let zuList = res.data[1].groupArr[0];  
        //code的数字,只是为了前端if判断时好用,并没有什么实际意义。  
            return {  
                code:888,  
                msg:'初始化数据成功',  
                cunList,  
                zuList  
            }  
        }else{  
            return{  
                code:400,  
                msg:'您请求的数据格式有误'  
            }  
        }  
    }
  • 前端页面调用的代码,在onLoad生命周期内,将查询的数据赋值给两个数组,再渲染到页面中(两个列表中)。
  • 页面端调用的代码this.$api.HandleUnicloud(cloudName, mydata){res=>{}},如何而来,文末有详解
export default {  
    data() {  
        return {  
            cun_list: [],  
            zu_list: []  
            }  
        }     
    onLoad() {  
        let mydata = ['initial'];  
        let cloudName = 'initial';  
        this.$api.HandleUnicloud(cloudName, mydata).then(res => {  
            this.cun_list = res.cunList;  
            this.zu_list = res.zuList;  
        });  
    }  
}

3.2 <font color="red">★重点★</font> 查询返回指定字段的数据

  • 示例demo数据库,由六部分组成,每一个_id独立为一个单元。

  • 数据库展开

{  
    "_id":"603eeaa40daee300011f18f4",  
    "villages": {  
        "name": "沙沟村",  
        "id": 0,  
        "groupArr": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "group-1": [{"3102568889": "翟**"},{"3105360550": "李**"},{"3105360619": "马**"},..省略..],  
        "group-2": [{"3078734642": "刘**"},..省略..],  
        "group-3": [],  
        "group-4": [],  
        "group-6": []  
    }  
}  
  ------------华丽的-----------分割线------------------  
{  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "大东沟村",  
            "id": 1,  
            "groupArr": ["一变","二变","三变"]  
        }  
}  
  ------------华丽的-----------分割线----------------  
  {  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "XXX村",  
            "id": 2,  
            "groupArr": ["一变","二变","三变","四变"]  
        }  
}  
  -------后面----还有-----数据-----不再-----展示-----
  • field({}) ,可以返回指定字段的内容,必须使用get()方法才能获取到数据。1表示显示,没有标注的数据不显示。但是 _id是默认显示的。
  • field({'ArrList':1,_id:0})不显示_id,查询关于ArrList的信息,
  • field({'villages.group-2':1}) <font color="red">查询 villages 数组或对象内 group-2 的内容。
  • 与变量相结合的查询方式,有二种:
  • const groupNum = "group-3"; field({[`villages.${groupNum}`]:1})
  • const groupNum = "group-4"; field({['villages.'+ groupNum]:true})
'use strict';  
const db = uniCloud.database();  
exports.main = async (event, context) => {  
//event==mydata: { cunIndex: 0, groupName: 'group-1', userObj: { username: '', usernum: '' }, pageNum: 0, rowsNum: 10 }  
    let {cunIndex,groupName,userObj,pageNum,rowsNum} = event;  
    let resData = await db.collection('demo')  
    .field({_id:0,[`villages.${groupName}`]:1})  
    .get();  
    //resList等于当前村下的,当前变电组的,全部用户的信息  
    let resList = resData.data[`${cunIndex}`].villages[`${groupName}`];  

    //如果当前村的变电组不存在,或者变电组内没有数据时,调用  
    if(!resList||resList.length===0){  
        return {  
            code:400,  
            msg:'该村变电组内还未收录用户信息',  
        }  
    }  
    //这一段为翻页时调用  
    //请求的数据条数(rowsNum默认10条)  
    //pageNum当前点击的页码(由于是H5的原因默认是1)  
    let pageStarNum = (pageNum - 1) * rowsNum;  
    let pageEndNum = pageStarNum + rowsNum;  
    let pagesTotal = resList.length;  
    //pages表示返回的数据,在页面中总共要显示多少页  
    let pages = parseInt(pagesTotal/rowsNum);  
    //前端页面点击页码后,显示从第几条数据到第几条数据的列表  
    let resArr = resList.slice(pageStarNum,pageEndNum);  
    //resObj用于存放,数据库查找到的电户信息  
    let resObj = {};  
    //遍历当前变电组内所有的用户信息,当遍历的姓名与查询的姓名一致时  
    //把结果追加给resObj,使用合并对象的方法Object.assign(resObj,item)也行  
    resList.forEach(item=>{  
        if(Object.values(item)==userObj.username){  
            resObj = {...item}  
        }  
    })  
    //当用户没有输入姓名,直接查询,会获取全部列表  
    if(userObj.username===''){  
        return {  
            code:200,  
            msg:'当前查询的是:该变电组内所有用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,查询不到时调用  
    //返回当前村、变电组,全部列表数据  
    //pages是总页数  
    if(Object.keys(resObj).length===0){  
        return {  
            code:404,  
            msg:'抱歉!该变电组内未收录此用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,数据库中有时调用  
    //msg的信息可以使用模板字符串  
    return {  
        code:200,  
        msg:`「 ${userObj.username} 」的电户号,查询结果如下:`,  
        resObj  
    }  
}

四、新增数据的云函数

4.1 在原数据外,新增一个_id,add()

  • 新增单一数据,用大括号包裹数据 {"name": "张三"}
  • 新增多条数据,用中括号包裹数据[{"name": "张三"},{"name": "李四"},{"name": "王五"}]
const db = uniCloud.database();  
exports.main = async (event, context) => {  
    let resData = await db.collection('demo')  
    .add([{"name": "张三"},{"name": "李四"},{"name": "王五"}]);  
    let resList = await db.collection('demo').get();  
    return {  
        code:200,  
        msg:'添加数据成功',  
        resList  
    }  
};//数据返回结果  
{  
    "code": 200,  
    "msg": "添加数据成功",  
    "resList": {  
        "data": [{  
            "_id": "60210b53ef338d00016d2404",  
            ....此处 .... 省略 ....一万字....  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf4",  
        "name": "张三"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf5",  
        "name": "李四"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf6",  
        "name": "王五"  
        }  
    }]  
}

4.2 在指定_id内,指定位置新增。

  • doc('_id').update();方法可用于更改,也可用于新增。

  • 普通数组添加、删除数据,官方文档中有示例,这里演示的是,数据为对象的数组"group-1":[{key:value},{key:vlaue}]如何新增。

  • update(),需紧随doc()之后,doc()内写指定数据的_id,因为一个集合内可能有多个_id

  • update()内引用变量,需要使用[`${变量名}`]

  • 在数组尾部新增对象,可以在中括号内写模板字符串dbCmd.push([{...addUserObj}])

'use strict';  
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    if(userObj.username==''||userObj.usernum==''){  
        return{  
            code:400,  
            msg:'新增数据不能为空'  
        }  
    }  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    //用于获取_id,存放与data[{_id:***},{_id:***},{_id:***},***]中  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = true;  
    //先查询,用户要新增的电户号码,在数据库中,有没有,有就赋值false  
    if (groupArr) {  
            groupArr.forEach(val=>{  
                if(Object.keys(val)==userObj.usernum){  
                    isTrue = false;  
                }  
            });  
        //如果数据库中没有该电户号码,就在对应村、变电组的尾部新增该数据  
        if(isTrue){  
            let addUserObj = {[`${userObj.usernum}`]:userObj.username};  
            let resSucc = await db.collection('demo')  
                .doc(`${id}`)  
                .update({  
                    villages: {  
                        [`${groupName}`]: dbCmd.push([{...addUserObj}])  
                    }  
                })  
                return {  
                    code: 200,  
                    msg: '数据添加成功',  
                    resSucc  
                    }  
            //当数据库中有该电户号码时,就提示已经存在        
            }else{  
                return {  
                    code: 400,  
                    msg: `抱歉!电户号「 ${userObj.usernum} 」已经存在`  
                }  
            }  
        }  

    //如果该村还未创建该变电组,就新建变电组,之后再新增用户信息  
    if (!groupArr) {  
        let resSucc = await db.collection('demo')  
            .doc(`${id}`)  
            .update({  
                villages: {  
                    [`${groupName}`]: dbCmd.set([{  
                        [`${userObj.usernum}`]: userObj.username  
                    }])  
                }  
            })  
        return {  
            code: 200,  
            msg: '创建变电组成功,数据添加成功',  
            resSucc  
        }  
    }  
}

五、更新数据的云函数

5.1 覆盖式更新

  • 覆盖式更新的意义不大,会将原数据彻底清除,一般情况下用不到。
  • update({'villages':dbCmd.set({key:value})})将villages做为字段,后面跟一个对象
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let resSucc = await db.collection('demo')  
    .doc("600bfa4d7f06f30001b47259")  
    .update({  
        'villages':dbCmd.set({  
            "6640059601": "张三"  
        })  
      }  
    );  
    let resObj = await db.collection('demo').get();  
    return {  
        code:200,  
        resObj,  
        resSucc  
        }  
    }  
    //返回的数据结果 villages下只剩下一个对象了  
 "villages": {"6640059601":"张三"}

5.2 指定_id下,指定位置更新。

  • 指定位置更新,同上面的update()方法一致,这里省略。

六、删除数据的云函数

6.1 删除指定_id的数据库的全部数据

  • collection.doc(_id).remove()

  • doc()内只能写字符串或者数字,可以使用ES6模板字符串doc(`${id}`)

// 删除指定_id的数据  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
const id = '60388f7eb6ce210001cbbf14';  
    await db.collection('demo')  
    .doc(`${id}`)  
    .remove();  
    let resData = await db.collection('demo').get();  
    return resData;  
};

6.2 删除指定位置的数据

  • 在update()内使用remove(),方法挂载在command下,不能用于数组,删除后,数组原索引位置会变成null。但是可以用于对象,删除key就等于删除了该对象。doc(`${id}`).update({villages:{name:dbCmd.remove()}})
  • 更新数组,可以先获取数组,再修改数组,最后把新数组更新到原位置即可。update({villages:{[`${groupName}`]:[...groupArr]}})
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = false;  
    var index = 0;  
    if (!groupArr) {  
        return {  
            code: 400,  
            msg: '抱歉!该村还未创建此变电组数据',  
            resSucc  
        }  
    };  
    groupArr.forEach((val,i)=>{  
        if(Object.keys(val)==userObj.usernum){  
            isTrue = true;  
            index = i  
        }  
    });  

    //先查询数据在数组中的索引,使用splice,删除数据,把获得的新数组,更新到原位置处  
    if(isTrue){  
        groupArr.splice([`${index}`],1);  
        let resData = await db.collection('demo')  
        .doc(`${id}`)  
        .update({  
            villages:{  
                [`${groupName}`]:[...groupArr]  
            }  
        })  
        return {  
            code: 200,  
            msg: `「 ${userObj.usernum}  」数据删除成功`,  
            index,  
            groupArr,  
            resData  
        }  
    };  
    return {  
        code: 400,  
        msg: '数据删除失败,原因:电户号错误'  
    }  
}  

七、处理云函数返回数据的工具函数

  • 工具函数的路径 common/api/index.js
  • HandleUnicloud有两个参数,用于uniCloud.callFunction({name,data})传参。
  • cloudName表示,需要调用哪个云函数。
  • mydata表示,用户向云函数传递的数据。
const HandleUnicloud = (cloudName,mydata)=>{  
    return new Promise((reslove,reject)=>{  
        uniCloud.callFunction({  
            name:cloudName,  
            data:mydata  
        }).then(res=>{  
            if(res.result){  
                reslove(res.result)  
            }else{  
                reject(res.result)  
            }  
        }).catch(res=>{  
            console.log(res);  
            })  
    });  
};  
export default{  
    HandleUnicloud  
}

八、全局注册处理云函数数据的工具函数

  • 先引入import api from './common/api'
  • 再注册Vue.prototype.$api = api
import Vue from 'vue'  
import App from './App'  
import api from './common/api'  

Vue.config.productionTip = false  
Vue.prototype.$api = api  
App.mpType = 'app'  

const app = new Vue({  
    ...App  
})  
app.$mount()

九、页面调用的方法


this.$api.HandleUnicloud()

addData() {  
    //用户传给云函数的数据,赋值给mydata  
    let mydata = this.mydata;  
    //当前需要调用的云函数名称  
    let cloudName = 'UpdateAdd';  

    //用于检查姓名和电户号码的正则函数checkName()和checkNum()  
    if (!this.checkName(this.mydata.userObj.username) || !this.checkNum(this.mydata.userObj.usernum)) {  
        this.tip = '抱歉,姓名和电户号,数据有误!';  
        return;  
    }  
    //有确定和取消按键的模态框  
    uni.showModal({  
        title: '请选择',  
        content: `您确定要添加${mydata.userObj.username}吗?`,  
        cancelText:'取消添加',  
        confirmText:'确定添加',  
        //这里应当使用箭头函数,否则影响this.$api和this.tip的使用  
        success: res=> {  
            if (res.confirm) {  
                this.$api.HandleUnicloud(cloudName, mydata).then(v => {  
                    this.tip = v.msg;  
                        uni.showLoading({  
                            title: this.tip  
                        });  
                        setTimeout(() => {  
                            uni.hideLoading();  
                        }, 1000);  
                    });  
                } else if (res.cancel) {  
                    this.tip = '选择了取消!'  
                }  
            }  
        });  
    }

十、写在最后

非常感谢,DCloud公司提供如此强大的生态系统,让我们去学习进步的效率大大的提升。

最后附上H5白~嫖建站的最后一关,跨域配置问题,将前端网页托管——参数配置——默认网址,复制粘贴到跨域配置——新增域名中,即可手机,PC端都能正常访问了。

目前uniCloud</font>提供了,免费的阿里云空间,</font>完全可以满足个人用户的建站使用。
只需要在https://unicloud.dcloud.net.cn/login申请账号就可以获得:
1、一个免费的云数据库,用于保存JSON格式的数据
2、一个免费的存储云函数的空间,用于保存可以在云端调用修改云数据库数据的函数,空间环境为nodejs,操作基于mongoDB,有所改动。
3、一个免费的云存储,用于保存图片、视频、文件等,并能够提供对应的访问地址
4、一个免费的网页托管,自动生成可访问的网址,只需处理跨域配置即可。
个人博客地址

继续阅读 »

一个H5页面,让你看懂数据库增删改查。

演示网站《电户号查询系统》

写在最前面


我是自学前端的小白,所以只能演示基本的操作,关于复杂的连表增删改查,还没有研究过。 就以这个demo数据库为原型,完成查询、新增、修改、删除的基本操作示例。

1、查询,①在网站初始化时需要调用查询;②用户查询电户号时,需要调用查询;③新增或删除电户信息时,需要比对数据,也需要调用查询。
2、新增,分为①在demo下,再新增_id,并添加字段和值;②在指定_id下指定位置新增。
3、更新,分为①覆盖式更新;②在同一个_id下指定位置更新数据。
4、删除,分为①指定_id全部删除;②在指定_id下,指定位置删除数据。

在云函数写好之后,还需页面调用处理返回的数据,文末有示例。

一、准备云数据库

  • 云数据库有两个,'initial'和'demo',后面有展开数据演示。
  • 'initial',用于初始化页面。
  • 'demo',用于增删改查。

二、编写云函数

  • uniCloud数据库,允许在网页端直接使用uniCloud.callFunction函数调用数据库的数据。
    • 但是,建议使用云函数调用,这样数据更安全。</font>
    • 云函数的主流是路由——自动匹配对应的云函数去处理数据,我还不会,所以就写了五个云函数,在页面要用哪个就调用哪个。

2.1 云函数默认目录。

  • uniCloud/cloudfunctions/云函数名称/云函数名称.js

2.2 uniCloud数据库操作基于mongoDB,可以查询相关文档。

三、获取数据的云函数

await db.collection('demo').field({}).get();

3.1 初始化页面获取数据的方法

  • 初始化页面,需要调用的云数据库,名称initial,展开如下:
{  
    "_id":"603a0b27c9e7be00013b5e33",  
    "ArrList":["沙沟村","大东沟村","罗家坡村","小山岔村","渡口村","七家洼村"]  
}  
    ---------------华丽的---------分割线-------------  
{  
    "_id":"603a120b20be4e000120b8f6",  
    "groupArr": {  
        "0": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "1": ["一变","二变","三变"],  
        "2": ["一变","二变","三变","四变"],  
        "3": ["一变","二变","三变","四变","五变"]  
    --------后面-------还有------内容-------省略------  
    }  
}
  • 初始化云函数,名称也叫initial,代码如下:
  • get()获取的数据存放在data数组中,第一个_id的数据,就是data[0],第二个_id的数据,就是data[1]
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let [str] = event;  
    if(str ==='initial'){  
        let res = await db.collection('initial').field({_id:0,ArrList:1,'groupArr.0':1}).get();  
       //get()获取的数据存放在data数组中,第一个`_id`数据,就是data[0]        
        let cunList = res.data[0].ArrList;  
        //get()获取的数据存放在data数组中,第二个`_id`数据,就是data[1]  
        let zuList = res.data[1].groupArr[0];  
        //code的数字,只是为了前端if判断时好用,并没有什么实际意义。  
            return {  
                code:888,  
                msg:'初始化数据成功',  
                cunList,  
                zuList  
            }  
        }else{  
            return{  
                code:400,  
                msg:'您请求的数据格式有误'  
            }  
        }  
    }
  • 前端页面调用的代码,在onLoad生命周期内,将查询的数据赋值给两个数组,再渲染到页面中(两个列表中)。
  • 页面端调用的代码this.$api.HandleUnicloud(cloudName, mydata){res=>{}},如何而来,文末有详解
export default {  
    data() {  
        return {  
            cun_list: [],  
            zu_list: []  
            }  
        }     
    onLoad() {  
        let mydata = ['initial'];  
        let cloudName = 'initial';  
        this.$api.HandleUnicloud(cloudName, mydata).then(res => {  
            this.cun_list = res.cunList;  
            this.zu_list = res.zuList;  
        });  
    }  
}

3.2 <font color="red">★重点★</font> 查询返回指定字段的数据

  • 示例demo数据库,由六部分组成,每一个_id独立为一个单元。

  • 数据库展开

{  
    "_id":"603eeaa40daee300011f18f4",  
    "villages": {  
        "name": "沙沟村",  
        "id": 0,  
        "groupArr": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "group-1": [{"3102568889": "翟**"},{"3105360550": "李**"},{"3105360619": "马**"},..省略..],  
        "group-2": [{"3078734642": "刘**"},..省略..],  
        "group-3": [],  
        "group-4": [],  
        "group-6": []  
    }  
}  
  ------------华丽的-----------分割线------------------  
{  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "大东沟村",  
            "id": 1,  
            "groupArr": ["一变","二变","三变"]  
        }  
}  
  ------------华丽的-----------分割线----------------  
  {  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "XXX村",  
            "id": 2,  
            "groupArr": ["一变","二变","三变","四变"]  
        }  
}  
  -------后面----还有-----数据-----不再-----展示-----
  • field({}) ,可以返回指定字段的内容,必须使用get()方法才能获取到数据。1表示显示,没有标注的数据不显示。但是 _id是默认显示的。
  • field({'ArrList':1,_id:0})不显示_id,查询关于ArrList的信息,
  • field({'villages.group-2':1}) <font color="red">查询 villages 数组或对象内 group-2 的内容。
  • 与变量相结合的查询方式,有二种:
  • const groupNum = "group-3"; field({[`villages.${groupNum}`]:1})
  • const groupNum = "group-4"; field({['villages.'+ groupNum]:true})
'use strict';  
const db = uniCloud.database();  
exports.main = async (event, context) => {  
//event==mydata: { cunIndex: 0, groupName: 'group-1', userObj: { username: '', usernum: '' }, pageNum: 0, rowsNum: 10 }  
    let {cunIndex,groupName,userObj,pageNum,rowsNum} = event;  
    let resData = await db.collection('demo')  
    .field({_id:0,[`villages.${groupName}`]:1})  
    .get();  
    //resList等于当前村下的,当前变电组的,全部用户的信息  
    let resList = resData.data[`${cunIndex}`].villages[`${groupName}`];  

    //如果当前村的变电组不存在,或者变电组内没有数据时,调用  
    if(!resList||resList.length===0){  
        return {  
            code:400,  
            msg:'该村变电组内还未收录用户信息',  
        }  
    }  
    //这一段为翻页时调用  
    //请求的数据条数(rowsNum默认10条)  
    //pageNum当前点击的页码(由于是H5的原因默认是1)  
    let pageStarNum = (pageNum - 1) * rowsNum;  
    let pageEndNum = pageStarNum + rowsNum;  
    let pagesTotal = resList.length;  
    //pages表示返回的数据,在页面中总共要显示多少页  
    let pages = parseInt(pagesTotal/rowsNum);  
    //前端页面点击页码后,显示从第几条数据到第几条数据的列表  
    let resArr = resList.slice(pageStarNum,pageEndNum);  
    //resObj用于存放,数据库查找到的电户信息  
    let resObj = {};  
    //遍历当前变电组内所有的用户信息,当遍历的姓名与查询的姓名一致时  
    //把结果追加给resObj,使用合并对象的方法Object.assign(resObj,item)也行  
    resList.forEach(item=>{  
        if(Object.values(item)==userObj.username){  
            resObj = {...item}  
        }  
    })  
    //当用户没有输入姓名,直接查询,会获取全部列表  
    if(userObj.username===''){  
        return {  
            code:200,  
            msg:'当前查询的是:该变电组内所有用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,查询不到时调用  
    //返回当前村、变电组,全部列表数据  
    //pages是总页数  
    if(Object.keys(resObj).length===0){  
        return {  
            code:404,  
            msg:'抱歉!该变电组内未收录此用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,数据库中有时调用  
    //msg的信息可以使用模板字符串  
    return {  
        code:200,  
        msg:`「 ${userObj.username} 」的电户号,查询结果如下:`,  
        resObj  
    }  
}

四、新增数据的云函数

4.1 在原数据外,新增一个_id,add()

  • 新增单一数据,用大括号包裹数据 {"name": "张三"}
  • 新增多条数据,用中括号包裹数据[{"name": "张三"},{"name": "李四"},{"name": "王五"}]
const db = uniCloud.database();  
exports.main = async (event, context) => {  
    let resData = await db.collection('demo')  
    .add([{"name": "张三"},{"name": "李四"},{"name": "王五"}]);  
    let resList = await db.collection('demo').get();  
    return {  
        code:200,  
        msg:'添加数据成功',  
        resList  
    }  
};//数据返回结果  
{  
    "code": 200,  
    "msg": "添加数据成功",  
    "resList": {  
        "data": [{  
            "_id": "60210b53ef338d00016d2404",  
            ....此处 .... 省略 ....一万字....  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf4",  
        "name": "张三"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf5",  
        "name": "李四"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf6",  
        "name": "王五"  
        }  
    }]  
}

4.2 在指定_id内,指定位置新增。

  • doc('_id').update();方法可用于更改,也可用于新增。

  • 普通数组添加、删除数据,官方文档中有示例,这里演示的是,数据为对象的数组"group-1":[{key:value},{key:vlaue}]如何新增。

  • update(),需紧随doc()之后,doc()内写指定数据的_id,因为一个集合内可能有多个_id

  • update()内引用变量,需要使用[`${变量名}`]

  • 在数组尾部新增对象,可以在中括号内写模板字符串dbCmd.push([{...addUserObj}])

'use strict';  
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    if(userObj.username==''||userObj.usernum==''){  
        return{  
            code:400,  
            msg:'新增数据不能为空'  
        }  
    }  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    //用于获取_id,存放与data[{_id:***},{_id:***},{_id:***},***]中  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = true;  
    //先查询,用户要新增的电户号码,在数据库中,有没有,有就赋值false  
    if (groupArr) {  
            groupArr.forEach(val=>{  
                if(Object.keys(val)==userObj.usernum){  
                    isTrue = false;  
                }  
            });  
        //如果数据库中没有该电户号码,就在对应村、变电组的尾部新增该数据  
        if(isTrue){  
            let addUserObj = {[`${userObj.usernum}`]:userObj.username};  
            let resSucc = await db.collection('demo')  
                .doc(`${id}`)  
                .update({  
                    villages: {  
                        [`${groupName}`]: dbCmd.push([{...addUserObj}])  
                    }  
                })  
                return {  
                    code: 200,  
                    msg: '数据添加成功',  
                    resSucc  
                    }  
            //当数据库中有该电户号码时,就提示已经存在        
            }else{  
                return {  
                    code: 400,  
                    msg: `抱歉!电户号「 ${userObj.usernum} 」已经存在`  
                }  
            }  
        }  

    //如果该村还未创建该变电组,就新建变电组,之后再新增用户信息  
    if (!groupArr) {  
        let resSucc = await db.collection('demo')  
            .doc(`${id}`)  
            .update({  
                villages: {  
                    [`${groupName}`]: dbCmd.set([{  
                        [`${userObj.usernum}`]: userObj.username  
                    }])  
                }  
            })  
        return {  
            code: 200,  
            msg: '创建变电组成功,数据添加成功',  
            resSucc  
        }  
    }  
}

五、更新数据的云函数

5.1 覆盖式更新

  • 覆盖式更新的意义不大,会将原数据彻底清除,一般情况下用不到。
  • update({'villages':dbCmd.set({key:value})})将villages做为字段,后面跟一个对象
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let resSucc = await db.collection('demo')  
    .doc("600bfa4d7f06f30001b47259")  
    .update({  
        'villages':dbCmd.set({  
            "6640059601": "张三"  
        })  
      }  
    );  
    let resObj = await db.collection('demo').get();  
    return {  
        code:200,  
        resObj,  
        resSucc  
        }  
    }  
    //返回的数据结果 villages下只剩下一个对象了  
 "villages": {"6640059601":"张三"}

5.2 指定_id下,指定位置更新。

  • 指定位置更新,同上面的update()方法一致,这里省略。

六、删除数据的云函数

6.1 删除指定_id的数据库的全部数据

  • collection.doc(_id).remove()

  • doc()内只能写字符串或者数字,可以使用ES6模板字符串doc(`${id}`)

// 删除指定_id的数据  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
const id = '60388f7eb6ce210001cbbf14';  
    await db.collection('demo')  
    .doc(`${id}`)  
    .remove();  
    let resData = await db.collection('demo').get();  
    return resData;  
};

6.2 删除指定位置的数据

  • 在update()内使用remove(),方法挂载在command下,不能用于数组,删除后,数组原索引位置会变成null。但是可以用于对象,删除key就等于删除了该对象。doc(`${id}`).update({villages:{name:dbCmd.remove()}})
  • 更新数组,可以先获取数组,再修改数组,最后把新数组更新到原位置即可。update({villages:{[`${groupName}`]:[...groupArr]}})
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = false;  
    var index = 0;  
    if (!groupArr) {  
        return {  
            code: 400,  
            msg: '抱歉!该村还未创建此变电组数据',  
            resSucc  
        }  
    };  
    groupArr.forEach((val,i)=>{  
        if(Object.keys(val)==userObj.usernum){  
            isTrue = true;  
            index = i  
        }  
    });  

    //先查询数据在数组中的索引,使用splice,删除数据,把获得的新数组,更新到原位置处  
    if(isTrue){  
        groupArr.splice([`${index}`],1);  
        let resData = await db.collection('demo')  
        .doc(`${id}`)  
        .update({  
            villages:{  
                [`${groupName}`]:[...groupArr]  
            }  
        })  
        return {  
            code: 200,  
            msg: `「 ${userObj.usernum}  」数据删除成功`,  
            index,  
            groupArr,  
            resData  
        }  
    };  
    return {  
        code: 400,  
        msg: '数据删除失败,原因:电户号错误'  
    }  
}  

七、处理云函数返回数据的工具函数

  • 工具函数的路径 common/api/index.js
  • HandleUnicloud有两个参数,用于uniCloud.callFunction({name,data})传参。
  • cloudName表示,需要调用哪个云函数。
  • mydata表示,用户向云函数传递的数据。
const HandleUnicloud = (cloudName,mydata)=>{  
    return new Promise((reslove,reject)=>{  
        uniCloud.callFunction({  
            name:cloudName,  
            data:mydata  
        }).then(res=>{  
            if(res.result){  
                reslove(res.result)  
            }else{  
                reject(res.result)  
            }  
        }).catch(res=>{  
            console.log(res);  
            })  
    });  
};  
export default{  
    HandleUnicloud  
}

八、全局注册处理云函数数据的工具函数

  • 先引入import api from './common/api'
  • 再注册Vue.prototype.$api = api
import Vue from 'vue'  
import App from './App'  
import api from './common/api'  

Vue.config.productionTip = false  
Vue.prototype.$api = api  
App.mpType = 'app'  

const app = new Vue({  
    ...App  
})  
app.$mount()

九、页面调用的方法


this.$api.HandleUnicloud()

addData() {  
    //用户传给云函数的数据,赋值给mydata  
    let mydata = this.mydata;  
    //当前需要调用的云函数名称  
    let cloudName = 'UpdateAdd';  

    //用于检查姓名和电户号码的正则函数checkName()和checkNum()  
    if (!this.checkName(this.mydata.userObj.username) || !this.checkNum(this.mydata.userObj.usernum)) {  
        this.tip = '抱歉,姓名和电户号,数据有误!';  
        return;  
    }  
    //有确定和取消按键的模态框  
    uni.showModal({  
        title: '请选择',  
        content: `您确定要添加${mydata.userObj.username}吗?`,  
        cancelText:'取消添加',  
        confirmText:'确定添加',  
        //这里应当使用箭头函数,否则影响this.$api和this.tip的使用  
        success: res=> {  
            if (res.confirm) {  
                this.$api.HandleUnicloud(cloudName, mydata).then(v => {  
                    this.tip = v.msg;  
                        uni.showLoading({  
                            title: this.tip  
                        });  
                        setTimeout(() => {  
                            uni.hideLoading();  
                        }, 1000);  
                    });  
                } else if (res.cancel) {  
                    this.tip = '选择了取消!'  
                }  
            }  
        });  
    }

十、写在最后

非常感谢,DCloud公司提供如此强大的生态系统,让我们去学习进步的效率大大的提升。

最后附上H5白~嫖建站的最后一关,跨域配置问题,将前端网页托管——参数配置——默认网址,复制粘贴到跨域配置——新增域名中,即可手机,PC端都能正常访问了。

目前uniCloud</font>提供了,免费的阿里云空间,</font>完全可以满足个人用户的建站使用。
只需要在https://unicloud.dcloud.net.cn/login申请账号就可以获得:
1、一个免费的云数据库,用于保存JSON格式的数据
2、一个免费的存储云函数的空间,用于保存可以在云端调用修改云数据库数据的函数,空间环境为nodejs,操作基于mongoDB,有所改动。
3、一个免费的云存储,用于保存图片、视频、文件等,并能够提供对应的访问地址
4、一个免费的网页托管,自动生成可访问的网址,只需处理跨域配置即可。
个人博客地址

收起阅读 »