You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
531 lines
19 KiB
531 lines
19 KiB
<!-- 附件组件 -->
|
|
<template>
|
|
<div class="table-form">
|
|
<el-table class="multipleTableComponents"
|
|
ref="TableBaseComponents_Ref"
|
|
v-loading="tableLoading"
|
|
:data="tableData"
|
|
:max-height="maxHeight"
|
|
row-key="id"
|
|
:border="border"
|
|
@selection-change="tableSelectionChange"
|
|
@sort-change="tableSortChange"
|
|
@row-click="handleTableSelect"
|
|
>
|
|
<!-- 删除按钮 -->
|
|
<el-table-column
|
|
fixed="left"
|
|
:width="50"
|
|
v-if="isShowReduceButton"
|
|
v-slot="{ row, $index }"
|
|
>
|
|
<Icon icon="ep:remove" color="#757575" size="26" style="cursor: pointer;margin-top: -16px;" @click="handleDeleteTable (row, $index)" />
|
|
</el-table-column>
|
|
<!-- 多选 -->
|
|
<el-table-column
|
|
fixed="left"
|
|
:reserve-selection="true"
|
|
type="selection"
|
|
:width="50"
|
|
v-if="selectionTable"
|
|
/>
|
|
<!-- 序号 -->
|
|
<el-table-column
|
|
type="index"
|
|
fixed="left"
|
|
label="序号"
|
|
width="80"
|
|
:align="'center'"
|
|
v-if="isShowIndex"
|
|
/>
|
|
<el-table-column
|
|
v-slot="{ row, $index }"
|
|
v-for="(headerItem) in tableFields"
|
|
:key="headerItem"
|
|
:fixed="headerItem.tableForm?.fixed"
|
|
:label="headerItem.label" :prop="headerItem.field"
|
|
:align="headerItem?.tableForm?.align || 'center'"
|
|
:sortable="headerItem?.tableForm?.sortable || false"
|
|
:width="headerItem?.tableForm?.width || '200'"
|
|
:min-width="headerItem?.tableForm?.minWidth || 'auto'">
|
|
<el-form
|
|
ref="TableBaseForm_Ref"
|
|
:model="row"
|
|
style="width: 100%;"
|
|
:rules="tableFormRules"
|
|
:class="tableFormRules ? '' : 'noRulesForm'">
|
|
<!-- 字符串输入框 -->
|
|
<el-form-item
|
|
v-if="!headerItem?.tableForm?.type || headerItem?.tableForm?.type == 'InputString'"
|
|
:prop="headerItem.field" style="display: flex;align-items: center;">
|
|
<el-input :key="headerItem.field+$index"
|
|
v-model="row[headerItem.field]"
|
|
clearable
|
|
:type="headerItem?.tableForm?.inputType"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '请输入' + headerItem.label"
|
|
:disabled="headerItem?.tableForm?.disabled ? true: headerItem?.tableForm?.isInpuFocusShow ? true : false"
|
|
style="flex:1"
|
|
@blur="inputStringBlur(headerItem.field, $event, row)"
|
|
/>
|
|
<el-button :key="headerItem.field+$index+'button'" v-if="headerItem?.tableForm?.isInpuFocusShow" @click="inpuFocus(headerItem,row,index)"><Icon icon="ep:search" size="14"/></el-button>
|
|
</el-form-item>
|
|
<el-form-item v-if="headerItem?.tableForm?.type == 'slot'">
|
|
<slot :row="row"></slot>
|
|
</el-form-item>
|
|
<!-- 金额输入框 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'number'"
|
|
:prop="headerItem.field">
|
|
<el-input
|
|
v-model="row[headerItem.field]"
|
|
clearable
|
|
type="number"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '请输入' + headerItem.label"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
style="width: 100%;"
|
|
@input="row[headerItem.field] = row[headerItem.field].replace(/[^\d\.-]/g, '')"
|
|
/>
|
|
</el-form-item>
|
|
<!-- 数字输入框 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'InputNumber'"
|
|
:prop="headerItem.field">
|
|
<el-input-number
|
|
style="width: 100%;"
|
|
:key="headerItem.field+$index"
|
|
v-model="row[headerItem.field]"
|
|
:max="headerItem?.tableForm?.max"
|
|
:min="headerItem?.tableForm?.min"
|
|
:precision="headerItem?.tableForm?.precision"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
@change="(e)=>{inputNumberChange(headerItem.field, $index, row, e)}"
|
|
/>
|
|
</el-form-item>
|
|
<!-- 下拉框 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'Select'"
|
|
:prop="headerItem.field">
|
|
<el-select :key="headerItem.field+$index"
|
|
v-model="row[headerItem.field]"
|
|
:clearable="headerItem?.tableForm.clearable || true"
|
|
:multiple="headerItem?.tableForm.multiple"
|
|
:size="headerItem?.tableForm.size"
|
|
:collapse-tags ="headerItem?.tableForm.collapseTags"
|
|
:collapse-tags-tooltip ="headerItem?.tableForm.collapseTagsTooltip"
|
|
:multiple-limit ="headerItem?.tableForm.multipleLimit"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:filterable="headerItem?.tableForm.filterable"
|
|
:allow-create="headerItem?.tableForm.allowCreate"
|
|
style="width: 100%"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '请选择' + headerItem.label"
|
|
@change="formSelectChange(headerItem.field, $event,row)"
|
|
@blur="tableFormSelectOnBlur(headerItem.field, $event,row, $index)">
|
|
<el-option
|
|
v-for="op in initSelectOptions(headerItem)"
|
|
:label="op.label"
|
|
:value="op.value"
|
|
:key="op.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<!-- 下拉框 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'SelectGroup'"
|
|
:prop="headerItem.field">
|
|
<el-select
|
|
v-model="row[headerItem.field]"
|
|
:clearable="headerItem?.tableForm.clearable || true"
|
|
:multiple="headerItem?.tableForm.multiple"
|
|
:size="headerItem?.tableForm.size"
|
|
:collapse-tags ="headerItem?.tableForm.collapseTags"
|
|
:collapse-tags-tooltip ="headerItem?.tableForm.collapseTagsTooltip"
|
|
:multiple-limit ="headerItem?.tableForm.multipleLimit"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:filterable="headerItem?.tableForm.filterable"
|
|
:allow-create="headerItem?.tableForm.allowCreate"
|
|
style="width: 100%"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '请选择' + headerItem.label"
|
|
@change="formSelectChange(headerItem.field, $event,row)"
|
|
@blur="tableFormSelectOnBlur(headerItem.field, $event,row, $index)">
|
|
<el-option-group
|
|
v-for="group in initSelectOptions(headerItem)"
|
|
:key="group.type"
|
|
:label="group.name"
|
|
>
|
|
<el-option
|
|
v-for="item in group.options"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-option-group>
|
|
</el-select>
|
|
</el-form-item>
|
|
<!-- 时间选择器 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'FormTime'"
|
|
:prop="headerItem.field">
|
|
<el-time-picker
|
|
v-model="row[headerItem.field]"
|
|
:clearable="true"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '选择时间'"
|
|
style="width: 100%" :disabled="itemIsDisabled(headerItem, row)"
|
|
:format="headerItem?.tableForm?.format || 'HH:mm:ss'"
|
|
:value-format="headerItem?.tableForm?.valueFormat || 'HH:mm:ss'" />
|
|
</el-form-item>
|
|
<!-- 日期选择器 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'FormDate'"
|
|
:prop="headerItem.field">
|
|
<el-date-picker
|
|
:key="headerItem.field+$index"
|
|
v-model="row[headerItem.field]"
|
|
:clearable="true"
|
|
style="width: 100%"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '选择日期'"
|
|
:format="headerItem?.tableForm?.format || 'YYYY-MM-DD'"
|
|
:value-format="headerItem?.tableForm?.valueFormat || 'YYYY-MM-DD'"
|
|
@change="formFormDateChange(headerItem.field, $event,row, $index)" />
|
|
</el-form-item>
|
|
<!-- 日期时间选择器 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'FormDateTime'"
|
|
:prop="headerItem.field">
|
|
<el-date-picker
|
|
:key="headerItem.field+$index"
|
|
type="datetime"
|
|
:clearable="true"
|
|
v-model="row[headerItem.field]"
|
|
:placeholder="headerItem?.tableForm?.placeholder || '选择日期时间'"
|
|
style="width: 100%"
|
|
:format="headerItem?.tableForm?.format || 'YYYY-MM-DD HH:mm:ss'"
|
|
:value-format="headerItem?.tableForm?.valueFormat || 'YYYY-MM-DDTHH:mm:ss'"
|
|
:disabled="itemIsDisabled(headerItem, row)" />
|
|
</el-form-item>
|
|
<!--开始时间结束时间选择器 (原类型datetimerange已弃用 使用type+timeType结合方式)-->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'FormTimerange'"
|
|
:prop="headerItem.field">
|
|
<el-date-picker
|
|
v-model="row[headerItem.field]"
|
|
:clearable="true"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:type="headerItem?.tableForm?.timeType || 'datetimerange'"
|
|
range-separator="至"
|
|
start-placeholder="开始日期"
|
|
end-placeholder="结束日期"
|
|
:format="headerItem?.tableForm?.format || 'YYYY-MM-DD HH:mm:ss'"
|
|
:value-format="headerItem?.tableForm?.valueFormat || 'YYYY-MM-DDTHH:mm:ss'" />
|
|
</el-form-item>
|
|
<!-- Switch 开关 -->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'Switch'"
|
|
:prop="headerItem.field">
|
|
<el-switch
|
|
v-model="row[headerItem.field]"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:loading="headerItem?.tableForm?.loading"
|
|
:size="headerItem?.tableForm?.size"
|
|
:active-icon="headerItem?.tableForm?.activeIcon"
|
|
:inactive-icon="headerItem?.tableForm?.inactiveIcon"
|
|
:active-text="headerItem?.tableForm?.activeText"
|
|
:inactive-text="headerItem?.tableForm?.inactiveText"
|
|
:active-value="headerItem?.tableForm?.activeValue"
|
|
:inactive-value="headerItem?.tableForm?.inactiveValue"
|
|
:active-color="headerItem?.tableForm?.inactiveColor"
|
|
:inactive-color="headerItem?.tableForm?.inactiveColor" />
|
|
</el-form-item>
|
|
<!-- Radio 单选-->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'Radio'"
|
|
:prop="headerItem.field">
|
|
<el-radio-group
|
|
v-model="row[headerItem.field]"
|
|
:size="headerItem?.tableForm?.size"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:text-color="headerItem?.tableForm?.textColor"
|
|
:fill="headerItem?.tableForm?.fill"
|
|
:name="headerItem?.tableForm?.name"
|
|
:id="headerItem?.tableForm?.id">
|
|
<el-radio
|
|
v-for="(item, index) in initSelectOptions(headerItem)"
|
|
:key="index"
|
|
:label="item.value"
|
|
:size="headerItem?.tableForm?.size"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:border="headerItem?.tableForm?.border">
|
|
{{ item.label }}
|
|
</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
<!-- Checkbox 多选-->
|
|
<el-form-item
|
|
v-if="headerItem?.tableForm?.type == 'Checkbox'"
|
|
:prop="headerItem.field">
|
|
<el-checkbox-group
|
|
v-model="row[headerItem.field]"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:size="headerItem?.tableForm?.size"
|
|
:min="headerItem?.tableForm?.min"
|
|
:max="headerItem?.tableForm?.max"
|
|
:text-color="headerItem?.tableForm?.textColor"
|
|
:fill="headerItem?.tableForm?.fill">
|
|
<el-checkbox
|
|
v-for="(item, index) in initSelectOptions(headerItem)"
|
|
:key="index"
|
|
:label="item.value"
|
|
:disabled="itemIsDisabled(headerItem, row)"
|
|
:true-label="headerItem?.tableForm?.trueLabel"
|
|
:false-label="headerItem?.tableForm?.falseLabel"
|
|
:border="headerItem?.tableForm?.border"
|
|
:size="headerItem?.tableForm?.size"
|
|
:name="headerItem?.tableForm?.name"
|
|
:checked="headerItem?.tableForm?.checked">
|
|
{{ item.label }}
|
|
</el-checkbox>
|
|
</el-checkbox-group>
|
|
</el-form-item>
|
|
<!-- table表添加操作列 -->
|
|
<!-- <el-form-item> -->
|
|
<div v-if="headerItem?.tableForm?.type == 'action'">
|
|
<el-button
|
|
v-for="(itemButton, indexButton) in headerItem?.tableForm?.buttonText.split('|')"
|
|
:key="indexButton"
|
|
type="text"
|
|
style="padding-top: 0px;align-items:unsafe;"
|
|
@click="buttonOperationClick(row, headerItem?.tableForm?.buttonName.split('|')[indexButton], $index)"
|
|
>{{itemButton}}</el-button>
|
|
</div>
|
|
<!-- </el-form-item> -->
|
|
</el-form>
|
|
</el-table-column>
|
|
</el-table>
|
|
<div class="button flex" v-if="isShowButton">
|
|
<div class="p-12px" @click="handleAddTable">
|
|
<Icon icon="ep:circle-plus" color="#409eff" size="26" style="cursor: pointer;" />
|
|
<div>添加明细</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
|
const props = defineProps({
|
|
// 是否显示添加按钮
|
|
isShowButton: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// 是否显示选择框 :custom="headerItem.sortable?headerItem.sortable:false"
|
|
selectionTable: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// 是否显示序号
|
|
isShowIndex: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// 是否显示删除按钮
|
|
isShowReduceButton:{
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// 加载状态
|
|
tableLoading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// 列表数据
|
|
tableData: {
|
|
type: Array,
|
|
default: () => {
|
|
return []
|
|
},
|
|
},
|
|
// 列表头定义
|
|
tableFields: {
|
|
type: Array,
|
|
default: () => {
|
|
return []
|
|
},
|
|
},
|
|
// table高度
|
|
height: {
|
|
type: [Number, String],
|
|
default: () => {
|
|
return '200'
|
|
}
|
|
},
|
|
maxHeight: {
|
|
type: [Number, String],
|
|
default: () => {
|
|
return '650'
|
|
}
|
|
},
|
|
// 是否有边框(可拖拽)
|
|
border: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// table输入表单的rules
|
|
tableFormRules: {
|
|
type: Object,
|
|
default: null
|
|
}
|
|
})
|
|
// 传递给父类
|
|
const emit = defineEmits([
|
|
'tableSelectionChange',
|
|
'extendedButtonsClick',
|
|
'formSelectChange',
|
|
'tableSortChange',
|
|
'selectCallback',
|
|
'handleTableSelect',
|
|
'handleDeleteTable',
|
|
'handleAddTable',
|
|
'inpuFocus',
|
|
'buttonOperationClick',
|
|
'inputStringBlur',
|
|
'tableFormSelectOnBlur',
|
|
'formFormDateChange'
|
|
])
|
|
// 获取下拉列表 | type = radio | type = select
|
|
const initSelectOptions = (item) => {
|
|
return item.dictType ? getStrDictOptions(item.dictType) : item.tableForm.initOptions
|
|
}
|
|
//普通下拉改变事件
|
|
const formSelectChange = (field, val,row) => {
|
|
emit('formSelectChange', field, val,row)
|
|
}
|
|
// 日期改变事件
|
|
const formFormDateChange = (field, val,row, index) => {
|
|
emit('formFormDateChange', field, val,row, index)
|
|
}
|
|
// 普通下拉失焦事件
|
|
const tableFormSelectOnBlur = (field, val,row,index) => {
|
|
emit('tableFormSelectOnBlur', field, val,row,index)
|
|
}
|
|
// 数字输入-改变事件
|
|
const inputNumberChange = (field, index, row, e) => {
|
|
emit('inputNumberChange', field, index, row, e)
|
|
}
|
|
|
|
// 点击selection框
|
|
const tableSelectionChange = (val) => {
|
|
emit('tableSelectionChange', val)
|
|
}
|
|
// 列表排序
|
|
const tableSortChange = (column, prop, order) => {
|
|
emit('tableSortChange', column, prop, order)
|
|
}
|
|
//下拉框回显方法
|
|
// const showSelect = (val, statusID) => {
|
|
// return getDictForStatusID(val, statusID)
|
|
// }
|
|
|
|
// 行点击
|
|
const handleTableSelect = (row, column, event) => {
|
|
emit('handleTableSelect', row, column, event)
|
|
}
|
|
|
|
// 某个item是否禁用
|
|
const itemIsDisabled = (colum, row) => {
|
|
return Boolean(colum.tableForm?.disabled) || Boolean(row.disabled) || Boolean(row['disabled_' + colum.field])
|
|
}
|
|
|
|
// const { t } = useI18n() // 国际化
|
|
// const message = useMessage() // 消息弹窗
|
|
|
|
const TableBaseComponents_Ref = ref()
|
|
const TableBaseForm_Ref = ref()
|
|
|
|
/**
|
|
* 验证表单是否符合rules
|
|
* @param {*} success 如果验证【成功】走的方法
|
|
* @param {*} error 如果验证【不成功】走的方法
|
|
*/
|
|
|
|
const validateForm = () => {
|
|
console.log(TableBaseForm_Ref.value)
|
|
let _lists = TableBaseForm_Ref.value?.map(v => v.validate())
|
|
return Promise.all(_lists).then(() => {
|
|
return true
|
|
}).catch(() => {
|
|
return false
|
|
})
|
|
}
|
|
// 删除数据
|
|
const handleDeleteTable = (row, index) => {
|
|
emit('handleDeleteTable', row, index)
|
|
}
|
|
// 添加数据
|
|
const handleAddTable = () => {
|
|
emit('handleAddTable')
|
|
}
|
|
// 输入框聚焦
|
|
const inpuFocus = (headerItem, row, index)=>{
|
|
if(headerItem?.tableForm?.isInpuFocusShow){
|
|
emit('inpuFocus', headerItem, row, index)
|
|
}
|
|
}
|
|
|
|
// input输入失去焦点事件
|
|
const inputStringBlur = (field, val,row) => {
|
|
emit('inputStringBlur', field, val,row)
|
|
}
|
|
|
|
//点击table操作列按钮
|
|
const buttonOperationClick = (row, label, index)=> {
|
|
emit("buttonOperationClick", row, label, index);
|
|
}
|
|
|
|
// setup 语法糖 抛出方法
|
|
defineExpose({
|
|
TableBaseComponents_Ref,
|
|
validateForm
|
|
})
|
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
::v-deep(.el-table__body){
|
|
padding:10px 0px
|
|
}
|
|
::v-deep(.el-table--default .el-table__cell) {
|
|
padding: 2px 0px;
|
|
border: none;
|
|
}
|
|
|
|
::v-deep(.el-table td.el-table__cell .el-form-item__content) {
|
|
display: flex !important;
|
|
align-items: center !important;
|
|
justify-content: center !important;
|
|
}
|
|
::v-deep(.el-table td.el-table__cell div) {
|
|
overflow: visible;
|
|
}
|
|
|
|
::v-deep(.el-icon) {
|
|
display: block;
|
|
}
|
|
|
|
.button {
|
|
>div {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
|
|
>div {
|
|
margin-left: 6px;
|
|
text-decoration: underline;
|
|
color: #409eff;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
</style>
|
|
|