135 lines
3.6 KiB
TypeScript
135 lines
3.6 KiB
TypeScript
import type {
|
||
FinanceSettlementFilterState,
|
||
FinanceSettlementListQueryPayload,
|
||
FinanceSettlementQueryPayload,
|
||
} from '../../types';
|
||
|
||
/**
|
||
* 文件职责:到账查询页面纯函数与数据转换工具。
|
||
*/
|
||
import type {
|
||
FinanceSettlementChannelFilter,
|
||
FinanceSettlementListItemDto,
|
||
} from '#/api/finance';
|
||
|
||
function formatDate(date: Date) {
|
||
const year = date.getFullYear();
|
||
const month = `${date.getMonth() + 1}`.padStart(2, '0');
|
||
const day = `${date.getDate()}`.padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
function normalizeChannel(value: FinanceSettlementChannelFilter) {
|
||
return value === 'all' ? undefined : value;
|
||
}
|
||
|
||
function decodeBase64ToBlob(base64: string) {
|
||
const binary = atob(base64);
|
||
const bytes = new Uint8Array(binary.length);
|
||
for (let index = 0; index < binary.length; index += 1) {
|
||
bytes[index] = binary.codePointAt(index) ?? 0;
|
||
}
|
||
return new Blob([bytes], { type: 'text/csv;charset=utf-8;' });
|
||
}
|
||
|
||
/** 获取今天日期字符串(yyyy-MM-dd)。 */
|
||
export function getTodayDateString() {
|
||
return formatDate(new Date());
|
||
}
|
||
|
||
/** 构建到账筛选请求。 */
|
||
export function buildFilterQueryPayload(
|
||
storeId: string,
|
||
filters: FinanceSettlementFilterState,
|
||
): FinanceSettlementQueryPayload {
|
||
return {
|
||
storeId,
|
||
startDate: filters.startDate || undefined,
|
||
endDate: filters.endDate || undefined,
|
||
channel: normalizeChannel(filters.channel),
|
||
};
|
||
}
|
||
|
||
/** 构建到账列表请求。 */
|
||
export function buildListQueryPayload(
|
||
storeId: string,
|
||
filters: FinanceSettlementFilterState,
|
||
page: number,
|
||
pageSize: number,
|
||
): FinanceSettlementListQueryPayload {
|
||
return {
|
||
...buildFilterQueryPayload(storeId, filters),
|
||
page,
|
||
pageSize,
|
||
};
|
||
}
|
||
|
||
/** 判断日期范围是否合法。 */
|
||
export function isDateRangeInvalid(filters: FinanceSettlementFilterState) {
|
||
if (!filters.startDate || !filters.endDate) {
|
||
return false;
|
||
}
|
||
return filters.startDate > filters.endDate;
|
||
}
|
||
|
||
/** 货币格式化(人民币)。 */
|
||
export function formatCurrency(value: number) {
|
||
return new Intl.NumberFormat('zh-CN', {
|
||
style: 'currency',
|
||
currency: 'CNY',
|
||
minimumFractionDigits: 2,
|
||
maximumFractionDigits: 2,
|
||
}).format(Number.isFinite(value) ? value : 0);
|
||
}
|
||
|
||
/** 数值格式化(千分位整数)。 */
|
||
export function formatCount(value: number) {
|
||
return new Intl.NumberFormat('zh-CN', {
|
||
maximumFractionDigits: 0,
|
||
}).format(Number.isFinite(value) ? value : 0);
|
||
}
|
||
|
||
/** 表格行唯一键。 */
|
||
export function getSettlementRowKey(row: FinanceSettlementListItemDto) {
|
||
return `${row.arrivedDate}_${row.channel}`;
|
||
}
|
||
|
||
/** 到账渠道圆点类名。 */
|
||
export function resolveChannelDotClass(channel: string) {
|
||
return channel === 'wechat' ? 'is-wechat' : 'is-alipay';
|
||
}
|
||
|
||
/** 明细支付时间格式化(HH:mm)。 */
|
||
export function formatPaidTime(value: string) {
|
||
const normalized = String(value || '').trim();
|
||
if (!normalized) {
|
||
return '--';
|
||
}
|
||
|
||
const separatorIndex = normalized.indexOf(' ');
|
||
if (separatorIndex !== -1 && normalized.length >= separatorIndex + 6) {
|
||
return normalized.slice(separatorIndex + 1, separatorIndex + 6);
|
||
}
|
||
|
||
const timePrefix = normalized.match(/^\d{2}:\d{2}/);
|
||
if (timePrefix?.[0]) {
|
||
return timePrefix[0];
|
||
}
|
||
|
||
return normalized;
|
||
}
|
||
|
||
/** 下载 Base64 编码文件。 */
|
||
export function downloadBase64File(
|
||
fileName: string,
|
||
fileContentBase64: string,
|
||
) {
|
||
const blob = decodeBase64ToBlob(fileContentBase64);
|
||
const url = URL.createObjectURL(blob);
|
||
const anchor = document.createElement('a');
|
||
anchor.href = url;
|
||
anchor.download = fileName;
|
||
anchor.click();
|
||
URL.revokeObjectURL(url);
|
||
}
|