From 8562aed7d14de1c4cf73c2d47ad24909daea2016 Mon Sep 17 00:00:00 2001 From: shenyifei Date: Fri, 19 Dec 2025 15:06:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(expenses):=20=E4=BC=98=E5=8C=96=E8=B4=B9?= =?UTF-8?q?=E7=94=A8=E5=88=9B=E5=BB=BA=E4=B8=8E=E8=AE=A1=E6=8F=90=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 ExpenseCostCreate 和 ExpenseProvisionCreate 组件添加必填字段标识 - 使用 generateShortId 替代时间戳生成唯一 ID - 移除备注字段的非必要校验逻辑 - 更新客户选择字段的显示文案与交互样式 - 在 ExpenseProvisionCreate 中移除客户名称必填限制 - 引入 Text 组件支持星号标注必填项 - 修复表单提交按钮的禁用条件判断逻辑 - 集成全局 loading 状态管理 - 实现费用记录保存成功后的提示反馈 - 将 DatePicker 替换为 Calendar 组件用于日期选择 - 为 CostPicker 添加 EXPENSE_TYPE 类型筛选参数 - 在 CostPageQry 类型中新增 name 字段定义 - 优化图标组件使用方式,替换原有 class 样式写法 --- .../src/components/cost/CostPicker.tsx | 4 +- .../components/expenses/ExpenseCostCard.tsx | 4 +- .../components/expenses/ExpenseCostCreate.tsx | 14 ++-- .../expenses/ExpenseProvisionCreate.tsx | 28 ++----- .../app-client/src/pages/expenses/create.tsx | 76 ++++++++++++------- .../src/services/business/typings.d.ts | 2 + 6 files changed, 72 insertions(+), 56 deletions(-) diff --git a/packages/app-client/src/components/cost/CostPicker.tsx b/packages/app-client/src/components/cost/CostPicker.tsx index ff1aea8..ad10c1e 100644 --- a/packages/app-client/src/components/cost/CostPicker.tsx +++ b/packages/app-client/src/components/cost/CostPicker.tsx @@ -7,10 +7,11 @@ import { business } from "@/services"; interface ICostPickerProps { onFinish: (costVO: BusinessAPI.CostVO) => void; trigger: React.ReactNode; + params?: BusinessAPI.CostPageQry; } export default function CostPicker(props: ICostPickerProps) { - const { onFinish, trigger } = props; + const { onFinish, trigger, params } = props; const [visible, setVisible] = useState(false); const [costVO, setCostVO] = useState(); @@ -28,6 +29,7 @@ export default function CostPicker(props: ICostPickerProps) { costListQry: { name: value || undefined, status: true, + ...params, }, }); diff --git a/packages/app-client/src/components/expenses/ExpenseCostCard.tsx b/packages/app-client/src/components/expenses/ExpenseCostCard.tsx index 5c29ca3..c25cae8 100644 --- a/packages/app-client/src/components/expenses/ExpenseCostCard.tsx +++ b/packages/app-client/src/components/expenses/ExpenseCostCard.tsx @@ -25,8 +25,8 @@ export default function ExpenseCostCard(props: IExpenseCostCardProps) { > - - + + diff --git a/packages/app-client/src/components/expenses/ExpenseCostCreate.tsx b/packages/app-client/src/components/expenses/ExpenseCostCreate.tsx index 8ec7626..82b01f6 100644 --- a/packages/app-client/src/components/expenses/ExpenseCostCreate.tsx +++ b/packages/app-client/src/components/expenses/ExpenseCostCreate.tsx @@ -6,8 +6,9 @@ import { TextArea, } from "@nutui/nutui-react-taro"; import { CostPicker, Icon } from "@/components"; -import { ScrollView, View } from "@tarojs/components"; +import { ScrollView, Text, View } from "@tarojs/components"; import { useEffect, useState } from "react"; +import { generateShortId } from "@/utils"; interface IExpenseCostCreateProps { onFinish?: (expressCost: BusinessAPI.ExpenseCost) => void; @@ -32,7 +33,6 @@ export default function ExpenseCostCreate(props: IExpenseCostCreateProps) { const [formErrors, setFormErrors] = useState<{ costId?: boolean; expenseAmount?: boolean; - remark?: boolean; }>({}); // 初始化表单数据 @@ -55,7 +55,6 @@ export default function ExpenseCostCreate(props: IExpenseCostCreateProps) { costId: !expressCost?.costId, expenseAmount: !expressCost?.expenseAmount || expressCost.expenseAmount <= 0, - remark: false, // 备注是可选的,不设为错误 }; setFormErrors(errors); @@ -75,7 +74,7 @@ export default function ExpenseCostCreate(props: IExpenseCostCreateProps) { ...expressCost, expenseCostId: editMode ? initialExpenseCost?.expenseCostId || expressCost.expenseCostId - : expressCost.expenseCostId || `EC_${Date.now()}`, + : expressCost.expenseCostId || generateShortId(), }; onFinish?.(finalExpenseCost); @@ -123,13 +122,16 @@ export default function ExpenseCostCreate(props: IExpenseCostCreateProps) { ) : ( <> - 费用类型 + 费用类型 * { setExpressCost((prev) => { return { @@ -167,7 +169,7 @@ export default function ExpenseCostCreate(props: IExpenseCostCreateProps) { )} - 金额 + 金额 * void; @@ -33,9 +34,7 @@ export default function ExpenseProvisionCreate( // 表单错误状态 const [formErrors, setFormErrors] = useState<{ - dealerName?: boolean; provisionAmount?: boolean; - remark?: boolean; }>({}); // 初始化表单数据 @@ -55,11 +54,9 @@ export default function ExpenseProvisionCreate( const validateForm = () => { const errors = { - dealerName: !expenseProvision?.dealerName, provisionAmount: !expenseProvision?.provisionAmount || expenseProvision.provisionAmount <= 0, - remark: false, // 备注是可选的,不设为错误 }; setFormErrors(errors); @@ -80,7 +77,7 @@ export default function ExpenseProvisionCreate( expenseProvisionId: editMode ? initialExpenseProvision?.expenseProvisionId || expenseProvision.expenseProvisionId - : expenseProvision.expenseProvisionId || `EP_${Date.now()}`, + : expenseProvision.expenseProvisionId || generateShortId(), }; onFinish?.(finalExpenseProvision); @@ -117,22 +114,22 @@ export default function ExpenseProvisionCreate( {editMode ? ( <> - 客户名称 + 客户选择(可选) - {expenseProvision?.dealerName || "未知客户"} + {expenseProvision?.dealerName || "未选客户"} ) : ( <> - 客户名称 + 客户名称(可选) { @@ -142,11 +139,6 @@ export default function ExpenseProvisionCreate( dealerName: dealerVO.shortName, }; }); - - setFormErrors((prev) => ({ - ...prev, - dealerId: false, - })); }} trigger={ - {formErrors.dealerName && ( - 请选择客户 - )} )} - 计提金额 + 计提金额 * item) diff --git a/packages/app-client/src/pages/expenses/create.tsx b/packages/app-client/src/pages/expenses/create.tsx index 909fbd7..c4360f7 100644 --- a/packages/app-client/src/pages/expenses/create.tsx +++ b/packages/app-client/src/pages/expenses/create.tsx @@ -2,12 +2,12 @@ import { useShareAppMessage } from "@tarojs/taro"; import hocAuth from "@/hocs/auth"; import { CommonComponent } from "@/types/typings"; import { View } from "@tarojs/components"; -import { ExpenseProvisionList, Icon } from "@/components"; +import { ExpenseCostList, ExpenseProvisionList, Icon } from "@/components"; import { useEffect, useRef, useState } from "react"; -import { Button, DatePicker, Dialog, SafeArea } 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 ExpenseCostList from "../../components/expenses/ExpenseCostList"; +import { globalStore } from "@/store/global-store"; export default hocAuth(function Page(props: CommonComponent) { const { shareOptions } = props; @@ -17,7 +17,7 @@ export default hocAuth(function Page(props: CommonComponent) { ); const [expenseRecord, setExpenseRecord] = useState(); - const [loading, setLoading] = useState(true); + const { setLoading } = globalStore((state: any) => state); const [show, setShow] = useState(false); @@ -98,14 +98,21 @@ export default hocAuth(function Page(props: CommonComponent) { try { // 这里添加实际的保存逻辑 console.log("保存数据:", expenseRecord); - // await business.expenseRecord.save(expenseRecord); + const { + data: { success }, + } = await business.expenseRecord.createExpenseRecord({ + ...expenseRecord, + recordDate: currentDate, + }); - // 保存成功后更新原始数据 - setOriginalData(JSON.parse(JSON.stringify(expenseRecord))); - setHasUnsavedChanges(false); - lastSaveTime.current = Date.now(); + if (success) { + // 保存成功后更新原始数据 + setOriginalData(JSON.parse(JSON.stringify(expenseRecord))); + setHasUnsavedChanges(false); + lastSaveTime.current = Date.now(); + } - return true; + return success; } catch (error) { console.error("保存数据失败:", error); return false; @@ -161,14 +168,6 @@ export default hocAuth(function Page(props: CommonComponent) { } }; - if (loading) { - return ( - - 加载中... - - ); - } - function onchange(expenseRecord: BusinessAPI.ExpenseRecordVO) { setExpenseRecord((prev) => { const totalProvision = @@ -291,7 +290,11 @@ export default hocAuth(function Page(props: CommonComponent) { onClick={async () => { const saveSuccess = await saveCurrentData(); if (saveSuccess) { - console.log("保存成功"); + Toast.show("toast", { + icon: "success", + title: "提示", + content: "保存成功", + }); } }} disabled={!hasUnsavedChanges} @@ -303,16 +306,13 @@ export default hocAuth(function Page(props: CommonComponent) { - setShow(false)} - threeDimensional={false} - onConfirm={(_, values) => { - const newDate = dayjs(values.join("-")).format("YYYY-MM-DD"); + onConfirm={(data) => { + const newDate = dayjs(data[3]).format("YYYY-MM-DD"); // 如果没有未保存变更,直接切换日期 if (!hasUnsavedChanges) { @@ -325,6 +325,28 @@ export default hocAuth(function Page(props: CommonComponent) { }} /> + {/* setShow(false)}*/} + {/* threeDimensional={false}*/} + {/* onConfirm={(_, values) => {*/} + {/* const newDate = dayjs(values.join("-")).format("YYYY-MM-DD");*/} + + {/* // 如果没有未保存变更,直接切换日期*/} + {/* if (!hasUnsavedChanges) {*/} + {/* setCurrentDate(newDate);*/} + {/* } else {*/} + {/* // 有未保存变更时,保存待切换日期,显示确认对话框*/} + {/* setPendingDate(newDate);*/} + {/* setConfirmVisible(true);*/} + {/* }*/} + {/* }}*/} + {/*/>*/} + {/* 日期切换确认对话框 */}