feat(finance): 实现发票管理页面与子页面
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
* 文件职责:发票管理页面状态与动作编排。
|
||||
*/
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user