push
This commit is contained in:
275
lib/component/table/use-table-edit.ts
Normal file
275
lib/component/table/use-table-edit.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
import { cloneDeep, isUndefined } from 'lodash-es';
|
||||
import {
|
||||
ComputedRef,
|
||||
getCurrentInstance,
|
||||
inject,
|
||||
reactive,
|
||||
ref,
|
||||
Ref,
|
||||
toRaw,
|
||||
UnwrapRef,
|
||||
watch,
|
||||
} from 'vue';
|
||||
import Schema from 'async-validator';
|
||||
import { RuleItem, ValidateError } from 'async-validator/dist-types/interface';
|
||||
|
||||
export interface TableEdit {
|
||||
tableEdit?: Function;
|
||||
tableSave?: Function;
|
||||
tableCancel?: Function;
|
||||
tableDelete?: Function;
|
||||
addRow?: Function;
|
||||
getKey?: Function;
|
||||
validate?: Function;
|
||||
getValidate?: Function;
|
||||
setValidate?: Function;
|
||||
setValue?: Function;
|
||||
getValue?: Function;
|
||||
}
|
||||
|
||||
export interface UseTableEdit {
|
||||
dataSource: Ref<Recordable[]>;
|
||||
columns: ComputedRef<Recordable[]>;
|
||||
rowKey: String;
|
||||
editable: Ref<Boolean>;
|
||||
}
|
||||
|
||||
export function useTableEdit({ dataSource, columns, rowKey, editable }: UseTableEdit) {
|
||||
const instance = getCurrentInstance();
|
||||
const emit = instance?.emit;
|
||||
|
||||
const editableData: UnwrapRef<Recordable> = reactive({}); //编辑关联数据
|
||||
const validateData: UnwrapRef<Recordable> = reactive({}); //验证数据
|
||||
|
||||
let autoKey = 0;
|
||||
|
||||
function getKey(record: Recordable): string {
|
||||
// if (isUndefined(record[rowKey]))
|
||||
// console.error(`rowKey: ${rowKey} not find in ${JSON.stringify(record)}`);
|
||||
return record[rowKey];
|
||||
}
|
||||
|
||||
function getValue(key?: string, field?: string): any {
|
||||
if (!key && !field) {
|
||||
//表格编辑 editableData会附加额外的单元格字段
|
||||
return dataSource.value;
|
||||
} else if (!field) {
|
||||
//行编辑
|
||||
return editableData[key as string];
|
||||
}
|
||||
|
||||
return editableData[key] ? editableData[key][field] : editableData[`${key}_${field}`];
|
||||
// 单元格编辑
|
||||
}
|
||||
|
||||
function addRow(item = {}) {
|
||||
const row = cloneDeep(item);
|
||||
row[rowKey] = ++autoKey;
|
||||
dataSource.value.push(row);
|
||||
console.log('addRow', item);
|
||||
console.log('dataSource.value', dataSource.value);
|
||||
|
||||
tableEdit(row[rowKey]);
|
||||
}
|
||||
|
||||
function setValue(key: string, val: any, field?: string) {
|
||||
if (!field) {
|
||||
editableData[key] = val;
|
||||
} else {
|
||||
editableData[key]
|
||||
? (editableData[key][field] = val)
|
||||
: (editableData[`${key}_${field}`] = val);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteValue(key: string, field?: string) {
|
||||
if (!field) {
|
||||
delete editableData[key];
|
||||
} else {
|
||||
delete editableData[`${key}_${field}`];
|
||||
}
|
||||
}
|
||||
|
||||
function getValidate(key: string, field?: string) {
|
||||
if (!field) {
|
||||
return validateData[key];
|
||||
} else {
|
||||
return validateData[`${key}_${field}`];
|
||||
}
|
||||
}
|
||||
|
||||
function setValidate(key: string, val: any, field?: string) {
|
||||
if (!field) {
|
||||
validateData[key] = val;
|
||||
} else {
|
||||
validateData[`${key}_${field}`] = val;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteValidate(key: string, field?: string) {
|
||||
if (!field) {
|
||||
delete validateData[key];
|
||||
} else {
|
||||
delete validateData[`${key}_${field}`];
|
||||
}
|
||||
}
|
||||
|
||||
const validator: Recordable = {};
|
||||
const rules: RuleItem = inject('rules', ref({})).value;
|
||||
|
||||
if (rules.defaultField?.fields) {
|
||||
Object.keys(rules.defaultField.fields).forEach(function (key) {
|
||||
validator[key] = new Schema({ [key]: rules.defaultField.fields[key] });
|
||||
});
|
||||
}
|
||||
|
||||
validator['ROW'] = new Schema(rules.defaultField?.fields || {});
|
||||
validator['TABLE'] = new Schema({
|
||||
table: rules,
|
||||
});
|
||||
|
||||
const getValidator = (key = 'ROW') => {
|
||||
return validator[key];
|
||||
};
|
||||
/**
|
||||
* 验证行
|
||||
* @param key
|
||||
*/
|
||||
const validate = (key?: string, field?: string) => {
|
||||
if (!key && !field) {
|
||||
return getValidator('TABLE')
|
||||
.validate({ table: dataSource.value })
|
||||
.then(() => {
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch(({ errors }: { errors: ValidateError[] }) => {
|
||||
return Promise.reject(new Error(errors[0].message));
|
||||
});
|
||||
} else if (!field) {
|
||||
return getValidator('ROW')
|
||||
.validate(getValue(key))
|
||||
.then(() => {
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch(({ errors }: { errors: ValidateError[] }) => {
|
||||
return Promise.reject(new Error(errors[0].message));
|
||||
});
|
||||
} else if (key) {
|
||||
return getValidator(field)?.validate({ [field]: getValue(key, field) }, (errors) => {
|
||||
if (errors) {
|
||||
setValidate(key, errors[0], field);
|
||||
} else {
|
||||
setValidate(key, undefined, field);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 编辑行
|
||||
* @param key
|
||||
*/
|
||||
const tableEdit = (key: string, field?: string) => {
|
||||
const item = dataSource.value.filter((item) => key === item[rowKey as keyof Recordable])[0];
|
||||
|
||||
if (!field) {
|
||||
const validateItem: Recordable = {};
|
||||
Object.keys(item).forEach((field) => (validateItem[field] = undefined));
|
||||
setValidate(key, validateItem);
|
||||
|
||||
// 表格编辑时为引用,否则为深拷贝
|
||||
if (editable.value) {
|
||||
setValue(key, item);
|
||||
} else {
|
||||
setValue(key, cloneDeep(item));
|
||||
}
|
||||
} else {
|
||||
setValue(key, item[field], field);
|
||||
setValidate(key, undefined, field);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存
|
||||
* @param key
|
||||
*/
|
||||
const tableSave = (key: string, field?: string) => {
|
||||
const data = dataSource.value.filter(
|
||||
(item: Recordable) => key === item[rowKey as keyof Recordable]
|
||||
)[0];
|
||||
if (!field) {
|
||||
Object.assign(data, getValue(key));
|
||||
deleteValue(key);
|
||||
deleteValidate(key);
|
||||
} else {
|
||||
data[field] = getValue(key, field);
|
||||
emit?.('cellChange', { field, value: data[field], key, record: toRaw(data) });
|
||||
deleteValue(key, field);
|
||||
deleteValidate(key, field);
|
||||
}
|
||||
};
|
||||
|
||||
const tableDelete = (key: string) => {
|
||||
console.log('tableDelete', key);
|
||||
deleteValue(key);
|
||||
deleteValidate(key);
|
||||
|
||||
dataSource.value.splice(
|
||||
dataSource.value.findIndex((item) => item[rowKey] === key),
|
||||
1
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消编辑
|
||||
* @param key
|
||||
*/
|
||||
const tableCancel = (key: string, field?: string) => {
|
||||
if (field) {
|
||||
deleteValue(key);
|
||||
} else {
|
||||
deleteValue(key, field);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置dataSource111
|
||||
* @param data
|
||||
*/
|
||||
|
||||
watch(
|
||||
() => dataSource.value,
|
||||
(val, prev) => {
|
||||
// console.log(val, prev);
|
||||
if (editable.value) {
|
||||
Object.keys(editableData).forEach((key) => {
|
||||
delete editableData[key];
|
||||
});
|
||||
Object.keys(validateData).forEach((key) => {
|
||||
delete validateData[key];
|
||||
});
|
||||
console.log('dataSource.value', dataSource.value);
|
||||
dataSource.value.forEach((item) => {
|
||||
item[rowKey] = ++autoKey;
|
||||
tableEdit(item[rowKey as keyof Recordable]);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
return {
|
||||
tableEdit,
|
||||
tableSave,
|
||||
tableCancel,
|
||||
tableDelete,
|
||||
addRow,
|
||||
getKey,
|
||||
validate,
|
||||
getValidate,
|
||||
setValidate,
|
||||
setValue,
|
||||
getValue,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user