table 表格组件封装
e-table-list
<template>
<el-table
ref="table"
v-loading="loading"
element-loading-text="Loading"
:data="tableData"
:row-key="rowKey"
border
fit
highlight-current-row
tooltip-effect="dark"
style="width: 100%"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
>
<!--多选列-->
<el-table-column
v-if="indexShow"
type="index"
align="center"
width="50">
</el-table-column>
<el-table-column
v-if="selectionShow"
type="selection"
width="50"
align="center"
highlight-current-row
fixed
:reserve-selection="true"
></el-table-column>
<el-table-column
v-for="(item, index) in tableLabel"
:width="item.width ? item.width : ''"
:fixed="item.fixed ? item.fixed : false"
:type="item.type ? item.type : ''"
:key="index"
:align="item.align"
:label="item.label"
:prop="item.param"
:sortable="item.sortable ? 'custom' : false"
v-show="index==1"
>
<template slot-scope="scope">
<slot v-if="item.slot" v-bind:scope="scope" :name="item.slot"></slot>
<div v-html="item.render(scope.row)" v-else-if="item.render">
</div>
<span v-else>{{ scope.row[item.param] }} {{ item.type }}</span>
</template>
</el-table-column>
<el-table-column
v-if="tableOption.label"
:width="tableOption.width"
:label="tableOption.label"
align="center"
class-name="small-padding fixed-width"
:fixed="tableOption.fixed ? tableOption.fixed : false"
>
<template slot-scope="scope">
<el-button
v-for="(item, index) in tableOption.options"
:key="index"
:type="item.type"
:icon="item.icon"
@click="handleButton(item.methods, scope.row, scope.row)"
size="mini"
>
{{ item.label }}
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
props: {
loading: {
type: Boolean,
default: false,
},
tableData: {
type: Array,
default: () => {
return [];
},
},
tableLabel: {
type: Array,
default: () => {
return [];
},
},
tableOption: {
type: Object,
default: () => {
return {};
},
},
indexShow:{
type: Boolean,
default: false,
},
selectionShow:{
type: Boolean,
default: false,
},
radioShow:{
type:Boolean,
default: false
},
rowKey:{
type:String,
default:''
}
},
components: {},
methods: {
handleButton(methods, row, index) {
// 按钮事件
this.$emit("handleButton", { methods: methods, row: row, index: index });
},
handleSortChange(val) {
// 排序
this.$emit("handleSortChange", val);
},
handleSelectionChange(val) {
this.$emit("handleSelectionChange", val);
}
},
};
</script>
<style>
</style>
使用
search 表格组件分装
e-search
<!-- 搜索组件 -->
<template>
<div class="content">
<template v-for="(item, index) in fieldList">
<div
v-show="icon === 'close' ? index < count : true"
:key="index"
>
<div class="item-style">
<span class="label-style" :style="{width: width.labelWidth + 'px'}">{{ item.label }}</span>
<!-- 普通输入框 -->
<el-input
v-if="item.type === 'input'"
v-model.trim="defaultData[item.value]"
:size="size"
:style="{width: width.itemWidth + 'px'}"
:type="item.type"
:disabled="item.disabled"
:placeholder="getPlaceholder(item)"
@keyup.enter.native="handleFilter"
@blur="handleEvent($event, item.value)"
/>
<!-- 日期/时间 -->
<el-date-picker
v-if="item.type === 'date'"
v-model="defaultData[item.value]"
:size="size"
:style="{width: width.itemWidth + 'px'}"
:type="item.dateType"
:picker-options="item.TimePickerOptions"
:clearable="item.clearable"
:disabled="item.disabled"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd HH:MM:SS"
:placeholder="getPlaceholder(item)"
@change="handleEvent($event, item.value, 'change')"
/>
<!-- 选择框 -->
<el-select
v-if="item.type === 'select'"
v-model="defaultData[item.value]"
:size="size"
:style="{width: width.itemWidth + 'px'}"
:disabled="item.disabled"
:clearable="item.clearable"
:filterable="item.filterable"
:multiple="item.multiple"
:placeholder="getPlaceholder(item)"
@change="handleEvent($event, item.value, 'change')"
>
<el-option
v-for="childItem in listTypeInfo[item.list]"
:key="childItem.id"
:label="childItem.name"
:value="childItem.id"
:disabled="childItem.disabled"
/>
</el-select>
<!-- 计数器 -->
<el-input-number
v-if="item.type === 'inputNumber'"
v-model="defaultData[item.value]"
:size="size"
:style="{width: width.itemWidth + 'px'}"
:min="item.min"
:max="item.max"
@change="handleEvent($event, item.value, 'change')"
/>
</div>
</div>
</template>
<div
v-if="!btnHidden && fieldList.length !== 0"
class="btn-style"
>
<el-button
:type="btnStyle[0].type"
:size="size"
:plain="btnStyle[0].plain"
:round="btnStyle[0].round"
:icon="btnStyle[0].icon"
:disabled="btnStyle[0].disabled"
@click="handleFilter"
>
{{ btnStyle[0].text }}
</el-button>
<el-button
:type="btnStyle[1].type"
:size="size"
:plain="btnStyle[1].plain"
:round="btnStyle[1].round"
:disabled="btnStyle[1].disabled"
:icon="btnStyle[1].icon"
@click="handleReset"
>
{{ btnStyle[1].text }}
</el-button>
</div>
<el-button
v-if="!btnHidden && fieldList.length > count"
type="text"
@click="icon === 'open' ? icon = 'close' : icon = 'open'"
style="margin-left: 6px;"
>{{ icon === 'open' ? '收起' : '展开' }}
<i :class="icon === 'open' ? 'el-icon-caret-top' : 'el-icon-caret-bottom'" />
</el-button>
</div>
</template>
<script>
export default {
name: 'ESearch',
props: {
/**字段默认数据 */
data: {
type: Object,
default: () => {},
required: true
},
/**字段配置项 */
fieldList: {
type: Array,
default: () => [],
required: true
},
/**相关的列表 */
listTypeInfo: {
type: Object,
default: () => {}
},
/**按钮区域是否隐藏 */
btnHidden: {
type: Boolean,
default: false
},
/**组件尺寸 */
size: {
type: String,
default: 'mini'
},
/**默认搜索数 */
count: {
type: Number,
default: 4
},
/**组件及label宽度 */
width: {
type: Object,
default: () => ({
labelWidth: 110,
itemWidth: 220
})
},
/**按钮配置 */
btnStyle: {
type: Array,
default: () => [
{ icon: null, text: '搜索', disabled: false, type: 'primary', plain: false, round: false },
{ icon: null, text: '重置', disabled: false, type: null, plain: false, round: false }
]
}
},
data: () => ({
defaultData: {},
icon: 'close'
}),
mounted () {
/**
* 子组件无法直接修改父组件传递过来的值
* 于是将父组件传递的值首先赋值给 defaultData
* 在搜索条件中同样使用 defaultData
* 永远保持 props 传递的 data 纯洁度
*/
this.defaultData = {...this.data}
},
methods: {
/**
* @func 占位符显示
* @param {Object} row
* @desc 📝
*/
getPlaceholder (row) {
let placeholder
if (row.type === 'input') {
placeholder = '请输入' + row.label
} else if (row.type === 'select' || row.type === 'time' || row.type === 'date') {
placeholder = '请选择' + row.label
} else {
placeholder = row.label
}
return placeholder
},
/**
* @func 事件处理
* @desc 📝
*/
handleEvent (event, val, change) {
let obj = {
value: change === 'change' ? event : event.target.value,
label: val
}
this.$emit('handleEvent', obj)
},
/**
* @func 搜索
* @desc 📝
*/
handleFilter () {
this.$emit('handleFilter', this.defaultData)
},
/**
* @func 重置
* @desc 📝
*/
handleReset () {
this.defaultData = {...this.data}
this.$emit('handleReset', this.defaultData)
}
}
}
</script>
<style lang="scss" scoped>
.content {
display: flex;
flex-wrap: wrap;
position: relative;
}
.content .item-style {
margin: 6px auto;
line-height: 1;
}
.content .item-style .label-style {
display: inline-block;
justify-self: end;
font-size: 13px;
white-space: nowrap;
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
text-align: right;
margin-right: 12px;
color: #222222;
}
.btn-style {
margin: 6px 0 6px auto;
}
</style>
使用
dialog 弹框
<template>
<div>
<el-dialog
class="comn_dialog"
:title="dialogTitle"
:visible.sync="visible"
:width="popupWidth"
:top="popupTop"
@close="Cancel"
>
<slot>
<p>弹窗内容自定义</p>
</slot>
<span slot="footer" class="dialog-footer">
<el-button @click="Cancel">取 消</el-button>
<el-button type="primary" @click="Save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
dialogTitle: {
type: String,
default: "标题"
},
centerDialogVisible: {
type: Boolean,
default() {
return false;
}
},
popupWidth: {
type: String,
default() {
return "430px";
}
},
popupTop: {
type: String,
default() {
return "23vh";
}
}
},
computed: {
visible: {
get() {
return this.centerDialogVisible;
},
set(val) { // 当visible改变的时候,触发父组件的 updateVisible方法,在该方法中更改传入子组件的 centerDialogVisible的值
this.$emit("updateVisible", val);
}
}
},
methods: {
Cancel() {
this.$emit("resetPopupData");
},
Save() {
this.$emit("submitPopupData");
}
}
};
</script>
<style lang="scss">
.comn_dialog {
.el-dialog__header {
padding: 8px 0px 3px 8px;
border-bottom: 1px solid #e7e6e6;
box-shadow: 0px 4px 4px -4px #d1d0d0;
}
.el-dialog__title {
font-size: 16px;
letter-spacing: 1px;
color: #464646;
font-weight: bolder;
}
.el-dialog__footer {
padding: 0px 20px 20px 0px;
}
.el-dialog__headerbtn {
position: static; // 兼容IE11 ,取消原有的position定位
}
.el-dialog__close {
// color: $header_bg;
font-size: 20px;
font-weight: bolder;
position: absolute;
top: 8px;
right: 8px;
&::after {
content: '';
// border: 2px solid $header_bg;
width: 20px;
height: 20px;
border-radius: 25px;
position: absolute;
right: -2px;
top: -3px;
}
}
.el-dialog__body {
padding: 20px;
}
.dialog-footer{
display: flex;
justify-content: center;
align-items: center;
}
}
</style>