Files
boursecu_admin/src/pages/menuPages/accounting/components/zarinTable.vue
T

188 lines
6.4 KiB
Vue
Raw Normal View History

2026-07-23 22:24:26 +03:30
<template>
<div class="min-w-0 w-full max-w-full overflow-x-hidden">
<BasicShowContext title="اسناد زرین">
<div v-if="!isMobile" class="min-w-0 w-full max-w-full overflow-x-auto">
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
<template #action="{ record }">
<div class="flex justify-center gap-2">
<!-- دکمه ۱: اطلاعات کلی (همیشه نمایان) -->
<a-tooltip placement="bottom" class="cursor-pointer" @click="openInfo(record)">
<template #title><span>اطلاعات سند</span></template>
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
</a-tooltip>
<!-- دکمه ۲: ثبت مشتری در زرین (فقط اگر سند هنوز ثبت نشده و مشتری کد ندارد) -->
<a-tooltip
v-if="!record.zarin_id && !record.customer?.moshtari_code"
placement="bottom"
class="cursor-pointer"
@click="openRegister(record)"
>
<template #title><span>ثبت مشتری در زرین</span></template>
<Icon icon="vuesax-linear:profile-add" color="#7C3AED" />
</a-tooltip>
<!-- دکمه ۳: ارسال به زرین (فقط اگر هنوز در زرین ثبت نشده) -->
<a-tooltip
v-if="!record.zarin_id"
placement="bottom"
class="cursor-pointer"
@click="openSend(record)"
>
<template #title><span>ارسال به زرین</span></template>
<Icon icon="vuesax-linear:send-2" color="#CA8A04" />
</a-tooltip>
</div>
</template>
</BaseTable>
</div>
<ZarinMobileCardList v-else ref="mobileListRef" />
</BasicShowContext>
<!-- مودال اطلاعات کلی -->
<BasicModal v-model:visible="infoVisible" title="اطلاعات سند" width="36rem" :footer="null">
<div class="space-y-2 text-sm">
<div
v-for="item in infoItems"
:key="item.label"
class="flex justify-between gap-3 border-b border-gray-100 py-2"
>
<span class="text-gray-500">{{ item.label }}</span>
<span class="break-all text-left">{{ item.value ?? '-' }}</span>
</div>
<div v-if="selected?.res" class="rounded-lg bg-gray-100 p-3 text-xs font-mono text-gray-700 whitespace-pre-wrap">
{{ selected.res }}
</div>
<div v-if="selected?.sync_log" class="rounded-lg bg-red-50 p-3 text-red-700 whitespace-pre-wrap">
{{ selected.sync_log }}
</div>
</div>
</BasicModal>
<!-- مودال ارسال به زرین -->
<ZarinRetryModal
v-model="sendVisible"
mode="retry-sanad"
:zarin-id="selected?.id"
@success="fetch"
/>
<!-- مودال ثبت مشتری در زرین -->
<ZarinRetryModal
v-model="registerVisible"
mode="register-customer"
:customer-id="selected?.customer_id"
:customer-name="selected?.customer?.name"
@success="fetch"
/>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
import type { TableInput } from '@core/type/baseTable'
import { getZarinTable, type ZarinRecord } from '@/api/zarin'
import Icon from '@core/components/BaseIcon/src/Icon.vue'
import { isMobile } from '@core/utils/is'
import BasicModal from '@/components/BasicModal.vue'
import ZarinRetryModal from '@/components/ZarinRetryModal.vue'
import ZarinMobileCardList from '@/pages/menuPages/accounting/components/ZarinMobileCardList.vue'
import { zarinStatusLabel } from '@/pages/menuPages/accounting/utils/zarinStatus'
import { toJalali } from '@core/utils/useDataTime'
const [submit, reload] = useBaseTable()
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
const infoVisible = ref(false)
const sendVisible = ref(false)
const registerVisible = ref(false)
const selected = ref<ZarinRecord | null>(null)
const columns = [
{
title: 'ردیف',
dataIndex: 'id',
key: 'id',
filterable: false,
sortable: false,
customRender: (r: any) => r.index + 1
},
{ title: 'مشتری', dataIndex: 'customer.name', key: 'customer.name', type: 'Text' },
{ title: 'نوع', dataIndex: 'type', key: 'type', type: 'Text' },
{ title: 'مقدار', dataIndex: 'amount', key: 'amount', type: 'Number' },
{ title: 'شرح', dataIndex: 'desc', key: 'desc', type: 'Text' },
{
title: 'وضعیت',
dataIndex: 'sync_status',
key: 'sync_status',
type: 'Text',
filterable: false,
customRender: (r: any) => zarinStatusLabel(r.record.sync_status, r.record.zarin_id)
},
{
title: 'زمان',
dataIndex: 'created_at',
key: 'created_at',
type: 'Text',
customRender: (r: any) => toJalali(r.record.created_at)
},
{
title: 'عملیات',
dataIndex: 'action',
key: 'action',
slot: 'action',
filterable: false
}
]
const tblProps = ref({
columns,
api: (params: TableInput) => getZarinTable(params)
})
/** اطلاعاتی که برای هر سند حسابداری نیاز است (بدون جزئیات زرین‌محور) */
const infoItems = computed(() => {
const row = selected.value
if (!row) return []
return [
{ label: 'شناسه سند', value: row.id },
{ label: 'مشتری', value: row.customer?.name },
{ label: 'موبایل', value: row.customer?.mobile },
{ label: 'نوع', value: row.type },
{ label: 'مقدار', value: row.amount },
{ label: 'شرح', value: row.desc },
{ label: 'زمان ثبت', value: row.created_at ? toJalali(row.created_at) : '-' },
{ label: 'وضعیت', value: zarinStatusLabel(row.sync_status, row.zarin_id) },
{ label: 'کد زرین', value: row.zarin_id || 'ثبت نشده' }
]
})
function openInfo(record: ZarinRecord) {
selected.value = record
infoVisible.value = true
}
function openSend(record: ZarinRecord) {
selected.value = record
sendVisible.value = true
}
function openRegister(record: ZarinRecord) {
selected.value = record
registerVisible.value = true
}
async function fetch() {
if (isMobile.value) {
await mobileListRef.value?.fetch?.()
return
}
await reload()
}
defineExpose({ fetch })
</script>