add date util
This commit is contained in:
@@ -168,6 +168,7 @@ import { useSettingStore } from "@/store/settingStore";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { NavBarAction } from "@/types/NavBarAction";
|
||||
import type { Tag } from "@/types/Tag";
|
||||
import { buildPresetDateRange, parseDateTime } from "@/utils/date";
|
||||
import { corePermissionCodes, gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||
|
||||
defineOptions({
|
||||
@@ -206,7 +207,7 @@ const dateOptions: Array<{ label: string; value: DateFilterType }> = [
|
||||
{ label: "自定义范围", value: "custom" }
|
||||
];
|
||||
const dateFilterType = ref<DateFilterType>("all");
|
||||
const dateRange = ref<[string, string]>(buildPresetRange("all"));
|
||||
const dateRange = ref<[string, string]>(buildPresetDateRange("all"));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
const startVisible = ref(false);
|
||||
@@ -279,7 +280,7 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
|
||||
dateFilterType.value = String(value) as DateFilterType;
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await refresh();
|
||||
}
|
||||
}
|
||||
@@ -499,53 +500,6 @@ function buildCreatedAtRange(): [number | undefined, number | undefined] {
|
||||
];
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth" | "lastMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
return [`${Time.formatDate(date)} 00:00`, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
@@ -148,6 +148,7 @@ import type { EventOptionStat, EventRecordPage, EventRecordPageResult, Verificat
|
||||
import type { NavBarAction } from "@/types/NavBarAction";
|
||||
import { isRetiredEvent } from "@/utils/event";
|
||||
import { formatEventNumberValue } from "@/utils/eventValue";
|
||||
import { buildPresetDateRange, parseDateFilterType, parseDateTime } from "@/utils/date";
|
||||
import { permissionCodes } from "@/utils/permission";
|
||||
import { Message } from "@/utils/message.ts";
|
||||
|
||||
@@ -178,7 +179,7 @@ const dateOptions: Array<{ label: string; value: DateFilterType }> = [
|
||||
const keyword = ref(getInitialKeyword());
|
||||
const customerId = ref(getQueryText("customerId"));
|
||||
const customerSelectorVisible = ref(false);
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType));
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType, dateOptions, "today"));
|
||||
const dateRange = ref(parseDateRange(dateFilterType.value));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
@@ -471,7 +472,7 @@ async function selectDateFilter(type: DropdownValue): Promise<void> {
|
||||
|
||||
dateFilterType.value = String(type) as DateFilterType;
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await replaceFilterQuery();
|
||||
await reloadRecords();
|
||||
} else {
|
||||
@@ -586,14 +587,9 @@ function getQueryText(key: string): string {
|
||||
return Array.isArray(value) ? String(value[0] || "") : String(value || "");
|
||||
}
|
||||
|
||||
function parseDateFilterType(value: unknown): DateFilterType {
|
||||
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
|
||||
return dateOptions.some(item => item.value === text) ? text as DateFilterType : "today";
|
||||
}
|
||||
|
||||
function parseDateRange(type: DateFilterType): [string, string] {
|
||||
if (type !== "custom") {
|
||||
return buildPresetRange(type);
|
||||
return buildPresetDateRange(type);
|
||||
}
|
||||
|
||||
const beginAt = getQueryText("beginAt");
|
||||
@@ -657,45 +653,6 @@ async function replaceFilterQuery(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth" | "lastMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
const value = `${Time.formatDate(date)} 00:00`;
|
||||
return [value, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number, number] {
|
||||
if (dateFilterType.value === "all") {
|
||||
return [0, Time.toTimestamp(new Date())];
|
||||
@@ -707,16 +664,6 @@ function buildUnixRange(): [number, number] {
|
||||
];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
navBarStore.clearRight();
|
||||
navBarStore.setCustomRightVisible(canShowActionMenu.value);
|
||||
|
||||
@@ -132,6 +132,7 @@ import EventAPI from "@/api/EventAPI";
|
||||
import EventRecordAPI from "@/api/EventRecordAPI";
|
||||
import type { CustomerEventRankView, EventRecordRankPage, EventRecordRankType } from "@/types/EventRecord";
|
||||
import type { EventItem } from "@/types/EventItem";
|
||||
import { buildPresetDateRange, parseDateFilterType, parseDateTime } from "@/utils/date";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import { formatEventNumberValue } from "@/utils/eventValue";
|
||||
import { permissionCodes } from "@/utils/permission";
|
||||
@@ -164,7 +165,7 @@ const dateOptions: Array<{ label: string; value: DateFilterType }> = [
|
||||
// ---------- 筛选 ----------
|
||||
|
||||
const rankType = ref<EventRecordRankType>(parseRankType(route.query.rankType));
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType));
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType, dateOptions, "all"));
|
||||
const dateRange = ref(parseDateRange(dateFilterType.value));
|
||||
const eventFilter = ref<string[]>([]);
|
||||
const eventList = ref<EventItem[]>([]);
|
||||
@@ -341,9 +342,9 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
dateFilterType.value = parseDateFilterType(value);
|
||||
dateFilterType.value = parseDateFilterType(value, dateOptions, "all");
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await replaceFilterQuery();
|
||||
await reloadRanks();
|
||||
return;
|
||||
@@ -388,14 +389,9 @@ function parseRankType(value: unknown): EventRecordRankType {
|
||||
return rankTypeOptions.some(item => item.value === text) ? text as EventRecordRankType : "TOTAL_DAYS";
|
||||
}
|
||||
|
||||
function parseDateFilterType(value: unknown): DateFilterType {
|
||||
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
|
||||
return dateOptions.some(item => item.value === text) ? text as DateFilterType : "all";
|
||||
}
|
||||
|
||||
function parseDateRange(type: DateFilterType): [string, string] {
|
||||
if (type !== "custom") {
|
||||
return buildPresetRange(type);
|
||||
return buildPresetDateRange(type);
|
||||
}
|
||||
|
||||
return [getQueryText("beginAt"), getQueryText("endAt")];
|
||||
@@ -436,38 +432,6 @@ async function replaceFilterQuery(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
return [`${Time.formatDate(date)} 00:00`, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
if (dateFilterType.value === "all") {
|
||||
return [undefined, undefined];
|
||||
@@ -478,16 +442,6 @@ function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadEvents();
|
||||
initialized = true;
|
||||
|
||||
@@ -142,6 +142,7 @@ import type { GaoFulfillmentStatus, OrderFulfillment } from "@/types/Fulfillment
|
||||
import type { NavBarAction } from "@/types/NavBarAction";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { SalesOrder } from "@/types/SalesOrder";
|
||||
import { buildPresetDateRange, parseDateFilterType, parseDateTime } from "@/utils/date";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import { Message } from "@/utils/message";
|
||||
import { permissionCodes } from "@/utils/permission";
|
||||
@@ -186,7 +187,7 @@ const selectedCustomer = ref<Customer>();
|
||||
const salesOrder = ref<SalesOrder>();
|
||||
const customerSelectorVisible = ref(false);
|
||||
const customerSearchKeyword = ref("");
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType));
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(getQueryText(route.query.dateType), dateOptions, "today"));
|
||||
const dateRange = ref<[string, string]>(parseDateRange(dateFilterType.value));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
@@ -224,14 +225,9 @@ function getInitialStatus(value: unknown): "ALL" | GaoFulfillmentStatus {
|
||||
return "ALL";
|
||||
}
|
||||
|
||||
function parseDateFilterType(value: unknown): DateFilterType {
|
||||
const dateFilter = getQueryText(value);
|
||||
return dateOptions.some(item => item.value === dateFilter) ? dateFilter as DateFilterType : "today";
|
||||
}
|
||||
|
||||
function parseDateRange(type: DateFilterType): [string, string] {
|
||||
if (type !== "custom") {
|
||||
return buildPresetRange(type);
|
||||
return buildPresetDateRange(type);
|
||||
}
|
||||
return [getQueryText(route.query.beginAt), getQueryText(route.query.endAt)];
|
||||
}
|
||||
@@ -368,7 +364,7 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
}
|
||||
dateFilterType.value = String(value) as DateFilterType;
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await replaceFilterQuery();
|
||||
await reloadList();
|
||||
} else {
|
||||
@@ -444,45 +440,6 @@ function isValidTransitionDepth(value: string): boolean {
|
||||
return value !== "" && Number.isInteger(depth) && 0 <= depth && depth <= 20;
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth" | "lastMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
const value = `${Time.formatDate(date)} 00:00`;
|
||||
return [value, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
if (dateFilterType.value === "all") {
|
||||
return [0, Time.toTimestamp(new Date())];
|
||||
@@ -493,16 +450,6 @@ function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
async function toDetail(item: OrderFulfillment): Promise<void> {
|
||||
if (item.id) {
|
||||
await router.push({
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { DropdownValue } from "tdesign-mobile-vue";
|
||||
import { PassTimeLabel, Time, Toolkit } from "timi-web";
|
||||
import { PassTimeLabel, Toolkit } from "timi-web";
|
||||
import { type PageResult, useUserStore } from "timi-web-api";
|
||||
import CustomerAPI from "@/api/CustomerAPI";
|
||||
import PointAPI from "@/api/PointAPI";
|
||||
@@ -151,6 +151,7 @@ import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { PointLedger, PointLedgerChangeType, PointLedgerPage } from "@/types/Point";
|
||||
import { getCustomerPhotoURL } from "@/utils/customer";
|
||||
import { buildPresetDateRange, parseDateTime } from "@/utils/date";
|
||||
import { Message } from "@/utils/message";
|
||||
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||
|
||||
@@ -175,7 +176,7 @@ const customerKeyword = ref("");
|
||||
const selectorVisible = ref(false);
|
||||
const changeTypeFilter = ref("ALL");
|
||||
const dateFilter = ref<DateFilter>("last30");
|
||||
const dateRange = ref<[string, string]>(buildDateRange(dateFilter.value));
|
||||
const dateRange = ref<[string, string]>(buildPresetDateRange("last30"));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
const startDateVisible = ref(false);
|
||||
@@ -253,7 +254,7 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
}
|
||||
dateFilter.value = String(value) as DateFilter;
|
||||
if (dateFilter.value !== "custom") {
|
||||
dateRange.value = buildDateRange(dateFilter.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilter.value);
|
||||
await reload();
|
||||
}
|
||||
}
|
||||
@@ -436,39 +437,14 @@ async function toDetail(item: PointLedger): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
// ---------- 时间 ----------
|
||||
|
||||
function buildDateRange(type: DateFilter): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 0, 0);
|
||||
if (type === "custom") {
|
||||
return ["", Time.formatDateTime(end)];
|
||||
}
|
||||
const begin = new Date(end);
|
||||
const dayCount = type === "today" ? 0 : type === "last7" ? 6 : 29;
|
||||
begin.setDate(begin.getDate() - dayCount);
|
||||
begin.setHours(0, 0, 0, 0);
|
||||
return [Time.formatDateTime(begin), Time.formatDateTime(end)];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number, number] {
|
||||
if (!dateRange.value[0] && !dateRange.value[1]) {
|
||||
return [0, Date.now()];
|
||||
}
|
||||
return [toTimestamp(dateRange.value[0], false), toTimestamp(dateRange.value[1], true)];
|
||||
}
|
||||
|
||||
function toTimestamp(value: string, isEnd: boolean): number {
|
||||
if (!value) {
|
||||
return isEnd ? Date.now() : 0;
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0).getTime();
|
||||
return [
|
||||
parseDateTime(dateRange.value[0], false).getTime(),
|
||||
parseDateTime(dateRange.value[1], true).getTime()
|
||||
];
|
||||
}
|
||||
|
||||
// ---------- 页面数据 ----------
|
||||
|
||||
@@ -158,6 +158,7 @@ import CustomerSelector from "@/components/CustomerSelector.vue";
|
||||
import { useNavBarStore } from "@/store/navBarStore";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { PointRedemption, PointRedemptionStatus } from "@/types/Point";
|
||||
import { buildPresetDateRange, parseDateFilterType, parseDateTime } from "@/utils/date";
|
||||
import { Message } from "@/utils/message";
|
||||
import { getPackageQuantityText } from "@/utils/package";
|
||||
import { getCustomerPhotoURL } from "@/utils/customer";
|
||||
@@ -183,7 +184,7 @@ const keyword = ref(getQueryText(route.query.keyword));
|
||||
const customerId = ref(getQueryText(route.query.customerId));
|
||||
const selectedCustomer = ref<Customer>();
|
||||
const customerSelectorVisible = ref(false);
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType));
|
||||
const dateFilterType = ref<DateFilterType>(parseDateFilterType(getQueryText(route.query.dateType), dateOptions, "today"));
|
||||
const dateRange = ref<[string, string]>(parseDateRange(dateFilterType.value));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
@@ -202,14 +203,9 @@ function getQueryText(value: unknown): string {
|
||||
return Array.isArray(value) ? "" : typeof value === "string" ? value : "";
|
||||
}
|
||||
|
||||
function parseDateFilterType(value: unknown): DateFilterType {
|
||||
const dateFilter = getQueryText(value);
|
||||
return dateOptions.some(item => item.value === dateFilter) ? dateFilter as DateFilterType : "today";
|
||||
}
|
||||
|
||||
function parseDateRange(type: DateFilterType): [string, string] {
|
||||
if (type !== "custom") {
|
||||
return buildPresetRange(type);
|
||||
return buildPresetDateRange(type);
|
||||
}
|
||||
return [getQueryText(route.query.beginAt), getQueryText(route.query.endAt)];
|
||||
}
|
||||
@@ -296,7 +292,7 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
}
|
||||
dateFilterType.value = String(value) as DateFilterType;
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await replaceFilterQuery();
|
||||
await reload();
|
||||
} else {
|
||||
@@ -358,45 +354,6 @@ async function replaceFilterQuery(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth" | "lastMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
const value = `${Time.formatDate(date)} 00:00`;
|
||||
return [value, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
if (dateFilterType.value === "all") {
|
||||
return [0, Time.toTimestamp(new Date())];
|
||||
@@ -407,16 +364,6 @@ function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
function statusText(value?: PointRedemptionStatus): string {
|
||||
return ({
|
||||
COMPLETED: "已兑换",
|
||||
|
||||
@@ -187,6 +187,7 @@ import type {
|
||||
ConsumptionRecordSourceType,
|
||||
ConsumptionRecordStatus
|
||||
} from "@/types/ConsumptionRecord";
|
||||
import { buildPresetDateRange, parseDateFilterType, parseDateTime } from "@/utils/date";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import { getCustomerPhotoURL } from "@/utils/customer";
|
||||
import { Message } from "@/utils/message";
|
||||
@@ -217,7 +218,7 @@ const customerId = ref("");
|
||||
const selectedCustomer = ref<Customer>();
|
||||
const customerSelectorVisible = ref(false);
|
||||
const dateFilterType = ref<DateFilterType>("all");
|
||||
const dateRange = ref<[string, string]>(buildPresetRange("all"));
|
||||
const dateRange = ref<[string, string]>(buildPresetDateRange("all"));
|
||||
const startDraft = ref("");
|
||||
const endDraft = ref("");
|
||||
const startVisible = ref(false);
|
||||
@@ -247,7 +248,7 @@ function applyRouteQuery(): void {
|
||||
customerId.value = getText(route.query.customerId);
|
||||
sourceType.value = ["ALL", "LEGACY_EVENT", "SALES_ORDER"].includes(routeSourceType) ? routeSourceType as ConsumptionRecordSourceType | "ALL" : "ALL";
|
||||
status.value = ["ALL", "ACTIVE", "REVOKED"].includes(routeStatus) ? routeStatus as ConsumptionRecordStatus | "ALL" : "ALL";
|
||||
dateFilterType.value = dateOptions.some(item => item.value === routeDateType) ? routeDateType as DateFilterType : "all";
|
||||
dateFilterType.value = parseDateFilterType(routeDateType, dateOptions, "all");
|
||||
dateRange.value = parseDateRange(dateFilterType.value, getText);
|
||||
}
|
||||
|
||||
@@ -270,7 +271,7 @@ async function selectDateFilter(value: DropdownValue): Promise<void> {
|
||||
|
||||
dateFilterType.value = String(value) as DateFilterType;
|
||||
if (dateFilterType.value !== "custom") {
|
||||
dateRange.value = buildPresetRange(dateFilterType.value);
|
||||
dateRange.value = buildPresetDateRange(dateFilterType.value);
|
||||
await reloadRecords();
|
||||
}
|
||||
}
|
||||
@@ -368,49 +369,11 @@ function buildPage(): ConsumptionRecordPage {
|
||||
|
||||
function parseDateRange(type: DateFilterType, getText: (value: unknown) => string): [string, string] {
|
||||
if (type !== "custom") {
|
||||
return buildPresetRange(type);
|
||||
return buildPresetDateRange(type);
|
||||
}
|
||||
return [getText(route.query.beginAt), getText(route.query.endAt)];
|
||||
}
|
||||
|
||||
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
if (type === "lastWeek") {
|
||||
const current = new Date();
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = new Date(current);
|
||||
thisWeekMonday.setDate(current.getDate() - day + 1);
|
||||
const lastWeekMonday = new Date(thisWeekMonday);
|
||||
lastWeekMonday.setDate(thisWeekMonday.getDate() - 7);
|
||||
const lastWeekSunday = new Date(thisWeekMonday);
|
||||
lastWeekSunday.setDate(thisWeekMonday.getDate() - 1);
|
||||
return [`${Time.formatDate(lastWeekMonday)} 00:00`, `${Time.formatDate(lastWeekSunday)} 23:59`];
|
||||
}
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(current)} 23:59`];
|
||||
}
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date();
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
const offsetMap: Record<Exclude<DateFilterType, "all" | "custom" | "lastWeek" | "thisMonth" | "lastMonth">, number> = {
|
||||
today: 0,
|
||||
yesterday: 1
|
||||
};
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setDate(date.getDate() - offsetMap[type]);
|
||||
return [`${Time.formatDate(date)} 00:00`, `${Time.formatDate(date)} 23:59`];
|
||||
}
|
||||
|
||||
function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
if (dateFilterType.value === "all") {
|
||||
return [undefined, undefined];
|
||||
@@ -421,16 +384,6 @@ function buildUnixRange(): [number | undefined, number | undefined] {
|
||||
];
|
||||
}
|
||||
|
||||
function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
async function reloadRecords(value?: DropdownValue): Promise<void> {
|
||||
if (value && Array.isArray(value)) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import { Time } from "timi-web";
|
||||
|
||||
/** 日期筛选器支持的预设范围。 */
|
||||
export type DateFilterPreset =
|
||||
| "all"
|
||||
| "today"
|
||||
| "yesterday"
|
||||
| "lastWeek"
|
||||
| "thisMonth"
|
||||
| "lastMonth"
|
||||
| "last7"
|
||||
| "last30";
|
||||
|
||||
/** 日期时间范围,文本格式为 YYYY-MM-DD HH:mm。 */
|
||||
export type DateTimeRange = [string, string];
|
||||
|
||||
/**
|
||||
* 根据预设筛选类型生成日期时间范围。
|
||||
*
|
||||
* `last7` 和 `last30` 为包含今天在内的最近 7 天和 30 天。
|
||||
*/
|
||||
export function buildPresetDateRange(type: DateFilterPreset, now = new Date()): DateTimeRange {
|
||||
if (type === "all") {
|
||||
return ["", ""];
|
||||
}
|
||||
|
||||
if (type === "lastWeek") {
|
||||
const current = getDateStart(now);
|
||||
const day = current.getDay() || 7;
|
||||
const thisWeekMonday = addDays(current, 1 - day);
|
||||
const lastWeekMonday = addDays(thisWeekMonday, -7);
|
||||
const lastWeekSunday = addDays(thisWeekMonday, -1);
|
||||
return buildDayRange(lastWeekMonday, lastWeekSunday);
|
||||
}
|
||||
|
||||
if (type === "thisMonth") {
|
||||
const current = new Date(now);
|
||||
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
|
||||
return buildDayRange(begin, current);
|
||||
}
|
||||
|
||||
if (type === "lastMonth") {
|
||||
const current = new Date(now);
|
||||
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
||||
const end = new Date(current.getFullYear(), current.getMonth(), 0);
|
||||
return buildDayRange(begin, end);
|
||||
}
|
||||
|
||||
if (type === "last7" || type === "last30") {
|
||||
const end = new Date(now);
|
||||
end.setHours(23, 59, 0, 0);
|
||||
const begin = new Date(end);
|
||||
begin.setDate(begin.getDate() - (type === "last7" ? 6 : 29));
|
||||
begin.setHours(0, 0, 0, 0);
|
||||
return [Time.formatDateTime(begin), Time.formatDateTime(end)];
|
||||
}
|
||||
|
||||
const date = getDateStart(now);
|
||||
date.setDate(date.getDate() - (type === "today" ? 0 : 1));
|
||||
return buildDayRange(date, date);
|
||||
}
|
||||
|
||||
/** 将路由或组件输入转换为合法的日期筛选类型。 */
|
||||
export function parseDateFilterType<T extends string>(
|
||||
value: unknown,
|
||||
options: readonly { value: T }[],
|
||||
fallback: T
|
||||
): T {
|
||||
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
|
||||
return options.some(item => item.value === text) ? text as T : fallback;
|
||||
}
|
||||
|
||||
/** 将日期时间文本解析为本地时间。空开始时间和空结束时间分别回退到 Unix 起点和当前时间。 */
|
||||
export function parseDateTime(value: string, isEnd: boolean): Date {
|
||||
if (!value) {
|
||||
return isEnd ? new Date() : new Date(0);
|
||||
}
|
||||
|
||||
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
|
||||
const [year, month, day] = dateText.split("-").map(Number);
|
||||
const [hour, minute] = timeText.split(":").map(Number);
|
||||
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
|
||||
}
|
||||
|
||||
function buildDayRange(begin: Date, end: Date): DateTimeRange {
|
||||
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
|
||||
}
|
||||
|
||||
function getDateStart(date: Date): Date {
|
||||
const value = new Date(date);
|
||||
value.setHours(0, 0, 0, 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
function addDays(date: Date, days: number): Date {
|
||||
const value = new Date(date);
|
||||
value.setDate(value.getDate() + days);
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user