HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

最新IOSAPP下架原因汇总,找到源头

对于移动应用开发者来说, 最令人沮丧的可能莫过于辛辛苦苦开发的应用, 没能通过苹果AppStore的审核,或者在应用更新时遭遇下架。苹果的AppStore的审核流程和标准, 一向不透明, 而且申诉起来也非常的麻烦。给大家总结了App被苹果AppStore下架的各大原因。

  1. 中国大陆禁用 CallKit

  5 月中,部分开发者收到苹果 App 审核中心的邮件,被告知因工信部规定,在中国大陆地区上架的 App 不可以使用 Callkit,使用该功能的的产品将会不被过审,或下架。

  1. 需适配 iOS 11 与刘海屏

  苹果于 5 月通知开发者,任何提交到 App Store 的所有 iOS 应用必须使用 iOS SDK 构建,并且必须支持 iPhone X 的超级 Retina 屏。此规定将于 7 月生效,不改的话,你懂的…

  1. 热更新代码成下架隐患(JSPatch、Weex 和 React Native)

  17 年 3 月,众多开发者收到苹果邮件,内容为对含有热更新的 App 进行警告,要求移除相关代码。原因是一些黑客可能利用热更新修改 App,给用户带来安全隐患。

  1. GDPR 后数据安全成重点

  WWDC18 后,苹果审核指南更新,结合欧盟颁布的 GDPR 条款,对数据安全、数据收集与存储、数据使用与共享 3 个方面进行补充。

  1. 数字加密货币(区块链)

  苹果对数字加密货币的监管也在 WWDC18 后有所体现,如 App 不得挖掘加密货币;为首次发币、密码货币期货交易等提供便利的 App,必须来自经批准的金融机构,并遵守当地法律。

  1. 刷榜

  出现在不正当竞争当中,竞争对手帮着App刷榜掌握证据之后向苹果举报,很容易导致App被下架。

  1. 条款违规

  App中的内容违反苹果App Store条款,应用的功能涉及侵犯他人的隐私滥用隐私权限或者存在与宗教、法律相悖的内容,这些App被查出会被苹果第一时间下架。

  360产品曾经被苹果下架就有人爆料说是因为360违反了在没有事先征求用户许可的情况下为某些特定的功能,擅自收集用户电话号码等数据的行为。

  1. 与iOS自带功能冲突

  App的有些功能可能由于种种原因在审核时没有看出,但后来暴露出与苹果规定不符,在功能上与iOS自带应用产生竞争,那么苹果就会将你视为竞争对手,后面App的命运也就可想而知。在去年6月的时候,曾经有一款名为Display Recorder的录屏应用通过苹果审核上架,而这是一款与iOS自带截图功能冲突的录屏应用,在不久之后这款应用随即就被苹果下架。

  1. 描述与实际不符

  如果App的截图、功能、说明与实际有很大出入,挂羊头卖狗肉之流显然也是不被苹果允许的。

  1. 有Bug或者崩溃

  如果App存在明显的Bug或者经常崩溃而被用户大量投诉,这类App也是很容易就被下架的。在App的调试阶段一定要严格把关,同时适配上也不要理论上可行,一定要亲自在各系统版本中进行测试,确保描述中包括的所有版本下都能良好运行。

  在2011年的时候,Google Voice上线了一个新版本1.3.0.1771,但是不少用户投诉说遇到了程序崩溃等问题,因为Google Voice的这个Bug至少影响到了一部分用户,该版本的Google Voice随之被下架重新调整。

  1. 山寨、侵权

  如果App被投诉有明显的山寨模仿痕迹,或者在其它方面涉及侵犯他人合法权益,苹果在调查取证之后也会将相应的App作下架处理。在2012年11月份的时候,115网盘就被多家市场下架,主要原因是商标侵权。因115商标并非由115网盘开发商广东五科技有限公司所有,在收到115注册商标权利人发出的删除115侵权软件公函后,苹果将115应用从App Store中下架。

  1. 采用“Beta”或者其他可能让苹果认为你的应用还未开发完成的名称

  由于Google的很多产品采用“Beta”来发布, IT业内也有一种把最终产品命名加上“Beta”的潮流。 而苹果对此非常严格。任何带有类似字眼的产品会被认为尚未完成。 我们就见到过不少如“Beta版”,“预览版”或者“Version 0.9”的产品没能通过AppStore审核

  1. 加载时间过长

  所有的移动操作系统(iOS, Android甚至Windows),都对应用的最大加载时间又限制。 对iOS来说, 大约是15秒,如果你的应用在15秒内未能启动, 操作系统就会杀进程。

  即便你的应用在这段时间内启动了,网络连接速度, 硬件等环境的不同, 也可能导致你的应用在审核期间加载时间过长。 因此, 不要仅仅依赖于iOS的模拟器,一定要在真实网络和真实硬件环境下进行测试, 而且最好保留一些旧版的手机以确保所有用户都能体验到相对较快的加载速度。

  1. 链接到第三方支付系统

  苹果要求所有的数字内容都要在通过iTunes内置的应用内购买来完成。 包括一次性购买或者注册付费等方式。 如果你的应用提供其他的购买方式, 你的应用肯定会被下架。这也就是为什么Kindle的应用不让用户直接从应用购买新书的原因。

  甚至对应用通过网页提供第三方支付链接也不行。 Dropbox的应用被苹果拒绝就是一个例子。 Dropbox的应用在登录界面提供了一个购买更多存储空间的链接而未能通过苹果的审核。这不仅仅对Dropbox的App有影响, 甚至对所有采用Dropbox API的应用都有影响。

  因此,一定要好好检查一下你的应用开发流程, 确保所有的数字内容的购买都是通过用户的iTunes账户完成的。 注意, 苹果只对数字内容才做出此限制,这也就是为什么一些旅游应用能够通过App预订酒店和机票的原因。

  1. 不要提对其他平台的支持

  不光是苹果。没有那个市场愿意你提到竞争对手名字的。 因此, 如果你的应用已经在Android上或者Windows上跑了, 在你自己的网站上说吧, 不要在App的描述里提。

  1. 本地化的一些问题

  你的App用户可能来自世界各地, 即便你不提供多语言版本, 在应用内购买的时候把日元符号写成欧元也表明你是一个不成熟的开发者。

  因此,要利用类似 asNSNumberFormatter或Invariant Culture这样的组件以及模拟器来测试在不同地区下的用户体验, 确保如日期之类的格式符合用户本地的格式要求。

  我们曾经见过一个欧洲的应用开发商的应用,因为没有正确处理负的经纬度而被苹果AppStore拒绝(注:苹果总部的经度是 -122.03)。 因此, 一定要好好检查你的应用在地图上任何经纬度都能跑。 特别要注意经过本初子午线的正负经度变化以及经过赤道正负纬度变化。

  1. 对存储和文件系统的不正确使用

  在iOS5.1推出后, 苹果曾经下架了一款应用的升级因为开发者把一个2MB大小的数据库从应用备份到了文件系统,违反了iCloud关于只备份用户产生内容的规定。

  对任何静态的或者应用自带的或者很容易从远程服务器下载的所谓“可再生的数据”都不需要备份。 对于非用户数据, 可以选择缓存位置或者选择“不需要备份”属性。

  1. 在用户拒绝权限请求时崩溃

  在iOS6, 用户对试图访问地址本, 照片集, 地理位置, 日历, 提醒, 蓝牙, Twitter和Facebook账户的应用, 必须提升权限申请。 如果用户拒绝应用的权限申请, 苹果要求App依然能够继续工作。

  这一点在审核时会自动测试,如果不能正常工作, 则会被自动拒绝。 因此, 一定要仔细测试应用使用数据时的所有的“允许”“拒绝”组合, 同时也包括用户开始允许权限后来又拒绝的情况。

  1. 对图标和按钮的不正确使用

  很多iOS App被拒绝不是因为性能或者功能的原因, 仅仅就是因为一些小的UI方面的问题。开发者要确保应用在采用内置的苹果的图标和按钮时在外观和功能上一致性。 可以采用UIButtonBarSystemItem来进行测试。另外, 要熟悉苹果的“人机交互指南”

  比如说,除了创建新内容, 你不能用苹果的“Compose” 图标代表任何其他的用途。苹果的工程师希望App的行为尽量可预测。 因此对内置图标和按钮的使用方面格外严格。

  1. 商标和Logo的错误使用

  在你的应用的图像上,不要使用他人的商标或者苹果图标。 也不要使用带有iPhone图样的图标。 我们见过在关键字中含有商标被拒绝的例子。

  另一方面,你的应用还需要在内置地图中明确属性信息(比如Google地图或者诺基亚的地图)等, 否则也会被拒绝。

  当然, 如果你的应用被拒绝了或者下架了, 也不要着急, 找出问题来再次提交就是了。 此外, 苹果还提供一种紧急审核的机制, 用来进行重要Bug或者安全问题的修复。 不过, 开发者如果过度使用紧急审核机制, 可能会在今后被禁止使用。

当然最好还是争取一次就通过审核。 所以,最根本的当然是, 开发者仔细阅读苹果的《提交指南》并且提供高质量的应用。有问题可以随时找我解决VX18064099649

继续阅读 »

对于移动应用开发者来说, 最令人沮丧的可能莫过于辛辛苦苦开发的应用, 没能通过苹果AppStore的审核,或者在应用更新时遭遇下架。苹果的AppStore的审核流程和标准, 一向不透明, 而且申诉起来也非常的麻烦。给大家总结了App被苹果AppStore下架的各大原因。

  1. 中国大陆禁用 CallKit

  5 月中,部分开发者收到苹果 App 审核中心的邮件,被告知因工信部规定,在中国大陆地区上架的 App 不可以使用 Callkit,使用该功能的的产品将会不被过审,或下架。

  1. 需适配 iOS 11 与刘海屏

  苹果于 5 月通知开发者,任何提交到 App Store 的所有 iOS 应用必须使用 iOS SDK 构建,并且必须支持 iPhone X 的超级 Retina 屏。此规定将于 7 月生效,不改的话,你懂的…

  1. 热更新代码成下架隐患(JSPatch、Weex 和 React Native)

  17 年 3 月,众多开发者收到苹果邮件,内容为对含有热更新的 App 进行警告,要求移除相关代码。原因是一些黑客可能利用热更新修改 App,给用户带来安全隐患。

  1. GDPR 后数据安全成重点

  WWDC18 后,苹果审核指南更新,结合欧盟颁布的 GDPR 条款,对数据安全、数据收集与存储、数据使用与共享 3 个方面进行补充。

  1. 数字加密货币(区块链)

  苹果对数字加密货币的监管也在 WWDC18 后有所体现,如 App 不得挖掘加密货币;为首次发币、密码货币期货交易等提供便利的 App,必须来自经批准的金融机构,并遵守当地法律。

  1. 刷榜

  出现在不正当竞争当中,竞争对手帮着App刷榜掌握证据之后向苹果举报,很容易导致App被下架。

  1. 条款违规

  App中的内容违反苹果App Store条款,应用的功能涉及侵犯他人的隐私滥用隐私权限或者存在与宗教、法律相悖的内容,这些App被查出会被苹果第一时间下架。

  360产品曾经被苹果下架就有人爆料说是因为360违反了在没有事先征求用户许可的情况下为某些特定的功能,擅自收集用户电话号码等数据的行为。

  1. 与iOS自带功能冲突

  App的有些功能可能由于种种原因在审核时没有看出,但后来暴露出与苹果规定不符,在功能上与iOS自带应用产生竞争,那么苹果就会将你视为竞争对手,后面App的命运也就可想而知。在去年6月的时候,曾经有一款名为Display Recorder的录屏应用通过苹果审核上架,而这是一款与iOS自带截图功能冲突的录屏应用,在不久之后这款应用随即就被苹果下架。

  1. 描述与实际不符

  如果App的截图、功能、说明与实际有很大出入,挂羊头卖狗肉之流显然也是不被苹果允许的。

  1. 有Bug或者崩溃

  如果App存在明显的Bug或者经常崩溃而被用户大量投诉,这类App也是很容易就被下架的。在App的调试阶段一定要严格把关,同时适配上也不要理论上可行,一定要亲自在各系统版本中进行测试,确保描述中包括的所有版本下都能良好运行。

  在2011年的时候,Google Voice上线了一个新版本1.3.0.1771,但是不少用户投诉说遇到了程序崩溃等问题,因为Google Voice的这个Bug至少影响到了一部分用户,该版本的Google Voice随之被下架重新调整。

  1. 山寨、侵权

  如果App被投诉有明显的山寨模仿痕迹,或者在其它方面涉及侵犯他人合法权益,苹果在调查取证之后也会将相应的App作下架处理。在2012年11月份的时候,115网盘就被多家市场下架,主要原因是商标侵权。因115商标并非由115网盘开发商广东五科技有限公司所有,在收到115注册商标权利人发出的删除115侵权软件公函后,苹果将115应用从App Store中下架。

  1. 采用“Beta”或者其他可能让苹果认为你的应用还未开发完成的名称

  由于Google的很多产品采用“Beta”来发布, IT业内也有一种把最终产品命名加上“Beta”的潮流。 而苹果对此非常严格。任何带有类似字眼的产品会被认为尚未完成。 我们就见到过不少如“Beta版”,“预览版”或者“Version 0.9”的产品没能通过AppStore审核

  1. 加载时间过长

  所有的移动操作系统(iOS, Android甚至Windows),都对应用的最大加载时间又限制。 对iOS来说, 大约是15秒,如果你的应用在15秒内未能启动, 操作系统就会杀进程。

  即便你的应用在这段时间内启动了,网络连接速度, 硬件等环境的不同, 也可能导致你的应用在审核期间加载时间过长。 因此, 不要仅仅依赖于iOS的模拟器,一定要在真实网络和真实硬件环境下进行测试, 而且最好保留一些旧版的手机以确保所有用户都能体验到相对较快的加载速度。

  1. 链接到第三方支付系统

  苹果要求所有的数字内容都要在通过iTunes内置的应用内购买来完成。 包括一次性购买或者注册付费等方式。 如果你的应用提供其他的购买方式, 你的应用肯定会被下架。这也就是为什么Kindle的应用不让用户直接从应用购买新书的原因。

  甚至对应用通过网页提供第三方支付链接也不行。 Dropbox的应用被苹果拒绝就是一个例子。 Dropbox的应用在登录界面提供了一个购买更多存储空间的链接而未能通过苹果的审核。这不仅仅对Dropbox的App有影响, 甚至对所有采用Dropbox API的应用都有影响。

  因此,一定要好好检查一下你的应用开发流程, 确保所有的数字内容的购买都是通过用户的iTunes账户完成的。 注意, 苹果只对数字内容才做出此限制,这也就是为什么一些旅游应用能够通过App预订酒店和机票的原因。

  1. 不要提对其他平台的支持

  不光是苹果。没有那个市场愿意你提到竞争对手名字的。 因此, 如果你的应用已经在Android上或者Windows上跑了, 在你自己的网站上说吧, 不要在App的描述里提。

  1. 本地化的一些问题

  你的App用户可能来自世界各地, 即便你不提供多语言版本, 在应用内购买的时候把日元符号写成欧元也表明你是一个不成熟的开发者。

  因此,要利用类似 asNSNumberFormatter或Invariant Culture这样的组件以及模拟器来测试在不同地区下的用户体验, 确保如日期之类的格式符合用户本地的格式要求。

  我们曾经见过一个欧洲的应用开发商的应用,因为没有正确处理负的经纬度而被苹果AppStore拒绝(注:苹果总部的经度是 -122.03)。 因此, 一定要好好检查你的应用在地图上任何经纬度都能跑。 特别要注意经过本初子午线的正负经度变化以及经过赤道正负纬度变化。

  1. 对存储和文件系统的不正确使用

  在iOS5.1推出后, 苹果曾经下架了一款应用的升级因为开发者把一个2MB大小的数据库从应用备份到了文件系统,违反了iCloud关于只备份用户产生内容的规定。

  对任何静态的或者应用自带的或者很容易从远程服务器下载的所谓“可再生的数据”都不需要备份。 对于非用户数据, 可以选择缓存位置或者选择“不需要备份”属性。

  1. 在用户拒绝权限请求时崩溃

  在iOS6, 用户对试图访问地址本, 照片集, 地理位置, 日历, 提醒, 蓝牙, Twitter和Facebook账户的应用, 必须提升权限申请。 如果用户拒绝应用的权限申请, 苹果要求App依然能够继续工作。

  这一点在审核时会自动测试,如果不能正常工作, 则会被自动拒绝。 因此, 一定要仔细测试应用使用数据时的所有的“允许”“拒绝”组合, 同时也包括用户开始允许权限后来又拒绝的情况。

  1. 对图标和按钮的不正确使用

  很多iOS App被拒绝不是因为性能或者功能的原因, 仅仅就是因为一些小的UI方面的问题。开发者要确保应用在采用内置的苹果的图标和按钮时在外观和功能上一致性。 可以采用UIButtonBarSystemItem来进行测试。另外, 要熟悉苹果的“人机交互指南”

  比如说,除了创建新内容, 你不能用苹果的“Compose” 图标代表任何其他的用途。苹果的工程师希望App的行为尽量可预测。 因此对内置图标和按钮的使用方面格外严格。

  1. 商标和Logo的错误使用

  在你的应用的图像上,不要使用他人的商标或者苹果图标。 也不要使用带有iPhone图样的图标。 我们见过在关键字中含有商标被拒绝的例子。

  另一方面,你的应用还需要在内置地图中明确属性信息(比如Google地图或者诺基亚的地图)等, 否则也会被拒绝。

  当然, 如果你的应用被拒绝了或者下架了, 也不要着急, 找出问题来再次提交就是了。 此外, 苹果还提供一种紧急审核的机制, 用来进行重要Bug或者安全问题的修复。 不过, 开发者如果过度使用紧急审核机制, 可能会在今后被禁止使用。

当然最好还是争取一次就通过审核。 所以,最根本的当然是, 开发者仔细阅读苹果的《提交指南》并且提供高质量的应用。有问题可以随时找我解决VX18064099649

收起阅读 »

关于TopTalk开发团队使用UniApp开发的一些规范协议

关于团队Uni项目开发的一些协议(持续完善中...):

1、长度、大小单位均使用rpx;
2、关于命名:

文件名、方法名、变量等名称命名一律使用英文,太长可缩减至前两个英文单词。

  • 包名全部小写
  • 变量名、方法名首字母小写,如果名称由多个单词组成,首单词小写其余单词的首字母都需大写

3、css样式语言的lang属性设置为scss,如

<style lang="scss">

4、组件引入遇到多页面引入时,需配置到main.js页面中,vue页面即无需再次引入;
5、本地js演示数据一律配置到main.js页面中;
注:main.js 为项目的配置文件。封装方法、js、vue插件、公用常量、服务地址均配置到此文件
6、涉及到单模块页面分包可纳入同一包下,不要层级包嵌套!规范示例如下:

7、减少深层的节点嵌套,避免在页面初始化构建造成内存占用;
8、减少 scroll-view 组件的 scroll 事件监听;
9、尽可能或完全避免在template里直接写view 的style样式!

注:进阶链接
uniMPSDK文档
高效开发技巧
HBuilderX - 高效极客技巧
manifest.json 全概述
uni调用原生的API

继续阅读 »

关于团队Uni项目开发的一些协议(持续完善中...):

1、长度、大小单位均使用rpx;
2、关于命名:

文件名、方法名、变量等名称命名一律使用英文,太长可缩减至前两个英文单词。

  • 包名全部小写
  • 变量名、方法名首字母小写,如果名称由多个单词组成,首单词小写其余单词的首字母都需大写

3、css样式语言的lang属性设置为scss,如

<style lang="scss">

4、组件引入遇到多页面引入时,需配置到main.js页面中,vue页面即无需再次引入;
5、本地js演示数据一律配置到main.js页面中;
注:main.js 为项目的配置文件。封装方法、js、vue插件、公用常量、服务地址均配置到此文件
6、涉及到单模块页面分包可纳入同一包下,不要层级包嵌套!规范示例如下:

7、减少深层的节点嵌套,避免在页面初始化构建造成内存占用;
8、减少 scroll-view 组件的 scroll 事件监听;
9、尽可能或完全避免在template里直接写view 的style样式!

注:进阶链接
uniMPSDK文档
高效开发技巧
HBuilderX - 高效极客技巧
manifest.json 全概述
uni调用原生的API

收起阅读 »

Hbuilder 多显示下一直有这个问题

HBuilder

[内容]

如附件所示,计算机中安装了三台显示器,

显示器1为4K,分辨率3840x2106 缩放:150%
显示器2为2K,分辨率1920x2160 缩放:150%
显示器3为2K,分辨率1920x2160 缩放:150%

[步骤]
当IDE从显示器1拖到显示器2,或者显示器3之后。

[结果]
无法再拖回去,IDE顶部不响应拖动事件,整个UI窗口无法拖动

[期望]

[如果语言难以表述清晰,拍一个视频或截图,有图有真相]

IDE运行环境说明

[HBuilder 或 HBuilderX。如果你用其他工具开发uni-app,也需要在此说明]

[IDE版本号]
2.6.16.20200424

[windows版本号]
Windows 10专业版

继续阅读 »

[内容]

如附件所示,计算机中安装了三台显示器,

显示器1为4K,分辨率3840x2106 缩放:150%
显示器2为2K,分辨率1920x2160 缩放:150%
显示器3为2K,分辨率1920x2160 缩放:150%

[步骤]
当IDE从显示器1拖到显示器2,或者显示器3之后。

[结果]
无法再拖回去,IDE顶部不响应拖动事件,整个UI窗口无法拖动

[期望]

[如果语言难以表述清晰,拍一个视频或截图,有图有真相]

IDE运行环境说明

[HBuilder 或 HBuilderX。如果你用其他工具开发uni-app,也需要在此说明]

[IDE版本号]
2.6.16.20200424

[windows版本号]
Windows 10专业版

收起阅读 »

小团队开发uniapp、uniapp定制开发

uniapp

uniapp定制开发
uniapp所需资料都是那些?
1.功能需求沟通,前期明确需求可以确定工期和报价;
2.UI设计图确认

  1. 前端搭建
  2. 后台搭建
  3. 填写内容上线
  4. 上线测试
  5. 158-3211-5099

uniapp定制开发
uniapp所需资料都是那些?
1.功能需求沟通,前期明确需求可以确定工期和报价;
2.UI设计图确认

  1. 前端搭建
  2. 后台搭建
  3. 填写内容上线
  4. 上线测试
  5. 158-3211-5099

HTML5+表单新增、删除、预览、上传图片

图片预览
第一种方法:表单提交,使用jquery的Ajax  
<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">    
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover" />  
        <meta name="apple-mobile-web-app-capable" content="yes" />  
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />  
    </head>  
    <body>  
        <style>  
            .preview ul {  
                margin: 0;  
                padding: 0;  
            }  
            .preview ul li {  
                position: relative;  
                display: inline-block;  
                margin-top: 10px;  
                margin-bottom: 10px;  
                margin-right: 10px;  
                float: left;  
                list-style: none;  
            }  
            .preview ul li img {  
                width: 50px;  
                height: 50px;  
                border-radius: 5px;  
            }  
            .preview ul li input {  
                display: inline-block;  
                position: absolute;  
                width: 50px;  
                height: 50px;  
                left: 0;  
                top: 0;  
                opacity: 0;  
            }  
            .del {  
                display: inline-block;  
                position: absolute;  
                top:6px;  
                right: 0px;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                line-height: 0;  
                font-size: 0;  
                vertical-align: middle;  
                -webkit-transform: rotate(45deg);  
            }  
            .del:after {  
                content: "/";  
                display: block;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                -webkit-transform: rotate(-90deg);  
            }  
        </style>  
    <header class="mui-bar mui-bar-nav" >  
        <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
        <div class="mui-title">图片预览上传</div>  
    </header>  
    <div class="mui-content" >  
        <form id='from1' enctype = "multipart/form-data">  
            <div style="margin-top: 16px;margin-bottom: 10px;">  
                <span class="title">添加照片(选填)</span>  
                <span id="picnum" style="float: right;margin-right: 20px;font-size: 12px; color: #666666;">0/4</span>  
            </div>  
            <div class="preview" style="background-color: #ffffff;height: 70px;width: 100%;padding-left: 15px;padding-right: 15px;">  
                <ul class="row mui-input-row">  
                    <li>  
                        <input id="file"  type="file" name="upload" accept="image/*"  
                               onchange="setImagePreviews();"  multiple="true" />  
                        <img src="../images/adddd.png"/>  
                    </li>  
                </ul>  
            </div>  
            <div style="margin-top: 16px;width: 100%;text-align: center;">  
                <button style="background-color: #169BD5;height: 40px;width: 266px;font-size: 14px;color: #FFFFFF;border-radius: 5px;border: 0px;" type="button" onclick="trans()">提交</button>  
            </div>  
        </form>  
    </div>  

    </body>  
<script src="../js/mui.min.js"></script>  
<script src="../js/jquery.min.js"></script>  
<script type="text/javascript">  
    mui.init({  
        swipeBack:true //启用右滑关闭功能  
        });  
    function submit(){  
        var formData = new FormData();  
        formData.append('name',name);  
        if(uploadfile.length>0){  
            for(var i=0;i<uploadfile.length;i++){  
                formData.append("upload", uploadfile[i]); // 文件对象  
            }  
        }  
        var url= ;  
        jQuery.ajax({  
          url: url,  
          type: 'post',  
          async: false,  
          contentType:false,  
          processData: false,  
          data:formData,  
          xhrFields: {  
            withCredentials: true  
          },  
          crossDomain: true,  
          success: function (data) {  
            console.log(JSON.stringify(data));  
            mui.toast("提交成功!",{ duration:'500', type:'div' });  
          },  
          error: function (error) {  
            console.log(JSON.stringify(error));  
            mui.toast('页面出错',{ duration:'500', type:'div' });  
          }  
        });  
    }  
    var uploadfile = [];  
    function setImagePreviews() {  
        var docObj = document.getElementById("file");  
        var piclength = uploadfile.length;  
        var fileList = docObj.files;  
        if((Number(piclength) + Number(fileList.length)) > 4) {  
            plus.nativeUI.alert('最多上传四张');  
        } else {  
            document.getElementById("picnum").innerText=Number(piclength) + Number(fileList.length)+'/4';  
            for(var i = 0; i < fileList.length; i++) {  
                uploadfile.push(docObj.files[i]);  
                var picid = Number(piclength) + Number(i);  
                var reader = new FileReader();  
                reader.readAsDataURL(docObj.files[i]);                      
                reader.onload = function(e) {  
                // 图片base64化  
                var newUrl = this.result;  
                $(".preview ul").prepend("<li onclick='delImg(this)'><img src='" + newUrl + "' /><span class='del'></span></li>");  
                };  

            }  
        }  
    }  
    function delImg(obj){  
        var list =document.getElementsByTagName('li');  
        for(var i=0;i<list.length;i++){  
            list[i].index=i;  
        }  
        var idx=2-obj.index;  
        var ul=obj.parentNode;  
        var btnArray=['是','否'];  
        plus.nativeUI.confirm("确定要删除此图?",function(e){  
            if(e.index==0){  
                ul.removeChild(obj);  
                uploadfile.splice(idx,1);  
                document.getElementById("picnum").innerText=Number(uploadfile.length)+'/4';  
            }  
        },{"buttons":btnArray})  
    }  
</script>  
</html>  
第二种:使用plus.uploader  

<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">    
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover" />  
        <meta name="apple-mobile-web-app-capable" content="yes" />  
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />  
    </head>  
    <body>  
        <style>  
            .dynamic_images ul {  
                margin: 0;  
                padding: 0;  
            }  
            .dynamic_images ul li {  
                position: relative;  
                display: inline-block;  
                margin-top: 10px;  
                margin-bottom: 10px;  
                margin-right: 10px;  
                float: left;  
                list-style: none;  
            }  
            .dynamic_images ul li img {  
                width: 50px;  
                height: 50px;  
                border-radius: 5px;  
            }  
            .del {  
                display: inline-block;  
                position: absolute;  
                top:6px;  
                right: 0px;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                line-height: 0;  
                font-size: 0;  
                vertical-align: middle;  
                -webkit-transform: rotate(45deg);  
            }  
            .del:after {  
                content: "/";  
                display: block;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                -webkit-transform: rotate(-90deg);  
            }  
        </style>  
    <header class="mui-bar mui-bar-nav" >  
        <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
        <div class="mui-title">图片预览上传</div>  
    </header>  
    <div class="mui-content" >  
        <form id='from1' enctype = "multipart/form-data">  
            <div style="margin-top: 16px;margin-bottom: 10px;">  
                <span class="title">添加照片(选填)</span>  
                <span id="picnum" style="float: right;margin-right: 20px;font-size: 12px; color: #666666;">0/4</span>  
            </div>  
            <div class="dynamic_images" style="background-color: #ffffff;height: 70px;width: 100%;padding-left: 15px;padding-right: 15px;">  
                <ul class="row mui-input-row">  
                    <li>  
                        <img src="../images/adddd.png" id="addnew" onclick="showActionSheet();" />  
                    </li>  
                </ul>  
            </div>  
            <div style="margin-top: 16px;width: 100%;text-align: center;">  
                <button style="background-color: #169BD5;height: 40px;width: 266px;font-size: 14px;color: #FFFFFF;border-radius: 5px;border: 0px;" type="button" onclick="submit()">提交</button>  
            </div>  
        </form>  
    </div>  
    </body>  
<script src="../js/mui.min.js"></script>  
<script src="../js/jquery.min.js"></script>  
<script type="text/javascript">  
    mui.init({  
        swipeBack:true //启用右滑关闭功能  
        });  

    function submit(){  
        var url= ;  
        var task = plus.uploader.createUpload( url,   
            { method:"POST",blocksize:204800,priority:100 },  
            function ( t, status ) {  
                // 上传完成  
                if ( status == 200 ) {   
                    wt.close();  
                    console.log( "Upload success: " + JSON.stringify(t));  
                } else {  
                    wt.close();  
                    console.log( "Upload failed: " + JSON.stringify(status));  
                }  
            });  
            for(var i = 0; i < files.length; i++) {    
                var f = files[i];    
                task.addFile(f.path,{  
                    key: f.name,  
                    name:'upload',  
                });  
            }  
            task.addData('name',name);  
            task.start();  
    }  

    var files = [];  
    // 添加文件  
    var index = 1;  
    var newUrlAfterCompress;  
    function appendFile(p) {  
        files.push({  
            name: "uploadkey" + index,//这个值服务器会用到,作为file的key  
            path: p  
        });  
        index++;  
    }  
    function showActionSheet() {  
        if($(".dynamic_images ul li").length<5){  
            var bts = [{  
                title: "拍照"  
            }, {  
                title: "从相册选择"  
            }];  
            plus.nativeUI.actionSheet({  
                    cancel: "取消",  
                    buttons: bts  
                },  
            function(e) {  
                    if (e.index == 1) {  
                        getImage();  
                    } else if (e.index == 2) {  
                        galleryImgs();  
                    }  
                }  
            );  
        }else{  
            plus.nativeUI.alert('最多上传四张图片!');  
        }  
    }  
    // 产生一个随机数  
    function getUid() {  
        return Math.floor(Math.random() * 100000000 + 10000000).toString();  
    }  
    //拍照  
    function getImage() {  
        var cmr = plus.camera.getCamera();  
        cmr.captureImage(function(p) {  
            plus.io.resolveLocalFileSystemURL(p, function(entry) {  
                var localurl = entry.toLocalURL(); //  
                $(".dynamic_images ul").prepend("<li onclick='delImg(this)'><img src='" + localurl + "' /><span class='del'></span></li>");  
                var dstname="_downloads/"+getUid()+".png";//设置压缩后图片的路径  
                newUrlAfterCompress=compressImage(localurl,dstname);  
                appendFile(dstname);  
                document.getElementById("picnum").innerText=files.length+'/4';  
            });  
        });  
    }  
    function galleryImgs() {  
        // 从相册中选择图片  
        var num=4;  
        if(5-$(".dynamic_images ul li").length>=1){  
            num=5-$(".dynamic_images ul li").length;  
        }  
        plus.gallery.pick(function(e) {  
            for (var i = 0; i < e.files.length; i++) {  
                $(".dynamic_images ul").prepend(  
                    "<li  onclick='delImg(this)'><img  src='" + e.files[i] + "'/><span class='del'></span></li>");  
                    var dstname="_downloads/"+getUid()+".png";//设置压缩后图片的路径  
                    newUrlAfterCompress=compressImage(e.files[i],dstname);  
                    appendFile(dstname);  
            }  
            document.getElementById("picnum").innerText=files.length+'/4';  
        }, function(e) {   
            console.log("取消选择图片");  
        }, {  
            filter: "image",  
            multiple: true,  
            maximum:num,  
            system:false,  
            onmaxed:function(){  
                plus.nativeUI.alert('最多只能选择四张图片');  
            }  
        });  
    }  
    //压缩图片,这个比较变态的方法,无法return  
    function compressImage(src,dstname) {  
        //兼容  
        if (0 != src.toString().indexOf("file://")) {  
            src = "file://" + src;  
        }  
        plus.zip.compressImage({  
                src: src,  
                dst: dstname,  
                overwrite:true,  
                quality: 5  
            },  
            function(event) {  
                //console.log("Compress success:"+event.target);  
                return event.target;  
            },  
            function(error) {  
                console.log(error);  
                return src;  
            });  

    }  
     function delImg(obj)  
     {  
        var list =document.getElementsByTagName('li');  
        for(var i=0;i<list.length;i++){  
            list[i].index=i;  
        }  
        var idx=2-obj.index;  
        var ul=obj.parentNode;  
        var btnArray=['是','否'];  
        plus.nativeUI.confirm("确定要删除此图?",function(e){  
            if(e.index==0){  
                ul.removeChild(obj);  
                files.splice(idx,1);  
                document.getElementById("picnum").innerText=Number(files.length)+'/4';  
            }  
        },{"buttons":btnArray})  
     }  
</script>  
</html>  
继续阅读 »
第一种方法:表单提交,使用jquery的Ajax  
<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">    
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover" />  
        <meta name="apple-mobile-web-app-capable" content="yes" />  
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />  
    </head>  
    <body>  
        <style>  
            .preview ul {  
                margin: 0;  
                padding: 0;  
            }  
            .preview ul li {  
                position: relative;  
                display: inline-block;  
                margin-top: 10px;  
                margin-bottom: 10px;  
                margin-right: 10px;  
                float: left;  
                list-style: none;  
            }  
            .preview ul li img {  
                width: 50px;  
                height: 50px;  
                border-radius: 5px;  
            }  
            .preview ul li input {  
                display: inline-block;  
                position: absolute;  
                width: 50px;  
                height: 50px;  
                left: 0;  
                top: 0;  
                opacity: 0;  
            }  
            .del {  
                display: inline-block;  
                position: absolute;  
                top:6px;  
                right: 0px;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                line-height: 0;  
                font-size: 0;  
                vertical-align: middle;  
                -webkit-transform: rotate(45deg);  
            }  
            .del:after {  
                content: "/";  
                display: block;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                -webkit-transform: rotate(-90deg);  
            }  
        </style>  
    <header class="mui-bar mui-bar-nav" >  
        <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
        <div class="mui-title">图片预览上传</div>  
    </header>  
    <div class="mui-content" >  
        <form id='from1' enctype = "multipart/form-data">  
            <div style="margin-top: 16px;margin-bottom: 10px;">  
                <span class="title">添加照片(选填)</span>  
                <span id="picnum" style="float: right;margin-right: 20px;font-size: 12px; color: #666666;">0/4</span>  
            </div>  
            <div class="preview" style="background-color: #ffffff;height: 70px;width: 100%;padding-left: 15px;padding-right: 15px;">  
                <ul class="row mui-input-row">  
                    <li>  
                        <input id="file"  type="file" name="upload" accept="image/*"  
                               onchange="setImagePreviews();"  multiple="true" />  
                        <img src="../images/adddd.png"/>  
                    </li>  
                </ul>  
            </div>  
            <div style="margin-top: 16px;width: 100%;text-align: center;">  
                <button style="background-color: #169BD5;height: 40px;width: 266px;font-size: 14px;color: #FFFFFF;border-radius: 5px;border: 0px;" type="button" onclick="trans()">提交</button>  
            </div>  
        </form>  
    </div>  

    </body>  
<script src="../js/mui.min.js"></script>  
<script src="../js/jquery.min.js"></script>  
<script type="text/javascript">  
    mui.init({  
        swipeBack:true //启用右滑关闭功能  
        });  
    function submit(){  
        var formData = new FormData();  
        formData.append('name',name);  
        if(uploadfile.length>0){  
            for(var i=0;i<uploadfile.length;i++){  
                formData.append("upload", uploadfile[i]); // 文件对象  
            }  
        }  
        var url= ;  
        jQuery.ajax({  
          url: url,  
          type: 'post',  
          async: false,  
          contentType:false,  
          processData: false,  
          data:formData,  
          xhrFields: {  
            withCredentials: true  
          },  
          crossDomain: true,  
          success: function (data) {  
            console.log(JSON.stringify(data));  
            mui.toast("提交成功!",{ duration:'500', type:'div' });  
          },  
          error: function (error) {  
            console.log(JSON.stringify(error));  
            mui.toast('页面出错',{ duration:'500', type:'div' });  
          }  
        });  
    }  
    var uploadfile = [];  
    function setImagePreviews() {  
        var docObj = document.getElementById("file");  
        var piclength = uploadfile.length;  
        var fileList = docObj.files;  
        if((Number(piclength) + Number(fileList.length)) > 4) {  
            plus.nativeUI.alert('最多上传四张');  
        } else {  
            document.getElementById("picnum").innerText=Number(piclength) + Number(fileList.length)+'/4';  
            for(var i = 0; i < fileList.length; i++) {  
                uploadfile.push(docObj.files[i]);  
                var picid = Number(piclength) + Number(i);  
                var reader = new FileReader();  
                reader.readAsDataURL(docObj.files[i]);                      
                reader.onload = function(e) {  
                // 图片base64化  
                var newUrl = this.result;  
                $(".preview ul").prepend("<li onclick='delImg(this)'><img src='" + newUrl + "' /><span class='del'></span></li>");  
                };  

            }  
        }  
    }  
    function delImg(obj){  
        var list =document.getElementsByTagName('li');  
        for(var i=0;i<list.length;i++){  
            list[i].index=i;  
        }  
        var idx=2-obj.index;  
        var ul=obj.parentNode;  
        var btnArray=['是','否'];  
        plus.nativeUI.confirm("确定要删除此图?",function(e){  
            if(e.index==0){  
                ul.removeChild(obj);  
                uploadfile.splice(idx,1);  
                document.getElementById("picnum").innerText=Number(uploadfile.length)+'/4';  
            }  
        },{"buttons":btnArray})  
    }  
</script>  
</html>  
第二种:使用plus.uploader  

<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">    
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover" />  
        <meta name="apple-mobile-web-app-capable" content="yes" />  
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />  
    </head>  
    <body>  
        <style>  
            .dynamic_images ul {  
                margin: 0;  
                padding: 0;  
            }  
            .dynamic_images ul li {  
                position: relative;  
                display: inline-block;  
                margin-top: 10px;  
                margin-bottom: 10px;  
                margin-right: 10px;  
                float: left;  
                list-style: none;  
            }  
            .dynamic_images ul li img {  
                width: 50px;  
                height: 50px;  
                border-radius: 5px;  
            }  
            .del {  
                display: inline-block;  
                position: absolute;  
                top:6px;  
                right: 0px;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                line-height: 0;  
                font-size: 0;  
                vertical-align: middle;  
                -webkit-transform: rotate(45deg);  
            }  
            .del:after {  
                content: "/";  
                display: block;  
                width: 12px;  
                height: 2px;  
                background: #ED544D;  
                -webkit-transform: rotate(-90deg);  
            }  
        </style>  
    <header class="mui-bar mui-bar-nav" >  
        <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
        <div class="mui-title">图片预览上传</div>  
    </header>  
    <div class="mui-content" >  
        <form id='from1' enctype = "multipart/form-data">  
            <div style="margin-top: 16px;margin-bottom: 10px;">  
                <span class="title">添加照片(选填)</span>  
                <span id="picnum" style="float: right;margin-right: 20px;font-size: 12px; color: #666666;">0/4</span>  
            </div>  
            <div class="dynamic_images" style="background-color: #ffffff;height: 70px;width: 100%;padding-left: 15px;padding-right: 15px;">  
                <ul class="row mui-input-row">  
                    <li>  
                        <img src="../images/adddd.png" id="addnew" onclick="showActionSheet();" />  
                    </li>  
                </ul>  
            </div>  
            <div style="margin-top: 16px;width: 100%;text-align: center;">  
                <button style="background-color: #169BD5;height: 40px;width: 266px;font-size: 14px;color: #FFFFFF;border-radius: 5px;border: 0px;" type="button" onclick="submit()">提交</button>  
            </div>  
        </form>  
    </div>  
    </body>  
<script src="../js/mui.min.js"></script>  
<script src="../js/jquery.min.js"></script>  
<script type="text/javascript">  
    mui.init({  
        swipeBack:true //启用右滑关闭功能  
        });  

    function submit(){  
        var url= ;  
        var task = plus.uploader.createUpload( url,   
            { method:"POST",blocksize:204800,priority:100 },  
            function ( t, status ) {  
                // 上传完成  
                if ( status == 200 ) {   
                    wt.close();  
                    console.log( "Upload success: " + JSON.stringify(t));  
                } else {  
                    wt.close();  
                    console.log( "Upload failed: " + JSON.stringify(status));  
                }  
            });  
            for(var i = 0; i < files.length; i++) {    
                var f = files[i];    
                task.addFile(f.path,{  
                    key: f.name,  
                    name:'upload',  
                });  
            }  
            task.addData('name',name);  
            task.start();  
    }  

    var files = [];  
    // 添加文件  
    var index = 1;  
    var newUrlAfterCompress;  
    function appendFile(p) {  
        files.push({  
            name: "uploadkey" + index,//这个值服务器会用到,作为file的key  
            path: p  
        });  
        index++;  
    }  
    function showActionSheet() {  
        if($(".dynamic_images ul li").length<5){  
            var bts = [{  
                title: "拍照"  
            }, {  
                title: "从相册选择"  
            }];  
            plus.nativeUI.actionSheet({  
                    cancel: "取消",  
                    buttons: bts  
                },  
            function(e) {  
                    if (e.index == 1) {  
                        getImage();  
                    } else if (e.index == 2) {  
                        galleryImgs();  
                    }  
                }  
            );  
        }else{  
            plus.nativeUI.alert('最多上传四张图片!');  
        }  
    }  
    // 产生一个随机数  
    function getUid() {  
        return Math.floor(Math.random() * 100000000 + 10000000).toString();  
    }  
    //拍照  
    function getImage() {  
        var cmr = plus.camera.getCamera();  
        cmr.captureImage(function(p) {  
            plus.io.resolveLocalFileSystemURL(p, function(entry) {  
                var localurl = entry.toLocalURL(); //  
                $(".dynamic_images ul").prepend("<li onclick='delImg(this)'><img src='" + localurl + "' /><span class='del'></span></li>");  
                var dstname="_downloads/"+getUid()+".png";//设置压缩后图片的路径  
                newUrlAfterCompress=compressImage(localurl,dstname);  
                appendFile(dstname);  
                document.getElementById("picnum").innerText=files.length+'/4';  
            });  
        });  
    }  
    function galleryImgs() {  
        // 从相册中选择图片  
        var num=4;  
        if(5-$(".dynamic_images ul li").length>=1){  
            num=5-$(".dynamic_images ul li").length;  
        }  
        plus.gallery.pick(function(e) {  
            for (var i = 0; i < e.files.length; i++) {  
                $(".dynamic_images ul").prepend(  
                    "<li  onclick='delImg(this)'><img  src='" + e.files[i] + "'/><span class='del'></span></li>");  
                    var dstname="_downloads/"+getUid()+".png";//设置压缩后图片的路径  
                    newUrlAfterCompress=compressImage(e.files[i],dstname);  
                    appendFile(dstname);  
            }  
            document.getElementById("picnum").innerText=files.length+'/4';  
        }, function(e) {   
            console.log("取消选择图片");  
        }, {  
            filter: "image",  
            multiple: true,  
            maximum:num,  
            system:false,  
            onmaxed:function(){  
                plus.nativeUI.alert('最多只能选择四张图片');  
            }  
        });  
    }  
    //压缩图片,这个比较变态的方法,无法return  
    function compressImage(src,dstname) {  
        //兼容  
        if (0 != src.toString().indexOf("file://")) {  
            src = "file://" + src;  
        }  
        plus.zip.compressImage({  
                src: src,  
                dst: dstname,  
                overwrite:true,  
                quality: 5  
            },  
            function(event) {  
                //console.log("Compress success:"+event.target);  
                return event.target;  
            },  
            function(error) {  
                console.log(error);  
                return src;  
            });  

    }  
     function delImg(obj)  
     {  
        var list =document.getElementsByTagName('li');  
        for(var i=0;i<list.length;i++){  
            list[i].index=i;  
        }  
        var idx=2-obj.index;  
        var ul=obj.parentNode;  
        var btnArray=['是','否'];  
        plus.nativeUI.confirm("确定要删除此图?",function(e){  
            if(e.index==0){  
                ul.removeChild(obj);  
                files.splice(idx,1);  
                document.getElementById("picnum").innerText=Number(files.length)+'/4';  
            }  
        },{"buttons":btnArray})  
     }  
</script>  
</html>  
收起阅读 »

现在uni-app感觉很沉寂啊,很不活跃

uniapp

uni-app现在用的人还多吗?感觉没什么人用了啊

uni-app现在用的人还多吗?感觉没什么人用了啊

uniAPP定制开发、uniapp团队开发

uniapp模板 uniapp

定制的APP
  APP开发定制是根据客户需求来进行开发,打造一款全新的APP软件,下面具体说说比较重要的几点。
  1、APP功能定位
  想要定制一款app首先一点要知道自己需要哪些功能,然后就是定位(人群、领域)要确认,把这两个部分确立好以后就围绕自己的需求来开展APP的开发。这也是定制开发APP的第一步,只有在明确了自己的需求以后才可以开发出一款自己想要的APP。
  2、细化功能需求
  一定要清楚明白的将自己的功能需求表达清楚,尽量细化功能。说的越清楚制作的就越全面,app的开发也就越精细。不过我们钰威软件的团队会提供专业的产品经理和策划人员来帮助客户对功能需求进行完善。前期功能细化说的越清楚对后续APP开发也会越顺利。
  3、开发团队的选择
  定制一款APP当然需要找到一家可靠技术过硬的软件开发公司,例如钰威软件。如何判断一个团队是否有足够的能力来开发完善一款APP,需要通过app开发的安全性、APP开发周期、APP开发交付、APP开发后的售后服务等几个方面来考虑。一个正规且完善的开发团队会具备产品经理、策划、工程师、项目经理、iOS程序员、Android程序员、后端程序员和测试等人员。团队技术过硬,人才储备完善都是对APP开发的保障。当然还有一点,无论是前期的APP开发还是后期的APP维护都是很重要的内容。
158-3211-5099

继续阅读 »

定制的APP
  APP开发定制是根据客户需求来进行开发,打造一款全新的APP软件,下面具体说说比较重要的几点。
  1、APP功能定位
  想要定制一款app首先一点要知道自己需要哪些功能,然后就是定位(人群、领域)要确认,把这两个部分确立好以后就围绕自己的需求来开展APP的开发。这也是定制开发APP的第一步,只有在明确了自己的需求以后才可以开发出一款自己想要的APP。
  2、细化功能需求
  一定要清楚明白的将自己的功能需求表达清楚,尽量细化功能。说的越清楚制作的就越全面,app的开发也就越精细。不过我们钰威软件的团队会提供专业的产品经理和策划人员来帮助客户对功能需求进行完善。前期功能细化说的越清楚对后续APP开发也会越顺利。
  3、开发团队的选择
  定制一款APP当然需要找到一家可靠技术过硬的软件开发公司,例如钰威软件。如何判断一个团队是否有足够的能力来开发完善一款APP,需要通过app开发的安全性、APP开发周期、APP开发交付、APP开发后的售后服务等几个方面来考虑。一个正规且完善的开发团队会具备产品经理、策划、工程师、项目经理、iOS程序员、Android程序员、后端程序员和测试等人员。团队技术过硬,人才储备完善都是对APP开发的保障。当然还有一点,无论是前期的APP开发还是后期的APP维护都是很重要的内容。
158-3211-5099

收起阅读 »

【不看手册硬刚踩坑系列1】微信模拟器白屏事件

*写的啰嗦,着急的朋友直接看最后一行问题解决办法就行

序言

一直是5+的簇拥,三天打鱼两天晒网的摆弄着移动端开发。从uniapp诞生之日就一直关注,但考虑到新框架“坑”会很多,再结合5+时期官方的反应速度,一直处于观望态度。
最近有个微信开发小项目,想起uniapp官方各种横向对比中牛逼的一塌糊涂,就更新了hbuilderX,和微信开发者工具。提刀上阵。
不喜欢看手册,本着有坑采坑没坑记录的心态,出个系列,给自己也给“后浪”一个参考和话题。

正文

本着硬刚的心态,开起hbuilderX,新建项目,找个官方项目hello uniapp,按下新建按钮,建立了第一个uniapp项目。点开运行菜单,比起5+时代有牌面了很多!什么微信,百度,头条,支付宝都给了模拟器。本鸟是要做微信项目,自然点微信,自然也是直接进坑。

1,安全端口
点开微信开发者工具运行后,直接卡住,得益于HbuilderX的人性化提示,得知,要想调用微信开发者工具,要安全端口。按说明,打勾,check!过了~

2,白屏
顺利启动开发者工具,正自鸣得意,直接入坑。白屏,妥妥的loading。可能我这2019老mbp不行了?等等看,刷了n多网页回来看,还是loading。。。,慌了,这尼玛是什么情况,看提示,【检查是否启动多个微信开发者工具,如果是则关闭所有打开的微信开发者工具,然后再重新运行】,启动了多个?看了下微信开发者工具,没有多个!
按照5+时代的尿性,那第一时间是回娘家登录账号,进社区搜索,白屏,一片关键字检索结果,没有我能用的。。。。。。。

  • 祭出百度搜索大发,竟然无从下手,无果。
  • 祭出5+app开发绝技!关hbuilder,关开发者工具,重新运行,依然无果!
  • 祭出乱试三板斧,重开个colorUI,按下运行->微信开发者工具,喵的一声,好用了!

见了鬼了,再试hello uninapp 不好用!依然不好用,继续百度,发现行踪,开发者工具论坛有人反映,项目名中文的就会白屏,一看现象一样,赶紧看我的manifest是不是中文,hello uni-app整整齐齐的摆在那,没有中文。。。。。不甘心啊,看看colorUI的项目名,colorUI,没毛病都是英文!

灵光突然一闪,hello uni-app? 这个空格是什么鬼??改成hello_uni-app,运行->微信开发者工具,夸嚓!好用,轻松跑起来。

总结:遇到白屏不要慌,知道掉坑里,就赶紧想办法,不抛弃不放弃,总会出坑。

【微信开发者工具白屏解决办法】检查项目名是否中文或含有空格!

继续阅读 »

*写的啰嗦,着急的朋友直接看最后一行问题解决办法就行

序言

一直是5+的簇拥,三天打鱼两天晒网的摆弄着移动端开发。从uniapp诞生之日就一直关注,但考虑到新框架“坑”会很多,再结合5+时期官方的反应速度,一直处于观望态度。
最近有个微信开发小项目,想起uniapp官方各种横向对比中牛逼的一塌糊涂,就更新了hbuilderX,和微信开发者工具。提刀上阵。
不喜欢看手册,本着有坑采坑没坑记录的心态,出个系列,给自己也给“后浪”一个参考和话题。

正文

本着硬刚的心态,开起hbuilderX,新建项目,找个官方项目hello uniapp,按下新建按钮,建立了第一个uniapp项目。点开运行菜单,比起5+时代有牌面了很多!什么微信,百度,头条,支付宝都给了模拟器。本鸟是要做微信项目,自然点微信,自然也是直接进坑。

1,安全端口
点开微信开发者工具运行后,直接卡住,得益于HbuilderX的人性化提示,得知,要想调用微信开发者工具,要安全端口。按说明,打勾,check!过了~

2,白屏
顺利启动开发者工具,正自鸣得意,直接入坑。白屏,妥妥的loading。可能我这2019老mbp不行了?等等看,刷了n多网页回来看,还是loading。。。,慌了,这尼玛是什么情况,看提示,【检查是否启动多个微信开发者工具,如果是则关闭所有打开的微信开发者工具,然后再重新运行】,启动了多个?看了下微信开发者工具,没有多个!
按照5+时代的尿性,那第一时间是回娘家登录账号,进社区搜索,白屏,一片关键字检索结果,没有我能用的。。。。。。。

  • 祭出百度搜索大发,竟然无从下手,无果。
  • 祭出5+app开发绝技!关hbuilder,关开发者工具,重新运行,依然无果!
  • 祭出乱试三板斧,重开个colorUI,按下运行->微信开发者工具,喵的一声,好用了!

见了鬼了,再试hello uninapp 不好用!依然不好用,继续百度,发现行踪,开发者工具论坛有人反映,项目名中文的就会白屏,一看现象一样,赶紧看我的manifest是不是中文,hello uni-app整整齐齐的摆在那,没有中文。。。。。不甘心啊,看看colorUI的项目名,colorUI,没毛病都是英文!

灵光突然一闪,hello uni-app? 这个空格是什么鬼??改成hello_uni-app,运行->微信开发者工具,夸嚓!好用,轻松跑起来。

总结:遇到白屏不要慌,知道掉坑里,就赶紧想办法,不抛弃不放弃,总会出坑。

【微信开发者工具白屏解决办法】检查项目名是否中文或含有空格!

收起阅读 »

运行到真机失败 报Module build failed怎么解决

[HBuilder] 20:25:37.837 Module build failed (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js):
[HBuilder] 20:25:37.837 TypeError: Cannot read property 'value' of undefined
[HBuilder] 20:25:37.842 at genVModel (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\uni-template-compiler\lib\app\service.js:186:78)
[HBuilder] 20:25:37.842 at Array.genData (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\uni-template-compiler\lib\app\service.js:196:3)
[HBuilder] 20:25:37.848 at genData$3 (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4167:32)
[HBuilder] 20:25:37.849 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4011:16)
[HBuilder] 20:25:37.855 at genNode (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4423:12)
[HBuilder] 20:25:37.856 at G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:55
[HBuilder] 20:25:37.861 at Array.map (<anonymous>)
[HBuilder] 20:25:37.861 at genChildren (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:29)
[HBuilder] 20:25:37.866 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4014:49)
[HBuilder] 20:25:37.867 at genFor (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4134:42)
[HBuilder] 20:25:37.872 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:3996:12)
[HBuilder] 20:25:37.873 at genChildren (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4380:50)
[HBuilder] 20:25:37.879 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4014:49)
[HBuilder] 20:25:37.880 at genNode (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4423:12)
[HBuilder] 20:25:37.885 at G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:55
[HBuilder] 20:25:37.885 at Array.map (<anonymous>)
[HBuilder] 20:25:37.891 ERROR Build failed with errors.

继续阅读 »

[HBuilder] 20:25:37.837 Module build failed (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js):
[HBuilder] 20:25:37.837 TypeError: Cannot read property 'value' of undefined
[HBuilder] 20:25:37.842 at genVModel (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\uni-template-compiler\lib\app\service.js:186:78)
[HBuilder] 20:25:37.842 at Array.genData (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\uni-template-compiler\lib\app\service.js:196:3)
[HBuilder] 20:25:37.848 at genData$3 (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4167:32)
[HBuilder] 20:25:37.849 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4011:16)
[HBuilder] 20:25:37.855 at genNode (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4423:12)
[HBuilder] 20:25:37.856 at G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:55
[HBuilder] 20:25:37.861 at Array.map (<anonymous>)
[HBuilder] 20:25:37.861 at genChildren (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:29)
[HBuilder] 20:25:37.866 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4014:49)
[HBuilder] 20:25:37.867 at genFor (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4134:42)
[HBuilder] 20:25:37.872 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:3996:12)
[HBuilder] 20:25:37.873 at genChildren (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4380:50)
[HBuilder] 20:25:37.879 at genElement (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4014:49)
[HBuilder] 20:25:37.880 at genNode (G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4423:12)
[HBuilder] 20:25:37.885 at G:\测试4\fenrunduo_uni\node_modules\@dcloudio\vue-cli-plugin-uni\packages\vue-template-compiler\build.js:4386:55
[HBuilder] 20:25:37.885 at Array.map (<anonymous>)
[HBuilder] 20:25:37.891 ERROR Build failed with errors.

收起阅读 »

pc端H5和微信内置浏览器的都可以用的一个小demo

应朋友要求,给他写了一个小项目。大家分享一下。

她的需求是可以在pc端和微信内浏览器都可以登录。然后可以在线进行劳动风险评测这么一个软件,在线收费。管理员可以查看统计。还需要在线下载。
因微信内不让下载,所以也没什么特别的好办法,只能跳转。不知道哪个大神能给个解决方案。在android和ios都已经测试了。

不足地方,欢迎大家留言批评指正。
你可以用手机微信扫码二维码测试,

登录二维码

pc端登录 入口pc端点击登录

继续阅读 »

应朋友要求,给他写了一个小项目。大家分享一下。

她的需求是可以在pc端和微信内浏览器都可以登录。然后可以在线进行劳动风险评测这么一个软件,在线收费。管理员可以查看统计。还需要在线下载。
因微信内不让下载,所以也没什么特别的好办法,只能跳转。不知道哪个大神能给个解决方案。在android和ios都已经测试了。

不足地方,欢迎大家留言批评指正。
你可以用手机微信扫码二维码测试,

登录二维码

pc端登录 入口pc端点击登录

收起阅读 »

uni.css样式详解

uniapp

类使用说明
1.uni-padding-wrap:宽度690rpx 左右内边距30rpx ,相当于690/750=92%的宽度。可用于外层包裹

2.单页头,标题和正文
uni-page-head:
uni-page-head-title:
uni-page-body:超出范围隐藏
这三个类的效果

  1. uni-word:上下内边距200rpx 左右100rpx。

过长效果,用在什么地方呢?。

4.uni-title:30rpx行高1.5
uni-title text:24rpx 灰色
可用作正负标题<view class="uni-title">uni-title<text>uni-title text</text></view>

  1. uni-text-gray 灰色#ccc;
  2. uni-text-small 24rpx号字

7.uni-common-mb,uni-common-pb,uni-common-pl,uni-common-mt
上面的common代表通用,后面的第一个字母m代表margin,p代表padding。b代表底部,l代表left,t代表top 他们的距离都是30rpx
.uni-common-mb{
margin-bottom:30rpx;
}
表示uni通用底部外边距30rpx;

8.背景色三个
uni-bg-red,uni-bg-green,uni-bg-blue

9h1-h6效果图

  1. uni-bold 加粗

  2. uni-ellipsis 文本溢出
    不自动换行,文本溢出时显示省略号。

12.uni-btn-v
/ 竖向百分百按钮 /
.uni-btn-v{
padding:10rpx 0;
}
.uni-btn-v button{margin:20rpx 0;}
没明白作者什么意思。

13.表单(from)
uni-form-item 宽度100% 弹性布局,上下内间距10rpx 左右0

附加带有预览效果图。后面的类还没看完。看完再传一遍。

继续阅读 »

类使用说明
1.uni-padding-wrap:宽度690rpx 左右内边距30rpx ,相当于690/750=92%的宽度。可用于外层包裹

2.单页头,标题和正文
uni-page-head:
uni-page-head-title:
uni-page-body:超出范围隐藏
这三个类的效果

  1. uni-word:上下内边距200rpx 左右100rpx。

过长效果,用在什么地方呢?。

4.uni-title:30rpx行高1.5
uni-title text:24rpx 灰色
可用作正负标题<view class="uni-title">uni-title<text>uni-title text</text></view>

  1. uni-text-gray 灰色#ccc;
  2. uni-text-small 24rpx号字

7.uni-common-mb,uni-common-pb,uni-common-pl,uni-common-mt
上面的common代表通用,后面的第一个字母m代表margin,p代表padding。b代表底部,l代表left,t代表top 他们的距离都是30rpx
.uni-common-mb{
margin-bottom:30rpx;
}
表示uni通用底部外边距30rpx;

8.背景色三个
uni-bg-red,uni-bg-green,uni-bg-blue

9h1-h6效果图

  1. uni-bold 加粗

  2. uni-ellipsis 文本溢出
    不自动换行,文本溢出时显示省略号。

12.uni-btn-v
/ 竖向百分百按钮 /
.uni-btn-v{
padding:10rpx 0;
}
.uni-btn-v button{margin:20rpx 0;}
没明白作者什么意思。

13.表单(from)
uni-form-item 宽度100% 弹性布局,上下内间距10rpx 左右0

附加带有预览效果图。后面的类还没看完。看完再传一遍。

收起阅读 »

希望文件搜索和编辑器内容搜索分开。

如题:希望文件搜索和编辑器内容搜索分开。
1)希望在项目管理器中增加搜索框,用来搜索文件。
2)在编辑器窗口新增搜索框,专门搜索编辑器代码内容和替换。

如题:希望文件搜索和编辑器内容搜索分开。
1)希望在项目管理器中增加搜索框,用来搜索文件。
2)在编辑器窗口新增搜索框,专门搜索编辑器代码内容和替换。