preface

The author previously implemented a PC personal web disk function, including breakpoint continuation, file second file management system, please refer to the article “How to Implement a lightweight Breakpoint Continuation personal Web disk System”

So the idea of personal network disk function to extend to small programs, followed before the back end (interface basically does not need to change), only need to complete the mobile UI. And since the PC is based on Vue, in order to facilitate development, I want to directly use the cross-platform framework and convert the Vue code into small programs, and in this way, I can also consider the subsequent transfer out of H5 or native mobile client.

Due to functional reasons, this mini program cannot be approved in principle, so it will only be a personal training project. In addition, the project was developed long before this article was written, so there is no guarantee that the API of the relevant framework has been updated

Cross-platform framework selection

As for the selection of cross-platform framework, three main frameworks are compared

  • Mpvue is an open source front-end framework that uses vue. js to develop small applications, but it seems that no one has maintained it for a long time
  • Uniapp: Uni-App is a unified front-end framework for developing applets, H5 and apps using vue. js
  • Taro: An open source multi-terminal development framework for JD.com. The 2.x version requires React. The current 3.x version supports VUe2 and VUe3.

Installation and Startup

Install (Taro) scaffolding globally, and then initialize a project to install dependencies.

Use NPM Run Dev: Retry p to start the development environment, and then use wechat developer tools to import projects for preview. (It is best to apply for a mini program Id so that you can do further preview.)

Introducing the VUant-repep UI framework

You can download the generated packages of Vant-pervasive P and store them in a directory. You can then introduce custom components under the configuration of the page, and Taro will automatically synchronize these to the packaged folder. Wechat mini program will also automatically remove unused packages when packaging.

// index.config.js
export default {
  usingComponents: {
    "van-icon": ".. /.. /components/vant/icon/index".'van-action-sheet': '.. /.. /components/vant/action-sheet/index'.'van-notify': '.. /.. /components/vant/notify/index'.'van-dialog': '.. /.. /components/vant/dialog/index'.'van-field': '.. /.. /components/vant/field/index'."van-checkbox": ".. /.. /components/vant/checkbox/index"."van-checkbox-group": ".. /.. /components/vant/checkbox-group/index"."van-progress": ".. /.. /components/vant/progress/index"."van-toast": ".. /.. /components/vant/toast/index"}}Copy the code

Please refer to:

  • Taro- Native third party components and plug-ins using applets
  • “Appellate P” official documentation

In addition, some of Vant’s global components can be mounted to Vue instances for easy use.

// app.js
import Vue from 'vue'
// ...
import Notify from './components/vant/notify/notify'
import Dialog from './components/vant/dialog/dialog'
import Toast from './components/vant/toast/toast'
// ...
Vue.prototype.$notify = Notify
Vue.prototype.$dialog = Dialog
Vue.prototype.$toast = Toast
// ...
const App = new Vue({
  store,
  onShow (options) {
  },
  render (h) {
    return h('block'.this.$slots.default)
  }
})
export default App
Copy the code

Note that the default node is defined for the three components of Vant, and the following node code is added to a global VUE

<van-notify id="van-notify" />
<van-dialog id="van-dialog" />
<van-toast id="van-toast" />
Copy the code

It can then be used in VUE

// Notify
this.$notify({ type: 'danger'.message: e || 'Login failed'.duration: 1000 })
// Dialog
this.$dialog.confirm({
  message: 'This action will move the file to the recycle bin, you can restore it within a month, after a month it will be permanently deleted',
}).then(() = > {
  // do something
}).catch(() = > {
  // on cancel
})
// Toast
this.$toast.loading({
  mask: true.message: '上传中...'
})
Copy the code

Request to packaging

Request interception and response interception can be added for requests, based on taro.request

  • Encapsulate some request headers, such ascontent-type: application/json
  • extractbaseURLTo extract the request prefix from the configuration for easy modification
  • Request interceptor: injects the sessionId into the request header
  • Response interceptor: Only the requests with errCode 200 pass. The other requests are error requests. If the Notify component is used, an error message is automatically displayed

The reference code is as follows:

// fetch.js
import Taro from '@tarojs/taro'
import Notify from '.. /components/vant/notify/notify';
const interceptor = function (chain) {
  const requestParams = chain.requestParams
  const sessionId = Taro.getStorageSync('sessionId')
  if (sessionId) requestParams.header.sessionId = sessionId
  return chain.proceed(requestParams).then(res= > {
    const data = res.data
    if (data.errCode === 200) {
      return Promise.resolve(data.data)
    } else {
      Notify({
        type: 'danger'.selector: '#van-notify'.message: data.errMsg,
        duration: 1000,})return Promise.reject(data.errMsg)
    }
  }, err= > {
    Notify({
      type: 'danger'.selector: '#van-notify'.message: 'Server exception'.duration: 1000,})return err.toString()
  })
}
Taro.addInterceptor(interceptor)
export const baseURL = 'http://localhost:5001/storage'
export const instance = (method, url, data, options) = > {
  return Taro.request({
    dataType: 'json'.header: {
      'content-type': 'application/json'
    },
    method,
    url: baseURL + url, data, ... options }) }Copy the code

Mount the encapsulated instance to the Vue instance as a global component for easy use.

// app.js
import Vue from 'vue'
// ...
import { instance, baseURL } from './utils/fetch'
// ...
Vue.prototype.$get = (url, data, options) = > instance('get', url, data, options)
Vue.prototype.$post = (url, data, options) = > instance('post', url, data, options)
Vue.prototype.$baseURL = baseURL
// ...
const App = new Vue({
  store,
  onShow (options) {
  },
  render (h) {
    return h('block'.this.$slots.default)
  }
})
export default App
Copy the code

Then use it in vue:

// get
this.$get('/getFileList', {
  currentPath: this.currentPathParams
}).then(data= > {
  this.fileList = data
})

//post
this.$post('/delete', {
  deleteList
}).then(data= > {
  this.$notify({ type: 'success'.message: 'Operation successful'.duration: 1000 })
  this.$emit('onNeedRefresh')})Copy the code

About File Uploading

Wechat file upload can not get the file instance, checked a lot of information, and did not find the function of file sharding, so can not realize the resumable breakpoint. This time, simple single-file uploads were used directly, and a simpleUpload interface was added to the back end to receive them. The rest of the operations are not covered here.

Wechat does not provide direct call system file manager API (may not have permissions), this time using wechat to provide the following ways to replace

  • Wx. ChooseImage: Select images from your local album or take photos with your camera
  • Wx. chooseVideo: Shoot videos or select videos from your phone’s album
  • Wx. chooseMessageFile: Select files from client session

Each of these interfaces returns a success callback containing the selected path to retrieve the file path for upload

Upload the logic

handleUploadFile (type = 1) {
  const callback = (res) = > {
    this.$emit('update:actionVisible'.false)
    this.$toast.loading({
      mask: true.message: '上传中...'
    })
    const filePaths = type === 3 ? res.tempFiles.map(item= > item.path) : res.tempFilePaths
    Promise.all(
      filePaths.map(item= > {
        return Taro.uploadFile({
          url: this.$baseURL + '/simpleUpload'.filePath: item,
          name: 'file'.formData: {
            targetPath: this.currentPathArr.join('/')},header: {
            sessionid: Taro.getStorageSync('sessionId')
          }
        }).then(data= > {
          try {
            const res = JSON.parse(data.data)
            if (res.errCode === 200) {
              const { fileName } = res.data
              this.$notify({ type: 'success'.message: 'Upload successful, save the file as${fileName}`.duration: 2000 })
              this.$emit('onNeedRefresh')}else {
              this.$notify({ type: 'success'.message: 'Upload failed,${res.errMsg}`.duration: 2000}}})catch (e) {
            this.$notify({ type: 'success'.message: 'Upload failed, server error'.duration: 2000 })
          }
        })
      })
    ).then(() = > {
      this.$toast.clear()
    })
  }
  if (type === 1) {
    wx.chooseImage({
      count: 1.sizeType: ['original'.'compressed'].sourceType: ['album'.'camera'],
      success (res) {
        callback(res)
      }
    })
  } else if (type === 2) {
    wx.chooseVideo({
      sourceType: ['album'.'camera'].maxDuration: 60.camera: 'back',
      success (res) {
        callback(res)
      }
    })
  } else if (type === 3) {
    wx.chooseMessageFile({
      count: 1,
      success (res) {
        callback(res)
      }
    })
  }
}
Copy the code

The file preview

Because the maximum storage capacity of wechat small program files is 10M, it is almost impossible to achieve the download function. The download function has been changed to an online preview function, which currently supports the following file types

  • Office documents (DOC, DOCX, XLS, XLSX, PPT, PPTX, PDF) : These documents can be passedTaro.openDocumentThe API implements preview operations
  • Image (JPG, PNG, SVG, GIF) : Once you have the image’s temporary address, use the float layer andimageComponent displays
  • Video (MP4, MOV, M4V, 3GP, AVI, M3U8) : Directly put the video address on the floating layervideoComponent display

Wx. DownloadFile is used to download files to a local temporary path and then perform corresponding preview operations. At this time, you can add a download progress bar to optimize user experience. The video will not be downloaded directly. The video resource needs to be set to accept-range at the back end, so that the video can be downloaded and played at the same time.

Progress bar uses wechat native request eventsonProgressUpdateimplementation

The main code

handleActionPreview (el) {
  const target = this.actionFileInfo
  const targetPath = this.currentPathArr.join('/') + '/' + target.fileName
  const realPath = targetPath.replace('$Root'.this.$baseURL)
  const sessionId = Taro.getStorageSync('sessionId')
  if (videoSuffixArr.includes(target.suffix)) {
    // Display the video directly
    this.handleActionCancel()
    this.mediaPreviewVisible = 2
    this.videoPreviewURL = realPath + '? sessionid=' + Taro.getStorageSync('sessionId')}else if (this.previewArr.includes(target.suffix)) {
    // Other types are downloaded first
    this.downloadTask = wx.downloadFile({
      url: realPath,
      header: {
        'sessionid': sessionId
      },
      success: (data) = > {
        const { tempFilePath } = data
        if (imgSuffixArr.includes(target.suffix)) {
          this.mediaPreviewVisible = 1
          this.imgPreviewURL = tempFilePath
        } else if (documentSuffixArr.includes(target.suffix)) {
          Taro.openDocument({
            filePath: tempFilePath
          })
        }
        this.handleActionCancel()
      },
      fail: () = > {
        this.$notify({ type: 'danger'.message: Download failed.duration: 2000})}})this.downloadTask.onProgressUpdate((res) = > {
      this.isDownloading = true
      const { progress, totalBytesWritten, totalBytesExpectedToWrite } = res
      this.downloadingInfo = { progress, totalBytesWritten, totalBytesExpectedToWrite }
    })
  }
}
Copy the code

PS: the Koa service is used at the back endkoa-rangeThe video can be downloaded and played at the same time. In Chrome, you can drag the progress bar for a video. Otherwise, you cannot drag the progress bar.

The rest of the function

The batch operation

Van-checkgroup is used to directly replace the current file list, but try to keep the node position unchanged, which can prevent interface backflow from affecting performance.

Move files

This function corresponds to the move of files on the PC. You can choose to move files only or copy them. On the PC, a tree component is used to select folders. However, it is found that Vant and others do not have relevant tree components, so they may need to encapsulate one by themselves. After the user clicks to move, the selected file information is recorded, and then the user needs to enter the corresponding directory for paste operation.

About Packaged publishing

After the NPM run build: retry p command is run, other operations are the same as those of normal mini-programs.

Other recommended articles

  • Personal JS plug-in library refactoring development record
  • Front-end audio visualization using G renderer
  • Vite + Vue3 develop a custom browser start page website
  • Mock Codepen online code compiler project development record