Skip to content

Commit

Permalink
Merge branch 'master' of github.com:szuprefix/vue-django
Browse files Browse the repository at this point in the history
  • Loading branch information
szuprefix committed Apr 26, 2020
2 parents bb83f99 + a0b917e commit df8566f
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 39 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-django",
"version": "0.7.8",
"version": "0.7.9",
"description": "个人实验项目, 本框架的目标是借鉴并超越django admin的自动化思想, 实现UI前端的极简快速定制开发",
"main": "index.js",
"files": [
Expand Down
56 changes: 56 additions & 0 deletions src/components/form/widgets/DateRange.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<el-date-picker
v-model="period"
:type="`${type}range`"
:range-separator="defaultSeparator"
start-placeholder="开始日期"
end-placeholder="结束日期"
:value-format="valueFormat"
align="right"
:picker-options="date_picker_options">
</el-date-picker>
</template>
<script>
import {options_without_time} from '../../../utils/date_picker_options'
import dateUtil from 'element-ui/src/utils/date'
export default{
props: {
value: String,
field: Object,
separator: {type: String, default: ''}
},
data () {
return {
date_picker_options: options_without_time,
defaultSeparator: '',
period: undefined
}
},
components: {},
mounted () {
this.setPeriod()
},
methods: {
setPeriod () {
this.period = this.value && this.value.split(this.separator)
}
},
computed: {
type () {
return this.field.type
},
valueFormat () {
return this.field && this.field.valueFormat || this.$attrs.valueFormat || (this.type === 'datetime' ? 'yyyy-MM-ddTHH:mm:ss' : 'yyyy-MM-dd')
}
},
watch: {
value (v) {
this.setPeriod()
},
period (v) {
let s = v && v.map(a => dateUtil.format(new Date(a), this.valueFormat)).join(this.separator) || undefined
this.$emit('input', s)
}
}
}
</script>
14 changes: 10 additions & 4 deletions src/components/generic/ContentType.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import axios from '../../configs/axios'
import Model from "../model/Model";
export default {
idMap: undefined,
nameMap: undefined,
model: Model('contenttypes.contenttype'),
loading: false,
getAppModel (id) {
Expand All @@ -15,19 +16,24 @@ export default {
let d = this.idMap[id]
return Model(`${d.app_label}.${d.model}`)
},
getId (name) {
return this.nameMap[name]
},
loadIdMap () {
if (this.idMap === undefined && this.loading === false) {
this.loading = true
axios.get(`${this.model.getListUrl()}?page_size=1000`).then(({data}) => {
return data.results
}).then(ls => {
let d = {}
let idm = {}
let nm = {}
ls.forEach(a => {
d[a.id] = a
idm[a.id] = a
nm[`${a.app_label}.${a.model}`] = a.id
})
this.idMap = d
this.idMap = idm
this.nameMap = nm
this.loading = false
// console.log(this.idMap)
}).catch((e) => {
this.loading = false
})
Expand Down
63 changes: 55 additions & 8 deletions src/components/model/Search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,34 @@
</el-input>
<template v-for="f in filterFields" v-if="! (f.name in exclude)">
<el-select v-model="value[f.name]" clearable :placeholder="`请选择${f.label}`" v-if="f.type=='boolean'"
@change="onSearch">
:title="f.label" :style="`width:${f.label.length+5}rem;min-width:8rem;`" @change="onSearch">
<el-option :label="f.label" :value="true"></el-option>
<el-option :label="getBoolFieldFalseLabel(f.label)" :value="false"></el-option>
</el-select>
<model-select :field="f" v-model="value[f.name]" @input="onSearch"
:showCreate="false" :appModel="f.model"
v-else-if="f.model" :pageSize="100"></model-select>
<el-select v-model="value[f.name]" clearable :placeholder="`请选择${f.label}`" v-else-if="f.choices" @change="onSearch">
:title="f.label" :style="`width:${f.label.length+5}rem;min-width:8rem;`"
v-else-if="f.model && f.name !== genericContentTypeField" :pageSize="100"></model-select>
<el-select v-model="value[f.name]" clearable :placeholder="`请选择${f.label}`" v-else-if="f.choices"
:title="f.label" @change="onSearch">
<el-option v-for="c in f.choices" :label="c.display_name" :value="c.value" :key="c.value"></el-option>
</el-select>
<date-range :field="f" v-model="value[`${f.name}__range`]" separator=","
:title="f.label" v-else-if="['date', 'datetime'].includes(f.type)" @input="onSearch"></date-range>
</template>

<template v-for="f in filterFields" v-if="! (f.name in exclude)">
<array-input v-if="f.type === 'string' && f.lookups && f.lookups.includes('in')"
v-model="value[`${f.name}__in`]" :placeholder="`批量查询${f.label}`" style="width: 10rem;"
:autosize="{minRows:1,maxRows:4}" @change="onSearch"></array-input>
:title="f.label" :autosize="{minRows:1,maxRows:4}" @change="onSearch"></array-input>
<el-input v-model="value[f.name]" :placeholder="`请输入${f.label}`"
v-else-if="f.type === 'string' && f.lookups && f.lookups.includes('exact') && !f.lookups.includes('in') && !searchFields.includes(f.label)"
:title="f.label" style="width: 10rem;" clearable @change="onSearch"></el-input>
</template>
</div>
</template>
<script>
import DateRange from '../form/widgets/DateRange.vue'
import ModelSelect from './Select.vue'
import ArrayInput from '../widgets/ArrayInput.vue'
import array_normalize from '../../utils/array_normalize'
Expand All @@ -40,6 +48,7 @@
model: Object,
items: Array,
value: Object,
map: {type: Object, default: {}},
exclude: [Array, Object]
},
data () {
Expand All @@ -50,7 +59,7 @@
baseQueries: {}
}
},
components: {ModelSelect, ArrayInput},
components: {ModelSelect, ArrayInput, DateRange},
created () {
},
methods: {
Expand All @@ -60,12 +69,38 @@
init () {
let search = this.model.options.actions.SEARCH
this.searchFields = search.search_fields
let filterItems = this.items || search.filter_fields
this.filterFields = array_normalize(filterItems, this.model.fieldConfigs, (a) => {
return {multiple: false, ...a}
let items = this.items || search.filter_fields
let ffields = array_normalize(items, this.model.fieldConfigs, (a) => {
let label = this.map[a.name] && this.map[a.name].label || a.label
return {multiple: false, ...a, label, widget: this.defaultWidget(a)}
})
this.filterFields = this.reorder(ffields)
this.filters = Object.assign({}, this.getFilters())
},
defaultWidget (item) {
let f = item
if (f.type=='boolean') {
return 'boolean'
} else if (f.model && f.name !== this.genericContentTypeField) {
return 'modelselect'
} else if (f.choices) {
return 'select'
} else if (['date', 'datetime'].includes(f.type)) {
return 'daterange'
} else if (f.type === 'string' && f.lookups && f.lookups.includes('in')) {
return 'array'
} else if (f.type === 'string' && f.lookups && f.lookups.includes('exact') && !f.lookups.includes('in') && !this.searchFields.includes(f.label)) {
return 'input'
}
},
reorder (items) {
let os = ['boolean', 'select', 'modelselect','daterange', 'input', 'array']
let rs = []
os.forEach(w => {
rs = rs.concat(items.filter(a => a.widget === w))
})
return rs
},
getFilters(){
let postFields = this.model.fieldConfigs
let filters = {}
Expand Down Expand Up @@ -104,6 +139,18 @@
})
return this.searchFields.filter((a) => !(a in vns)).join(',')
},
genericContentTypeField () {
let popt = this.model.options
if (popt.generic_foreign_key) {
let {ct_field, fk_field} = popt.generic_foreign_key
return ct_field
}
}
},
watch: {
map () {
this.init()
}
}
}
</script>
Expand Down
35 changes: 12 additions & 23 deletions src/components/model/Table.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<template>
<div>
<search v-model="search" :model="model" :items="searchItems" :exclude="_baseQueries" ref="search"
v-if="showSearch"
@change="onSearch"></search>
v-if="showSearch" :map="searchMap" @change="onSearch"></search>
<batch-actions :items="batchActionItems" @done="refresh" :context="{selection,count}"
v-if="batchActionItems.length>0"></batch-actions>
<el-drawer :visible.sync="editing" direction="rtl"
Expand Down Expand Up @@ -44,6 +43,7 @@
import Date2Now from '../widgets/Date2Now.vue'
import ForeignKey from '../widgets/ForeignKey.vue'
import Search from './Search.vue'
import ContentType from '../generic/ContentType'
export default{
name: 'ModelTable',
Expand Down Expand Up @@ -286,25 +286,7 @@
return (d, n, v) => d[`${f.name}_name`]
}
},
// excelFormat(data){
// let ds = data.map((d) => {
// console.log(this.tableItems)
// return this.tableItems.map((a) => {
// let v = d[a.name]
// if (a.choices) {
// v= a.choices.find(a => a.value === v).display_name
// } else if (a.model) {
// v = d[`${a.name}_name`]
// }
// if (a.formatter) {
// v = a.formatter(d, a.name, v)
// }
// return v
//
// })
// })
// return [this.tableItems.map((a) => a.label)].concat(ds)
// },
checkPermission(p, m){
m = m || this
return this.$store.state.user.model_permissions[m.appModel].includes(p)
Expand All @@ -328,11 +310,11 @@
let popt = this.model.options
if (popt.generic_foreign_key) {
let {ct_field, fk_field} = popt.generic_foreign_key
r[ct_field] = this.parent.options.content_type_id
r[ct_field] = ContentType.getId(this.parent.appModel)
if (!this.model.fieldConfigs[fk_field]) {
throw Error(`genric foreign key id_field:${id_field} not found.`)
}
r[fk_field] = pid
r[fk_field] = pid || undefined
}
}
Expand Down Expand Up @@ -393,6 +375,13 @@
},
_baseQueries () {
return Object.assign({}, this.parentQueries, this.baseQueries)
},
searchMap () {
let d = {}
this.tableItems.forEach(a => {
d[a.name]={name: a.name, label: a.label}
})
return d
}
},
watch: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/stats/ChartGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@
}
},
loadTimeData(period){
let context = {measures: this.items.map((a) => a.name), period: `${period[0]}${period[1]}`}
period = period instanceof Array ? `${period[0]}${period[1]}` : period
let context = {measures: this.items.map((a) => a.name), period}
let qs = Qs.stringify(context, {indices: false})
this.loading = "加载中"
let url = this.url
Expand Down
2 changes: 1 addition & 1 deletion src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export var genModelRouters = function (apps, importFunc, defaultLayout) {
path: `/${a}/${m}/${action.name}/`,
name: `${a}-${m}-${action.name}`,
meta: {
title: `${action.verbose_name || action.title}${mname}`,
title: `${mname}${action.verbose_name || action.title}`,
model,
icon: model.icon,
permissions: action.permission || []
Expand Down
3 changes: 2 additions & 1 deletion src/utils/date_picker_options.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export var addDays = function (d, days) {
return d
}
import dateUtil from 'element-ui/src/utils/date'
const DFMT = "yyyy-MM-ddTHH:mm:ss"
const DFMT = "yyyy-MM-ddTHH:mm:ss+08:00"
// const DFMT0 = "yyyy-MM-ddT00:00:00+08:00"


export var recent_nday = function (n) {
Expand Down

0 comments on commit df8566f

Please sign in to comment.