一级片大奶子_色又黄又爽18禁免费视频_热久久久久久久_久久久精品一区二区_日韩av不卡在线播放_精品国内自产拍在线观看视频

商城系統 注冊

小程序預覽碼如何生成

2018-07-18|HiShop
導讀:小程序開發時,會可能會需要開發一個預覽碼,那么需要怎么開發,下面是開發詳細流程及發布過程...

小程序開發時,會可能會需要開發一個預覽碼,那么需要怎么開發,下面是開發詳細流程及發布過程

小程序預覽碼如何生成

找微信開發者工具的接口

最重要的事情莫過于看看微信開發者工具有沒有給我們提供這樣的接口讓我們去操作,經過一番查閱文檔我們會發現,果然有!

https://developers.weixin.qq....
會發現,文檔給我們提供了兩種方式的接口,命令行調用以及HTTP調用。有了接口,一切都好辦了,無非就是調一下接口,拿到二維碼,貼到頁面上去而已嘛,很簡單。

梳理開發流程
我們就把這個簡單的事情,用流程圖說明一下:
https://www.processon.com/vie...

小程序預覽碼如何生成

 

所需技術

工欲善其事,必先利其器,我們要搞這個東西,還是先要把用到的技術整理一下。

  1. 微信開發者工具
  2. 一個小程序項目(這里以一個mpvue項目為例子)
  3. 前端vue + vux,這里前端沒什么需要做的東西,這樣的搭配純屬是因為本來就正在做移動端的東西,直接拿來用而已。
  4. 后端koa2,當然后端用什么都可以,這里選擇koa2,純屬是因為我也不會用別的……
  5. 前后端HTTP請求統一用axios
  6. 涉及到node操作命令行需要用到shelljs

好像沒別的東西了,用到了再說吧。

擼起袖子從后端開始

為了省事,直接把前后端的東西放在一起。項目目錄:

 

小程序預覽碼如何生成

可以看到server這個目錄下放的都是后端的東西。

server/index.js
先看看入口文件index.js,從這里我們可以知道后端要做兩件事情,第一要能訪問到前端build出來的靜態資源,第二要能與前端通過HTTP接口進行交互。見代碼:

const path = require('path')
const Koa = require('koa')
const koaStatic = require('koa-static')
const bodyParser = require('koa-bodyparser')
const router = require('./router')
const app = new Koa()
const port = 9871
app.use(bodyParser())
// 處理靜態資源 這里是前端build好之后的目錄
app.use(koaStatic(
  path.resolve(__dirname, '../dist')
))
// 路由處理接口
app.use(router.routes()).use(router.allowedMethods())
// 監聽端口
app.listen(9871)
console.log(`[demo] start-quick is starting at port ${port}`)

靜態資源方面的話使用koa-static即可,重點是怎樣給前端提供接口,這就要看路由了。

server/router/index.js

const Router = require('koa-router')
// 業務邏輯
const wx = require('../controller/wx')
const router = new Router({
  // 接口前綴 比如open接口 請求路徑就是/api/open
  prefix: '/api'
})
router.get('/open', wx.open)
  .get('/login', wx.login)
  .get('/preview', wx.preview)
  .get('/build', wx.build)
module.exports = router

這里可以清晰看到,后端提供了四個接口,但具體每個接口的業務邏輯則封裝在controller里的wx.js,如果以后還有別的業務邏輯,就在controller加相應的模塊即可。

server/controller/wx.js

// 微信開發者工具接口調用邏輯
const {open, login, preview, build} = require('../utli/wxToolApi')
// 處理成功失敗返回格式的工具
const {successBody, errorBody} = require('../utli')
class WxController {
  /**
   * 根據環境對mpvue項目進行打包
   * @returns {Promise<void>}
   */
  static async build (ctx) {
    // 前端傳過來的get參數
    const query = ctx.request.query
    if (!query || !query.env) {
      ctx.body = errorBody(null, '構建項目失敗')
      return
    }
    const [err, data] = await build(query.env)
    ctx.body = err ? errorBody(err, '構建項目失敗') : successBody(data, '構建項目成功')
  }
  /**
   * 打開微信開發者工具
   * @returns {Promise<void>}
   */
  static async open (ctx) {
    const [err, data] = await open()
    ctx.body = err ? errorBody(err, '打開微信開發者工具失敗') : successBody(data, '打開微信開發者工具成功')
  }
  /**
   * 登錄微信開發者工具
   * @returns {Promise<void>}
   */
  static async login (ctx) {
    const [err, data] = await login()
    ctx.body = err ? errorBody(err, '登錄二維碼返回失敗') : successBody(data, '登錄二維碼返回成功')
  }
  /**
   * 查看預覽碼
   * @returns {Promise<void>}
   */
  static async preview (ctx) {
    const [err, data] = await preview()
    ctx.body = err ? errorBody(err, '預覽二維碼返回失敗') : successBody(data, '預覽二維碼返回成功')
  }
}
module.exports = WxController

為了代碼更加清晰,這里將具體操作微信開發者工具的接口邏輯抽到util/wxToolApi.js里去了,僅僅處理怎樣以統一格式返回給前端。
util/wxToolApi.js

const {promiseWrap, successBody, errorBody} = require('../utli')
const {INSTALL_PATH, PROJECT_PATH, PORT_PATH, PORT_FILE_NAME, HOST} = require('../const')
const {readFile} = require('../utli/nodeApi')
const shell = require('shelljs')
const axios = require('axios')
module.exports = {
  /**
   * 根據環境對mpvue項目進行打包
   * @param env [doc, pre, prd]
   * @returns {*}
   */
  build (env) {
    return promiseWrap(new Promise((resolve, reject) => {
      // 進入項目目錄
      shell.cd(PROJECT_PATH)
      // 執行打包命令
      shell.exec(`npm run build:${env}`, function (code, stdout, stderr) {
        resolve(stdout)
      })
    }))
  },
  /**
   * 打開微信開發者工具
   * @returns {*}
   */
  open () {
    return promiseWrap(new Promise((resolve, reject) => {
      // 進入項目目錄
      shell.cd(INSTALL_PATH)
      // 執行微信開發者工具接口“命令行啟動工具”
      shell.exec(`cli -o ${PROJECT_PATH}`, function (code, stdout, stderr) {
        if (stderr) return reject(stderr)
        resolve(stdout)
      })
    }))
  },
  /**
   * 獲取微信開發者工具端口號
   * @returns {Promise<*>}
   */
  async getPort () {
    shell.cd(PORT_PATH)
    // http 服務在工具啟動后自動開啟,HTTP 服務端口號在用戶目錄下記錄,可通過檢查用戶目錄、檢查用戶目錄下是否有端口文件及嘗試連接來判斷工具是否安裝/啟動。
    const [err, data] = await readFile(PORT_FILE_NAME)
    return err ? errorBody(err, '讀取端口號文件失敗') : successBody(data, '讀取端口號文件成功')
  },
  /**
   * 微信開發者工具進行登錄
   * @returns {*}
   */
  login () {
    return promiseWrap(new Promise(async (resolve, reject) => {
      // 獲取端口號
      const portData = await module.exports.getPort()
      if (portData.code !== 0) {
        reject(portData)
        return
      }
      const port = portData.data
      axios.get(`http://${HOST}:${port}/login?format=base64`)
        .then(res => {
          resolve(res.data)
        })
        .catch(e => {
          reject(e)
        })
    }))
  },
  /**
   * 微信開發者工具獲取預覽碼
   * @returns {*}
   */
  preview () {
    return promiseWrap(new Promise(async (resolve, reject) => {
      const portData = await module.exports.getPort()
      if (portData.code !== 0) {
        reject(portData)
        return
      }
      const port = portData.data
      axios.get(`http://${HOST}:${port}/preview?format=base64&projectpath=${encodeURIComponent(PROJECT_PATH)}`)
        .then(res => {
          resolve(res.data)
        })
        .catch(e => {
          reject(e)
        })
    }))
  }
}

這里有一點需要注意,為什么只有open接口需要用命令行調用方式?那是因為HTTP調用方式必須加端口,比如open接口

# 打開工具
http://127.0.0.1:端口號/open
# 打開/刷新項目
http://127.0.0.1:端口號/open?projectpath=項目全路徑

如果你根本都沒有打開微信開發者工具,在以下地方就會找不到端口:

端口號文件位置:

macOS : ~/Library/Application Support/微信web開發者工具/Default/.ide

Windows : ~/AppData/Local/微信web開發者工具/User Data/Default/.ide

所以作為一個全自動化打碼工具,怎么可能還要自己去手動打開微信開發者工具呢!

前端

后端的東西基本就那么多,終于到前端了,前端十分簡單,就不多說了:

<template>
  <div>
    <group title="請選擇環境">
      <radio :options="envOption" v-model="env"></radio>
    </group>
    <x-button class="btn" type="default" @click.native="handlePreviewProject">點擊預覽</x-button>
    <div v-if="loginImg" class="code">
      <divider>請先登錄</divider>
      <img class="code-img" :src="loginImg"    </div>
    <div v-if="preImg" class="code" id="preImg">
      <divider>預覽二維碼</divider>
      <img class="code-img" :src="`${base64Prefix}${preImg}`"    </div>
  </div>
</template>

<script>
import {openProject, login, previewProject, buildProject} from 'SERVICES/index'
import {showLoading, hideLoading} from 'UTILS'
import { Divider, XButton, Radio, Group } from 'vux'
export default {
  data () {
    return {
      // data表示取得數據的協定名稱,image/png 是數據類型名稱,base64 是數據的編碼方法,逗號后面就是這個image/png文件base64編碼后的數據。
      base64Prefix: 'data:image/png;base64,',
      // 登錄二維碼
      loginImg: '',
      // 預覽二維碼
      preImg: '',
      // 環境 默認為doc
      env: 'doc',
      // 所有的環境選項
      envOption: ['doc', 'pre', 'prd']
    }
  },
  components: {
    Divider,
    XButton,
    Radio,
    Group
  },
  methods: {
    handleError (msg) {
      alert(msg)
    },
    async login () {
      const {data: {code, data, msg}} = await login()
      if (code !== 0) {
        this.handleError(msg)
        return code
      }
      this.loginImg = data
      return code
    },
    async previewProject () {
      const {data: {code, data, msg}} = await previewProject()
      if (code !== 0) {
        this.handleError(msg)
        return code
      }
      this.preImg = data
      return code
    },
    async handlePreviewProject () {
      showLoading()
      // 重置二維碼
      this.resetImg()
      // 打開微信開發者工具
      const {data: {code}} = await openProject()
      if (code !== 0) {
        // 登錄微信開發者工具
        await this.login()
        hideLoading()
        return
      }
      // 根據環境打包
      await buildProject(this.env)
      // 預覽
      await this.previewProject()
      hideLoading()
    },
    resetImg () {
      this.loginImg = ''
      this.preImg = ''
    }
  }
}
</script>

<style lang='less'>
  .btn {
    width: 90%!important;
    margin: 30px auto 30px auto;
  }
  .code {
    display: flex;
    align-items: center;
    flex-direction: column;
    .code-img {
      width: 300px;
      height: 300px;
    }
  }
</style>

這里有一個坑就是,login返回的base64是帶了data:image/jpeg;base64,前綴的,所以可以直接放到img的src里,但是獲取預覽碼的preview返回的卻沒有這個前綴!所以需要自己加上去,就是那個base64Prefix:'data:image/png;base64,'

最后

其實到這里已經基本實現了整個打碼功能,但如果真的要可以用還有很多事情沒做。

  1. 部署到測試機器上。雖然可以直接用自己的機子作為部署這個工具的機器,但這實在是有點……如果要部署到測試機器上,有一個問題就是,微信開發者工具依賴圖形界面,而服務器一般是命令行,雖然有 https://github.com/cytle/wech... 這樣的項目移植微信開發者工具到linux,但這種部署方式似乎還是怪怪的。
  2. 假設完成了上述部署,進行小程序項目打包的環節需要修改一下,變成根據選擇的環境,到相應的代碼倉庫(比如gitlab)拉取該環境的最新代碼,然后進行安裝依賴才能執行打包命令。
  3. 既然都做到這一步了,也不差把上傳小程序也加上去,微信開發者工具接口也有提供,這樣一來整個測試打碼到上線的步驟都有了。

HiShop小程序工具提供多類型商城/門店小程序制作,可視化編輯 1秒生成5步上線。通過拖拽、拼接模塊布局小程序商城頁面,所看即所得,只需要美工就能做出精美商城。更多小程序商店請查看:小程序商店

電話咨詢 預約演示 0元開店
主站蜘蛛池模板: 铠甲勇士全52集免费播放|饥渴丰满少妇大力进入|免费女人高潮流视频在线观看|欧美国产国产综合|麻豆tv在线观看|男人操女人的免费视频 | 龙珠z国语版普通话免费播放|人妻阿敏被老外玩弄系列|久久露脸国语精品国产91|国产成人午夜精品影院观看视频|91视频一区二区|国产高清露脸孕妇系列 | 日本xxx大片免费观看|久色在线三级三级三级免费看|视频一区在线播放|国产=a∨国片精品白丝美女视频|天美传媒=aV成人片免费看|成人天堂yy6080亚洲高清 | 日本免费中文字幕|狠狠操综合网|国产一区二区=av在线|国产91精清纯白嫩高中在线观看|少妇特黄V一区二区三区|免费看荫蒂添的好舒服视频 | 久久亚洲=aV成人无码软件|91亚洲网|成人在线看片|成人做爰www网站视频|粉嫩=av一区二区三区高清|免费一级片91 | 亚洲免费看片网站|欧美香蕉|久久免费视老师机影片|国产精品成人久久小草|日本熟妇大屁股人妻|性色=a∨人人爽网站HDkp885 | 一级影片在线观看|亚洲精品久久久久9999吃药|免费毛片wwwcomcn|91一级片|超碰人人精品|GOGO亚洲肉体艺术 | 亚洲免费不卡视频|国精产品一品二品国精品69XX|欧美色p|国产成人黄色网址|国产成人无码免费看片软件|欧美一二区在线观看 | 日本一区三区|欧美成人日韩|中国内地毛片免费高清|影音先锋国产精品|成人一级福利|精品一区二区三区国产 | 久久久久资源|亚洲精品中文字幕在线播放|免费大香伊蕉在人线国产|成人久久久久|精品99人妻|午夜成午夜成年片在线观看 | 一级女毛片|日本美女bb视频|尹人成人|亚洲成人=av观看|亚洲精品中文字幕制|91人成亚洲高清在线观看 | 狠狠躁天天躁又黄又爽|亚洲精品无码国产一区二区|黄色影视在线观看|国产精品福利网|久在线看|亚洲视频国产 | 福利综合网|成年人网站黄色|欧美大陆国产|日韩视频在线免费|精品国产一区二区三区久久久久久|奇米超碰在线 | 国产精品麻豆高潮刺激=a片|国产=aⅴ无码专区亚洲=av|草草在线视频|亚洲日韩精品无码专区加勒比|国产精品激情|成全视频观看免费高清第6季 | 国产精品麻豆高潮刺激=a片|国产=aⅴ无码专区亚洲=av|草草在线视频|亚洲日韩精品无码专区加勒比|国产精品激情|成全视频观看免费高清第6季 | 国产精品视频专区|国产在线国产|精品一区二区三区成人精品|国产不卡在线观看免费视频|蜜桃综合|欧美精品日韩一区 | 久久激情久久|国产人妻久久精品二区三区|国产人妖=av|中日韩免费=av|日本一区2区|欧美亚洲国产第一精品久久 | 超碰在线进入|一级全黄少妇免费录像片|欧美大成色WWW永久网站婷|免费看=a=a=a=a=a级淫片涩爱=av|亚洲=av成人一区二区三区在线观看|99一级片 | 亚洲国产精品热久久|亚洲免费大全|欧美成人ccc大片|国产精品二三区|国产V片在线播放免费无码|亚洲精品久久国产高清 | 强乱中文字幕=av一区乱码|1204国产成人精品视频|精品无码国产一区二区三区=aV|亚洲国产精品一区二区成人片不卡|99久久无码一区人妻=a片竹菊|无码中文字幕=av免费放 | 日韩=av在线中文|三年片在线观看大全中国|日韩视频在线观看中文字幕|91在线看免费|免费人成在线观看视频无码|一个人看的视频www在线观看 | 三区视频在线观看|中文字幕第2页|色吧在线播放|啦啦啦视频在线观看高清免费|日本ⅹxxxx久色视频免费观看|亚洲精品久久久久久久蜜臀老牛 | 干亚洲美女|亚洲视频精选|91国自视频|亚洲一级影片|韩国三级在线中文字幕无码|xxx黄色片 | 荡乳欲妇在线观看|小次郎=av收藏家|国产亚洲日韩在线=a不卡|亚洲天堂久久久久久久|国产精品福利在线播放|国产成人无码=a片免费 | 水蜜桃一区二区|特黄特黄=a级毛片免费专区|99久免费视频精品老司机|#NAME?|狠狠综合久久久久尤物|欧美成人精品在线观看 | 台湾久久网|99久久精品免费看国产四区|亚洲一区二区三区在线视频观看|一区二区三区四区在线免费视频|红桃视频二区|国产久艹视频 | 国产一级黄色|美女把尿口扒开让男人桶|sif=angtv国产在线|亚洲一级毛片色视频|一级二级三级=av|特级理论片 | 亚洲精品网站在线观看|国产精品美女久久福利网站|久久xxxx|亚洲精品精品|国产激情99|国产高清无码日韩一区 | 日韩三级在线免费观看|久久艹艹|色爱综合另类图片=av|国内久久精品视频|xx69在线观看|亚洲国产一区二区精品 | 91经典视频|国产高清在线精品一区二区三区|久久男女视频|最新亚洲=av日韩=av一区二区三区|五月综合激情|国产一=a | 超碰人人草人人干|精品国产伦一区二区三区观看方式|无码中文字幕人妻在线一区二区三区|隔壁老王国产在线精品|在线欧美精品一区二区三区|91在线视频九色 | 亚洲第一视频专区|亚洲一区二区三区高清不卡|亚洲а∨天堂久久精品|亚洲一区二区三区麻豆|无码福利写真片视频在线播放|久久久人人人 | 国产高跟丝袜脚交视频|最短的距离是圆的高清在线观看|一区二区三区视频播放|国产精品黄页在线播放免费|#NAME?|精品国产乱码久久久久久中文 | 无码免费婬=aV片在线观看|免费黄色小视频在线观看|eeuss鲁丝片=aV无码|国产精品videossexohd|亚洲欧美成人一区二区在线|久久www免费人成网站 | 好男人日本社区www|国产精品乱码一区二三区小蝌蚪|欧亚精品一区|国产欧美在线免费观看|我爱草逼网|乱码专区一卡二卡国色天香 | 日本三级韩国三级欧美三级|日韩黄色大片免费看|美国黄色小视频|久久精品国产亚洲=aV麻豆~|中文字幕人成人|一级在线免费 | 中文字幕在线观看视频www|在线视频网站WWW色|91啦国产|国产社区精品视频|91毛片免费观看|国产一区二区黑人欧美xxxx | 无码免费婬=aV片在线观看|免费黄色小视频在线观看|eeuss鲁丝片=aV无码|国产精品videossexohd|亚洲欧美成人一区二区在线|久久www免费人成网站 | 美女=aV一区二区三区|九九热久久这里只有精品|国产精品免费不卡|少妇的BBBB爽爽爽自慰|中文字幕乱码久久午夜不卡|天天做日日做天天爽视频免费 | 欧美在线中文字幕|亚洲天堂成人|国产一区二区精品久久91|精品人妻无码一区二区三区GIF|久久亚洲精品情侣|国产成人在线影院 | 东北寡妇特级毛片免费|99热精品国产一区二区在线观看|亚洲=aV永久纯肉无码精品动漫|国产成人一区二区三区|午夜=av一区二区|久久久久久久久久久动漫 国产1区在线观看|四房播播成人社区|嫩草影视亚洲|免费毛片在线不卡|久久亚洲精品国产一区最新章节|911免费看片 |