element-nice-ui
Version:
A Component Library for Vue.js.
256 lines (219 loc) • 6.38 kB
JavaScript
// 该类用来控制表格的数据来源, 以及提供一些对数据的处理操作
import { getValueByPath } from 'element-nice-ui/src/utils/util'
import Vue from 'vue'
/**
* 创建数据模型
* @param {Object} options
* @param {string} [options.api] 请求地址
* @param {any[]} [options.data] 表格数据
* @param {any} [options.http] 请求实例
* @returns
*/
export default function createModel(options) {
let vm = new Vue({
data() {
const { data, api, pagination, rowKey, showAsTree, query, dataPath, autoQueried } = options
const state = {
/** 表格数据 */
data: [], // 表格数据
/** 请求的api */
api: '', // 表格请求api
/** 是否是分页类型的表格 */
pagination, // 是否是分页模式的数据
/** 分页页码 */
page: 1,
/** 分页大小 */
size: 20,
/** 数据总数 */
total: 0,
/** 数据加载 */
loading: false,
/** 是否应该发起请求 */
_shouldRequest: true,
/** 请求方法 */
method: 'get',
/** 查询触发状态 */
willQuery: false,
/** 树状表格属性 */
childrenKey: 'children',
/** 行key */
rowKey,
/** 是否以树形显示 */
showAsTree,
/** 查询条件 */
query,
_defaultQuery: {...query},
/** 已选中行的row-key值 */
selected: '',
/** 已选中行的row-key值的集合 */
checked: [],
dataPath,
/** 自动校验 */
_autoQueried: autoQueried
}
// 传入一个自定义
if (data) {
state.data = data
state._shouldRequest = false
}
if (api) {
let apiArray = api.split(':').map(s => s.trim())
if (apiArray.length === 1) {
state.api = api
} else {
state.method = apiArray[0].toLowerCase()
state.api = apiArray[1]
}
}
return state
},
watch: {
willQuery(v) {
v &&
void (async () => {
await this.fetchData()
this.notifyToCompleteTheQuery()
})()
},
api: {
immediate: true,
handler() {
this.notifyToQuery()
}
},
page() {
this.notifyToQuery()
},
size() {
this.notifyToQuery()
}
},
methods: {
transformData(data) {
const { childrenKey } = this
if (this.showAsTree) {
function recurse(data, depth = 0) {
data.forEach((item, i) => {
item._depth = depth
item.$_expanded = false
if (item[childrenKey] && item[childrenKey].length) {
recurse(item[childrenKey], depth + 1)
}
})
}
recurse(data)
}
return data
},
/** 请求远端数据 */
async fetchData() {
// TODO这个地方还需要配合cahce来实现table的缓存读取
const { api, method, $EL_TABLE_PROP_CONFIG, page, size, pagination, $http } = this
if (!$http || !api || !this.$data._shouldRequest) return
const {
// 分页数据路径
pageDataPath,
// 列表数据路径
listDataPath,
// 总数路径
totalPath,
pageKey = 'current',
// 分页数据大小
sizeKey = 'size'
} = $EL_TABLE_PROP_CONFIG
const params = {
...this.query
}
if (pagination) {
params[pageKey] = page
params[sizeKey] = size
}
this.loading = true
const { data, code } = await $http[method](api, { params }).catch(err => {
this.loading = false
return Promise.reject(err)
})
this.loading = false
if (code !== 200) return
this.data = this.transformData(
getValueByPath(data, this.dataPath || (pagination ? pageDataPath : listDataPath))
)
if (pagination) {
this.total = getValueByPath(data, totalPath)
}
},
/** 通知侦听器即将发起查询 */
notifyToQuery() {
this.willQuery = true
},
/** 完成查询 */
notifyToCompleteTheQuery() {
this.willQuery = false
},
/** 新增数据 */
create(index, record) {
if (typeof record === 'undefined' && typeof index === 'object') {
record = index
this.data.unshift(record)
} else if (Array.isArray(index) && typeof record === 'object') {
this.find(index)?.children?.unshift(record)
}
},
/** 删除数据 */
delete(index) {
if (typeof index === 'number') {
this.data.splice(index, 1)
} else if (Array.isArray(index)) {
}
},
/** 更新数据 */
update() {},
/** 查找数据 */
find(conditions) {
if (typeof conditions === 'undefined') {
return this.data
}
if (typeof conditions === 'number') {
return this.data[conditions]
}
if (Array.isArray(conditions)) {
const children = this.childrenKey
const initialValue = {
[children]: this.data
}
return conditions.reduce((acc, cur) => {
let item = acc[children]
if (item) {
return item[cur]
}
return null
}, initialValue)
}
if (typeof conditions === 'object' && conditions !== null) {
let conditionKeys = Object.keys(conditions)
let ret = []
this.data.forEach(item => {
conditionKeys.every(key => item[key] === conditions[key]) && ret.push(item)
})
return ret
}
return this.data
},
resetQuery() {
const { _defaultQuery } = this.$data
Object.keys(this.query).forEach(key => {
this.query[key] = _defaultQuery[key]
})
}
},
created() {
if (this.$data._autoQueried) {
this.$watch(
() => this.$data._autoQueried.map(field => this.query[field]),
() => this.notifyToQuery()
)
}
}
})
return vm
}