Base Login
This commit is contained in:
946
components/datatable/ContextMenu.vue
Normal file
946
components/datatable/ContextMenu.vue
Normal file
@@ -0,0 +1,946 @@
|
||||
<template>
|
||||
<div class="fs-14 has-text-weight-normal">
|
||||
<div>
|
||||
<b-tooltip label="Sắp xếp tăng dần" type="is-dark" position="is-right">
|
||||
<a @click="checkFilter()? false : $emit('modalevent', {name: 'dosort', data: 'az'})">
|
||||
<span class="icon is-medium fs-22 mr-2" :class="checkFilter()? 'has-text-grey-light' : ''">
|
||||
<i class="mdi mdi-sort-alphabetical-ascending" />
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Sắp xếp giảm dần" type="is-dark" position="is-right">
|
||||
<a @click="checkFilter()? false : $emit('modalevent', {name: 'dosort', data: 'za'})">
|
||||
<span class="icon is-medium fs-22 mr-2" :class="checkFilter()? 'has-text-grey-light' : '' " >
|
||||
<i class="mdi mdi-sort-alphabetical-descending" />
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Chuyển cột sang trái" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-22 mr-2" @click="moveLeft()">
|
||||
<i class="mdi mdi-arrow-left" />
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Chuyển cột sang phải" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-22 mr-2" @click="moveRight()">
|
||||
<i class="mdi mdi-arrow-right"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Ẩn cột" type="is-dark" position="is-right">
|
||||
<a @click="hideField()">
|
||||
<span class="icon is-medium fs-22 mr-2">
|
||||
<i class="mdi mdi-eye-off-outline"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Xóa cột" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-22 mr-2" @click="currentField.mandatory? false : doRemove()">
|
||||
<i :class="`mdi mdi-delete-outline ${currentField.mandatory? 'has-text-grey-light' : ''}`"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Sao chép cột" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-20 mr-2" @click="$emit('modalevent', {name: 'copyfield', data:currentField})">
|
||||
<i class="mdi mdi-content-copy"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Tăng độ rộng cột" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-22 mr-2" @click="resizeWidth()">
|
||||
<i class="mdi mdi-arrow-expand-horizontal"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Giảm độ rộng cột" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium fs-22 mr-2" @click="resizeWidth(true)">
|
||||
<i class="mdi mdi-arrow-collapse-horizontal"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<b-tooltip label="Danh sách cột" type="is-dark" position="is-right">
|
||||
<a>
|
||||
<span class="icon is-medium mr-2 fs-22" @click="$emit('modalevent', {name: 'showsidebar', data: {field: currentField, name: 'option'}})">
|
||||
<i class="mdi mdi-format-list-bulleted"/>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
</div>
|
||||
<div class="field mt-2 mb-2" v-if="currentField.disable? currentField.disable.indexOf('search') <0 : true">
|
||||
<div :class="loading? 'control is-loading' : 'control'">
|
||||
<input class="input is-rounded fs-13" type="text" v-model="search" @keyup="startSearch" @keypress.enter="pressEnter"
|
||||
:placeholder="'Tìm kiếm: ' + (currentField.label.indexOf('<')>=0? currentField.name : currentField.label)"
|
||||
@focus="doFocus()" :ref="currentField.name">
|
||||
</div>
|
||||
</div>
|
||||
<p class="panel-tabs mb-2">
|
||||
<a v-for="(v,i) in getMenu().filter(x=>currentField.format==='number'? (currentField.formula? true : x.code!=='formula')
|
||||
: !['filter','formula'].find(y=>y===x.code))" :key="i"
|
||||
:class="selectTab.code===v.code? 'is-active' : ''" @click="selectTab=v"> {{v.name}}
|
||||
</a>
|
||||
</p>
|
||||
<template v-if="selectTab.code==='value'">
|
||||
<ScrollBox v-bind="{data: filterData, name: currentField.name, maxheight: '380px', perpage: 20, selects: checkSelected()}"
|
||||
@selected="doSelect" />
|
||||
</template>
|
||||
<template v-else-if="selectTab.code==='display'">
|
||||
<div class="field is-horizontal border-bottom pb-0 mb-1">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Màu nền </label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice" :key="i" v-model="radioBGcolor"
|
||||
:native-value="v" @input="changeBGColor()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioBGcolor? radioBGcolor.code==='option' : false">
|
||||
<label class="label fs-14"> Mã màu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<input type="color" v-model="bgcolor" @change="changeBGColor()">
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioBGcolor? radioBGcolor.code==='condition' : false">
|
||||
<label class="label fs-14"> Mã màu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<a class="button is-small is-primary is-outlined is-rounded" @click="doAdvance('bgcolor')"> Nâng cao </a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal border-bottom pb-0 mb-1">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Màu chữ </label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice" :key="i" v-model="radioColor"
|
||||
:native-value="v" @input="changeColor()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioColor? radioColor.code==='option' : false">
|
||||
<label class="label fs-14"> Mã màu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<input type="color" v-model="color" @change="changeColor()">
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioColor? radioColor.code==='condition' : false">
|
||||
<label class="label fs-14"> Mã màu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<a class="button is-small is-primary is-outlined is-rounded" @click="doAdvance('color')"> Nâng cao </a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal border-bottom pb-0 mb-1">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Cỡ chữ </label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice" :key="i" v-model="radioSize"
|
||||
:native-value="v" @input="changeSize()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioSize? radioSize.code==='option' : false">
|
||||
<label class="label fs-14"> Cỡ chữ <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<input class="input is-small" type="text" placeholder="Nhập số" v-model="textsize" @change="changeSize()">
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioSize? radioSize.code==='condition' : false">
|
||||
<label class="label fs-14"> Cỡ chữ <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<a class="button is-small is-primary is-outlined is-rounded" @click="doAdvance('textsize')"> Nâng cao </a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal pb-0 mb-1 border-bottom">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Vị trí text</label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice.filter(v=>v.code!=='condition')" :key="i" v-model="radioAlign"
|
||||
:native-value="v" @input="changeAlign()">{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field is-narrow" v-if="radioAlign? radioAlign.code==='option' : false">
|
||||
<label class="label fs-14">Chọn vị trí <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<b-autocomplete
|
||||
size="is-small"
|
||||
icon-right="magnify"
|
||||
:value="selectAlign? selectAlign.name : ''"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="textalign"
|
||||
field="name"
|
||||
@select="option => { selectAlign = option; changeAlign()}">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal border-bottom pb-0 mb-1">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Độ rộng nhỏ nhất</label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice.filter(v=>v.code!=='condition')" :key="i" v-model="radioWidth"
|
||||
:native-value="v" @input="changeWidth()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioWidth? radioWidth.code==='option' : false">
|
||||
<label class="label fs-14"> Kích thước</label>
|
||||
<p class="control fs-14">
|
||||
<input class="input is-small" type="text" placeholder="Nhập số" v-model="minwidth" @change="changeWidth()">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal border-bottom pb-0 mb-1">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Độ rộng lớn nhất</label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice.filter(v=>v.code!=='condition')" :key="i" v-model="radioMaxWidth"
|
||||
:native-value="v" @input="changeMaxWidth()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioMaxWidth? radioMaxWidth.code==='option' : false">
|
||||
<label class="label fs-14"> Kích thước</label>
|
||||
<p class="control fs-14">
|
||||
<input class="input is-small" type="text" placeholder="Nhập số" v-model="maxwidth" @change="changeMaxWidth()">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="selectTab.code==='filter'">
|
||||
<p class="mt-5 has-text-grey" v-if="arr===undefined">Không thể áp dụng đồng thời chức năng lọc cùng với sắp xếp</p>
|
||||
<div :class="`field is-horizontal mt-4`" v-for="(v,i) in arr" :key="i">
|
||||
<div class="field-body">
|
||||
<div class="field" style="width: 10%;">
|
||||
<label class="label" v-if="i===0">Điều kiện<span class="has-text-danger"> * </span></label>
|
||||
<p class="control">
|
||||
<b-autocomplete
|
||||
icon-right="magnify"
|
||||
v-model="v.condition"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="arr2"
|
||||
field="code"
|
||||
@select="option => doOption()">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" style="width:30%">
|
||||
<label class="label" v-if="i===0">Giá trị<span class="has-text-danger"> *</span></label>
|
||||
<p class="control">
|
||||
<input class="input" type="text" placeholder="" v-model="v.value" @change="checkValid()">
|
||||
</p>
|
||||
<p class="is-help mt-2 has-text-danger" v-if="v.error">{{v.error}}</p>
|
||||
</div>
|
||||
<div class="field" style="width: 10%;" v-if="arr.length>=1 && i===arr.length-2">
|
||||
<label class="label" v-if="i===0">Kết hợp<span class="has-text-danger"> * </span></label>
|
||||
<p class="control">
|
||||
<b-autocomplete
|
||||
icon-right="magnify"
|
||||
v-model="v.operator"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="arr1"
|
||||
field="code"
|
||||
@select="option => doOption()">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field is-narrow">
|
||||
<div class="control">
|
||||
<div :class="i===0? 'mt-5 pt-2' : ''">
|
||||
<span class="icon has-text-primary is-clickable" @click="addCondition()" v-if="arr.length<2">
|
||||
<i class="mdi mdi-plus-thick fs-22"></i>
|
||||
</span>
|
||||
<span class="icon has-text-danger is-clickable" @click="removeCondition(i)" v-if="arr.length>1">
|
||||
<i class="mdi mdi-minus-thick fs-22"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="selectTab.code==='detail'">
|
||||
<p class="fs-14 mt-3"> <strong> Tên trường: </strong> {{currentField.name}}
|
||||
<a @click="copyContent(currentField.name)">
|
||||
<b-tooltip label="Copy tên trường" type="is-dark">
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-content-copy"/>
|
||||
</span>
|
||||
</b-tooltip>
|
||||
</a>
|
||||
</p>
|
||||
<div class="field mt-3">
|
||||
<label class="label fs-14">Mô tả<span class="has-text-danger"> *</span></label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
class="input fs-14"
|
||||
type="text"
|
||||
@change="changeLabel($event.target.value)"
|
||||
v-model="label"
|
||||
/>
|
||||
<a class="button is-clickable icon is-right fs-14" @click="editLabel()">
|
||||
<i class="mdi mdi-pen has-text-primary fs-18"></i>
|
||||
</a>
|
||||
<p class="help is-danger" v-if="errors.find((v) => v.name === 'label')">
|
||||
{{ errors.find((v) => v.name === "label").msg }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mt-3">
|
||||
<label class="label fs-14">Kiểu dữ liệu<span class="has-text-danger"> * </span></label>
|
||||
<div class="control fs-14 has-text-primary">
|
||||
<b-radio v-for="(v,i) in datatype" :key="i" v-model="radioType" :native-value="v" disabled>
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal" v-if="field.format==='number'">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Đơn vị <span class="has-text-danger"> * </span> </label>
|
||||
<div class="control">
|
||||
<b-autocomplete
|
||||
size="is-small"
|
||||
icon-right="magnify"
|
||||
:value="selectUnit? selectUnit.name : ''"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="moneyunit"
|
||||
field="name"
|
||||
@select="option => {selectUnit = option; changeUnit()}">
|
||||
</b-autocomplete>
|
||||
</div>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='unit')"> {{errors.find(v=>v.name==='unit').msg}} </p>
|
||||
</div>
|
||||
<div class="field is-narrow">
|
||||
<label class="label fs-14">Phần thập phân</label>
|
||||
<div class="control">
|
||||
<input class="input is-small" type="text" placeholder="" v-model="decimal" @input="changeDecimal($event.target.value)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal mt-3">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label fs-14">Định dạng nâng cao</label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice.filter(v=>v.code!=='condition')" :key="i" v-model="radioTemplate"
|
||||
:native-value="v" @input="changeTemplate(undefined)">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3" v-if="radioTemplate? radioTemplate.code==='option' : false">
|
||||
<button class="button is-primary is-outlined is-rounded is-small" @click="$emit('modalevent', {name: 'showsidebar', data: {name: 'template', field: currentField}})">
|
||||
<span class="fs-14">{{`${currentField.template? 'Sửa' : 'Tạo'} định dạng`}}</span>
|
||||
</button>
|
||||
</p>
|
||||
</template>
|
||||
<template v-if="selectTab.code==='tooltip'">
|
||||
<p class="mt-5 fs-15 has-text-dark" v-if="currentField.template">
|
||||
Không thể sử dụng đồng thời template và tooltip
|
||||
</p>
|
||||
<template v-else>
|
||||
<div class="field mt-3">
|
||||
<label class="label fs-14">Sử dụng tooltip</label>
|
||||
<p class="control fs-14">
|
||||
<b-radio v-for="(v,i) in colorchoice.filter(v=>v.code!=='condition')" :key="i" v-model="radioTooltip"
|
||||
:native-value="v" @input="changeTooltip()">
|
||||
{{v.name}}
|
||||
</b-radio>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field" v-if="radioTooltip? radioTooltip.code==='option' : false">
|
||||
<label class="label fs-14"> Chọn trường <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<b-autocomplete
|
||||
size="is-small"
|
||||
icon-right="magnify"
|
||||
:value="selectField? selectField.label : ''"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="pagedata.fields"
|
||||
field="label"
|
||||
@select="option => {selectField = option; changeTooltip()}">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='tooltip')"> {{errors.find(v=>v.name==='tooltip').msg}} </p>
|
||||
</div>
|
||||
<div class="field mt-3" v-if="radioTooltip? radioTooltip.code==='option' : false">
|
||||
<label class="label fs-14"> Vị trí hiển thị <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<b-autocomplete
|
||||
size="is-small"
|
||||
icon-right="magnify"
|
||||
:value="selectPlacement? selectPlacement.name : ''"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="placement"
|
||||
field="name"
|
||||
@select="option => {selectPlacement = option; changeTooltip()}">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='placement')"> {{errors.find(v=>v.name==='placement').msg}} </p>
|
||||
</div>
|
||||
<div class="field mt-3" v-if="radioTooltip? radioTooltip.code==='option' : false">
|
||||
<label class="label fs-14"> Bảng màu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control fs-14">
|
||||
<b-autocomplete
|
||||
size="is-small"
|
||||
icon-right="magnify"
|
||||
:value="selectScheme? selectScheme.name : ''"
|
||||
placeholder=""
|
||||
:keep-first=true
|
||||
:open-on-focus=true
|
||||
:data="colorscheme"
|
||||
field="name"
|
||||
@select="option => {selectScheme = option; changeTooltip()}">
|
||||
</b-autocomplete>
|
||||
</p>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='tooltip')"> {{errors.find(v=>v.name==='tooltip').msg}} </p>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="selectTab.code==='formula'">
|
||||
<div class="field mt-3 px-0 mx-0">
|
||||
<label class="label fs-14"> Trường để tạo công thức <span class="has-text-danger"> * </span> </label>
|
||||
<div class="control">
|
||||
<b-taginput
|
||||
size="is-small"
|
||||
v-model="tags"
|
||||
:data="fields.filter(v=>v.format==='number')"
|
||||
type="is-dark is-light"
|
||||
autocomplete
|
||||
:open-on-focus="true"
|
||||
field="caption"
|
||||
icon="plus"
|
||||
placeholder="Chọn trường"
|
||||
>
|
||||
<template slot-scope="props">
|
||||
<span class="mr-3 has-text-danger">{{props.option.name}}</span>
|
||||
<span :class="tags.find(v=>v.id===props.option.id)? 'has-text-dark' : ''">{{$stripHtml(props.option.label,50)}}</span>
|
||||
</template>
|
||||
<template slot="empty">
|
||||
Không có trường thỏa mãn
|
||||
</template>
|
||||
</b-taginput>
|
||||
</div>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='tags')"> {{errors.find(v=>v.name==='tags').message}} </p>
|
||||
</div>
|
||||
<div class="field mt-3" v-if="tags.length>0">
|
||||
<p class="help is-primary">Click đúp vào để thêm vào công thức tính.</p>
|
||||
<div class="tags mb-2">
|
||||
<span @dblclick="formula = formula? (formula + ' ' + y.name) : y.name" class="tag is-dark is-rounded is-clickable"
|
||||
v-for="y in tags"><b-tooltip type="is-primary" :label="$stripHtml(y.label)">{{y.name}}</b-tooltip></span>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<b-tooltip type="is-dark" :label="v.name" v-for="(v,i) in operator" :key="i">
|
||||
<span @dblclick="addOperator(v)" class="tag is-primary is-rounded is-clickable mr-4">
|
||||
<span class="fs-16">{{v.code}}</span>
|
||||
</span>
|
||||
</b-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mt-3 px-0 mx-0">
|
||||
<label class="label fs-14">Công thức tính <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<textarea class="textarea" rows="4" type="text" placeholder="Tạo công thức tại đây" v-model="formula"></textarea>
|
||||
</p>
|
||||
<p class="help has-text-danger" v-if="errors.find(v=>v.name==='formula')"> {{errors.find(v=>v.name==='formula').message}} </p>
|
||||
</div>
|
||||
<div class="mt-5"><button class="button is-primary is-rounded" @click="changeFormula()">Cập nhật</button></div>
|
||||
</template>
|
||||
<Modal @close="showmodal=undefined" v-bind="showmodal" v-if="showmodal" @label="changeLabel"></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
ScrollBox: ()=> import('@/components/datatable/ScrollBox')
|
||||
},
|
||||
props: ['pagename', 'field', 'filters', 'filterData', 'width'],
|
||||
data() {
|
||||
return {
|
||||
search: undefined,
|
||||
loading: false,
|
||||
fields: [],
|
||||
current: 1,
|
||||
currentPage: 1,
|
||||
timer: undefined,
|
||||
selectTab: undefined,
|
||||
radioBGcolor: undefined,
|
||||
radioColor: undefined,
|
||||
radioSize: undefined,
|
||||
selectAlign: undefined,
|
||||
radioAlign: undefined,
|
||||
radioWidth: undefined,
|
||||
minwidth: undefined,
|
||||
color: undefined,
|
||||
bgcolor: undefined,
|
||||
textsize: undefined,
|
||||
showPage: 1,
|
||||
perPage: 30,
|
||||
value1: undefined,
|
||||
value2: undefined,
|
||||
errors: [],
|
||||
label: undefined,
|
||||
radioType: undefined,
|
||||
selectUnit: undefined,
|
||||
radioTemplate: undefined,
|
||||
currentField: this.$copy(this.field),
|
||||
selectPlacement: undefined,
|
||||
radioTooltip: undefined,
|
||||
selectScheme: undefined,
|
||||
selectField: undefined,
|
||||
tags: [],
|
||||
formula: undefined,
|
||||
radioMaxWidth: undefined,
|
||||
maxwidth: undefined,
|
||||
bgcolorFilter: [{id: this.$id()}],
|
||||
colorFilter: [{id: this.$id()}],
|
||||
sizeFilter: [{id: this.$id()}],
|
||||
tabs: [{code: 'expression', name: 'Biểu thức'}, {code: 'script', name: 'Mã lệnh'}],
|
||||
tab: {},
|
||||
decimal: undefined,
|
||||
arr: [{id:this.$id(), operator: 'and'}],
|
||||
arr1: [{code: 'and', name: '&&'}, {code: 'or', name: 'or'}],
|
||||
arr2: [{code: '>', name: 'gt'}, {code: '>=', name: 'gte'}, {code: '=', name: 'e'},
|
||||
{code: '<=', name: 'lte'}, {code: '<', name: 'lt'}, {code: '<>', name: 'oth'}],
|
||||
showmodal: undefined,
|
||||
operator: [{code: '+', name: 'Cộng'}, {code: '-', name: 'Trừ'}, {code: '*', name: 'Nhân'}, {code: '/', name: 'Chia'}, {code: '>', name: 'Lớn hơn'},
|
||||
{code: '>=', name: 'Lớn hơn hoặc bằng'}, {code: '<', name: 'Nhỏ hơn'}, {code: '<=', name: 'Nhỏ hơn hoặc bằng'}, {code: '==', name: 'Bằng'},
|
||||
{code: '&&', name: 'Và'}, {code: '||', name: 'Hoặc'}, {code: 'iif', name: 'Điều kiện rẽ nhánh'}]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.label = this.$copy(this.field.label)
|
||||
this.getFields()
|
||||
this.selectTab = this.getMenu()[0]
|
||||
this.tab = this.tabs.find(v=>v.code==='expression')
|
||||
let found = this.filters.find(v=>v.name===this.field.name)
|
||||
if(found) this.arr = this.$copy(found.filter)
|
||||
this.getDisplay(this.field)
|
||||
},
|
||||
watch: {
|
||||
selectTab: function(newVal) {
|
||||
if(newVal? newVal.code==='value' : false) {
|
||||
if(this.$refs[this.field.name]) this.$refs[this.field.name].focus()
|
||||
}
|
||||
},
|
||||
field: function(newVal) {
|
||||
this.currentField = this.$copy(newVal)
|
||||
this.getDisplay(newVal)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pagedata: {
|
||||
get: function() {return this.$store.state[this.pagename]},
|
||||
set: function(val) {this.$store.commit('updateStore', {name: this.pagename, data: val})}
|
||||
},
|
||||
tablesetting: {
|
||||
get: function() {return this.$store.state.tablesetting},
|
||||
set: function(val) {this.$store.commit("updateTableSetting", {tablesetting: val})}
|
||||
},
|
||||
colorchoice: {
|
||||
get: function() {return this.$store.state.colorchoice},
|
||||
set: function(val) {this.$store.commit("updateColorChoice", {colorchoice: val})}
|
||||
},
|
||||
textalign: {
|
||||
get: function() {return this.$store.state.textalign},
|
||||
set: function(val) {this.$store.commit("updateTextAlign", {textalign: val})}
|
||||
},
|
||||
filterchoice: {
|
||||
get: function () {return this.$store.state.filterchoice},
|
||||
set: function (val) {this.$store.commit("updateFilterChoice", { filterchoice: val })}
|
||||
},
|
||||
datatype: {
|
||||
get: function() {return this.$store.state.datatype},
|
||||
set: function(val) {this.$store.commit("updateDataType", {datatype: val})}
|
||||
},
|
||||
moneyunit: {
|
||||
get: function() {return this.$store.state.moneyunit},
|
||||
set: function(val) {this.$store.commit("updateMoneyUnit", {moneyunit: val})}
|
||||
},
|
||||
menuaction: {
|
||||
get: function() {return this.$store.state.menuaction},
|
||||
set: function(val) {this.$store.commit("updateMenuAction", {menuaction: val})}
|
||||
},
|
||||
placement: {
|
||||
get: function() {return this.$store.state.placement},
|
||||
set: function(val) {this.$store.commit("updatePlacement", {placement: val})}
|
||||
},
|
||||
colorscheme: {
|
||||
get: function() {return this.$store.state.colorscheme},
|
||||
set: function(val) {this.$store.commit("updateColorScheme", {colorscheme: val})}
|
||||
},
|
||||
menuchoice: {
|
||||
get: function() {return this.$store.state.menuchoice},
|
||||
set: function(val) {this.$store.commit("updateMenuChoice", {menuchoice: val})}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addOperator(v) {
|
||||
let text = v.code==='iif'? 'a>b? c : d' : v.code
|
||||
this.formula = `${this.formula || ''} ${text}`
|
||||
},
|
||||
doSelect(row) {
|
||||
this.$emit('modalevent', {name: 'doselect', data: row[this.field.name]})
|
||||
},
|
||||
editLabel() {
|
||||
this.showmodal = {component: 'datatable/EditLabel', width: '500px', height: '300px', vbind: {label: this.label}}
|
||||
},
|
||||
addCondition() {
|
||||
this.arr.push({})
|
||||
},
|
||||
removeCondition(i) {
|
||||
this.$delete(this.arr, i)
|
||||
this.setFilter(this.field)
|
||||
},
|
||||
getMenu() {
|
||||
let field = this.getfield()
|
||||
let arr = field.disable? field.disable.split(',') : undefined
|
||||
return arr? this.menuchoice.filter(v=>arr.findIndex(x=>x===v.code) <0) : this.menuchoice
|
||||
},
|
||||
getFields() {
|
||||
this.fields = this.pagedata? this.$copy(this.pagedata.fields) : []
|
||||
this.fields.map(v=>v.caption = (v.label? v.label.indexOf('<')>=0 : false)? v.name : v.label)
|
||||
},
|
||||
getDisplay(field) {
|
||||
this.current = 1
|
||||
this.value1 = undefined
|
||||
this.value2 = undefined
|
||||
this.radioType = this.datatype.find(v=>v.code===field.format)
|
||||
if(field.format==='number') this.selectUnit = this.moneyunit.find(v=>v.detail===field.unit)
|
||||
this.bgcolor = undefined
|
||||
this.radioBGcolor = this.colorchoice.find(v=>v.code==='none')
|
||||
this.color = undefined
|
||||
this.radioColor = this.colorchoice.find(v=>v.code==='none')
|
||||
this.textsize = undefined
|
||||
this.radioSize = this.colorchoice.find(v=>v.code==='none')
|
||||
this.minwidth = undefined
|
||||
this.radioWidth = this.colorchoice.find(v=>v.code==='none')
|
||||
this.radioMaxWidth = this.colorchoice.find(v=>v.code==='none')
|
||||
this.maxwidth = undefined
|
||||
this.selectAlign = undefined
|
||||
this.radioAlign = this.colorchoice.find(v=>v.code==='none')
|
||||
this.radioTemplate = this.colorchoice.find(v=>v.code=== (field.template? 'option' : 'none'))
|
||||
this.selectPlacement = this.placement.find(v=>v.code==='is-right')
|
||||
this.selectScheme = this.colorscheme.find(v=>v.code==='is-primary')
|
||||
this.radioTooltip = this.colorchoice.find(v=>v.code==='none')
|
||||
this.selectField = undefined
|
||||
this.tags = field.tags? field.tags.map(v=>this.fields.find(x=>x.name===v)) : []
|
||||
this.formula = field.formula? field.formula : undefined
|
||||
this.decimal = field.decimal
|
||||
let shortmenu = this.menuchoice.filter(x=>field.format==='number'? (field.formula? true : x.code!=='formula')
|
||||
: !['filter','formula'].find(y=>y===x.code))
|
||||
this.selectTab = shortmenu.find(v=>this.selectTab.code===v.code)? this.selectTab : this.menuchoice.find(v=>v.code==='value')
|
||||
this.search = undefined
|
||||
if(this.selectTab.code==='value') {
|
||||
let self = this
|
||||
setTimeout(function() {self.$refs[field.name]? self.$refs[field.name].focus() : false}, 50)
|
||||
}
|
||||
|
||||
this.bgcolorFilter = [{id: this.$id()}]
|
||||
if(field.bgcolor) {
|
||||
if(Array.isArray(field.bgcolor)) {
|
||||
this.radioBGcolor = this.colorchoice.find(v=>v.code==='condition')
|
||||
this.bgcolorFilter = this.$copy(field.bgcolor)
|
||||
} else {
|
||||
this.radioBGcolor = this.colorchoice.find(v=>v.code==='option')
|
||||
this.bgcolor = field.bgcolor
|
||||
}
|
||||
}
|
||||
|
||||
this.colorFilter = [{id: this.$id()}]
|
||||
if(field.color) {
|
||||
if(Array.isArray(field.color)) {
|
||||
this.radioColor = this.colorchoice.find(v=>v.code==='condition')
|
||||
this.colorFilter = this.$copy(field.color)
|
||||
} else {
|
||||
this.radioColor = this.colorchoice.find(v=>v.code==='option')
|
||||
this.color = field.color
|
||||
}
|
||||
}
|
||||
this.sizeFilter = [{id: this.$id()}]
|
||||
if(field.textsize) {
|
||||
if(Array.isArray(field.textsize)) {
|
||||
this.radioSize = this.colorchoice.find(v=>v.code==='condition')
|
||||
this.sizeFilter = field.textsize
|
||||
} else {
|
||||
this.radioSize = this.colorchoice.find(v=>v.code==='option')
|
||||
this.textsize = field.textsize
|
||||
}
|
||||
}
|
||||
|
||||
if(field.textalign) {
|
||||
this.radioAlign = this.colorchoice.find(v=>v.code==='option')
|
||||
this.selectAlign = this.textalign.find(v=>v.code===field.textalign)
|
||||
}
|
||||
|
||||
if(field.minwidth) {
|
||||
this.radioWidth = this.colorchoice.find(v=>v.code==='option')
|
||||
this.minwidth = field.minwidth
|
||||
}
|
||||
|
||||
if(field.maxwidth) {
|
||||
this.radioMaxWidth = this.colorchoice.find(v=>v.code==='option')
|
||||
this.maxwidth = field.maxwidth
|
||||
}
|
||||
|
||||
if(field.tooltip) {
|
||||
this.radioTooltip = this.colorchoice.find(v=>v.code==='option')
|
||||
this.selectPlacement = this.placement.find(v=>v.code===field.tooltip.placement)
|
||||
this.selectField = this.pagedata.fields.find(v=>v.name===field.tooltip.field)
|
||||
this.selectScheme = this.colorscheme.find(v=>v.code===field.tooltip.type)
|
||||
}
|
||||
},
|
||||
moveLeft() {
|
||||
let i = this.pagedata.fields.findIndex(v=>v.name===this.field.name)
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = i-1>=0? i - 1 : copy.length - 1
|
||||
copy = this.$arrayMove(copy, i, idx)
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "update", data: {fields: copy}})
|
||||
this.$emit('changepos')
|
||||
},
|
||||
moveRight() {
|
||||
let i = this.pagedata.fields.findIndex(v=>v.name===this.field.name)
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = copy.length-1>i? i + 1 : 0
|
||||
copy = this.$arrayMove(copy, i, idx)
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "update", data: {fields: copy}})
|
||||
this.$emit('changepos')
|
||||
},
|
||||
doRemove() {
|
||||
let field = this.getfield()
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = copy.findIndex(v=>v.name===field.name)
|
||||
this.$delete(copy, idx)
|
||||
this.$store.commit("updateState", {name: this.pagename, key: "update", data: {fields: copy}})
|
||||
this.$emit('close')
|
||||
},
|
||||
startSearch(event) {
|
||||
if (this.timer) clearTimeout(this.timer)
|
||||
let self = this
|
||||
this.timer = setTimeout(() => { self.$emit('modalevent', {name: 'dosearch', data: event.srcElement.value})}, 100)
|
||||
},
|
||||
pressEnter(event) {
|
||||
if(!this.$empty(event.srcElement.value) && this.filterData.length>0) this.$emit('modalevent', {name: 'doselect', data: this.filterData[0][this.field.name]})
|
||||
},
|
||||
getfield() {
|
||||
return this.currentField
|
||||
},
|
||||
changeColor() {
|
||||
let copy = this.getfield()
|
||||
copy.color = this.radioColor.code==='none'? undefined : this.color
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeBGColor() {
|
||||
let copy = this.getfield()
|
||||
copy.bgcolor = this.radioBGcolor.code==='none'? undefined : this.bgcolor
|
||||
this.updateFields(copy)
|
||||
},
|
||||
checkSelected() {
|
||||
let found = this.filters.find(v=>v.name===this.field.name)
|
||||
return found? found.select : undefined
|
||||
},
|
||||
doAdvance(name) {
|
||||
let field = this.getfield()
|
||||
let script = (field[name]? Array.isArray(field[name]) : false)? JSON.stringify(field[name]) : undefined
|
||||
this.$emit('modalevent', {name: 'showsidebar', data: {field: field, name: name, script: script,
|
||||
radio: name==='bgcolor'? this.radioBGcolor : (name==='color'? this.radioColor : this.radioSize) }})
|
||||
},
|
||||
changeSize() {
|
||||
let copy = this.getfield()
|
||||
if(this.radioSize.code==='option' && !this.$isNumber(this.textsize)) return
|
||||
copy.textsize = this.radioSize.code==='none'? undefined : this.textsize
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeAlign() {
|
||||
let copy = this.getfield()
|
||||
copy.textalign = this.radioAlign.code==='none'? undefined : (this.selectAlign? this.selectAlign.code : undefined)
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeWidth() {
|
||||
let copy = this.getfield()
|
||||
if(!this.$isNumber(this.minwidth)) return
|
||||
copy.minwidth = this.radioWidth.code==='none'? undefined : this.minwidth
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeMaxWidth() {
|
||||
let copy = this.getfield()
|
||||
if(!this.$isNumber(this.maxwidth)) return
|
||||
copy.maxwidth = this.radioMaxWidth.code==='none'? undefined : this.maxwidth
|
||||
this.updateFields(copy)
|
||||
},
|
||||
setFilter(field) {
|
||||
let arr = this.arr.map(v=>{return {
|
||||
condition: v.condition, value: v.value, operator: v.operator
|
||||
}})
|
||||
let text = ''
|
||||
arr.map((y,k)=>{
|
||||
text += `${k>0? (arr[k-1].operator==='and'? ' &' : ' ||') : ''} ${y.condition} ${this.$numtoString(y.value)}`
|
||||
})
|
||||
let filter = {name: field.name, label: field.label, filter: arr, condition: text}
|
||||
this.$emit('modalevent', {name: 'setfilter', data: filter})
|
||||
},
|
||||
copyContent(value) {
|
||||
this.$copyToClipboard(value)
|
||||
},
|
||||
changeLabel(value) {
|
||||
if(this.$empty(value)) return
|
||||
if(this.label!==value) this.label = value
|
||||
let copy = this.getfield()
|
||||
copy.label = value
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeUnit() {
|
||||
if(this.$empty(this.selectUnit)) return
|
||||
let copy = this.getfield()
|
||||
copy.unit = this.selectUnit.detail
|
||||
this.updateFields(copy)
|
||||
setTimeout(()=> this.menuaction = {pagename: this.pagename, name: 'reload-data', time: new Date()}, 1000)
|
||||
},
|
||||
changeTemplate(value) {
|
||||
if(this.radioTemplate.code==='none') value = undefined
|
||||
else if(this.$empty(value)) return
|
||||
let copy = this.getfield()
|
||||
copy.template = value
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeDecimal(evt) {
|
||||
if(!this.$isNumber(evt)) return
|
||||
let copy = this.getfield()
|
||||
copy.decimal = evt
|
||||
this.updateFields(copy)
|
||||
setTimeout(()=>this.menuaction = {pagename: this.pagename, name: 'reload-data', time: new Date()}, 1000)
|
||||
},
|
||||
checkFilter() {
|
||||
if(!this.pagedata) return
|
||||
let field = this.getfield()
|
||||
let found = this.pagedata.filters? this.pagedata.filters.find(v=>v.name===field.name) : undefined
|
||||
return found? (found.select || found.filter) : false
|
||||
},
|
||||
changeTooltip() {
|
||||
let copy = this.getfield()
|
||||
if(this.radioTooltip? this.radioTooltip.code==='none' : false) copy.tooltip = undefined
|
||||
else if(!(this.selectField && this.selectPlacement && this.selectScheme)) return
|
||||
else {copy.tooltip = {field: this.selectField.name, placement: this.selectPlacement.code, type: this.selectScheme.code}}
|
||||
this.updateFields(copy)
|
||||
},
|
||||
changeFormula() {
|
||||
let field = this.getfield()
|
||||
//check formula
|
||||
this.errors = []
|
||||
let val = this.$copy(this.formula)
|
||||
this.tags.forEach(v => {
|
||||
let myRegExp = new RegExp(v.name, 'g')
|
||||
val = val.replace(myRegExp, Math.random())
|
||||
})
|
||||
try {
|
||||
let value = this.$calc(val)
|
||||
if(isNaN(value) || value===Number.POSITIVE_INFINITY || value===Number.NEGATIVE_INFINITY) {
|
||||
this.errors.push({name: 'formula', message: 'Công thức không hợp lệ'})
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
this.errors.push({name: 'formula', message: 'Công thức không hợp lệ'})
|
||||
}
|
||||
if(this.errors.length>0) return
|
||||
let copyField = this.$copy(field)
|
||||
copyField.formula = this.formula.trim()
|
||||
copyField.tags = this.tags.map(v=>v.name)
|
||||
copyField.level = Math.max(...this.tags.map(v=>v.level? v.level : 0)) + 1
|
||||
this.updateFields(copyField, 'fields')
|
||||
this.$emit('close')
|
||||
},
|
||||
updateFields(field, type) {
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let idx = copy.findIndex(v=>v.name===field.name)
|
||||
copy[idx] = this.$copy(field)
|
||||
if(type==='fields') this.$store.commit("updateState", {name: this.pagename, key: "update", data: {fields: copy, data: this.pagedata.data}})
|
||||
else {
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'fields', data: copy})
|
||||
if(this.field.inputitem) this.$updateinput(this.pagename)
|
||||
setTimeout(()=>this.$store.commit("updateState", {name: this.pagename, key: "update", data: {columns: copy}}), 100)
|
||||
}
|
||||
},
|
||||
doFocus() {
|
||||
if(this.selectTab.code!=='value') this.selectTab = this.menuchoice.find(v=>v.code==='value')
|
||||
},
|
||||
hideField() {
|
||||
let field = this.getfield()
|
||||
let copy = this.$copy(this.pagedata.fields)
|
||||
let found = copy.find(v=>v.name===field.name)
|
||||
found.show = false
|
||||
this.$store.commit('updateState', {name: this.pagename, key: 'update', data: {fields: copy}})
|
||||
this.$emit('close')
|
||||
},
|
||||
checkValid() {
|
||||
let error
|
||||
this.arr.map((v,i) => {
|
||||
if(this.$empty(v.condition)) error = 'Chưa chọn điều kiện'
|
||||
if(this.arr.length>=2 && i===0 && this.$empty(v.operator)) error = 'Chưa chọn kết hợp'
|
||||
if(!this.$isNumber(v.value)) error = 'Giá trị phải là số'
|
||||
if(error) v.error = error
|
||||
else {
|
||||
v.error = undefined
|
||||
v.value = this.$numtoString(v.value)
|
||||
}
|
||||
})
|
||||
this.arr = this.$copy(this.arr)
|
||||
if(!error) this.setFilter(this.field)
|
||||
},
|
||||
doOption() {
|
||||
setTimeout(()=> this.checkValid(), 100)
|
||||
},
|
||||
resizeWidth(minus) {
|
||||
let val = this.maxwidth || this.minwidth || this.width
|
||||
val = minus? parseInt(val - 0.1* val) : parseInt(val + 0.1* val)
|
||||
if(val>1000) return this.$buefy.toast.open('Độ rộng cột lớn hơn giới hạn cho phép')
|
||||
else if(val<20) return this.$buefy.toast.open('Độ rộng cột nhỏ hơn giới hạn cho phép')
|
||||
this.radioMaxWidth = this.colorchoice.find(v=>v.code==='option')
|
||||
this.radioWidth = this.colorchoice.find(v=>v.code==='option')
|
||||
this.maxwidth = val
|
||||
this.currentField.maxwidth = val
|
||||
this.minwidth = val
|
||||
this.currentField.minwidth = val
|
||||
this.updateFields(this.currentField)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user