596 lines
16 KiB
Vue
596 lines
16 KiB
Vue
<template>
|
|
<view>
|
|
<slot :data="dataList" :loading="loading" :hasMore="hasMore" :pagination="pagination" :error="error" />
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="uts" setup>
|
|
import { UniCloudDBElement } from './global.uts'
|
|
|
|
defineOptions({
|
|
name: 'unicloud-db',
|
|
// @ts-ignore
|
|
rootElement: {
|
|
class: UniCloudDBElement
|
|
}
|
|
})
|
|
|
|
const slots = defineSlots<{
|
|
default(props: {
|
|
data : Array<UTSJSONObject>,
|
|
loading : boolean,
|
|
hasMore : boolean,
|
|
pagination : UniCloudDBComponentPaginationType,
|
|
error : UniCloudError | null
|
|
}): any
|
|
}>()
|
|
|
|
interface UniCloudDBProps {
|
|
collection : String | any;
|
|
field : String;
|
|
orderby : String;
|
|
where : String | any;
|
|
pageData : String;
|
|
pageCurrent : Number;
|
|
pageSize : Number;
|
|
getcount : Boolean;
|
|
gettree : String | any;
|
|
gettreepath : Boolean;
|
|
startwith : String;
|
|
limitlevel : Number;
|
|
groupby : String;
|
|
groupField : String;
|
|
distinct : Boolean;
|
|
pageIndistinct : Boolean;
|
|
foreignKey : String;
|
|
loadtime : String;
|
|
manual : Boolean;
|
|
ssrKey : String
|
|
}
|
|
|
|
const props = withDefaults(defineProps<UniCloudDBProps>(), {
|
|
collection: '',
|
|
field : '',
|
|
orderby : '',
|
|
where : '',
|
|
pageData : 'add',
|
|
pageCurrent : 1,
|
|
pageSize : 20,
|
|
getcount : false,
|
|
gettree : '',
|
|
gettreepath : false,
|
|
startwith : '',
|
|
limitlevel : 10,
|
|
groupby : '',
|
|
groupField : '',
|
|
distinct : false,
|
|
pageIndistinct : false,
|
|
foreignKey : '',
|
|
loadtime : 'auto',
|
|
manual : false,
|
|
ssrKey : '',
|
|
})
|
|
|
|
const dataList = ref<Array<UTSJSONObject>>([])
|
|
const loading = ref(false)
|
|
const hasMore = ref(false)
|
|
const isEnded = ref(false)
|
|
const pagination = ref<UniCloudDBComponentPaginationType>({
|
|
current: 1,
|
|
size: 20,
|
|
count: 0,
|
|
})
|
|
const error = ref<UniCloudError | null>(null)
|
|
|
|
const EVENT_LOAD = 'load'
|
|
const EVENT_ERROR = 'error'
|
|
const PAGE_MODE_ADD = 'add'
|
|
const PAGE_MODE_REPLACE = 'replace'
|
|
const LOAD_MODE_AUTO = 'auto'
|
|
const LOAD_MODE_MANUAL = 'manual'
|
|
// const LOAD_MODE_ONREADY = 'onready'
|
|
|
|
type SuccessCallback<T> = (res : T | null) => void | null
|
|
type FailCallback = (err : any | null) => void | null
|
|
type CompleteCallback = () => void | null
|
|
|
|
type GetSuccessCallback = SuccessCallback<UniCloudDBGetResult>
|
|
type AddSuccessCallback = SuccessCallback<UniCloudDBAddResult>
|
|
type RemoveSuccessCallback = SuccessCallback<UniCloudDBRemoveResult>
|
|
type UpdateSuccessCallback = SuccessCallback<UniCloudDBUpdateResult>
|
|
|
|
type UniCloudDBComponentPaginationType = {
|
|
current : number,
|
|
size : number,
|
|
count : number
|
|
}
|
|
|
|
type UniCloudDBComponentLoadDataOptions = {
|
|
clear ?: boolean | null,
|
|
current ?: number | null,
|
|
success ?: GetSuccessCallback,
|
|
fail ?: FailCallback,
|
|
complete ?: CompleteCallback,
|
|
}
|
|
|
|
type UniCloudDBComponentAddOptions = {
|
|
/**
|
|
* @default true
|
|
*/
|
|
showToast ?: boolean | null,
|
|
toastTitle ?: string | null,
|
|
/**
|
|
* @default true
|
|
*/
|
|
needLoading ?: boolean | null,
|
|
loadingTitle ?: string | null,
|
|
success ?: AddSuccessCallback,
|
|
fail ?: FailCallback,
|
|
complete ?: CompleteCallback,
|
|
}
|
|
|
|
type UniCloudDBComponentRemoveOptions = {
|
|
confirmTitle ?: string | null,
|
|
confirmContent ?: string | null,
|
|
/**
|
|
* @default true
|
|
*/
|
|
needConfirm ?: boolean | null,
|
|
/**
|
|
* @default true
|
|
*/
|
|
needLoading ?: boolean | null,
|
|
loadingTitle ?: string | null,
|
|
success ?: RemoveSuccessCallback,
|
|
fail ?: FailCallback,
|
|
complete ?: CompleteCallback,
|
|
}
|
|
|
|
type UniCloudDBComponentUpdateOptions = {
|
|
/**
|
|
* @default true
|
|
*/
|
|
showToast ?: boolean | null,
|
|
toastTitle ?: string | null,
|
|
confirmTitle ?: string | null,
|
|
confirmContent ?: string | null,
|
|
/**
|
|
* @default true
|
|
*/
|
|
needConfirm ?: boolean | null,
|
|
/**
|
|
* @default true
|
|
*/
|
|
needLoading ?: boolean | null,
|
|
loadingTitle ?: string | null,
|
|
success ?: UpdateSuccessCallback,
|
|
fail ?: FailCallback,
|
|
complete ?: CompleteCallback,
|
|
}
|
|
|
|
function cast_callback<T>(options : any | null) : T | null {
|
|
return options as T | null
|
|
}
|
|
|
|
const emit = defineEmits<{
|
|
'load' : UniCloudDBGetResult
|
|
}>()
|
|
|
|
const loadData = async (options : UniCloudDBComponentLoadDataOptions = {}) : Promise<void> => {
|
|
const clear = (options.clear != null && options.clear == true)
|
|
if (clear == true) {
|
|
if (props.pageData == PAGE_MODE_REPLACE) {
|
|
clear()
|
|
}
|
|
reset()
|
|
}
|
|
await get(options)
|
|
}
|
|
|
|
const loadMore = () => {
|
|
if (isEnded.value || loading.value) {
|
|
return
|
|
}
|
|
|
|
if (props.pageData == PAGE_MODE_ADD) {
|
|
pagination.value.current++
|
|
}
|
|
|
|
get(null)
|
|
}
|
|
|
|
const refresh = () => {
|
|
clear()
|
|
get(null)
|
|
}
|
|
|
|
const clear = () => {
|
|
isEnded.value = false
|
|
dataList.value.length = 0
|
|
}
|
|
|
|
const reset = () => {
|
|
pagination.value.current = 1
|
|
}
|
|
|
|
const get = async (options ?: UniCloudDBComponentLoadDataOptions | null) : Promise<void> => {
|
|
let loadAfterClear = false
|
|
if (options != null && options.clear != null && options.clear == true) {
|
|
loadAfterClear = true
|
|
}
|
|
if (options != null && options.current != null) {
|
|
pagination.value.current = options.current!
|
|
}
|
|
|
|
error.value = null
|
|
loading.value = true
|
|
await getExec().then((res : UniCloudDBGetResult) => {
|
|
const data = res.data
|
|
const count = res.count
|
|
|
|
isEnded.value = (count != null) ? (pagination.value.current * pagination.value.size >= count) : (data.length < props.pageSize)
|
|
hasMore.value = !isEnded.value
|
|
|
|
if (props.getcount && count != null) {
|
|
pagination.value.count = count
|
|
}
|
|
|
|
_dispatchEvent(EVENT_LOAD, data)
|
|
|
|
if (loadAfterClear || props.pageData == PAGE_MODE_REPLACE) {
|
|
dataList.value = data
|
|
} else {
|
|
dataList.value.push(...data)
|
|
}
|
|
|
|
options?.success?.(res)
|
|
}).catch((err : any | null) => {
|
|
_requestFail(err, null)
|
|
options?.fail?.(err)
|
|
}).then(() => {
|
|
loading.value = false
|
|
options?.complete?.()
|
|
}, () => {
|
|
loading.value = false
|
|
options?.complete?.()
|
|
})
|
|
}
|
|
|
|
const add = (value : UTSJSONObject, options : UniCloudDBComponentAddOptions = {}) => {
|
|
_needLoading(options.needLoading, options.loadingTitle)
|
|
const db = uniCloud.databaseForJQL()
|
|
db.collection(_getMainCollection()).add(value).then<void>((res : UniCloudDBAddResult) => {
|
|
options.success?.(res)
|
|
_isShowToast(options.showToast ?? false, options.toastTitle ?? 'add success')
|
|
}).catch((err) => {
|
|
_requestFail(err, options.fail)
|
|
}).then(() => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
}, () => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
})
|
|
}
|
|
|
|
const update = (id : string, value : UTSJSONObject, options : UniCloudDBComponentUpdateOptions = {}) => {
|
|
if (options.needConfirm == true) {
|
|
uni.showModal({
|
|
title: options.confirmTitle,
|
|
content: options.confirmContent,
|
|
showCancel: true,
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
_update(id, value, options)
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
_update(id, value, options)
|
|
}
|
|
}
|
|
|
|
const remove = (id : any, options : UniCloudDBComponentRemoveOptions = {}) => {
|
|
const ids = Array.isArray(id) ? (id as Array<any>) : [id]
|
|
if (options.needConfirm == true) {
|
|
uni.showModal({
|
|
title: options.confirmTitle,
|
|
content: options.confirmContent,
|
|
showCancel: true,
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
_remove(ids, options)
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
_remove(ids, options)
|
|
}
|
|
}
|
|
|
|
const _update = (id : string, value : UTSJSONObject, options : UniCloudDBComponentUpdateOptions) => {
|
|
_needLoading(options.needLoading, options.loadingTitle)
|
|
const db = uniCloud.databaseForJQL()
|
|
db.collection(_getMainCollection()).doc(id).update(value).then((res) => {
|
|
options.success?.(res)
|
|
_isShowToast(options.showToast ?? false, options.toastTitle ?? 'update success')
|
|
}).catch((err : any | null) => {
|
|
_requestFail(err, options.fail)
|
|
}).then(() => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
}, () => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
})
|
|
}
|
|
|
|
const _remove = (ids : Array<any>, options : UniCloudDBComponentRemoveOptions) => {
|
|
_needLoading(options.needLoading, options.loadingTitle)
|
|
const db = uniCloud.databaseForJQL()
|
|
const dbCommand = db.command
|
|
db.collection(_getMainCollection()).where({
|
|
_id: dbCommand.in(ids)
|
|
}).remove().then((res) => {
|
|
options.success?.(res)
|
|
if (props.pageData == PAGE_MODE_REPLACE) {
|
|
refresh()
|
|
} else {
|
|
_removeData(ids)
|
|
}
|
|
}).catch((err : any | null) => {
|
|
_requestFail(err, options.fail)
|
|
}).then(() => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
}, () => {
|
|
_requestComplete(options.complete, options.needLoading)
|
|
})
|
|
}
|
|
|
|
const _removeData = (ids : Array<any>) => {
|
|
const il = ids.slice(0)
|
|
const dl = dataList.value
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
const _isShowToast = (showToast : boolean, title : string) => {
|
|
if (showToast == true) {
|
|
uni.showToast({
|
|
title: title
|
|
})
|
|
}
|
|
}
|
|
|
|
const _needLoading = (needLoading ?: boolean | null, title ?: string | null) => {
|
|
if (needLoading == true) {
|
|
uni.showLoading({
|
|
mask: true,
|
|
title: title ?? ''
|
|
})
|
|
}
|
|
}
|
|
|
|
const _requestFail = (err ?: any | null, callback ?: FailCallback | null) => {
|
|
callback?.(err)
|
|
error.value = err as UniCloudError
|
|
emit(EVENT_ERROR, err)
|
|
}
|
|
|
|
const _requestComplete = (callback ?: CompleteCallback | null, needLoading ?: boolean | null) => {
|
|
callback?.()
|
|
if (needLoading == true) {
|
|
uni.hideLoading()
|
|
}
|
|
}
|
|
|
|
const getExec = () : Promise<UniCloudDBGetResult> => {
|
|
return getTemp()
|
|
}
|
|
|
|
const getTemp = () : Promise<UniCloudDBGetResult> => {
|
|
let db = uniCloud.databaseForJQL()
|
|
|
|
let collection = Array.isArray(props.collection) ? db.collection(...(props.collection as Array<any>)) : db.collection(props.collection)
|
|
|
|
let filter : UniCloudDBFilter | null = null
|
|
if (props.foreignKey.length > 0) {
|
|
filter = collection.foreignKey(props.foreignKey)
|
|
}
|
|
|
|
if (typeof props.where == 'string') {
|
|
const whereString = props.where as string
|
|
if (whereString.length > 0) {
|
|
filter = (filter != null) ? filter.where(props.where) : collection.where(props.where)
|
|
}
|
|
} else if (typeof props.where == 'object') {
|
|
filter = (filter != null) ? filter.where(props.where) : collection.where(props.where)
|
|
}
|
|
|
|
let query : UniCloudDBQuery | null = null
|
|
if (props.field.length > 0) {
|
|
query = (filter != null) ? filter.field(props.field) : collection.field(props.field)
|
|
}
|
|
if (props.groupby.length > 0) {
|
|
if (query != null) {
|
|
query = query.groupBy(props.groupby)
|
|
} else if (filter != null) {
|
|
query = filter.groupBy(props.groupby)
|
|
}
|
|
}
|
|
if (props.groupField.length > 0) {
|
|
if (query != null) {
|
|
query = query.groupField(props.groupField)
|
|
} else if (filter != null) {
|
|
query = filter.groupField(props.groupField)
|
|
}
|
|
}
|
|
if (props.distinct == true) {
|
|
if (query != null) {
|
|
query = query.distinct(props.field)
|
|
} else if (filter != null) {
|
|
query = filter.distinct(props.field)
|
|
}
|
|
}
|
|
if (props.orderby.length > 0) {
|
|
if (query != null) {
|
|
query = query.orderBy(props.orderby)
|
|
} else if (filter != null) {
|
|
query = filter.orderBy(props.orderby)
|
|
} else {
|
|
query = collection.orderBy(props.orderby)
|
|
}
|
|
}
|
|
|
|
const size = pagination.value.size
|
|
const current = pagination.value.current
|
|
const skipSize = size * (current - 1)
|
|
if (query != null) {
|
|
query = query.skip(skipSize).limit(size)
|
|
} else if (filter != null) {
|
|
query = filter.skip(skipSize).limit(size)
|
|
} else {
|
|
query = collection.skip(skipSize).limit(size)
|
|
}
|
|
|
|
const getOptions = {}
|
|
const treeOptions = {
|
|
limitLevel: props.limitlevel,
|
|
startWith: props.startwith
|
|
}
|
|
if (props.getcount == true) {
|
|
getOptions['getCount'] = props.getcount
|
|
}
|
|
if (typeof props.gettree == 'string') {
|
|
const getTreeString = props.gettree as string
|
|
if (getTreeString.length > 0) {
|
|
getOptions['getTree'] = treeOptions
|
|
}
|
|
} else if (typeof props.gettree == 'object') {
|
|
getOptions['getTree'] = treeOptions
|
|
}
|
|
if (props.gettreepath == true) {
|
|
getOptions['getTreePath'] = treeOptions
|
|
}
|
|
|
|
return query.get(getOptions)
|
|
}
|
|
|
|
const _getMainCollection = () : string => {
|
|
if (typeof props.collection === 'string') {
|
|
return (props.collection as string).split(',')[0]
|
|
}
|
|
|
|
if (Array.isArray(props.collection)) {
|
|
const array = props.collection as Array<any>
|
|
const index = array[0] as UTSJSONObject
|
|
const collection = index.getString('$db[0].$param[0]')
|
|
return collection ?? ''
|
|
}
|
|
|
|
return ''
|
|
}
|
|
|
|
const _dispatchEvent = (type : string, data : Array<UTSJSONObject>) => {
|
|
emit(type, data, isEnded.value, {
|
|
current: pagination.value.current,
|
|
size: pagination.value.size,
|
|
count: pagination.value.count
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
const proxy = getCurrentInstance()?.proxy
|
|
if (proxy?.$el) {
|
|
let udb = (proxy.$el as unknown as UniCloudDBElement)
|
|
udb.onLoadData = (options : any) => {
|
|
loadData(options)
|
|
}
|
|
udb.onLoadMore = () => {
|
|
loadMore()
|
|
}
|
|
udb.onAdd = (value : any, options: any) => {
|
|
add(value, options)
|
|
}
|
|
udb.onRemove = (id : any, options: any) => {
|
|
remove(id, options)
|
|
}
|
|
udb.onUpdate = (id : string, value : any, options: any) => {
|
|
update(id, value, options)
|
|
}
|
|
}
|
|
// const uniCloudDBElement = this.$refs['UniCloudDB'] as UniCloudDBElement
|
|
// uniCloudDBElement.dataList = this.dataList;
|
|
})
|
|
|
|
watch(
|
|
() : any => [
|
|
props.pageCurrent,
|
|
props.pageSize,
|
|
props.collection,
|
|
props.field,
|
|
props.getcount,
|
|
props.orderby,
|
|
props.where,
|
|
props.groupby,
|
|
props.groupField,
|
|
props.distinct
|
|
],
|
|
(newValue : Array<any>, oldValue : Array<any>) => {
|
|
pagination.value.size = props.pageSize
|
|
if (newValue[0] !== oldValue[0]) {
|
|
pagination.value.current = props.pageCurrent
|
|
}
|
|
|
|
if (props.loadtime == LOAD_MODE_MANUAL) {
|
|
return
|
|
}
|
|
|
|
let needReset = false
|
|
for (let i = 2; i < newValue.length; i++) {
|
|
if (newValue[i] !== oldValue[i]) {
|
|
needReset = true
|
|
break
|
|
}
|
|
}
|
|
if (needReset) {
|
|
clear()
|
|
reset()
|
|
}
|
|
|
|
get(null)
|
|
}
|
|
)
|
|
|
|
const initData = () => {
|
|
if (!props.manual && props.loadtime == LOAD_MODE_AUTO && dataList.value.length == 0) {
|
|
if (typeof props.collection == 'string') {
|
|
const collectionString = props.collection as string
|
|
if (collectionString.length == 0) {
|
|
return
|
|
}
|
|
} else if (Array.isArray(props.collection)) {
|
|
const collectionArray = props.collection as Array<any>
|
|
if (collectionArray.length == 0) {
|
|
return
|
|
}
|
|
}
|
|
get(null)
|
|
}
|
|
}
|
|
|
|
pagination.value.current = props.pageCurrent
|
|
pagination.value.size = props.pageSize
|
|
|
|
initData()
|
|
|
|
defineExpose({
|
|
loadData,
|
|
loadMore,
|
|
add,
|
|
remove,
|
|
update
|
|
})
|
|
|
|
</script> |