前面已將基礎知識准備的差不多了,下面實際做一個小程序。
一、目標
用於上傳照片和文字。
2個主要頁面:我me,設置set
二、開始制作
1、打開微信開發者工具(我用的1.02.1907160 Windows 64版本),點+號,新建項目diary,選擇目錄E:\wxDEV\diary,填入從微信開發平台申請到的AppID,開發模式默認為小程序,后端服務選擇雲開發,點新建,生成了雲開發QuitStart示例模板。下面在此模板基礎上制作。
2、建立me set頁面,並給小程序增加tabBar。即修改E:\wxDEV\minishop\miniprogram\app.json並保存。代碼如下:
{ "pages": [ "pages/index/index", "pages/me/me", "pages/people/people", "pages/set/set" ], "window": { "backgroundColor": "#F6F6F6", "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#F6F6F6", "navigationBarTitleText": "日記", "navigationBarTextStyle": "black" }, "tabBar": { "backgroundColor": "#eeeeee", "position": "bottom", "list": [ { "pagePath": "pages/me/me", "text": "我", "iconPath": "images/img.jpg", "selectedIconPath": "images/img.jpg" }, { "pagePath": "pages/set/set", "text": "設置", "iconPath": "images/img.jpg", "selectedIconPath": "images/img.jpg" } ] }, "sitemapLocation": "sitemap.json" }
同時,要在images目錄中放置一張img.jpg圖片(我自己畫了一張)
3、我打算將現有的index頁作為將來的splash頁。所以先修改E:\wxDEV\diary\miniprogram\pages\index\index.js,以實現2秒后跳轉me頁,代碼:
//index.js Page({ data: {}, onLoad: function() { setTimeout(function() { wx.reLaunch({ url: '../me/me', }) }, 2000) } })
4、修改me頁(為方便調試,可更改app.json中pages值的順序,將me調整到前面)。原本想在me頁上用movable-view增加可拖動的按鈕樣式,如下:
<!--可拖動按鈕--> <movable-area style="height:{{mHeight}}px;width:100%;position:fixed;z-index:999;pointer-events:none;"> <movable-view direction="all" style="height: 30px; line-height:30px;width: 30px; margin-left:100%; border:2px solid lightblue;border-radius:50%;"> <cover-view bindtap="writeDiary"> <cover-image src='../../images/img.jpg'></cover-image> </cover-view> </movable-view> </movable-area>
結果在安卓真機上出現兼容性問題,拖動時cover-view瞬間移動,而cover-image不跟隨移動,無法正常工作。(誰知道解決辦法給我講一下?)只好棄用。
雲開發的雲函數的獨特優勢在於與微信登錄鑒權的無縫整合,參考:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/userinfo.html
所以,對不同用戶上傳內容可以用openid區分。
5.半成品的me.wxml ,代碼如下:
<!--pages/me/me.wxml--> <view style="display:flex;flex-direction: row-reverse;margin-right:20px;font-size:150%;"><text bindtap="writeDiary">{{inputCursor}}</text></view> <view style="width:100%;"> <!-- 上傳圖片 --> <view class="uploader"> <view class="uploader-text" bindtap="selPic"> <text>拍照或選擇圖片(可選)</text> </view> <view class="uploader-container" wx:if="{{imgUrl}}"> <image class="uploader-image" src="{{imgUrl}}" mode="aspectFit" bindtap="previewImg"></image> </view> </view> <!-- 表單 --> <form class="formpub" bindsubmit="formSubmit" bindreset="formReset"> <!-- 保存圖片臨時路徑 --> <view class="section"> <input name="img" value="{{imgUrl}}" hidden="true" /> </view> <view class="content"> <view class="currentWordNumber">{{currentWordNumber|0}}/{{max}}</view> <!-- 別忘了給textarea加上name屬性 --> <textarea name="diaryContent" bindblur="getText" bindinput="getValueLength" show-confirm-bar='true' value="{{editText}}" bindconfirm="getText" maxlength="{{max}}" minlength="{{min}}" placeholder="內容..." auto-focus> <text class="minWord">{{minWord}}</text> </textarea> </view> <view class="tips">在上面填寫內容</view> <view class="btn-area"> <button form-type="submit" style="width: 80%; margin-top: 20rpx;background-color: beige;color: black;border:2px solid lightblue;">寫完了</button> </view> </form> </view> <block wx:for="{{diarys}}" wx:key="{{index}}"> <view style="display:flex;width:100%;min-height:50px;background:rgb(248, 248, 248);margin:8px;"> <view style="border:20px;"> <image wx:if='{{item["img"]}}' src='{{item["img"]}}'mode="widthFix" style="width:100px;"></image> </view> <view style="width:100%;border-bottom:solid 1px lightgrey;padding-left:10px;"> {{item["content"]}} </view> </view> </block> <view> <image src='../../images/img.jpg' mode="widthFix" style="width:50px"></image> </view>
me.js
// pages/me/me.js Page({ /** * 頁面的初始數據 */ data: { //以下變量也可以不寫在這里,可直接在代碼中聲明和使用,但推薦寫在這里 mHeight: 500, hiddenInput: true, inputCursor: '+', max: 2000, //限制最大輸入字符數 min: 10, //限制最小輸入字符數 minWord: '', //提示語句 imgUrl: '', //要上傳的圖片的url editText: '', //textarea中編輯的內容 diarys: {}, curPage: 1 }, /** * 生命周期函數--監聽頁面加載 */ onLoad: function(options) { }, //寫日記 writeDiary: function() { let tempCursor = '' if (this.data.inputCursor == '+') { tempCursor = '-' } else { tempCursor = '+' } this.setData({ hiddenInput: !this.data.hiddenInput, inputCursor: tempCursor }) //滾動視口,返回頂部 wx.pageScrollTo({ scrollTop: 0, duration: 300 }) }, /****限制字數與計算 */ getValueLength: function(e) { let value = e.detail.value let len = parseInt(value.length) //最少字數限制 if (len <= this.data.min) this.setData({ minWord: "至少填寫10個字哦~" }) else if (len > this.data.min) this.setData({ minWord: " " }) //最多字數限制 if (len > this.data.max) return; this.setData({ currentWordNumber: len //當前字數 }) }, formSubmit: function(e) { console.log('form發生了submit事件,攜帶數據為:', e.detail.value) let upDiaryContent = e.detail.value["diaryContent"] let upimgUrl = e.detail.value["img"] let len = parseInt(upDiaryContent.length) //最少字數限制 if (len <= this.data.min) { this.setData({ minWord: "至少填寫10個字哦~" }) return } wx.showLoading({ title: '請等待', }) //判斷有無圖片 if (typeof upimgUrl == "undefined" || upimgUrl == null || upimgUrl == "") { //沒有圖片,直接上傳文字 const db = wx.cloud.database() db.collection('diarys').add({ data: { content: upDiaryContent }, success: res => { //無圖,文字上傳成功了 this.reset() console.log('[數據庫] [新增記錄] 成功,記錄 _id: ', res._id) }, fail: err => { wx.showToast({ icon: 'none', title: '新增記錄失敗' }) console.error('[數據庫] [新增記錄] 失敗:', err) } }) } else { //有圖片,則先上傳圖片 const timestamp = new Date().getTime(); const relCloudPath = 'diarys/' + timestamp + upimgUrl.match(/\.[^.]+?$/)[0] console.log(1) console.log(upimgUrl) console.log(relCloudPath) wx.cloud.uploadFile({ cloudPath: relCloudPath, filePath: upimgUrl, success: res => { console.log('[上傳文件] 成功:', res) let imgFileID = res.fileID //再上傳文字 const db = wx.cloud.database() db.collection('diarys').add({ data: { img: imgFileID, content: upDiaryContent }, success: res => { //文字也上傳成功了 this.reset() console.log('[數據庫] [新增記錄] 成功,記錄 _id: ', res._id) }, fail: err => { //文字上傳失敗 wx.showToast({ icon: 'none', title: '新增記錄失敗' }) console.error('[數據庫] [新增記錄] 失敗:', err) } }) }, fail: e => { console.error('[上傳文件] 失敗:', e) wx.showToast({ icon: 'none', title: '上傳失敗', }) } }) } //圖片和文字全部上傳了。 wx.hideLoading() }, // 選擇圖片 selPic: function() { var that = this wx.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: function(res) { wx.showLoading({ title: '請等待', }) const imgfilePath = res.tempFilePaths[0] that.setData({ imgUrl: imgfilePath }) }, fail: e => { this.setData({ imgUrl: '' }) //console.error(e) }, complete: () => { wx.hideLoading() } }) }, //重置 reset: function() { let tempCursor = '' if (this.data.inputCursor == '+') { tempCursor = '-' } else { tempCursor = '+' } this.setData({ 'imgUrl': '', 'editText': '', 'hiddenInput': !this.data.hiddenInput, minWord: '', inputCursor: tempCursor }) }, // 查詢當前用戶的數據庫集合,暫時沒用 onQuery: function(p) { const db = wx.cloud.database() db.collection('diarys').skip(p) .get() .then(res => { console.log(res.data) console.log(res.data[0].img) }) .catch(console.error) }, /** * 生命周期函數--監聽頁面初次渲染完成 */ onReady: function() { wx.getSystemInfo({ success: res => { let h = res.windowHeight //取20條數據 const db = wx.cloud.database() db.collection('diarys') .get() .then(res => { this.setData({ mHeight: h, diarys: res.data }) console.log(res.data) console.log(res.data[5].img) }) .catch(console.error) }, }) }, /** * 生命周期函數--監聽頁面顯示 */ onShow: function() { }, /** * 生命周期函數--監聽頁面隱藏 */ onHide: function() { }, /** * 生命周期函數--監聽頁面卸載 */ onUnload: function() { }, /** * 頁面相關事件處理函數--監聽用戶下拉動作 */ onPullDownRefresh: function() { }, /** * 頁面上拉觸底事件的處理函數 */ onReachBottom: function() { }, /** * 用戶點擊右上角分享 */ onShareAppMessage: function() { } })
me.wxss
/* pages/me/me.wxss */ .currentWordNumber { height: 35px; line-height: 35px; font-size: 14px; float: right; margin-right: 15px; color: rgba(136, 136, 136, 1); margin-bottom: 10px; } .minWord { color: rgb(248, 248, 248); font-size: 14px; position: absolute; top: 30px; } .tips { width: 96%; margin-left: 2%; height: 45px; color: rgba(136, 136, 136, 1); font-size: 14px; margin-top: 15px; text-align: left; font-family: PingFangSC-regular; } textarea { min-height: 500rpx; max-height: 500rpx; padding: 10rpx 10rpx; font-size: 100%; width: 94%; margin-left: 3%; margin-top: 15px; } .content { border-top: 1px solid rgb(247, 247, 247); width: 100%; margin: 0 auto; background-color: #ffff; }
參考:授權 https://www.jianshu.com/p/480ff10bfb54
textarea https://blog.csdn.net/ChibiMarukoChan/article/details/88659746
...