UNPKG

vue-django

Version:

个人实验项目, 本框架的目标是借鉴并超越django admin的自动化思想, 实现UI前端的极简快速定制开发

265 lines (261 loc) 9.36 kB
/** * Created by denishuang on 2017/8/2. */ import {Register} from '../../utils/app_model' import axios from '../../configs/axios' import Qs from 'qs' // import store from '../store' export function joinErrors(errors) { let es = {} for (let n in errors) { es[n] = errors[n].join('') } return es } export default function (appModel, defaults, eventor) { let m = { appModel, defaults: defaults || {}, eventor, config: {}, id: null, fieldConfigs: {}, options: {}, errors: {}, data: {}, viewsConfig: undefined, init () { this.config = Register.getConfig(this.appModel) this.loadOptions() }, clear () { Object.assign(this.data, this.emptyDataFromOptions(this.fieldConfigs)) this.id = null this.errors = {} }, loadData () { if (!this.id) { return Promise.resolve({}) } else { return axios.get(this.getDetailUrl()).then(({data}) => { this.id = data.id return data }) } }, loadOptions () { if (this.config.rest_options) { this.cacheOptions(this.config.rest_options) return Promise.resolve(this.config.rest_options) } return axios.options(this.getListUrl()).then(({data}) => { this.config.rest_options = data this.cacheOptions(this.config.rest_options) return data }) }, cacheOptions (options) { this.options = Object.assign({}, this.options, options) this.fieldConfigs = Object.assign({}, this.fieldConfigs, options.actions.LIST, options.actions.POST) Object.keys(this.fieldConfigs).forEach((a) => { this.fieldConfigs[a].name = a }) }, emptyDataFromOptions (m) { let dvs = {} Object.assign(dvs, this.defaults) let r = {} Object.keys(m).forEach((k) => { let f = m[k] let v = dvs[f.name] || f.default if (v !== undefined) { r[k] = v } else if (f.type === 'boolean') { r[k] = true } else if (f.multiple) { r[k] = [] } else if (f.type === 'string') { r[k] = '' } else if (f.type === 'nested object') { r[k] = {} } else { r[k] = null } // r[k] = v !== undefined ? v : (f.type === 'boolean' ? true : f.multiple ? [] : f.type === 'string' ? '' : null) }) return r }, fillEmptyDataFromOptions (r) { let m = this.fieldConfigs let dvs = {...this.defaults} Object.keys(m).forEach((k) => { if (!(k in r)) { let f = m[k] let v = dvs[f.name] || f.default r[k] = v !== undefined ? v : (f.type === 'boolean' ? true : f.multiple ? [] : f.type === 'string' ? '' : null) } }) }, load () { return Promise.all([this.loadData(), this.loadOptions(), this.loadViewsConfig()]).then(rs => { let data = rs[0], restOptions = rs[1] if (!this.id) { data = this.emptyDataFromOptions(restOptions.actions.POST) } this.data = Object.assign({}, this.data, data) return rs }) }, save (data) { let d = Object.assign({}, this.defaults, this.data, data) let promise if (!this.id) { promise = axios.post(this.getListUrl(), d) } else { promise = axios.patch(this.getDetailUrl(), d) } return promise.then(({data}) => { this.id = data.id this.data = Object.assign({}, this.data, data) this.emitPosted(this.id) return data }) // .catch((error) => this.onErrors(error)) }, doAction (action, data, method, id) { if (!method) { method = 'post' } if (!id) { id = this.id } method = axios[method] if(action.length>0 && !action.endsWith('/')){ action= `${action}/` } if (!id) { return method(`${this.getListUrl()}${action}`, data) } else { return method(`${this.getDetailUrl(id)}${action}`, data) } }, selectOrCreate (d) { let url = this.getListUrl() return axios.get(`${url}?${Qs.stringify(d)}`).then(({data}) => { if (data.count === 1) { return data.results[0] } else if (data.count === 0) { return axios.post(url, d).then(({data}) => { return data }) } else { throw Error('记录不唯一') } }) }, removeRelateObject (rel, id) { this.data[rel] = this.data[rel].filter(a => a !== id) return this.save() }, destroy (id) { id = id || this.id return axios.delete(this.getDetailUrl(id)).then(() => { this.eventor && this.eventor.$emit('model-deleted', {appModel: this.appModel, id}) }) }, emitPosted (id) { this.eventor && this.eventor.$emit('model-posted', {appModel: this.appModel, id}) }, onErrors (error) { if (error.code === 400) { this.errors = joinErrors(error.msg) } return Promise.reject(error) }, checkPermission (p, ps) { if (!ps) { return false } let pn = this.appModel.replace('.', `.${p}_`) return ps.includes(pn) }, getListUrl () { return `/${this.appModel.replace('.', '/')}/` }, getDetailUrl (id) { let mid = id || this.id return `${this.getListUrl()}${mid}/` }, query (d, url) { if (!url) { url = this.getListUrl() } return axios.get(`${url}?${Qs.stringify(d, {arrayFormat: 'comma'})}`).then(({data}) => { return data }) }, title () { return (!this.id && `新增${this.config.verbose_name}`) || this.data['__str__'] }, loadViewsConfig () { if (this.viewsConfig) { return Promise.resolve(this.viewsConfig) } return import(`@/views${this.getListUrl()}config.js`).then(m => { return m.default || {} }).catch((err) => { console.warn(`找不到视图配置@/views${this.getListUrl()}config.js,将使用默认配置, err: ${err}`) return {} }).then(config => { this.viewsConfig = config return config }) }, loadOptionsAndViewsConfig () { return Promise.all([this.loadOptions(), this.loadViewsConfig()]) }, parentMultipleRelationField (parent) { if (parent) { let pfs = Object.values(parent.fieldConfigs) let f = pfs.find(a => a.model === this.appModel) if (f && f.multiple === true) { return f } } return null }, getParentQueries(parent, pct_id) { let r = {} if (parent) { let f = this.parentMultipleRelationField(parent) if (f) { let ids = parent.data[f.name] r['id__in'] = ids.length > 0 && ids || [0] } else { let am = parent.appModel let pid = parent.id let fs = Object.values(this.fieldConfigs) let f = fs.find(a => a.model === am) if (f && f.multiple !== true) { r[f.name] = pid } else { let popt = this.options if (popt.generic_foreign_key) { let {ct_field, fk_field} = popt.generic_foreign_key r[ct_field] = pct_id if (!this.fieldConfigs[fk_field]) { throw Error(`genric foreign key id_field:${fk_field} not found.`) } r[fk_field] = pid || undefined } } } } return r }, getOptionDisplayName(f, v) { return this.fieldConfigs[f].choices.find(a => a.value===v).display_name } } m.init() return m }