398 lines
9.3 KiB
TypeScript
398 lines
9.3 KiB
TypeScript
/**
|
|
* 文件职责:发票管理页面状态与动作编排。
|
|
*/
|
|
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<FinanceInvoiceTabKey>('records');
|
|
|
|
const filters = reactive<FinanceInvoiceFilterState>(
|
|
createDefaultFilters() as FinanceInvoiceFilterState,
|
|
);
|
|
const pagination = reactive<FinanceInvoicePaginationState>(
|
|
createDefaultPagination(),
|
|
);
|
|
const rows = ref<FinanceInvoiceRecordListItemDto[]>([]);
|
|
|
|
const stats = reactive<FinanceInvoiceStatsDto>({ ...DEFAULT_INVOICE_STATS });
|
|
|
|
const settingForm = reactive<FinanceInvoiceSettingFormState>(
|
|
createDefaultSettingsForm(),
|
|
);
|
|
const settingSnapshot = ref<FinanceInvoiceSettingFormState>(
|
|
createDefaultSettingsForm(),
|
|
);
|
|
|
|
const issueForm = reactive<FinanceInvoiceIssueFormState>(
|
|
createDefaultIssueForm(),
|
|
);
|
|
const voidForm = reactive<FinanceInvoiceVoidFormState>(createDefaultVoidForm());
|
|
|
|
const detail = ref<FinanceInvoiceRecordDetailDto | null>(null);
|
|
const issueDetail = ref<FinanceInvoiceRecordDetailDto | null>(null);
|
|
const issueResult = ref<FinanceInvoiceIssueResultDto | null>(null);
|
|
|
|
const issueTargetRecord = ref<FinanceInvoiceRecordListItemDto | null>(null);
|
|
const voidTargetRecord = ref<FinanceInvoiceRecordListItemDto | null>(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<K extends keyof FinanceInvoiceSettingFormState>(
|
|
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<Promise<void>> = [];
|
|
|
|
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,
|
|
};
|
|
}
|