|
|
- <template>
- <div>
- <div class="custom-table-wrapper" :class="{ 'no-border': !isBorder }">
- <div class="custom-table-header no-break" v-if="isBorder">
- <div class="custom-table-row">
- <div v-if="showSort" class="custom-table-cell header-cell sort-cell">
- 序号
- </div>
- <div class="custom-table-cell header-cell c-cell" v-if="showCheckAll">
- <div class="checkbox-item">
- <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate"
- @change="handleCheckAllChange"></el-checkbox>
- </div>
- </div>
- <div v-for="(col, colIndex) in columns" :key="colIndex"
- class="custom-table-cell header-cell no-break" :style="getCellWidth(col)">
- <div class="header-cell-content" v-if="col.headerColumns && col.headerColumns.length > 0">
- <div class="header-columns-grid"
- :style="{ 'grid-template-columns': `repeat(${col.span || 2}, 1fr)` }">
- <div v-for="(headerCol, headerIndex) in col.headerColumns" :key="headerIndex"
- class="header-column-item">
- <template v-if="headerCol.type === 'span'">
- <div class="span-content">{{ $t(headerCol.label) }}</div>
- </template>
- <template v-else-if="isRegent(headerCol)">
- <HandleFormItem
- :fieldKey="prefixKey + colIndex + '_' + headerCol.key + '_' + headerIndex"
- :fieldItemLabel="fieldItemLabel" :type="headerCol.type"
- class="body-clickable" sourceFrom="customTable"
- :item="getHeaderColumnItem(headerCol)"
- :value="headerFields[`${colIndex}_${headerIndex}`]"
- :error="hasHeaderError(colIndex, headerIndex, headerCol.key)"
- @update:error="onHeaderColumnErrorUpdate(colIndex, headerIndex, headerCol.key, $event)"
- :orange-bg="regentIsExpired(headerCol.key,colIndex)"
- @onRegentSubmit="(data, inputValue) => onHeaderRegentSubmit(data, inputValue, colIndex, headerIndex)" />
- </template>
- <template
- v-else-if="headerCol.type === 'input' || headerCol.type === 'select' || headerCol.type === 'inputNumber'">
- <HandleFormItem
- :fieldKey="prefixKey + '_header_' + colIndex + '_' + headerIndex"
- :fieldItemLabel="fieldItemLabel" :type="headerCol.type"
- :item="getHeaderColumnItem(headerCol)"
- v-model="headerFields[`${colIndex}_${headerIndex}`]"
- @change="onHeaderColumnChange(colIndex, headerIndex, headerCol, $event)"
- :error="hasHeaderError(colIndex, headerIndex, headerCol.key)"
- @update:error="onHeaderColumnErrorUpdate(colIndex, headerIndex, headerCol.key, $event)" />
- </template>
- </div>
- </div>
- </div>
- <div class="header-cell-content" v-else>
- <div>{{ $t(col.label) }}</div>
- <template
- v-if="col.headerSelectKey && col.headerOptions && (showHeaderSelect || templateFillType === 'preFill')">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.headerSelectKey"
- :fieldItemLabel="fieldItemLabel" type="select" class="header-select"
- :item="getHeaderItem(col)" v-model="headerSelectFields[col.headerSelectKey]"
- @change="onHeaderSelectChange(col, $event)"
- :error="hasError(-1, colIndex, col.headerSelectKey)"
- @update:error="onErrorUpdate(-1, colIndex, col.headerSelectKey, $event)" />
- </template>
- <div v-else-if="headerSelectFields[col.headerSelectKey]" class="fill-type-icon"
- :style="{ width: (templateFillType !== 'actFill') ? '60px' : 'auto' }">({{
- headerSelectFields[col.headerSelectKey] }})</div>
- </div>
-
- </div>
- <!-- 默认操作栏 -->
- <div class="custom-table-cell header-cell" :style="{ width: operationWidth }" v-if="showOperation">
- <div class="header-cell-content">
- <div>操作</div>
- </div>
- </div>
- </div>
- </div>
-
- <div class="custom-table-body">
- <div v-for="(row, rowIndex) in localDataSource" :key="rowIndex" class="custometable-row no-break">
- <div v-if="showSort" class="custom-table-cell body-cell sort-cell">
- {{ rowIndex + 1 }}
- </div>
- <div class="custom-table-cell body-cell c-cell" v-if="showCheckAll">
- <div class="checkbox-item">
- <el-checkbox v-model="row._checked" @change="handleCheckChange(row, $event)"></el-checkbox>
- </div>
- </div>
- <div v-for="(col, colIndex) in columns" :key="colIndex"
- class="custom-table-cell body-cell no-break" :style="getCellWidth(col)">
- <div class="inner-table-cell">
- <div class="flex1" :class="{ 'item-center': !isBorder && col.label }">
- <div v-if="!isBorder && col.label" class="mr-5">
- {{ $t(col.label) }}
- </div>
- <template
- v-if="col.bodyType === 'input' || col.bodyType === 'inputNumber' || col.bodyType === 'select' || col.bodyType === 'dateTimeRange' || col.bodyType === 'dateTime' || col.bodyType === 'radio'">
- <div class="flex flex1">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.prop + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" :type="col.bodyType"
- @blur="onBlur(rowIndex, col.prop, $event)" @copy="onCopy(rowIndex, col)"
- class="body-input" :item="getBodyItem(col, rowIndex)"
- v-model="row[col.prop]" :ref="col.prop + rowIndex"
- @change="onBodyValueChange(rowIndex, colIndex, $event, row, col.bodyType)"
- :error="hasError(rowIndex, colIndex, col.prop)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)"
- @beforeSaveRecord="(data, callback) => beforeSaveRecord(data, callback, rowIndex, col, row)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, col.prop)" />
- </div>
-
- </template>
- <div v-else-if="col.bodyType === 'checkboxTree'">
- <HandleFormItem :field-item-label="fieldItemLabel"
- :field-key="prefixKey + '_' + col.prop + rowIndex" type="checkboxTree"
- :item="getBodyItem(col, rowIndex)" :value="row[col.prop]"
- @change="(e) => onBodyValueChange(rowIndex, colIndex, e, row, col.bodyType)"
- :error="hasError(rowIndex, colIndex, col.prop)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, col.prop)" />
- </div>
- <div v-else-if="col.bodyType === 'operableInput'" class="flex flex1">
- <div class="flex1 grid-container">
- <div class="flex"
- :class="{ 'full-row': row[col.prop] && row[col.prop].length == 1 }"
- v-for="(opItem, itemIndex) in row[col.prop]" :key="itemIndex">
- <HandleFormItem
- :fieldKey="prefixKey + '_' + col.prop + '_' + row.id + '_' + itemIndex"
- :fieldItemLabel="fieldItemLabel" type="input"
- @blur="onOperableInputBlur(opItem, $event)" class="body-input"
- :item="getBodyItem(col, rowIndex)" :value="opItem.value"
- :error="hasError(rowIndex, colIndex, rowIndex + col.prop + itemIndex)"
- @update:error="onErrorUpdate(rowIndex, colIndex, rowIndex + col.prop + itemIndex, $event)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, rowIndex + col.prop + itemIndex)" />
- <el-popconfirm confirm-button-text='确认' cancel-button-text='取消'
- icon="el-icon-info" icon-color="red" title="确认删除当前输入框?"
- @confirm="removeOperableInput(rowIndex, colIndex, col.prop, itemIndex)">
- <i slot="reference" class="el-icon-remove-outline remove-icon"
- v-if="itemIndex > 0 && templateFillType === 'actFill' && !row.isComplete"></i>
- </el-popconfirm>
- </div>
- </div>
- <i class="el-icon-circle-plus add-icon"
- v-if="templateFillType === 'actFill' && !row.isComplete"
- @click="addOperableInput(rowIndex, colIndex, col.prop)"></i>
- </div>
-
- <div class="flex flex1" v-else-if="col.bodyType === 'clickable'">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.prop + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" type="clickable" class="body-clickable"
- :item="getBodyItem(col, rowIndex)" :value="row[col.prop]"
- :error="hasError(rowIndex, colIndex, col.prop)"
- @clickable="handleClickable(col, rowIndex, colIndex, row)"
- @resetRecord="resetRecord(rowIndex, colIndex, col.prop)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, col.prop)" />
- </div>
- <div class="flex flex1" v-else-if="isRegent(col, 'bodyType')">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.prop + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" :type="col.bodyType" class="body-clickable"
- sourceFrom="customTable" :item="getBodyItem(col, rowIndex)"
- :value="row[col.prop]" :error="hasError(rowIndex, colIndex, col.prop)"
- @onRegentSubmit="(data, inputValue) => onRegentSubmit(data, inputValue, col, rowIndex, colIndex, row, col.prop)"
- @beforeReagentSubmit="(data, callback) => onBeforeReagentSubmit(data, callback, col, row)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)"
- :orange-bg="regentIsExpired(col.prop,rowIndex)" />
- </div>
- <template v-else-if="col.bodyType === 'span'">
- <div class="body-span">
- {{ row[col.prop] }}
- </div>
- </template>
- <template v-else-if="col.bodyType === 'checkboxTag'">
- <div class="flex flex-wrap"
- :class="{ 'row-error-border': hasError(rowIndex, colIndex, col.prop) }">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.prop + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" type="checkboxTag" :value="row[col.prop]"
- :item="getBodyItem(col, rowIndex)"
- @change="onCheckboxTagChange(rowIndex, colIndex, col, $event)"
- @deleteTag="onDeleteCheckboxTag(rowIndex, col, $event)"
- :error="hasError(rowIndex, colIndex, col.prop)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)" />
- </div>
- </template>
- <template v-else-if="col.bodyType === 'checkbox'">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.prop + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" type="checkbox" v-model="row[col.prop]"
- :item="getBodyItem(col, rowIndex)"
- @change="onCheckboxChange(rowIndex, colIndex, col, $event)"
- :error="hasError(rowIndex, colIndex, col.prop)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.prop, $event)" />
- </template>
-
- </div>
- <div v-show="isShowOther(row[col.prop], col)" class="flex flex1">
- <div class="other-title">{{ col.otherLabel ? $t(col.otherLabel) :
- $t("template.common.other") }}
- </div>
- <div class="flex flex1">
- <HandleFormItem :field-item-label="fieldItemLabel"
- :field-key="prefixKey + '_' + col.otherCode"
- @blur="onBlur(rowIndex, col.prop, $event)" :item="getOtherItem(col)"
- v-model="row[col.otherCode]"
- :error="hasError(rowIndex, colIndex, col.otherCode)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.otherCode, $event)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, col.otherCode)" />
- </div>
- </div>
- <div class="m-l-5 flex"
- :class="{ 'flex1': (col.bodySubType !== 'button' && col.bodySubType !== 'span') }"
- v-if="isShowBodySub(col, row)">
- <template
- v-if="col.bodySubType === 'inputNumber' || col.bodySubType === 'input' || col.bodySubType === 'select'">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.bodySubKey + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" :type="col.bodySubType"
- @blur="onSubBlur(rowIndex, col.bodySubKey, $event)"
- @copy="onCopy(rowIndex, col)" :item="getBodySubItem(col)"
- v-model="row[col.bodySubKey]"
- @change="onBodySubValueChange(rowIndex, colIndex, $event, row, col.bodySubType)"
- :error="hasError(rowIndex, colIndex, col.bodySubKey)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.bodySubKey, $event)"
- :orange-bg="hasOrangeBg(rowIndex, colIndex, col.bodySubKey)" />
- </template>
- <template v-else-if="col.bodySubType === 'span'">
- <div class="body-span">
- {{ row[col.bodySubKey] }}
- </div>
- </template>
- <template v-else-if="col.bodySubType === 'button'">
- <HandleFormItem class="ml-10" type="button" :item="getBodyButtonItem(col, rowIndex)"
- :value="row[col.bodySubKey]"
- :fieldKey="prefixKey + '_' + col.bodySubKey + '_' + row.id"
- @clickButton="(e, val, data) => handleClickButton(e, data, col.bodySubKey, rowIndex, colIndex)" />
- </template>
- <div class="flex flex1" v-else-if="isRegent(col, 'bodySubType')">
- <HandleFormItem :fieldKey="prefixKey + '_' + col.bodySubKey + '_' + row.id"
- :fieldItemLabel="fieldItemLabel" :type="col.bodySubType" class="body-clickable"
- sourceFrom="customTable" :item="getBodySubItem(col, rowIndex)"
- :value="row[col.bodySubKey]"
- :error="hasError(rowIndex, colIndex, col.bodySubKey)"
- @onRegentSubmit="(data, inputValue) => onRegentSubmit(data, inputValue, col, rowIndex, colIndex, row, col.bodySubKey)"
- @beforeReagentSubmit="(data, callback) => onBeforeReagentSubmit(data, callback, col, row)"
- @update:error="onErrorUpdate(rowIndex, colIndex, col.bodySubKey, $event)"
- :orange-bg="regentIsExpired(col.bodySubKey,rowIndex)" />
- </div>
- <template v-if="col.bodyThirdType === 'button'">
- <HandleFormItem class="ml-10" type="button"
- :item="getBodyThirdButtonItem(col, rowIndex)" :value="row[col.bodyThirdKey]"
- :fieldKey="prefixKey + '_' + col.bodyThirdKey + '_' + row.id"
- @clickButton="(e, val, data) => handleClickButton(e, data, col.bodyThirdKey, rowIndex, colIndex)" />
- </template>
- </div>
- </div>
- </div>
-
- <!-- 默认操作栏 -->
- <div class="custom-table-cell body-cell" :style="{ width: isBorder ? operationWidth : 'auto' }"
- v-if="showOperation">
- <div class="inner-table-cell">
- <slot name="operation" :row="row" :rowIndex="rowIndex" :columns="getOperationColumns()">
- </slot>
- </div>
- </div>
- </div>
- </div>
- <div v-if="localDataSource.length == 0">
- <div class="no-data">暂无数据</div>
- </div>
-
-
- </div>
- <div class="add-row" v-if="isShowAddRos()">
- <el-button type="primary" plain @click="onAddRow">添加行</el-button>
- </div>
- </div>
- </template>
-
- <script>
- import HandleFormItem from "./HandleFormItem.vue";
- import { isEqual } from "@/utils/index.js";
- import { isShowOther } from "@/utils/formPackageCommon.js";
- import { EventBus } from "@/utils/eventBus";
- import { getuuid, justUpdateFilledFormData } from "@/utils/index.js";
- import { isRegent } from "@/utils/index.js";
- import { isValueEmpty } from '@/utils/index.js';
- import moment from 'moment';
-
- import _ from "lodash";
- export default {
- inject: ['templateFillType', 'getZdxgjl', 'updateZdxgjl'],
- name: 'CustomTable',
- components: {
- HandleFormItem
- },
- props: {
- operationWidth: {
- type: String,
- default: '245px',
- },
- // 是否显示表头选择器
- showHeaderSelect: {
- type: Boolean,
- default: false,
- },
- showAddRow: {
- type: Boolean,
- default: undefined,
- },
- // 是否显示操作栏
- showOperation: {
- type: Boolean,
- default: true,
- },
- columns: {
- type: Array,
- required: true,
- // 示例格式:
- // [
- // { label: '姓名', prop: 'name' },
- // { label: '状态', prop: 'status', type: 'select', options: [{value:1,label:'启用'},...], selected: null }
- // ]
- },
- formData: {
- type: Object,
- default: () => {
- return {
- stepTableFormData: [],
- headerSelectFields: {},
- }
- }
- },
- fieldItemLabel: {
- type: String,
- default: '',
- },
- //循环组件的情况下需要用这个来区分字段
- prefixKey: {
- type: String,
- default: "",
- },
- isBorder: {//是否无边框,无边框的没有表头和border
- type: Boolean,
- default: true,
- },
- // 是否显示全选
- showCheckAll: {
- type: Boolean,
- default: false,
- },
- // 是否显示排序
- showSort: {
- type: Boolean,
- default: false,
- },
- },
- data() {
- return {
- localDataSource: [],
- headerSelectFields: {},
- headerFields: {}, // 存储 headerColumns 的数据
- formErrors: [], // 表单错误状态管理
- orangeBgCells: {}, // 存储需要橙色背景的单元格 {rowIndex-colIndex: true/false}
- isShowOther,
- oldLocalDataSource: [],
- uuid: getuuid(),
- isRegent,
- selectedRows: [], // 存储选中的行
- isIndeterminate: false, // 半选状态
- checkAll: false, // 全选状态
- }
- },
- watch: {
- formData: {
- immediate: true,
- handler(newData) {
- const { stepTableFormData = [], headerSelectFields = {}, headerFields = {} } = newData;
- this.updateDataSource(stepTableFormData);
- this.headerSelectFields = JSON.parse(JSON.stringify(headerSelectFields));
- this.headerFields = JSON.parse(JSON.stringify(headerFields));
- // 在数据加载后检查 compareTo 逻辑
- this.checkCompareToOnDataLoad();
- }
- },
- localDataSource: {
- immediate: true,
- deep: true,
- handler(newVal, oldVal) {
- // if(newVal.length == 0){
- // return
- // }
- // this.localDataSource = [...newVal];
- }
- }
- },
- mounted() {
- },
- unmounted() {
- this.oldLocalDataSource = [];
- },
- methods: {
- // 删除operableInput
- removeOperableInput(rowIndex, colIndex, prop, itemIndex) {
- this.localDataSource[rowIndex][prop].splice(itemIndex, 1);
- justUpdateFilledFormData();
- },
- // 添加operableInput
- addOperableInput(rowIndex, colIndex, prop) {
- this.localDataSource[rowIndex][prop].push({ value: undefined });
- justUpdateFilledFormData();
- },
- onOperableInputBlur(opItem, e) {
- opItem.value = e;
- },
- getHeaderColumnItem(headerCol) {
- return {
- label: headerCol.label || '',
- fillType: headerCol.fillType,
- options: headerCol.options,
- maxlength: headerCol.maxlength,
- checkType: headerCol.checkType,
- regentFillType: headerCol.regentFillType,
- type: headerCol.type,
- };
- },
-
- onHeaderColumnChange(colIndex, headerIndex, headerCol, value) {
- const fieldKey = `${colIndex}_${headerIndex}`;
- this.headerFields[fieldKey] = value;
- this.$emit('headerColumnChange', {
- colIndex,
- headerIndex,
- key: fieldKey,
- value,
- headerFields: this.headerFields
- });
- },
-
- hasHeaderError(colIndex, headerIndex, key) {
- return this.formErrors.some(error =>
- error.rowIndex === -1 &&
- error.colIndex === colIndex &&
- error.headerIndex === headerIndex &&
- error.field === key
- );
- },
-
- onHeaderColumnErrorUpdate(colIndex, headerIndex, key, isError) {
- if (!isError) {
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === -1 &&
- error.colIndex === colIndex &&
- error.headerIndex === headerIndex &&
- error.field === key)
- );
- }
- },
-
- // 删除checkboxTag
- onDeleteCheckboxTag(rowIndex, col, tagIndex) {
- this.localDataSource[rowIndex][col.prop].splice(tagIndex, 1);
- this.$emit("onDeleteTag", rowIndex, col, tagIndex);
- justUpdateFilledFormData();
- },
- onCheckboxTagChange(rowIndex, colIndex, col, value) {
- // value 现在是整个数组
- this.localDataSource[rowIndex][col.prop] = value;
- // 根据校验规则判断是否清除错误状态
- let isValid = false;
- if (this.templateFillType === "actFill") {
- // actFill时,检查是否有checked为true的项
- isValid = value && value.some(tag => tag.checked === true);
- } else if (this.templateFillType === "preFill") {
- // preFill时,检查所有tagValue是否不为空
- isValid = value && value.every(tag => tag.tagValue && (tag.tagValue + '').trim() !== '');
- }
- this.onErrorUpdate(rowIndex, colIndex, col.prop, !isValid);
- this.$emit("onCheckboxTagChange", rowIndex, col, value)
- },
- // checkbox变化
- onCheckboxChange(rowIndex, colIndex, col, value) {
- this.localDataSource[rowIndex][col.prop] = value;
- // 输入时清除对应表单项的错误状态
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === rowIndex &&
- error.colIndex === colIndex &&
- error.field === col.prop)
- );
- this.$emit("onCheckboxChange", rowIndex, col, value);
- justUpdateFilledFormData();
- },
- handleClickButton(e, data, key, rowIndex, colIndex) {
- this.$emit("clickButton", key, rowIndex, colIndex, e, data,)
- },
- beforeSaveRecord(data, callback, rowIndex, col, row) {
- this.$emit("beforeSaveRecord", { inputData: data, callback, rowIndex, key: col.prop, rowData: row, dataSource: this.localDataSource })
- },
- getCellWidth(col) {
- const { templateFillType } = this;
- let width = col.width ? col.width + 'px' : 'auto';
- if (templateFillType !== "actFill" && templateFillType !== "preFill") {
- width = (col.showWidth) ? col.showWidth + 'px' : (col.width ? col.width + 'px' : 'auto')
- }
- return { width }
- },
- //取消按钮 重置记录
- resetRecord(rowIndex, colIndex,) {
- if (this.localDataSource.length) {
- this.localDataSource = [...this.oldLocalDataSource];
- this.oldLocalDataSource = [];
- }
- },
- //获取操作栏的列
- getOperationColumns() {
- return { columnsData: this.columns, headerSelectFields: this.headerSelectFields, fieldItemLabel: this.fieldItemLabel }
- },
- //获取其他下拉框的配置
- getOtherItem(sItem) {
- return {
- label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
- fillType: sItem.bodyFillType,
- maxlength: sItem.otherMaxlength || 50,
- parentLabel: sItem.label,
- type: "input"
- }
- },
- isShowBodySub(col, row) {
- if (col.hasOwnProperty("showBodySub")) {
- return col.showBodySub
- } else if (col.bodySubType === 'span' && !row[col.bodySubKey]) {//如果是span没有值的话就隐藏
- return false;
- }
- return col.bodySubType && col.bodySubKey;
- },
- // 点击事件
- handleClickable(col, rowIndex, colIndex, row) {
- // if (this.templateFillType !== 'actFill') {
- // return
- // }
- this.$emit("clickable", col, rowIndex, row)
- },
- onBeforeReagentSubmit(data, callback, col, row) {
- if (this.templateFillType !== 'actFill') {
- return
- }
- this.$emit("beforeReagentSubmit", { selectData: data, callback, key: col.prop, rowData: row })
- },
- onHeaderRegentSubmit(data, inputValue, colIndex, headerIndex) {
- this.headerFields[`${colIndex}_${headerIndex}`] = inputValue;
-
- this.$emit("onHeaderRegentSubmit", { selectInfo: data, headerIndex, colIndex, headerFields: this.headerFields })
- },
- //是否过期
- regentIsExpired(key,rowIndex) {
- const item = this.localDataSource[rowIndex] || {};
- const { yxq, sxrq } = item[`selectInfo_${key}`] || {};
- const rq = sxrq || yxq;
- if (rq) {
- const time = moment(yxq);
- return time.isBefore(moment());
- } else {
- return false;
- }
- },
- onRegentSubmit(data, inputValue, col, rowIndex, colIndex, row, key) {
- // if (this.templateFillType !== 'actFill') {
- // return
- // }
- this.updateDataSourceByRowIndex(rowIndex, { [key]: inputValue, [`selectInfo_${key}`]: data.selectInfo })
- this.$emit("onRegentSubmit", { selectInfo: data, key, col, rowIndex, colIndex, rowData: row })
- },
- isShowAddRos() {
- if (this.showAddRow !== undefined) {
- return this.showAddRow
- }
- return this.templateFillType === 'preFill';
- },
- // 复制值
- onCopy(rowIndex, col) {
-
- if (col.copyFrom) {
- if (isValueEmpty(this.localDataSource[rowIndex][col.copyFrom])) {//没有值就不用复制了
- return
- }
- this.updateDataSourceByRowIndex(rowIndex, { [col.prop]: this.localDataSource[rowIndex][col.copyFrom] }, "clickable")
- this.onBlur(rowIndex, col.prop, this.localDataSource[rowIndex][col.prop]);
- }
- },
- // 初始化表头选择器值
- initHeaderSelectValues() {
- const headerSelectObj = {};
- this.columns.map(col => {
- if (col.headerSelectKey) {
- headerSelectObj[col.headerSelectKey] = col.defaultValue || col.headerOptions[0].value || ""
- }
- });
- this.headerSelectFields = headerSelectObj;
- },
- // 直接获取表单数据,不做校验
- getFilledFormData() {
- return {
- stepTableFormData: [...this.localDataSource],
- headerSelectFields: this.headerSelectFields,
- headerFields: this.headerFields,
- };
- },
- // 获取最新数据
- getFormData() {
- // 合并表头选择器值到 columns
-
-
- // 数据校验
- const validateResult = this.validateFormData();
- return new Promise((resolve, reject) => {
- if (validateResult.valid) {
- resolve({
- stepTableFormData: [...this.localDataSource],
- headerSelectFields: this.headerSelectFields,
- headerFields: this.headerFields,
- })
- } else {
- // this.$message.error("表单内容未填完,请填写后再提交");
- reject(validateResult.errors[0].error)
- }
- })
-
- },
- // 表单数据校验
- validateFormData() {
- const errors = [];
-
- // 清空之前的错误状态
- this.formErrors = [];
-
- // 校验表头的 HandleFormItem
- this.columns.forEach((col, colIndex) => {
- if (col.headerSelectKey && col.headerOptions && col.fillType === this.templateFillType) {
- const headerValue = this.headerSelectFields[col.headerSelectKey];
- if (isValueEmpty(headerValue)) {
- const errorItem = {
- rowIndex: -1, // 表头特殊标记
- colIndex,
- field: col.headerSelectKey,
- label: this.$t(col.label),
- error: `请选择${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- } else if (col.headerColumns && col.headerColumns.length > 0) {
- col.headerColumns.forEach((headerCol, headerColIndex) => {
- const headerValue = this.headerFields[`${colIndex}_${headerColIndex}`];
- if (headerCol.fillType === this.templateFillType) {
- if (isValueEmpty(headerValue) && headerCol.type !== "span") {
- const errorItem = {
- rowIndex: -1, // 表头特殊标记
- colIndex,
- field: headerCol.key,
- label: this.$t(headerCol.label),
- headerIndex: headerColIndex,
- error: `请选择${this.$t(headerCol.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- }
-
- });
-
- }
- });
-
- // 遍历数据行
- this.localDataSource.forEach((row, rowIndex) => {
- // 遍历列
- this.columns.forEach((col, colIndex) => {
- // 只校验 fillType 与当前模板状态匹配的字段
- if (col.bodyFillType === this.templateFillType || col.bodySubFillType === this.templateFillType) {
- // 检查主字段
- const mainValue = row[col.prop];
- if (col.bodyType === "checkboxTag") {
- // checkboxTag类型的校验逻辑
- if (this.templateFillType === "actFill") {
- // actFill时,检查是否有checked为true的项
- const hasChecked = mainValue && mainValue.some(tag => tag.checked === true);
- if (!hasChecked) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.prop,
- label: this.$t(col.label),
- error: `请勾选${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- } else if (this.templateFillType === "preFill") {
- // preFill时,检查所有tagValue是否不为空
- const allTagValuesFilled = mainValue && mainValue.every(tag => tag.tagValue && (tag.tagValue + '').trim() !== '');
- if (!allTagValuesFilled) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.prop,
- label: this.$t(col.label),
- error: `请填写${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- }
- } else if (col.bodyType === "checkbox") {
- // checkbox类型的校验逻辑
- // checkbox只在actFill时进行必填校验
- if (this.templateFillType === 'actFill' && !col.isNeedCheck) {
- // 单个checkbox:值必须为true
- // checkbox组:至少选中一个
- const hasChecked = Array.isArray(mainValue) ? mainValue.length > 0 : mainValue === true;
- if (!hasChecked) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.prop,
- label: this.$t(col.label),
- error: `请勾选${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- }
- } else if (col.bodyType === "operableInput") {
- mainValue.forEach((itemItem, itemIndex) => {
- if (isValueEmpty(itemItem.value)) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: rowIndex + col.prop + itemIndex,
- label: this.$t(col.label),
- error: `请填写${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- })
-
- } else {
- if (isValueEmpty(mainValue) &&col.bodyFillType === this.templateFillType && col.bodyType !== 'span' && col.bodyType !== 'button') {
- console.log(col.bodyFillType,col.bodySubFillType,"bodySubFillType")
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.prop,
- label: this.$t(col.label),
- error: `请填写${this.$t(col.label)}`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- // 检查子字段(如果有)
- if (col.bodySubKey && col.bodySubFillType === this.templateFillType && col.bodySubType !== 'span' && col.bodySubType !== "button") {
- const subValue = row[col.bodySubKey];
- if (isValueEmpty(subValue)) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.bodySubKey,
- label: `${this.$t(col.label)}单位`,
- error: `请填写${this.$t(col.label)}单位`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- }
- }
-
- console.log(col.otherCode, "col.otherCode")
-
- // 检查其他输入框
- if (col.otherCode) {
- const isSelectedOther = this.isShowOther(mainValue);
- if (!isSelectedOther) {
- return;
- }
- const otherValue = row[col.otherCode];
- if (isValueEmpty(otherValue)) {
- const errorItem = {
- rowIndex,
- colIndex,
- field: col.otherCode,
- label: `${this.$t(col.label)}单位`,
- error: `请填写${this.$t(col.otherLabel) ? this.$t(col.otherLabel) : '其他'}信息`
- };
- errors.push(errorItem);
- this.formErrors.push(errorItem);
- }
- }
-
- }
- });
- });
- console.log(errors, this.localDataSource, "errors")
- return {
- valid: errors.length === 0,
- errors: errors
- };
- },
-
- // 表头选择器变化
- onHeaderSelectChange(col, value) {
- if (col.headerSelectTo) {
- this.headerSelectFields[col.headerSelectTo] = value;
- }
- this.headerSelectFields[col.headerSelectKey] = value;
- this.$emit('headerSelectChange', { key: col.headerSelectKey, headerSelectFields: this.headerSelectFields, dataSource: this.localDataSource });
- // 输入时清除对应表单项的错误状态
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === -1 &&
- error.field === col.headerSelectKey)
- );
-
- if (col && col.headerSelectTo) {
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === -1 &&
- error.field === col.headerSelectTo)
- );
- }
- },
- // 检查并应用 compareTo 逻辑
- checkCompareToLogic(rowIndex, colIndex, colKey, value) {
- const col = this.columns[colIndex];
-
- // 检查主字段的 compareTo 逻辑
- if (col && col.bodyFillType === "actFill" && col.compareTo) {
- const compareToValue = this.localDataSource[rowIndex][col.compareTo];
-
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (!isEqual(value, compareToValue)) {
- this.setOrangeBg(rowIndex, colIndex, colKey, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, colIndex, colKey, false);
- }
- }
- },
-
- // 在数据加载时检查 compareTo 逻辑
- checkCompareToOnDataLoad() {
- // 遍历所有行和列,检查 compareTo 逻辑
- this.localDataSource.forEach((row, rowIndex) => {
- this.columns.forEach((col, colIndex) => {
- const currentValue = row[col.prop];
- const compareToValue = row[col.compareTo];
- if (col.compareTo && !isValueEmpty(currentValue) && !isValueEmpty(compareToValue)) {
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (!isEqual(currentValue, compareToValue)) {
- this.setOrangeBg(rowIndex, colIndex, col.prop, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, colIndex, col.prop, false);
- }
- }
-
- // 检查子字段的 compareTo 逻辑
- if (col.bodySubFillType === "actFill" && col.bodySubCompareTo) {
- const currentValue = row[col.bodySubKey];
- const compareToValue = row[col.bodySubCompareTo];
-
- if (!isValueEmpty(currentValue) && !isValueEmpty(compareToValue)) {
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (!isEqual(currentValue, compareToValue)) {
- this.setOrangeBg(rowIndex, colIndex, col.bodySubKey, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, colIndex, col.bodySubKey, false);
- }
- }
- }
- });
- });
- },
-
- // 表体值变化
- onBodyValueChange(rowIndex, colIndex, value, row, type) {
- const col = this.columns[colIndex];
- this.localDataSource[rowIndex][col.prop] = value;
-
- // 检查并应用 compareTo 逻辑
- this.checkCompareToLogic(rowIndex, colIndex, col.prop, value);
-
- // 输入时清除对应表单项的错误状态
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === rowIndex &&
- error.colIndex === colIndex &&
- error.field === col.prop)
- );
- if (type === "select") {
- this.$emit('bodySelectChange', { rowIndex, item: row, colIndex, value, key: col.prop, dataSource: this.localDataSource, headerSelectFields: this.headerSelectFields });
- }
- if (type === "checkboxTree") {
- this.$emit('bodyTreeChange', { rowIndex, colIndex, value, row, type });
- }
- },
- // 表体子值变化
- onBodySubValueChange(rowIndex, colIndex, value, row, type) {
- const col = this.columns[colIndex];
- this.localDataSource[rowIndex][col.bodySubKey] = value;
-
- // 检查子字段的 compareTo 逻辑
- if (col && col.bodySubFillType === "actFill" && col.bodySubCompareTo) {
- const compareToValue = this.localDataSource[rowIndex][col.bodySubCompareTo];
-
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (value !== compareToValue) {
- this.setOrangeBg(rowIndex, colIndex, col.bodySubKey, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, colIndex, col.bodySubKey, false);
- }
- }
-
- // 输入时清除对应表单项的错误状态
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === rowIndex &&
- error.colIndex === colIndex &&
- error.field === col.bodySubKey)
- );
- if (type === "select") {
- this.$emit('bodySelectChange', { rowIndex, item: row, colIndex, value, key: col.bodySubKey, dataSource: this.localDataSource, headerSelectFields: this.headerSelectFields });
- }
- },
- getHeaderItem(col) {
- return {
- fillType: col.fillType,
- options: col.headerOptions,
- label: ""
- }
- },
- getBodyItem(col, rowIndex) {
- const currentItem = this.localDataSource[rowIndex];
- const item = {
- fillType: col.bodyFillType,
- options: col.bodyOptions,
- maxlength: col.bodyMaxlength,
- label: this.$t(col.label),
- precision: currentItem[col.bodyPrecisionKey] || col.precision,
- copyFrom: col.copyFrom || "",
- compareTo: col.compareTo, // 添加 compareTo 字段
- type: col.bodyType || "input",
- filledCodes: col.filledCodes,
- };
- if (col.bodyDisabled) {
- item.disabled = col.bodyDisabled;
- }
- if (col.qxbdType) {
- item.qxbdType = col.qxbdType;
- }
- if (col.regentFillType) {
- item.regentFillType = col.regentFillType;
- }
- if (col.checkType) {
- item.checkType = col.checkType;
- }
- // 支持动态checkboxLabel - 从行数据中获取
- const dynamicLabelKey = col.prop + 'Label';
- if (currentItem && currentItem[dynamicLabelKey]) {
- // 优先从行数据中获取动态label(如jzbh1Label)
- item.checkboxLabel = currentItem[dynamicLabelKey];
- } else if (col.checkboxLabel !== undefined && col.checkboxLabel !== '') {
- // 否则使用列配置的checkboxLabel
- item.checkboxLabel = this.$t(col.checkboxLabel);
- }
- if (col.bodyType === "operableInput") {
- if (currentItem.isComplete || this.templateFillType !== 'actFill') {
- item.disabled = true;
- } else {
- item.disabled = false;
- }
- }
- if (col.noBorder) {
- item.noBorder = true;
- }
- if (col.bodyLayout) {
- item.layout = col.bodyLayout;
- }
-
- return item
- },
- getBodyButtonItem(col,) {
- return {
- buttonName: col.bodySubButtonName,
- fillType: col.bodySubFillType,
- type: "button",
- }
- },
- getBodyThirdButtonItem(col, rowIndex) {
- return {
- buttonName: col.bodyThirdButtonName,
- fillType: col.bodyThirdFillType,
- type: "button",
- }
- },
- getBodySubItem(col) {
- const item = {
- fillType: col.bodySubFillType,
- options: col.bodySubOptions,
- maxlength: col.bodySubMaxlength || 10,
- label: "",
- placeholder: col.bodySubPlaceholder || (col.bodySubType === 'select' ? '请选择' : '请输入'),
- precision: col.subPrecision,
- compareTo: col.bodySubCompareTo, // 添加 compareTo 字段
- type: col.bodySubType || "input",
- }
- if (col.bodySubDisabled) {
- item.disabled = col.bodySubDisabled;
- }
- return item
- },
- // 删除行
- deleteRow(rowIndex) {
- this.localDataSource.splice(rowIndex, 1);
- this.$emit('row-delete', rowIndex);
- },
- deleteRows(rowsIndex) {
- rowsIndex.sort((a, b) => b - a);
- rowsIndex.forEach(index => {
- this.localDataSource.splice(index, 1);
- this.$emit('row-delete', index);
- });
-
- },
- deleteSelectedRows(rowsIndex) {
- this.deleteRows(rowsIndex);
- this.selectedRows = [];
- this.isIndeterminate = false;
- this.$emit('selectionChange', this.selectedRows);
- },
- updateHeaderSelectFields(fields) {
- this.headerSelectFields = { ...this.headerSelectFields, ...fields };
- },
- // 更新数据方法,可在formData变更时调用,也可由父组件调用
- updateDataSource(dataSource = []) {
- this.oldLocalDataSource = JSON.parse(JSON.stringify(this.localDataSource));
- // 深拷贝数据以避免直接修改原始数据
- this.localDataSource = JSON.parse(JSON.stringify(dataSource || [])).map(row => ({
- ...row,
- _checked: false // 初始化选中状态为 false
- }));
- this.updateCheckStatus();
- this.checkCompareToOnDataLoad();
- },
- // 根据行索引更新数据 autoUpdateRecord 是否自动更新记录
- updateDataSourceByRowIndex(rowIndex, data, updateFieldsInfo = {}) {
- const { signData, updateFields = [] } = updateFieldsInfo;
- this.oldLocalDataSource = JSON.parse(JSON.stringify(this.localDataSource));
- this.localDataSource[rowIndex] = { ...this.localDataSource[rowIndex], ...data };
- this.localDataSource = [...this.localDataSource];
- if (updateFields.length > 0) {
- updateFields.map((key) => {
- const ref = this.$refs[key + rowIndex];
- if (ref) {
- ref[0].handleUpdateRecord(signData, { oldValue: this.oldLocalDataSource[rowIndex][key], inputValue: data[key] });
- }
- })
- }
-
- this.checkCompareToOnDataLoad();
- // justUpdateFilledFormData();
- },
- pushDataSource(data = []) {
- this.localDataSource.push(...data);
- this.localDataSource = [...this.localDataSource];
- this.checkCompareToOnDataLoad();
- justUpdateFilledFormData();
- },
- // 比较newData和oldData的值是否相等,只要有一对不相等就返回false
- compareOldAndCurrentFormFields(newData, oldData) {
- for (const key in newData) {
- const oldValue = newData[key];
- const currentValue = oldData[key];
- if (JSON.stringify(oldValue) !== JSON.stringify(currentValue)) {
- return false;
- } else {
- return false;
- }
- }
-
- return true;
- },
- // 处理全选
- handleCheckAllChange(val) {
- this.localDataSource.forEach(row => {
- row._checked = val;
- });
- this.updateCheckStatus();
- this.$emit('selectionChange', this.selectedRows);
- },
- // 处理单个 checkbox 变化
- handleCheckChange(row, val) {
- row._checked = val;
- this.updateCheckStatus();
- this.$emit('selectionChange', this.selectedRows);
- },
- // 更新选中状态和半选状态
- updateCheckStatus() {
- const totalRows = this.localDataSource.length;
- const checkedRows = this.localDataSource.filter(row => row._checked).length;
- this.checkAll = checkedRows === totalRows && totalRows > 0;
- this.isIndeterminate = checkedRows > 0 && checkedRows < totalRows;
- // 记录选中的行数据和对应的行索引
- this.selectedRows = this.localDataSource.map((row, rowIndex) => ({
- ...row,
- rowIndex
- })).filter(item => item._checked);
- },
- onAddRow() {
- if (this.$listeners && this.$listeners['onAddRow']) {
- this.$emit('onAddRow', { dataSource: this.localDataSource });
- return;
- }
- this.addRow({
- actSolutionVolumePrecision: 3,//小数点精度默认为3
- actSolutionConcentrationPrecision: 3,//小数点精度默认为3
- targetDiluentVolumePrecision: 3,//小数点精度默认为3
- targetStartSolutionVolumePrecision: 3,//小数点精度默认为3
- id: getuuid(),
- rowIndex: this.localDataSource.length,
- });
- justUpdateFilledFormData()
- },
-
- // 添加行
- addRow(row = {}) {
- this.localDataSource.push({
- ...row,
- _checked: false // 初始化选中状态为 false
- });
- this.updateCheckStatus();
- },
- addRows(rows = []) {
- this.localDataSource.push(...rows.map(row => ({
- ...row,
- _checked: false // 初始化选中状态为 false
- })));
- this.updateCheckStatus();
- },
- getDataSource() {
- return this.localDataSource;
- },
-
- // 判断表单项是否有错误
- hasError(rowIndex, colIndex, field) {
- return this.formErrors.some(error =>
- error.rowIndex === rowIndex &&
- error.colIndex === colIndex &&
- error.field === field
- );
- },
- // 处理错误状态更新
- onErrorUpdate(rowIndex, colIndex, field, isError) {
- if (!isError) {
- this.formErrors = this.formErrors.filter(error =>
- !(error.rowIndex === rowIndex &&
- error.colIndex === colIndex &&
- error.field === field)
- );
- }
- },
- // onSubBlur(rowIndex, colKey, value) {
- // this.$emit("blur", { rowIndex, colKey, value, item: this.localDataSource[rowIndex] });
- // },
- // 检查是否需要橙色背景
- hasOrangeBg(rowIndex, colIndex, field) {
- const key = `${rowIndex}-${colIndex}-${field}`;
- return this.orangeBgCells[key] || false;
- },
- // 设置橙色背景状态
- setOrangeBg(rowIndex, colIndex, field, status) {
- const key = `${rowIndex}-${colIndex}-${field}`;
- this.$set(this.orangeBgCells, key, status);
- },
- onBlur(rowIndex, colKey) {
- const value = this.localDataSource[rowIndex][colKey];
-
- // 查找对应的列配置
- const col = this.columns.find(c => c.prop === colKey);
- if (col && col.bodyFillType === "actFill" && col.compareTo) {
- const compareToValue = this.localDataSource[rowIndex][col.compareTo];
-
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (value !== compareToValue) {
- this.setOrangeBg(rowIndex, this.columns.findIndex(c => c.prop === colKey), colKey, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, this.columns.findIndex(c => c.prop === colKey), colKey, false);
- }
- }
-
- this.$emit("blur", { rowIndex, colKey, value, dataSource: this.localDataSource, headerSelectFields: this.headerSelectFields, item: this.localDataSource[rowIndex] });
- },
- onSubBlur(rowIndex, colKey, value) {
- // 查找对应的列配置
- const col = this.columns.find(c => c.bodySubKey === colKey);
- if (col && col.bodySubFillType === "actFill" && col.bodySubCompareTo) {
- const compareToValue = this.localDataSource[rowIndex][col.bodySubCompareTo];
-
- // 比较当前值和compareTo值,如果不相等则设置橙色背景
- if (value !== compareToValue) {
- this.setOrangeBg(rowIndex, this.columns.findIndex(c => c.bodySubKey === colKey), colKey, true);
- } else {
- // 相等则移除橙色背景
- this.setOrangeBg(rowIndex, this.columns.findIndex(c => c.bodySubKey === colKey), colKey, false);
- }
- }
-
- this.$emit("blur", { rowIndex, colKey, value, dataSource: this.localDataSource, headerSelectFields: this.headerSelectFields, item: this.localDataSource[rowIndex] });
- }
- }
- };
- </script>
-
- <style scoped>
- .custom-table-wrapper {
- border: 1px solid #ebeef5;
- border-radius: 4px;
- overflow: hidden;
- font-size: 14px;
- color: #606266;
- margin-top: 20px;
-
- &.no-border {
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- border-radius: 5px 5px;
- border: none;
-
- .custom-table-cell {
- border-right: none;
- }
-
- .custometable-row {
- display: flex;
- border-bottom: none;
- }
- }
- }
-
- .inner-table-cell {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .m-l-5 {
- margin-left: 5px;
- }
-
- .sub-input-number {
- width: 145px;
-
- .el-input-number--mini {
- width: 145px;
- }
- }
-
- /* 表头 */
- .custom-table-header {
- background-color: #f5f7fa;
- border-bottom: 1px solid #ebeef5;
- white-space: nowrap;
- display: block;
- }
-
- .custom-table-body {
- /* max-height: 500px; */
- /* overflow-y: auto; */
- /* 可根据需要调整或由父组件控制 */
- }
-
- .header-cell-content {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .header-columns-grid {
- display: grid;
- gap: 10px;
- }
-
- .header-column-item {
- display: flex;
- align-items: center;
- padding: 0 5px;
- }
-
- /* 共同行样式 */
- .custom-table-row {
- display: table;
- width: 100%;
- table-layout: fixed;
- }
-
- .custometable-row {
- display: table;
- width: 100%;
- table-layout: fixed;
-
- &:not(:last-child) {
- border-bottom: 1px solid #ebeef5;
- }
- }
-
- /* 单元格 */
- .custom-table-cell {
- display: table-cell;
- padding: 12px 10px;
- text-align: left;
- vertical-align: middle;
- border-right: 1px solid #ebeef5;
- page-break-inside: avoid;
- box-sizing: border-box;
- }
-
- .custom-table-cell:last-child {
- border-right: none;
- }
-
- .header-cell {
- color: #909399;
- background-color: #f5f7fa;
- font-size: 12px;
- word-break: break-word;
- white-space: normal;
- }
-
-
-
- .body-cell {
- color: #606266;
- page-break-inside: avoid;
- background-color: #fff;
- }
-
- /* select 样式(模仿 Element UI) */
- .header-cell select {
- width: 100%;
- padding: 4px 8px;
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- outline: none;
- background-color: #fff;
- font-size: 13px;
- color: #606266;
- appearance: none;
- /* 隐藏默认箭头(可选) */
- background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e");
- background-repeat: no-repeat;
- background-position: right 8px center;
- background-size: 14px;
- padding-right: 28px;
- }
-
- /* 滚动容器:如果整体宽度超限,显示横向滚动条 */
- .custom-table-wrapper {
- display: flex;
- flex-direction: column;
- max-width: 100%;
- /* 父容器决定宽度 */
- overflow: auto;
- max-height: 500px;
- }
-
- .custom-table-header,
- .custom-table-body {
- min-width: 100%;
- }
-
- .header-select {
- width: 100px;
- margin-left: 5px;
- }
-
- .no-data {
- text-align: center;
- padding: 20px 0;
- color: rgb(144, 147, 153)
- }
-
- .add-row {
- display: flex;
- justify-content: center;
- padding: 20px 0;
- margin-top: 20px;
- }
-
- .flex1 {
- flex: 1;
- }
-
- .flex {
- display: flex;
- }
-
- .other-title {
- text-align: right;
- margin: 0 10px;
- font-size: 14px;
- font-weight: normal;
- color: #606266;
- width: auto;
- }
-
- .body-span {
- text-align: center;
- }
-
- .item-center {
- display: flex;
- align-items: center;
- }
-
- .mr-5 {
- margin-right: 5px;
- }
-
- .sort-cell {
- text-align: center;
- width: 100px;
- }
-
- .flex-wrap {
- flex-wrap: wrap;
- gap: 10px;
- }
-
- .row-error-border {
- box-shadow: 0 0 6px #ffc3c3;
- padding: 8px;
- border-radius: 4px;
- border: 1px solid #ff5d5d;
- }
-
- .checkbox-item {
- /* width: 50px; */
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .c-cell {
- width: 50px;
- }
-
- .span-content {
- width: -webkit-fill-available;
- text-align: center;
- }
-
- .add-icon {
- color: #409eff;
- font-size: 20px;
- margin-left: 10px;
- cursor: pointer;
- }
-
- .remove-icon {
- color: #ff4949;
- font-size: 20px;
- margin-left: 5px;
- cursor: pointer;
- }
-
- .full-row {
- grid-column: span 2;
- }
-
- .grid-container {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- /* 默认2列 */
- gap: 5px;
- /* 防止网格容器被分割到不同页面 */
- page-break-inside: avoid;
- break-inside: avoid;
- }
- </style>
|