unicloud-db.vue 10.5 KB
Newer Older
d-u-a's avatar
d-u-a 已提交
1 2
<template>
  <view>
d-u-a's avatar
d-u-a 已提交
3 4 5 6 7
    <slot
      :options="options"
      :data="dataList"
      :pagination="paginationInternal"
      :loading="loading"
d-u-a's avatar
d-u-a 已提交
8
      :hasMore="hasMore"
d-u-a's avatar
d-u-a 已提交
9 10
      :error="errorMessage"
    />
d-u-a's avatar
d-u-a 已提交
11 12 13 14
  </view>
</template>

<script>
d-u-a's avatar
d-u-a 已提交
15 16 17 18 19 20 21 22
const events = {
  load: 'load',
  error: 'error'
}
const pageMode = {
  add: 'add',
  replace: 'replace'
}
d-u-a's avatar
d-u-a 已提交
23

d-u-a's avatar
d-u-a 已提交
24 25 26 27 28 29 30 31
const attrs = [
  'pageCurrent',
  'pageSize',
  'collection',
  'action',
  'field',
  'getcount',
  'orderby',
32 33 34 35
  'where',
  'groupby',
  'groupField',
  'distinct'
d-u-a's avatar
d-u-a 已提交
36
]
d-u-a's avatar
d-u-a 已提交
37

d-u-a's avatar
d-u-a 已提交
38 39 40 41 42 43 44
export default {
  name: 'UniClouddb',
  props: {
    options: {
      type: [Object, Array],
      default () {
        return {}
d-u-a's avatar
d-u-a 已提交
45 46
      }
    },
d-u-a's avatar
d-u-a 已提交
47 48 49
    collection: {
      type: String,
      default: ''
d-u-a's avatar
d-u-a 已提交
50
    },
d-u-a's avatar
d-u-a 已提交
51 52 53 54 55 56 57 58
    action: {
      type: String,
      default: ''
    },
    field: {
      type: String,
      default: ''
    },
59 60 61 62 63 64 65 66
    orderby: {
      type: String,
      default: ''
    },
    where: {
      type: [String, Object],
      default: ''
    },
d-u-a's avatar
d-u-a 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    pageData: {
      type: String,
      default: 'add'
    },
    pageCurrent: {
      type: Number,
      default: 1
    },
    pageSize: {
      type: Number,
      default: 20
    },
    getcount: {
      type: [Boolean, String],
      default: false
    },
83 84 85 86 87 88 89 90
    getone: {
      type: [Boolean, String],
      default: false
    },
    gettree: {
      type: [Boolean, String],
      default: false
    },
91
    startwith: {
d-u-a's avatar
d-u-a 已提交
92 93 94
      type: String,
      default: ''
    },
95 96 97
    limitlevel: {
      type: Number,
      default: 10
d-u-a's avatar
d-u-a 已提交
98 99 100 101
    },
    manual: {
      type: Boolean,
      default: false
102 103 104 105 106 107 108 109 110 111 112 113
    },
    groupby: {
      type: String,
      default: ''
    },
    groupField: {
      type: String,
      default: ''
    },
    distinct: {
      type: [Boolean, String],
      default: false
d-u-a's avatar
d-u-a 已提交
114 115 116 117 118
    }
  },
  data () {
    return {
      loading: false,
d-u-a's avatar
d-u-a 已提交
119
      hasMore: false,
120
      dataList: this.getone ? undefined : [],
d-u-a's avatar
d-u-a 已提交
121 122 123 124 125 126 127 128 129 130
      paginationInternal: {
        current: this.pageCurrent,
        size: this.pageSize,
        count: 0
      },
      errorMessage: ''
    }
  },
  created () {
    this._isEnded = false
d-u-a's avatar
d-u-a 已提交
131

d-u-a's avatar
d-u-a 已提交
132 133 134 135 136 137 138
    this.$watch(() => {
      var al = []
      attrs.forEach(key => {
        al.push(this[key])
      })
      return al
    }, (newValue, oldValue) => {
139
      this.paginationInternal.size = this.pageSize
d-u-a's avatar
d-u-a 已提交
140

d-u-a's avatar
d-u-a 已提交
141 142 143 144 145
      let needReset = false
      for (let i = 2; i < newValue.length; i++) {
        if (newValue[i] !== oldValue[i]) {
          needReset = true
          break
d-u-a's avatar
d-u-a 已提交
146
        }
d-u-a's avatar
d-u-a 已提交
147 148 149 150 151 152 153 154
      }
      if (needReset) {
        this.clear()
        this.reset()
      }
      if (newValue[0] !== oldValue[0]) {
        this.paginationInternal.current = this.pageCurrent
      }
d-u-a's avatar
d-u-a 已提交
155

d-u-a's avatar
d-u-a 已提交
156 157
      this._execLoadData()
    })
d-u-a's avatar
d-u-a 已提交
158

d-u-a's avatar
d-u-a 已提交
159 160 161 162 163 164 165
    // #ifdef H5
    if (process.env.NODE_ENV === 'development') {
      this._debugDataList = []
      if (!window.unidev) {
        window.unidev = {
          clientDB: {
            data: []
d-u-a's avatar
d-u-a 已提交
166 167 168
          }
        }
      }
d-u-a's avatar
d-u-a 已提交
169 170 171
      window.unidev.clientDB.data.push(this._debugDataList)
    }
    // #endif
d-u-a's avatar
d-u-a 已提交
172

d-u-a's avatar
d-u-a 已提交
173 174 175 176 177 178 179
    // #ifdef MP-TOUTIAO
    let changeName
    const events = this.$scope.dataset.eventOpts
    for (var i = 0; i < events.length; i++) {
      const event = events[i]
      if (event[0].includes('^load')) {
        changeName = event[1][0][0]
d-u-a's avatar
d-u-a 已提交
180
      }
d-u-a's avatar
d-u-a 已提交
181 182 183 184 185 186 187 188 189 190 191
    }
    if (changeName) {
      let parent = this.$parent
      let maxDepth = 16
      this._changeDataFunction = null
      while (parent && maxDepth > 0) {
        const fun = parent[changeName]
        if (fun && typeof fun === 'function') {
          this._changeDataFunction = fun
          maxDepth = 0
          break
d-u-a's avatar
d-u-a 已提交
192
        }
d-u-a's avatar
d-u-a 已提交
193 194
        parent = parent.$parent
        maxDepth--
d-u-a's avatar
d-u-a 已提交
195
      }
d-u-a's avatar
d-u-a 已提交
196 197
    }
    // #endif
d-u-a's avatar
d-u-a 已提交
198

d-u-a's avatar
d-u-a 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211
    if (!this.manual) {
      this.loadData()
    }
  },
  // #ifdef H5
  beforeDestroy () {
    if (process.env.NODE_ENV === 'development' && window.unidev) {
      var cd = this._debugDataList
      var dl = window.unidev.clientDB.data
      for (var i = dl.length - 1; i >= 0; i--) {
        if (dl[i] === cd) {
          dl.splice(i, 1)
          break
d-u-a's avatar
d-u-a 已提交
212 213
        }
      }
d-u-a's avatar
d-u-a 已提交
214 215 216 217 218 219 220 221 222 223
    }
  },
  // #endif
  methods: {
    loadData (args1, args2) {
      let callback = null
      if (typeof args1 === 'object') {
        if (args1.clear) {
          this.clear()
          this.reset()
d-u-a's avatar
d-u-a 已提交
224
        }
d-u-a's avatar
d-u-a 已提交
225 226
        if (args1.current !== undefined) {
          this.paginationInternal.current = args1.current
d-u-a's avatar
d-u-a 已提交
227
        }
d-u-a's avatar
d-u-a 已提交
228 229
        if (typeof args2 === 'function') {
          callback = args2
d-u-a's avatar
d-u-a 已提交
230
        }
d-u-a's avatar
d-u-a 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
      } else if (typeof args1 === 'function') {
        callback = args1
      }

      this._execLoadData(callback)
    },
    loadMore () {
      if (this._isEnded) {
        return
      }
      this._execLoadData()
    },
    refresh () {
      this.clear()
      this._execLoadData()
    },
    clear () {
      this._isEnded = false
      this.dataList = []
    },
    reset () {
      this.paginationInternal.current = 1
    },
    add (value, {
      toastTitle,
      success,
      fail,
      complete
    } = {}) {
      uni.showLoading()
      /* eslint-disable no-undef */
      const db = uniCloud.database()
      db.collection(this.collection).add(value).then((res) => {
        success && success(res)
        uni.showToast({
          title: toastTitle || '新增成功'
        })
      }).catch((err) => {
        fail && fail(err)
d-u-a's avatar
d-u-a 已提交
270
        uni.showModal({
d-u-a's avatar
d-u-a 已提交
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
          content: err.message,
          showCancel: false
        })
      }).finally(() => {
        uni.hideLoading()
        complete && complete()
      })
    },
    remove (id, {
      action,
      success,
      fail,
      complete,
      confirmTitle,
      confirmContent
    } = {}) {
      if (!id || !id.length) {
        return
      }
      uni.showModal({
        title: confirmTitle || '提示',
        content: confirmContent || '是否删除该数据',
        showCancel: true,
        success: (res) => {
          if (!res.confirm) {
            return
d-u-a's avatar
d-u-a 已提交
297
          }
d-u-a's avatar
d-u-a 已提交
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
          this._execRemove(id, action, success, fail, complete)
        }
      })
    },
    update (id, value, {
      toastTitle,
      success,
      fail,
      complete
    } = {}) {
      uni.showLoading()
      /* eslint-disable no-undef */
      const db = uniCloud.database()
      return db.collection(this.collection).doc(id).update(value).then((res) => {
        success && success(res)
        uni.showToast({
          title: toastTitle || '修改成功'
d-u-a's avatar
d-u-a 已提交
315
        })
d-u-a's avatar
d-u-a 已提交
316 317 318 319 320
      }).catch((err) => {
        fail && fail(err)
        uni.showModal({
          content: err.message,
          showCancel: false
d-u-a's avatar
d-u-a 已提交
321
        })
d-u-a's avatar
d-u-a 已提交
322 323 324 325 326 327 328 329 330 331 332
      }).finally(() => {
        uni.hideLoading()
        complete && complete()
      })
    },
    _execLoadData (callback) {
      if (this.loading) {
        return
      }
      this.loading = true
      this.errorMessage = ''
d-u-a's avatar
d-u-a 已提交
333

d-u-a's avatar
d-u-a 已提交
334 335 336 337 338 339 340
      this._getExec().then((res) => {
        this.loading = false
        const {
          data,
          count
        } = res.result
        this._isEnded = data.length < this.pageSize
d-u-a's avatar
d-u-a 已提交
341
        this.hasMore = !this._isEnded
d-u-a's avatar
d-u-a 已提交
342

d-u-a's avatar
d-u-a 已提交
343
        const data2 = this.getone ? (data.length ? data[0] : undefined) : data
344

d-u-a's avatar
d-u-a 已提交
345 346
        callback && callback(data2, this._isEnded)
        this._dispatchEvent(events.load, data2)
d-u-a's avatar
d-u-a 已提交
347

348 349 350
        if (this.getone || this.pageData === pageMode.replace) {
          this.dataList = data2
        } else {
d-u-a's avatar
d-u-a 已提交
351 352 353
          this.dataList.push(...data2)
          if (this.dataList.length) {
            this.paginationInternal.current++
d-u-a's avatar
d-u-a 已提交
354 355
          }
        }
d-u-a's avatar
d-u-a 已提交
356

d-u-a's avatar
d-u-a 已提交
357 358
        if (this.getcount) {
          this.paginationInternal.count = count
d-u-a's avatar
d-u-a 已提交
359
        }
d-u-a's avatar
d-u-a 已提交
360 361 362 363

        // #ifdef H5
        if (process.env.NODE_ENV === 'development') {
          this._debugDataList.length = 0
364
          const formatData = JSON.parse(JSON.stringify(this.dataList))
365 366 367 368 369
          if (Array.isArray(this.dataList)) {
            this._debugDataList.push(...formatData)
          } else {
            this._debugDataList.push(formatData)
          }
d-u-a's avatar
d-u-a 已提交
370
        }
d-u-a's avatar
d-u-a 已提交
371 372 373 374 375 376 377 378
        // #endif
      }).catch((err) => {
        this.loading = false
        this.errorMessage = err
        callback && callback()
        this.$emit(events.error, err)
        if (process.env.NODE_ENV === 'development') {
          console.error(err)
d-u-a's avatar
d-u-a 已提交
379
        }
d-u-a's avatar
d-u-a 已提交
380 381 382 383 384
      })
    },
    _getExec () {
      /* eslint-disable no-undef */
      let db = uniCloud.database()
d-u-a's avatar
d-u-a 已提交
385

d-u-a's avatar
d-u-a 已提交
386 387 388
      if (this.action) {
        db = db.action(this.action)
      }
d-u-a's avatar
d-u-a 已提交
389

d-u-a's avatar
d-u-a 已提交
390
      db = db.collection(this.collection)
d-u-a's avatar
d-u-a 已提交
391

d-u-a's avatar
d-u-a 已提交
392 393 394 395 396 397
      if (!(!this.where || !Object.keys(this.where).length)) {
        db = db.where(this.where)
      }
      if (this.field) {
        db = db.field(this.field)
      }
398 399 400 401 402 403 404 405 406
      if (this.groupby) {
        db = db.groupby(this.groupby)
      }
      if (this.groupField) {
        db = db.groupField(this.groupField)
      }
      if (this.distinct === true) {
        db = db.distinct()
      }
d-u-a's avatar
d-u-a 已提交
407 408 409
      if (this.orderby) {
        db = db.orderBy(this.orderby)
      }
d-u-a's avatar
d-u-a 已提交
410

d-u-a's avatar
d-u-a 已提交
411 412 413 414
      const {
        current,
        size
      } = this.paginationInternal
415 416 417 418 419 420 421 422 423 424 425
      const getOptions = {}
      if (this.getcount) {
        getOptions.getCount = this.getcount
      }
      if (this.gettree) {
        getOptions.getTree = {
          limitLevel: this.limitlevel,
          startWith: this.startwith
        }
      }
      db = db.skip(size * (current - 1)).limit(size).get(getOptions)
d-u-a's avatar
d-u-a 已提交
426

d-u-a's avatar
d-u-a 已提交
427 428 429 430 431 432
      return db
    },
    _execRemove (id, action, success, fail, complete) {
      if (!this.collection || !id) {
        return
      }
d-u-a's avatar
d-u-a 已提交
433

d-u-a's avatar
d-u-a 已提交
434 435 436 437
      const ids = Array.isArray(id) ? id : [id]
      if (!ids.length) {
        return
      }
d-u-a's avatar
d-u-a 已提交
438

d-u-a's avatar
d-u-a 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
      uni.showLoading({
        mask: true
      })

      /* eslint-disable no-undef */
      const db = uniCloud.database()
      const dbCmd = db.command

      let exec = db
      if (action) {
        exec = exec.action(action)
      }

      exec.collection(this.collection).where({
        _id: dbCmd.in(ids)
      }).remove().then((res) => {
        success && success(res.result)
        if (this.pageData === pageMode.replace) {
          this.refresh()
d-u-a's avatar
d-u-a 已提交
458
        } else {
d-u-a's avatar
d-u-a 已提交
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
          this.removeData(ids)
        }
      }).catch((err) => {
        fail && fail(err)
        uni.showModal({
          content: err.message,
          showCancel: false
        })
      }).finally(() => {
        uni.hideLoading()
        complete && complete()
      })
    },
    removeData (ids) {
      const il = ids.slice(0)
      const dl = this.dataList
      for (let i = dl.length - 1; i >= 0; i--) {
        const index = il.indexOf(dl[i]._id)
        if (index >= 0) {
          dl.splice(i, 1)
          il.splice(index, 1)
d-u-a's avatar
d-u-a 已提交
480 481
        }
      }
d-u-a's avatar
d-u-a 已提交
482 483 484 485 486 487 488
    },
    _dispatchEvent (type, data) {
      if (this._changeDataFunction) {
        this._changeDataFunction(data, this._isEnded)
      } else {
        this.$emit(type, data, this._isEnded)
      }
d-u-a's avatar
d-u-a 已提交
489 490
    }
  }
d-u-a's avatar
d-u-a 已提交
491
}
d-u-a's avatar
d-u-a 已提交
492
</script>