7 changed files with 771 additions and 64 deletions
@ -0,0 +1,78 @@ |
|||
<template> |
|||
<div> |
|||
<el-checkbox |
|||
:indeterminate="isIndeterminate" |
|||
v-model="checkAll" |
|||
@change="handleCheckAllChange">全选</el-checkbox> |
|||
<div style="margin: 15px 0;"></div> |
|||
<el-checkbox-group v-model="checkedList" @change="handleChange"> |
|||
<div v-for="n in boxList" :key="n.itemId" class="mb10"> |
|||
<el-checkbox :label="n.itemId">{{n.label}}</el-checkbox> |
|||
</div> |
|||
</el-checkbox-group> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'checkBox', |
|||
model: { |
|||
prop: 'value', |
|||
event: 'change' |
|||
}, |
|||
props: { |
|||
value: { |
|||
type: Array, |
|||
default: () => [] |
|||
}, |
|||
list: { |
|||
type: Array, |
|||
default: () => [] |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
boxList: [], |
|||
checkAll: false, |
|||
checkedList: [], |
|||
isIndeterminate: false, |
|||
pid: '', |
|||
} |
|||
}, |
|||
created() { |
|||
this.boxList = this.list.filter(item => item.itemType != 'inputRange') |
|||
console.log('cehck-bo----', this.list) |
|||
this.pid = this.list[0].itemGroupId |
|||
}, |
|||
methods: { |
|||
handleCheckAllChange(val) { |
|||
|
|||
this.checkedList = val ? this.boxList.map(item => item.itemId) : []; |
|||
this.isIndeterminate = false; |
|||
|
|||
this.$emit('change', { list: this.filterArr(this.checkedList), pid: this.pid }) |
|||
}, |
|||
handleChange(value) { |
|||
let checkedCount = value.length; |
|||
this.checkAll = checkedCount === this.list.length; |
|||
this.isIndeterminate = checkedCount > 0 && checkedCount < this.boxList.length; |
|||
this.$emit('change', { list: this.filterArr(this.checkedList), pid: this.pid }) |
|||
}, |
|||
filterArr(arr) { |
|||
let list = [] |
|||
arr.forEach(item => { |
|||
this.boxList.forEach(n => { |
|||
if (item === n.itemId) list.push(n) |
|||
}) |
|||
}) |
|||
return list |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.mb10 { |
|||
margin-bottom: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,94 @@ |
|||
<template> |
|||
<div class="right-wr scroll-h" :id="'wrItems' + id"> |
|||
<div v-for="(n, i) in list" :key="n.itemId" class="right-item"> |
|||
<div class="item-label">{{ n.label }}</div> |
|||
<div class="item-btn"> |
|||
<el-tag type="danger" class="mr10" @click="handleDelItem(n, i)"> |
|||
<i class="el-icon-delete"></i> |
|||
</el-tag> |
|||
<el-tag type="primary"> |
|||
<i class="el-icon-rank"></i> |
|||
</el-tag> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Sortable from 'sortablejs' |
|||
export default { |
|||
name: 'DragItems', |
|||
props: { |
|||
list: { |
|||
type: Array, |
|||
default: () => [] |
|||
}, |
|||
id: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
dragList: [] |
|||
} |
|||
}, |
|||
mounted() { |
|||
|
|||
// this.dragSort() |
|||
}, |
|||
watch: { |
|||
list: { |
|||
handler(val) { |
|||
this.dragList = val.filter(item => item.itemType != 'inputRange') |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
handleDelItem(item, i) { |
|||
this.$emit('del', { item, index: i}) |
|||
}, |
|||
dragSort () { |
|||
const el = document.getElementById(`wrItems${this.id}`) |
|||
this.sortTable = Sortable.create(el, { |
|||
group: 'right-item', |
|||
ghostClass: 'sortable-ghost', // Class name for the drop placeholder, |
|||
chosenClass: 'sortable-choose', |
|||
animation: 500, |
|||
delay: 0, |
|||
onEnd: evt => { |
|||
console.log('evt----', evt) |
|||
const targetRow = this.list.splice(evt.oldIndex, 1)[0] |
|||
this.list.splice(evt.newIndex, 0, targetRow) |
|||
this.$emit('drag', this.list) |
|||
} |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.right-wr { |
|||
max-height: calc(80vh - 270px); |
|||
overflow: auto; |
|||
.right-item { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
cursor: pointer; |
|||
padding: 10px 30px; |
|||
|
|||
} |
|||
} |
|||
.sortable-choose { |
|||
background: #eee; |
|||
} |
|||
.mr10 { |
|||
margin-right: 10px; |
|||
} |
|||
.mb10 { |
|||
margin-bottom: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,463 @@ |
|||
<template> |
|||
<div v-if="list.length > 0" class="diy-container"> |
|||
<el-tabs v-model="activeName"> |
|||
<el-tab-pane label="自定义模板" name="first"> |
|||
<div class="diy-wr"> |
|||
<div class="left"> |
|||
<el-tabs tab-position="left" class="left-h"> |
|||
<el-tab-pane v-for="item in list" :key="item.id" :label="item.label"> |
|||
<div class="pd10 dialog-h-content scroll-h"> |
|||
<checkBox v-if="item.queryItemList" :ref="'checkbox' + item.id" |
|||
:list="item.queryItemList" @change="handleChangeBox" /> |
|||
</div> |
|||
</el-tab-pane> |
|||
|
|||
</el-tabs> |
|||
</div> |
|||
<div class="right"> |
|||
<div class="right-header"> |
|||
<div class="title">导出信息</div> |
|||
<el-button plain @click="handlePreview('')">预览</el-button> |
|||
</div> |
|||
<div> |
|||
<el-collapse v-model="activeCollapse" id="collapsWr"> |
|||
<el-collapse-item v-for="item in rightList" :key="item.id" |
|||
:title="item.label" :name="item.id" class="col-h"> |
|||
<dragItem :ref="'drag' + item.id" :list="item.queryItemList" :id="item.id" |
|||
@del="handleDelItem" |
|||
@drag="handleDrag($event, item)"></dragItem> |
|||
</el-collapse-item> |
|||
</el-collapse> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-tab-pane> |
|||
<el-tab-pane label="模板列表" name="second"> |
|||
<el-table |
|||
:data="tableData" |
|||
height="calc(80vh - 140px)" |
|||
style="width: 100%"> |
|||
<el-table-column |
|||
type="index" |
|||
label="序号" |
|||
align="center" |
|||
width="50"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="name" |
|||
label="模板名称" |
|||
align="center" |
|||
min-width="180"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="createdBy" |
|||
align="center" |
|||
label="创建者" |
|||
width="180"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
align="center" |
|||
prop="createdTime" |
|||
label="创建时间" |
|||
width="180"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
align="center" |
|||
label="操作" |
|||
width="160"> |
|||
<template slot-scope="scope"> |
|||
<el-button v-if="scope.row.isSelf" type="text" size="small" class="div-table-button--delete" |
|||
@click="handleDeltemplate(scope.row.id)">删除</el-button> |
|||
<el-button type="text" size="small" class="div-table-button--detail" |
|||
@click="handlePreview(scope.row.id)">预览</el-button> |
|||
<el-button |
|||
type="text" |
|||
size="small" |
|||
class="div-table-button--edit" @click="handleExportTemplate(scope.row.id)">导出</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</el-tab-pane> |
|||
</el-tabs> |
|||
<div v-if="activeName == 'first'" class="diy-footer"> |
|||
<div class="left"> |
|||
<div class="flex-div"> |
|||
<div>模板名称:</div> |
|||
<el-input v-model="form.name" class="wd200 mr10" /> |
|||
<el-checkbox v-model="form.isSaveTemp">保存为常用模板</el-checkbox> |
|||
</div> |
|||
</div> |
|||
<el-button class="diy-button--delete" :loading="exportLoading" @click="handleExport">导出</el-button> |
|||
</div> |
|||
<el-dialog :visible.sync="diyDialog" |
|||
:close-on-click-modal="false" |
|||
:close-on-press-escape="false" |
|||
width="1150px" |
|||
append-to-body |
|||
top="5vh" |
|||
class="dialog-h" |
|||
@close="handleClose" |
|||
> |
|||
<div style="padding: 20px;"> |
|||
<el-table |
|||
:data="tableData" |
|||
height="calc(80vh - 140px)" |
|||
style="width: 100%"> |
|||
<el-table-column |
|||
v-for="(item, index) in previewList" |
|||
:label="item.label" |
|||
:key="index" |
|||
align="center" |
|||
min-width="120"> |
|||
<el-table-column |
|||
v-for="(n, i) in item.children" |
|||
:label="n.label" |
|||
:key="i" |
|||
align="center" |
|||
min-width="120"> |
|||
|
|||
</el-table-column> |
|||
</el-table-column> |
|||
|
|||
</el-table> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import checkBox from '../../components/checkBox.vue' |
|||
import dragItem from '../../components/dragItem.vue' |
|||
import Sortable from 'sortablejs' |
|||
export default { |
|||
props: { |
|||
list: { |
|||
type: Array, |
|||
default: () => [] |
|||
}, |
|||
search: { |
|||
type: Object, |
|||
default: () => {} |
|||
} |
|||
}, |
|||
components: { |
|||
checkBox, |
|||
dragItem |
|||
}, |
|||
data() { |
|||
return { |
|||
exportLoading: false, |
|||
activeCollapse: ['1'], |
|||
activeName: 'first', |
|||
info: {}, |
|||
rightList: [], |
|||
form: { |
|||
isSaveTemp: false, |
|||
name: '', |
|||
itemList: [] |
|||
}, |
|||
tableData: [], |
|||
previewList: [], |
|||
diyDialog: false, |
|||
} |
|||
}, |
|||
created() { |
|||
this.list.forEach(item => { |
|||
this.$set(this.info, item.id, []) |
|||
}) |
|||
console.log('infodiy----', this.list) |
|||
this.getTemplateList() |
|||
}, |
|||
watch: { |
|||
rightList: { |
|||
handler(val) { |
|||
if (val.length > 0) this.dragSort() |
|||
|
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
handleChangeBox({list, pid}) { |
|||
console.log('ccccc----', list) |
|||
// if (list.length == 0) return |
|||
let obj = {} |
|||
this.list.forEach(item =>{ |
|||
if (item.id == pid) obj = { ...item, queryItemList: [...list] } |
|||
}) |
|||
const groups = this.rightList.map(item => item.id) |
|||
if (groups.includes(pid)) { |
|||
this.rightList.forEach((item, i) => { |
|||
if (item.id == pid ) { |
|||
item.queryItemList = [...list] |
|||
if (list.length == 0) this.rightList.splice(i, 1) |
|||
} |
|||
}) |
|||
} else { |
|||
this.rightList.push(obj) |
|||
|
|||
this.$nextTick(() => { |
|||
console.log('itemttt------', this.$refs[`drag${pid}`]) |
|||
this.$refs[`drag${pid}`][0].dragSort() |
|||
}) |
|||
} |
|||
this.activeCollapse = [...this.activeCollapse, pid] |
|||
}, |
|||
handleDelItem(val) { |
|||
const { item, index } = val |
|||
console.log('item------', item, this.$refs[`checkbox${item.itemGroupId}`]) |
|||
const checkList = this.$refs[`checkbox${item.itemGroupId}`][0].checkedList |
|||
checkList.forEach((n, i) => { |
|||
if (n == item.itemId) this.$refs[`checkbox${item.itemGroupId}`][0].checkedList.splice(i, 1) |
|||
}) |
|||
this.rightList.forEach((n, i) => { |
|||
if (n.id === item.itemGroupId) { |
|||
n.queryItemList.splice(index, 1) |
|||
if (n.queryItemList.length === 0) this.rightList.splice(i, 1) |
|||
} |
|||
}) |
|||
|
|||
}, |
|||
dragSort() { |
|||
const el = document.getElementById('collapsWr') |
|||
this.sortTable = Sortable.create(el, { |
|||
group: 'el-collapse-item', |
|||
ghostClass: 'sortable-ghost', // Class name for the drop placeholder, |
|||
animation: 500, |
|||
delay: 0, |
|||
onEnd: evt => { |
|||
console.log('evt----', evt) |
|||
const targetRow = this.rightList.splice(evt.oldIndex, 1)[0] |
|||
this.rightList.splice(evt.newIndex, 0, targetRow) |
|||
} |
|||
}) |
|||
}, |
|||
handleDrag(val, item) { |
|||
console.log('drag-----', val) |
|||
console.log('drag-----', item) |
|||
this.rightList.forEach((n, i) => { |
|||
if (item.id == n.id) n.queryItemList = [...val] |
|||
}) |
|||
}, |
|||
handleClose() { |
|||
this.previewList = [] |
|||
this.diyDialog = false |
|||
}, |
|||
handleDeltemplate(id) { |
|||
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.delTemplate(id) |
|||
}).catch(() => { |
|||
this.$message({ |
|||
type: 'info', |
|||
message: '已取消删除' |
|||
}); |
|||
}) |
|||
}, |
|||
handlePreview(id) { |
|||
if (id) this.getPreview(id) |
|||
else { |
|||
if (this.rightList.length == 0) return this.$message.error('请选择导出信息') |
|||
this.previewList = this.rightList.map(item => { |
|||
return { |
|||
label: item.label, |
|||
children: item.queryItemList |
|||
} |
|||
}) |
|||
} |
|||
this.diyDialog = true |
|||
}, |
|||
handleExport() { |
|||
if (this.rightList.length === 0) return this.$message.error('请选择导出信息') |
|||
if (this.form.isSaveTemp && !this.form.name) return this.$message.error('请输入模板名称') |
|||
this.exportLoading = true |
|||
this.exportTemplate() |
|||
|
|||
}, |
|||
handleExportTemplate(id) { |
|||
this.exportTemplate(id) |
|||
}, |
|||
async exportTemplate(id) { |
|||
let url = "/epmetuser/icresiuser/exportExcelCustom" |
|||
|
|||
let params = { |
|||
templateId: id || '', |
|||
searchForm: {...this.search}, |
|||
exportConfig: { |
|||
...this.form, |
|||
formCode: 'resi_base_info', |
|||
itemList: this.rightList.map(item => { |
|||
return { |
|||
itemId: item.id, |
|||
label: item.label, |
|||
tableName: item.queryItemList[0].tableName, |
|||
children: item.queryItemList, |
|||
supportAdd: item.supportAdd |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
await this.$http({ |
|||
method: 'POST', |
|||
url, |
|||
responseType: 'blob', |
|||
data: params |
|||
}) |
|||
.then(res => { |
|||
console.log('res----dddd', res) |
|||
// this.download(res.data, title + '.xls') |
|||
this.getTemplateList() |
|||
if (res.headers["content-disposition"]) { |
|||
let fileName = window.decodeURI(res.headers["content-disposition"].split(";")[1].split("=")[1]) |
|||
console.log('filename', fileName) |
|||
let blob = new Blob([res.data], { type: 'application/vnd.ms-excel' }) |
|||
var url = window.URL.createObjectURL(blob) |
|||
var aLink = document.createElement('a') |
|||
aLink.style.display = 'none' |
|||
aLink.href = url |
|||
aLink.setAttribute('download', fileName) |
|||
document.body.appendChild(aLink) |
|||
aLink.click() |
|||
document.body.removeChild(aLink) //下载完成移除元素 |
|||
window.URL.revokeObjectURL(url) //释放掉blob对象 |
|||
this.$message.success('导出成功') |
|||
this.$emit('close') |
|||
} else this.$message.error('下载失败') |
|||
this.exportLoading = false |
|||
}) |
|||
.catch(err => { |
|||
console.log('err', err) |
|||
this.exportLoading = false |
|||
return this.$message.error('网络错误') |
|||
}) |
|||
}, |
|||
async getTemplateList () { |
|||
let params = { |
|||
formCode: 'resi_base_info' |
|||
} |
|||
await this.$http |
|||
.post('/oper/customize/icExportTemplate/templateList', params) |
|||
.then(({ data: res }) => { |
|||
if (res.code !== 0) { |
|||
return this.$message.error(res.msg) |
|||
} else { |
|||
this.tableData = res.data |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
return this.$message.error('网络错误') |
|||
}) |
|||
}, |
|||
async getPreview (id) { |
|||
let params = { |
|||
id: id || '' |
|||
} |
|||
await this.$http |
|||
.post('/oper/customize/icExportTemplate/templateDetail', params) |
|||
.then(({ data: res }) => { |
|||
if (res.code !== 0) { |
|||
return this.$message.error(res.msg) |
|||
} else { |
|||
this.previewList = res.data |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
return this.$message.error('网络错误') |
|||
}) |
|||
}, |
|||
async delTemplate(id) { |
|||
let params = [id] |
|||
await this.$http |
|||
.post('/oper/customize/icExportTemplate/delete', params) |
|||
.then(({ data: res }) => { |
|||
if (res.code !== 0) { |
|||
return this.$message.error(res.msg) |
|||
} else { |
|||
this.$message({ |
|||
type: 'success', |
|||
message: '删除成功!' |
|||
}); |
|||
this.getTemplateList() |
|||
} |
|||
}) |
|||
.catch(() => { |
|||
return this.$message.error('网络错误') |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.diy-container { |
|||
padding: 20px 20px 0 20px; |
|||
} |
|||
.diy-wr { |
|||
display: flex; |
|||
width: 100%; |
|||
height: calc(80vh - 120px); |
|||
.left { |
|||
width: 49%; |
|||
} |
|||
.right { |
|||
flex-shrink: 0; |
|||
width: 50%; |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
margin-left: 20px; |
|||
padding: 0 20px; |
|||
border-left: 1px solid #eee; |
|||
.right-header { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
padding-bottom: 10px; |
|||
// border-bottom: 1px solid #eee; |
|||
.title { |
|||
font-weight: 500; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.diy-footer { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
margin-top: 10px; |
|||
} |
|||
.left-h { |
|||
|
|||
::v-deep .el-tabs__header.is-left, |
|||
::v-deep .el-tabs__nav-wrap.is-left::after { |
|||
height: calc(80vh - 120px); |
|||
} |
|||
} |
|||
.flex-div { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
// #collapsWr { |
|||
// .col-h { |
|||
// ::v-deep .el-collapse-item__wrap { |
|||
// max-height: calc(80vh - 220px); |
|||
// // overflow: auto; |
|||
// } |
|||
|
|||
// } |
|||
// } |
|||
.mb10 { |
|||
margin-bottom: 10px; |
|||
} |
|||
.pd10 { |
|||
padding: 10px; |
|||
} |
|||
.mr10 { |
|||
margin-right: 10px; |
|||
} |
|||
.wd200 { |
|||
width: 200px; |
|||
} |
|||
</style> |
Loading…
Reference in new issue