sh_real_name_system_web/src/components/TableModel/index.vue

630 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 表格公共组件 -->
<div>
<!-- 表单搜索 -->
<el-form
:inline="true"
size="small"
ref="queryFormRef"
:rules="formRules"
v-show="showSearch"
:model="queryParams"
label-width="auto"
class="query-form"
>
<el-form-item
:key="v"
:prop="item.f_model"
v-for="(item, v) in formLabel"
:label="item.isShow ? item.f_label : ''"
>
<el-input
clearable
:maxlength="item.f_max || 50"
v-if="item.f_type === 'ipt'"
v-model.trim="queryParams[item.f_model]"
:placeholder="`请输入${item.f_label}`"
:style="{ width: item.f_width || '180px' }"
/>
<el-select
clearable
filterable
v-if="item.f_type === 'sel'"
v-model="queryParams[item.f_model]"
:placeholder="`请选择${item.f_label}`"
:style="{ width: item.f_width || '180px' }"
@change="handleSelChange($event, item.f_model)"
>
<el-option
:key="v"
:label="sel.label"
:value="sel.value"
v-for="(sel, v) in item.f_selList"
/>
</el-select>
<el-cascader
clearable
style="width: 180px"
:show-all-levels="false"
:props="item.optionProps"
:options="item.f_selList"
v-if="item.f_type === 'selCasAdd'"
v-model="queryParams[item.f_model]"
@change="
handleCasAdd(
$event,
item.f_model,
cascadeFunc,
extraTableProp,
)
"
/>
<el-cascader
style="width: 180px"
:show-all-levels="false"
:options="item.f_selList"
:props="item.optionProps"
v-if="item.f_type === 'selCas'"
v-model="queryParams[item.f_model]"
@change="handleCas($event, item.f_model)"
/>
<el-date-picker
type="date"
:style="{ width: item.f_width || '240px' }"
value-format="yyyy-MM-dd"
v-if="item.f_type === 'date'"
v-model="queryParams[item.f_model]"
:placeholder="`请选择${item.f_label}`"
/>
<el-date-picker
type="daterange"
:style="{ width: item.f_width || '240px' }"
range-separator="至"
value-format="yyyy-MM-dd"
start-placeholder="开始日期"
end-placeholder="结束日期"
v-if="item.f_type === 'dateRange'"
v-model="queryParams[item.f_model]"
@change="onChangeTime($event, item.dateType)"
:picker-options="pickerOptions"
/>
<el-input-number
:min="0"
style="width: 240px"
v-if="item.f_type === 'num'"
v-model="queryParams[item.f_model]"
/>
</el-form-item>
<el-form-item v-if="showBtnCrews">
<el-button
size="mini"
type="primary"
icon="el-icon-search"
@click="handleQuery"
>
查询
</el-button>
<el-button
plain
size="mini"
type="warning"
icon="el-icon-refresh"
@click="resetQuery"
>
重置
</el-button>
<slot name="btn" :queryParams="queryParams"></slot>
</el-form-item>
<slot name="left-tip"> </slot>
</el-form>
<!-- 按钮集群 -->
<el-row class="btn-container">
<ToolbarModel
v-if="showRightTools"
:columns="columnCheckList"
@queryTable="getTableList"
:showSearch.sync="showSearch"
:handleShow.sync="handleShow"
:indexNumShow.sync="indexNumShow"
:selectionShow.sync="selectionShow"
:isSelectShow="isSelectShow"
:showOperation="showOperation"
/>
</el-row>
<!-- 表格 -->
<el-table
border
ref="tableRef"
:data="tableList"
style="width: 100%"
v-loading="loading"
select-on-indeterminate
@selection-change="handleSelectionChange"
>
<el-table-column
width="45"
align="center"
type="selection"
:selectable="selectable"
v-if="selectionShow && isSelectShow"
/>
<el-table-column
fixed
width="55"
label="序号"
type="index"
align="center"
:index="
indexContinuation(queryParams.pageNum, queryParams.pageSize)
"
v-if="indexNumShow && isIndexShow"
/>
<el-table-column
:key="v"
align="center"
:label="item.t_label"
:prop="item.t_props"
:width="item.t_width"
show-overflow-tooltip
v-for="(item, v) in tableColumCheckProps"
>
<template slot-scope="scope">
<!-- 判断当前列数据是否需要使用插槽的数据 -->
<template v-if="item.t_slot">
<slot :data="scope.row" :name="item.t_slot"></slot>
</template>
<template v-else>
{{ scope.row[item.t_props] || '-' }}
</template>
</template>
</el-table-column>
<el-table-column
align="center"
label="操作"
:min-width="dynamicWidth"
:show-overflow-tooltip="false"
v-if="handleShow && showOperation"
>
<template slot-scope="{ row }">
<div class="optionDivRef">
<slot :data="row" name="handle">-</slot>
</div>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
:total="total"
:pageSizes="pageSizes"
@pagination="getTableList"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
/>
</div>
</template>
<script>
import ToolbarModel from '../ToolbarModel'
export default {
components: { ToolbarModel },
props: {
// 表单查询条件
formLabel: {
type: Array,
default: () => [],
},
// 列表请求接口
requestApi: {
type: Function,
default: () => function () {},
},
// 列表配置项
columnsList: {
type: Array,
default: () => [],
},
// 传递的额外参数
sendParams: {
type: Object,
default: () => null,
},
// 是否显示查询按钮 默认显示
showBtnCrews: {
type: Boolean,
default: true,
},
// 级联选择
cascadeFunc: {
type: Function,
default: () => null,
},
// 级联选择 额外参数
extraTableProp: {
type: Object,
default: () => null,
},
// 是否显示操作列 默认不显示
showOperation: {
type: Boolean,
default: false,
},
// 是否显示右侧工具栏 默认不显示
showRightTools: {
type: Boolean,
default: false,
},
// 复选框是否勾选
selectable: {
type: Function,
default: () => {
return true
},
},
// 是否显示复选框 由父组件传递 默认不显示
isSelectShow: {
type: Boolean,
default: false,
},
// 测试时使用的数据源
testTableList: {
type: Array,
default: () => [],
},
// 是否显示当天日期
isCurrentDate: {
type: Boolean,
default: false,
},
// 是否只可选择一个月的范围
isOneMonth: {
type: Boolean,
default: false,
},
// 是否显示序号
isIndexShow: {
type: Boolean,
default: true,
},
// 分页大小
pageSizes: {
type: Array,
default: () => [10, 20, 30, 50],
},
},
computed: {
/* 根据操作栏控制表头是否显示 */
tableColumCheckProps() {
return this.columnCheckList.filter((e) => {
return e.checked != false
})
},
},
watch: {
columnsList: {
handler(nv, ov) {
if (nv !== ov) {
this.columnsList = nv
this.columnCheckList = this.columnsList.map((e) => {
this.$set(e, 'checked', true)
return e
})
}
},
deep: true,
},
},
data() {
return {
// 表单校验
formRules: {},
loading: false,
// 列表接口查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
},
// 列表数据源
tableList: [],
// 选中数据
selectedData: [],
// 列表数据条数
total: 0,
// 搜索区域是否隐藏
showSearch: true,
// 是否显示复选框
selectionShow: true,
// 是否显示序号
indexNumShow: true,
// 是否显示操作列
handleShow: true,
// 列表每列 label
columnCheckList: [],
// 操作列最小宽度
dynamicWidth: 0,
// 自增id
idCount: 1,
// 日期查询条件 字段名称
typeList: [],
// 日期选择器配置
pickerOptions: {},
}
},
created() {
this.columnCheckList = this.columnsList.map((e) => {
this.$set(e, 'checked', true)
return e
})
/* 生成查询参数 */
this.formLabel.map((e) => {
if (e.f_type === 'dateRange') {
this.$set(this.queryParams, e.dateType[0], '')
this.$set(this.queryParams, e.dateType[1], '')
this.typeList = e.dateType
if (this.isOneMonth) {
this.pickerOptions = {
disabledDate: (time) => {
// 禁用今天之后的日期
return time.getTime() > Date.now()
},
onPick: ({ maxDate, minDate }) => {
// 当选择第一个日期后,设置第二个日期的可选范围
this.pickerOptions.minDate = minDate
if (minDate) {
const maxRangeDate = new Date(minDate)
maxRangeDate.setMonth(minDate.getMonth() + 1)
this.pickerOptions.maxDate = maxRangeDate
} else {
this.pickerOptions.maxDate = null
}
},
}
}
} else {
this.$set(this.queryParams, e.f_model, '')
}
})
if (this.sendParams !== null) {
for (let key in this.sendParams) {
this.$set(this.queryParams, key, this.sendParams[key])
}
}
this.getTableList()
},
updated() {
// 更新时重新计算操作列需要的最小宽度 确保展示无误
this.dynamicWidth = this.getOperatorWidth()
},
methods: {
/** 获取列表数据 */
async getTableList() {
try {
if (
this.queryParams.time &&
this.queryParams.time.length !== 0
) {
this.queryParams[this.typeList[0]] =
this.queryParams.time[0]
this.queryParams[this.typeList[1]] =
this.queryParams.time[1]
}
const params = { ...this.queryParams }
const queryParams = JSON.parse(JSON.stringify(params))
delete queryParams.time // 剔除无关参数
// console.log(
// `%c🔍 列表查询入参 %c`,
// 'background: linear-gradient(90deg, #FF6B6B, #4ECDC4); color: white; padding: 5px 10px; border-radius: 5px; font-weight: bold;',
// '',
// queryParams,
// )
this.loading = true
const res = await this.requestApi(queryParams)
if (res.code === 200) {
this.tableList = res.rows
this.total = res.total
}
this.loading = false
} catch (error) {
this.loading = false
this.tableList = this.testTableList
}
},
/** 查询按钮 */
handleQuery() {
this.getTableList()
},
// 根据传递的参数进行查询
getTableListByParams(data) {
Object.assign(this.queryParams, data)
this.getTableList()
},
/** 重置按钮 */
resetQuery() {
this.$refs.queryFormRef.resetFields()
if (this.typeList.length > 1) {
if (this.isCurrentDate) {
this.queryParams[this.typeList[0]] = new Date()
.toISOString()
.split('T')[0]
this.queryParams[this.typeList[1]] = new Date()
.toISOString()
.split('T')[0]
this.queryParams.time = [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
]
} else {
this.queryParams[this.typeList[0]] = ''
this.queryParams[this.typeList[1]] = ''
this.queryParams.time = []
}
} else {
this.queryParams[this.typeList[0]] = ''
}
this.queryParams.pageNum = 1
this.queryParams.pageSize = 10
this.getTableList()
},
/** 级联选择 */
handleCas(e, val) {
this.queryParams[val] = e[e.length - 1]
},
/** 级联选择只选最后一级 */
handleCasAdd(e, val, func, prop) {
if (e.length !== 0) {
this.queryParams[val] = e[e.length - 1]
let setObj = {}
// 合并
if (prop) {
Object.assign(setObj, prop)
}
// 设置id自增
this.$set(setObj, 'id', this.idCount)
this.idCount++
// 获取单位
func({
id: e[e.length - 1],
})
.then((res) => {
this.$set(setObj, 'name', res.data.parentName)
this.$set(setObj, 'unitName', res.data.unitName)
this.$set(setObj, 'typeName', res.data.name)
})
.catch((err) => {})
for (let key in this.queryParams) {
this.$set(setObj, key, this.queryParams[key])
}
this.tableList.unshift(setObj)
console.log(this.tableList)
}
},
/** 动态设置操作列的列宽 */
getOperatorWidth() {
const operatorColumn =
document.getElementsByClassName('optionDivRef')
// 默认宽度
let width = 100
// 内间距
let paddingSpacing = 0
// 按钮数量
let buttonCount = 0
if (operatorColumn.length > 0) {
Array.prototype.forEach.call(operatorColumn, function (item) {
// 最宽的宽度
width = width > item.offsetWidth ? width : item.offsetWidth
const buttons = item.getElementsByClassName('el-button')
buttonCount = buttons.length
buttonCount =
buttonCount > buttons.length
? buttonCount
: buttons.length
})
return width + 10
}
},
queryTableList(params) {
Object.assign(this.queryParams, params)
this.getTableList()
},
handleSelectionChange(e) {
this.selectedData = e
this.$emit('selection-change', e)
},
/* 时间change事件 */
onChangeTime(e, type) {
if (this.isOneMonth) {
if (e && e.length === 2) {
const [start, end] = e
const startDate = new Date(start)
const endDate = new Date(end)
// 计算两个日期之间的天数差
const diffTime = Math.abs(endDate - startDate)
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
// 如果超过31天自动调整结束日期
if (diffDays > 31) {
const newEndDate = new Date(startDate)
newEndDate.setDate(startDate.getDate() + 31)
this.queryParams.time = [
start,
newEndDate.toISOString().split('T')[0],
]
this.$message.warning(
'选择的时间范围超过31天查询将会缓慢已自动调整',
)
}
}
} else {
const [_1, _2] = type
const [_time1, _time2] = e
if (e.length > 0) {
this.queryParams[_1] = _time1
this.queryParams[_2] = _time2
}
}
},
// 选择change事件
handleSelChange(e, val) {
this.$emit('sel-change', e, val)
},
},
watch: {
sendParams: {
handler(nv, ov) {
if (nv) {
for (let key in nv) {
this.$set(this.queryParams, key, this.sendParams[key])
}
}
},
deep: true,
},
},
}
</script>
<style scoped lang="scss">
.btn-container {
margin-bottom: 6px;
display: flex;
justify-content: flex-end;
align-items: center;
}
::v-deep .btn-handler {
display: flex;
flex: 1;
.el-button {
padding: 6px 18px;
}
}
::v-deep .optionDivRef {
white-space: nowrap;
display: inline-block;
.el-button {
padding: 6px 12px;
}
}
.query-form {
position: relative;
}
</style>