小程序-心理學辭典應用開發的心得

小程序-心理學辭典應用開發的心得

前言

最近學習小程序,用了五天工做之餘從0開始,到一個簡單的App完成,有點心得,記錄下來。html

想法

最近在學習算法動態規劃那部分,有點感悟,不要想着怎麼樣讓總體結果最優,由於在系統足夠複雜的狀況下太消耗時間。若是按貪婪算法的思路,讓每一步都是當下最優,也許結果並非最優,但也足夠優秀了,關鍵時間很快。
因此此次寫項目改了思路,不像以前設計的很完整後再作,此次只先作最核心的功能,其餘功能暫時用簡單技術替代,先作出東西來,再慢慢優化。
坑仍是隻有走過了才印象深入。vue

預備工做

前陣子剛學習了心理學皮毛,裏面有個心理學詞典的內容,我以爲很受用,就像作個詞典類的App,讓我能時常回顧溫習,運氣好的話還能夠幫助到別人。
因此個人核心需求就是:作個「心理學辭典」,可以瀏覽各個詞條,並推薦一些文章供擴展閱讀。
花了點時間大體構思了下,我要作的事情有:程序員

  • 設計原型
  • 設計界面
  • 設計數據庫
  • 技術選型算法

    • 瀏覽一遍小程序文檔(不用深刻,只須要知道它有哪些能力,在大腦建個索引,須要時能快速查找)
    • 數據庫方案
  • 製做測試數據
  • 開發階段數據庫

    • 界面製做
    • 數據
    • 優化
  • 總結概括

進入開發

設計原型

由於需求簡單,原型也不須要高保真,手繪就搞定了。一個搜索框,一個標籤列表,一個結果列表。一個詞典的內容並不會不少,能夠在列表項中直接作展開。
由於詞典數據量有限,選擇一次加載完全部的項目(包含_id,name,tags),點擊後查詢詳情緩存結果,再展開。
搜索有兩種模式,普通搜索和標籤搜索。爲了更好展現,這裏設計成,tag搜索也當作條件,只是在前面加個「#」號。
具體交互效果可查看小程序。
小程序二維碼json

界面設計

交互稿肯定後,去網絡上找了幾個對眼的設計稿,參考了下,在psd上大體設計了下(設計和PS技術太渣 ( ̄. ̄)|||)小程序

數據庫設計

App的第一階段作純展現,就涉及一張表後端

  • vocabulary(_id, name, tags, content, remark, links, create_at, update_at)

技術選型

小程序的語法很簡單,和Vue有點類似,發展到現在有基於ReactTaro,基於Vuempvue/wepy,還有uni-app。可選擇的挺多的,可是我任然選擇用小程序自帶的語法來寫,畢竟在用其餘語法時,明白其原先的樣子老是有好處的。確實在實際過程當中發現小程序自身語法設計不足與不一樣之處。 數組

數據庫方面,小程序最近推出雲開發的服務,這東西相似LeancloudBmob這些後端雲服務,並且這些第三方的服務對微信支持的也不錯。此次項目選用雲開發,畢竟是一家的,集成的應該會更好一些。不過實際使用過程當中發現這玩意不足的地方不少,大項目慎用。 promise

由於選用的技術都是沒有使用的技術,這裏就要用些策略了,我是這樣作的。

  • 先把文檔大體看下,主要了解下大致狀況,瞭解小程序和雲開發的能力,在腦海裏創建個索引,知道哪些內容文檔裏有,在要用到的時候就能快速查找。
  • 遇到雲開發增刪改查的問題,我是把經常使用的方法和場景都羅列到本身的筆記本里,爲了更方便的查找

製做測試數據

數據源主要來自《武志紅的心理學課》,在課程末尾老師有把講到的關鍵詞都羅列出來了。可是有個問題,老師給的那些資料裏,都是以圖片展現的,若是一個個手動錄入也太不像程序員了。因而找了個Mac下好用的OCR工具iText,App Store裏能夠下載到。如此一來靜態文本數據就不是問題了,可是要怎麼入庫呢?

雲開發裏有個經過CSV或JSON上傳數據的功能。那麼咱們就作個JSON文件吧。
又有個問題,在content字段裏存的是比較複雜的文本數據,JSON文件處理字符串麻煩。因此我借用yaml,把數據卸載yml文件裏,而後寫個函數把結果翻譯成JSON

開發階段

這裏記錄幾個開發過程當中遇到的幾個問題

獲取多條數據

由於雲開發有對取數據作限制,客戶端請求數據最多每次20條,雲函數每次100條。由於個人需求是取出全部詞條的基本數據,因此須要作點工做,我拿官方的代碼稍做修改:

// 雲函數目錄/db_get_many_record/index.js
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const MAX_LIMIT = 100 // 雲函數一次最多獲取100條數據

/**
 * 取出多條數據
 * wx.cloud.callFunction({
    name: 'db_get_many_record',
    data: {
      collection: 'vocabulary',
      field: {
        name: true,
        tags: true
      },
    }
  }).then().catch()
 */
exports.main = async (event, context) => {
  const { collection = "", where, field } = event
  let commond = db.collection(collection)

  if (collection === ""){
    return;
  }
  if(where){
    commond = commond.where(where)
  }

  // 先取出集合記錄總數
  const { total } = await commond.count()
  // 計算需分幾回取
  const batchTimes = Math.ceil(total / 100)
  // 承載全部讀操做的 promise 的數組
  const tasks = []
  
  if (field) {
    commond = commond.field(field)
  }
  for (let i = 0; i < batchTimes; i++) {
    const promise = commond.skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }
  // 等待全部
  return (await Promise.all(tasks)).reduce((acc, cur) => {
    return {
      data: acc.data.concat(cur.data),
      errMsg: acc.errMsg,
    }
  })
}

換存數據

爲了減小請求的次數,提示性能,緩存數據是必要的。我利用app.globalData,和微信提供的Storage能力。
原本是想用Map類型來作數據存儲的,可是Storage不支持這種數據類型。

富文本內容

內容是分段落的,可是小程序自己是不支持html標籤的,但還好有個rich-text的組件能夠用。
如何把本身收集的內容翻譯成html的內容?寫個腳本遍歷下。固然後期會寫個可視化的界面來管理內容。

const fs = require('fs');

const readYaml = require('read-yaml');
readYaml('./data.yml', function(err, data) {
  if (err) throw err;
  // 處理content內容
  let result = data.map(item => {
    let _content = item.content.split(/[\r\n]/).map(item => {
      return '<p style="margin-bottom: .8em;">' + item + '</p>'
    })
    item.content = _content.join("")
    return item
  });

  fs.writeFileSync('./result.json', JSON.stringify(result));
});

補充

總結目前小程序雲開發會用到的代碼

const db = wx.cloud.database()
const _ = db.command
const xxCollection = db.collection('collection')

/////////////////////////////////////// 查詢記錄 ///////////////////////////////////////
xxCollection.doc('id').get()
// ID查詢
db.collection('collection').doc('id').get().then(res => {}).catch(error => {})
// 條件查詢
db.collection('collection').where({}).get()
db.collection('collection').where({name:_.eq('xxx')}).get() // _.eq  neq  lt  lte  gt  gte  in  nin  and  or
// 限制返回字段
db.collection('collection').where({}).field({name: true}).get()
// 排序
db.collection('collection').where({}).orderBy('field', 'asc|desc').get()
// 分頁
db.collection('collection').where({}).skip(0).limit(10).get()
// 統計
db.collection('collection').where({}).count()

/////////////////////////////////////// 新增記錄 ///////////////////////////////////////
db.collection('collection').add({
  data:{
    update_at: db.serverDate(),
    location: db.Geo.Point(113, 23)
  }
})

/////////////////////////////////////// 更新數據 ///////////////////////////////////////
db.collection('collection').where({}).update({})
db.collection('collection').doc('id').set({}) // 替換記錄
db.collection('collection').doc('id').update({
  data:{
    // _.inc(自增) _.set(更新對象使用) _.push _.pop _.shift _.unshift(數組)
  }
})

/////////////////////////////////////// 刪除數據 ///////////////////////////////////////
db.collection('collection').doc('id').remove()
db.collection('collection').where({}).remove() // 目前只能在雲函數裏操做

//////////////////////////////////////// 文件 /////////////////////////////////////////
wx.chooseImage({
  success: chooseResult => {
    // 將圖片上傳至雲存儲空間
    wx.cloud.uploadFile({
      // 指定上傳到的雲路徑
      cloudPath: 'my-photo.png',
      // 指定要上傳的文件的小程序臨時文件路徑
      filePath: chooseResult.tempFilePaths[0]
    })
  },
})
wx.cloud.downloadFile({
  fileID: '',
})
wx.cloud.deleteFile({
  fileID: '',
})
// 換取臨時連接
wx.cloud.getTempFileURL({
  fileList: [],
})

/////////////////////////////////////// 雲函數 ////////////////////////////////////////
wx.cloud.callFunction({
  name: 'methodName', 
  data: {
    a: 12,
  },
  success: res => {},
  fail: error => {},
  complete: () => {}
})
wx.cloud.callFunction({
  name: 'methodName',
  data: {
    a: 12,
  }
}).then(res => {}).catch(error => {})
// error: errCode errMsg

/////////////////////////////////////// 錯誤參考 ///////////////////////////////////////
error => {
  let message;
  switch (error.errCode) {
    case -1:
      message = '通用錯誤'
      break
    case -401001:
      message = '無權限使用 API'
      break
    case -401002:
      message = 'API 傳入參數錯誤'
      break
    case -401003:
      message = 'API 傳入參數類型錯誤'
      break
    case -402001:
      message = '檢測到循環引用'
      break
    case -403001:
      message = '上傳的文件超出大小上限'
      break
    case -404001:
    case -404002:
    case -404003:
    case -404004:
    case -404005:
    case -404006:
    case -404007:
    case -404008:
    case -404009:
      message = '雲函數調用失敗'
      break
    case -404010:
      message = '雲函數執行失敗'
      break
    case -601004:
      message = '無權限使用 API'
      break
    case -501001:
      message = '雲端系統錯誤'
      break
    case -501002:
      message = '雲端響應超時'
      break
    case -501003:
      message = '請求次數超出環境配額'
      break
    case -501004:
      message = '請求併發數超出環境配額'
      break
    case -501005:
      message = '環境信息異常'
      break
    case -501009:
      message = '操做的資源對象非法或不存在'
      break
    case -502001:
      message = '數據庫請求失敗'
      break
    case -502002:
      message = '非法的數據庫指令'
      break
    case -502003:
      message = '無權限操做數據庫'
      break
    case -502005:
      message = '集合不存在'
      break
    case -503001:
      message = '雲文件請求失敗'
      break
    case -503002:
      message = '無權限訪問雲文件'
      break
    case -503003:
      message = '文件不存在'
      break
    case -504001:
      message = '雲函數調用失敗'
      break
    case -504002:
      message = '雲函數執行失敗'
      break
  
    default:
      message = error.errMsg
      break
  }
}

總結

  • 雖然初看小程序的語法和vue有點像,實際作起來,和想象的差太多,不少功能不支持,作起來不是那麼順手
  • 雲開發的能力也頗有限,解決一點簡單數據能夠,稍微複雜點功能要本身用代碼實現
相關文章
相關標籤/搜索