用uniCloud开发了一个性格测试小程序,已经完美发布

简介: 最近研究了uniCloud,并用uniCloud开发了一个性格测试小程序,已经发布到服务器,完美的发布到抖音,在抖音可以搜索到该小程序。

最近研究了uniCloud,并用uniCloud开发了一个性格测试小程序,已经发布到服务器,完美的发布到抖音,在抖音可以搜索到该小程序。源码和视频教程都开源给大家了。


视频的教程放在b站了,希望下坡伙伴,给个三连:


微信图片_20221009221720.png


https://www.bilibili.com/video/BV19u411z7Jr?spm_id_from=333.999.0.0


一,什么是uniCloud:


uniCloud是uni-app的云开发库,是 DCloud 联合阿里云、腾讯云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。


uniCloud基本抹平了不同云厂商的差异,如果你熟悉mongoDB,那么就很容易上手了!


现在用uniCloud可以大大的提高开发的效率,而且可以降低运维方面的成本,因为现在serverless还处于免费阶段。


当然也有很多的缺点,新手上手的话不是很快,很多东西也不支持,例如删除数据,竟然还要去调api。


最近小孟和老王研究了下,感觉还是可以搞的,于是就测试并发布了整个通用的版本,发布到了抖音,这个大家可以搞一下,抖音的流量你懂的,但是我们现在对赚钱不感兴趣。所以有熊伙伴想搞的,可以拿去源码学习,但是不要商用和贩卖!


二,系统界面截图:


微信图片_20221009221730.png


微信图片_20221009221734.png


微信图片_20221009221737.png


微信图片_20221009221740.png


微信图片_20221009221745.png


微信图片_20221009221748.png


微信图片_20221009221752.png


微信图片_20221009221756.png


微信图片_20221009221800.png


微信图片_20221009221804.png


微信图片_20221009221808.png


微信图片_20221009221812.png



三,核心代码演示:


<template>
  <view class="center">
  <view class="userInfo" @click.capture="toUserInfo">
    <uni-file-picker v-if="userInfo.avatar_file" v-model="userInfo.avatar_file"
    fileMediatype="image" :del-icon="false" return-type="object" :image-styles="listStyles" disablePreview
    disabled />
    <image v-else class="logo-img" src="/static/uni-center/defaultAvatarUrl.png"></image>
    <view class="logo-title">
    <text class="uer-name">{{userInfo.nickname||userInfo.username||userInfo.mobile||'未登录'}}</text>
    </view>
  </view>
  <uni-list class="center-list" v-for="(sublist , index) in ucenterList" :key="index">
    <uni-list-item v-for="(item,i) in sublist" :title="item.title" link :rightText="item.rightText" :key="i"
    :clickable="true" :to="item.to" @click="ucenterListClick(item)" :show-extra-icon="true"
    :extraIcon="{type:item.icon,color:'#999'}">
    <view v-if="item.showBadge" class="item-footer" slot="footer">
      <text class="item-footer-text">{{item.rightText}}</text>
      <view class="item-footer-badge"></view>
    </view>
    </uni-list-item>
  </uni-list>
  </view>
</template>
<script>
  import {
  mapGetters,
  mapMutations
  } from 'vuex';
  import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
  import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version';
  import uniShare from 'uni_modules/uni-share/js_sdk/uni-share.js';
  const db = uniCloud.database();
  export default {
  data() {
    return {
    ucenterList: [
      [{
      "title": '问题与反馈',
      "to": '/uni_modules/uni-feedback/pages/uni-feedback/uni-feedback',
      "icon": "help"
      }, {
      "title": '设置',
      "to": '/pages/ucenter/settings/settings',
      "icon": "gear"
      }],
      [{
      "title": '关于',
      "to": '/pages/ucenter/about/about',
      "icon": "info"
      }]
    ],
    listStyles: {
      "height": "150rpx", // 边框高度
      "width": "150rpx", // 边框宽度
      "border": { // 如果为 Boolean 值,可以控制边框显示与否
      "color": "#eee", // 边框颜色
      "width": "1px", // 边框宽度
      "style": "solid", // 边框样式
      "radius": "100%" // 边框圆角,支持百分比
      }
    }
    }
  },
  onLoad() {
    //#ifdef APP-PLUS
    this.ucenterList[this.ucenterList.length - 2].unshift({
    title: '检查更新',
    rightText: this.appVersion.version + '-' + this.appVersion.versionCode,
    event: 'checkVersion',
    icon: 'loop',
    showBadge: this.appVersion.hasNew
    })
    //#endif
  },
  computed: {
    ...mapGetters({
    userInfo: 'user/info',
    login: 'user/hasLogin'
    })
    // #ifdef APP-PLUS
    ,
    appVersion() {
    return getApp().appVersion
    }
    // #endif
    ,
    appConfig() {
    return getApp().globalData.config
    }
  },
  methods: {
    ...mapMutations({
    setUserInfo: 'user/login'
    }),
    toSettings() {
    uni.navigateTo({
      url: "/pages/ucenter/settings/settings"
    })
    },
    /**
    * 个人中心项目列表点击事件
    */
    ucenterListClick(item) {
    if (!item.to && item.event) {
      this[item.event]();
    }
    },
    async checkVersion() {
    let res = await callCheckVersion()
    console.log(res);
    if (res.result.code > 0) {
      checkUpdate()
    } else {
      uni.showToast({
      title: res.result.message,
      icon: 'none'
      });
    }
    },
    toUserInfo() {
    uni.navigateTo({
      url: '/pages/ucenter/userinfo/userinfo'
    })
    },
    /**
    * 去应用市场评分
    */
    gotoMarket() {
    // #ifdef APP-PLUS
    if (uni.getSystemInfoSync().platform == "ios") {
      // 这里填写appstore应用id
      let appstoreid = this.appConfig.marketId.ios; // 'id1417078253';
      plus.runtime.openURL("itms-apps://" + 'itunes.apple.com/cn/app/wechat/' + appstoreid + '?mt=8');
    }
    if (uni.getSystemInfoSync().platform == "android") {
      var Uri = plus.android.importClass("android.net.Uri");
      var uri = Uri.parse("market://details?id=" + this.appConfig.marketId.android);
      var Intent = plus.android.importClass('android.content.Intent');
      var intent = new Intent(Intent.ACTION_VIEW, uri);
      var main = plus.android.runtimeMainActivity();
      main.startActivity(intent);
    }
    // #endif
    },
    async share() {
    let {result} = await uniCloud.callFunction({
      name: 'uni-id-cf',
      data: {
      action: 'getUserInviteCode'
      }
    })
    console.log(result);
    let myInviteCode = result.myInviteCode || result.userInfo.my_invite_code
    console.log(myInviteCode);
    let {
      appName,
      logo,
      company,
      slogan
    } = this.appConfig.about
    // #ifdef APP-PLUS
    uniShare({
      content: { //公共的分享类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
      type: 0,
      href: this.appConfig.h5.url +
        `/#/pages/ucenter/invite/invite?code=${myInviteCode}`,
      title: appName,
      summary: slogan,
      imageUrl: logo + '?x-oss-process=image/resize,m_fill,h_100,w_100' //压缩图片解决,在ios端分享图过大导致的图片失效问题
      },
      menus: [{
        "img": "/static/app-plus/sharemenu/wechatfriend.png",
        "text": "微信好友",
        "share": {
        "provider": "weixin",
        "scene": "WXSceneSession"
        }
      },
      {
        "img": "/static/app-plus/sharemenu/wechatmoments.png",
        "text": "",
        "share": {
        "provider": "weixin",
        "scene": "WXSenceTimeline"
        }
      },
      {
        "img": "/static/app-plus/sharemenu/weibo.png",
        "text": "微博",
        "share": {
        "provider": "sinaweibo"
        }
      },
      {
        "img": "/static/app-plus/sharemenu/qq.png",
        "text": "QQ",
        "share": {
        "provider": "qq"
        }
      },
      {
        "img": "/static/app-plus/sharemenu/copyurl.png",
        "text": "复制",
        "share": "copyurl"
      },
      {
        "img": "/static/app-plus/sharemenu/more.png",
        "text": "更多",
        "share": "shareSystem"
      }
      ],
      cancelText: "取消分享",
    }, e => { //callback
      console.log(e);
    })
    // #endif
    }
  }
  }
</script>
<style>
  /* #ifndef APP-PLUS-NVUE */
  page {
  background-color: #f8f8f8;
  }
  /* #endif*/
  .center {
  flex: 1;
  flex-direction: column;
  background-color: #f8f8f8;
  }
  .userInfo {
  width: 750rpx;
  padding: 20rpx;
  padding-top: 50px;
  background-image: url(../../static/uni-center/headers.png);
  flex-direction: column;
  align-items: center;
  }
  .logo-img {
  width: 150rpx;
  height: 150rpx;
  border-radius: 150rpx;
  }
  .logo-title {
  flex: 1;
  align-items: center;
  justify-content: space-between;
  flex-direction: row;
  }
  .uer-name {
  height: 100rpx;
  line-height: 100rpx;
  font-size: 38rpx;
  color: #FFFFFF;
  }
  .center-list {
  margin-bottom: 30rpx;
  background-color: #f9f9f9;
  }
  .center-list-cell {
  width: 750rpx;
  background-color: #007AFF;
  height: 40rpx;
  }
  .grid {
  background-color: #FFFFFF;
  margin-bottom: 6px;
  }
  .uni-grid .text {
  font-size: 30rpx;
  height: 25px;
  line-height: 25px;
  color: #817f82;
  }
  .uni-grid .item /deep/ .uni-grid-item__box {
  justify-content: center;
  align-items: center;
  }
  /*修改边线粗细示例*/
  /* #ifndef APP-NVUE */
  .center-list /deep/ .uni-list--border:after {
  -webkit-transform: scaleY(0.2);
  transform: scaleY(0.2);
  margin-left: 80rpx;
  }
  .center-list /deep/ .uni-list--border-top,
  .center-list /deep/ .uni-list--border-bottom {
  display: none;
  }
  /* #endif */
  .item-footer {
  flex-direction: row;
  align-items: center;
  }
  .item-footer-text {
  color: #999;
  font-size: 24rpx;
  padding-right: 10rpx;
  }
  .item-footer-badge {
  width: 20rpx;
  height: 20rpx;
  /* #ifndef APP-NVUE */
  border-radius: 50%;
  /* #endif */
  /* #ifdef APP-NVUE */
  border-radius: 10rpx;
  /* #endif */
  background-color: #DD524D;
  }
</style>


<script>
 import uQRCode from './uqrcode.js'
 export default {
  props: {
   cid: {
    type: String,
    default(){
     return Date.now()+Math.random()+'';
    }
   },
   text: {
    type: String,
    required: true
   },
   size: {
    type: Number,
    default: uni.upx2px(200)
   },
   margin: {
    type: Number,
    default: 0
   },
   backgroundColor: {
    type: String,
    default: '#ffffff'
   },
   foregroundColor: {
    type: String,
    default: '#000000'
   },
   backgroundImage: {
    type: String
   },
   logo: {
    type: String
   },
   makeOnLoad: {
    type: Boolean,
    default: false
   }
  },
  data() {
   return {
   }
  },
  mounted() {
   if (this.makeOnLoad) {
    this.make()
   }
  },
  methods: {
   async make() {
    var options = {
     canvasId: this.cid,
     componentInstance: this,
     text: this.text,
     size: this.size,
     margin: this.margin,
     backgroundColor: this.backgroundImage ? 'rgba(255,255,255,0)' : this.backgroundColor,
     foregroundColor: this.foregroundColor
    }
    var filePath = await this.makeSync(options)
    if (this.backgroundImage) {
     filePath = await this.drawBackgroundImageSync(filePath)
    }
    if (this.logo) {
     filePath = await this.drawLogoSync(filePath)
    }
    this.makeComplete(filePath)
   },
   makeComplete(filePath) {
    this.$emit('makeComplete', filePath)
   },
   drawBackgroundImage(options) {
    var ctx = uni.createCanvasContext(this.cid, this)
    ctx.drawImage(this.backgroundImage, 0, 0, this.size, this.size)
    ctx.drawImage(options.filePath, 0, 0, this.size, this.size)
    ctx.draw(false, () => {
     uni.canvasToTempFilePath({
      canvasId: this.cid,
      success: res => {
       options.success && options.success(res.tempFilePath)
      },
      fail: error => {
       options.fail && options.fail(error)
      }
     }, this)
    })
   },
   async drawBackgroundImageSync(filePath) {
    return new Promise((resolve, reject) => {
     this.drawBackgroundImage({
      filePath: filePath,
      success: res => {
       resolve(res)
      },
      fail: error => {
       reject(error)
      }
     })
    })
   },
   fillRoundRect(ctx, r, x, y, w, h) {
    ctx.save()
    ctx.translate(x, y)
    ctx.beginPath()
    ctx.arc(w - r, h - r, r, 0, Math.PI / 2)
    ctx.lineTo(r, h)
    ctx.arc(r, h - r, r, Math.PI / 2, Math.PI)
    ctx.lineTo(0, r)
    ctx.arc(r, r, r, Math.PI, Math.PI * 3 / 2)
    ctx.lineTo(w - r, 0)
    ctx.arc(w - r, r, r, Math.PI * 3 / 2, Math.PI * 2)
    ctx.lineTo(w, h - r)
    ctx.closePath()
    ctx.setFillStyle('#ffffff')
    ctx.fill()
    ctx.restore()
   },
   drawLogo(options) {
    var ctx = uni.createCanvasContext(this.cid, this)
    ctx.drawImage(options.filePath, 0, 0, this.size, this.size)
    var logoSize = this.size / 4
    var logoX = this.size / 2 - logoSize / 2
    var logoY = logoX
    var borderSize = logoSize + 10
    var borderX = this.size / 2 - borderSize / 2
    var borderY = borderX
    var borderRadius = 5
    this.fillRoundRect(ctx, borderRadius, borderX, borderY, borderSize, borderSize)
    ctx.drawImage(this.logo, logoX, logoY, logoSize, logoSize)
    ctx.draw(false, () => {
     uni.canvasToTempFilePath({
      canvasId: this.cid,
      success: res => {
       options.success && options.success(res.tempFilePath)
      },
      fail: error => {
       options.fail && options.fail(error)
      }
     }, this)
    })
   },
   async drawLogoSync(filePath) {
    return new Promise((resolve, reject) => {
     this.drawLogo({
      filePath: filePath,
      success: res => {
       resolve(res)
      },
      fail: error => {
       reject(error)
      }
     })
    })
   },
   async makeSync(options) {
    return new Promise((resolve, reject) => {
     uQRCode.make({
      canvasId: options.canvasId,
      componentInstance: options.componentInstance,
      text: options.text,
      size: options.size,
      margin: options.margin,
      backgroundColor: options.backgroundColor,
      foregroundColor: options.foregroundColor,
      success: res => {
       resolve(res)
      },
      fail: error => {
       reject(error)
      }
     })
    })
   }
  }
 }
</script>



目录
相关文章
|
23天前
|
存储 测试技术 API
数据驱动开发软件测试脚本
今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。
28 0
|
6月前
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
5月前
|
小程序 前端开发 Android开发
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
1073 29
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
|
4月前
|
传感器 人工智能 JavaScript
鸿蒙开发:DevEcoTesting中的稳定性测试
DevEcoTesting主要的目的也是用于软件的测试,可以让开发者无需复杂的配置,即可一键执行测试任务,同时提供了测试报告和分析,无论是对于开发者还是测试同学来说,都是一个非常方便的工具。
133 3
鸿蒙开发:DevEcoTesting中的稳定性测试
|
3月前
|
敏捷开发 运维 数据可视化
DevOps看板工具中的协作功能:如何打破开发、测试与运维之间的沟通壁垒
在DevOps实践中,看板工具通过可视化任务管理和自动化流程,提升开发与运维团队的协作效率。它支持敏捷开发、持续交付,助力团队高效应对需求变化,实现跨职能协作与流程优化。
|
3月前
|
运维 jenkins 测试技术
"还在苦等开发部署环境?3步教你用Jenkins拿回测试主动权"
测试工程师最头疼的问题是什么?依赖开发部署环境! 开发延期→测试时间被压缩→紧急上线后BUG频出→测试背锅。传统流程中,测试被动等待部署,效率低下。而Jenkins自动化部署让测试人员自主搭建环境,实现: ✅ 随时触发测试,不再苦等开发 ✅ 部署效率提升10倍,抢回测试时间 ✅ 改善团队协作,减少互相甩锅 学习Jenkins部署能力,成为高效测试工程师,告别被动等待!
|
6月前
|
监控 前端开发 小程序
陪练,代练,护航,代打小程序源码/前端UNIAPP-VUE2.0开发 后端Thinkphp6管理/具备家政服务的综合型平台
这款APP通过技术创新,将代练、家政、娱乐社交等场景融合,打造“全能型生活服务生态圈”。以代练为切入点,提供模块化代码支持快速搭建平台,结合智能匹配与技能审核机制,拓展家政服务和商业管理功能。技术架构具备高安全性和扩展性,支持多业务复用,如押金冻结、录屏监控等功能跨领域应用。商业模式多元,包括交易抽成、增值服务及广告联名,同时设计跨领域积分体系提升用户粘性,实现生态共生与B端赋能。
493 12
|
6月前
|
小程序 Java 关系型数据库
weixin163基于微信小程序的校园二手交易平台系统设计与开发ssm(文档+源码)_kaic
本文介绍了一款基于微信小程序的校园二手物品交易平台的开发与实现。该平台采用Java语言开发服务端,使用MySQL数据库进行数据存储,前端以微信小程序为载体,支持管理员和学生两种角色操作。管理员可管理用户、商品分类及信息、交易记录等,而学生则能注册登录、发布购买商品、参与交流论坛等。系统设计注重交互性和安全性,通过SSM框架优化开发流程,确保高效稳定运行,满足用户便捷交易的需求,推动校园资源共享与循环利用。
|
6月前
|
人工智能 开发框架 小程序
工会成立100周年纪念,开发职工健身AI运动小程序、APP方案推荐
为庆祝中华全国总工会成立100周年,特推出基于AI技术的智能健身系统,以小程序和APP形式呈现,助力职工健康生活。方案包括:1) 小程序插件,支持多种运动识别,开箱即用;2) APP插件,提供更高精度的运动检测;3) 成熟的「AI乐运动」系统,支持赛事活动管理。这些方案满足不同需求,推动全民健身体验升级,彰显工会对职工健康的关怀。
|
6月前
|
小程序 关系型数据库 Java
weixin168“返家乡”高校暑期社会实践微信小程序设计与开发ssm(文档+源码)_kaic
本文探讨高校暑期社会实践微信小程序的开发与应用,旨在通过信息化手段提升活动管理效率。借助微信小程序技术、SSM框架及MySQL数据库,实现信息共享、流程规范和操作便捷。系统涵盖需求分析、可行性研究、设计实现等环节,确保技术可行、操作简便且经济合理。最终,该小程序可优化活动发布、学生信息管理和心得交流等功能,降低管理成本并提高工作效率。

热门文章

最新文章