IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 从零开始编写一个微信小程序(微信开发者工具+JS+WuxUI组件库+云开发)万字整理,建议收藏! -> 正文阅读

[移动开发]从零开始编写一个微信小程序(微信开发者工具+JS+WuxUI组件库+云开发)万字整理,建议收藏!

微信小程序—魔镜 笔记&源码(微信开发者工具+JS+UI组件库+云开发)

效果展示

视频演示

经历了一次升级之后,我的小程序怎么样了?


0.准备工作

Wux组件库官方文档:https://www.wuxui.com/点击转到文档
微信小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/点击转到文档
微信开发者工具下载:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html点击转到下载页

1.搭建环境

安装npm安装组件库

安装node
检查node版本 node -v
检查npm版本 npm -v

或者安装yarn安装组件库

npm install -g yarn

2.引入WuxWeapp组件库或者VantUI组件库

# Using npm install Wux UI
npm i wux-weapp -S --production
# 通过 npm 安装 vant UI
npm i @vant/weapp -S --production
#直接下载源码
git clone https://github.com/wux-weapp/wux-weapp.git D:\File\Project\Download
//‘cnpm‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件,则安装cnpm
//npm install -g cnpm --registry=https://registry.npm.taobao.org

//cnpm -v

//'cross-env' 不是内部或外部命令,也不是可运行的程序,则安装cross-env
//cnpm i cross-env --save-dev

//'gulp'不是内部或者外部命令,也不是可运行的程序或批处理文件,则安装
//npm install gulp -g

//提示try running:yarn add gulp,则执行
//yarn add gulp

//提示error An unexpected error occurred: "ENOENT: no such file or directory, copyfile 'C:\\Users\\WangZhuo\\AppData\\Local\\Yarn\\Cache\\v6\\npm-shebang-regex-1.0.0-da42f49740c0b42db2ca9728571cb190c98efea3-integrity\\node_modules\\shebang-regex\\index.js' -> 'D:\\File\\Project\\Download\\wux-weapp\\node_modules\\cross-spawn\\node_modules\\shebang-regex\\index.js'". 则

//删除国外代理
//npm config rm proxy 
//npm config rm https-proxy
//更换成国内镜像
//yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass

安装依赖包
npm install

在wux-weapp文件夹下,编译
npm run build -- --config ./config.custom.json --output ./build

3.修改app.json

将 app.json 中的 "style": "v2" 去除

4.修改project.config.json,在settings中添加

"packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "./package.json",
        "miniprogramNpmDistDir": "./"
      }

开发工具会默认在当前目录下创建miniprogram_npm的文件名,所以新版本的miniprogramNpmDistDir配置为’./'即可

5.构建npm包

点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件

3.使用Wux组件库

全局使用
app.json配置
{
  "usingComponents": {
    "wux-button": "/miniprogram_npm/wux-weapp/button/index", //按钮
    "wux-icon": "/miniprogram_npm/wux-weapp/icon/index", //icon图标
    "wux-badge": "/miniprogram_npm/wux-weapp/badge/index", 
    "wux-tabbar": "/miniprogram_npm/wux-weapp/tabbar/index", //底部触摸栏
    "wux-tabbar-item": "/miniprogram_npm/wux-weapp/tabbar-item/index"
  }
}

4.微信开发者工具配置

"checkSiteMap":false  //project.config.json里面去进行配置,有个checkSiteMap的配置项,默认为true,改成false就不会报sitemap的警告

//2.18.1 加入了组件属性和对应数据的类型匹配检查,如果不匹配就会展示the type of property "xx" is illegal

5.魔镜主题色

@positive: #387ef5;
@calm: #6a9ef8;//75%@positive//#11c1f3
@balanced: #a5c5fb;//45%@positive//#33cd5f
@energized: #ffb9c1;//45%@royal//#ffc900
@assertive: #ff8b98;//75%@royal//#ef473a
@royal: #ff6476;//#886aea

6.项目目录结构
在这里插入图片描述

正式开发

1.自定义底部导航tabbar

在这里插入图片描述

①app.json

"tabBar": {
    "custom": true,
    "list": [
      {
        "pagePath": "pages/home/home"
      },{
        "pagePath": "pages/person/person"
      },{
        "pagePath": "pages/shop/shop"
      }
    ]
  },
  "usingComponents": {}

②根目录下创建custom-tab-bar文件夹

在custom-tab-bar下创建四个文件

custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss

③在custom-tab-bar/index.js中写switchTap方法

Page({
  data: {
    // current: '0',
    pagePath:[
      '/pages/home/home','----忽略----','/pages/shop/shop','/pages/person/person'
    ]
  },
  onChange(e) {
    // console.log('onChange', e.detail)
    const that=this;
    if(e.detail.key!==1){//非扫一扫
      var pageUrl=that.data.path[e.detail.key]
      wx.switchTab({url:pageUrl})
    }
    else{//扫一扫
    }
  },

})

④在跳转的目标页.js中写getTabBar 获取当前页面下的自定义 tabBar 组件实例

并setData()更新current,tab栏icon变为选中

page({ 
  onShow: function () {
    if (typeof this.getTabBar === 'function' &&
        this.getTabBar()) {
        this.getTabBar().setData({
          current: 0
        })
     }
  }
}) 

2.使用压屏窗

在这里插入图片描述

①app.json中引入

app.json
"usingComponents":{
    "wux-landscape": "./components/lib/landscape/index"
}

②在custom-tab-bar/index.wxml添加

<wux-landscape visible="{{ visible1 }}" bind:close="onClose1" maskClosable="{{true}}">
  <view class='SVGcontainer'>
    <image class='SVG' src="{{bgImg}}" mode='aspectFit' style="height:140px;width:130px" />
    <wux-white-space body-style="height: 25px" />
    <wux-button block size="small" type="assertive" bind:click="navToCamera" data-way="takePhoto">拍摄照片</wux-button>
    <wux-white-space body-style="height: 12px" />
    <wux-button block size="small" type="assertive" bind:click="navToCamera" data-way="chooseGallery">相册选择</wux-button>
  </view>
</wux-landscape>

③在custom-tab-bar/index.wxss中添加

/**index.wxss**/
.SVG{
  top:-80px;
  position: absolute;
  left:41px;
}
.SVGcontainer{
  margin:40px auto 0 auto;
  height:200px;
  width: 220px;
  align-items: center;
  background-color: rgb(255, 255, 255);
  padding: 30px;
  box-sizing: border-box;
  border-radius: 15px;
  border:5px solid rgb(255, 197, 210);
  position: relative;
} 

④在custom-tab-bar/index.js中增加

 data: {
   current: 0,//记录当前tabbar选中对象
   last: 0,//记录上次tabbar选中对象
   bgImg:'data:image/svg+xml;base64,77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjE0NHB4IiBoZWlnaHQ9IjE0NHB4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICA8ZGVmcz4NCiAgICA8cGF0aCBkPSJNIDAgMCAgTCAxMjkzIDAgIEwgMTI5MyAxMDI0ICBMIDAgMTAyNCAgWiAiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZmlsbD0iYmxhY2siIGlkPSJwYXRoMjAiIC8+DQogICAgPGNsaXBQYXRoIGlkPSJjbGlwMjEiPg0KICAgICAgPHVzZSB4bGluazpocmVmPSIjcGF0aDIwIiAvPg0KICAgIDwvY2xpcFBhdGg+DQogICAgPGZpbHRlciB4PSItNTAuMDAlIiB5PSItNTAuMDAlIiB3aWR0aD0iMjAwLjAwJSIgaGVpZ2h0PSIyMDAuMDAlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJmaWx0ZXIyMiI+DQogICAgICA8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMSAwIDAgMCAwICAwIDEgMCAwIDAgIDAgMCAxIDAgMCAgMCAwIDAgMSAwICAiIGluPSJTb3VyY2VHcmFwaGljIiAvPg0KICAgIDwvZmlsdGVyPg0KICAgIDxmaWx0ZXIgeD0iMTE1cHgiIHk9IjE0M3B4IiB3aWR0aD0iMTQ0cHgiIGhlaWdodD0iMTQ0cHgiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImZpbHRlcjIzIj4NCiAgICAgIDxmZU9mZnNldCBkeD0iMCIgZHk9IjUiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRJbm5lciIgLz4NCiAgICAgIDxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjQiIGluPSJzaGFkb3dPZmZzZXRJbm5lciIgcmVzdWx0PSJzaGFkb3dHYXVzc2lhbiIgLz4NCiAgICAgIDxmZUNvbXBvc2l0ZSBpbjI9InNoYWRvd0dhdXNzaWFuIiBvcGVyYXRvcj0iYXRvcCIgaW49IlNvdXJjZUFscGhhIiByZXN1bHQ9InNoYWRvd0NvbXBvc2l0ZSIgLz4NCiAgICAgIDxmZUNvbG9yTWF0cml4IHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAuMTkyMTU2ODYyNzQ1MDk4ICAwIDAgMCAwIDAuMTkyMTU2ODYyNzQ1MDk4ICAwIDAgMCAwIDAuMTkyMTU2ODYyNzQ1MDk4ICAwIDAgMCAwLjEyMTU2ODYyNzQ1MDk4IDAgICIgaW49InNoYWRvd0NvbXBvc2l0ZSIgLz4NCiAgICA8L2ZpbHRlcj4NCiAgICA8ZyBpZD0id2lkZ2V0MjQiPg0KICAgICAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC4wOTg5OTQ1ODYyMzM1NjU0IDAgMCAwLjA5ODk5NDU4NjIzMzU2NTQgMTIzIDE1OS4zMTQ3NzE4NDg0MTUgKSIgY2xpcC1wYXRoPSJ1cmwoI2NsaXAyMSkiIGZpbHRlcj0idXJsKCNmaWx0ZXIyMikiPg0KICAgICAgICA8cGF0aCBkPSJNMjg3LjUyODM0NSAyNjAuNTgxMjU0bDQyLjg0NjMwNS0yMjMuNjYzMUExMi4xMjYzMTMgMTIuMTI2MzEzIDAgMCAxIDM0Mi4yMzE0ODkgMjYuOTQ3NjMxaDYwOS4wMTAzNjZhMTIuMTI2MzEzIDEyLjEyNjMxMyAwIDAgMSAxMS44NTY4MzkgOS45NzA1MjNsNDIuODQ2MzA0IDIyMy42NjMxeiIgZmlsbD0iI0ZEQ0E4OSIgcC1pZD0iNjEwMSIgZGF0YS1zcG0tYW5jaG9yLWlkPSJhMzEzeC43NzgxMDY5LjAuaTkiIGNsYXNzPSJzZWxlY3RlZCI+PC9wYXRoPg0KICAgICAgICA8cGF0aCBkPSJNOTM5LjExNTU0MiA1My44OTQ5OTJsMzQuMjIzMTQ5IDE3OS43Mzg5SDMyMC4xMzQ2NTNMMzU0LjM1NzgwMSA1My44OTQ5OTJoNTg0Ljc1Nzc0MW0xMi4zOTU3ODctNTMuODk0NzIzSDM0Mi4yMzE0ODlhMzkuMDczNjc0IDM5LjA3MzY3NCAwIDAgMC0zOC4yNjUyNTMgMzEuNzk3ODg3bC00OS4wNDQxOTggMjU1LjczMDQ1OWg3ODMuNjI5MjY4bC00OC43NzQ3MjQtMjU1LjczMDQ1OUEzOS4wNzM2NzQgMzkuMDczNjc0IDAgMCAwIDk1MS4yNDE4NTUgMC4wMDAyNjl6IiBmaWxsPSIjRkY2NDc2IiBwLWlkPSI2MTAyIiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pNCIgY2xhc3M9InNlbGVjdGVkIj48L3BhdGg+DQogICAgICAgIDxwYXRoIGQ9Ik0yNi45NDczNjEgMTg4LjYzMTc5OWwxMjM5LjU3ODYyMSAwIDAgODA4LjQyMDg0LTEyMzkuNTc4NjIxIDAgMC04MDguNDIwODRaIiBmaWxsPSIjRkRBQ0JEIiBwLWlkPSI2MTAzIiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pMCIgY2xhc3M9IiI+PC9wYXRoPg0KICAgICAgICA8cGF0aCBkPSJNMTIxMi42MzEyNiAyMTUuNTc5MTZhMjYuOTQ3MzYxIDI2Ljk0NzM2MSAwIDAgMSAyNi45NDczNjEgMjYuOTQ3MzYxdjcwMC42MzEzOTVhMjYuOTQ3MzYxIDI2Ljk0NzM2MSAwIDAgMS0yNi45NDczNjEgMjYuOTQ3MzYxSDgwLjg0MjA4NGEyNi45NDczNjEgMjYuOTQ3MzYxIDAgMCAxLTI2Ljk0NzM2MS0yNi45NDczNjFWMjQyLjUyNjUyMWEyNi45NDczNjEgMjYuOTQ3MzYxIDAgMCAxIDI2Ljk0NzM2MS0yNi45NDczNjFoMTEzMS43ODkxNzZtMC01My44OTQ3MjNIODAuODQyMDg0YTgwLjg0MjA4NCA4MC44NDIwODQgMCAwIDAtODAuODQyMDg0IDgwLjg0MjA4NHY3MDAuNjMxMzk1YTgwLjg0MjA4NCA4MC44NDIwODQgMCAwIDAgODAuODQyMDg0IDgwLjg0MjA4NGgxMTMxLjc4OTE3NmE4MC44NDIwODQgODAuODQyMDg0IDAgMCAwIDgwLjg0MjA4NC04MC44NDIwODRWMjQyLjUyNjUyMWE4MC44NDIwODQgODAuODQyMDg0IDAgMCAwLTgwLjg0MjA4NC04MC44NDIwODR6IiBmaWxsPSIjRkY2NDc2IiBwLWlkPSI2MTA0IiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pMSIgY2xhc3M9IiI+PC9wYXRoPg0KICAgICAgICA8cGF0aCBkPSJNNjQ2LjczNjY3MiA4ODMuMzM0Nzc0QTI5MC40OTI1NTUgMjkwLjQ5MjU1NSAwIDEgMSA5MzcuMjI5MjI3IDU5Mi44NDIyMTkgMjkxLjAzMTUwMiAyOTEuMDMxNTAyIDAgMCAxIDY0Ni43MzY2NzIgODgzLjMzNDc3NHoiIGZpbGw9IiNGRkZGRkYiIHAtaWQ9IjYxMDUiPjwvcGF0aD4NCiAgICAgICAgPHBhdGggZD0iTTY0Ni43MzY2NzIgMzI5LjI5NzAyNUEyNjMuNTQ1MTk0IDI2My41NDUxOTQgMCAxIDEgMzgzLjE5MTQ3OCA1OTIuODQyMjE5IDI2My44MTQ2NjcgMjYzLjgxNDY2NyAwIDAgMSA2NDYuNzM2NjcyIDMyOS4yOTcwMjVtMC01My44OTQ3MjNBMzE3LjQzOTkxNiAzMTcuNDM5OTE2IDAgMSAwIDk2NC4xNzY1ODggNTkyLjg0MjIxOSAzMTcuNDM5OTE2IDMxNy40Mzk5MTYgMCAwIDAgNjQ2LjczNjY3MiAyNzUuNDAyMzAyeiIgZmlsbD0iI0ZGNjQ3NiIgcC1pZD0iNjEwNiIgZGF0YS1zcG0tYW5jaG9yLWlkPSJhMzEzeC43NzgxMDY5LjAuaTIiIGNsYXNzPSIiPjwvcGF0aD4NCiAgICAgICAgPHBhdGggZD0iTTY0Ni43MzY2NzIgNTkyLjg0MjIxOW0tMTIwLjE4NTIzMiAwYTEyMC4xODUyMzIgMTIwLjE4NTIzMiAwIDEgMCAyNDAuMzcwNDYzIDAgMTIwLjE4NTIzMiAxMjAuMTg1MjMyIDAgMSAwLTI0MC4zNzA0NjMgMFoiIGZpbGw9IiNGRjY0NzYiIHAtaWQ9IjYxMDciIGRhdGEtc3BtLWFuY2hvci1pZD0iYTMxM3guNzc4MTA2OS4wLmkxMCIgY2xhc3M9IiI+PC9wYXRoPg0KICAgICAgICA8cGF0aCBkPSJNNjQ2LjczNjY3MiA0OTkuNjA0MzQ5QTkzLjIzNzg3IDkzLjIzNzg3IDAgMSAxIDU1My40OTg4MDIgNTkyLjg0MjIxOSA5My4yMzc4NyA5My4yMzc4NyAwIDAgMSA2NDYuNzM2NjcyIDQ5OS42MDQzNDltMC01My44OTQ3MjNBMTQ3LjEzMjU5MyAxNDcuMTMyNTkzIDAgMSAwIDc5My44NjkyNjUgNTkyLjg0MjIxOSAxNDcuMTMyNTkzIDE0Ny4xMzI1OTMgMCAwIDAgNjQ2LjczNjY3MiA0NDUuNzA5NjI2eiIgZmlsbD0iI0ZGNjQ3NiIgcC1pZD0iNjEwOCIgZGF0YS1zcG0tYW5jaG9yLWlkPSJhMzEzeC43NzgxMDY5LjAuaTMiIGNsYXNzPSIiPjwvcGF0aD4NCiAgICAgICAgPHBhdGggZD0iTTEwMDcuMjkyMzY3IDI4MC43OTE3NzVsMTY5LjQ5ODkwMiAwIDAgODguOTI2MjkyLTE2OS40OTg5MDIgMCAwLTg4LjkyNjI5MloiIGZpbGw9IiNGRjY0NzYiIHAtaWQ9IjYxMDkiIGRhdGEtc3BtLWFuY2hvci1pZD0iYTMxM3guNzc4MTA2OS4wLmk2IiBjbGFzcz0iIj48L3BhdGg+DQogICAgICAgIDxwYXRoIGQ9Ik0xMTQ5Ljg0MzkwOCAzMDcuNzM5MTM2djM1LjAzMTU3aC0xMTUuNjA0MTh2LTM1LjAzMTU3aDExNS42MDQxOG00LjMxMTU3OC01My44OTQ3MjNoLTEyMy45NTc4NjJhNDkuNTgzMTQ1IDQ5LjU4MzE0NSAwIDAgMC00OS41ODMxNDUgNDkuNTgzMTQ1djQzLjM4NTI1MmE0OS41ODMxNDUgNDkuNTgzMTQ1IDAgMCAwIDQ5LjU4MzE0NSA0OS41ODMxNDVoMTIzLjk1Nzg2MmE0OS41ODMxNDUgNDkuNTgzMTQ1IDAgMCAwIDQ5LjU4MzE0NS00OS41ODMxNDV2LTQzLjM4NTI1MmE0OS41ODMxNDUgNDkuNTgzMTQ1IDAgMCAwLTQ5LjU4MzE0NS00OS41ODMxNDV6IiBmaWxsPSIjZmZmZmZmIiBwLWlkPSI2MTEwIiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pNSIgY2xhc3M9IiI+PC9wYXRoPg0KICAgICAgPC9nPg0KICAgIDwvZz4NCiAgPC9kZWZzPg0KICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIC0xMTUgLTE0MyApIj4NCiAgICA8dXNlIHhsaW5rOmhyZWY9IiN3aWRnZXQyNCIgZmlsdGVyPSJ1cmwoI2ZpbHRlcjIzKSIgLz4NCiAgICA8dXNlIHhsaW5rOmhyZWY9IiN3aWRnZXQyNCIgLz4NCiAgPC9nPg0KPC9zdmc+',//syg格式的粉色相机图片
   visible1: false,
   }, 
//显示压屏窗
  onOpen1() {
    this.setData({
      current: 1,
      visible1: true,
    })
  },
    //tabbar栏1号被点击
  chooseScan(){
    this.setData({last:this.data.current})
    this.onOpen1();
    console.log('-----可以忽略此问题-----');
  },
    //隐藏压屏窗
  onClose1() {
    const that=this;
    this.setData({
      current: that.data.last,
      visible1: false,
    })
  },
    //跳转到处理页面
async navToCamera(e){
    console.log(e.target.dataset['way'])
    var choice=e.target.dataset['way'];
    // await this.onClose1()//隐藏压屏窗
    if(choice==='takePhoto'){
      //调用相机拍照
      //跳转到拍摄页面
      await wx.navigateTo({
        url: '/pages/takePhoto/takePhoto',
      })
    }
    else if(choice==='chooseGallery'){
      //从相册选择
      wx.chooseImage({
        count: 1,
        sizeType: ['original'],
        sourceType: ['album', 'camera'],
        success (res) {
          // tempFilePath可以作为img标签的src属性显示图片
          const tempFilePaths = res.tempFilePaths
          console.log(tempFilePaths[0]);
        }
      })
    }
  }

3.使用动画组

wxml

Switch state

  <switch data-model="example.in" bindchange="switchChange" checked="{{ example.in }}" />
     
   <wux-animation-group
      in="{{ example.in }}"
      enter="{{ true}}"
      exit="{{ true }}"
      class-names="wux-animate--fadeInDown"
    >
        <view>
          微信小程序自定义组件 https://github.com/wux-weapp/wux-weapp
        </view>
    </wux-animation-group>

js

  switchChange(e) {
    console.log(e.currentTarget.dataset);
    console.log(e.detail)
    const { model } = e.currentTarget.dataset
    this.setData({
      [model]: e.detail.value,
    })
  }

6.使用svg(小程序不支持)

<view class="svg_outline">
	<image class="svg_outline-inner" src="/images/取景框/outline.svg"/>
</view>

7.取景框拍照实现

在这里插入图片描述

takePhoto.wxml

  <view class='cameraContainer'>
    <wux-button class='loading' block loading type="light">相机加载中...</wux-button>
    <camera class='camer' device-position="{{camera.position}}" flash="{{camera.flash}}"	binderror="{{camera.binderror}}" frame-size="{{camera.framesize}}" 	bindstop="{{camera.bindstop}}"></camera>
    <!-- <view class='outline'> -->
    <!-- <image class="outline" src='{{svgOutline}}'><image> -->
      <view class="svg">
        <image class="svg_outline" src="{{svgOutline}}" type='aspectFill' style="width: 100%; height: 100%;" />
      </view>
      <!-- <view class="svg_outline">
        <image class="svg_outline-inner" src="/images/取景框/outline.svg"/>
      </view> -->
    <!-- </view> -->
  </view>
  <view class='coverView'>
    <view class='btnBar'>
      <view class='littleBtn' bindtap="switchFlash"><wux-icon type="ios-flash" size="34" color="#fff"/></view>
    </view>
    <view class='btnBar'>
      <view class='mainBtn' bindtap="takePhoto"><wux-icon type="ios-radio-button-off" size="70" color="#fff"/></view>
    </view>
    <view class='btnBar'>
      <view class='littleBtn' bindtap="switchPosition"><wux-icon type="ios-sync" size="34" color="#fff"/></view>
    </view>
  </view>
  <wux-toast id="wux-toast" />

takePhoto.js

data:{
   camera:{
      mode:"normal",
      resolution:"high",
      position:'back',
      flash:"off",
      framesize:"large",
      bindstop:"exceptionalStop",
      bindinitdone:"hideLoading",
      binderror:"grantFail"
   }
}


//检测相机授权
  onShow: function () {
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.camera']) {
          wx.authorize({
            scope: 'scope.camera',
            success () {
              console.log('相机授权成功')
            }
          })
        }
      }
    })
  },
      
      
      
 //切换闪光灯
  switchFlash(){
    if(this.data.camera.flash=='torch'){
      wx.showToast({
        title: '关闭闪光灯',
        icon:'none',
      })
      this.setData({
        ['camera.flash']:'off',
        success:res=>{
          wx.hideToast({ })
        }
      })
      console.log(this.data.camera.flash)
    }
    else{
      wx.showToast({
        title: '打开闪光灯',
        icon:'none',
      })
      this.setData({
        ['camera.flash']:'torch',
        success:res=>{
          wx.hideToast({ })
      }})
      console.log(this.data.camera.flash)
    }
  }
  ,
      
      
  //切换前后置摄像头
  switchPosition(){
    if(this.data.camera.position=='front'){
      wx.showToast({
        title: '切换后置相机',
        icon:'none',
      })
      this.setData({
        ['camera.position']:'back',
        success:res=>{
          wx.hideToast({ })
        }
      })
      // console.log(this.data.camera.position)
  }
    else{
      wx.showToast({
        title: '切换前置相机',
        icon:'none',
      })
      this.setData({
        ['camera.position']:'front',
        success:res=>{
          wx.hideToast({ })
      }})
      // console.log(this.data.camera.position)
    }
  },
      
      
  //相机授权失败处理
  grantFail:function(){
          
    wx.showModal({
      title: '提示',
      content: '请打开相机授权后继续',
      success (res) {
        if (res.confirm) {
          wx.openSetting({
            success (res) {
              console.log(res.authSetting)
              res.authSetting = {
                "scope.userInfo": true,
                "scope.camera": true
              }
             // that.onLoad();//重载takePhoto页面(测不可用)
                wx.redirectTo({ url: '/pages/takePhoto/takePhoto'});//重载takePhoto页面(测试可用)
            }
          })

        } else if (res.cancel) {
          wx.showToast({
            icon:'none',
            title:'授权失败'
          })
          wx.navigateBack({
            delta: 1,
          })
        }
      }
    })
  }

takePhoto.css

/*相机父容器 相对定位*/
.cameraContainer{
  box-sizing: border-box;
  width:100%; 
  height:1260rpx;
  position: relative;
  /* align-items: center; */
}
/*加载中 绝对定位 index-0*/
.loading{
  position: absolute;
  width: 100%;
  top:240rpx;
  left:0;
}
/*相机画布 绝对定位 index-0*/
.camer{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
/*取景框svg 绝对定位*/
.svg{
  width: 100%; 
  height:100%;
  left: 0;
  top:0;
  display: flex;
  flex-direction: column;
  align-items: center;
  box-sizing: border-box;
  /* padding-top: 105rpx; */
  padding-left:115rpx;
  padding-right: 115rpx;
  /* padding-bottom: 115rpx; */
  /* position: fixed; */
  position: absolute;
  z-index: 10;
}

/*底部按钮 固定定位*/
.coverView{
  width: 100%;
  position: fixed;
  bottom: 50rpx;
  display: flex;
  z-index: 20;
}
/*底部按钮父容器*/
.btnBar{
  width: 33.3%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
/*其他按钮*/
.littleBtn{
  width:70rpx;
  height: 70rpx;
  padding: 5rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: rgba(168, 114, 255, 0.685);
}
/*拍照按钮*/
.mainBtn{
  width:125rpx;
  height: 125rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: rgba(168, 114, 255, 0.685);
}

8.takePhoto页

使用到的局部数据

takePhoto.js

data:{
    windowHeight:0,//屏幕高度
    windowWidth:0,//屏幕宽度
    screenMaxBright:0,//屏幕是否最大亮度
    showCamera:false,//渲染takePhoto页
    camera:{
      mode:"normal",//拍照模式
      resolution:"high",//拍照质量
      // position:getApp().globalData.camera.direction,
      flash:"off",//闪光灯
      framesize:"large",
      bindstop:"exceptionalStop",
      bindinitdone:"hideLoading",
      binderror:"grantFail"//相机授权失败时触发
    },
}

使用的全局数据

app.js

globalData: {
    orignalBright:0.5,//屏幕初始亮度
    camera:{
      direction:'back'//前置\后置相机
    }
  }

takePhoto页主要逻辑

在这里插入图片描述

具体实现

1.页面加载,获取屏幕的宽高,将camera的父容器和camera本身的宽高设为屏幕宽高

onLoad(){
	this.getsize()//将camera的父容器和camera本身的宽高设为屏幕宽高
}
//getsize方法的实现
getsize(){
    let that=this;
    wx.getSystemInfo({
      success(res) {
        console.log("height="+ res.windowHeight)
        console.log("width="+res.windowWidth)
        that.setData({
          windowHeight:res.windowHeight,
          windowWidth:res.windowWidth
        })
      },
    })
  }

2.页面就绪,展示Modal“确认拍摄”,阻塞其他进程,等待用户确认

wx.showModal({
      cancelColor: '#FF4242',
      showCancel:true,
      content:'确认拍摄?',
      success:res=>{
       
      }
    })

success:res=>{ }

用户选择确认,showCamera置为true,渲染takePhoto.wxml页面,相机方向设为全局数据中保存的camera.direction相机方向

if(res.confirm){
          that.setData({
            showCamera:true,
            ['camera.position']: getApp().globalData.camera.direction
          })
    }

用户选择取消,返回上一页

 if(res.cancel){
          wx.navigateBack({
            delta: 1,
          })
        }

4.切换前后置相机

1.在takePhoto页面onLoad()或者onReady()时,初始化this.data.camera.position为globalData.camera.direction
(恢复用户上次相机的(前置/后置)配置)
2.点击切换前后置事件
判断当前data.camera.position
如果是front前置
	则showToast"切换后置中..." 展示文字提示
	this.setData()'camera.position'设为'back' 后置
	然后hideToast
否则
	showToast"切换前置中..."
	setData 将 'camera.position'设为'front' 前置
	隐藏Toast 文字提示
    
    
  //切换前后置摄像头
  switchPosition(){
    if(this.data.camera.position=='front'){
      wx.showToast({
        title: '切换后置相机',
        icon:'none',
      })
     this.setData({
        ['camera.position']:'back',
        success:res=>{
          wx.hideToast({ })
        }
      })
      console.log(this.data.camera.position)
  }
    else{
      wx.showToast({
        title: '切换前置相机',
        icon:'none',
      })
     this.setData({
        ['camera.position']:'front',
        success:res=>{
          wx.hideToast({ })
      }})
      console.log(this.data.camera.position)
    }
    
  }

3.takePhoto页面unLoad()卸载时,将当前镜头方向信息传给全局数据globalData.camera.direction(下次重新加载takePage页相机方向就会恢复成上次退出时的状态)
let app=getApp()
    app.globalData.camera.direction=that.data.camera.position//返回当前相机direction给全局对象

5.相机授权失败事件

展示对话框
选择确认
	则打开设置
  	设置完成则重载takePhoto页
    wx.redirectTo({ url: '/pages/takePhoto/takePhoto'});(重载保证相机授权成功后显示出来)
选择取消
	则展示“授权失败”
    返回上一页wx.navigateBack({ delta: 1 })


grantFail:function(){
    const pagePath=this.getCurrentPageFullPath;//返回当前页面全路径
    wx.showModal({
      title: '提示',
      content: '请打开相机授权后继续',
      success (res) {
        if (res.confirm) {
          wx.openSetting({
            success (res) {
              console.log(res.authSetting)
              res.authSetting = {
                "scope.userInfo": true,
                "scope.camera": true
              }
              wx.redirectTo({ url: '/pages/takePhoto/takePhoto'});//重载takePhoto页面
            }
          })
          // that.onReady();
        } else if (res.cancel) {
          wx.showToast({
            icon:'none',
            title:'授权失败'
          })
          wx.navigateBack({
            delta: 1,
          })
        }
      }
    })
  }
  1. 闪光灯/屏幕补光逻辑
1.在小程序onLaunch()启动时获取屏幕亮度,并保存到全局数据globalData.orignalBright中      wx.getScreenBrightness({
      success(res){
        getApp().globalData.orignalBright=res.value;
      }
    })

2.takePhoto页面onLoad()加载时或者onReady()就绪时,初始化this.data.camera.position相机方向为全局数据globalData.camera.direction的值
that.setData({
            showCamera:true,
            ['camera.position']: getApp().globalData.camera.direction
          })

3.闪光灯点击事件
首先判断当前相机方向this.data.camera.position
如果是'back'后置
	如果闪光灯当前是'torch'状态
		则关闭闪光灯that.setData({['camera.flash']:'off'})
	否则打开闪光灯that.setData({['camera.flash']:'torch'})
否则是前置(前置情况下没有闪光灯,变为调节屏幕亮度)
	如果当前data.screenMaxBright==1是屏幕最大亮度
		则恢复手机原始亮度,将value设为全局数据getApp().globalData.orignalBright屏幕亮度的值,将data.screenMaxBright=0
	否则将屏幕调为最大亮度,将data.screenMaxBright=1
    wx.setScreenBrightness({
          value:1,
          success(){
            that.data.screenMaxBright=1
          }
        })

 4. takePhoto页面unLoad()卸载时,退出拍摄页,回归屏幕原来的亮度
 将当前屏幕亮度设为globalData.orignalBright原始亮度,data.screenMaxBright=0
 wx.setScreenBrightness({
      value: getApp().globalData.orignalBright,
      success(){
        that.data.screenMaxBright=0
      }
    })

7.拍摄事件

takePhoto() {
      console.log('拍照')
      const ctx = wx.createCameraContext()
      ctx.takePhoto({
        quality: 'high',
        success: (res) => {
          var tmpPath=res.tempImagePath;
          wx.navigateTo({
            url: '/pages/takePhoto/scanning/scanning',
            success: function(res) {
              // 通过eventChannel向被打开页面传送数据
              res.eventChannel.emit('acceptDataFromOpenerPage', { imagePath: tmpPath })
            }
          })
        }
      })
  }

9.Scanning页

扫描动画

在这里插入图片描述

wxml

<view class="container" class="scanning">
    <view class='logo'>
        <image src="{{logoUrl}}" ></image>
    </view>
    <view class='processing'>
        <progress percent="{{processValue}}" color="rgb(255, 100, 118)" active stroke-width="5" bindactiveend='onScanningFinish' />
    </view>
    <text style="color: #ccc;">正在扫描生成结果...</text>
    <view class='uploadPhoto'> 
        <image src="{{facePhoto}}" mode="aspectFill"></image>
        <canvas type="2d" id="canvas" style="width: {{canvasWidth}}px; height: {{canvasWidth}}px; position: absolute; border-width: 3px; border-style:dashed; border-color: pink;"></canvas>
    </view>
</view>

css

.logo{
  width:300px;
  height:230px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20rpx;
}
.logo image{
  width:140rpx;
  height:140rpx;
}
.processing{
  width:300px;height:50px;margin-top: 10rpx;
}
.uploadPhoto{
  width:300px;
  height:300px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 10rpx;
  position: relative;
}
.uploadPhoto image{
  width:30%;
  height:40%
}
.scanning{
  display: flex;
  flex-direction: column;
  align-items: center;
}

扫描动画

scanning.js(page({ }))

data

  data: {
    canvasWidth:150,//canvas画布宽度
    lineWidth:153,//线的宽度
    lineHeight:2,//线的高度
  },

onready()

onReady() {
      /**
       *绘制动画
       */
      this.position = {
        x: 1,//线的初始坐标
        y: this.data.canvasWidth+40,
      }
      // 通过 SelectorQuery 获取 Canvas 节点
      wx.createSelectorQuery()
        .select('#canvas')
        .fields({
          node: true,
          size: true,
        })
        .exec(this.init.bind(this))
  },
/**
 * 扫描动画
 */
 init(res) {
   const width = res[0].width
   const height = res[0].height

   const canvas = res[0].node
   const ctx = canvas.getContext('2d')

   const dpr = wx.getSystemInfoSync().pixelRatio
   canvas.width = width * dpr
   canvas.height = height * dpr
   ctx.scale(dpr, dpr)

   const renderLoop = () => {
     this.render(canvas, ctx)
     canvas.requestAnimationFrame(renderLoop)
   }
   canvas.requestAnimationFrame(renderLoop)

   const img = canvas.createImage()
   img.onload = () => {
     this._img = img
   }
   img.src = '/images/检测界面/scan.png'
 
 },

 render(canvas, ctx) {
   ctx.clearRect(0, 0, this.data.canvasWidth+5, this.data.canvasWidth+30)
   this.drawCar(ctx)
 },

 drawCar(ctx) {
   if (!this._img) return
   if (this.position.y < 0) {
     this.position.y = this.data.lineWidth+40
   }
   ctx.drawImage(this._img, this.position.x, this.position.y-=1, this.data.lineWidth, this.data.lineHeight)
   ctx.restore()
 },
  • 页面跳转并传送数据

    拍照页拍照并发送图片临时地址

    takePhoto.js

      console.log('拍照')
      const ctx = wx.createCameraContext()
      ctx.takePhoto({
        quality: 'high',
        success: (res) => {
          var tmpPath=res.tempImagePath;
          wx.navigateTo({
            url: '/pages/takePhoto/scanning/scanning',
            success: function(res) {
              // 通过eventChannel向被打开页面传送数据
              res.eventChannel.emit('acceptDataFromOpenerPage', { imagePath: tmpPath })
            }
          })
        }
      })

?

? scanning.js

? 接收页onLoad并接收图片临时地址

? onLoad()中

	//接收传送的数据
    const eventChannel= this.getOpenerEventChannel()
    eventChannel.on('acceptDataFromOpenerPage', function (data) {
      console.log('图片路径:'+data.imagePath)
      that.setData({facePhotoUrl:data.imagePath})
      /*****图片转base64*****/
    })

? eventChannel.on({})中

  • 图片转base64
      //图片转base64
      const fs=wx.getFileSystemManager()
      // 同步接口
      try {
        const res = fs.readFileSync(that.data.facePhotoUrl, 'base64', 0)
        console.log("scanning页成功获取到base64!")
        that.data.facePhotoBase64=res;
      } catch(e) {
        console('scanning页base64获取失败!')
        console.error(e)
      }

引用的外部js文件

const util=require("../../../utils/util");

util.js

数据库的操作

①查询

查询UserPrivateInfo的skinAnalyzeInspect

//openId查询数据库
const  queryDbByOpenId = async (collectionName,openid) =>{
  return new Promise((resolve)=>db.collection(collectionName).where({
    _openid:_.eq(openid)
  }).get({success:res=>{resolve(res.data)}})).then((val)=>{return val})//.data//{success:res=>{console.log(res.data[0])}}
}

人脸检测与皮肤分析主要逻辑

app.js

    //初始化云开发
    wx.cloud.init({
      env: '',//cloud1-6g4fn1e1fc689993
      traceUser: true,
    })

scanning.js

一、余额查询与判断

全局数据:
freeTimes (免费次数)
remainingTimes (剩余购买的次数)
局部数据:

事件逻辑
appLunch()时
查询免费次数并保存到globalData.freeTimes
查询剩余付费次数并保存到globalData.userInfo.remainingTimes
查询单价(元/次)并保存到globalData.charge
    let chargeConfig=await util.queryDbById('Settings','charge_manage')
    // console.log("价格:"+chargeConfig.cost_each_time+"元/次")
    this.globalData.charge=chargeConfig.cost_each_time;
    // console.log('免费次数:'+chargeConfig.free_times)
    this.globalData.freeTimes=chargeConfig.free_times;

统计用户检测次数amount(已保存的用户分析记录数)

用户检测皮肤前进行判断
amount小于等于(免费次数+剩余付费次数),直接进行检测
大于(免费次数+剩余付费次数)询问支付(查询次数不足,是否前往付费?)
选择“否”,返回上一页
选择“是”,跳转到支付界面
选择支付套餐(次数*globalData.charge),选择支付数量
支付完成之后
更新数据库,更新全局数据globalData.userInfo.remainingTimes,更新页面数据
在用户个人主页显示可用次数
购买的总数+免费总数-已用总数

二、人脸检测API鉴权与请求

此处仅列出思路

1.查询settings中自己保存的的api相关请求token信息

util.js
// util.queryDbAll('Settings')
//数据库中获取到自己请求api的一些配置信息

2.api鉴权并请求人脸识别

getFaceResult()

3.人脸检测并反馈结果

faceDetect()

三、皮肤分析结果与显示

skinAnalyze()

数据库的查询

①费用相关

app.js

//初始化云开发
wx.cloud.init({
  env: '你的云开发环境id',//cloud1-6g4fn1e1fc689993
  traceUser: true,
})

util.js

const db=wx.cloud.database();

//id查询数据库
const  queryDbById = async (collectionName,id) =>{ //async内有同步方法
  return (await db.collection(collectionName).doc(id).get()).data //await同步
}
module.exports = {
  queryDbById
}

引用页.js

const util=require('../../utils/util')//引用util.js

onReady:async function(){//同步
    let chargeConfig=await util.queryDbById('Settings','charge_manage')//同步查询,必须要await,否侧console.log(chargeConfig)为F{}空结果
    console.log(chargeConfig)
}

②API相关

util.js

//id更新数据库
const updateDbById = async (collectionName,id,keyvalue) =>{
  await db.collection(collectionName).doc(id).update({
    data:keyvalue
  })
}
  /**
   * 获得百度Access_Token
   * new promise 实现同步返回新的token
   */
  const getAPIgrant = async function (key) {
    let that = this;
    var client_id = key.API_Key; //client_id: 必须参数,应用的API Key;
    var client_secret = key.Secret_Key; //client_secret: 必须参数,应用的Secret Key;
    var Access_Token
    return new Promise(
      (resolve) => {
        wx.request({
          url: 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret + '&',
          method: 'GET',
          dataType: 'json',
          success: res => {
            console.log('人脸检测API Access Token 请求成功!')
            const newTime = Math.round(Date.parse(res.header.Date)/1000) //Math.round(Date.parse(new Date())/1000);获取13位当前时间戳,/1000再向上取整,精确到秒
            //本次更新时间,保存到数据库
            that.updateDbById('Settings', 'bd_face_detect_token', {
              ['lastUpdateTime']: newTime,
              ['Access_Token']: res.data.access_token,
              ['effictiveTime']: res.data.expires_in
            })
            Access_Token = res.data.access_token;
            console.log('新授权token:' + Access_Token);
            resolve(Access_Token)
          },
          fail: res => {
            console.log("人脸检测API Access Token请求失败:");
            console.log(res)
          }
        })
      }).then((value) => {
      getApp().globalData.API.Access_Token = value
      // console.log(value)
      return value
    })
  }
  /**
   * 判断是否允许直接进行检测
   */
  const isDetectAllow = async ()=>{
    var num={}; var freeTimes=0; var paidTimes=0;
    return new Promise((resolve)=>{
      num = db.collection("FaceInfo").count();//FaceInfo集合(权限为仅创建者可读写)中当前用户的测肤记录数,也是最后一条测肤记录的编号
      resolve(num)
    }).then((value)=>{
      freeTimes = getApp().globalData.freeTimes//免费次数
      paidTimes = getApp().globalData.userInfo.reaminingTimes//购买的次数
      // console.log(value.total)
      return ( value.total <= (freeTimes+paidTimes) )? true : false;
    })

app.js

    //查询API相关信息
    var key=await util.queryDbById('Settings','bd_face_detect_token')
    // console.dir( util.queryDbAll('Settings'))
    getApp().globalData.API.Access_Token=key.Access_Token
    var timestamp = Math.round(Date.parse(new Date())/1000);//获取13位当前时间戳,/1000再向上取整,精确到秒
    console.log("当前时间戳:"+timestamp)
    var gap=timestamp-key.lastUpdateTime
    if(gap>=key.effictiveTime){//token超过有效期
      //重新获取access_token,更新全局数据global.data.API.Access_Token
      getApp().globalData.API.Access_Token = (await util.getAPIgrant(key))
      // console.log(getApp().globalData.API.Access_Token)
    }

③用户皮肤分析余额相关

applunch()时 查询当前用户余额及检测次数并存至全局globalData.remaning_times
查询当前用户皮肤分析次数并存至global.skinAnalyzeAmount
如果查询到的结果为空,
则发起注册登录
思路一:
1.用户注册时,remaining_times自动置为free_times
2.用户分析皮肤时,判断remaining_times>0,
    如果True继续检测
	如果False,发起支付,支付(charge*数量)完成后,remainning_times+=数量,更新数据库,更新全局变量
3.分析完成后,将remaining_times-1,并更新数据库

思路二:
1.用户注册时,remaining_times置为0
2.用户分析皮肤时,判断分析次数<=remaining_times+free_times,
    如果True继续检测
	如果False,发起支付,支付(charge*数量)后,remainning_times+=数量,更新数据库,更新全局变量
3.分析完成后,如果amount<=free_times,则免费次数剩余=free_times-amount,付费余额剩余remainning_times,否则免费次数=0,
免费次数剩余:次;付费次数剩余:次


1.在app.js的onlunch()查询用户数据
如果找到,则更新globalData.userInfo.remainingTimes、globalData.userInfo.skinAnalyzeInspect
更新globalData.userInfo.detectAllow
如果没有找到,则将globalData.userInfo置为undefined
    //用户数据管理
    // let userPriInfo=await util.queryDbById('UserPrivateInfo','bb4c25156261752300d2ebbd49f05d7a')
    // let userPriInfo=await util.queryDbByOpenId('UserPrivateInfo','oid')//通过openid查询
    var userPriInfo =await util.queryDbAll('UserPrivateInfo')
    userPriInfo=userPriInfo[0];
    if(userPriInfo){
      console.log("剩余可用次数:"+userPriInfo.remaining_times)
      this.globalData.userInfo.reaminingTimes=userPriInfo.remaining_times
      console.log("皮肤分析指标:"+userPriInfo.skinAnalyzeInspect)
      this.globalData.userInfo.skinAnalyzeInspect=userPriInfo.skinAnalyzeInspect
      this.globalData.userInfo.detectAllow=await util.isDetectAllow()
      console.log("允许直接检测:"this.globalData.userInfo.detectAllow)
    }else{
      //用户还未使用过小程序,需要初始化账户
      this.globalData.userInfo=undefined
      console.log("用户"+this.globalData.userInfo+"\n新用户需注册")
    }

2.在scanning.js中
判断globalData.userInfo是否undefined
若是,则注册并初始化用户数据
若否则,直接使用globalData.userInfo的数据,进行下一步操作
3.判断globalData.userInfo.detectAllow
若为T,直接请求API
若为F,则询问并支付
(返回看思路二)

皮肤检测事件逻辑

皮肤分析结果页展示出来后,remaining_times–

否则不更新remaining_times

10.云函数的使用

在 project.config.json 文件中添加以下字段

//  
 "cloudfunctionRoot": "cloudbase/"

新建云函数目录cloudfunctions

cloudfunctions下新建node.js云函数getopenid

index.js中编写云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    // event,
    openid: wxContext.OPENID,
    // appid: wxContext.APPID,
    // unionid: wxContext.UNIONID,
  }
}

config.json中配置触发器(可选)

{
  "permissions": {
    "openapi": [
    ]
  },
  "triggers": [
    {
      "name": "tomylove",
      "type": "timer",
      "config": "0  0  2  1  *  *  *"
    }
  ]
}

最后右键保存部署到云环境

其它内容**详见微信官方云开发文档

11.Home页

在这里插入图片描述

使用模板template

实现多个页面引入topBar

在这里插入图片描述

模板页

/template/topBar.wxml

<template name="topBar">
  <view style="display: flex; flex-direction:column; align-items: center; font-size: smaller; padding:10rpx; position: relative; width:100%" class='wux-energized--bg wux-light'>
    <view style='position: absolute;top:0rpx;left:0rpx;display: flex;align-items: center;height:100%; width:35%; overflow: scroll;'>
      <wux-avatar wx:if="{{avatarUrl}}" bind:tap='{{openSettings}}' src='{{avatarUrl}}' style="margin: 10rpx;"></wux-avatar>
      <wux-icon wx:else="{{avatarUrl}}" bindtap="{{initAccount}}" style="margin: 10rpx;" type="ios-contact" size="40" color="#f0f0f0" />
      {{nickName}}
    </view>
    <view><wux-avatar style="margin: 10rpx 10rpx;" size='large' src='https://636c-cloud1-6g4fn1e1fc689993-1309475441.tcb.qcloud.la/photos/%E7%99%BD%E8%BE%B9%E5%9C%86%E8%A7%92logo.png?sign=e773d7f0b3b6337c6b572ce0a80dd8ba&t=1651971170'></wux-avatar>Magic Mirror</view>
  </view>
</template>

引用页

以home页为例

home.wxml

<import src="/template/topBar" />
<template  is="topBar" data="{{...userInfo}}" ></template>

传入数据和绑定事件

home.js

  data: {
    userInfo:{
      avatarUrl:'',//https://636c-cloud1-6g4fn1e1fc689993-1309475441.tcb.qcloud.la/photos/%E7%99%BD%E8%BE%B9%E5%9C%86%E8%A7%92logo.png?sign=e773d7f0b3b6337c6b572ce0a80dd8ba&t=1651971170
      nickName:'',
      openSettings:'openPerson',
      initAccount:'initAccount'
    }
  },
page({
      openPerson:()=>{
    wx.showModal({
      title:'hello',
    })
  },
  initAccount:()=>{
    wx.showToast({
      title: 'hello',
    })
  }
})

魔镜用户默认头像base64 icon:

data:image/svg+xml;base64,PHN2ZyB0PSIxNjM2NjEzNDY0Mjg4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI0OTcwIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTQyOS4zIDU0NC4xYy00MS4zLTI0LjEtNjUuNy01NS4xLTg0LjItMTA3bC0xLjQtMy41Yy0zLjUtNi45LTEwLjUtMTEuMS0xOC41LTExLjEtMi4yIDAuMS00LjIgMC41LTYuMSAxLjEtOS4xIDMuMi0xNC42IDEyLjYtMTMgMjIuN2wxLjMgNC40YzIxLjIgNTkuNyA1MS4xIDk3LjUgOTkuOSAxMjYuNCAwLjEgMCA3LjIgNC44IDExIDQuOGwyLjggMC4xYzEuOS0wLjEgMy45LTAuNCA1LjgtMS4xIDEwLjQtMy43IDE1LjgtMTUuMiAxMi4xLTI1LjctMS42LTUuMS01LjMtOS4yLTkuNy0xMS4xek0zMTcuOSA0MTIuOWM1LjQtMS44IDkuOC01LjUgMTIuNS0xMC43IDIuNi01LjEgMy0xMC45IDEuMy0xNi40LTIuOS04LjktMTEuMS0xNC44LTIwLjQtMTQuOC0yLjIgMC00LjQgMC40LTYuNyAxLjEtMTEuMiAzLjctMTcuNCAxNS44LTEzLjcgMjcgMi45IDguOSAxMS4xIDE0LjggMjAuNCAxNC44IDIuMiAwLjEgNC40LTAuMyA2LjYtMXoiIGZpbGw9IiNGRjY0NzYiIHAtaWQ9IjI0OTcxIiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pMzgiIGNsYXNzPSJzZWxlY3RlZCI+PC9wYXRoPjxwYXRoIGQ9Ik02ODIuOCA2NjkuM2M5My45LTU3LjcgMTU2LjgtMTYwLjcgMTU2LjgtMjc4LjMgMC0xODAuNC0xNDcuNi0zMjcuMi0zMjguOS0zMjcuMlMxODEuOCAyMTAuNiAxODEuOCAzOTFjMCAxMTcuNiA2Mi45IDIyMC42IDE1Ni44IDI3OC4zbC0xMzQgMTcwLjFjLTkuMiAxNi41LTEwLjYgMzUtMTAuNiA0NC42IDAgNTAuOCAyNiA3NS43IDY2LjIgNzUuN2g1MDEuMWM0MC4yIDAgNjYuMi0yNC45IDY2LjItNzUuNyAwLTE3LjgtMy4yLTMxLjQtMTAuNC00NC4zTDY4Mi44IDY2OS4zek0yNDIuNyAzOTFjMC0xNDYuOCAxMjAuMi0yNjYuMyAyNjgtMjY2LjNzMjY4IDExOS40IDI2OCAyNjYuMy0xMjAuMiAyNjYuMy0yNjggMjY2LjMtMjY4LTExOS41LTI2OC0yNjYuM3ogbTQ5NC4xIDUwNi4xSDI4NC43Yy0xMy41IDAtMjIuNS0xMi4xLTIyLjUtMjQuMiAwLTQuOCAwLTcuMyAyLjMtMTIuMWwxMjcuNC0xNjUuMWMzNi45IDE0LjMgNzYuOSAyMi41IDExOC45IDIyLjVzODEuOS04LjEgMTE4LjktMjIuNUw3NTcgODYwLjhjMi4yIDIuNCAyLjIgNy4zIDIuMiAxMi4xIDAuMSAxMi4xLTguOSAyNC4yLTIyLjQgMjQuMnoiIGZpbGw9IiNmZmZmZmYiIHAtaWQ9IjI0OTcyIj48L3BhdGg+PHBhdGggZD0iTTYyOS42IDY5NS43Yy0zNi45IDE0LjMtNzYuOSAyMi41LTExOC45IDIyLjUtNDEuOSAwLTgxLjktOC4xLTExOC45LTIyLjVMMjY0LjQgODYwLjhjLTIuMyA0LjgtMi4zIDcuMy0yLjMgMTIuMSAwIDEyLjEgOSAyNC4yIDIyLjUgMjQuMmg0NTIuMWMxMy41IDAgMjIuNS0xMi4xIDIyLjUtMjQuMiAwLTQuOCAwLTkuNy0yLjItMTIuMUw2MjkuNiA2OTUuN3oiIGZpbGw9IiNmZmZmZmYiIHAtaWQ9IjI0OTczIj48L3BhdGg+PC9zdmc+

使用fabButton浮动按钮

请添加图片描述

更改

/components/lib/fab-button

.wux-fab-button{position:absolute;z-index:1020}

app.json

 "wux-fab-button": "./components/lib/fab-button/index"

wxml

<view style='height:100rpx;width:100%;position:fixed;bottom:135rpx;left:0'>
  <view style="height:100%; width:100%; position:relative;">
    <wux-fab-button
    position="center"
    theme="energized"
    hideShadow='true'
    scale='1.1'
    backdrop='true'
    direction="circle"
    sAngle="110"
    eAngle="250"
    buttons="{{ buttons }}"
    bind:change="onChange"
    bind:click="onClick"
    />
  </view>
</view>

js

data:

    buttons:[
      {
        // openType: '',
        // hoverClass:'wux-light wux-assertive--bg',
        label: 'Camera',
        icon:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPkNhbWVyYTwvdGl0bGU+PHBhdGggZD0iTTM1MC41NCAxNDguNjhsLTI2LjYyLTQyLjA2QzMxOC4zMSAxMDAuMDggMzEwLjYyIDk2IDMwMiA5NmgtOTJjLTguNjIgMC0xNi4zMSA0LjA4LTIxLjkyIDEwLjYybC0yNi42MiA0Mi4wNkMxNTUuODUgMTU1LjIzIDE0OC42MiAxNjAgMTQwIDE2MEg4MGEzMiAzMiAwIDAwLTMyIDMydjE5MmEzMiAzMiAwIDAwMzIgMzJoMzUyYTMyIDMyIDAgMDAzMi0zMlYxOTJhMzIgMzIgMCAwMC0zMi0zMmgtNTljLTguNjUgMC0xNi44NS00Ljc3LTIyLjQ2LTExLjMyeiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjxjaXJjbGUgY3g9IjI1NiIgY3k9IjI3MiIgcj0iODAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMzIiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjMyIiBkPSJNMTI0IDE1OHYtMjJoLTI0djIyIi8+PC9zdmc+',
        hideShadow:true,
      },
      {
        // openType: '',
        // hoverClass:'wux-light wux-assertive--bg',
        label: 'Image',
        icon:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPkltYWdlPC90aXRsZT48cmVjdCB4PSI0OCIgeT0iODAiIHdpZHRoPSI0MTYiIGhlaWdodD0iMzUyIiByeD0iNDgiIHJ5PSI0OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMzIiLz48Y2lyY2xlIGN4PSIzMzYiIGN5PSIxNzYiIHI9IjMyIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjMyIi8+PHBhdGggZD0iTTMwNCAzMzUuNzlsLTkwLjY2LTkwLjQ5YTMyIDMyIDAgMDAtNDMuODctMS4zTDQ4IDM1Mk0yMjQgNDMybDEyMy4zNC0xMjMuMzRhMzIgMzIgMCAwMTQzLjExLTJMNDY0IDM2OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjwvc3ZnPg==',
        hideShadow:true
      },
      {
        // openType: '',
        // hoverClass:'wux-light wux-assertive--bg',
        label: 'Create',
        icon:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPkJydXNoPC90aXRsZT48cGF0aCBkPSJNNDUyLjM3IDU5LjYzaDBhNDAuNDkgNDAuNDkgMCAwMC01Ny4yNiAwTDE4NCAyOTQuNzRjMjMuMDggNC43IDQ2LjEyIDI3LjI5IDQ5LjI2IDQ5LjI2bDIxOS4xMS0yMjcuMTFhNDAuNDkgNDAuNDkgMCAwMDAtNTcuMjZ6TTEzOCAzMzZjLTI5Ljg4IDAtNTQgMjQuNS01NCA1NC44NiAwIDIzLjk1LTIwLjg4IDM2LjU3LTM2IDM2LjU3QzY0LjU2IDQ0OS43NCA5Mi44MiA0NjQgMTIwIDQ2NGMzOS43OCAwIDcyLTMyLjczIDcyLTczLjE0IDAtMzAuMzYtMjQuMTItNTQuODYtNTQtNTQuODZ6IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjMyIi8+PC9zdmc+',
        hideShadow:true
      }
      
    ]

onClick事件

  onClick(e) {
    console.log('onClick', e.detail)
    switch(e.detail.index) {
      // wx.switchTab({
        // url: '/pages/index/index',
      // })
      case 0:
        this.camera()
        break;
      case 1:
        this.image()
        break;
      case 2:
        this.create()
        break;
      }
  },
  image:function(){
    wx.showModal({
      title:'image',
      cancelColor: '#000',
    })
  },
  camera:function(){
    wx.showModal({
      title:'camera',
      cancelColor: '#000',
    })
  },
  create:function(){
    wx.showModal({
      title:'create',
      cancelColor: '#000',
    })
  }

maddleBar

在这里插入图片描述

maddleBar.wxml

<template name="middleBar_logo">
  <view style="display: flex; flex-direction:column; align-items: center; font-size: smaller; padding:10rpx; position: relative; width:100%; font-size: larger; font-weight: bolder;" class='wux-royal '>
    <view><wux-avatar style="margin: 10rpx 10rpx;" size='large' src='https://636c-cloud1-6g4fn1e1fc689993-1309475441.tcb.qcloud.la/photos/%E7%99%BD%E8%BE%B9%E5%9C%86%E8%A7%92logo.png?sign=e773d7f0b3b6337c6b572ce0a80dd8ba&t=1651971170'></wux-avatar>Magic Mirror</view>
  </view>
</template>

person.wxml

<import src="/template/middleBar" />

卡片1

在这里插入图片描述

app.json

    "wux-card": "./components/lib/card/index",
    "wux-wing-blank": "./components/lib/wing-blank/index",
    "wux-grids": "./components/lib/grids/index",
    "wux-grid": "./components/lib/grid/index"

引入页.js

	avatar:'/images/logo/logo.png',
    nickName:'孤勇者',
    free_times:0,
    remain_times:0,

引入页.wxml

    <wux-wing-blank size="default">
      <wux-card
        title="{{nickName}}"
        extra="我的账户"
        thumb="{{avatar}}"
        thumb-style="border-radius: 50%;"

      >
        <view slot="body">
          <wux-grids col="2">
            <!-- <wux-grid thumb="" label="follow" />
            <wux-grid thumb="" label="follwer" />
            <wux-grid thumb="" label="enshrine" />
            <wux-grid thumb="" label="shop" /> -->
            <wux-grid thumb="" label="剩余免费{{free_times}}次" />
            <wux-grid thumb="" label="剩余付费{{remain_times}}次" />
          </wux-grids>
        </view>
        <view slot="footer">
        </view>
      </wux-card>
    </wux-wing-blank>

卡片2

在这里插入图片描述

<wux-wing-blank size="default">
  <wux-card extra="">
    <view slot="body">
      <!-- <wux-cell-group title="测肤设置"> -->
        <wux-popup-select value="{{ value2 }}" options="{{ options2 }}" multiple data-index="2" bind:confirm="onConfirm" bind:valueChange="onValueChange">
          <wux-cell thumb="{{inspectOptions}}" title="测肤指标" label='肤色、光滑度、痣、皱纹、黑眼圈···' is-link extra="自定义"></wux-cell>
        </wux-popup-select>
        <wux-cell thumb="{{analyzeHistory}}" is-link extra="测肤记录"></wux-cell>
      <!-- </wux-cell-group> -->
    </view>
  </wux-card>
</wux-wing-blank>

.js

data

    inspectOptions:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPk9wdGlvbnM8L3RpdGxlPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMzIiIGQ9Ik0zNjggMTI4aDgwTTY0IDEyOGgyNDBNMzY4IDM4NGg4ME02NCAzODRoMjQwTTIwOCAyNTZoMjQwTTY0IDI1Nmg4MCIvPjxjaXJjbGUgY3g9IjMzNiIgY3k9IjEyOCIgcj0iMzIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMzIiLz48Y2lyY2xlIGN4PSIxNzYiIGN5PSIyNTYiIHI9IjMyIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjMyIi8+PGNpcmNsZSBjeD0iMzM2IiBjeT0iMzg0IiByPSIzMiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjwvc3ZnPg==',
    analyzeHistory:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPkFuYWx5dGljczwvdGl0bGU+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIgZD0iTTM0NCAyODBsODgtODhNMjMyIDIxNmw2NCA2NE04MCAzMjBsMTA0LTEwNCIvPjxjaXJjbGUgY3g9IjQ1NiIgY3k9IjE2OCIgcj0iMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMzIiLz48Y2lyY2xlIGN4PSIzMjAiIGN5PSIzMDQiIHI9IjI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjMyIi8+PGNpcmNsZSBjeD0iMjA4IiBjeT0iMTkyIiByPSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjxjaXJjbGUgY3g9IjU2IiBjeT0iMzQ0IiByPSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjwvc3ZnPg==',
            value2:['001','002','003','004','005','006'],
        options2: [
      {
        title: '肤色',
        value: '001',
      },
      {
        title: ' 光滑度',
        value: '002',
      },
      {
        title: '痘、斑、痣',
        value: '003',
      },
      {
        title: '皱纹',
        value: '004',
      },
      {
        title: '黑眼圈、眼袋',
        value: '005',
      },
      {
        title: '毛孔、黑头',
        value: '006',
      }
    ],

app.json

    "wux-popup-select": "./components/lib/popup-select/index",
    "wux-cell-group": "./components/lib/cell-group/index",
    "wux-cell": "./components/lib/cell/index"

卡片3

xml

<wux-wing-blank size="default">
      <wux-card title="" extra="分享社区" thumb="">
        <view slot="body">
          <wux-cell thumb="{{articleShare}}" is-link extra="我的贴子"></wux-cell>
          <wux-cell thumb="{{articleEnshrine}}" is-link extra="我的收藏"></wux-cell>
          </view>
        <!-- <view slot="footer">尾部内容</view> -->
      </wux-card>
    </wux-wing-blank>

data

articleShare:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPkRvY3VtZW50IFRleHQ8L3RpdGxlPjxwYXRoIGQ9Ik00MTYgMjIxLjI1VjQxNmE0OCA0OCAwIDAxLTQ4IDQ4SDE0NGE0OCA0OCAwIDAxLTQ4LTQ4Vjk2YTQ4IDQ4IDAgMDE0OC00OGg5OC43NWEzMiAzMiAwIDAxMjIuNjIgOS4zN2wxNDEuMjYgMTQxLjI2YTMyIDMyIDAgMDE5LjM3IDIyLjYyeiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMzIiLz48cGF0aCBkPSJNMjU2IDU2djEyMGEzMiAzMiAwIDAwMzIgMzJoMTIwTTE3NiAyODhoMTYwTTE3NiAzNjhoMTYwIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjMyIi8+PC9zdmc+',
    articleEnshrine:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpb25pY29uIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPlN0YXI8L3RpdGxlPjxwYXRoIGQ9Ik00ODAgMjA4SDMwOEwyNTYgNDhsLTUyIDE2MEgzMmwxNDAgOTYtNTQgMTYwIDEzOC0xMDAgMTM4IDEwMC01NC0xNjB6IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIzMiIvPjwvc3ZnPg==',

limit查询加载首页推荐列表

在这里插入图片描述

wx:for 循环来加载推荐列表

xml


<wux-wing-blank>
  <!-- 文章推荐列表 -->
  <block wx:for="{{articleList}}" wx:for-item="items">
  <view style="height:310rpx; margin-top: 10rpx; margin-bottom: 15rpx; border-radius: 12rpx; overflow: hidden; box-shadow: 0rpx 0rpx 30rpx rgb(216, 216, 216);"  bindtap="navToArticle" data-articleid='{{index}}'><!--卡片-->
    <view style="height: 75%;" class="wux-light--bg"><!--配图 标题 描述-->
      <view style="width: 40%;height:100%; ;float:left;display:flex;align-items: center;/*垂直居中*/justify-content: center;">
        <!-- <view style="width:80%;height:80%;background-color: chartreuse; "></view>配图 -->
        <image style="width:85%;height:82%; ; border-radius: 15rpx" mode="aspectFill" src="{{items.layoutPicture?items.layoutPicture:'/images/logo/logo.png'}}"></image>
      </view>
      <view style="width: 60%;height:100%; ;float:right;"><!--标题 文字 display: flex;align-items: center;-->
        <view style="height:50%; ; font-weight: bolder; margin-left: 10rpx; margin-right: 10rpx; display:flex; align-items: center;/*垂直居中*/"><!--标题-->
          <view style="margin-top:10rpx;" class="wux-ellipsis--l2">{{items.title?items.title:"标题加载中"}}</view>
        </view>
        <view style="height:50%; ; margin-left: 10rpx; margin-right: 10rpx; display:flex; align-items: center;/*垂直居中*/ color:rgb(128, 132, 143)"><!--简介   background-clip: content-box; padding: 0.6em; padding-top: 0; -->
          <view style="margin-bottom: 10rpx;" class="wux-ellipsis--l2">{{items.subTitle?items.subTitle:"简介加载中"}}</view>
        </view>
      </view>
    </view>
    <view style="height: 25%; background-color: rgb(255, 240, 243);" class="wux-energized--border" ><!--头像 点赞 评论 收藏
    border: 1rpx solid; border-left: 0; border-bottom: 0; border-right: 0; -->
      <view style="width: 40%;height:100%; float:left"><!--头像昵称-->
        <view style="width: 30%;height:100%; ;float:left;display:flex;align-items: center;/*垂直居中*/justify-content: center;">
          <wux-avatar src="{{items.userAvatar?items.userAvatar:'/images/logo/logo.png'}}"></wux-avatar><!--头像-->
        </view>
        <view style="width: 70%;height:100%; ;float:left; display: flex; align-items: center; font-weight: bolder;" class="wux-royal"><view class="wux-ellipsis">{{items.nickName?items.nickName:""}}</view></view><!--昵称  white-space: nowrap; text-overflow: ellipsis; overflow:hidden; -o-text-overflow:ellipsis;-->
      </view>
      <view style="width: 60%;height:100%; ; float:right; font-size: smaller; color:rgb(128, 132, 143) "><!--点赞 评论 转发-->
        <view style="width: 34%;height:100%; ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--点赞-->
          <wux-icon type="md-thumbs-up" size="30"  class="wux-royal wux-margin-right--5" />
          <text>{{items.like?items.like:0}}</text>
        </view>
        <view style="width: 33%;height:100%; ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--评论-->
          <wux-icon type="md-text" size="30" class="wux-royal wux-margin-right--5 wux-margin-top--5" />
          <text>{{items.discuss?items.discuss:0}}</text>
        </view>
        <view style="width: 33%;height:100%; ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--转发-->
          <wux-icon type="md-share-alt" size="30" class="wux-royal wux-margin-right--5" />
          <text>{{items.share?items.share:0}}</text>
        </view>
      </view>
    </view>
  </view>
  </block>
</wux-wing-blank>

util.js

//分页查询
const queryDBbyLimt=async function(collectionName,skipNum,limitNum,condition){
  return (await db.collection(collectionName)
    .where(
      condition
    )
    // .field({
    //   name: true,
    //   price: true,
    // })
    .orderBy('like', 'desc')
    .skip(skipNum)
    .limit(limitNum)
    .get()
  ).data
}

home.js

const util=require('../../utils/util')
let app=getApp();
let begin=0;
const step=4;

data

    articleList:[
    ]

onload()

    //加载四篇文章
    let aList=await util.queryDBbyLimt('Articles',begin,step,{visibility:true});
    // console.log(articleList);
    this.setData({articleList:aList})
    getApp().globalData.showArticleList=aList;//赋给全局数组
    console.log(this.data.articleList)

点击跳转事件

  navToArticle(e){
    // console.log(e.target);//点击的view
    // console.log(e.currentTarget);//有绑定事件的view
    var url='/pages/...';
    var articleid=e.currentTarget.dataset['articleid']
    // wx.showToast({
    //   icon:'none',
    //   title: data.detail.dataset,
    // })
    // wx.navigateTo({
    //   url: 'url?id=${articleid}',
    // })
    console.log(`${url}?id=${articleid}`)
   }

打开新页面展示文章

  navToArticle(e){
    // console.log(e.target);//点击的view
    // console.log(e.currentTarget);//有绑定事件的view
    var pageUrl='/pages/article/readArticle';
    var articleid=e.currentTarget.dataset['articleid']
    wx.navigateTo({
      url: `${pageUrl}?id=${articleid}`,
    })
   }

下拉触底加载更多

onReachBottom()

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom:async function () {
    //跳跃加载
    wx.showToast({
      icon:'loading',
      title: 'loading',
    })
    begin+=step;
    var addList=await util.queryDBbyLimt('Articles',begin,step,{visibility:true});

    console.log(addList)
    wx.hideToast({})
    if(addList==false){
      wx.showToast({
        icon:'none',
        title: '暂无更多内容',
        duration:1500
      })
    }else{   
       // this.data.articleList.concat(addList);//追加数组
       getApp().globalData.showArticleList=getApp().globalData.showArticleList.concat(addList)
      this.setData({
        articleList:this.data.articleList.concat(addList)
      })
    }
  },

浏览文章页

xml

<view class="container" style="height:{{editorHeight}}px;">
  <editor
    id="editor"
    class="ql-container" 
    placeholder="{{'正在加载...'}}" 
    bindready="onEditorReady"
    read-only="{{true}}"
    >
  </editor>
</view>

js

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    let app=getApp();
    // console.log(app.globalData.showArticleList[options.id]);//第i篇文章
    this.setData({article:app.globalData.showArticleList[options.id]})
    const { windowHeight, platform } = wx.getSystemInfoSync()
    let editorHeight = windowHeight //占满屏幕
    this.setData({ editorHeight })
  },
onEditorReady() {
    const that = this
    let app=getApp()
    wx.createSelectorQuery().select('#editor').context(function (res) {
      that.editorCtx = res.context //必备初始化语句
      let article=that.data.article;
      if(article){
        var title=article.title;
        // that.editorCtx.insertText({html:`<h2>${title}</h2>`})
        that.editorCtx.setContents({
          // html:article.html,
          // text:article.text,
          delta:article.content,
          fail:res=>{
            console.log(res)
          }
        })
      }
    }).exec()
  },

wxss

@import "/components/editor/assets/iconfont.wxss";
@import "/components/common/lib/weui.wxss";
.container {
  position: absolute; 
  top: 0; 
  left: 0; 
  width: 100%;
}
.ql-container {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  font-size: 16px;
  line-height: 1.5;
  overflow: auto;
  padding: 10px 10px 20px 10px;
  border: 1px solid #ECECEC;
}

半屏窗

在这里插入图片描述

template xml

<template name="middleBar_logo2">
  <view style="display: flex; flex-direction:column; align-items: center; font-size: smaller; position: relative; width:100%; font-weight: bolder;" class='wux-light '>
    <view><wux-avatar style="margin: 5rpx 5rpx;" size='large' src='https://636c-cloud1-6g4fn1e1fc689993-1309475441.tcb.qcloud.la/photos/%E7%99%BD%E8%BE%B9%E5%9C%86%E8%A7%92logo.png?sign=e773d7f0b3b6337c6b572ce0a80dd8ba&t=1651971170'></wux-avatar>Magic Mirror</view>
  </view>
</template>

wxss

.recordBtn{
  border-radius: 18rpx;
  /* border: 1rpx solid rgb(255, 100, 118);
  box-shadow: 1rpx 1rpx 10rpx rgb(255, 100, 118);
  color: rgb(255, 100, 118); */
  margin-top: 18rpx;
  width: 48%;
  font-size: 28rpx;
  padding-top: 18rpx;
  padding-bottom: 18rpx;
  background-color: #fff;
  text-align: center;
  font-weight: bolder;
}
.settingBtn{
  width: 100%;
  border-radius: 18rpx;
  margin-top: 18rpx;
  padding-top: 15rpx;
  padding-bottom: 15rpx;
  background-color: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  color:rgb(155, 155, 155);
}

app.json

  "useExtendedLib": {
    "weui": true
  },

usingcomponent

"mp-half-screen-dialog": "weui-miniprogram/half-screen-dialog/half-screen-dialog"

12.Shop购物页

在这里插入图片描述

json

    "wux-row": "./components/lib/row/index",
    "wux-col": "./components/lib/col/index"

xml

<wux-row>
      <wux-col span="6" wx:for="{{goodsList}}" wx:for-key="{{item._id}}">
      <!-- class="wux-energized--bg" class="wux-balanced--bg"-->
        <view  style="height:350rpx;border-radius: 15rpx;overflow: hidden;margin: 15rpx 15rpx 15rpx 15rpx;box-shadow: 0 0 20rpx rgb(216, 209, 255);">
          <view  style="height:280rpx; ;bottom: 0rpx; background-image: url('{{item.imgurl}}'); background-repeat: no-repeat;background-size:contain;background-position: center">
          </view><!-- background-color: rgba(173, 86, 255, 0.828); -->
          <view style="height:70rpx; background-color: white; bottom: 0rpx; color: gray;">
              <view style="width: 34%;height:100%; ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--浏览-->
            <wux-icon type="md-eye" size="22"  class="wux-calm wux-margin-right--5" />
            <text>{{item.watching}}</text>
            </view>
            <view style="width: 33%;height:100%; ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--评论-->
              <wux-icon type="md-text" size="22" class="wux-calm wux-margin-right--5" />
              <text>{{item.discussion}}</text>
            </view>
            <view style="width: 33%;height:100%;  ;float:left; display:flex;align-items: center;/*垂直居中*/ justify-content: center;/*水平居中*/"><!--收藏-->
            <wux-icon type="md-star" size="22" class="wux-calm wux-margin-right--5" />
            <text>{{item.stars}}</text>
          </view>
          </view>
        </view>
      </wux-col>
    </wux-row>

js

data

goodsList:[
      {
          _id:0,
          imgurl:'http://cdn.skyvow.cn/logo.png',
          navurl:'',
          goodsInfo:'',
          watching:0,
          discussion:0,
          stars:0
      },
      {
          _id:1,
          imgurl:'http://cdn.skyvow.cn/logo.png',
          navurl:'',
          goodsInfo:'',
          watching:0,
          discussion:0,
          stars:0
      },
      {
          _id:2,
          imgurl:'http://cdn.skyvow.cn/logo.png',
          navurl:'',
          goodsInfo:'',
          watching:0,
          discussion:0,
          stars:0
      },
      {
        _id:3,
        imgurl:'http://cdn.skyvow.cn/logo.png',
        navurl:'',
        goodsInfo:'',
        watching:0,
        discussion:0,
        stars:0
      },
]

onload()

  onLoad: async function (options) {
    let app=getApp();
    const db=wx.cloud.database()
    let goods=await db.collection('Goods').where({}).limit(8).get()
    goods=goods.data
    console.log(goods)
    app.globalData.goods=goods
    this.setData({
      pageHeight:app.globalData.windowHeight,
      ['userInfo.avatarUrl']:app.globalData.userInfo.avatarUrl,
      ['userInfo.nickName']:app.globalData.userInfo.nickName,
      ['userInfo.bgc']:app.globalData.presentTheme.lightBgColor,
      presentTheme:app.globalData.presentTheme,
      themeName:app.globalData.presentTheme.deepColor.match(/wux-(\S*)/)[1],
      goodsList:goods,
      
    })
    var j=0;
    var tabs1=[];
    var contents=[];
    for(var i=0;i<goods.length;i++){
      contents.push(goods[i].product_name)
      if((i+1)%3==0){
        tabs1[j]={
          key:"tab"+(j+1),
          title:"推荐"+(j+1),
          content:contents
        }
        console.log(contents)
        contents=[]
        j++
      }
    }
    if(i>=1){
      if(contents!=false){
        tabs1.push({ 
          key:"tab"+(j+1),
          title:"推荐"+(j+1),
          content:contents}
        )
      }
      this.setData({
        tabs1:tabs1,
        tabsHeight:tabs1.length*87<520?tabs1.length*87:520
      }) 
    }
  },

13.富文本编辑及提交存储

程序流程逻辑

在这里插入图片描述

具体实现

wxss

@import "../common/lib/weui.wxss";
@import "./assets/iconfont.wxss";

.container {
  position: absolute; 
  top: 0; 
  left: 0; 
  width: 100%;
}

.ql-container {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  font-size: 16px;
  line-height: 1.5;
  overflow: auto;
  padding: 10px 10px 20px 10px;
  border: 1px solid #ECECEC;
}

.ql-active {
  color: #7044ffc4;
}

.iconfont {
  display: inline-block;
  width: 30px;
  height: 30px;
  cursor: pointer;
  font-size: 20px;
}

.toolbar {
  box-sizing: border-box;
  padding: 0 10px;
  height: 50px;
  width: 100%;
  position: fixed;
  left: 0;
  right: 100%;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid #ECECEC;
  border-left: none;
  border-right: none;
}

wxml

<view style="height:{{editorHeight}}px;">
  
    <editor id="editor" class="ql-container" placeholder="{{placeholder}}" bindstatuschange="onStatusChange" bindready="onEditorReady">
      <!--show-img-size='{{true}}' show-img-resize='{{true}}' -->
    </editor>
    <wux-wing-blank size="default">
      <wux-button block outline type="royal" bindtap="submit">提交</wux-button>
    </wux-wing-blank>
    <wux-backdrop id="wux-backdrop"  /> 

</view>

<view class="toolbar" catchtouchend="format" hidden="{{keyboardHeight > 0 ? false : true}}" show-img-toolbar="{{true}}" style="bottom: {{isIOS ? keyboardHeight : 0}}px">
  <i class="iconfont " bindtap="indentClick"> ? </i>
  <i class="iconfont icon-charutupian" catchtouchend="insertImage"></i>
  <i class="iconfont icon-format-header-2 {{formats.header === 2 ? 'ql-active' : ''}}" data-name="header" data-value="{{2}}"></i>
  <i class="iconfont icon-format-header-3 {{formats.header === 3 ? 'ql-active' : ''}}" data-name="header" data-value="{{3}}"></i>
  <i class="iconfont icon-zitijiacu {{formats.bold ? 'ql-active' : ''}}" data-name="bold"></i>
  <i class="iconfont icon-zitixieti {{formats.italic ? 'ql-active' : ''}}" data-name="italic"></i>
  <i class="iconfont icon-zitixiahuaxian {{formats.underline ? 'ql-active' : ''}}" data-name="underline"></i>
  <i class="iconfont icon-juzhongduiqi {{formats.align === 'center' ? 'ql-active' : ''}}" data-name="align" data-value="center"></i>
  <i class="iconfont icon-zuoyouduiqi {{formats.align === 'justify' ? 'ql-active' : ''}}" data-name="align" data-value="justify"></i>
  <i class="iconfont icon-youduiqi {{formats.align === 'right' ? 'ql-active' : ''}}" data-name="align" data-value="right"></i>
  <i class="iconfont icon-youxupailie {{formats.list === 'ordered' ? 'ql-active' : ''}}" data-name="list" data-value="ordered"></i>
  <i class="iconfont icon-wuxupailie {{formats.list === 'bullet' ? 'ql-active' : ''}}" data-name="list" data-value="bullet"></i>
  <i class="iconfont icon-undo {{formats.redo === 'undo' ? 'ql-active' : ''}}" data-name='undo' bindtap="undo"></i>
</view>

js

const util=require('../../utils/util')
import { $wuxBackdrop } from '../../components/lib/index'
// var tmpimages=[];//图片数组路径
Page({
  data: {
    locks:0,
    show:false,

    formats: {},
    readOnly: false,
    placeholder: '分享你的护肤小妙招吧!',
    editorHeight: 300,
    keyboardHeight: 0,
    isIOS: false,

    tempimageid: 1,
    imageid: 1,
    image:[
      // {
      //   imageid:0,
      //   imageurl:'null'
      // }
    ],
    result:[]//图片上传成功后的url数组
  },
  readOnlyChange() {
    this.setData({
      readOnly: !this.data.readOnly
    })
  },
  onLoad() {
    const platform = wx.getSystemInfoSync().platform
    this.$wuxBackdrop = $wuxBackdrop()
    const isIOS = platform === 'ios'
    this.setData({ isIOS})
    const that = this
    this.updatePosition(0)
    let keyboardHeight = 0
    wx.onKeyboardHeightChange(res => {
      if (res.height === keyboardHeight) return
      const duration = res.height > 0 ? res.duration * 1000 : 0
      keyboardHeight = res.height
      setTimeout(() => {
        wx.pageScrollTo({
          scrollTop: 0,
          success() {
            that.updatePosition(keyboardHeight)
            that.editorCtx.scrollIntoView()
          }
        })
      }, duration)
    })

  },
  updatePosition(keyboardHeight) {
    const toolbarHeight = 50
    const { windowHeight, platform } = wx.getSystemInfoSync()
    let editorHeight = keyboardHeight > 0 ? (windowHeight - keyboardHeight - toolbarHeight-60) : (windowHeight-80)
    this.setData({ editorHeight, keyboardHeight })
  },
  calNavigationBarAndStatusBar() {
    const systemInfo = wx.getSystemInfoSync()
    const { statusBarHeight, platform } = systemInfo
    const isIOS = platform === 'ios'
    const navigationBarHeight = isIOS ? 44 : 48
    return statusBarHeight + navigationBarHeight
  },
  onEditorReady() {
    const that = this
    let app=getApp()
    wx.createSelectorQuery().select('#editor').context(function (res) {
      that.editorCtx = res.context //必备初始化语句
      let article=getApp().globalData.article;
      if(article){
        that.editorCtx.setContents({
          // html:article.html,
          // text:article.text,
          delta:article.delta,
          fail:res=>{
            console.log(res)
          }
        })
      }
    }).exec()
  },
  blur() {
    this.editorCtx.blur()
  },
  undo(){
    this.editorCtx.undo()
  }
  ,
  format(e) {
    let { name, value } = e.target.dataset
    if (!name) return
    // console.log('format', name, value)
    this.editorCtx.format(name, value)

  },
  onStatusChange(e) {
    const formats = e.detail
    this.setData({ formats })
  },
  insertDivider() {
    this.editorCtx.insertDivider({
      success: function () {
        console.log('insert divider success')
      }
    })
  },
  clear() {
    let that=this;
    this.editorCtx.clear({
      success: function (res) {
        // html='<p><br></p>';
        // text='\r';
        // imagesTempPath=[];
        console.log("clear success")
      }
    })
  },
  removeFormat() {
    this.editorCtx.removeFormat()
  },
  insertDate() {
    const date = new Date()
    const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`
    this.editorCtx.insertText({
      text: formatDate
    })
  },
  insertImage() {
    const that = this
    var max=1//3
    wx.chooseImage({
      count: max,
      success: function (res) {
        let tmpId=that.data.tempimageid
        // console.log(res.tempFilePaths)
        var i = 0
        // for(; i < res.tempFilePaths.length ; i++){
          that.editorCtx.insertImage({
            src: res.tempFilePaths[i], //插入图片临时文件地址
            data: {
              id: tmpId, //临时图片id
            },
            width: '100%',
            success: function () {
              that.data.image.push({id:tmpId,url:res.tempFilePaths[i]})
                // imagesTempPath.push(res.tempFilePaths[i]);//追加到图片数组中
              //   tmpimages.push({id:tmpid,url:res.tempFilePaths[i],success:function(){
              //    tmpid+=1//临时图片id加1
              //  }})
                // console.log('insert image success '+(imagesTempPath.length-1)+":"+res.tempFilePaths[i])
                that.data.tempimageid=tmpId+1;
                console.log(tmpId+" "+res.tempFilePaths[i]);
            }
          })
        // }
      }
    })
  }
  ,
  /*提交*/
  submit: function(){
    let app=getApp()
  //   if(!app.globalData.hasUserInfo){wx.showToast({
  //     icon:'none',
  //     title: '请先登录后进行操作',
  //     duration:2000
  //   })
  //   return;
  // }
    let that=this; 
    var time= util.formatTime(new Date());
    var visible=true;//可见性
    let title='';
    let subTitle='';
    // that.insertDate();
    that.editorCtx.getContents({
       success:async function(res){ //async await 问题
        // html = res.html;
        // text = res.text;
        if(!res.text.replace(/\s+/g, '').length ==0 ){ //&&!res.text.replace(/\s+/g, '\r') if (res.html !== constTxt) {
          // var flag=0;
          // console.log("检测到输入内容" ) //+ res.text
          // console.log(res.delta);

          //替换res.delta中的图片url

          let images=that.data.image;
          console.log(images.length+"张临时图片")
          var length = res.delta.ops.length;
          wx.showLoading({
            title: '正在上传',
          })
          for (var i = 0; i < length; i++) {
            if(res.delta.ops[i].attributes){//筛选出里面的图片
              let imageId=that.data.imageid;  
              var _id =parseInt(res.delta.ops[i].attributes['data-custom'].trim().slice(3));//取出临时图片的id
              for (var j = 0; j < images.length; j++){      
                if (_id === images[j].id){			//与实际图片地址的id比较,并替换图片地址
                    // tmpimages[j].url=await util.uploadFile('image',tmpimages[j].url,'articlePictures/'+ (new Date().getTime())+'.png',{
                    // id: imageId
                    // });//设置图片id,需与临时图片id一致,所以初始化赋值时两个均为0即可
                    res.delta.ops[i].insert.image = await util.uploadFile('image',images[j].url,'articlePictures/'+ (new Date().getTime())+'.png',{
                      id: imageId
                    });
                    that.data.result.push(res.delta.ops[i].insert.image);
                    console.log(_id+" "+that.data.result[imageId-1])
                    that.data.imageid=imageId+1;
                  break;
                }                          
              }        
            }
          }
          // console.log((that.data.imageid-1)+"张实际图片")
          console.log(that.data.result.length+"张实际图片")
          var strify = JSON.stringify(res.delta);//dealta转成字符串变成strify
          console.log(strify);
          //提交审核
          //发布
          utils.addDB('Articles',{
            // 'articleID':'id' 文章ID
            'title':title, //标题
            'subTitle':subTitle, //子标题
            'images': that.data.result,//图片数组
            'content':res.delta,
            'time':time,// 发布时间
            'like':0,// 点赞数
            'discuss':0,// 评论数 
            'collect':0,// 收藏数
            'visibility': visible//可见性
          });
          wx.hideLoading({
            success: (res) => {
              console.log('文章发布成功')
            },
          })
          var arrParse = JSON.parse(strify);//strify转成数组变回dealta,这里的arrParse是等于dealta的
          console.log(arrParse);
        } else {
          // console.log(res.html)
          wx.showModal({
            showCancel: false,
            title: '提示',
            content: '内容不能为空或仅包含图片'
          })
          return;
        }
      }
    });


  },

  onUnload: function () {
    let that=this;
    that.editorCtx.getContents({
      success: res=>{
        // html=res.html;
        // text=res.text;
        let content=res;
        if (!res.text.replace(/\s+/g, '').length ==0) {//res.html!==constTxt内容不为空
        wx.showModal({
          title: '要放弃编辑的内容吗?',
          // cancelColor: '#000000',
          confirmColor:'#f00',
          success (res) {
            if (res.confirm) {
              console.log('用户点击确认');
              that.clear();
            } else if (res.cancel) {
              console.log('用户点击取消');
              getApp().globalData.article=content
              console.log(content)
            }
          }
        })
      }
      }
    });
    
  },
  //缩进
  indentClick(){
    this.editorCtx.insertText({
      text: "??"
    })
  },
  retain() {
    this.$wuxBackdrop.retain()
    this.setData({
      locks: this.$wuxBackdrop.backdropHolds,
      show:true//显示组件
    })
  },
  release() {
    this.$wuxBackdrop.release()
    this.setData({
      locks: this.$wuxBackdrop.backdropHolds,
      show:false
    })
  }
})


以上是对本人前段时间开发魔镜微信小程序过程中所写的代码和笔记,上传到CSDN方便日后复习回顾。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:17:25  更:2022-08-19 19:22:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:30:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码