kashkool ver 1
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
class="!w-16"
|
||||
type="number"
|
||||
v-model:value="record.sort_order"
|
||||
@blur="() => saveSortOrder(record)"
|
||||
@onchange="() => scheduleSortOrder(record)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
@@ -53,7 +53,8 @@
|
||||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { TableColumnType } from 'ant-design-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { debounce } from 'lodash'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { getCategories, syncCategoriesFromProducts, updateCategory } from '@/api/category'
|
||||
import type { Category } from '@/model/category'
|
||||
|
||||
@@ -61,6 +62,12 @@ const loading = ref(false)
|
||||
const syncing = ref(false)
|
||||
const items = ref<Category[]>([])
|
||||
|
||||
type CategoryField = 'active' | 'show_in_filter' | 'show_in_select' | 'sort_order'
|
||||
|
||||
const pendingPatches = new Map<number, Partial<Record<CategoryField, number>>>()
|
||||
const debouncedFlush = new Map<number, ReturnType<typeof debounce>>()
|
||||
let syncInFlight: Promise<void> | null = null
|
||||
|
||||
const columns: TableColumnType<Category>[] = [
|
||||
{ title: 'نام دسته', dataIndex: 'name', key: 'name' },
|
||||
{
|
||||
@@ -106,50 +113,90 @@ async function fetchList() {
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleField(record: Category, field: 'active' | 'show_in_filter' | 'show_in_select', checked: boolean) {
|
||||
const prev = record[field]
|
||||
record[field] = checked ? 1 : 0
|
||||
function scheduleSave(record: Category, patch: Partial<Record<CategoryField, number>>) {
|
||||
const id = record.id
|
||||
const current = pendingPatches.get(id) ?? {}
|
||||
pendingPatches.set(id, { ...current, ...patch })
|
||||
|
||||
if (!debouncedFlush.has(id)) {
|
||||
debouncedFlush.set(
|
||||
id,
|
||||
debounce(() => flushSave(id), 500)
|
||||
)
|
||||
}
|
||||
debouncedFlush.get(id)!()
|
||||
}
|
||||
|
||||
async function flushSave(id: number) {
|
||||
const patch = pendingPatches.get(id)
|
||||
if (!patch || Object.keys(patch).length === 0) return
|
||||
pendingPatches.delete(id)
|
||||
|
||||
const record = items.value.find((item) => item.id === id)
|
||||
if (!record) return
|
||||
|
||||
const snapshot = {
|
||||
active: record.active,
|
||||
show_in_filter: record.show_in_filter,
|
||||
show_in_select: record.show_in_select,
|
||||
sort_order: record.sort_order
|
||||
}
|
||||
|
||||
try {
|
||||
await updateCategory(record.id, { [field]: checked ? 1 : 0 })
|
||||
await updateCategory(id, patch)
|
||||
message.success('ذخیره شد')
|
||||
} catch (e) {
|
||||
record[field] = prev
|
||||
Object.assign(record, snapshot)
|
||||
console.error(e)
|
||||
message.error('خطا در ذخیره')
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSortOrder(record: Category) {
|
||||
function toggleField(
|
||||
record: Category,
|
||||
field: 'active' | 'show_in_filter' | 'show_in_select',
|
||||
checked: boolean
|
||||
) {
|
||||
if (asBool(record[field]) === checked) return
|
||||
|
||||
const next = checked ? 1 : 0
|
||||
record[field] = next
|
||||
scheduleSave(record, { [field]: next })
|
||||
}
|
||||
|
||||
function scheduleSortOrder(record: Category) {
|
||||
const order = Number(record.sort_order)
|
||||
if (Number.isNaN(order)) return
|
||||
|
||||
try {
|
||||
await updateCategory(record.id, { sort_order: order })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در ذخیره ترتیب')
|
||||
await fetchList()
|
||||
}
|
||||
scheduleSave(record, { sort_order: order })
|
||||
}
|
||||
|
||||
async function syncList(showMessage = false) {
|
||||
syncing.value = true
|
||||
try {
|
||||
const res = await syncCategoriesFromProducts()
|
||||
items.value = res.items ?? (await getCategories())
|
||||
if (showMessage) {
|
||||
message.success(res.message || 'همگامسازی انجام شد')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (showMessage) {
|
||||
message.error('خطا در همگامسازی')
|
||||
} else {
|
||||
await fetchList()
|
||||
}
|
||||
} finally {
|
||||
syncing.value = false
|
||||
if (syncInFlight) {
|
||||
return syncInFlight
|
||||
}
|
||||
|
||||
syncing.value = true
|
||||
syncInFlight = (async () => {
|
||||
try {
|
||||
const res = await syncCategoriesFromProducts()
|
||||
items.value = res.items ?? (await getCategories())
|
||||
if (showMessage) {
|
||||
message.success(res.message || 'همگامسازی انجام شد')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (showMessage) {
|
||||
message.error('خطا در همگامسازی')
|
||||
} else {
|
||||
await fetchList()
|
||||
}
|
||||
} finally {
|
||||
syncing.value = false
|
||||
syncInFlight = null
|
||||
}
|
||||
})()
|
||||
|
||||
return syncInFlight
|
||||
}
|
||||
|
||||
async function handleSync() {
|
||||
@@ -159,4 +206,10 @@ async function handleSync() {
|
||||
onMounted(() => {
|
||||
void syncList()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
debouncedFlush.forEach((fn) => fn.cancel())
|
||||
debouncedFlush.clear()
|
||||
pendingPatches.clear()
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user