Base Login
This commit is contained in:
612
components/datatable/DataTable.vue
Normal file
612
components/datatable/DataTable.vue
Normal file
@@ -0,0 +1,612 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="pb-1" v-if="pagedata.showFilter && filters.length>0">
|
||||
<div class="field is-grouped is-grouped-multiline pl-2" v-if="filters? filters.length>0 : false">
|
||||
<div class="control mr-5">
|
||||
<a class="button is-primary is-outlined is-rounded fs-10" @click="clearFilter()">
|
||||
<span class="fs-13">Xóa lọc</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control pr-2 mr-5">
|
||||
<span class="icon has-text-primary fsb-18"> <i class="mdi mdi-sigma"> </i>
|
||||
{{totalRows}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="control" v-for="(v,i) in filters" :key="i">
|
||||
<div class="tags has-addons is-marginless">
|
||||
<a class="tag is-primary is-marginless" @click="showCondition(v)">{{v.label.indexOf('>')>=0? $stripHtml(v.label,30) : v.label}}</a>
|
||||
<a class="tag is-delete is-marginless has-text-black-bis" @click="removeFilter(i)"></a>
|
||||
</div>
|
||||
<span class="help has-text-black-bis">
|
||||
{{v.sort? v.sort : (v.select? ('[' + (v.select.length>0? $stripHtml(v.select[0],20) : '') + '...Σ' + v.select.length + ']') :
|
||||
(v.condition))}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-container" ref="container">
|
||||
<table class="table is-bordered is-narrow is-hoverable" ref="table" :style="getSettingStyle('table')">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="(field,i) in displayFields" :key="i" :ref="`th${field.name}`"
|
||||
:style="getSettingStyle('header', field)">
|
||||
<div class="hyperlink" @click="showField(field)" :style="getSettingStyle('dropdown', field)">
|
||||
<template v-if="field.label.indexOf('<')<0">{{field.label}}</template>
|
||||
<template v-else>
|
||||
<component v-bind="{row: field, tick: tickall}" :is="compiledComponent(field.label)" @clickevent="doAction($event, field)" />
|
||||
</template>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(v,i) in displayData" :key="i">
|
||||
<td v-for="(field, j) in fields.filter(v=>v.show)" :key="j" :ref="`${v.stock_code}${field.name}`" :id="`${v.stock_code}${field.name}`"
|
||||
:style="v[`${field.name}color`]" @dblclick="doubleClick(field, v)">
|
||||
<component v-bind="{row: v, tick: tick, pagename: pagename, field: field, highlight: highlight}" v-if="field.template"
|
||||
:is="compiledComponent(field.template)" @clickevent="doAction($event, v, field)"
|
||||
/>
|
||||
<template v-else-if="field.tooltip">
|
||||
<b-tooltip :label="v[field.tooltip.field]"
|
||||
:position="field.tooltip.placement"
|
||||
:type="field.tooltip.type">
|
||||
{{v[field.name]}}
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<template v-else> {{v[field.name]}} </template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="mt-3 px-3" v-if="showPaging">
|
||||
<b-pagination
|
||||
:total="totalRows"
|
||||
:current.sync="currentPage"
|
||||
:order="'is-centered'"
|
||||
:rounded="true"
|
||||
:per-page="perPage"
|
||||
@change="changePage()"
|
||||
>
|
||||
</b-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<Modal @close="showmodal=undefined" v-bind="showmodal" v-if="showmodal"
|
||||
@dosearch="doSearch(currentField, $event)" @doselect="doSelect(currentField, $event)" @dosort="doSort(currentField, $event)"
|
||||
@setfilter="setFilter(currentField, $event)" @showsidebar="showSidebar($event)" @copyfield="copyField">
|
||||
</Modal>
|
||||
<Modal @close="showmodal1=undefined" v-bind="showmodal1" v-if="showmodal1" @updatefields="updateFields"></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
export default {
|
||||
props: ['pagename'],
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
fields: [],
|
||||
search: '',
|
||||
filters: [],
|
||||
currentPage: 1,
|
||||
filterData: [],
|
||||
timer: undefined,
|
||||
perPage: 30,
|
||||
currentField: undefined,
|
||||
flagSearch: false,
|
||||
scrollbar: undefined,
|
||||
tablesetting: undefined,
|
||||
tick: {},
|
||||
tickall: false,
|
||||
displayData: [],
|
||||
displayFields: [],
|
||||
showmodal: undefined,
|
||||
showmodal1: undefined,
|
||||
totalRows: 0,
|
||||
showPaging: false,
|
||||
highlight: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(this.pagedata.data) this.data = this.$copy(this.pagedata.data)
|
||||
if(this.pagedata.fields) this.fields = this.$copy(this.pagedata.fields)
|
||||
if(this.pagedata.filters) this.filters = this.$copy(this.pagedata.filters)
|
||||
this.tablesetting = this.$copy(this.pagedata.tablesetting || this.gridsetting)
|
||||
this.perPage = this.pagedata.perPage? this.pagedata.perPage : this.$formatNumber(this.tablesetting.find(v=>v.code==='per-page').detail)
|
||||
if(this.data.length>0 && this.fields.length>0) this.updateShow()
|
||||
else this.showPagination()
|
||||
},
|
||||
watch: {
|
||||
'pagedata.update': function(newVal) {
|
||||
if(newVal) this.updateData(newVal)
|
||||
},
|
||||
menuaction: function(newVal) {
|
||||
if(this.$empty(newVal)) return
|
||||
if(newVal.name==='export-excel' && (newVal.pagename? newVal.pagename===this.pagename : true)) {
|
||||
this.$exportExcel(this.data, this.menuaction.file, this.fields.filter(v=>v.show))
|
||||
} else if(newVal.name==='opensidebar' && (newVal.pagename? newVal.pagename===this.pagename : true)) {
|
||||
this.showmodal = {component: 'datatable/TableOption', vbind: {pagename: this.pagename}, width: '850px', height: '600px', title: 'Danh sách cột'}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pagedata: {
|
||||
get: function() {return this.$store.state[this.pagename]},
|
||||
set: function(val) {this.$store.commit('updateStore', {name: this.pagename, data: val})}
|
||||
},
|
||||
gridsetting: {
|
||||
get: function() {return this.$store.state.tablesetting},
|
||||
set: function(val) {this.$store.commit("updateTableSetting", {tablesetting: val})}
|
||||
},
|
||||
menuaction: {
|
||||
get: function() {return this.$store.state.menuaction},
|
||||
set: function(val) {this.$store.commit("updateMenuAction", {menuaction: val})}
|
||||
},
|
||||
currentsetting: {
|
||||
get: function() {return this.$store.state.currentsetting},
|
||||
set: function(val) {this.$store.commit("updateCurrentSetting", {currentsetting: val})}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showPagination() {
|
||||
this.showPaging = this.pagedata.pagination===false? false : true
|
||||
this.totalRows = this.data.length
|
||||
if(this.showPaging && this.pagedata.api) {
|
||||
if(this.pagedata.api.full_data===false) this.totalRows = this.pagedata.api.total_rows
|
||||
this.showPaging = this.totalRows > this.perPage
|
||||
}
|
||||
},
|
||||
clearFilter() {
|
||||
this.updateData({filters: []})
|
||||
},
|
||||
async updateData(newVal) {
|
||||
if(newVal.columns) { //change attribute
|
||||
this.fields = this.$copy(newVal.columns)
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'fields', data: this.fields})
|
||||
this.$emit('changefield', this.fields)
|
||||
let fields = this.fields.filter(v=>v.show)
|
||||
this.data.map(v=>{
|
||||
fields.map(x=>v[`${x.name}color`] = this.getStyle(x, v))
|
||||
})
|
||||
return this.updateShow()
|
||||
}
|
||||
if(newVal.tablesetting) {
|
||||
this.tablesetting = newVal.tablesetting
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'tablesetting', data: this.tablesetting})
|
||||
this.perPage = this.$formatNumber(this.tablesetting.find(v=>v.code=="per-page").detail)
|
||||
this.currentPage = 1
|
||||
}
|
||||
this.tablesetting = this.$copy(this.pagedata.tablesetting || this.gridsetting)
|
||||
if(this.tablesetting) {
|
||||
this.perPage = this.pagedata.perPage? this.pagedata.perPage : Number(this.tablesetting.find(v=>v.code==='per-page').detail)
|
||||
}
|
||||
if(newVal.fields) {
|
||||
this.fields = this.$copy(newVal.fields)
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'fields', data: this.$copy(this.fields)})
|
||||
this.$emit('changefield', this.fields)
|
||||
} else this.fields = this.$copy(this.pagedata.fields)
|
||||
if(newVal.data || newVal.fields) {
|
||||
let copy = this.$copy(newVal.data || this.data)
|
||||
this.data = this.$calculateData(copy, this.fields)
|
||||
let fields = this.fields.filter(v=>v.show)
|
||||
this.data.map(v=>{
|
||||
fields.map(x=>v[`${x.name}color`] = this.getStyle(x, v))
|
||||
})
|
||||
if(newVal.data) {
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'data', data: this.$copy(this.data)})
|
||||
this.$emit('changedata', this.data)
|
||||
}
|
||||
}
|
||||
if(newVal.filters) this.filters = this.$copy(newVal.filters)
|
||||
else if(this.pagedata.filters) this.filters = this.$copy(this.pagedata.filters)
|
||||
if(newVal.data || newVal.fields || newVal.filters) {
|
||||
let copy = this.$copy(this.filters)
|
||||
this.filters.map((v,i)=>{
|
||||
let idx = this.$findIndex(this.fields, {name: v.name})
|
||||
let index = this.$findIndex(copy, {name: v.name})
|
||||
if(idx<0 && index>=0) this.$delete(copy, index)
|
||||
else if(idx>=0 && index>=0) copy[index].label = this.fields[idx].label
|
||||
})
|
||||
this.filters = copy
|
||||
this.doFilter(this.filters)
|
||||
}
|
||||
if(newVal.data || newVal.fields || newVal.filters || newVal.tablesetting) this.updateShow()
|
||||
if(newVal.data || newVal.fields) setTimeout(()=> this.scrollbarVisible(), 100)
|
||||
if(newVal.highlight) {
|
||||
this.highlight = this.$copy(newVal.highlight)
|
||||
setTimeout(()=>this.highlight = undefined, 500)
|
||||
}
|
||||
},
|
||||
updateShow(full_data) {
|
||||
this.showPagination()
|
||||
this.displayFields = this.fields.filter(v=>v.show)
|
||||
if(full_data===false) this.displayData = this.data
|
||||
else this.displayData = this.data.filter((ele,index) => (index>=(this.currentPage-1)*this.perPage && index<this.currentPage*this.perPage))
|
||||
},
|
||||
async changePage() {
|
||||
if(this.pagedata.api? this.pagedata.api.full_data===false : false) await this.backendFilter(this.filters)
|
||||
else this.updateShow()
|
||||
this.$emit('changepage', this.currentPage)
|
||||
},
|
||||
doubleClick(field, v) {
|
||||
this.doSelect(field, v[field.name])
|
||||
},
|
||||
showField(field) {
|
||||
if(this.pagedata.contextMenu===false || field.menu==='no') return
|
||||
this.showContextMenu(field)
|
||||
let doc = this.$refs[`th${field.name}`]
|
||||
let width = (doc? doc.length>0 : false)? doc[0].getBoundingClientRect().width : 100
|
||||
if(this.pagedata.setting) this.currentsetting = this.$copy(this.pagedata.setting)
|
||||
this.showmodal = {vbind: {pagename: this.pagename, field: this.currentField, filters: this.filters, filterData: this.filterData, width: width},
|
||||
component: 'datatable/ContextMenu', title: this.$stripHtml(field.label), width: '600px', height: '500px'}
|
||||
},
|
||||
showCondition(v) {
|
||||
this.$emit('contextmenu', 'open')
|
||||
this.currentField = this.$find(this.pagedata.fields, {'name': v.name})
|
||||
this.showField(this.currentField)
|
||||
},
|
||||
compiledComponent(value) {
|
||||
return {
|
||||
template: `${value}`,
|
||||
props: ['row', 'tick', 'pagename', 'field', 'highlight'],
|
||||
methods: {
|
||||
formatNumber(val) {
|
||||
return this.$formatNumber(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
showContextMenu(field) {
|
||||
this.currentField = field
|
||||
this.filterData = this.$unique(this.data, [field.name])
|
||||
this.menuaction = {name: 'display', key: this.$id(), field: field}
|
||||
this.$emit('contextmenu', 'open')
|
||||
},
|
||||
showSidebar(event) {
|
||||
let title = 'Danh sách cột'
|
||||
if(event.name==="bgcolor") title = `Đổi màu nền: ${event.field.name} / ${this.$stripHtml(event.field.label, 30)}`
|
||||
else if(event.name==="color") title = `Đổi màu chữ: ${event.field.name} / ${this.$stripHtml(event.field.label, 30)}`
|
||||
else if(event.name==='template') title = `Định dạng nâng cao: ${this.$stripHtml(event.field.label, 30)}`
|
||||
this.showmodal1 = {component: 'datatable/FormatOption',
|
||||
vbind: {event: event, currentField: this.currentField, pagename: this.pagename}, width: '850px', height: '700px', title: title}
|
||||
},
|
||||
getStyle(field, record) {
|
||||
var stop = false
|
||||
let val = this.tablesetting.find(v=>v.code==='td-border')? this.tablesetting.find(v=>v.code==='td-border').detail : 'border: solid 1px rgb(44, 44, 44); '
|
||||
val = val.indexOf(';')>=0? val : val + ';'
|
||||
if(field.bgcolor? !Array.isArray(field.bgcolor) : false) {
|
||||
val += ` background-color:${field.bgcolor}; `
|
||||
} else if(field.bgcolor? Array.isArray(field.bgcolor) : false) {
|
||||
field.bgcolor.map(v=>{
|
||||
if(v.type==='search') {
|
||||
if(record[field.name] && !stop? record[field.name].toLowerCase().indexOf(v.keyword.toLowerCase())>=0 : false) {
|
||||
val += ` background-color:${v.color}; `
|
||||
stop = true
|
||||
}
|
||||
} else {
|
||||
let res = this.$calculate(record, v.tags, v.expression)
|
||||
if(res.success && res.value && !stop) {
|
||||
val += ` background-color:${v.color}; `
|
||||
stop = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
stop = false
|
||||
if(field.color? !Array.isArray(field.color) : false) {
|
||||
val += ` color:${field.color}; `
|
||||
} else if(field.color? Array.isArray(field.color) : false) {
|
||||
field.color.map(v=>{
|
||||
if(v.type==='search') {
|
||||
if(record[field.name] && !stop? record[field.name].toLowerCase().indexOf(v.keyword.toLowerCase())>=0 : false) {
|
||||
val += ` color:${v.color}; `
|
||||
stop = true
|
||||
}
|
||||
} else {
|
||||
let res = this.$calculate(record, v.tags, v.expression)
|
||||
if(res.success && res.value && !stop) {
|
||||
val += ` color:${v.color}; `
|
||||
stop = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
stop = false
|
||||
if(field.textsize? !Array.isArray(field.textsize) : false) {
|
||||
val += ` font-size:${field.textsize}px; `
|
||||
} else if(field.textsize? Array.isArray(field.textsize) : false) {
|
||||
field.textsize.map(v=>{
|
||||
if(v.type==='search') {
|
||||
if(record[field.name] && !stop? record[field.name].toLowerCase().indexOf(v.keyword.toLowerCase())>=0 : false) {
|
||||
val += ` font-size:${v.size}px; `
|
||||
stop = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
let res = this.$calculate(record, v.tags, v.expression)
|
||||
if(res.success && res.value && !stop) {
|
||||
val += ` font-size:${v.size}px; `
|
||||
stop = true
|
||||
}
|
||||
}
|
||||
})
|
||||
} else val += ` font-size:${this.tablesetting.find(v=>v.code==='table-font-size').detail}px;`
|
||||
if(field.textalign) val += ` text-align:${field.textalign}; `
|
||||
if(field.minwidth) val += ` min-width:${field.minwidth}px; `
|
||||
if(field.maxwidth) val += ` max-width:${field.maxwidth}px; `
|
||||
return val
|
||||
},
|
||||
getSettingStyle(name, field) {
|
||||
let value = ''
|
||||
if(name==='container') {
|
||||
value = 'min-height:' + this.tablesetting.find(v=>v.code==='container-height').detail + 'rem; '
|
||||
} else if(name==='table') {
|
||||
value += 'background-color:' + this.tablesetting.find(v=>v.code==='table-background').detail + '; '
|
||||
value += 'font-size:' + this.tablesetting.find(v=>v.code==='table-font-size').detail + 'px;'
|
||||
value += 'color:' + this.tablesetting.find(v=>v.code==='table-font-color').detail + '; '
|
||||
} else if(name==='header') {
|
||||
value += 'background-color:' + this.tablesetting.find(v=>v.code==='header-background').detail + '; '
|
||||
if(field.minwidth) value += ' min-width: ' + field.minwidth + 'px; '
|
||||
if(field.maxwidth) value += ' max-width: ' + field.maxwidth + 'px; '
|
||||
} else if(name==='menu') {
|
||||
let arg = this.tablesetting.find(v=>v.code==='menu-width').detail
|
||||
arg = field? (field.menuwidth? field.menuwidth : arg) : arg
|
||||
value += 'width:' + arg + 'rem; '
|
||||
value += 'min-height:' + this.tablesetting.find(v=>v.code==='menu-min-height').detail + 'rem; '
|
||||
value += 'max-height:' + this.tablesetting.find(v=>v.code==='menu-max-height').detail + 'rem; '
|
||||
value += "overflow:auto; "
|
||||
} else if(name==='dropdown') {
|
||||
value += 'font-size:' + this.tablesetting.find(v=>v.code==='header-font-size').detail + 'px; '
|
||||
let found = this.filters.find(v=>v.name===field.name)
|
||||
found? value += 'color:' + this.tablesetting.find(v=>v.code==='header-filter-color').detail + '; '
|
||||
:value += 'color:' + this.tablesetting.find(v=>v.code==='header-font-color').detail + '; '
|
||||
}
|
||||
return value
|
||||
},
|
||||
removeFilter(i) {
|
||||
Vue.delete(this.filters, i)
|
||||
this.doFilter(this.filters)
|
||||
this.updateShow()
|
||||
},
|
||||
updateFields(field) {
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = copy.findIndex(v=>v.name===field.name)
|
||||
copy[idx] = field
|
||||
this.updateData({columns: copy})
|
||||
this.currentField = this.$copy(field)
|
||||
if(this.showmodal) {
|
||||
this.showmodal.vbind.field = this.$copy(field)
|
||||
this.showmodal = this.$copy(this.showmodal)
|
||||
}
|
||||
},
|
||||
doAction(event, row, field) {
|
||||
let name = typeof event === "string"? event : event.name
|
||||
let data = typeof event === "string"? event : event.data
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'action', data: {event: name, row: row, field: field, data: data, time: new Date()}})
|
||||
if(name==='remove') this.$deleterow(this.pagedata.api.name, row.id, this.pagename, true)
|
||||
if(name==='batchdelete') this.batchDelete()
|
||||
this.$emit(name, row, field, data)
|
||||
if(name==='tickall') {
|
||||
this.tickall = data
|
||||
if(data===false) this.tick = {}
|
||||
else {
|
||||
this.data.map(v=>this.tick[v.id] = true)
|
||||
this.tick = this.$copy(this.tick)
|
||||
}
|
||||
}
|
||||
},
|
||||
batchDelete() {
|
||||
let arr = []
|
||||
Object.entries(this.tick).forEach(([key, value]) => {
|
||||
if(value) arr.push({id: Number(key)})
|
||||
})
|
||||
if(arr.length===0) this.$buefy.toast.open({message: 'Bạn chưa chọn bản ghi để xoá', type: 'is-warning'})
|
||||
else this.$deleterow(this.pagedata.api.name, arr, this.pagename, true)
|
||||
},
|
||||
doSort(field, type) {
|
||||
let filter = {name: field.name, label: field.label, sort: type, format: field.format}
|
||||
let idx = this.filters.findIndex(v=>v.name===field.name)
|
||||
if(idx>=0) Vue.set(this.filters, idx, filter)
|
||||
else this.filters.push(filter)
|
||||
this.doFilter(this.filters)
|
||||
this.updateShow()
|
||||
},
|
||||
doSearch(field, search) {
|
||||
let copy = this.$copy(this.filters)
|
||||
let idx = copy.findIndex(v=>v.name===field.name)
|
||||
if(idx>=0) Vue.delete(copy, idx)
|
||||
if(this.pagedata.origin_api.full_data) {
|
||||
let data = this.frontendFilter(copy)
|
||||
let rows = this.$empty(search)? data
|
||||
: data.filter(v=>v[field.name]? v[field.name].toString().toLowerCase().indexOf(search.toLowerCase())>=0 : false)
|
||||
this.filterData = this.$unique(rows, [field.name])
|
||||
if(this.showmodal) this.showmodal.vbind.filterData = this.filterData
|
||||
} else {
|
||||
copy.push({name: field.name, label: field.label, search: search.toLowerCase(), format: field.format})
|
||||
this.flagSearch = true
|
||||
this.backendFilter(copy)
|
||||
}
|
||||
},
|
||||
doSelect(field, value) {
|
||||
let found = this.filters.find(v=>v.name===field.name)
|
||||
if(found) {
|
||||
!found.select? found.select = [] : false
|
||||
let idx = found.select.findIndex(x=>x===value)
|
||||
idx>=0? Vue.delete(found.select, idx) : found.select.push(value)
|
||||
if(found.select.length===0) {
|
||||
idx = this.filters.findIndex(v=>v.name===field.name)
|
||||
if(idx>=0) Vue.delete(this.filters, idx)
|
||||
}
|
||||
} else {
|
||||
this.filters.push({name: field.name, label: field.label, select: [value], format: field.format})
|
||||
}
|
||||
this.doFilter(this.filters)
|
||||
this.updateShow()
|
||||
},
|
||||
setFilter(field, filter) {
|
||||
let idx = this.filters.findIndex(v=>v.name===field.name)
|
||||
if(idx<0) this.filters.push(filter)
|
||||
else Vue.set(this.filters, idx, filter)
|
||||
this.doFilter(this.filters)
|
||||
this.updateShow()
|
||||
},
|
||||
doFilter(newVal, nonset) {
|
||||
if(this.currentPage>1 && nonset!==true) this.currentPage = 1
|
||||
if(this.pagedata.origin_api.full_data) {
|
||||
this.data = this.frontendFilter(newVal)
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "dataFilter", data: this.$copy(this.data)})
|
||||
this.$emit('changedata', newVal)
|
||||
}
|
||||
else {
|
||||
if(this.timer) clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => this.backendFilter(newVal), 200)
|
||||
}
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "filters", data: this.$copy(newVal)})
|
||||
this.$emit('changefilter', newVal? newVal.length>0 : false)
|
||||
},
|
||||
frontendFilter(newVal) {
|
||||
let self = this
|
||||
let checkValid = function(name, x, filter) {
|
||||
if(self.$empty(x[name])) return false
|
||||
else {
|
||||
let text = ''
|
||||
filter.map((y,k)=>{
|
||||
text += `${k>0? (filter[k-1].operator==='and'? ' &&' : ' ||') : ''} ${self.$formatNumber(x[name])}
|
||||
${y.condition==='='? '==' : (y.condition==='<>'? '!==' : y.condition)} ${self.$formatNumber(y.value)}`
|
||||
})
|
||||
return self.$calc(text)
|
||||
}
|
||||
}
|
||||
newVal = this.$copy(newVal)
|
||||
var data = this.$copy(this.pagedata.data)
|
||||
newVal.filter(m=>m.select || m.filter).map(v => {
|
||||
if(v.select) {
|
||||
data = data.filter(x => v.select.findIndex(y => this.$empty(y)? this.$empty(x[v.name]) : (y===x[v.name])) >-1)
|
||||
} else if(v.filter) {
|
||||
data = data.filter(x => checkValid(v.name, x, v.filter))
|
||||
}
|
||||
})
|
||||
let sort = {}
|
||||
let format = {}
|
||||
let list = this.filters.filter(x=>x.sort)
|
||||
list.map(v=>{
|
||||
sort[v.name] = v.sort === "az" ? "asc" : "desc"
|
||||
format[v.name] = v.format;
|
||||
})
|
||||
return list.length>0? this.$multiSort(data, sort, format) : data
|
||||
},
|
||||
// Sử dụng backend filter
|
||||
async backendFilter(newVal) {
|
||||
let arr = [{code: '>', name: 'gt'}, {code: '>=', name: 'gte'}, {code: '<', name: 'lt'}, {code: '<=', name: 'lte'}, {code: '=', name: 'e'},
|
||||
{code: '<>', name: 'e'}]
|
||||
let params = this.pagedata.origin_api.params? this.$copy(this.pagedata.origin_api.params) : {}
|
||||
params.page = this.currentPage
|
||||
var where = params.filter? params.filter : {}
|
||||
var exclude = {}
|
||||
var sort = params.sort? params.sort.split(',') : []
|
||||
var filter = newVal.filter(v=>!v.formula)
|
||||
if (this.pagedata.origin_api.url.indexOf("data/") >= 0) {
|
||||
filter.forEach(v => {
|
||||
if(v.search) where[v.name + "__icontains"] = v.search
|
||||
else if (v.select) where[v.name + "__in"] = v.select
|
||||
else if (v.filter) {
|
||||
v.filter.map(x=>{
|
||||
let obj = this.$find(arr, {code: x.condition})
|
||||
if(obj) {
|
||||
if(x.condition==='<>') exclude[v.name + (obj.name==='e'? '' : '__' + obj.name)] = this.$formatNumber(x.value)
|
||||
else where[v.name + (obj.name==='e'? '' : '__' + obj.name)] = this.$formatNumber(x.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
else if (v.sort) sort.push(v.sort==="az" ? v.name : "-" + v.name)
|
||||
})
|
||||
params.filter = Object.keys(where).length>0? where : undefined
|
||||
params.exclude = Object.keys(exclude).length>0? exclude : undefined
|
||||
params.sort = sort.length === 0 ? undefined : sort.toString()
|
||||
}
|
||||
// Tải lại dữ liệu
|
||||
let found = this.$copy(this.pagedata.api)
|
||||
found.params = params
|
||||
await this.loadData(found)
|
||||
},
|
||||
async loadData(found) {
|
||||
let result = await this.$getapi([found])
|
||||
if(result==='error') return
|
||||
if(this.flagSearch) {
|
||||
this.flagSearch = false
|
||||
var rows = result[0].data.rows
|
||||
if(this.currentField) this.filterData = this.$unique(rows, [this.currentField.name])
|
||||
} else {
|
||||
let copy = this.$copy(result[0])
|
||||
copy.total_rows = copy.data.total_rows
|
||||
copy.full_data = copy.data.full_data
|
||||
delete copy.data
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "data", data: this.$copy(result[0].data.rows)})
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "api", data: this.$copy(copy)})
|
||||
this.data = this.$copy(result[0].data.rows)
|
||||
this.updateShow(copy.full_data)
|
||||
}
|
||||
},
|
||||
scrollbarVisible() {
|
||||
let element = this.$refs['container']
|
||||
if(!element) return
|
||||
let result = element.scrollWidth > element.clientWidth? true : false
|
||||
if(this.scrollbar) {
|
||||
element.parentNode.removeChild(this.scrollbar)
|
||||
this.scrollbar = undefined
|
||||
}
|
||||
if(result) this.doubleScroll(element)
|
||||
},
|
||||
doubleScroll(element) {
|
||||
var scrollbar= document.createElement('div');
|
||||
scrollbar.appendChild(document.createElement('div'));
|
||||
scrollbar.style.overflow= 'auto';
|
||||
scrollbar.style.overflowY= 'hidden';
|
||||
scrollbar.firstChild.style.width= element.scrollWidth+'px';
|
||||
scrollbar.firstChild.style.height = '1px'
|
||||
scrollbar.firstChild.appendChild(document.createTextNode('\xA0'));
|
||||
var running = false;
|
||||
scrollbar.onscroll= function() {
|
||||
if(running) {
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
running = true;
|
||||
element.scrollLeft= scrollbar.scrollLeft;
|
||||
};
|
||||
element.onscroll= function() {
|
||||
if(running) {
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
running = true;
|
||||
scrollbar.scrollLeft= element.scrollLeft;
|
||||
}
|
||||
element.parentNode.insertBefore(scrollbar, element)
|
||||
scrollbar.scrollLeft= element.scrollLeft
|
||||
this.scrollbar = scrollbar
|
||||
},
|
||||
copyField(field) {
|
||||
let newField = this.$copy(field)
|
||||
newField.name = `f${this.$id()}`
|
||||
newField.label = field.label + '-copy'
|
||||
if(field.format==='number') {
|
||||
newField.formula = field.name
|
||||
newField.tags = [field.name]
|
||||
newField.unit = field.unit==='0.01'? field.unit : '1'
|
||||
} else {
|
||||
newField.copy = field.name
|
||||
if(newField.mandatory==='yes') delete newField['mandatory']
|
||||
}
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = copy.findIndex(v=>v.name===field.name)
|
||||
copy.splice(idx+1, 0, newField)
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "update", data: {fields: copy, data: this.pagedata.data}})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.table tbody tr:hover td, .table tbody tr:hover th {
|
||||
background-color: hsl(0, 0%, 29%);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user