/** * 文件职责:发票管理页面状态与动作编排。 */ import type { FinanceInvoiceIssueResultDto, FinanceInvoiceRecordDetailDto, FinanceInvoiceRecordListItemDto, FinanceInvoiceStatsDto, } from '#/api/finance'; import type { FinanceInvoiceFilterState, FinanceInvoiceIssueFormState, FinanceInvoicePaginationState, FinanceInvoiceSettingFormState, FinanceInvoiceTabKey, FinanceInvoiceVoidFormState, } from '../types'; import { computed, onActivated, onMounted, reactive, ref, watch } from 'vue'; import { useAccessStore } from '@vben/stores'; import { message } from 'ant-design-vue'; import { createDefaultFilters, createDefaultIssueForm, createDefaultPagination, createDefaultSettingsForm, createDefaultVoidForm, DEFAULT_INVOICE_STATS, FINANCE_INVOICE_ISSUE_PERMISSION, FINANCE_INVOICE_SETTINGS_PERMISSION, FINANCE_INVOICE_VIEW_PERMISSION, FINANCE_INVOICE_VOID_PERMISSION, INVOICE_TAB_OPTIONS, } from './invoice-page/constants'; import { createDataActions } from './invoice-page/data-actions'; import { createDrawerActions } from './invoice-page/drawer-actions'; import { isDateRangeInvalid } from './invoice-page/helpers'; import { createSettingsActions } from './invoice-page/settings-actions'; /** 创建发票管理页面组合状态。 */ export function useFinanceInvoicePage() { const accessStore = useAccessStore(); const activeTab = ref('records'); const filters = reactive( createDefaultFilters() as FinanceInvoiceFilterState, ); const pagination = reactive( createDefaultPagination(), ); const rows = ref([]); const stats = reactive({ ...DEFAULT_INVOICE_STATS }); const settingForm = reactive( createDefaultSettingsForm(), ); const settingSnapshot = ref( createDefaultSettingsForm(), ); const issueForm = reactive( createDefaultIssueForm(), ); const voidForm = reactive(createDefaultVoidForm()); const detail = ref(null); const issueDetail = ref(null); const issueResult = ref(null); const issueTargetRecord = ref(null); const voidTargetRecord = ref(null); const isListLoading = ref(false); const isSettingsLoading = ref(false); const isDetailLoading = ref(false); const isIssueDetailLoading = ref(false); const isIssueSubmitting = ref(false); const isVoidSubmitting = ref(false); const isSettingsSaving = ref(false); const isDetailDrawerOpen = ref(false); const isIssueDrawerOpen = ref(false); const isVoidModalOpen = ref(false); const isIssueResultModalOpen = ref(false); const isSettingsConfirmModalOpen = ref(false); const accessCodeSet = computed( () => new Set((accessStore.accessCodes ?? []).map(String)), ); const canViewRecords = computed(() => { const accessCodes = accessCodeSet.value; return ( accessCodes.has(FINANCE_INVOICE_VIEW_PERMISSION) || accessCodes.has(FINANCE_INVOICE_ISSUE_PERMISSION) || accessCodes.has(FINANCE_INVOICE_VOID_PERMISSION) ); }); const canIssue = computed(() => accessCodeSet.value.has(FINANCE_INVOICE_ISSUE_PERMISSION), ); const canVoid = computed(() => accessCodeSet.value.has(FINANCE_INVOICE_VOID_PERMISSION), ); const canViewSettings = computed(() => { const accessCodes = accessCodeSet.value; return ( accessCodes.has(FINANCE_INVOICE_VIEW_PERMISSION) || accessCodes.has(FINANCE_INVOICE_SETTINGS_PERMISSION) ); }); const canManageSettings = computed(() => accessCodeSet.value.has(FINANCE_INVOICE_SETTINGS_PERMISSION), ); const canViewPage = computed( () => canViewRecords.value || canViewSettings.value, ); const tabOptions = computed(() => INVOICE_TAB_OPTIONS.filter((item) => { if (item.value === 'records') { return canViewRecords.value; } if (item.value === 'settings') { return canViewSettings.value; } return false; }), ); const { applySettingsResult, clearByPermission, clearRecordData, loadRecordList, loadSettings, } = createDataActions({ canViewRecords, canViewSettings, createDefaultSettingsForm, filters, isListLoading, isSettingsLoading, pagination, rows, settingForm, settingSnapshot, stats, }); const { openDetail, openIssue, openVoid, setDetailDrawerOpen, setIssueDrawerOpen, setIssueResultModalOpen, setVoidModalOpen, submitIssue, submitVoid, } = createDrawerActions({ canIssue, canVoid, detail, isDetailDrawerOpen, isDetailLoading, isIssueDetailLoading, isIssueDrawerOpen, isIssueResultModalOpen, isIssueSubmitting, isVoidModalOpen, isVoidSubmitting, issueDetail, issueForm, issueResult, issueTargetRecord, reloadRecordList: loadRecordList, voidForm, voidTargetRecord, }); const { hasSettingsChanged, openSettingsConfirmModal, resetSettings, setSettingsConfirmModalOpen, submitSettings, } = createSettingsActions({ applySettingsResult, canManageSettings, isSettingsConfirmModalOpen, isSettingsSaving, settingForm, settingSnapshot, }); function setActiveTab(value: FinanceInvoiceTabKey) { activeTab.value = value; } function setStartDate(value: string) { filters.startDate = value; } function setEndDate(value: string) { filters.endDate = value; } function setStatus(value: string) { filters.status = (value || 'all') as FinanceInvoiceFilterState['status']; } function setInvoiceType(value: string) { filters.invoiceType = (value || 'all') as FinanceInvoiceFilterState['invoiceType']; } function setKeyword(value: string) { filters.keyword = value; } function setIssueFormContactEmail(value: string) { issueForm.contactEmail = value; } function setIssueFormRemark(value: string) { issueForm.issueRemark = value; } function setVoidReason(value: string) { voidForm.voidReason = value; } function setSettingsField( field: K, value: FinanceInvoiceSettingFormState[K], ) { settingForm[field] = value; } async function handleSearch() { if (isDateRangeInvalid(filters)) { message.warning('开始日期不能晚于结束日期'); return; } pagination.page = 1; await loadRecordList(); } async function handlePageChange(page: number, pageSize: number) { pagination.page = page; pagination.pageSize = pageSize; await loadRecordList(); } function closeTransientPanels() { setDetailDrawerOpen(false); setIssueDrawerOpen(false); setVoidModalOpen(false); setIssueResultModalOpen(false); setSettingsConfirmModalOpen(false); } async function loadByPermission() { const tasks: Array> = []; if (canViewRecords.value) { tasks.push(loadRecordList()); } else { clearRecordData(); } if (canViewSettings.value) { tasks.push(loadSettings()); } await Promise.all(tasks); } watch(tabOptions, (next) => { const values = next.map((item) => item.value); if (values.length === 0) { return; } if (!values.includes(activeTab.value)) { activeTab.value = values[0] as FinanceInvoiceTabKey; } }); watch( canViewPage, async (value, oldValue) => { if (value === oldValue) { return; } if (!value) { clearByPermission(); closeTransientPanels(); return; } await loadByPermission(); }, { immediate: false }, ); onMounted(async () => { if (!canViewPage.value) { clearByPermission(); closeTransientPanels(); return; } await loadByPermission(); }); onActivated(() => { if (!canViewPage.value) { return; } void loadByPermission(); }); return { activeTab, canIssue, canManageSettings, canViewPage, canViewRecords, canViewSettings, canVoid, detail, filters, handlePageChange, handleSearch, hasSettingsChanged, isDetailDrawerOpen, isDetailLoading, isIssueDetailLoading, isIssueDrawerOpen, isIssueResultModalOpen, isIssueSubmitting, isListLoading, isSettingsConfirmModalOpen, isSettingsLoading, isSettingsSaving, isVoidModalOpen, isVoidSubmitting, issueDetail, issueForm, issueResult, issueTargetRecord, openDetail, openIssue, openSettingsConfirmModal, openVoid, pagination, resetSettings, rows, setActiveTab, setDetailDrawerOpen, setEndDate, setInvoiceType, setIssueDrawerOpen, setIssueFormContactEmail, setIssueFormRemark, setIssueResultModalOpen, setKeyword, setSettingsConfirmModalOpen, setSettingsField, setStartDate, setStatus, setVoidModalOpen, setVoidReason, settingForm, stats, submitIssue, submitSettings, submitVoid, tabOptions, voidForm, voidTargetRecord, }; }