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.

244 lines
6.1 KiB

4 months ago
<template>
<div class="editable-cell">
<!-- 显示模式 -->
<div class="editable-cell-text-wrapper" v-if="!getRowValue && !editable">
<div> {{ value }}</div>
<div class="editable-cell-action">
<edit-outlined class="editable-cell-icon" @click="editCell" />
</div>
</div>
<!-- 编辑模式 -->
<a-popover
v-else
:destroyTooltipOnHide="true"
:visible="!isUndefined(getValidateInfo) && visible"
:content="getValidateInfo?.message"
:overlayClassName="'ns-cell-rule-popover'"
:getPopupContainer="(triggerNode) => triggerNode.parentNode"
>
<div class="editable-cell-input-wrapper">
<component :is="column.edit.component || 'NsInput'" v-bind="formProps" />
<!--单元格编辑-->
<div class="editable-cell-action" v-if="editable">
<check-outlined class="editable-cell-icon" @click="saveCell" />
<!-- <close-outlined class="editable-cell-icon" @click="cancelCell" /> -->
</div>
</div>
</a-popover>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, inject, nextTick, PropType, ref, watch } from 'vue';
import { PropTypes } from '/nerv-lib/util/type';
import { CheckOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons-vue';
import { TableEdit } from '/nerv-lib/component/table/use-table-edit';
import { isUndefined, upperFirst } from 'lodash-es';
import Schema from 'async-validator';
export default defineComponent({
name: 'NsTableCell',
components: {
EditOutlined,
CheckOutlined,
CloseOutlined,
},
props: {
value: {
type: [String, Number, Boolean, Object] as PropType<string | number | boolean | Recordable>,
default: '',
required: true,
},
record: {
type: Object as PropType<Recordable>,
required: true,
},
column: {
type: Object as PropType<Recordable>,
required: true,
default: () => ({}),
},
index: PropTypes.number,
},
setup(props) {
const {
getValidate,
setValidate,
setValue,
getValue,
getKey,
validate,
tableEdit,
tableSave,
} = inject('tableEdit') as TableEdit;
const visible = ref(true);
const getRowKey = computed(() => {
return getKey({ ...props.record });
});
const getField = computed(() => {
return props.column.dataIndex;
});
let editable = ref(false);
const getCellValue = computed({
get: () => getValue(getRowKey.value, getField.value),
set: (val) => setValue(getRowKey.value, val, getField.value),
});
watch(
() => props.index,
() => {
console.log('index', props.record, props.index);
},
{
deep: true,
}
);
const getRowValue = computed(() => {
return getValue(getRowKey.value);
});
const getValidateInfo = computed({
get: () => getValidate(getRowKey.value, getField.value),
set: (val) => setValidate(getRowKey.value, val, getField.value),
});
// setTimeout(() => console.log('getCellValue', getCellValue.value), 1000);
watch(
[() => getCellValue.value, () => getRowValue.value],
() => {
validate(getRowKey.value, getField.value);
},
{
immediate: true,
}
);
/**
* 解决删除后验证遗留的问题
*/
watch(
() => props.index,
() => {
if (getValidateInfo.value) {
visible.value = false;
// 延迟等待隐藏动画操作
setTimeout(() => {
visible.value = true;
});
}
}
);
const editCell = () => {
tableEdit(getRowKey.value, getField.value);
editable.value = true;
};
const cancelCell = () => {
getValidateInfo.value = undefined; //清空验证信息
editable.value = false;
};
const saveCell = () => {
// console.log('getValidated.value', getValidated.value);
if (!getValidateInfo.value) {
editable.value = false;
tableSave(getRowKey.value, getField.value);
}
};
const formProps = computed(() => {
const {
component,
valueField,
changeEvent = 'change',
props: componentProps,
} = props.column.edit;
const isCheck =
component && ['NsSwitch', 'NsCheckbox', 'Switch', 'Checkbox'].includes(component);
const bindValue: Recordable = {
[valueField || (isCheck ? 'checked' : 'value')]: getCellValue.value,
};
const eventKey = `on${upperFirst(changeEvent)}`;
const on = {
[eventKey]: (...args: Nullable<Recordable>[]) => {
const [e] = args;
const target = e ? e.target : null;
getCellValue.value = target ? (isCheck ? target.checked : target.value) : e;
},
};
return {
...componentProps,
...bindValue,
...on,
};
});
return {
editCell,
saveCell,
cancelCell,
editable,
formProps,
visible,
getValidateInfo,
getCellValue,
getRowValue,
isUndefined,
};
},
});
</script>
<style lang="less" scoped>
.ns-cell-rule-popover {
color: @error-color;
}
.editable-cell {
position: relative;
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.editable-cell-action {
width: 36px;
display: flex;
align-items: center;
justify-content: center;
}
.editable-cell-icon {
width: 24px;
line-height: 28px;
opacity: 0;
}
&:hover .editable-cell-icon {
color: #108ee9;
opacity: 1;
}
.editable-add-btn {
margin-bottom: 8px;
}
}
.editable-cell:hover .editable-cell-icon {
display: inline-block;
}
:deep(.ant-popover) {
z-index: 50;
}
</style>