Skip to content

Commit

Permalink
importer
Browse files Browse the repository at this point in the history
  • Loading branch information
szuprefix committed Jul 20, 2019
1 parent 5fee752 commit 40aa9ee
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 78 deletions.
131 changes: 131 additions & 0 deletions src/components/creator/BatchCreator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<template>
<div>
<template v-for="f in foreignKeys">
<batch-creator :structure="f" :value="getForeignKeyData(f)"
:appModelName="f.name" @optionLoaded="onForeignKeyLoaded"></batch-creator>

</template>

<h4>{{structure.label}}</h4>
<data-table :value="value" :fields="structure.tableItems" v-if="structure.tableItems && value && value.length>0" :topActions="[]" :options="{elTable:{maxHeight:400}}"></data-table>
</div>
</template>
<script>
import DataTable from '../table/DataTable.vue'
import {pick, last, uniqWith, isEqual} from 'lodash'
import ModelView from '../../mixins/model_view'
export default{
name: 'BatchCreator',
mixins: [ModelView],
props: {
structure: Object,
value: Array
},
data () {
return {
activeList: [],
loaded: false
}
},
components: {DataTable},
created(){
this.modelInit()
this.modelLoadOptions().then(() => {
this.structure.label = this.modelConfig.verbose_name
if (!this.structure.rel) {
this.structure.rel = last(this.structure.name.split('.'))
}
this.loaded = true
this.checkStatus()
})
// console.log(this.plainFieldData)
},
methods: {
onForeignKeyLoaded(context){
let st = context.structure
Object.assign(this.structure.foreignKeys.find(fk => fk.name === st.name ), st)
this.activeList.push(st)
this.checkStatus()
},
checkStatus() {
if(this.activeList.length=== this.foreignKeys.length && this.loaded){
this.structure = Object.assign({}, this.structure, {
tableItems:this.tableItems,
count: this.activeList.map(a => a.count).reduce((a,b) => a+b, this.plainFields.length)
})
// console.log(this.structure)
this.$emit('optionLoaded', {structure: this.structure})
}
// console.log([this.activeList.length, this.foreignKeys.length, this.loaded])
},
normalizeStructure(){
let r = Object.assign({}, this.structure)
r.insertMode = r.insertMode || 'ignore'
if (s.foreignKeys) {
s.foreignKeys.forEach(fk => {
let st = this.getStructure(fk)
r.count += st.count
r.foreignKeys.push(st)
})
}
r.count += s.plainFields.length
if (!r.rel) {
r.rel = last(s.name.split('.'))
}
return r
},
getForeignKeyData(f){
// console.log(f)
if(!f.tableItems){
return []
}
let fns = []
let pairs = []
f.tableItems.forEach(ti => {
let ofn = `${f.rel}.${ti.name}`
fns.push(ofn)
pairs.push([ofn, ti.name])
})
let data = this.value.map(a =>pick(a, fns))
data.forEach(d => {
pairs.forEach(p => {
d[p[1]] = d[p[0]]
delete d[p[0]]
})
})
console.log([pairs, fns, f])
return uniqWith(data, isEqual)
}
},
computed: {
plainFields(){
return this.structure.plainFields || []
},
foreignKeys() {
return this.structure.foreignKeys || []
},
tableItems(){
let r = []
let fcs = this.modelFieldConfigs
let pfs = this.plainFields && this.plainFields.map(pf => fcs[pf])
let fks = this.foreignKeys && this.foreignKeys.map(fk => fcs[fk])
this.activeList.forEach(fk => {
fk.tableItems.forEach(ti => {
let label = fk.count>1 ?`${fk.label}.${ti.label}`:`${fk.label}`
let synonyms = fk.count>1 ? []: fk.synonyms
let nti = Object.assign({}, ti, {name:`${fk.rel}.${ti.name}`, label, synonyms})
// console.log(nti)
r.push(nti)
})
})
r=r.concat(pfs)
return r
},
plainFieldData(){
return this.value.map(a => pick(a, this.plainFields))
}
}
}
</script>
<style scoped></style>
22 changes: 18 additions & 4 deletions src/components/layout/Actions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<div>
<el-button-group v-if="showActions.length>0">
<template v-for="a in showActions">
<el-button :type="a.type" :title="a.title" size="small" @click="handleCommand(a.do)" v-if="!a.show || a.show()" :key="a.name">
<el-button :type="a.type" :title="a.title" size="small" @click="handleCommand(a.do)"
v-if="!a.show || a.show()" :key="a.name">
<i :class="`fa fa-${a.icon}`"></i>{{a.label}}
</el-button>
</template>
Expand All @@ -27,7 +28,12 @@
props: {
items: Array,
context: Object,
trigger: {type: String, default: "hover"}
trigger: {type: String, default: "hover"},
map: {
type: Object, default: () => {
return {}
}
}
},
data () {
return {}
Expand All @@ -39,13 +45,21 @@
}
},
computed: {
_items (){
return this.items.map(a => {
if(typeof a === 'string'){
a = this.map[a]
}
return a
})
},
showActions () {
return this.items.filter((a) => {
return this._items.filter((a) => {
return !(a instanceof Array)
})
},
dropdownActions () {
return this.items.filter((a) => {
return this._items.filter((a) => {
return (a instanceof Array)
}).reduce((a, b) => a.concat(b), []).filter((a) => {
return !a.show || a.show()
Expand Down
24 changes: 7 additions & 17 deletions src/components/sheets/Block.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,10 @@
ActionLabel,
EditableLabel,
actions: [
{name: 'drop', label: '删除整列', postAction: this.dropColumn, do: this.toDoSelectionAction},
{name: 'merge', label: '合并字段', postAction: this.mergeColumn, do: this.toDoSelectionAction},
{
name: 'splitline2column',
label: '分拆内容为新列',
postAction: this.splitLine2Column,
do: this.toDoSelectionAction
},
{
name: 'splitline2row',
label: '分拆内容为新行',
postAction: this.splitLine2Row,
do: this.toDoSelectionAction
},
{name: 'drop', label: '删除整列', do: this.toDoSelectionAction},
{name: 'merge', label: '合并字段', do: this.toDoSelectionAction},
{name: 'splitLine2Column', label: '分拆内容为新列', do: this.toDoSelectionAction},
{name: 'splitLine2Row', label: '分拆内容为新行', do: this.toDoSelectionAction},
]
}
},
Expand All @@ -53,9 +43,9 @@
return fields
},
headerChange ({context, newValue, oldValue}){
ColumnUtil.rename(this.value, [oldValue, newValue])
ColumnUtil.rename(this.value, [[oldValue, newValue.trim()]])
},
mergeColumn(){
merge(){
let fl = this.selection.list
if (fl.length < 2) {
this.$message({type: 'info', message: '请选择至少两个字段'})
Expand All @@ -66,7 +56,7 @@
ColumnUtil.merge(this.value, fl)
this.loading = false
},
dropColumn(){
drop(){
this.selection.show = false
ColumnUtil.drop(this.value, this.selection.list)
},
Expand Down
8 changes: 4 additions & 4 deletions src/components/sheets/Book.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
return {
curSheet: this.value.sheets[0].name,
actions: [
{name: 'drop', label: '删除数据表', postAction: this.dropSheet, do: this.toDoSelectionAction},
{name: 'merge', label: '合并数据表', postAction: this.mergeSheet, do: this.toDoSelectionAction}
{name: 'drop', label: '删除数据表', do: this.toDoSelectionAction},
{name: 'merge', label: '合并数据表', do: this.toDoSelectionAction}
],
}
},
components: { ActionLabel, Sheet},
methods: {
dropSheet(){
drop(){
if (this.selection.list.length === this.value.sheets.length) {
this.$message({message: '请至少留下一张数据表吧?'})
return
Expand All @@ -43,7 +43,7 @@
SheetUtil.drop(this.value, this.selection.list)
this.curSheet = this.value.sheets[0].name
},
mergeSheet() {
merge() {
this.selection.show = false
SheetUtil.merge(this.value, this.selection.list)
}
Expand Down
124 changes: 124 additions & 0 deletions src/components/sheets/Importer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<template>

<div v-loading="loading" :element-loading-text="loading">
<el-steps :active="step" finish-status="success">
<el-step title="上传Excel"></el-step>
<el-step title="整理数据"></el-step>
<el-step title="绑定字段"></el-step>
<!--<el-step title="创建关联数据"></el-step>-->
</el-steps>

<el-upload :action="actionUrl" v-if="step===0"
:show-file-list="false" :with-credentials="true" :auto-upload="false"
:on-change="submitUpload">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传excel文件,且不超过5MB</div>
</el-upload>
<template v-if="this.excelData && step===1">
<el-button @click="step --">上一步</el-button>
<el-button @click="genFieldMap(); step ++; ">下一步</el-button>
<book v-model="this.excelData"></book>
</template>
<div v-if="step===2">
<el-button @click="step --">上一步</el-button>
<el-button @click="change(); step ++; ">确认</el-button>
<column-bind v-model="fieldMap" :choices="bindChoices"></column-bind>
</div>
<!--<div v-if="step===3">-->
<!--<el-button @click="step &#45;&#45;">上一步</el-button>-->
<!--<el-button @click="change">确认</el-button>-->
<!--&lt;!&ndash;<data-table v-model="importData" :fields="fields" group></data-table>&ndash;&gt;-->
<!--</div>-->
</div>
</template>
<script>
import ColumnBind from '../table/ColumnBind.vue'
import DataTable from '../table/DataTable.vue'
import Book from './Book.vue'
import EditableLabel from '../widgets/EditableLabel.vue'
import {SheetUtil, ColumnUtil} from '../../utils/sheets'
import {uniqWith, isEqual, pick, zip} from 'lodash'
export default{
props: {
value: Object,
binding: Object
},
data () {
return {
fieldMap: {},
step: 0,
excelData: null,
importData: null
}
},
components: {Book, EditableLabel, ColumnBind, DataTable},
created () {
},
methods: {
genFieldMap(){
let d = {}
this.binding.forEach(f => {
let cs = [f.name, f.label].concat(f.synonyms)
d[f.label] = this.fieldNames.find(n => cs.includes(n))
})
this.fieldMap = Object.assign(d)
},
genData() {
let data = uniqWith(this.block.data, isEqual)
this.importData = data
this.change()
// this.$emit('data', {data})
},
onUploadSuccess(res, file) {
this.excelData = file.response
},
submitUpload (file, fileList){
this.loading = '上传中'
let formData = new FormData()
formData.append('file', file.raw)
formData.append('orient', 'blocks')
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
this.$http.post('/common/excel/read/', formData, config).then(({data}) => {
this.loading = false
SheetUtil.normalize(data)
this.excelData = data
this.step++
}).catch(this.onServerResponseError)
},
change(){
let pairs = []
let d = this.fieldMap
this.binding.forEach(f => {
pairs.push([d[f.label], f.name])
})
// console.log([pairs, this.importData])
ColumnUtil.rename(this.block, pairs)
this.$emit('input', this.block)
}
},
computed: {
block () {
return this.excelData.sheets[0].blocks[0]
},
fields(){
return this.block.fields
},
fieldNames() {
return this.fields.map(f => f.name)
},
bindChoices() {
return this.fields.map(f => {
return {value: f.name, display_name: f.label}
})
}
}
}
</script>
<style scoped></style>

0 comments on commit 40aa9ee

Please sign in to comment.