Skip to content

Commit

Permalink
restruct widget props
Browse files Browse the repository at this point in the history
  • Loading branch information
szuprefix committed Jul 5, 2019
1 parent 2ae300b commit eba846f
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 128 deletions.
51 changes: 0 additions & 51 deletions src/components/layout/DataTable.vue

This file was deleted.

43 changes: 43 additions & 0 deletions src/components/layout/table/ActionLabel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<el-dropdown @command="handleCommand">
<editable-label v-model="value"></editable-label>
<el-dropdown-menu slot="dropdown">
<template v-for="a in actions">
<el-dropdown-item :command="a.do" v-if="!a.show || a.show()" :key="a.name" :title="a.title"
:icon="`fa fa-${a.icon}`">
{{a.label}}
</el-dropdown-item>
</template>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
import EditableLabel from '../../widgets/EditableLabel.vue'
export default{
props: {
value: String,
context: Object,
actions: Array
},
data () {
return {}
},
components: {EditableLabel},
methods: {
handleCommand (command) {
command(this.context)
},
setValue(v){
this.$emit('change', v)
}
},
computed: {},
watch: {
value (newValue, oldValue){
this.$emit('input', newValue)
this.$emit('changed', {context: this.context, newValue, oldValue})
}
}
}
</script>
<style></style>
101 changes: 101 additions & 0 deletions src/components/layout/table/DataBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<template>
<div v-loading="loading" :element-loading-text="loading">
<data-table v-model="value.data" :fields="setHeaderActions(value.fields)" :headerWidget="ActionLabel"
:cellWidget="EditableLabel" :options="{elTable:{border:true,minHeight:400,stripe:true}}">

</data-table>
<el-dialog title="合并字段" :visible.sync="showMerge">
<el-checkbox-group v-model="fieldList">
<el-checkbox :label="f.label || f.name" v-for="f in value.fields" :key="f.name"></el-checkbox>
</el-checkbox-group>

<div slot="footer" class="dialog-footer">
<el-button @click="showMerge = false">取 消</el-button>
<el-button type="primary" @click="mergeColumn">合并</el-button>
</div>
</el-dialog>
</div>

</template>
<script>
import DataTable from './DataTable.vue'
import ActionLabel from './ActionLabel.vue'
import EditableLabel from '../../widgets/EditableLabel.vue'
import {set, unset, uniqueId, pick} from 'lodash'
export default{
props: {
value: Object
},
data () {
return {
loading: false,
ActionLabel,
EditableLabel,
actions: [
{name: 'delete', label: '删除整列', do: this.deleteColumn},
{name: 'merge', label: '合并字段', do: () => this.showMerge = true },
{name: 'delete', label: '按分隔符拆分内容'},
],
showMerge: false,
fieldList : []
}
},
components: {DataTable},
methods: {
setHeaderActions (fields){
fields.forEach(f => {
f.label = f.label || f.name
f.actions = this.actions
f.headerChange = this.headerChange
})
return fields
},
headerChange ({context, newValue, oldValue}){
let ds = this.value.data
ds.forEach(d => {
d[newValue] = d[oldValue]
delete d[oldValue]
})
let f = this.value.fields.find(f => f.name === oldValue)
f.name = f.label = newValue
},
mergeColumn(context){
let fl = this.fieldList
if(fl.length<2){
this.$message({type:'info', message:'请选择至少两个字段'})
return
}
this.showMerge = false
this.loading = '合并中...'
let fs = this.value.fields
let bf = fs.find(a => a.name === fl[0])
let mfs = fs.filter(a => fl.slice(1).includes(a.name))
let ds = this.value.data
let ds2 = []
let nfn = `mergeField${uniqueId()}`
let nf = Object.assign({}, bf, {name:nfn, label:nfn})
let cfs = fs.filter(f => !fl.includes(f.name))
let cfns = cfs.map(f => f.name)
ds.forEach(d => {
d[nfn] = bf.label
let bvs = pick(d, cfns)
mfs.forEach(f => {
let nd = Object.assign({}, bvs)
nd[nfn] = f.label
nd[bf.name] = d[f.name]
ds2.push(nd)
})
})
this.value.data = ds.concat(ds2)
this.value.fields = cfs.concat([bf, nf])
this.loading = false
},
deleteColumn(context){
this.value.fields = this.value.fields.filter(a => a.name !== context.name)
}
},
computed: {}
}
</script>
<style></style>
36 changes: 11 additions & 25 deletions src/components/layout/table/DataSheets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,33 @@
<el-tabs tab-position="bottom" max-height="32rem">
<el-tab-pane lazy v-for="s,i in value.sheets" :key="i">
<template slot="label">

<el-dropdown>
<span class="el-dropdown-link">
<editable-label v-model="s.name"></editable-label>
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<template v-for="a in sheetActions">
<el-dropdown-item :command="a.do" v-if="!a.show || a.show()" :key="a.name" :title="a.title"
:icon="`fa fa-${a.icon}`">
{{a.label}}
</el-dropdown-item>
</template>
</el-dropdown-menu>
</el-dropdown>
<action-label v-model="s.name" :actions="actions"></action-label>
</template>
<div class="data-sheet-block" v-for="b,j in s.blocks" :key="j">
<data-table v-model="b.data" :fields="b.fields" :defaultWidget=""></data-table>
<data-block v-model="s.blocks[j]"></data-block>
</div>
</el-tab-pane>
</el-tabs>
</template>
<script>
import DataTable from './DataTable.vue'
import Actions from '../Actions.vue'
import EditableLabel from '../../widgets/EditableLabel.vue'
import ActionLabel from './ActionLabel.vue'
import DataBlock from './DataBlock.vue'
export default{
props: {
value: Array
},
data () {
return {
sheetActions: [
ActionLabel,
actions: [
{name: 'delete', label: '删除'},
{name: 'delete', label: '合并数据块'},
{name: 'delete', label: '拆分行'},
]
{name: 'delete', label: '合并数据表'}
],
}
},
components: {DataTable, Actions, EditableLabel},
methods: {},
components: { DataBlock,ActionLabel},
methods: {
},
computed: {}
}
</script>
Expand Down
42 changes: 28 additions & 14 deletions src/components/layout/table/DataTable.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
<template>
<el-popover placement="right-start" trigger="hover">
<actions :items="actions"></actions>
<el-table slot="reference" :data="_value" ref="table" :span-method="spanMethod" v-loading="loading"
:element-loading-text="loading" :cell-class-name="options.cellClassName" :max-height="options.maxHeight">
<template slot="left"></template>
<data-table-column :field="f" v-for="f in _fields" :key="f.name"></data-table-column>
<template slot="right"></template>
</el-table>
</el-popover>
<el-table slot="reference" :data="_value" ref="table" :span-method="spanMethod" v-loading="loading"
:element-loading-text="loading" :cell-class-name="elOptions.cellClassName"
:height="elOptions.height" :max-height="elOptions.maxHeight" :stripe="elOptions.stripe"
:border="elOptions.border">
<template slot="left"></template>
<data-table-column :field="f" v-for="f in _fields" :key="f.name"></data-table-column>
<el-table-column label="" align="right" v-if="rowActions || topActions">
<template slot="header" slot-scope="scope" v-if="topActions">
<actions :items="topActions" :context="scope"></actions>
</template>
<template slot-scope="scope" v-if="rowActions">
<actions :items="rowActions" :context="scope" class="hover-show" trigger="hover"></actions>
</template>
</el-table-column>

<slot name="right">
</slot>
</el-table>
</template>
<script>
import {percent, toThousandslsFilter} from '../../../utils/filters'
Expand All @@ -32,7 +41,8 @@
export default{
props: {
value: Array,
defaultWidget: [Function, Object],
cellWidget: [Function, Object],
headerWidget: [Function, Object],
group: false,
options: {
type: Object, default: () => {
Expand All @@ -48,14 +58,14 @@
data () {
return {
loading: false,
actions:[{
topActions: [{
icon: 'download',
label: '导出',
title: '导出',
do: this.dumpExcelData
}]
}
},
components: {DataTableColumn,Actions},
components: {DataTableColumn, Actions},
methods: {
getGridData(data){
let ds = data.map((d) => {
Expand Down Expand Up @@ -101,7 +111,8 @@
}
f.type = f.type || 'string'
f.align = f.align || ['decimal', 'number', 'percent', 'integer'].includes(f.type) && 'right' || 'left'
f.widget = f.widget || this.defaultWidget
f.widget = f.widget || this.cellWidget
f.headerWidget = f.headerWidget || this.headerWidget
f.formatter = f.formatter || this.genDefaultFormater(f)
if (f.subColumns) {
f.subColumns = f.subColumns.map(i => this.normalizeField(i))
Expand Down Expand Up @@ -155,6 +166,9 @@
return sortBy(this.value, this.fieldNames)
}
return this.value
},
elOptions () {
return this.options.elTable || {}
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/components/layout/table/DataTableColumn.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@
:min-width="f.min_width" :width="f.width" :formater="f.formater"
:align="f.align" :class-name="f.type" :type="f.type" :key="f.name"
v-else>

<template slot="header" slot-scope="scope">
<component :is="f.headerWidget" v-model="f.name" :field="f" :actions="f.actions" :context="f" @changed="f.headerChange"
v-if="f.headerWidget && typeof f.headerWidget == 'object'"></component>
<span v-else-if="f.headerWidget && typeof f.headerWidget == 'function'"
v-html="f.headerWidget(row)"></span>
<template v-else>{{f.label || f.name}}</template>
</template>
<template slot-scope="{row}">
<component :is="f.widget" v-model="row" :prop="f.name" :field="f"
<component :is="f.widget" v-model="row[f.name]" :context="row" :field="f"
v-if="f.widget && typeof f.widget == 'object'"></component>
<span v-else-if="f.widget && typeof f.widget == 'function'" v-html="f.widget(row)"></span>
<template v-else>{{row[f.name]}}</template>
Expand Down
4 changes: 2 additions & 2 deletions src/components/rest/ModelTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
:filter-method="f.name in modelTableFilters?filterHandler:undefined"
:key="f.columnKey || f.name">
<template slot-scope="{row}">
<form-widget v-if="f.useFormWidget" v-model="row" :field="f"
<form-widget v-if="f.useFormWidget" v-model="row" :field="f" :context="row"
@change="onCellValueChange"></form-widget>
<component :is="f.widget" v-model="row" :prop="f.name" :field="f.field"
<component :is="f.widget" v-model="row[f.name]" :field="f.field" :context="row"
v-else-if="f.widget && typeof f.widget == 'object'"></component>
<span v-else-if="f.widget && typeof f.widget == 'function'" v-html="f.widget(row)"></span>
<template v-else>{{row[f.name]}}</template>
Expand Down
4 changes: 2 additions & 2 deletions src/components/widgets/ChoicesDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
<script>
export default{
props: {
value: Object,
value: [String, Number],
field: Object
},
computed:{
display(){
let a = this.field.choices.find(a => a.value == this.value[this.field.name])
let a = this.field.choices.find(a => a.value == this.value)
return a && a.display_name
}
}
Expand Down

0 comments on commit eba846f

Please sign in to comment.