feat(expenses): 新增费用统计页面及功能优化

- 在Icon组件中新增箭头图标(arrow-up、arrow-down)
- 优化费用创建页面,支持从路由参数获取默认日期
- 费用创建页面增加返回按钮
- 移除旧版日期选择器注释代码
- 新增费用统计页面,实现按日期范围查询费用记录
- 实现费用统计计算逻辑,包括总车次、计提总额、费用总额和日常利润
- 添加计提方统计和费用分类汇总功能
- 支持每日花销明细的展开与收起
- 增加日期范围选择日历组件
- 页面布局优化,提升用户体验
This commit is contained in:
shenyifei 2025-12-19 16:37:57 +08:00
parent 8562aed7d1
commit c98d4313fd
8 changed files with 695 additions and 54 deletions

View File

@ -22,6 +22,11 @@ export default function ExpenseCostList(props: IExpenseCostProps) {
</View>
</View>
{expenseRecord?.expenseCostList?.length === 0 && (
<View className="py-2 text-center text-sm text-gray-500">
</View>
)}
<View className="divide-y divide-gray-100">
{expenseCosts.map((expense) => {
return (

View File

@ -61,6 +61,12 @@ export default function ExpenseCostList(props: IExpenseCostProps) {
</View>
</View>
{expenseRecord?.expenseProvisionList?.length === 0 && (
<View className="py-2 text-center text-sm text-gray-500">
</View>
)}
{Object.entries(dealerGroups).map(([dealerName, expenseProvisions]) => (
<View
key={dealerName}

View File

@ -3,6 +3,8 @@ import classNames from "classnames";
import React from "react";
export type IconNames =
| "arrow-up"
| "arrow-down"
| "trash-can"
| "pen"
| "chevron-up"

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 5042354 */
src: url('//at.alicdn.com/t/c/font_5042354_coygo8knq0j.woff2?t=1766029596765') format('woff2'),
url('//at.alicdn.com/t/c/font_5042354_coygo8knq0j.woff?t=1766029596765') format('woff'),
url('//at.alicdn.com/t/c/font_5042354_coygo8knq0j.ttf?t=1766029596765') format('truetype');
src: url('//at.alicdn.com/t/c/font_5042354_iq8kowp9bio.woff2?t=1766132042848') format('woff2'),
url('//at.alicdn.com/t/c/font_5042354_iq8kowp9bio.woff?t=1766132042848') format('woff'),
url('//at.alicdn.com/t/c/font_5042354_iq8kowp9bio.ttf?t=1766132042848') format('truetype');
}
.iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow-down:before {
content: "\e62d";
}
.icon-arrow-up:before {
content: "\e633";
}
.icon-chevron-up:before {
content: "\e62c";
}

View File

@ -1,20 +1,27 @@
import { useShareAppMessage } from "@tarojs/taro";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { View } from "@tarojs/components";
import { ExpenseCostList, ExpenseProvisionList, Icon } from "@/components";
import { useEffect, useRef, useState } from "react";
import { Button, Calendar, Dialog, SafeArea, Toast } from "@nutui/nutui-react-taro";
import {
Button,
Calendar,
Dialog,
SafeArea,
Toast,
} from "@nutui/nutui-react-taro";
import dayjs from "dayjs";
import { business } from "@/services";
import { globalStore } from "@/store/global-store";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const { shareOptions, router } = props;
const date = router.params.date as string;
const [currentDate, setCurrentDate] = useState<string>(
dayjs().format("YYYY-MM-DD"),
);
const [currentDate, setCurrentDate] = useState<string>(() => {
return dayjs(date || new Date()).format("YYYY-MM-DD");
});
const [expenseRecord, setExpenseRecord] =
useState<BusinessAPI.ExpenseRecordVO>();
const { setLoading } = globalStore((state: any) => state);
@ -266,15 +273,32 @@ export default hocAuth(function Page(props: CommonComponent) {
<View className="border-t border-gray-200 pt-2.5">
<View className="flex items-center justify-between">
<View className="text-neutral-darker text-sm"></View>
<View className="text-primary font-medium">
<View
className={`text-sm font-medium ${(expenseRecord?.dailyProfit || 0) >= 0 ? "text-green-600" : "text-red-600"}`}
>
¥{(expenseRecord?.dailyProfit || 0).toLocaleString()}
</View>
</View>
<View className="text-primary bg-primary/10 mt-1 inline-block rounded px-2 py-1 text-sm">
<Icon name={"arrow-up"} className="mr-1" />
{(expenseRecord?.dailyProfit || 0) >= 0
? "盈利状态"
: "亏损状态"}
<View className={"flex flex-row items-center"}>
<Icon
name={
(expenseRecord?.dailyProfit || 0) >= 0
? "arrow-up"
: "arrow-down"
}
color={
(expenseRecord?.dailyProfit || 0) >= 0 ? "green" : "red"
}
className="mr-1"
size={14}
/>
<View
className={`text-sm font-medium ${(expenseRecord?.dailyProfit || 0) >= 0 ? "text-green-600" : "text-red-600"}`}
>
{(expenseRecord?.dailyProfit || 0) >= 0
? "盈利状态"
: "亏损状态"}
</View>
</View>
</View>
</View>
@ -282,6 +306,19 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
<View className="sticky bottom-0 z-10 bg-white">
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{/* 返回 */}
<View className="flex-1">
<Button
size={"large"}
block
type={"default"}
onClick={() => {
Taro.navigateBack();
}}
>
</Button>
</View>
<View className="flex-1">
<Button
size={"large"}
@ -325,28 +362,6 @@ export default hocAuth(function Page(props: CommonComponent) {
}}
/>
{/*<DatePicker*/}
{/* title="日期选择"*/}
{/* type="date"*/}
{/* visible={show}*/}
{/* value={new Date(currentDate)}*/}
{/* showChinese*/}
{/* onClose={() => setShow(false)}*/}
{/* threeDimensional={false}*/}
{/* onConfirm={(_, values) => {*/}
{/* const newDate = dayjs(values.join("-")).format("YYYY-MM-DD");*/}
{/* // 如果没有未保存变更,直接切换日期*/}
{/* if (!hasUnsavedChanges) {*/}
{/* setCurrentDate(newDate);*/}
{/* } else {*/}
{/* // 有未保存变更时,保存待切换日期,显示确认对话框*/}
{/* setPendingDate(newDate);*/}
{/* setConfirmVisible(true);*/}
{/* }*/}
{/* }}*/}
{/*/>*/}
{/* 日期切换确认对话框 */}
<Dialog
visible={confirmVisible}

View File

@ -1,6 +1,13 @@
import { useShareAppMessage } from "@tarojs/taro";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { View } from "@tarojs/components";
import dayjs from "dayjs";
import { Icon } from "@/components";
import { Button, Calendar, SafeArea } from "@nutui/nutui-react-taro";
import { useEffect, useState } from "react";
import { business } from "@/services";
import { globalStore } from "@/store/global-store";
interface PageProps extends CommonComponent {
expenseRecordId?: string;
@ -8,6 +15,7 @@ interface PageProps extends CommonComponent {
export default hocAuth(function Page(props: PageProps) {
const { shareOptions } = props;
const { setLoading } = globalStore((state: any) => state);
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
@ -19,5 +27,590 @@ export default hocAuth(function Page(props: PageProps) {
return {};
});
return <></>;
const [show, setShow] = useState(false);
const [currentDate, setCurrentDate] = useState<string[]>([
//这个月的开始时间
dayjs().startOf("month").format("YYYY-MM-DD"),
//这个月的结束时间
dayjs().endOf("month").format("YYYY-MM-DD"),
]);
const [expenseRecordList, setExpenseRecordList] =
useState<BusinessAPI.ExpenseRecordVO[]>();
const [expandedDays, setExpandedDays] = useState<Set<string>>(new Set()); // 展开的日期
const [summaryExpanded, setSummaryExpanded] = useState(false); // 汇总概览展开状态
useEffect(() => {
if (currentDate) {
loadExpenseData(currentDate).then();
}
}, [currentDate]);
// 数据加载完成后默认展开所有日期
// useEffect(() => {
// if (expenseRecordList && expenseRecordList.length > 0) {
// const allDates = new Set(
// expenseRecordList.map((record) => record.recordDate).filter(Boolean),
// );
// setExpandedDays(allDates as any);
// }
// }, [expenseRecordList]);
const loadExpenseData = async (currentDate: string[]) => {
try {
setLoading(true);
const {
data: { data: expenseRecordList, success },
} = await business.expenseRecord.listExpenseRecord({
expenseRecordListQry: {
startDate: currentDate[0], // 使用今天的日期
endDate: currentDate[1],
},
});
if (success) {
setExpenseRecordList(expenseRecordList || []);
}
} catch (error) {
console.error("加载费用数据失败:", error);
} finally {
setLoading(false);
}
};
// 计算统计数据
const calculateStatistics = () => {
if (!expenseRecordList || expenseRecordList.length === 0) {
return {
totalVehicles: 0,
totalProvision: 0,
totalExpense: 0,
dailyProfit: 0,
dealerStatistics: new Map<
string,
{ vehicleCount: number; totalAmount: number }
>(),
costCategoryStatistics: new Map<string, number>(),
};
}
const totalVehicles = expenseRecordList.reduce((sum, record) => {
return sum + (record.expenseProvisionList?.length || 0);
}, 0);
const totalProvision = expenseRecordList.reduce((sum, record) => {
return sum + (record.totalProvision || 0);
}, 0);
const totalExpense = expenseRecordList.reduce((sum, record) => {
return sum + (record.totalExpense || 0);
}, 0);
const dailyProfit = totalProvision - totalExpense;
// 计提方统计(按客户/计提方分组)
const dealerStatistics = new Map<
string,
{ vehicleCount: number; totalAmount: number }
>();
expenseRecordList.forEach((record) => {
record.expenseProvisionList?.forEach((provision) => {
const dealerName = provision.dealerName || "未分组客户";
const current = dealerStatistics.get(dealerName) || {
vehicleCount: 0,
totalAmount: 0,
};
dealerStatistics.set(dealerName, {
vehicleCount: current.vehicleCount + 1,
totalAmount: current.totalAmount + (provision.provisionAmount || 0),
});
});
});
// 费用分类汇总(按费用类型分组)
const costCategoryStatistics = new Map<string, number>();
expenseRecordList.forEach((record) => {
record.expenseCostList?.forEach((cost) => {
const costName = cost.costName || "未知费用";
const currentAmount = costCategoryStatistics.get(costName) || 0;
costCategoryStatistics.set(
costName,
currentAmount + (cost.expenseAmount || 0),
);
});
});
return {
totalVehicles,
totalProvision,
totalExpense,
dailyProfit,
dealerStatistics,
costCategoryStatistics,
};
};
// 切换日期展开状态
const toggleDayExpansion = (recordDate: string) => {
setExpandedDays((prev) => {
const newSet = new Set(prev);
if (newSet.has(recordDate)) {
newSet.delete(recordDate);
} else {
newSet.add(recordDate);
}
return newSet;
});
};
// 获取某天的费用统计
const getDayCostStatistics = (record: BusinessAPI.ExpenseRecordVO) => {
const costMap = new Map<string, number>();
// 统计每种费用类型的金额
record.expenseCostList?.forEach((cost) => {
const currentAmount = costMap.get(cost.costName || "") || 0;
costMap.set(
cost.costName || "",
currentAmount + (cost.expenseAmount || 0),
);
});
return costMap;
};
// 渲染计提明细
const renderProvisionDetails = (record: BusinessAPI.ExpenseRecordVO) => {
const provisionList = record.expenseProvisionList || [];
if (provisionList.length === 0) {
return (
<View className="p-2.5 text-center text-sm text-gray-500">
</View>
);
}
// 按客户分组统计
const dealerGroups = provisionList.reduce(
(groups, provision) => {
const dealerName = provision.dealerName || "未分组客户";
if (!groups[dealerName]) {
groups[dealerName] = [];
}
groups[dealerName].push(provision);
return groups;
},
{} as Record<string, BusinessAPI.ExpenseProvision[]>,
);
return (
<View className="border-b border-gray-100 bg-white p-2.5">
<View className="mb-3 text-xs font-medium tracking-wider text-blue-600 uppercase">
({provisionList.length})
</View>
<View className="space-y-3">
{Object.entries(dealerGroups).map(([dealerName, provisions]) => {
const totalAmount = provisions.reduce(
(sum, p) => sum + (p.provisionAmount || 0),
0,
);
return (
<View
key={dealerName}
className="rounded-lg border border-blue-100 bg-blue-50 p-3"
>
<View className="mb-2 flex items-center justify-between">
<View className="flex items-center">
<View className="mr-2 flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
{provisions.length}
</View>
<View className="text-sm font-medium text-blue-900">
{dealerName}
</View>
</View>
<View className="text-sm font-medium text-blue-700">
¥{totalAmount.toLocaleString()}
</View>
</View>
<View className="flex flex-wrap gap-2">
{provisions.map((provision) => (
<View
key={provision.expenseProvisionId}
className="rounded border border-gray-200 bg-white px-2 py-1 text-xs text-gray-600"
>
{provision.vehicleNo || "未分配"}: ¥
{provision.provisionAmount?.toLocaleString()}
</View>
))}
</View>
</View>
);
})}
</View>
</View>
);
};
// 渲染费用明细
const renderCostDetails = (record: BusinessAPI.ExpenseRecordVO) => {
const costStatistics = getDayCostStatistics(record);
if (costStatistics.size === 0) {
return (
<View className="bg-gray-50 p-2.5 text-center text-sm text-gray-500">
</View>
);
}
return (
<View className="bg-white p-2.5">
<View className="mb-3 text-xs font-medium tracking-wider text-orange-600 uppercase">
</View>
<View className="flex flex-wrap gap-3">
{Array.from(costStatistics.entries()).map(([costName, amount]) => (
<View
key={costName}
className="min-w-[45%] flex-1 items-center justify-between rounded-lg border border-orange-200 bg-orange-50 p-3"
>
<View className="min-w-0 flex-1">
<View className="truncate text-sm font-medium text-gray-900">
{costName}
</View>
<View className="mt-1 text-xs text-gray-500">
¥{amount.toFixed(2)}
</View>
</View>
</View>
))}
</View>
</View>
);
};
return (
<>
<View className={"flex flex-1 flex-col gap-2.5 p-2.5"}>
<View className="overflow-hidden rounded-md bg-white">
<View className="bg-gray-50">
<View
className={`flex h-10 w-full items-center rounded-md border-4 border-gray-300`}
>
<View
className={
"flex flex-1 flex-row items-center justify-between px-5"
}
style={{
color: "var(--nutui-color-title, #1a1a1a)",
}}
onClick={() => {
setShow(true);
}}
>
<View className={"text-sm"}>
{currentDate
? dayjs(currentDate[0]).format("YYYY年MM月DD日") +
" ~ " +
dayjs(currentDate[1]).format("YYYY年MM月DD日")
: "请选择录入花销时间"}
</View>
<Icon name={"chevron-down"} />
</View>
</View>
</View>
</View>
<View className="overflow-hidden rounded-md bg-white shadow-md">
<View className={"flex flex-col gap-2.5 p-2.5"}>
{/* 头部 - 可点击展开/收起 */}
<View
className="flex cursor-pointer items-center justify-between"
onClick={() => setSummaryExpanded(!summaryExpanded)}
>
<View className="font-medium text-gray-900"></View>
<View className="flex items-center space-x-2">
<View className="text-xs text-gray-500">
{currentDate
? dayjs(currentDate[0]).format("YYYY年MM月DD日") +
" ~ " +
dayjs(currentDate[1]).format("YYYY年MM月DD日")
: ""}
</View>
<Icon
name={summaryExpanded ? "chevron-up" : "chevron-down"}
size={16}
className="text-gray-500"
/>
</View>
</View>
{/* 基础统计 - 始终显示 */}
<View className="space-y-2">
<View className="flex justify-between">
<View className="text-sm text-gray-600"></View>
<View className="text-sm font-medium">
{calculateStatistics().totalVehicles}
</View>
</View>
<View className="flex justify-between">
<View className="text-sm text-gray-600"></View>
<View className="text-sm font-medium">
¥{calculateStatistics().totalProvision.toLocaleString()}
</View>
</View>
<View className="flex justify-between">
<View className="text-sm text-gray-600"></View>
<View className="text-sm font-medium">
¥{calculateStatistics().totalExpense.toLocaleString()}
</View>
</View>
<View className="flex justify-between">
<View className="text-sm text-gray-600"></View>
<View className={"flex flex-row items-center"}>
<View
className={`text-sm font-medium ${calculateStatistics().dailyProfit >= 0 ? "text-green-600" : "text-red-600"}`}
>
¥{calculateStatistics().dailyProfit.toLocaleString()}
</View>
<Icon
name={
calculateStatistics().dailyProfit >= 0
? "arrow-up"
: "arrow-down"
}
color={
calculateStatistics().dailyProfit >= 0 ? "green" : "red"
}
className="ml-1"
size={16}
/>
</View>
</View>
</View>
{/* 展开的详细统计 */}
{summaryExpanded && (
<View className="space-y-4 border-t border-gray-200 pt-4">
{/* 计提方统计 */}
<View>
<View className="mb-3 text-sm font-medium text-blue-600">
</View>
<View className="space-y-2">
{Array.from(
calculateStatistics().dealerStatistics.entries(),
).map(([dealerName, stats]) => (
<View
key={dealerName}
className="flex items-center justify-between rounded-lg border border-blue-100 bg-blue-50 p-3"
>
<View className="flex items-center">
<View className="mr-2 flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
{stats.vehicleCount}
</View>
<View className="text-sm font-medium text-blue-900">
{dealerName}
</View>
</View>
<View className="text-sm font-medium text-blue-700">
¥{stats.totalAmount.toLocaleString()}
</View>
</View>
))}
{calculateStatistics().dealerStatistics.size === 0 && (
<View className="py-2 text-center text-sm text-gray-500">
</View>
)}
</View>
</View>
{/* 费用分类汇总 */}
<View>
<View className="mb-3 text-sm font-medium text-orange-600">
</View>
<View className="flex flex-wrap gap-3">
{Array.from(
calculateStatistics().costCategoryStatistics.entries(),
).map(([costName, amount]) => (
<View
key={costName}
className="min-w-[45%] flex-1 items-center justify-between rounded-lg border border-orange-200 bg-orange-50 p-3"
>
<View className="min-w-0 flex-1">
<View className="truncate text-sm font-medium text-gray-900">
{costName}
</View>
</View>
<View className="ml-2 text-sm font-medium text-orange-700">
¥{amount.toFixed(0)}
</View>
</View>
))}
{calculateStatistics().costCategoryStatistics.size ===
0 && (
<View className="w-full py-2 text-center text-sm text-gray-500">
</View>
)}
</View>
</View>
</View>
)}
</View>
</View>
<View className="overflow-hidden rounded-md bg-white shadow-md">
<View className="border-b border-gray-100 p-2.5">
<View className="text-neutral-darkest text-base font-medium">
</View>
</View>
{expenseRecordList && expenseRecordList.length > 0 ? (
expenseRecordList.map((record) => {
const isExpanded = expandedDays.has(record.recordDate || "");
const vehicleCount = record.expenseProvisionList?.length || 0;
const dayProfit =
(record.totalProvision || 0) - (record.totalExpense || 0);
return (
<View
key={record.recordDate}
className="border-b border-gray-100 last:border-b-0"
>
{/* 日期头部 - 可点击展开 */}
<View
className="cursor-pointer bg-gray-50 p-2.5 hover:bg-gray-100"
onClick={() => toggleDayExpansion(record.recordDate || "")}
>
{/* 第一行:日期 */}
<View className="mb-2 flex items-center justify-between">
<View className="flex items-center space-x-2">
<View className="text-sm font-medium text-gray-900">
{dayjs(record.recordDate).format("YYYY年MM月DD日")}
</View>
</View>
<View className="flex items-center space-x-2">
<View
className={`text-sm font-medium ${dayProfit >= 0 ? "text-green-600" : "text-red-600"}`}
>
¥{dayProfit.toLocaleString()}
</View>
<Icon
name={isExpanded ? "chevron-up" : "chevron-down"}
size={16}
className="text-gray-500"
/>
</View>
</View>
{/* 第二行:统计数据 */}
<View className="flex items-center justify-between text-xs">
<View className="flex items-center space-x-6">
<View className="text-gray-600">
<View className="font-medium"></View>
<View>{vehicleCount}</View>
</View>
<View className="text-blue-600">
<View className="font-medium"></View>
<View>
¥{(record.totalProvision || 0).toLocaleString()}
</View>
</View>
<View className="text-orange-600">
<View className="font-medium"></View>
<View>
¥{(record.totalExpense || 0).toLocaleString()}
</View>
</View>
</View>
<Button
icon={<Icon name="plus" size={12} color={"white"} />}
size={"mini"}
type={"primary"}
onClick={(e) => {
e.stopPropagation();
Taro.navigateTo({
url: `/pages/expenses/create?date=${record.recordDate}`,
});
}}
>
</Button>
</View>
</View>
{/* 展开的明细内容 */}
{isExpanded && (
<View className="max-h-96 overflow-y-auto">
{renderProvisionDetails(record)}
{renderCostDetails(record)}
</View>
)}
</View>
);
})
) : (
<View className="p-8 text-center">
<View className="text-sm text-gray-500"></View>
<View className="mt-2 text-xs text-gray-400">
</View>
</View>
)}
</View>
</View>
<View className="sticky bottom-0 z-10 bg-white">
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{/* 返回 */}
<View className="flex-1">
<Button
size={"large"}
block
type={"default"}
onClick={() => {
Taro.navigateBack();
}}
>
</Button>
</View>
<View className="flex-1">
<Button
icon={<Icon name="plus" size={12} color={"white"} />}
size={"large"}
block
type={"primary"}
onClick={() => {
Taro.navigateTo({
url: "/pages/expenses/create",
});
}}
>
</Button>
</View>
</View>
<SafeArea position="bottom" />
</View>
<Calendar
visible={show}
defaultValue={currentDate}
type="range"
startDate={"2025-01-01"}
onClose={() => setShow(false)}
onConfirm={(data) => {
setCurrentDate([
dayjs(data[0][3]).format("YYYY-MM-DD"),
dayjs(data[1][3]).format("YYYY-MM-DD"),
]);
}}
/>
</>
);
});

View File

@ -898,7 +898,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
@ -1061,7 +1062,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
@ -1091,7 +1093,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
offset?: number;
@ -1113,7 +1116,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
@ -1141,7 +1145,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
@ -1979,8 +1984,10 @@ declare namespace BusinessAPI {
type ExpenseRecordListQry = {
/** 状态1_启用0_禁用 */
status?: boolean;
/** 花销统计记录ID */
expenseRecordId?: string;
/** 开始日期 */
startDate?: string;
/** 结束日期 */
endDate?: string;
};
type ExpenseRecordShowQry = {
@ -2008,18 +2015,20 @@ declare namespace BusinessAPI {
expenseRecordId: string;
/** 记录日期YYYY-MM-DD */
recordDate?: string;
/** 计提车次数量 */
totalVehicleCount?: number;
/** 计提总金额 */
totalProvision?: number;
/** 花销总额 */
totalExpense?: number;
/** 日常利润 */
dailyProfit?: number;
/** 创建时间 */
createdAt?: string;
/** 花销费用明细 */
expenseCostList?: ExpenseCost[];
/** 花销计提明细 */
expenseProvisionList?: ExpenseProvision[];
/** 花销费用明细 */
expenseCostList?: ExpenseCost[];
/** 创建时间 */
createdAt?: string;
};
type getLastVehicleNoParams = {
@ -2767,7 +2776,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 关联项目id */
costItemIds?: string[];
/** 是否选中 */
@ -2799,7 +2809,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 关联项目id */
costItemIds?: string[];
/** 是否付款 */
@ -2897,7 +2908,8 @@ declare namespace BusinessAPI {
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
| "LOGISTICS_TYPE"
| "EXPENSE_TYPE";
/** 关联项目id */
costItemIds?: string[];
/** 创建时间 */

File diff suppressed because one or more lines are too long