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 Jul 6, 2021
2 parents f45ad55 + c0afebe commit 18cd4ae
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 35 deletions.
64 changes: 64 additions & 0 deletions doc/config配置.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Config 文件配置

## 创建新的app

1. 首先在apps.js 文件中将app加入到apps中

```
let apps = {
'app_name':{
verbose_name: '在侧边栏显示的列名'
icon: 'el ui 中的icon',
menu: '上级菜单',
itemActions:[
{name: '取名', icon: '图标', title: '标题', do:'执行的命令'}
]
}
}
```



2. 在src/views目录下创建app对应的目录,并创建对应的子目录如: baidu/user为百度app下的user目录,并在user目录下创建config.js文件, 通过配置config.js可以生成对应django model中对应表的列表页。例如在django中我们startapp 名为baidu,并添加了user的model,对应数据库中的baidu_user表,在前端vue配置config文件即可自动生成对应的列表页,省去了创建列表页的繁琐。下面展示部分配置:

```
function search_post({row}){
console.log(row)
}
export default {
list: {
items: ['username', 'age', 'city'],
options: {
remoteTable:{
rowActions:[{name:'anyname', label: '按钮上的文字', do:search_post}]
}
},
batchActions:[
{
name: 'name',
api: 'batch_disable',
context: {'enable_flag': false},
label: '禁用',
notice: '禁用将不再显示.'
}
]
}
}
```

其中list表示列表的配置,items用于配置显示的列,代码表示显示username, age, city三列, options用于配置表格,在remoteTable下可以配置行操作按钮, name可以随意设置,label设置按钮文字,do设置执行的命令。

**特别注意:do如果设置为方法名(不带括号)则会调用前面设置的function如上面的search_post方法,而且会自动传参过去,如上面的row就是传入的参数,里面包含了行信息。除此之外还会有column, store等参数可选。如果do后面跟随字符串如 'baidu/user/add' 则点击按钮后会访问'baidu/user/add.vue' , 我们可以使用this.$attrs 获取row的参数。**

batchActions用于批处理数据,批处理多行信息如删除等操作。其中name可以随意设置,api为后端api, 如示例代码将会调用 url/api/baidu/user/batch_disable 方法,并会默认传入每行的id, 并附带context中的参数enable_flag. label设置顶部按钮文本,notice设置弹出的提示。

后端的api的设计:

```
@decorators.action(['POST'], detail=False)
def batch_disable(self, request):
return self.do_batch_action('is_active')
```

后端使用do_batch_action可以用来处理请求,如上面的代码可以将 is_active 字段设置为true, 因为is_active字段是boolean类型的,do_batch_action 默认支持处理boolean数据, 如果哟啊将is_active设为false则需要传入context.
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.9.5",
"version": "0.9.7",
"description": "个人实验项目, 本框架的目标是借鉴并超越django admin的自动化思想, 实现UI前端的极简快速定制开发",
"main": "index.js",
"files": [
Expand Down
3 changes: 3 additions & 0 deletions src/components/form/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
},
onPosted(data){
this.loading = false
if(data === false){
return
}
this.$message({message: this.successInfo || `${this.submitName}成功`, type: 'success'})
this.$emit('form-posted', data)
return data
Expand Down
10 changes: 5 additions & 5 deletions src/components/generic/ForeignKey.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<a :href="`#${url}`" title="点击跳转" class="foreignkey-link" v-if="hasLink">
{{label}}
</a>
<span v-else>
<a :href="`#${url}`" title="点击跳转" class="foreignkey-link" v-if="hasLink">
{{label}}
</a>
<span v-else>
{{label}}
</span>
</template>
Expand All @@ -13,7 +13,7 @@
export default{
props: {
value: [String, Number],
field: Object ,
field: Object,
context: Object
},
created () {
Expand Down
15 changes: 11 additions & 4 deletions src/components/mobile/Tabbar.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<template>
<tabbar v-show="show" style="position: fixed;" v-on="$listeners">
<tabbar-item :show-dot="t.showDot" :selected="t.link === $route.fullPath" :badge="t.badge" v-for="t in tabItems" :link="t.link" :key="t.name">
<i slot="icon" :class="`iconfont icon-${t.icon}`"></i>
<span slot="label">{{t.label}}</span>
<tabbar v-show="show" style="position: fixed;" v-bind="[$attrs]" v-on="$listeners">
<tabbar-item :show-dot="t.showDot" :selected="t.link === $route.fullPath" :badge="t.badge" v-for="t in tabItems"
:link="t.link" :key="t.name">
<template #icon>
<component v-if="t.iconComponent" :is="t.iconComponent" v-bind="[t]"></component>
<i :class="t.iconClass || `iconfont icon-${t.icon}`"></i>
</template>
<template #label>
<component v-if="t.labelComponent" :is="t.labelComponent" v-bind="[t]"></component>
<span :class="$attrs.labelClass" v-else>{{t.label}}</span>
</template>
</tabbar-item>
</tabbar>
</template>
Expand Down
5 changes: 4 additions & 1 deletion src/components/mobile/model/Cells.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<template>
<div>
<group :title="group.title" v-for="group in groups" :key="group.title">
<group v-bind="[$attrs, $props]" :title="group.title" v-for="group in groups" :key="group.title">
<cell :title="c.name" :is-link="true" :link="getLink(c)" v-for="c, i in group.cells"
:key="c.id">
<template slot="icon" v-if="$scopedSlots.icon">
<slot name="icon" :data="c"></slot>
</template>
<template v-if="$scopedSlots.title" v-slot:title="scope">
<slot name="title" :data="c"></slot>
</template>
</cell>
</group>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/components/mobile/model/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<template v-if="$scopedSlots.icon" v-slot:icon="scope">
<slot name="icon" v-bind="scope"></slot>
</template>
<template v-if="$scopedSlots.title" v-slot:title="scope">
<slot name="title" v-bind="scope"></slot>
</template>
</cells>
</slot>
<load-more :tip="tip" :show-loading="loading" v-if="currentPageSize < count"></load-more>
Expand Down
13 changes: 9 additions & 4 deletions src/components/mobile/model/Relations.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<div>
<tab v-model="tab" :animate="false">
<tab-item :active-class="`active-${i%4+1}`" :badge-label="badges[a.name]" v-for="a, i in tabItems" :key="a.name">{{a.label}}</tab-item>
<tab-item :active-class="`active-${i%4+1}`" :badge-label="badges[a.name]" v-for="a, i in tabItems"
:key="a.name">{{a.label}}
</tab-item>
</tab>
<component :is="tabItems[tab].component" :owner="owner" v-bind="[$attrs, tabItems[tab]]"
v-if="loaded"></component>
Expand Down Expand Up @@ -40,9 +42,11 @@
a.component = a.component || `${a.name.replace('.', '/')}/components/List`
if (a.getAsyncInfo) {
a.getAsyncInfo().then(info => {
this.badges[a.name] = info.badge
this.badges={...this.badges}
this.$emit('syncinfo', info)
if (info) {
this.badges[a.name] = info.badge
this.badges = {...this.badges}
this.$emit('syncinfo', info)
}
})
}
return a
Expand Down Expand Up @@ -88,6 +92,7 @@
color: rgb(55, 174, 252) !important;
border-color: rgb(55, 174, 252) !important;
}
.active-4 {
color: darkorange !important;
border-color: darkorange !important;
Expand Down
11 changes: 6 additions & 5 deletions src/components/model/Select.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
<template>
<el-select v-model="selectedValue" :disabled="field.disabled" ref="select" :class="`related-select ${field.name}`"
:multiple="field.multiple" filterable @change="changed" remote clearable reserve-keyword
<el-select v-model="selectedValue" v-bind="[field]" ref="select" :class="`related-select ${field.name}`"
filterable @change="changed" remote clearable reserve-keyword
:remote-method="onFilter" default-first-option
:loading="loading" :loading-text="`${loading}`"
:placeholder="field.placeholder || `请选择${field.label}`">
<el-option :label="c.__str__ || c.name || c.title" :value="c[idField] || c.pk || c.url || c.name"
v-for="c in optionList" :key="c[idField] || c.pk || c.url || c.name">
<span>{{c[selectOptionsFields[0]]}}</span>
<i v-if="showLink && idField === 'id'" class="fa fa-link" title="跳转到详情页" @click="$router.push(modelDetailPath)"></i>
<i v-if="showLink && idField === 'id'" class="fa fa-link" title="跳转到详情页" @click.stop="$router.push(model.getDetailUrl(c.id))"></i>
<span class="label-right" v-if="selectOptionsFields[1]">{{c[selectOptionsFields[1]]}}</span>
</el-option>
<el-alert type="info" v-if="moreThanOnePage" show-icon title="记录太多未展示完全,请输入关键字进行搜索" :closable="false">
</el-alert>

<el-alert v-if="showCreate && canAdd" @click.native="toCreateModel" type="warning" center
style="cursor: pointer"
:closable="false">
style="cursor: pointer" :closable="false">
<i class="fa fa-plus" style="margin-right: 1rem"></i>新增{{field.label}}
</el-alert>
<template #empty>
Expand Down Expand Up @@ -84,6 +83,7 @@
v = [v]
}
if (!v || v.length === 0) {
this.selectedObjects = []
return Promise.resolve()
}
let qs = Object.assign({}, this.field.baseQueries)
Expand Down Expand Up @@ -176,6 +176,7 @@
display: inline-block;
margin-top: 0.5rem;
margin-left: 0.5rem;
margin-right:2rem;
cursor: pointer;
color: gray;
float: right;
Expand Down
25 changes: 17 additions & 8 deletions src/components/model/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
:batchActions="[{name:'add', label:`添加到${parent.title()}`, type:'primary', confirm:false, do:addToParent}]"
v-if="parentMultipleRelationField"></model-table>
<component :is="creator" :appModel="appModel" :defaults="createDefaults" v-else
:parent="parent" :topActions="['saveAndAnother']"></component>
:parent="parent" :topActions="['saveAndAnother']"></component>

</slot>
</el-drawer>
Expand Down Expand Up @@ -320,21 +320,25 @@
}
}
this.addSearchParentQueries(r)
try{
this.addSearchParentQueries(r)
}catch(e){
console.error(e)
}
}
return r
},
addSearchParentQueries(d) {
let model=this.model
let model = this.model
let sf = model.options.actions.SEARCH.filter_fields.find(a => {
if(a.name.includes('__')){
if (a.name.includes('__')) {
let pn = a.name.split('__').pop()
if(this.parent.appModel.endsWith(`.${pn}`)){ // todo: 临时代码,这里有待写得更严谨
if (this.parent.appModel.endsWith(`.${pn}`)) { // todo: 临时代码,这里有待写得更严谨
return true
}
}
})
if(sf) {
if (sf) {
d[sf.name] = this.parent.id
}
},
Expand All @@ -359,8 +363,13 @@
if (mc.actions) {
mc.actions.forEach(a => {
bactions[a.name] = a
a.do = () => {
this.$router.push(`${this.model.getListUrl()}${a.name}/`)
a.do = ({row}) => {
if (a.detail) {
console.log(row, mc.idField || 'id')
this.$router.push(`${this.model.getDetailUrl(row[mc.idField || 'id'])}${a.name}`)
} else {
this.$router.push(`${this.model.getListUrl()}${a.name}`)
}
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/table/widgets/Picture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
return this.proxy || this.field.proxy || ''
},
rootPath () {
return this.$store.state.party.settings.imageRoot || ''
return this.field.imageRoot || this.$store.state.party.settings.imageRoot || ''
},
url () {
let url = this.value[this.field.name]
Expand Down
2 changes: 1 addition & 1 deletion src/components/widgets/ForeignKey.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<a :href="`#/${field.model.replace('.','/')}/${value[field.name]}/`" title="点击跳转" class="foreignkey-link" v-if="hasLink">
<a :href="`#/${field.model.replace('.','/')}/${value[field.keyField || field.name]}/`" title="点击跳转" class="foreignkey-link" v-if="hasLink">
{{theValue}}
</a>
<span v-else>
Expand Down
2 changes: 1 addition & 1 deletion src/utils/clip.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Created by denishuang on 2021/2/1.
*/
export function copyContentH5(content) {
export default function copyContentH5(content) {
var copyDom = document.createElement('div');
copyDom.innerText = content;
copyDom.style.position = 'absolute';
Expand Down
13 changes: 11 additions & 2 deletions src/utils/dailylog.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import axios from 'axios'
import Qs from 'qs'
import {parseTime} from './filters'
let INTERVAL = 5
function DailyLog () {
function DailyLog() {
let a = {
m: {},
saveTime: undefined,
Expand Down Expand Up @@ -41,7 +41,7 @@ export default DailyLog()
// }
// })

export function Performance (app, model, ownerId, target, interval) {
export function Performance(app, model, ownerId, target, interval) {
let qd = {app, model, owner_id: ownerId}
return {
data: {
Expand Down Expand Up @@ -85,3 +85,12 @@ export function Performance (app, model, ownerId, target, interval) {
}
}
}

export function userOnlineTimeCounter(callBack) {
let seconds = 30
function action () {
axios.post(`/dailylog/user/count/`, {metics: 'online_time', delta: seconds}).then(callBack)
}
action()
setInterval(action, seconds * 1000)
}
4 changes: 2 additions & 2 deletions src/views/model/edit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<template v-slot:bottom="{model}">
<template v-if="model.viewsConfig">
<el-collapse v-model="activePanels" v-if="model.viewsConfig.pannels">
<el-collapse-item :title="p.label" :name="i" v-for="p in model.viewsConfig.pannels"
<el-collapse-item :title="p.label" :name="i" v-for="p,i in model.viewsConfig.pannels"
:key="p.name">
<component :is="p.component" :parent="model"></component>
<component :is="p.component" v-bind="[p]" :parent="model"></component>
</el-collapse-item>
</el-collapse>

Expand Down

0 comments on commit 18cd4ae

Please sign in to comment.