You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
692 lines
18 KiB
692 lines
18 KiB
export type PaginationType = { |
|
current : number, |
|
size : number, |
|
count : number |
|
} |
|
|
|
export type LoadMoreType = { |
|
contentdown : string, |
|
contentrefresh : string, |
|
contentnomore : string |
|
} |
|
|
|
export type SelectedItemType = { |
|
name : string, |
|
value : string, |
|
} |
|
|
|
export type GetCommandOptions = { |
|
collection ?: UTSJSONObject, |
|
field ?: string, |
|
orderby ?: string, |
|
where ?: any, |
|
pageData ?: string, |
|
pageCurrent ?: number, |
|
pageSize ?: number, |
|
getCount ?: boolean, |
|
getTree ?: any, |
|
getTreePath ?: UTSJSONObject, |
|
startwith ?: string, |
|
limitlevel ?: number, |
|
groupby ?: string, |
|
groupField ?: string, |
|
distinct ?: boolean, |
|
pageIndistinct ?: boolean, |
|
foreignKey ?: string, |
|
loadtime ?: string, |
|
manual ?: boolean |
|
} |
|
|
|
const DefaultSelectedNode = { |
|
text: '请选择', |
|
value: '' |
|
} |
|
|
|
export const dataPicker = defineMixin({ |
|
props: { |
|
localdata: { |
|
type: Array as PropType<Array<UTSJSONObject>>, |
|
default: [] as Array<UTSJSONObject> |
|
}, |
|
collection: { |
|
type: Object, |
|
default: '' |
|
}, |
|
field: { |
|
type: String, |
|
default: '' |
|
}, |
|
orderby: { |
|
type: String, |
|
default: '' |
|
}, |
|
where: { |
|
type: Object, |
|
default: '' |
|
}, |
|
pageData: { |
|
type: String, |
|
default: 'add' |
|
}, |
|
pageCurrent: { |
|
type: Number, |
|
default: 1 |
|
}, |
|
pageSize: { |
|
type: Number, |
|
default: 20 |
|
}, |
|
getcount: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
gettree: { |
|
type: Object, |
|
default: '' |
|
}, |
|
gettreepath: { |
|
type: Object, |
|
default: '' |
|
}, |
|
startwith: { |
|
type: String, |
|
default: '' |
|
}, |
|
limitlevel: { |
|
type: Number, |
|
default: 10 |
|
}, |
|
groupby: { |
|
type: String, |
|
default: '' |
|
}, |
|
groupField: { |
|
type: String, |
|
default: '' |
|
}, |
|
distinct: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
pageIndistinct: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
foreignKey: { |
|
type: String, |
|
default: '' |
|
}, |
|
loadtime: { |
|
type: String, |
|
default: 'auto' |
|
}, |
|
manual: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
preload: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
stepSearh: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
selfField: { |
|
type: String, |
|
default: '' |
|
}, |
|
parentField: { |
|
type: String, |
|
default: '' |
|
}, |
|
multiple: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
value: { |
|
type: Object, |
|
default: '' |
|
}, |
|
modelValue: { |
|
type: Object, |
|
default: '' |
|
}, |
|
defaultProps: { |
|
type: Object as PropType<UTSJSONObject>, |
|
} |
|
}, |
|
data() { |
|
return { |
|
loading: false, |
|
error: null as UniCloudError | null, |
|
treeData: [] as Array<UTSJSONObject>, |
|
selectedIndex: 0, |
|
selectedNodes: [] as Array<UTSJSONObject>, |
|
selectedPages: [] as Array<UTSJSONObject>[], |
|
selectedValue: '', |
|
selectedPaths: [] as Array<UTSJSONObject>, |
|
pagination: { |
|
current: 1, |
|
size: 20, |
|
count: 0 |
|
} as PaginationType |
|
} |
|
}, |
|
computed: { |
|
mappingTextName() : string { |
|
// TODO |
|
return (this.defaultProps != null) ? this.defaultProps!.getString('text', 'text') : 'text' |
|
}, |
|
mappingValueName() : string { |
|
// TODO |
|
return (this.defaultProps != null) ? this.defaultProps!.getString('value', 'value') : 'value' |
|
}, |
|
currentDataList() : Array<UTSJSONObject> { |
|
if (this.selectedIndex > this.selectedPages.length - 1) { |
|
return [] as Array<UTSJSONObject> |
|
} |
|
return this.selectedPages[this.selectedIndex] |
|
}, |
|
isLocalData() : boolean { |
|
return this.localdata.length > 0 |
|
}, |
|
isCloudData() : boolean { |
|
return this._checkIsNotNull(this.collection) |
|
}, |
|
isCloudDataList() : boolean { |
|
return (this.isCloudData && (this.parentField.length == 0 && this.selfField.length == 0)) |
|
}, |
|
isCloudDataTree() : boolean { |
|
return (this.isCloudData && this.parentField.length > 0 && this.selfField.length > 0) |
|
}, |
|
dataValue() : any { |
|
return this.hasModelValue ? this.modelValue : this.value |
|
}, |
|
hasCloudTreeData() : boolean { |
|
return this.treeData.length > 0 |
|
}, |
|
hasModelValue() : boolean { |
|
if (typeof this.modelValue == 'string') { |
|
const valueString = this.modelValue as string |
|
return (valueString.length > 0) |
|
} else if (Array.isArray(this.modelValue)) { |
|
const valueArray = this.modelValue as Array<string> |
|
return (valueArray.length > 0) |
|
} |
|
return false |
|
}, |
|
hasCloudDataValue() : boolean { |
|
if (typeof this.dataValue == 'string') { |
|
const valueString = this.dataValue as string |
|
return (valueString.length > 0) |
|
} |
|
return false |
|
} |
|
}, |
|
created() { |
|
this.pagination.current = this.pageCurrent |
|
this.pagination.size = this.pageSize |
|
|
|
this.$watch( |
|
() : any => [ |
|
this.pageCurrent, |
|
this.pageSize, |
|
this.localdata, |
|
this.value, |
|
this.collection, |
|
this.field, |
|
this.getcount, |
|
this.orderby, |
|
this.where, |
|
this.groupby, |
|
this.groupField, |
|
this.distinct |
|
], |
|
(newValue : Array<any>, oldValue : Array<any>) => { |
|
this.pagination.size = this.pageSize |
|
if (newValue[0] !== oldValue[0]) { |
|
this.pagination.current = this.pageCurrent |
|
} |
|
|
|
this.onPropsChange() |
|
} |
|
) |
|
}, |
|
methods: { |
|
onPropsChange() { |
|
this.selectedIndex = 0 |
|
this.selectedNodes.length = 0 |
|
this.selectedPages.length = 0 |
|
this.selectedPaths.length = 0 |
|
|
|
// 加载数据 |
|
this.$nextTick(() => { |
|
this.loadData() |
|
}) |
|
}, |
|
|
|
onTabSelect(index : number) { |
|
this.selectedIndex = index |
|
}, |
|
|
|
onNodeClick(nodeData : UTSJSONObject) { |
|
if (nodeData.getBoolean('disable', false)) { |
|
return |
|
} |
|
|
|
const isLeaf = this._checkIsLeafNode(nodeData) |
|
|
|
this._trimSelectedNodes(nodeData) |
|
|
|
this.$emit('nodeclick', nodeData) |
|
|
|
if (this.isLocalData) { |
|
if (isLeaf || !this._checkHasChildren(nodeData)) { |
|
this.onFinish() |
|
} |
|
} else if (this.isCloudDataList) { |
|
this.onFinish() |
|
} else if (this.isCloudDataTree) { |
|
if (isLeaf) { |
|
this.onFinish() |
|
} else if (!this._checkHasChildren(nodeData)) { |
|
// 尝试请求一次,如果没有返回数据标记为叶子节点 |
|
this.loadCloudDataNode(nodeData) |
|
} |
|
} |
|
}, |
|
|
|
getChangeNodes(): Array<UTSJSONObject> { |
|
const nodes: Array<UTSJSONObject> = [] |
|
this.selectedNodes.forEach((node : UTSJSONObject) => { |
|
const newNode: UTSJSONObject = {} |
|
newNode[this.mappingTextName] = node.getString(this.mappingTextName) |
|
newNode[this.mappingValueName] = node.getString(this.mappingValueName) |
|
nodes.push(newNode) |
|
}) |
|
return nodes |
|
}, |
|
|
|
onFinish() { }, |
|
|
|
// 加载数据(自动判定环境) |
|
loadData() { |
|
if (this.isLocalData) { |
|
this.loadLocalData() |
|
} else if (this.isCloudDataList) { |
|
this.loadCloudDataList() |
|
} else if (this.isCloudDataTree) { |
|
this.loadCloudDataTree() |
|
} |
|
}, |
|
|
|
// 加载本地数据 |
|
loadLocalData() { |
|
this.treeData = this.localdata |
|
if (Array.isArray(this.dataValue)) { |
|
const value = this.dataValue as Array<UTSJSONObject> |
|
this.selectedPaths = value.slice(0) |
|
this._pushSelectedTreeNodes(value, this.localdata) |
|
} else { |
|
this._pushSelectedNodes(this.localdata) |
|
} |
|
}, |
|
|
|
// 加载 Cloud 数据 (单列) |
|
loadCloudDataList() { |
|
this._loadCloudData(null, (data : Array<UTSJSONObject>) => { |
|
this.treeData = data |
|
this._pushSelectedNodes(data) |
|
}) |
|
}, |
|
|
|
// 加载 Cloud 数据 (树形) |
|
loadCloudDataTree() { |
|
let commandOptions = { |
|
field: this._cloudDataPostField(), |
|
where: this._cloudDataTreeWhere(), |
|
getTree: true |
|
} as GetCommandOptions |
|
if (this._checkIsNotNull(this.gettree)) { |
|
commandOptions.startwith = `${this.selfField}=='${this.dataValue as string}'` |
|
} |
|
this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => { |
|
this.treeData = data |
|
if (this.selectedPaths.length > 0) { |
|
this._pushSelectedTreeNodes(this.selectedPaths, data) |
|
} else { |
|
this._pushSelectedNodes(data) |
|
} |
|
}) |
|
}, |
|
|
|
// 加载 Cloud 数据 (节点) |
|
loadCloudDataNode(nodeData : UTSJSONObject) { |
|
const commandOptions = { |
|
field: this._cloudDataPostField(), |
|
where: this._cloudDataNodeWhere() |
|
} as GetCommandOptions |
|
this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => { |
|
nodeData['children'] = data |
|
if (data.length == 0) { |
|
nodeData['isleaf'] = true |
|
this.onFinish() |
|
} else { |
|
this._pushSelectedNodes(data) |
|
} |
|
}) |
|
}, |
|
|
|
// 回显 Cloud Tree Path |
|
loadCloudDataPath() { |
|
if (!this.hasCloudDataValue) { |
|
return |
|
} |
|
|
|
const command : GetCommandOptions = {} |
|
|
|
// 单列 |
|
if (this.isCloudDataList) { |
|
// 根据 field's as value标识匹配 where 条件 |
|
let where : Array<string> = []; |
|
let whereField = this._getForeignKeyByField(); |
|
if (whereField.length > 0) { |
|
where.push(`${whereField} == '${this.dataValue as string}'`) |
|
} |
|
|
|
let whereString = where.join(' || ') |
|
if (this._checkIsNotNull(this.where)) { |
|
whereString = `(${this.where}) && (${whereString})` |
|
} |
|
|
|
command.field = this._cloudDataPostField() |
|
command.where = whereString |
|
} |
|
|
|
// 树形 |
|
if (this.isCloudDataTree) { |
|
command.field = this._cloudDataPostField() |
|
command.getTreePath = { |
|
startWith: `${this.selfField}=='${this.dataValue as string}'` |
|
} |
|
} |
|
|
|
this._loadCloudData(command, (data : Array<UTSJSONObject>) => { |
|
this._extractTreePath(data, this.selectedPaths) |
|
}) |
|
}, |
|
|
|
_loadCloudData(options ?: GetCommandOptions, callback ?: ((data : Array<UTSJSONObject>) => void)) { |
|
if (this.loading) { |
|
return |
|
} |
|
this.loading = true |
|
|
|
this.error = null |
|
|
|
this._getCommand(options).then((response : UniCloudDBGetResult) => { |
|
callback?.(response.data) |
|
}).catch((err : any | null) => { |
|
this.error = err as UniCloudError |
|
}).finally(() => { |
|
this.loading = false |
|
}) |
|
}, |
|
|
|
_cloudDataPostField() : string { |
|
let fields = [this.field]; |
|
if (this.parentField.length > 0) { |
|
fields.push(`${this.parentField} as parent_value`) |
|
} |
|
return fields.join(',') |
|
}, |
|
|
|
_cloudDataTreeWhere() : string { |
|
let result : Array<string> = [] |
|
let selectedNodes = this.selectedNodes.length > 0 ? this.selectedNodes : this.selectedPaths |
|
let parentField = this.parentField |
|
if (parentField.length > 0) { |
|
result.push(`${parentField} == null || ${parentField} == ""`) |
|
} |
|
if (selectedNodes.length > 0) { |
|
for (var i = 0; i < selectedNodes.length - 1; i++) { |
|
const parentFieldValue = selectedNodes[i].getString('value', '') |
|
result.push(`${parentField} == '${parentFieldValue}'`) |
|
} |
|
} |
|
|
|
let where : Array<string> = [] |
|
if (this._checkIsNotNull(this.where)) { |
|
where.push(`(${this.where as string})`) |
|
} |
|
|
|
if (result.length > 0) { |
|
where.push(`(${result.join(' || ')})`) |
|
} |
|
|
|
return where.join(' && ') |
|
}, |
|
|
|
_cloudDataNodeWhere() : string { |
|
const where : Array<string> = [] |
|
if (this.selectedNodes.length > 0) { |
|
const value = this.selectedNodes[this.selectedNodes.length - 1].getString('value', '') |
|
where.push(`${this.parentField} == '${value}'`) |
|
} |
|
|
|
let whereString = where.join(' || ') |
|
if (this._checkIsNotNull(this.where)) { |
|
return `(${this.where as string}) && (${whereString})` |
|
} |
|
|
|
return whereString |
|
}, |
|
|
|
_getWhereByForeignKey() : string { |
|
let result : Array<string> = [] |
|
let whereField = this._getForeignKeyByField(); |
|
if (whereField.length > 0) { |
|
result.push(`${whereField} == '${this.dataValue as string}'`) |
|
} |
|
|
|
if (this._checkIsNotNull(this.where)) { |
|
return `(${this.where}) && (${result.join(' || ')})` |
|
} |
|
|
|
return result.join(' || ') |
|
}, |
|
|
|
_getForeignKeyByField() : string { |
|
const fields = this.field.split(',') |
|
let whereField = '' |
|
for (let i = 0; i < fields.length; i++) { |
|
const items = fields[i].split('as') |
|
if (items.length < 2) { |
|
continue |
|
} |
|
if (items[1].trim() === 'value') { |
|
whereField = items[0].trim() |
|
break |
|
} |
|
} |
|
return whereField |
|
}, |
|
|
|
_getCommand(options ?: GetCommandOptions) : Promise<UniCloudDBGetResult> { |
|
let db = uniCloud.databaseForJQL() |
|
|
|
let collection = Array.isArray(this.collection) ? db.collection(...(this.collection as Array<any>)) : db.collection(this.collection) |
|
|
|
let filter : UniCloudDBFilter | null = null |
|
if (this.foreignKey.length > 0) { |
|
filter = collection.foreignKey(this.foreignKey) |
|
} |
|
|
|
const where : any = options?.where ?? this.where |
|
if (typeof where == 'string') { |
|
const whereString = where as string |
|
if (whereString.length > 0) { |
|
filter = (filter != null) ? filter.where(where) : collection.where(where) |
|
} |
|
} else { |
|
filter = (filter != null) ? filter.where(where) : collection.where(where) |
|
} |
|
|
|
let query : UniCloudDBQuery | null = null |
|
if (this.field.length > 0) { |
|
query = (filter != null) ? filter.field(this.field) : collection.field(this.field) |
|
} |
|
if (this.groupby.length > 0) { |
|
if (query != null) { |
|
query = query.groupBy(this.groupby) |
|
} else if (filter != null) { |
|
query = filter.groupBy(this.groupby) |
|
} |
|
} |
|
if (this.groupField.length > 0) { |
|
if (query != null) { |
|
query = query.groupField(this.groupField) |
|
} else if (filter != null) { |
|
query = filter.groupField(this.groupField) |
|
} |
|
} |
|
if (this.distinct == true) { |
|
if (query != null) { |
|
query = query.distinct(this.field) |
|
} else if (filter != null) { |
|
query = filter.distinct(this.field) |
|
} |
|
} |
|
if (this.orderby.length > 0) { |
|
if (query != null) { |
|
query = query.orderBy(this.orderby) |
|
} else if (filter != null) { |
|
query = filter.orderBy(this.orderby) |
|
} |
|
} |
|
|
|
const size = this.pagination.size |
|
const current = this.pagination.current |
|
if (query != null) { |
|
query = query.skip(size * (current - 1)).limit(size) |
|
} else if (filter != null) { |
|
query = filter.skip(size * (current - 1)).limit(size) |
|
} else { |
|
query = collection.skip(size * (current - 1)).limit(size) |
|
} |
|
|
|
const getOptions = {} |
|
const treeOptions = { |
|
limitLevel: this.limitlevel, |
|
startWith: this.startwith |
|
} |
|
if (this.getcount == true) { |
|
getOptions['getCount'] = this.getcount |
|
} |
|
|
|
const getTree : any = options?.getTree ?? this.gettree |
|
if (typeof getTree == 'string') { |
|
const getTreeString = getTree as string |
|
if (getTreeString.length > 0) { |
|
getOptions['getTree'] = treeOptions |
|
} |
|
} else if (typeof getTree == 'object') { |
|
getOptions['getTree'] = treeOptions |
|
} else { |
|
getOptions['getTree'] = getTree |
|
} |
|
|
|
const getTreePath = options?.getTreePath ?? this.gettreepath |
|
if (typeof getTreePath == 'string') { |
|
const getTreePathString = getTreePath as string |
|
if (getTreePathString.length > 0) { |
|
getOptions['getTreePath'] = getTreePath |
|
} |
|
} else { |
|
getOptions['getTreePath'] = getTreePath |
|
} |
|
|
|
return query.get(getOptions) |
|
}, |
|
|
|
_checkIsNotNull(value : any) : boolean { |
|
if (typeof value == 'string') { |
|
const valueString = value as string |
|
return (valueString.length > 0) |
|
} else if (value instanceof UTSJSONObject) { |
|
return true |
|
} |
|
return false |
|
}, |
|
|
|
_checkIsLeafNode(nodeData : UTSJSONObject) : boolean { |
|
if (this.selectedIndex >= this.limitlevel) { |
|
return true |
|
} |
|
|
|
if (nodeData.getBoolean('isleaf', false)) { |
|
return true |
|
} |
|
|
|
return false |
|
}, |
|
|
|
_checkHasChildren(nodeData : UTSJSONObject) : boolean { |
|
const children = nodeData.getArray('children') ?? ([] as Array<any>) |
|
return children.length > 0 |
|
}, |
|
|
|
_pushSelectedNodes(nodes : Array<UTSJSONObject>) { |
|
this.selectedNodes.push(DefaultSelectedNode) |
|
this.selectedPages.push(nodes) |
|
this.selectedIndex = this.selectedPages.length - 1 |
|
}, |
|
|
|
_trimSelectedNodes(nodeData : UTSJSONObject) { |
|
this.selectedNodes.splice(this.selectedIndex) |
|
this.selectedNodes.push(nodeData) |
|
|
|
if (this.selectedPages.length > 0) { |
|
this.selectedPages.splice(this.selectedIndex + 1) |
|
} |
|
|
|
const children = nodeData.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>) |
|
if (children.length > 0) { |
|
this.selectedNodes.push(DefaultSelectedNode) |
|
this.selectedPages.push(children) |
|
} |
|
|
|
this.selectedIndex = this.selectedPages.length - 1 |
|
}, |
|
|
|
_pushSelectedTreeNodes(paths : Array<UTSJSONObject>, nodes : Array<UTSJSONObject>) { |
|
let children : Array<UTSJSONObject> = nodes |
|
paths.forEach((node : UTSJSONObject) => { |
|
const findNode = children.find((item : UTSJSONObject) : boolean => { |
|
return (item.getString(this.mappingValueName) == node.getString(this.mappingValueName)) |
|
}) |
|
if (findNode != null) { |
|
this.selectedPages.push(children) |
|
this.selectedNodes.push(node) |
|
children = findNode.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>) |
|
} |
|
}) |
|
this.selectedIndex = this.selectedPages.length - 1 |
|
}, |
|
|
|
_extractTreePath(nodes : Array<UTSJSONObject>, result : Array<UTSJSONObject>) { |
|
if (nodes.length == 0) { |
|
return |
|
} |
|
|
|
const node = nodes[0] |
|
result.push(node) |
|
|
|
const children = node.getArray<UTSJSONObject>('children') |
|
if (Array.isArray(children) && children!.length > 0) { |
|
this._extractTreePath(children, result) |
|
} |
|
} |
|
} |
|
})
|
|
|