refs #5673 feat(FormModel): support crud
This commit is contained in:
parent
b7bbb4ba41
commit
e2e34089e2
|
@ -29,12 +29,26 @@ const $props = defineProps({
|
|||
type: String,
|
||||
default: null,
|
||||
},
|
||||
crud: {
|
||||
type: Boolean,
|
||||
default: null,
|
||||
},
|
||||
primaryKey: {
|
||||
type: String,
|
||||
default: 'id',
|
||||
},
|
||||
dataRequired: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onFetch']);
|
||||
|
||||
defineExpose({
|
||||
save,
|
||||
insert,
|
||||
remove,
|
||||
});
|
||||
|
||||
onMounted(async () => await fetch());
|
||||
|
@ -55,7 +69,7 @@ async function fetch() {
|
|||
});
|
||||
|
||||
state.set($props.model, data);
|
||||
originalData.value = Object.assign({}, data);
|
||||
originalData.value = JSON.parse(JSON.stringify(data));
|
||||
|
||||
watch(formData.value, () => (hasChanges.value = true));
|
||||
|
||||
|
@ -72,7 +86,7 @@ async function save() {
|
|||
isLoading.value = true;
|
||||
await axios.patch($props.urlUpdate || $props.url, formData.value);
|
||||
|
||||
originalData.value = formData.value;
|
||||
originalData.value = JSON.parse(JSON.stringify(formData.value));
|
||||
hasChanges.value = false;
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -96,22 +110,157 @@ function filter(value, update, filterOptions) {
|
|||
);
|
||||
}
|
||||
|
||||
async function crudSave() {
|
||||
if (!hasChanges.value) {
|
||||
return quasar.notify({
|
||||
type: 'negative',
|
||||
message: t('globals.noChanges'),
|
||||
});
|
||||
}
|
||||
isLoading.value = true;
|
||||
const changes = getChanges();
|
||||
await saveChanges(changes);
|
||||
if (changes.creates?.length) await fetch();
|
||||
}
|
||||
|
||||
async function saveChanges(changes) {
|
||||
try {
|
||||
await axios.post($props.urlUpdate || $props.url + '/crud', changes);
|
||||
} catch (e) {
|
||||
quasar.notify({
|
||||
type: 'negative',
|
||||
message: 'Some fields are invalid',
|
||||
});
|
||||
}
|
||||
|
||||
originalData.value = JSON.parse(JSON.stringify(formData.value));
|
||||
hasChanges.value = false;
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
async function insert() {
|
||||
const $index = formData.value.length + 1;
|
||||
formData.value.push(Object.assign({ $index }, $props.dataRequired));
|
||||
hasChanges.value = true;
|
||||
}
|
||||
|
||||
// function addRemove(ids) {
|
||||
// for (let id of ids) {
|
||||
// const index = removed.value.indexOf(id);
|
||||
// if (index > -1) {
|
||||
// removed.value = removed.value.slice(index, 1);
|
||||
// continue;
|
||||
// }
|
||||
// removed.value.push(id);
|
||||
// }
|
||||
// }
|
||||
|
||||
async function remove(data) {
|
||||
if (!data.length)
|
||||
return quasar.notify({
|
||||
type: 'warning',
|
||||
message: t('globals.noChanges'),
|
||||
});
|
||||
|
||||
const pk = $props.primaryKey;
|
||||
let ids = data.map((d) => d[pk]).filter(Boolean);
|
||||
let preRemove = data.map((d) => d.$index).filter(Boolean);
|
||||
let newData = formData.value;
|
||||
|
||||
// addRemove(ids);
|
||||
if (preRemove.length) {
|
||||
newData = newData.filter(
|
||||
(form) => !preRemove.some((index) => index == form.$index)
|
||||
);
|
||||
state.set($props.model, newData);
|
||||
const changes = getChanges();
|
||||
if (!changes.creates?.length && !changes.updates?.length)
|
||||
hasChanges.value = false;
|
||||
}
|
||||
if (ids.length) {
|
||||
await saveChanges({ deletes: ids });
|
||||
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
|
||||
state.set($props.model, newData);
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
if ($props.crud) return crudSave();
|
||||
return save();
|
||||
}
|
||||
|
||||
watch(formUrl, async () => {
|
||||
originalData.value = null;
|
||||
reset();
|
||||
fetch();
|
||||
});
|
||||
|
||||
function getChanges() {
|
||||
const updates = [];
|
||||
const creates = [];
|
||||
|
||||
const pk = $props.primaryKey;
|
||||
|
||||
for (const [i, row] of formData.value.entries()) {
|
||||
if (!row[pk]) {
|
||||
creates.push(row);
|
||||
} else if (originalData.value) {
|
||||
const data = getDifferences(originalData.value[i], row);
|
||||
if (!isEmpty(data)) {
|
||||
updates.push({
|
||||
data,
|
||||
where: { [pk]: row[pk] },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const changes = { updates, creates };
|
||||
|
||||
for (let prop in changes) {
|
||||
if (changes[prop].length === 0) changes[prop] = undefined;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
function getDifferences(obj1, obj2) {
|
||||
let diff = {};
|
||||
for (let key in obj1) {
|
||||
if (obj2[key] && obj1[key] !== obj2[key]) {
|
||||
diff[key] = obj2[key];
|
||||
}
|
||||
}
|
||||
for (let key in obj2) {
|
||||
if (obj1[key] === undefined && obj2[key]) {
|
||||
diff[key] = obj2[key];
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
if (obj == null) return true;
|
||||
if (obj === undefined) return true;
|
||||
if (Object.keys(obj).length === 0) return true;
|
||||
|
||||
if (obj.length > 0) return false;
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<QBanner v-if="hasChanges" class="text-white bg-warning">
|
||||
<QIcon name="warning" size="md" class="q-mr-md" />
|
||||
<span>{{ t('globals.changesToSave') }}</span>
|
||||
</QBanner>
|
||||
<QForm v-if="formData" @submit="save" @reset="reset" class="q-pa-md">
|
||||
<QForm v-if="formData" @submit="onSubmit" @reset="reset" class="q-pa-md">
|
||||
<slot name="form" :data="formData" :validate="validate" :filter="filter"></slot>
|
||||
<div class="q-mt-lg">
|
||||
<slot name="actions">
|
||||
<QBtn :label="t('globals.save')" type="submit" color="primary" />
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
type="submit"
|
||||
color="primary"
|
||||
:disable="!hasChanges"
|
||||
/>
|
||||
<QBtn
|
||||
:label="t('globals.reset')"
|
||||
type="reset"
|
||||
|
|
Loading…
Reference in New Issue