feat: refs #8406 upgraded CrudModel
This commit is contained in:
parent
5d6784588f
commit
e874375276
|
@ -42,7 +42,15 @@ const $props = defineProps({
|
|||
},
|
||||
dataRequired: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
default: () => ({}),
|
||||
},
|
||||
dataDefault: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
insertOnLoad: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
defaultSave: {
|
||||
type: Boolean,
|
||||
|
@ -86,6 +94,9 @@ const vnPaginateRef = ref();
|
|||
const formData = ref([]);
|
||||
const saveButtonRef = ref(null);
|
||||
const watchChanges = ref();
|
||||
let isNotEqual = ref(false);
|
||||
let isLastRowEmpty = ref(false);
|
||||
const isFirstFetch = ref(true);
|
||||
const formUrl = computed(() => $props.url);
|
||||
|
||||
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
||||
|
@ -122,9 +133,14 @@ async function fetch(data) {
|
|||
const rows = keyData ? data[keyData] : data;
|
||||
resetData(rows);
|
||||
emit('onFetch', rows);
|
||||
if (isFirstFetch.value && $props.insertOnLoad) {
|
||||
await insert();
|
||||
}
|
||||
isFirstFetch.value = false;
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
function resetData(data) {
|
||||
if (!data) return;
|
||||
if (data && Array.isArray(data)) {
|
||||
|
@ -132,12 +148,27 @@ function resetData(data) {
|
|||
data.map((d) => (d.$index = $index++));
|
||||
}
|
||||
originalData.value = JSON.parse(JSON.stringify(data));
|
||||
|
||||
formData.value = JSON.parse(JSON.stringify(data));
|
||||
|
||||
if (watchChanges.value) watchChanges.value(); //destroy watcher
|
||||
watchChanges.value = watch(formData, () => (hasChanges.value = true), { deep: true });
|
||||
watchChanges.value = watch(formData, (nVal) => {
|
||||
hasChanges.value = false;
|
||||
for(let index = 0; index < nVal.length; index++) {
|
||||
const curRow = nVal[index];
|
||||
const originalRow = originalData.value[index];
|
||||
if(originalRow && JSON.stringify(removeIndexField(curRow)) == JSON.stringify(removeIndexField(originalRow))) continue;
|
||||
for(const key in curRow) {
|
||||
if(key == '$index') continue;
|
||||
if(Object.hasOwn($props.dataRequired || {}, key)) continue;
|
||||
if(curRow[key]) {
|
||||
hasChanges.value = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { deep: true });
|
||||
}
|
||||
|
||||
async function reset() {
|
||||
await fetch(originalData.value);
|
||||
hasChanges.value = false;
|
||||
|
@ -165,7 +196,9 @@ async function onSubmit() {
|
|||
});
|
||||
}
|
||||
isLoading.value = true;
|
||||
|
||||
await saveChanges($props.saveFn ? formData.value : null);
|
||||
|
||||
}
|
||||
|
||||
async function onSubmitAndGo() {
|
||||
|
@ -203,14 +236,36 @@ async function saveChanges(data) {
|
|||
});
|
||||
}
|
||||
|
||||
async function insert(pushData = $props.dataRequired) {
|
||||
const $index = formData.value.length
|
||||
? formData.value[formData.value.length - 1].$index + 1
|
||||
: 0;
|
||||
formData.value.push(Object.assign({ $index }, pushData));
|
||||
hasChanges.value = true;
|
||||
async function insert(pushData = { ...$props.dataRequired, ...$props.dataDefault }) {
|
||||
const lastRow = formData.value.at(-1);
|
||||
const $index = lastRow?.$index >= 0 ? lastRow.$index + 1 : 0;
|
||||
isNotEqual = JSON.stringify(removeIndexField(formData.value)) !== JSON.stringify(removeIndexField(originalData.value));
|
||||
isLastRowEmpty = checkLastRow(lastRow);
|
||||
if (isNotEqual && isLastRowEmpty) return;
|
||||
|
||||
const nRow = Object.assign({ $index }, pushData);
|
||||
formData.value.push(nRow);
|
||||
for (const key in nRow) {
|
||||
if (isChange(nRow, key)) continue;
|
||||
else {
|
||||
hasChanges.value = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isChange(row,key){
|
||||
return !row[key] || key == '$index' || Object.hasOwn($props.dataRequired || {}, key);
|
||||
}
|
||||
|
||||
function checkLastRow(lastRow) {
|
||||
for (const key in lastRow) {
|
||||
if (isChange(lastRow, key)) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async function remove(data) {
|
||||
if (!data.length)
|
||||
return quasar.notify({
|
||||
|
@ -220,7 +275,7 @@ async function remove(data) {
|
|||
|
||||
const pk = $props.primaryKey;
|
||||
let ids = data.map((d) => d[pk]).filter(Boolean);
|
||||
let preRemove = data.map((d) => (d[pk] ? null : d.$index)).filter(Boolean);
|
||||
let preRemove = data.map((d) => (d[pk] ? null : d.$index)).filter(index => index !== null && index !== undefined);
|
||||
let newData = formData.value;
|
||||
|
||||
if (preRemove.length) {
|
||||
|
@ -249,8 +304,23 @@ async function remove(data) {
|
|||
fetch(newData);
|
||||
});
|
||||
} else {
|
||||
reset();
|
||||
await fetch(formData.value);
|
||||
hasChanges.value = false;
|
||||
|
||||
const lastRow = formData.value.at(-1);
|
||||
|
||||
const limitedFormData = formData.value.slice(0, originalData.value.length);
|
||||
isNotEqual = JSON.stringify(removeIndexField(limitedFormData)) !== JSON.stringify(removeIndexField(originalData.value));
|
||||
|
||||
const additionalRows = formData.value.slice(originalData.value.length);
|
||||
const hasNonEmptyAdditionalRows = additionalRows.some(row => !checkLastRow(row));
|
||||
|
||||
|
||||
if (isNotEqual || hasNonEmptyAdditionalRows) {
|
||||
hasChanges.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
emit('update:selected', []);
|
||||
}
|
||||
|
||||
|
@ -261,7 +331,7 @@ function getChanges() {
|
|||
const pk = $props.primaryKey;
|
||||
for (const [i, row] of formData.value.entries()) {
|
||||
if (!row[pk]) {
|
||||
creates.push(row);
|
||||
creates.push(Object.assign(row, { ...$props.dataRequired }));
|
||||
} else if (originalData.value[i]) {
|
||||
const data = getDifferences(originalData.value[i], row);
|
||||
if (!isEmpty(data)) {
|
||||
|
@ -287,6 +357,16 @@ function isEmpty(obj) {
|
|||
return !Object.keys(obj).length;
|
||||
}
|
||||
|
||||
function removeIndexField(data) {
|
||||
if (Array.isArray(data)) {
|
||||
return data.map(({ $index, ...rest }) => rest);
|
||||
} else if (typeof data === 'object' && data !== null) {
|
||||
const { $index, ...rest } = data;
|
||||
return rest;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function reload(params) {
|
||||
const data = await vnPaginateRef.value.fetch(params);
|
||||
fetch(data);
|
||||
|
|
|
@ -649,6 +649,7 @@ const rowCtrlClickFunction = computed(() => {
|
|||
:class="$attrs['class'] ?? 'q-px-md'"
|
||||
:limit="$attrs['limit'] ?? 100"
|
||||
ref="CrudModelRef"
|
||||
:insert-on-load="crudModel.insertOnLoad"
|
||||
@on-fetch="(...args) => emit('onFetch', ...args)"
|
||||
:search-url="searchUrl"
|
||||
:disable-infinite-scroll="isTableMode"
|
||||
|
|
|
@ -85,6 +85,7 @@ onBeforeMount(async () => {
|
|||
data-key="InvoiceInDueDays"
|
||||
url="InvoiceInDueDays"
|
||||
:filter="filter"
|
||||
:insert-on-load="false"
|
||||
auto-load
|
||||
:data-required="{ invoiceInFk: invoiceId }"
|
||||
v-model:selected="rowsSelected"
|
||||
|
|
|
@ -76,15 +76,22 @@ const insertTag = (rows) => {
|
|||
model="ItemTags"
|
||||
url="ItemTags"
|
||||
:data-required="{
|
||||
$index: undefined,
|
||||
itemFk: route.params.id,
|
||||
priority: undefined,
|
||||
tag: {
|
||||
isFree: undefined,
|
||||
isFree: true,
|
||||
value: undefined,
|
||||
name: undefined,
|
||||
},
|
||||
|
||||
}"
|
||||
:data-default="{
|
||||
tag: {
|
||||
isFree: true,
|
||||
value: undefined,
|
||||
name: undefined,
|
||||
},
|
||||
tagFk: undefined,
|
||||
priority: undefined,
|
||||
}"
|
||||
:default-remove="false"
|
||||
:user-filter="{
|
||||
|
|
|
@ -58,6 +58,7 @@ const submitTaxes = async (data) => {
|
|||
:save-fn="submitTaxes"
|
||||
:filter="taxesFilter"
|
||||
:default-remove="false"
|
||||
:insert-on-load="false"
|
||||
data-key="ItemTax"
|
||||
model="ItemTax"
|
||||
ref="ItemTaxRef"
|
||||
|
|
|
@ -24,10 +24,10 @@ const crudModelFilter = reactive({
|
|||
where: { ticketFk: route.params.id },
|
||||
});
|
||||
|
||||
const crudModelRequiredData = computed(() => ({
|
||||
const crudModelDefaultData = computed(() => ({
|
||||
created: Date.vnNew(),
|
||||
packagingFk: null,
|
||||
quantity: 0,
|
||||
created: Date.vnNew(),
|
||||
ticketFk: route.params.id,
|
||||
}));
|
||||
|
||||
|
@ -59,7 +59,7 @@ watch(
|
|||
url="TicketPackagings"
|
||||
model="TicketPackagings"
|
||||
:filter="crudModelFilter"
|
||||
:data-required="crudModelRequiredData"
|
||||
:data-default="crudModelDefaultData"
|
||||
:default-remove="false"
|
||||
auto-load
|
||||
style="max-width: 800px"
|
||||
|
|
|
@ -690,6 +690,7 @@ watch(
|
|||
:create-as-dialog="false"
|
||||
:crud-model="{
|
||||
disableInfiniteScroll: true,
|
||||
insertOnLoad: false,
|
||||
}"
|
||||
:default-remove="false"
|
||||
:default-reset="false"
|
||||
|
|
Loading…
Reference in New Issue