feat(dealer): 添加经销商应收账款功能并优化订单发货单相关组件
- 新增 DealerAccountRecordList 组件用于展示经销商应收账款记录 - 在 DealerList 中添加应收账款标签页和相关组件 - 为 OrderShipList 和 OrderShipModal 添加应收金额和调整金额列 - 新增 OrderSupplierSelectList 替代原有的 OrderSupplierInvoiceList - 重构 ReconciliationSummary 使用 ProForm 组件并优化抹零功能 - 更新对账单创建页面逻辑,使用新的应收金额和调整金额字段 - 添加 ReceivablesDetail 页面用于查看应收账款明细 - 优化发货单选择列表的列配置和渲染方式
This commit is contained in:
parent
925b9f4f76
commit
9001490da1
626
.claude/commands/create-page-component.md
Normal file
626
.claude/commands/create-page-component.md
Normal file
@ -0,0 +1,626 @@
|
||||
# /create-page-component Command
|
||||
|
||||
当使用此命令时,创建一个新的页面组件及其相关的业务组件。
|
||||
|
||||
## 目的
|
||||
|
||||
在 ERPTurbo_Admin 项目中快速创建一个标准的页面组件,包括:
|
||||
1. 业务组件(基于 BizContainer)
|
||||
2. 页面组件
|
||||
3. 国际化翻译
|
||||
4. 组件导出配置
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 项目使用 UmiJS Max + Ant Design + TypeScript
|
||||
- 已有 BizContainer 核心业务组件
|
||||
- 已有 API 服务层(通过 OpenAPI 自动生成)
|
||||
|
||||
## 使用方法
|
||||
|
||||
```
|
||||
/create-page-component <页面名称> <API服务名称>
|
||||
```
|
||||
|
||||
**参数说明:**
|
||||
- `<页面名称>`: 页面名称,如 `ReceivablesDetail`
|
||||
- `<API服务名称>`: API 服务名称,如 `dealerAccountRecord`
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 1. 分析现有代码结构
|
||||
|
||||
首先查找类似页面作为参考:
|
||||
- 查看目标页面组件(如 `FarmerPayment.tsx`)的实现模式
|
||||
- 确定业务组件应该放在哪个目录(如 `components/Dealer/`)
|
||||
- 查找 API 服务定义(如 `services/business/dealerAccountRecord.ts`)
|
||||
- 查看 API 类型定义(`services/business/typings.d.ts` 中的 VO 类型)
|
||||
|
||||
### 2. 创建业务组件
|
||||
|
||||
在 `packages/app-operation/src/components/<业务目录>/` 下创建 `<ComponentName>List.tsx`:
|
||||
|
||||
**组件结构模板:**
|
||||
```tsx
|
||||
import { BizContainer, BizValueType, ModeType } from '@/components';
|
||||
import { business } from '@/services';
|
||||
import { useIntl } from '@@/exports';
|
||||
import { ProColumns } from '@ant-design/pro-components';
|
||||
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
|
||||
import React from 'react';
|
||||
|
||||
interface IComponentNameListProps {
|
||||
ghost?: boolean;
|
||||
// 筛选参数
|
||||
xxxId?: BusinessAPI.XXXVO['xxxId'];
|
||||
search?: boolean;
|
||||
onValueChange?: () => void;
|
||||
mode?: ModeType;
|
||||
trigger?: () => React.ReactNode;
|
||||
}
|
||||
|
||||
export default function ComponentNameList(props: IComponentNameListProps) {
|
||||
const {
|
||||
ghost = false,
|
||||
xxxId,
|
||||
search = true,
|
||||
mode = 'page',
|
||||
trigger,
|
||||
onValueChange,
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const intlPrefix = 'componentName'; // 国际化前缀
|
||||
|
||||
// 定义表格列
|
||||
const columns: ProColumns<BusinessAPI.XXXVO, BizValueType>[] = [
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.xxx' }),
|
||||
dataIndex: 'xxx',
|
||||
key: 'xxx',
|
||||
valueType: 'text', // text|money|dateTime|select等
|
||||
},
|
||||
// 更多列...
|
||||
];
|
||||
|
||||
const detailColumns: ProDescriptionsItemProps<
|
||||
BusinessAPI.XXXVO,
|
||||
BizValueType
|
||||
>[] = columns as ProDescriptionsItemProps<
|
||||
BusinessAPI.XXXVO,
|
||||
BizValueType
|
||||
>[];
|
||||
|
||||
return (
|
||||
<BizContainer<
|
||||
typeof business.apiService,
|
||||
BusinessAPI.XXXVO,
|
||||
BusinessAPI.XXXPageQry
|
||||
>
|
||||
rowKey={'id'}
|
||||
permission={'operation-xxx'}
|
||||
func={business.apiService}
|
||||
method={'apiService'}
|
||||
methodUpper={'ApiService'}
|
||||
intlPrefix={intlPrefix}
|
||||
modeType={mode}
|
||||
onValueChange={onValueChange}
|
||||
container={{ ghost }}
|
||||
status={false}
|
||||
page={{
|
||||
fieldProps: {
|
||||
bordered: true,
|
||||
ghost,
|
||||
search,
|
||||
params: {
|
||||
...(xxxId && { xxxId }),
|
||||
},
|
||||
},
|
||||
columns,
|
||||
options: () => [],
|
||||
}}
|
||||
create={false} // 根据需要启用
|
||||
update={false}
|
||||
destroy={false}
|
||||
detail={{
|
||||
rowId: xxxId,
|
||||
formType: 'drawer',
|
||||
columns: detailColumns,
|
||||
trigger,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**关键点:**
|
||||
- 使用 `BizContainer` 作为容器组件
|
||||
- 定义 `columns` 用于列表展示
|
||||
- 定义 `detailColumns` 用于详情展示
|
||||
- 通过 `params` 传递筛选条件
|
||||
- 根据需求配置 `create/update/destroy`
|
||||
|
||||
### 3. 导出业务组件
|
||||
|
||||
在 `packages/app-operation/src/components/<业务目录>/index.ts` 中添加导出:
|
||||
|
||||
```typescript
|
||||
export { default as ComponentNameList } from './ComponentNameList';
|
||||
```
|
||||
|
||||
### 4. 创建页面组件
|
||||
|
||||
在 `packages/app-operation/src/pages/` 下创建 `<PageName>.tsx`:
|
||||
|
||||
```tsx
|
||||
import { ComponentNameList } from '@/components';
|
||||
|
||||
export default function Page() {
|
||||
return <ComponentNameList />;
|
||||
}
|
||||
```
|
||||
|
||||
**关键点:**
|
||||
- 文件名与路由一致
|
||||
- 导出为 `Page` 函数
|
||||
- 直接渲染业务组件
|
||||
|
||||
### 5. 添加国际化翻译
|
||||
|
||||
在 `packages/app-operation/src/locales/zh-CN.ts` 中添加翻译:
|
||||
|
||||
```typescript
|
||||
componentName: {
|
||||
column: {
|
||||
// 列标题
|
||||
fieldName: '字段名称',
|
||||
// 枚举值
|
||||
'enum.key': '枚举值显示文本',
|
||||
option: '操作',
|
||||
},
|
||||
modal: {
|
||||
view: {
|
||||
title: '查看详情',
|
||||
button: '详情',
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
**关键点:**
|
||||
- 使用 `intlPrefix` 作为顶级键
|
||||
- `column` 中包含所有列的翻译
|
||||
- 枚举值使用 `'enum.key'` 格式
|
||||
- 添加 `modal` 相关翻译
|
||||
|
||||
## 常见 BizContainer 配置
|
||||
|
||||
### 如何判断是否有内置 valueType
|
||||
|
||||
**快速检查方法:**
|
||||
查看 `packages/app-operation/src/components/Biz/typing.ts` 中的 `BizValueType` 类型定义(第 18-28 行)。
|
||||
|
||||
**内置 valueType 列表:**
|
||||
```typescript
|
||||
export type BizValueType =
|
||||
| 'user' // 用户
|
||||
| 'customField' // 自定义字段
|
||||
| 'status' // 状态
|
||||
| 'remark' // 备注
|
||||
| 'order' // 采购单 ✅
|
||||
| 'dealer' // 经销商 ✅
|
||||
| 'paymentTask' // 付款任务 ✅
|
||||
| 'company' // 公司 ✅
|
||||
| 'orderCost' // 订单费用 ✅
|
||||
| 'supplier'; // 供应商 ✅
|
||||
```
|
||||
|
||||
**判断流程:**
|
||||
```
|
||||
1. 检查关联对象类型(如 orderVO、dealerVO、orderShipVO)
|
||||
↓
|
||||
2. 去掉 "VO" 后缀,得到类型名(order → order, orderShip → orderShip)
|
||||
↓
|
||||
3. 在 BizValueType 中查找
|
||||
↓
|
||||
4a. 找到 → 使用对应的 valueType
|
||||
↓
|
||||
4b. 未找到 → 使用嵌套 dataIndex 数组
|
||||
```
|
||||
|
||||
**示例:**
|
||||
- `orderVO` → 去掉 "VO" → `order` → 在列表中 ✅ → 使用 `valueType: 'order'`
|
||||
- `dealerVO` → 去掉 "VO" → `dealer` → 在列表中 ✅ → 使用 `valueType: 'dealer'`
|
||||
- `orderShipVO` → 去掉 "VO" → `orderShip` → 不在列表 ❌ → 使用 `dataIndex: ['orderShipVO', 'orderSn']`
|
||||
|
||||
### valueType 类型
|
||||
|
||||
| 类型 | 说明 | dataIndex 格式 | key 格式 | 适用场景 |
|
||||
|------|------|----------------|----------|----------|
|
||||
| `text` | 文本 | `fieldName` | `fieldName` | 普通文本字段 |
|
||||
| `money` | 金额 | `amount` | `amount` | 自动格式化货币 |
|
||||
| `dateTime` | 日期时间 | `createdAt` | `createdAt` | 格式化时间戳 |
|
||||
| `select` | 下拉选择 | `type` | `type` | 配合 valueEnum |
|
||||
| `switch` | 开关 | `status` | `status` | 布尔值显示 |
|
||||
| `order` | 采购单 | `orderVO` | `orderId` | orderVO 对象 |
|
||||
| `dealer` | 经销商 | `dealerVO` | `dealerId` | dealerVO 对象 |
|
||||
| `company` | 公司 | `companyVO` | `companyId` | companyVO 对象 |
|
||||
| `paymentTask` | 付款任务 | `paymentTaskVO` | `paymentTaskId` | paymentTaskVO 对象 |
|
||||
| `orderCost` | 订单费用 | `orderCostVO` | `orderCostId` | orderCostVO 对象 |
|
||||
| `supplier` | 供应商 | `supplierVO` | `supplierId` | supplierVO 对象 |
|
||||
|
||||
### 对象关联列配置(xxxVO 模式)
|
||||
|
||||
项目中大量使用对象关联模式,当 VO 类型中包含嵌套的 `xxxVO` 对象时,优先使用内置 valueType。
|
||||
|
||||
#### 通用规则
|
||||
|
||||
**有内置 valueType 的情况:**
|
||||
```tsx
|
||||
// 1. 检查 BizValueType 是否包含对应类型
|
||||
// 2. 如果包含,使用 xxxVO + xxxId + xxx 模式
|
||||
|
||||
{
|
||||
dataIndex: 'orderVO', // 完整的 VO 字段名
|
||||
key: 'orderId', // 对应的主键字段
|
||||
valueType: 'order', // BizValueType 中定义的类型
|
||||
}
|
||||
```
|
||||
|
||||
**无内置 valueType 的情况:**
|
||||
```tsx
|
||||
// 1. BizValueType 中没有对应类型
|
||||
// 2. 使用嵌套 dataIndex 数组直接访问子字段
|
||||
|
||||
{
|
||||
dataIndex: ['orderShipVO', 'orderSn'], // 嵌套路径
|
||||
key: 'orderShipId',
|
||||
// 不需要 valueType,默认为文本
|
||||
}
|
||||
```
|
||||
|
||||
**示例对照表:**
|
||||
|
||||
| VO 字段 | 是否有 valueType | dataIndex | key | valueType | 说明 |
|
||||
|---------|-----------------|-----------|-----|-----------|------|
|
||||
| `orderVO?: OrderVO` | ✅ 是 | `orderVO` | `orderId` | `order` | 采购单信息 |
|
||||
| `dealerVO?: DealerVO` | ✅ 是 | `dealerVO` | `dealerId` | `dealer` | 经销商信息 |
|
||||
| `companyVO?: CompanyVO` | ✅ 是 | `companyVO` | `companyId` | `company` | 公司信息 |
|
||||
| `supplierVO?: SupplierVO` | ✅ 是 | `supplierVO` | `supplierId` | `supplier` | 供应商信息 |
|
||||
| `orderShipVO?: OrderShipVO` | ❌ 否 | `['orderShipVO', 'orderSn']` | `orderShipId` | - | 发货单信息 |
|
||||
| `paymentTaskVO?: PaymentTaskVO` | ✅ 是 | `paymentTaskVO` | `paymentTaskId` | `paymentTask` | 付款任务信息 |
|
||||
| `orderCostVO?: OrderCostVO` | ✅ 是 | `orderCostVO` | `orderCostId` | `orderCost` | 订单费用信息 |
|
||||
|
||||
#### order 列(采购单关联)
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.order' }),
|
||||
dataIndex: 'orderVO',
|
||||
key: 'orderId',
|
||||
valueType: 'order',
|
||||
},
|
||||
```
|
||||
|
||||
**要点:**
|
||||
- BizContainer 内部会自动处理订单链接和展示
|
||||
- 支持点击跳转到订单详情页
|
||||
- 自动显示订单编号或关键信息
|
||||
|
||||
**参考文件:** `components/Order/OrderSupplierList.tsx:54-59`
|
||||
|
||||
#### dealer 列(经销商关联)
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.dealer' }),
|
||||
dataIndex: 'dealerVO',
|
||||
key: 'dealerId',
|
||||
valueType: 'dealer',
|
||||
hidden: !!dealerId, // 可选:如果已传入 dealerId,则隐藏此列
|
||||
},
|
||||
```
|
||||
|
||||
**要点:**
|
||||
- 显示经销商名称链接
|
||||
- 支持点击跳转到经销商详情
|
||||
- 可根据业务需求使用 `hidden` 属性控制显示
|
||||
|
||||
**参考文件:**
|
||||
- `components/Dealer/DealerPaymentAccountList.tsx:44-48`
|
||||
- `components/Order/OrderShipList.tsx:41-45`
|
||||
|
||||
#### company 列(公司关联)
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.company' }),
|
||||
dataIndex: 'companyVO',
|
||||
key: 'companyId',
|
||||
valueType: 'company',
|
||||
},
|
||||
```
|
||||
|
||||
**要点:**
|
||||
- 显示公司名称链接
|
||||
- 支持点击跳转到公司详情
|
||||
- 常用于展示入账公司、销售公司等
|
||||
|
||||
**参考文件:** `components/Order/OrderShipList.tsx:47-51`
|
||||
|
||||
#### 无内置 valueType 的关联列
|
||||
|
||||
对于 BizValueType 中没有定义的类型(如 `orderShipVO`),使用嵌套 dataIndex 数组:
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.orderShip' }),
|
||||
dataIndex: ['orderShipVO', 'orderSn'], // 直接访问嵌套字段
|
||||
key: 'orderShipId',
|
||||
// 不需要指定 valueType
|
||||
},
|
||||
```
|
||||
|
||||
**优点:**
|
||||
- ✅ 简洁:无需自定义 render 函数
|
||||
- ✅ 类型安全:利用 ProTable 的嵌套字段访问
|
||||
- ✅ 自动处理空值:ProTable 自动处理 undefined 情况
|
||||
|
||||
**更多嵌套示例:**
|
||||
```tsx
|
||||
// 访问嵌套对象的单个字段
|
||||
{ dataIndex: ['orderShipVO', 'orderSn'] } // 发货单编号
|
||||
{ dataIndex: ['dealerVO', 'shortName'] } // 经销商简称
|
||||
{ dataIndex: ['companyVO', 'fullName'] } // 公司全称
|
||||
{ dataIndex: ['orderVO', 'orderVehicle', 'plate'] } // 多层嵌套:订单的车辆车牌
|
||||
```
|
||||
|
||||
**参考文件:** `components/Dealer/DealerAccountRecordList.tsx:73-77`
|
||||
|
||||
#### 条件隐藏关联列
|
||||
|
||||
当组件已通过 props 传入关联对象的 ID 时,可以隐藏该列避免冗余:
|
||||
|
||||
```tsx
|
||||
// 接收 props
|
||||
interface IDealerAccountRecordListProps {
|
||||
dealerId?: BusinessAPI.DealerAccountRecordVO['dealerId'];
|
||||
orderId?: BusinessAPI.DealerAccountRecordVO['orderId'];
|
||||
}
|
||||
|
||||
// 列配置
|
||||
{
|
||||
dataIndex: 'dealerVO',
|
||||
key: 'dealerId',
|
||||
valueType: 'dealer',
|
||||
hidden: !!dealerId, // 如果已传入 dealerId,则隐藏此列
|
||||
},
|
||||
```
|
||||
|
||||
**使用场景:**
|
||||
- 列表作为详情页的子组件时
|
||||
- 已知特定经销商/订单的记录列表
|
||||
- 避免显示冗余的关联信息
|
||||
|
||||
#### select 列(枚举类型)
|
||||
|
||||
对于有固定选项的枚举字段:
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.targetType' }),
|
||||
dataIndex: 'targetType',
|
||||
key: 'targetType',
|
||||
valueType: 'select',
|
||||
valueEnum: {
|
||||
VALUE_1: { text: '选项1', status: 'Processing' },
|
||||
VALUE_2: { text: '选项2', status: 'Success' },
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
#### money 列(金额格式化)
|
||||
|
||||
金额字段会自动格式化,也可以自定义渲染:
|
||||
|
||||
```tsx
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.amount' }),
|
||||
dataIndex: 'amount',
|
||||
key: 'amount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
render: (_, record) => (
|
||||
<span className={record.amount >= 0 ? 'text-green-600' : 'text-red-600'}>
|
||||
{formatCurrency(record.amount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
```
|
||||
|
||||
### 权限配置格式
|
||||
|
||||
```
|
||||
operation-<资源>-<操作>
|
||||
例如: operation-dealer-account-record-view
|
||||
```
|
||||
|
||||
### 国际化前缀命名规范
|
||||
|
||||
- 页面级别: 使用小写+连字符,如 `dealer-account-record`
|
||||
- 组件级别: 使用驼峰式,如 `dealerAccountRecord`
|
||||
- 保持与 API 服务名称一致
|
||||
|
||||
## 快速参考:关联列配置决策树
|
||||
|
||||
```
|
||||
需要显示关联对象(xxxVO)?
|
||||
↓
|
||||
检查 BizValueType 是否包含对应类型
|
||||
↓
|
||||
┌─────────────┬─────────────────┐
|
||||
│ 包含 ✅ │ 不包含 ❌ │
|
||||
├─────────────┼─────────────────┤
|
||||
│ 使用 │ 使用嵌套 │
|
||||
│ valueType │ dataIndex 数组 │
|
||||
├─────────────┼─────────────────┤
|
||||
│ 示例: │ 示例: │
|
||||
│ dataIndex: │ dataIndex: │
|
||||
│ 'orderVO' │ ['orderShipVO',│
|
||||
│ valueType: │ 'orderSn'] │
|
||||
│ 'order' │ │
|
||||
└─────────────┴─────────────────┘
|
||||
```
|
||||
|
||||
## 常见关联列配置速查表
|
||||
|
||||
| 场景 | dataIndex | key | valueType | 备注 |
|
||||
|------|-----------|-----|-----------|------|
|
||||
| **有内置 valueType** |
|
||||
| 采购单 | `orderVO` | `orderId` | `order` | 自动显示订单链接 |
|
||||
| 经销商 | `dealerVO` | `dealerId` | `dealer` | 自动显示经销商链接 |
|
||||
| 公司 | `companyVO` | `companyId` | `company` | 自动显示公司链接 |
|
||||
| 供应商 | `supplierVO` | `supplierId` | `supplier` | 自动显示供应商链接 |
|
||||
| 付款任务 | `paymentTaskVO` | `paymentTaskId` | `paymentTask` | 自动显示任务链接 |
|
||||
| 订单费用 | `orderCostVO` | `orderCostId` | `orderCost` | 自动显示费用链接 |
|
||||
| **无内置 valueType** |
|
||||
| 发货单编号 | `['orderShipVO', 'orderSn']` | `orderShipId` | - | 直接访问嵌套字段 |
|
||||
| 经销商简称 | `['dealerVO', 'shortName']` | `dealerId` | - | 直接访问嵌套字段 |
|
||||
| 车牌号 | `['orderVO', 'orderVehicle', 'plate']` | - | - | 支持多层嵌套 |
|
||||
|
||||
## 示例参考
|
||||
|
||||
查看以下文件作为参考:
|
||||
- 业务组件: `components/Dealer/DealerAccountRecordList.tsx`
|
||||
- 页面组件: `pages/ReceivablesDetail.tsx`
|
||||
- 组件导出: `components/Dealer/index.ts`
|
||||
- 国际化: `locales/zh-CN.ts` 中的 `dealerAccountRecord` 部分
|
||||
|
||||
### DealerAccountRecordList 组件示例
|
||||
|
||||
该组件展示了以下特性:
|
||||
- ✅ **dealer 列**: 展示关联的经销商(第 60-66 行)
|
||||
- 使用 `valueType: 'dealer'`
|
||||
- 条件隐藏:当已传入 `dealerId` 时隐藏此列
|
||||
- ✅ **order 列**: 展示关联的采购单(第 67-72 行)
|
||||
- 使用 `valueType: 'order'`
|
||||
- ✅ **orderShip 列**: 使用嵌套 dataIndex 访问发货单字段(第 73-77 行)
|
||||
- 使用 `dataIndex: ['orderShipVO', 'orderSn']`
|
||||
- 无需自定义 render 函数
|
||||
- 无需 valueType(BizValueType 中未定义 orderShip)
|
||||
- ✅ **枚举类型列**: 变动类型使用 Tag 和颜色区分(第 89-103 行)
|
||||
- ✅ **金额格式化**: 使用 formatCurrency 格式化金额(第 110-144 行)
|
||||
- ✅ **动态样式**: 根据正负值显示不同颜色和图标
|
||||
- ✅ **筛选条件**: 支持 dealerId 和 orderId 筛选(第 182-185 行)
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 业务组件已创建在正确的目录
|
||||
- [ ] 组件已正确导出
|
||||
- [ ] 页面组件已创建
|
||||
- [ ] 国际化翻译已添加
|
||||
- [ ] API 服务和类型定义已确认存在
|
||||
- [ ] 权限配置正确
|
||||
- [ ] 组件 props 支持所需的筛选条件
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 问题: 组件找不到
|
||||
**解决**: 检查 `components/index.ts` 是否正确导出了业务组件目录
|
||||
|
||||
### 问题: 翻译未生效
|
||||
**解决**: 检查 `intlPrefix` 是否与国际化文件中的键一致
|
||||
|
||||
### 问题: API 类型错误
|
||||
**解决**:
|
||||
1. 确认 API 服务文件存在于 `services/business/`
|
||||
2. 检查类型定义是否存在于 `typings.d.ts`
|
||||
3. 确保 `business.apiService` 导入正确
|
||||
|
||||
### 问题: 权限报错
|
||||
**解决**: 确认 `permission` 属性格式为 `operation-<resource>-<action>`
|
||||
|
||||
### 问题: order 列不显示或报错
|
||||
**原因分析**:
|
||||
1. TypeScript 类型定义中可能没有 `orderVO` 字段
|
||||
2. API 返回数据时实际包含 `orderVO` 字段(后端动态扩展)
|
||||
|
||||
**解决方案**:
|
||||
- 方案1: 如果类型定义中缺少 `orderVO`,可以在组件中扩展类型:
|
||||
```tsx
|
||||
// 在组件顶部添加类型扩展
|
||||
declare module '@/services/business' {
|
||||
namespace BusinessAPI {
|
||||
interface DealerAccountRecordVO {
|
||||
orderVO?: OrderVO;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 方案2: 使用类型断言(不推荐,但可用):
|
||||
```tsx
|
||||
const columns: ProColumns<any, BizValueType>[] = [
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
- 方案3: 联系后端更新 OpenAPI 规范,确保 `orderVO` 字段在类型定义中
|
||||
|
||||
### 问题: dealer 列不显示经销商名称
|
||||
**原因**: BizContainer 内部会自动处理,但需要确保 `dealerVO` 字段存在
|
||||
|
||||
**解决**:
|
||||
1. 确认 API 返回数据包含 `dealerVO` 对象
|
||||
2. 检查 `dataIndex` 使用的是 `dealerVO` 而不是 `dealerId`
|
||||
3. 检查 `valueType` 是否设置为 `dealer`
|
||||
|
||||
### 问题: 自定义关联列(如 orderShip)显示为 [object Object]
|
||||
**原因**: 直接渲染对象而没有提取具体字段
|
||||
|
||||
**解决**:
|
||||
```tsx
|
||||
// ❌ 错误写法 - 直接渲染整个对象
|
||||
{
|
||||
dataIndex: 'orderShipVO',
|
||||
render: (_, record) => <span>{record.orderShipVO}</span>,
|
||||
}
|
||||
|
||||
// ❌ 错误写法 - 使用自定义 render 访问字段
|
||||
{
|
||||
dataIndex: 'orderShipVO',
|
||||
render: (_, record) =>
|
||||
record.orderShipVO ? (
|
||||
<span>{record.orderShipVO.orderSn}</span>
|
||||
) : null,
|
||||
}
|
||||
|
||||
// ✅ 正确写法 - 使用嵌套 dataIndex 数组
|
||||
{
|
||||
dataIndex: ['orderShipVO', 'orderSn'], // 直接访问嵌套字段
|
||||
key: 'orderShipId',
|
||||
// 不需要 render,ProTable 自动处理
|
||||
}
|
||||
```
|
||||
|
||||
**优势对比:**
|
||||
- ❌ render 方式:代码冗长,需要手动处理空值
|
||||
- ✅ 嵌套 dataIndex:简洁清晰,ProTable 自动处理所有情况
|
||||
|
||||
### 问题: 关联列在嵌套组件中重复显示
|
||||
**原因**: 当列表作为详情页的子组件时,父组件已通过 props 传入 ID
|
||||
|
||||
**解决**: 使用 `hidden` 属性条件隐藏
|
||||
```tsx
|
||||
{
|
||||
dataIndex: 'dealerVO',
|
||||
key: 'dealerId',
|
||||
valueType: 'dealer',
|
||||
hidden: !!dealerId, // 如果已传入 dealerId,则隐藏此列
|
||||
},
|
||||
```
|
||||
|
||||
### 问题: order 列点击后不跳转
|
||||
**解决**:
|
||||
1. 确认 `dataIndex` 使用的是 `orderVO` 而不是 `orderId`
|
||||
2. 确认 `key` 使用的是 `orderId`
|
||||
3. 检查 BizContainer 配置中 `detail` 是否正确启用
|
||||
80
.claude/rules/services-generated.md
Normal file
80
.claude/rules/services-generated.md
Normal file
@ -0,0 +1,80 @@
|
||||
---
|
||||
paths: src/services/**/*.ts
|
||||
---
|
||||
# 规则:不要直接修改 src/services 目录,使用 typings.d.ts 获取类型
|
||||
|
||||
## 规则说明
|
||||
|
||||
`packages/app-operation/src/services/` 目录下的文件由 OpenAPI 自动生成,不应手动修改。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
src/services/
|
||||
├── index.ts # 导出入口(自动生成)
|
||||
├── business/ # 业务 API
|
||||
│ ├── index.ts # 模块导出(自动生成)
|
||||
│ ├── order.ts # API 实现(自动生成)
|
||||
│ └── typings.d.ts # 类型定义(从 typings.d.ts 读取)
|
||||
├── auth/
|
||||
│ ├── index.ts
|
||||
│ ├── user.ts
|
||||
│ └── typings.d.ts
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 禁止行为
|
||||
|
||||
- ❌ 直接修改 `src/services/**/*.ts` 文件
|
||||
- ❌ 在 `.ts` 文件中添加、删除或修改 API 函数
|
||||
- ❌ 手动编辑类型定义
|
||||
|
||||
## 正确做法
|
||||
|
||||
### 1. 获取类型信息
|
||||
|
||||
当需要查看或使用 API 类型时,**必须**使用 Glob/Grep 工具读取 `typings.d.ts` 文件:
|
||||
|
||||
```bash
|
||||
# 正确:读取类型定义文件
|
||||
Glob pattern: "packages/app-operation/src/services/**/typings.d.ts"
|
||||
Grep pattern: "OrderVO" path: "packages/app-operation/src/services/business/typings.d.ts"
|
||||
|
||||
# 错误:直接读取 .ts 实现文件
|
||||
Read file: "packages/app-operation/src/services/business/typings.d.ts"
|
||||
```
|
||||
|
||||
### 2. 查找 API 函数
|
||||
|
||||
查找 API 函数时,通过模块名推断文件位置,使用 Grep 搜索:
|
||||
|
||||
```bash
|
||||
# 查找订单相关 API
|
||||
Grep path: "packages/app-operation/src/services" pattern: "order"
|
||||
```
|
||||
|
||||
### 3. 更新 API
|
||||
|
||||
如需更新 API 类型定义,运行:
|
||||
|
||||
```bash
|
||||
cd packages/app-operation
|
||||
pnpm openapi
|
||||
```
|
||||
|
||||
## 类型命名规范
|
||||
|
||||
`typings.d.ts` 中的类型遵循以下命名模式:
|
||||
|
||||
| 类型后缀 | 用途 | 示例 |
|
||||
|---------|------|------|
|
||||
| `VO` | 视图对象(响应) | `OrderVO` |
|
||||
| `Qry` | 查询参数 | `OrderPageQry` |
|
||||
| `Cmd` | 命令参数(创建/更新) | `OrderCreateCmd` |
|
||||
| `PageQry` | 分页查询 | `OrderPageQry` |
|
||||
|
||||
## 违反此规则的后果
|
||||
|
||||
- 手动修改会在 `pnpm openapi` 后被覆盖
|
||||
- 可能导致 API 类型与后端不一致
|
||||
- 破坏自动生成机制的完整性
|
||||
31
.claude/rules/swagger-json.md
Normal file
31
.claude/rules/swagger-json.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
paths: swagger/*.json
|
||||
---
|
||||
# 规则:不要加载或修改 swagger/*.json 文件
|
||||
|
||||
## 规则说明
|
||||
|
||||
`swagger/` 目录下的 JSON 文件是后端服务自动生成的 OpenAPI 规范文件,由后端团队维护。
|
||||
|
||||
## 禁止行为
|
||||
|
||||
- ❌ 直接读取 `swagger/*.json` 文件
|
||||
- ❌ 修改 `swagger/*.json` 文件
|
||||
- ❌ 在前端代码中依赖这些文件
|
||||
- ❌ 将 swagger JSON 文件纳入版本控制(如需跟踪,应由后端处理)
|
||||
|
||||
## 正确做法
|
||||
|
||||
1. **更新 API 类型**:如需更新前端 API 类型定义,运行命令:
|
||||
```bash
|
||||
cd packages/app-operation
|
||||
pnpm openapi
|
||||
```
|
||||
|
||||
2. **使用生成的 services**:前端应使用 `src/services/` 目录下自动生成的 API 客户端代码,而非直接解析 swagger 文件
|
||||
|
||||
## 违反此规则的后果
|
||||
|
||||
- 可能导致前端与后端 API 不同步
|
||||
- 手动修改的 swagger 文件会在下次后端同步时被覆盖
|
||||
- 破坏前后端约定的 OpenAPI 规范
|
||||
22
CLAUDE.md
22
CLAUDE.md
@ -272,27 +272,30 @@ pnpm test
|
||||
## 开发注意事项
|
||||
|
||||
1. **不要直接修改 services/ 目录**
|
||||
- 这些文件由 OpenAPI 自动生成
|
||||
- 修改 swagger/ 规范后重新生成
|
||||
- 这些文件由 OpenAPI 自动生成,修改后会被覆盖
|
||||
- 详细规则见 [.claude/rules/services-generated.md](./.claude/rules/services-generated.md)
|
||||
|
||||
2. **遵循组件命名约定**
|
||||
2. **不要加载或修改 swagger/*.json 文件**
|
||||
- 详细规则见 [.claude/rules/swagger-json.md](./.claude/rules/swagger-json.md)
|
||||
|
||||
3. **遵循组件命名约定**
|
||||
- 页面组件:文件名 + `Page` 后缀,导出为 `Page`
|
||||
- 业务组件:语义化命名,如 `NewComponentList`
|
||||
|
||||
3. **国际化是必需的**
|
||||
4. **国际化是必需的**
|
||||
- 所有用户可见文本必须使用 `useIntl()` 和 `intl.formatMessage()`
|
||||
- 定义 `intlPrefix` 前缀
|
||||
|
||||
4. **权限控制**
|
||||
5. **权限控制**
|
||||
- 页面使用 `PageContainer` 包装
|
||||
- 操作按钮使用 `ButtonAccess` 包装
|
||||
- 权限标识格式:`operation-{resource}-{action}`
|
||||
|
||||
5. **响应式设计**
|
||||
6. **响应式设计**
|
||||
- 使用 `isMobile` 属性自动适配移动端
|
||||
- 表单宽度和布局会自动调整
|
||||
|
||||
6. **状态管理**
|
||||
7. **状态管理**
|
||||
- 使用 UmiJS 内置状态管理(initialState、model)
|
||||
- 组件间通信使用 `actionRef`
|
||||
|
||||
@ -316,9 +319,14 @@ pnpm test
|
||||
|
||||
## 相关文档
|
||||
|
||||
### 开发规则
|
||||
- services 自动生成规则:[.claude/rules/services-generated.md](./.claude/rules/services-generated.md)
|
||||
- 不要查看或修改 swagger JSON:[.claude/rules/swagger-json.md](./.claude/rules/swagger-json.md)
|
||||
- 项目架构设计:`.lingma/rules/design.md`
|
||||
- Biz 组件设计规则:`.lingma/rules/biz.md`
|
||||
- 添加新页面指南:`.lingma/rules/add-new-page.md`
|
||||
|
||||
### 官方文档
|
||||
- UmiJS Max 文档:https://umijs.org/docs/max/introduce
|
||||
- Ant Design 文档:https://ant.design
|
||||
- PNPM 文档:https://pnpm.io
|
||||
|
||||
@ -0,0 +1,203 @@
|
||||
import { BizContainer, BizValueType, ModeType } from '@/components';
|
||||
import { business } from '@/services';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { useIntl } from '@@/exports';
|
||||
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||
import { ProColumns } from '@ant-design/pro-components';
|
||||
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
|
||||
import { Tag } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
interface IDealerAccountRecordListProps {
|
||||
ghost?: boolean;
|
||||
dealerVO?: BusinessAPI.DealerVO;
|
||||
orderVO?: BusinessAPI.OrderVO;
|
||||
dealerAccountRecordId: BusinessAPI.DealerAccountRecordVO['dealerAccountRecordId'];
|
||||
search?: boolean;
|
||||
onValueChange?: () => void;
|
||||
mode?: ModeType;
|
||||
trigger?: () => React.ReactNode;
|
||||
}
|
||||
|
||||
export default function DealerAccountRecordList(
|
||||
props: IDealerAccountRecordListProps,
|
||||
) {
|
||||
const {
|
||||
ghost = false,
|
||||
dealerVO,
|
||||
orderVO,
|
||||
dealerAccountRecordId,
|
||||
search = true,
|
||||
mode = 'page',
|
||||
trigger,
|
||||
onValueChange,
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const intlPrefix = 'dealerAccountRecord';
|
||||
|
||||
// 变动类型映射
|
||||
const targetTypeMap: Record<string, { label: string; color: string }> = {
|
||||
ORIGIN_PURCHASE_SHIP: {
|
||||
label: intl.formatMessage({
|
||||
id: intlPrefix + '.targetType.originPurchaseShip',
|
||||
}),
|
||||
color: 'blue',
|
||||
},
|
||||
MARKET_PURCHASE_SHIP: {
|
||||
label: intl.formatMessage({
|
||||
id: intlPrefix + '.targetType.marketPurchaseShip',
|
||||
}),
|
||||
color: 'green',
|
||||
},
|
||||
MARKET_TRANSFER_SHIP: {
|
||||
label: intl.formatMessage({
|
||||
id: intlPrefix + '.targetType.marketTransferShip',
|
||||
}),
|
||||
color: 'orange',
|
||||
},
|
||||
};
|
||||
|
||||
const columns: ProColumns<BusinessAPI.DealerAccountRecordVO, BizValueType>[] =
|
||||
[
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.dealer' }),
|
||||
dataIndex: 'dealerVO',
|
||||
key: 'dealerId',
|
||||
valueType: 'dealer',
|
||||
hidden: !!dealerVO, // 如果已传入 dealerId,则隐藏此列
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.order' }),
|
||||
dataIndex: 'orderVO',
|
||||
key: 'orderId',
|
||||
valueType: 'order',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.orderShip' }),
|
||||
dataIndex: ['orderShipVO', 'orderSn'],
|
||||
key: 'targetId',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.recordSn' }),
|
||||
dataIndex: 'recordSn',
|
||||
key: 'recordSn',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.targetType' }),
|
||||
dataIndex: 'targetType',
|
||||
key: 'targetType',
|
||||
valueType: 'select',
|
||||
valueEnum: Object.entries(targetTypeMap).reduce(
|
||||
(acc, [key, value]) => ({
|
||||
...acc,
|
||||
[key]: { text: value.label, status: value.color as any },
|
||||
}),
|
||||
{},
|
||||
),
|
||||
render: (_, record) => {
|
||||
const typeInfo = targetTypeMap[record.targetType];
|
||||
return typeInfo ? (
|
||||
<Tag color={typeInfo.color}>{typeInfo.label}</Tag>
|
||||
) : (
|
||||
<Tag>{record.targetType}</Tag>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.beforeAmount' }),
|
||||
dataIndex: 'beforeAmount',
|
||||
key: 'beforeAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
render: (_, record) => (
|
||||
<span className="text-gray-500">
|
||||
¥{formatCurrency(record.beforeAmount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.amount' }),
|
||||
dataIndex: 'amount',
|
||||
key: 'amount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
render: (_, record) => (
|
||||
<span
|
||||
className={record.amount >= 0 ? 'text-green-600' : 'text-red-600'}
|
||||
>
|
||||
{record.amount >= 0 ? <ArrowUpOutlined /> : <ArrowDownOutlined />}
|
||||
<span className="ml-1">
|
||||
¥{formatCurrency(Math.abs(record.amount))}
|
||||
</span>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.afterAmount' }),
|
||||
dataIndex: 'afterAmount',
|
||||
key: 'afterAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
render: (_, record) => (
|
||||
<span className="text-blue-600 font-medium">
|
||||
¥{formatCurrency(record.afterAmount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const detailColumns: ProDescriptionsItemProps<
|
||||
BusinessAPI.DealerAccountRecordVO,
|
||||
BizValueType
|
||||
>[] = columns as ProDescriptionsItemProps<
|
||||
BusinessAPI.DealerAccountRecordVO,
|
||||
BizValueType
|
||||
>[];
|
||||
|
||||
return (
|
||||
<BizContainer<
|
||||
typeof business.dealerAccountRecord,
|
||||
BusinessAPI.DealerAccountRecordVO,
|
||||
BusinessAPI.DealerAccountRecordPageQry
|
||||
>
|
||||
rowKey={'dealerAccountRecordId'}
|
||||
permission={'operation-dealer-account-record'}
|
||||
func={business.dealerAccountRecord}
|
||||
method={'dealerAccountRecord'}
|
||||
methodUpper={'DealerAccountRecord'}
|
||||
intlPrefix={intlPrefix}
|
||||
modeType={mode}
|
||||
onValueChange={onValueChange}
|
||||
container={{
|
||||
ghost,
|
||||
}}
|
||||
remark={{
|
||||
mode: 'editor',
|
||||
}}
|
||||
status={false}
|
||||
page={{
|
||||
fieldProps: {
|
||||
bordered: true,
|
||||
ghost,
|
||||
//@ts-ignore
|
||||
search,
|
||||
params: {
|
||||
...(dealerVO && { dealerId: dealerVO.dealerId }),
|
||||
...(orderVO && { orderId: orderVO.orderId }),
|
||||
},
|
||||
},
|
||||
columns,
|
||||
options: () => [],
|
||||
}}
|
||||
create={false}
|
||||
update={false}
|
||||
destroy={false}
|
||||
detail={{
|
||||
rowId: dealerAccountRecordId,
|
||||
formType: 'drawer',
|
||||
columns: detailColumns,
|
||||
trigger,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import {
|
||||
BizContainer,
|
||||
BizValueType,
|
||||
DealerAccountRecordList,
|
||||
DealerPaymentAccountList,
|
||||
DealerPurchaseSetting,
|
||||
DealerRebateCustomerList,
|
||||
@ -367,6 +368,18 @@ export default function DealerList(props: IDealerListProps) {
|
||||
onValueChange: () => void,
|
||||
) => {
|
||||
return [
|
||||
{
|
||||
label: `应收账款`,
|
||||
key: 'dealerAccountRecord',
|
||||
children: (
|
||||
<DealerAccountRecordList
|
||||
dealerVO={dealerVO}
|
||||
ghost={true}
|
||||
search={false}
|
||||
onValueChange={onValueChange}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: `结算账户`,
|
||||
key: 'dealerPaymentAccountList',
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
export { default as DealerAccountRecordList } from './DealerAccountRecordList';
|
||||
export { default as DealerFormItem } from './DealerFormItem';
|
||||
export { default as DealerList } from './DealerList';
|
||||
export { default as DealerModal } from './DealerModal';
|
||||
export type { IDealerModalProps } from './DealerModal';
|
||||
export { default as DealerPaymentAccountList } from './DealerPaymentAccountList';
|
||||
export { default as DealerPurchaseSetting } from './DealerPurchaseSetting';
|
||||
export { default as DealerRebateCustomerList } from './DealerRebateCustomerList';
|
||||
export { default as DealerSearch } from './DealerSearch';
|
||||
export { default as DealerSelect } from './DealerSelect';
|
||||
export { default as DealerStallList } from './DealerStallList';
|
||||
export { default as DealerWarehouseList } from './DealerWarehouseList';
|
||||
export { default as DeliveryTemplate } from './DeliveryTemplate';
|
||||
export { default as DealerPurchaseSetting } from './DealerPurchaseSetting';
|
||||
export { default as DealerStallList } from './DealerStallList';
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { BizContainer, BizValueType, ModeType } from '@/components';
|
||||
import { business } from '@/services';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { useIntl } from '@@/exports';
|
||||
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||
import { ProColumns } from '@ant-design/pro-components';
|
||||
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
|
||||
import React, { useState } from 'react';
|
||||
@ -86,6 +88,43 @@ export default function OrderShipList(props: IOrderShipListProps) {
|
||||
key: 'watermelonGrade',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: intlPrefix + '.column.receivableAmount',
|
||||
}),
|
||||
dataIndex: 'receivableAmount',
|
||||
key: 'receivableAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span className="text-blue-600 font-medium">
|
||||
¥{formatCurrency(record.receivableAmount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.adjustedAmount' }),
|
||||
dataIndex: 'adjustedAmount',
|
||||
key: 'adjustedAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span
|
||||
className={
|
||||
record.adjustedAmount >= 0 ? 'text-green-600' : 'text-red-600'
|
||||
}
|
||||
>
|
||||
{record.adjustedAmount >= 0 ? (
|
||||
<ArrowUpOutlined />
|
||||
) : (
|
||||
<ArrowDownOutlined />
|
||||
)}
|
||||
<span className="ml-1">
|
||||
¥{formatCurrency(Math.abs(record.adjustedAmount))}
|
||||
</span>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.type' }),
|
||||
dataIndex: 'type',
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { SelectModal } from '@/components';
|
||||
import { business } from '@/services';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { formatParam } from '@/utils/formatParam';
|
||||
import { pagination } from '@/utils/pagination';
|
||||
import { useIntl } from '@@/exports';
|
||||
@ -7,6 +8,7 @@ import {
|
||||
ActionType,
|
||||
LightFilter,
|
||||
ProColumns,
|
||||
ProFormDateRangePicker,
|
||||
ProFormSelect,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Alert, ModalProps, Space, Tag } from 'antd';
|
||||
@ -99,6 +101,8 @@ export default function OrderShipModal(props: IOrderShipModalProps) {
|
||||
dataIndex: 'shippingDate',
|
||||
key: 'shippingDate',
|
||||
valueType: 'date',
|
||||
sorter: true,
|
||||
defaultSortOrder: 'ascend',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
@ -114,6 +118,38 @@ export default function OrderShipModal(props: IOrderShipModalProps) {
|
||||
key: 'watermelonGrade',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: intlPrefix + '.column.receivableAmount',
|
||||
}),
|
||||
dataIndex: 'receivableAmount',
|
||||
key: 'receivableAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span className="text-blue-600 font-medium">
|
||||
¥{formatCurrency(record.receivableAmount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.adjustedAmount' }),
|
||||
dataIndex: 'adjustedAmount',
|
||||
key: 'adjustedAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span
|
||||
className={
|
||||
record.adjustedAmount >= 0 ? 'text-green-600' : 'text-red-600'
|
||||
}
|
||||
>
|
||||
<span className="ml-1">
|
||||
¥{formatCurrency(Math.abs(record.adjustedAmount))}
|
||||
</span>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.type' }),
|
||||
dataIndex: 'type',
|
||||
@ -329,6 +365,16 @@ export default function OrderShipModal(props: IOrderShipModalProps) {
|
||||
}}
|
||||
>
|
||||
{extraFilter}
|
||||
{/* 发货时间筛选 */}
|
||||
<ProFormDateRangePicker
|
||||
label={'发货时间'}
|
||||
name={'shippingDate'}
|
||||
placeholder={'请选择发货时间'}
|
||||
fieldProps={{
|
||||
allowClear: true,
|
||||
picker: 'date',
|
||||
}}
|
||||
/>
|
||||
<ProFormSelect
|
||||
label={'发货单状态'}
|
||||
name={'state'}
|
||||
|
||||
@ -1,9 +1,19 @@
|
||||
import { CompanyList, DealerList, OrderList } from '@/components';
|
||||
import { BizValueType } from '@/components';
|
||||
import BizProvider from '@/components/Biz/BizProvider';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { useIntl } from '@@/exports';
|
||||
import { Space, Table, TableProps } from 'antd';
|
||||
import { camelCase } from 'lodash';
|
||||
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
ProColumns,
|
||||
ProTable,
|
||||
ProTableProps,
|
||||
} from '@ant-design/pro-components';
|
||||
|
||||
type IOrderShipSelectListProps = TableProps<BusinessAPI.OrderShipVO>;
|
||||
type IOrderShipSelectListProps = ProTableProps<
|
||||
BusinessAPI.OrderShipVO,
|
||||
BusinessAPI.OrderShipPageQry,
|
||||
BizValueType
|
||||
>;
|
||||
|
||||
export default function OrderShipSelectList(props: IOrderShipSelectListProps) {
|
||||
const intl = useIntl();
|
||||
@ -11,69 +21,24 @@ export default function OrderShipSelectList(props: IOrderShipSelectListProps) {
|
||||
|
||||
const { ...tableProps } = props;
|
||||
// 订单列表列定义
|
||||
const orderColumns = [
|
||||
const orderColumns: ProColumns<BusinessAPI.OrderShipVO, BizValueType>[] = [
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.order' }),
|
||||
dataIndex: 'orderVO',
|
||||
key: 'orderId',
|
||||
render: (orderShipVO: BusinessAPI.OrderShipVO) => {
|
||||
const orderVO = orderShipVO.orderVO;
|
||||
return (
|
||||
orderVO && (
|
||||
<OrderList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
orderId={orderShipVO.orderId}
|
||||
trigger={() => (
|
||||
<Space>
|
||||
<a>
|
||||
{`${orderVO.orderVehicle?.dealerName} | 第 ${orderVO.orderVehicle?.vehicleNo || '暂无'} 车 | ${orderVO.orderSn || '暂无'}`}
|
||||
</a>
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
valueType: 'order',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.dealer' }),
|
||||
dataIndex: 'dealerVO',
|
||||
key: 'dealerId',
|
||||
render: (orderShipVO: BusinessAPI.OrderShipVO) => {
|
||||
return (
|
||||
orderShipVO && (
|
||||
<DealerList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
dealerId={orderShipVO.dealerId}
|
||||
trigger={() => (
|
||||
<Space>
|
||||
<a>{orderShipVO.dealerName}</a>
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
valueType: 'dealer',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.company' }),
|
||||
dataIndex: 'companyVO',
|
||||
key: 'companyId',
|
||||
render: (orderShipVO: BusinessAPI.OrderShipVO) => {
|
||||
return (
|
||||
orderShipVO && (
|
||||
<CompanyList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
companyId={orderShipVO.companyId}
|
||||
trigger={() => (
|
||||
<Space>
|
||||
<a>{orderShipVO.companyName}</a>
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
valueType: 'company',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.orderSn' }),
|
||||
@ -112,35 +77,111 @@ export default function OrderShipSelectList(props: IOrderShipSelectListProps) {
|
||||
key: 'watermelonGrade',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: intlPrefix + '.column.receivableAmount',
|
||||
}),
|
||||
dataIndex: 'receivableAmount',
|
||||
key: 'receivableAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span className="text-blue-600 font-medium">
|
||||
¥{formatCurrency(record.receivableAmount)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.adjustedAmount' }),
|
||||
dataIndex: 'adjustedAmount',
|
||||
key: 'adjustedAmount',
|
||||
search: false,
|
||||
valueType: 'money',
|
||||
render: (_, record) => (
|
||||
<span
|
||||
className={
|
||||
record.adjustedAmount >= 0 ? 'text-green-600' : 'text-red-600'
|
||||
}
|
||||
>
|
||||
{record.adjustedAmount >= 0 ? (
|
||||
<ArrowUpOutlined />
|
||||
) : (
|
||||
<ArrowDownOutlined />
|
||||
)}
|
||||
<span className="ml-1">
|
||||
¥{formatCurrency(Math.abs(record.adjustedAmount))}
|
||||
</span>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.type' }),
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
render: (orderShipVO: BusinessAPI.OrderShipVO) => {
|
||||
return intl.formatMessage({
|
||||
id: `${intlPrefix}.type.${camelCase(orderShipVO.type) || 'unknown'}`,
|
||||
});
|
||||
valueType: 'select',
|
||||
valueEnum: {
|
||||
PURCHASE_SHIP: intl.formatMessage({
|
||||
id: intlPrefix + '.column.type.enum.purchaseShip',
|
||||
}),
|
||||
TRANSFER_SHIP: intl.formatMessage({
|
||||
id: intlPrefix + '.column.type.enum.transferShip',
|
||||
}),
|
||||
CHANGE_SHIP: intl.formatMessage({
|
||||
id: intlPrefix + '.column.type.enum.changeShip',
|
||||
}),
|
||||
RETURN_SHIP: intl.formatMessage({
|
||||
id: intlPrefix + '.column.type.enum.returnShip',
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.state' }),
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
valueType: 'select',
|
||||
search: false,
|
||||
render: (orderShipVO: BusinessAPI.OrderShipVO) => {
|
||||
return intl.formatMessage({
|
||||
id: `${intlPrefix}.state.${camelCase(orderShipVO.state) || 'unknown'}`,
|
||||
});
|
||||
valueEnum: {
|
||||
DRAFT: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.draft',
|
||||
}),
|
||||
WAIT_SHIPMENT: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.waitShipment',
|
||||
}),
|
||||
WAIT_PAYMENT: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.waitPayment',
|
||||
}),
|
||||
PARTIAL_PAYMENT: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.partialPayment',
|
||||
}),
|
||||
FULL_PAYMENT: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.fullPayment',
|
||||
}),
|
||||
REJECT_FINISH: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.rejectFinish',
|
||||
}),
|
||||
FINISH: intl.formatMessage({
|
||||
id: intlPrefix + '.column.state.enum.finish',
|
||||
}),
|
||||
},
|
||||
},
|
||||
...(tableProps.columns || []),
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
{...tableProps}
|
||||
rowKey="ordershipId"
|
||||
columns={orderColumns}
|
||||
pagination={false}
|
||||
size="small"
|
||||
/>
|
||||
<BizProvider>
|
||||
<ProTable
|
||||
ghost={true}
|
||||
search={false}
|
||||
options={false}
|
||||
{...tableProps}
|
||||
rowKey="ordershipId"
|
||||
columns={orderColumns}
|
||||
pagination={false}
|
||||
size="small"
|
||||
scroll={{
|
||||
x: 'max-content',
|
||||
}}
|
||||
/>
|
||||
</BizProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
import { BizValueType, CompanyList } from '@/components';
|
||||
import BizProvider from '@/components/Biz/BizProvider';
|
||||
import { business } from '@/services';
|
||||
import { useIntl } from '@@/exports';
|
||||
import {
|
||||
ProColumns,
|
||||
ProTable,
|
||||
ProTableProps,
|
||||
} from '@ant-design/pro-components';
|
||||
|
||||
type IOrderSupplierSelectListProps = ProTableProps<
|
||||
BusinessAPI.OrderSupplierVO,
|
||||
BusinessAPI.OrderSupplierPageQry,
|
||||
BizValueType
|
||||
>;
|
||||
|
||||
export default function OrderSupplierSelectList(
|
||||
props: IOrderSupplierSelectListProps,
|
||||
) {
|
||||
const intl = useIntl();
|
||||
const intlPrefix = 'orderSupplier';
|
||||
const { ...tableProps } = props;
|
||||
// 订单列表列定义
|
||||
const orderColumns: ProColumns<BusinessAPI.OrderSupplierVO, BizValueType>[] =
|
||||
[
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.order' }),
|
||||
dataIndex: 'orderVO',
|
||||
key: 'orderId',
|
||||
valueType: 'order',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.name' }),
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.invoiceAmount' }),
|
||||
dataIndex: 'invoiceAmount',
|
||||
key: 'invoiceAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.depositAmount' }),
|
||||
dataIndex: 'depositAmount',
|
||||
key: 'depositAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
},
|
||||
// 剩余付款金额
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: intlPrefix + '.column.remainingAmount',
|
||||
}),
|
||||
dataIndex: 'remainingAmount',
|
||||
key: 'remainingAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
renderText: (_, record) => {
|
||||
return record.invoiceAmount - record.depositAmount || 0;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.orderCompany' }),
|
||||
dataIndex: 'orderCompany',
|
||||
valueType: 'select',
|
||||
request: async (params) => {
|
||||
const { data } = await business.company.listCompany({
|
||||
companyListQry: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
data?.map((item) => {
|
||||
return {
|
||||
label: item.fullName,
|
||||
value: item.companyId,
|
||||
};
|
||||
}) || []
|
||||
);
|
||||
},
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<CompanyList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
companyId={record.orderCompany.companyId}
|
||||
trigger={() => <a href={'#'}>{record.orderCompany.fullName}</a>}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: intlPrefix + '.column.isPaid' }),
|
||||
dataIndex: 'isPaid',
|
||||
key: 'isPaid',
|
||||
valueType: 'select',
|
||||
valueEnum: {
|
||||
true: {
|
||||
text: intl.formatMessage({
|
||||
id: intlPrefix + '.column.isPaid.paid',
|
||||
}),
|
||||
status: 'success',
|
||||
},
|
||||
false: {
|
||||
text: intl.formatMessage({
|
||||
id: intlPrefix + '.column.isPaid.unpaid',
|
||||
}),
|
||||
status: 'processing',
|
||||
},
|
||||
},
|
||||
},
|
||||
...(tableProps.columns || []),
|
||||
];
|
||||
|
||||
return (
|
||||
<BizProvider>
|
||||
<ProTable
|
||||
ghost={true}
|
||||
search={false}
|
||||
options={false}
|
||||
{...tableProps}
|
||||
rowKey="orderSupplierId"
|
||||
columns={orderColumns}
|
||||
pagination={false}
|
||||
size="small"
|
||||
scroll={{
|
||||
x: 'max-content',
|
||||
}}
|
||||
/>
|
||||
</BizProvider>
|
||||
);
|
||||
}
|
||||
@ -11,7 +11,8 @@ export { default as OrderSelect } from './OrderSelect';
|
||||
export { default as OrderShipList } from './OrderShipList';
|
||||
export { default as OrderShipModal } from './OrderShipModal';
|
||||
export type { IOrderShipModalProps } from './OrderShipModal';
|
||||
export { default as OrderShipSelectList } from './OrderShipSelectList';
|
||||
export { default as OrderStallList } from './OrderStallList';
|
||||
export { default as OrderSupplierList } from './OrderSupplierList';
|
||||
export { default as OrderSupplierModal } from './OrderSupplierModal';
|
||||
export { default as OrderShipSelectList } from './OrderShipSelectList';
|
||||
export { default as OrderSupplierSelectList } from './OrderSupplierSelectList';
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
import { OrderList, SupplierFarmerList } from '@/components';
|
||||
import { Space, Table, TableProps } from 'antd';
|
||||
|
||||
type IOrderSupplierInvoiceListProps = TableProps<BusinessAPI.OrderSupplierVO>;
|
||||
|
||||
export default function OrderSupplierInvoiceList(
|
||||
props: IOrderSupplierInvoiceListProps,
|
||||
) {
|
||||
const { ...tableProps } = props;
|
||||
// 订单列表列定义
|
||||
const orderColumns = [
|
||||
{
|
||||
title: '采购单',
|
||||
dataIndex: 'orderVO',
|
||||
key: 'orderId',
|
||||
render: (orderVO: BusinessAPI.OrderVO) => {
|
||||
return (
|
||||
orderVO && (
|
||||
<OrderList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
orderId={orderVO.orderId}
|
||||
trigger={() => (
|
||||
<Space>
|
||||
<a>
|
||||
{`${orderVO.orderVehicle?.dealerName} | 第 ${orderVO.orderVehicle?.vehicleNo || '暂无'} 车 | ${orderVO.orderSn || '暂无'}`}
|
||||
</a>
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '瓜农名称',
|
||||
key: 'name',
|
||||
render: (orderSupplierVO: BusinessAPI.OrderSupplierVO) => {
|
||||
return (
|
||||
orderSupplierVO && (
|
||||
<SupplierFarmerList
|
||||
ghost={true}
|
||||
mode={'detail'}
|
||||
supplierId={orderSupplierVO.supplierId}
|
||||
trigger={() => <a>{orderSupplierVO.name}</a>}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '货款金额(元)',
|
||||
dataIndex: 'invoiceAmount',
|
||||
key: 'invoiceAmount',
|
||||
valueType: 'money',
|
||||
},
|
||||
{
|
||||
title: '定金金额(元)',
|
||||
dataIndex: 'depositAmount',
|
||||
key: 'depositAmount',
|
||||
valueType: 'money',
|
||||
},
|
||||
{
|
||||
title: '应付金额(元)',
|
||||
key: 'remainingAmount',
|
||||
valueType: 'money',
|
||||
search: false,
|
||||
render: (record: BusinessAPI.OrderSupplierVO) => {
|
||||
return record.invoiceAmount - record.depositAmount || 0;
|
||||
},
|
||||
},
|
||||
...(tableProps.columns || []),
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
{...tableProps}
|
||||
rowKey="orderSupplierId"
|
||||
columns={orderColumns}
|
||||
pagination={false}
|
||||
size="small"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -2,7 +2,7 @@ import {
|
||||
BizEditor,
|
||||
ButtonAccess,
|
||||
InsertPosition,
|
||||
OrderSupplierInvoiceList,
|
||||
OrderSupplierSelectList,
|
||||
SupplierFarmerList,
|
||||
SupplierInvoiceList,
|
||||
SupplierSelect,
|
||||
@ -241,7 +241,7 @@ export default function PaymentTaskCreate(props: IPaymentTaskCreateProps) {
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
{selectedOrderSupplierList.length > 0 ? (
|
||||
<OrderSupplierInvoiceList
|
||||
<OrderSupplierSelectList
|
||||
rowKey="orderSupplierId"
|
||||
dataSource={selectedOrderSupplierList}
|
||||
columns={[
|
||||
@ -326,6 +326,7 @@ export default function PaymentTaskCreate(props: IPaymentTaskCreateProps) {
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
render: (record: BusinessAPI.OrderSupplierVO) => (
|
||||
<Button
|
||||
type="link"
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
BizValueType,
|
||||
InvoicerStatisticCard,
|
||||
ModeType,
|
||||
OrderSupplierInvoiceList,
|
||||
OrderSupplierSelectList,
|
||||
PaymentRecordList,
|
||||
PaymentTaskCreate,
|
||||
PaymentTaskPay,
|
||||
@ -251,7 +251,7 @@ export default function PaymentTaskList(props: IPaymentTaskListProps) {
|
||||
{ count: statistics.selfInvoiceCount },
|
||||
),
|
||||
children: (
|
||||
<OrderSupplierInvoiceList
|
||||
<OrderSupplierSelectList
|
||||
rowKey="orderSupplierId"
|
||||
dataSource={statistics.selfInvoiceList}
|
||||
columns={[
|
||||
@ -320,7 +320,7 @@ export default function PaymentTaskList(props: IPaymentTaskListProps) {
|
||||
{ count: statistics.proxyInvoiceCount },
|
||||
),
|
||||
children: (
|
||||
<OrderSupplierInvoiceList
|
||||
<OrderSupplierSelectList
|
||||
rowKey="orderSupplierId"
|
||||
dataSource={statistics.proxyInvoiceList}
|
||||
columns={[
|
||||
@ -389,7 +389,7 @@ export default function PaymentTaskList(props: IPaymentTaskListProps) {
|
||||
{ count: statistics.noInvoiceCount },
|
||||
),
|
||||
children: (
|
||||
<OrderSupplierInvoiceList
|
||||
<OrderSupplierSelectList
|
||||
rowKey="orderSupplierId"
|
||||
columns={[
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
ButtonAccess,
|
||||
CompanyPaymentAccountSelect,
|
||||
InsertPosition,
|
||||
OrderSupplierInvoiceList,
|
||||
OrderSupplierSelectList,
|
||||
ProFormUploadMaterial,
|
||||
SupplierFarmerList,
|
||||
SupplierInvoiceList,
|
||||
@ -220,7 +220,7 @@ export default function PaymentTaskPay(props: IPaymentTaskPayProps) {
|
||||
})}
|
||||
>
|
||||
<ProCard bordered>
|
||||
<OrderSupplierInvoiceList
|
||||
<OrderSupplierSelectList
|
||||
rowKey="orderSupplierId"
|
||||
dataSource={orderSupplierVOList || []}
|
||||
columns={[
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
export { default as InvoicerStatisticCard } from './InvoicerStatisticCard';
|
||||
export { default as OrderSupplierInvoiceList } from './OrderSupplierInvoiceList';
|
||||
export { default as PaymentTaskCreate } from './PaymentTaskCreate';
|
||||
export { default as PaymentTaskFormItem } from './PaymentTaskFormItem';
|
||||
export { default as PaymentTaskList } from './PaymentTaskList';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ReconciliationShipCardProps } from '@/components';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { DownOutlined, UpOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
@ -56,11 +57,7 @@ export default function ReconciliationShipCard({
|
||||
};
|
||||
|
||||
// 计算汇总数据
|
||||
const originalAmount =
|
||||
shipOrder.orderShipItemList?.reduce(
|
||||
(sum, item) => sum + (item.totalAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
const originalAmount = shipOrder.receivableAmount;
|
||||
|
||||
const adjustmentTotal = adjustments.reduce((sum, adj) => sum + adj.amount, 0);
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { ReconciliationSummaryProps } from '@/components';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import {
|
||||
Checkbox,
|
||||
Col,
|
||||
Input,
|
||||
InputNumber,
|
||||
Row,
|
||||
Space,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
ProForm,
|
||||
ProFormDependency,
|
||||
ProFormMoney,
|
||||
ProFormSwitch,
|
||||
ProFormTextArea,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Row, Typography } from 'antd';
|
||||
import { useIntl } from 'umi';
|
||||
|
||||
const { Text } = Typography;
|
||||
@ -25,25 +25,18 @@ const ADJUSTMENT_TYPE_LABELS: Record<string, string> = {
|
||||
export default function ReconciliationSummary({
|
||||
shipOrders,
|
||||
adjustmentsMap,
|
||||
roundOffEnabled = false,
|
||||
onRoundOffChange,
|
||||
roundOffAmount,
|
||||
onRoundOffAmountChange,
|
||||
roundOffRemark = '',
|
||||
onRoundOffRemarkChange,
|
||||
roundOff,
|
||||
onFinish,
|
||||
}: ReconciliationSummaryProps) {
|
||||
const intl = useIntl();
|
||||
const intlPrefix = 'reconciliation';
|
||||
|
||||
// 计算原应收总额
|
||||
const originalTotalAmount = shipOrders.reduce((sum, order) => {
|
||||
const orderTotal =
|
||||
order.orderShipItemList?.reduce(
|
||||
(total, item) => total + (item.totalAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
return sum + orderTotal;
|
||||
}, 0);
|
||||
const originalTotalAmount =
|
||||
shipOrders.reduce(
|
||||
(total, item) => total + (item.receivableAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
|
||||
// 按类型汇总调整项
|
||||
const adjustmentTotalsByType = Object.values(adjustmentsMap)
|
||||
@ -67,7 +60,7 @@ export default function ReconciliationSummary({
|
||||
|
||||
// 计算实际应收总额(包含抹零金额)
|
||||
const actualTotalAmount =
|
||||
originalTotalAmount + adjustmentTotal + (roundOffAmount || 0);
|
||||
originalTotalAmount - adjustmentTotal + (roundOff?.roundOffAmount || 0);
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -116,74 +109,76 @@ export default function ReconciliationSummary({
|
||||
backgroundColor: '#f8f9fa',
|
||||
}}
|
||||
>
|
||||
<Row style={{ marginBottom: 16 }}>
|
||||
<Checkbox
|
||||
checked={roundOffEnabled}
|
||||
onChange={(e) => onRoundOffChange?.(e.target.checked)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
<ProForm
|
||||
submitter={false}
|
||||
request={async () => {
|
||||
return Promise.resolve({
|
||||
roundOffEnabled: roundOff?.roundOffEnabled || false,
|
||||
roundOffAmount: roundOff?.roundOffAmount || 0,
|
||||
roundOffRemark: roundOff?.roundOffRemark || '',
|
||||
});
|
||||
}}
|
||||
onValuesChange={(_, formData) => {
|
||||
onFinish?.(formData);
|
||||
}}
|
||||
layout="horizontal"
|
||||
>
|
||||
<ProFormSwitch
|
||||
label={intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.roundOffEnabled`,
|
||||
})}
|
||||
</Checkbox>
|
||||
</Row>
|
||||
{roundOffEnabled && (
|
||||
<>
|
||||
<Row style={{ marginBottom: 12 }}>
|
||||
<Col>
|
||||
<Space>
|
||||
<Text type="secondary">
|
||||
{intl.formatMessage({
|
||||
name={'roundOffEnabled'}
|
||||
/>
|
||||
<ProFormDependency name={['roundOffEnabled']}>
|
||||
{({ roundOffEnabled }) =>
|
||||
roundOffEnabled && (
|
||||
<>
|
||||
<ProFormMoney
|
||||
label={intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.roundOffAmount`,
|
||||
})}
|
||||
</Text>
|
||||
<InputNumber
|
||||
style={{ width: 200 }}
|
||||
name="roundOffAmount"
|
||||
placeholder={intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.roundOffAmountPlaceholder`,
|
||||
})}
|
||||
value={roundOffAmount}
|
||||
onChange={onRoundOffAmountChange}
|
||||
precision={2}
|
||||
min={-999999999}
|
||||
max={999999999}
|
||||
fieldProps={{
|
||||
precision: 2,
|
||||
min: -999999999,
|
||||
max: 999999999,
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<Space>
|
||||
<Text type="secondary">
|
||||
{intl.formatMessage({
|
||||
<ProFormTextArea
|
||||
label={intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.roundOffRemark`,
|
||||
})}
|
||||
</Text>
|
||||
<Input
|
||||
style={{ width: 300 }}
|
||||
name="roundOffRemark"
|
||||
placeholder={intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.roundOffRemarkPlaceholder`,
|
||||
})}
|
||||
value={roundOffRemark}
|
||||
onChange={(e) => onRoundOffRemarkChange?.(e.target.value)}
|
||||
fieldProps={{
|
||||
autoSize: { minRows: 3, maxRows: 6 },
|
||||
showCount: true,
|
||||
maxLength: 200,
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
</ProFormDependency>
|
||||
</ProForm>
|
||||
</div>
|
||||
|
||||
{/* 调整总额 */}
|
||||
<Row justify="space-between" align="middle" style={{ marginBottom: 10 }}>
|
||||
<Text type="secondary">
|
||||
{intl.formatMessage({
|
||||
id: `${intlPrefix}.summary.adjustmentTotal`,
|
||||
})}
|
||||
</Text>
|
||||
<Text type={adjustmentTotal < 0 ? 'danger' : undefined}>
|
||||
{formatCurrency(adjustmentTotal)}
|
||||
</Text>
|
||||
</Row>
|
||||
{/*/!* 调整总额 *!/*/}
|
||||
{/*<Row justify="space-between" align="middle" style={{ marginBottom: 10 }}>*/}
|
||||
{/* <Text type="secondary">*/}
|
||||
{/* {intl.formatMessage({*/}
|
||||
{/* id: `${intlPrefix}.summary.adjustmentTotal`,*/}
|
||||
{/* })}*/}
|
||||
{/* </Text>*/}
|
||||
{/* <Text type={adjustmentTotal < 0 ? 'danger' : undefined}>*/}
|
||||
{/* {formatCurrency(adjustmentTotal)}*/}
|
||||
{/* </Text>*/}
|
||||
{/*</Row>*/}
|
||||
|
||||
{/* 实际应收总额 */}
|
||||
<Row
|
||||
|
||||
@ -24,22 +24,24 @@ export interface ReconciliationShipCardProps {
|
||||
onExpandChange?: (expanded: boolean) => void;
|
||||
}
|
||||
|
||||
/** 抹零数据 */
|
||||
export interface RoundOff {
|
||||
/** 是否抹零 */
|
||||
roundOffEnabled?: boolean;
|
||||
/** 抹零金额 */
|
||||
roundOffAmount?: number;
|
||||
/** 抹零备注 */
|
||||
roundOffRemark?: string;
|
||||
}
|
||||
|
||||
/** 对账汇总Props */
|
||||
export interface ReconciliationSummaryProps {
|
||||
/** 发货单列表 */
|
||||
shipOrders: BusinessAPI.OrderShipVO[];
|
||||
/** 调整项数据 Map<发货单ID, 调整项数组> */
|
||||
adjustmentsMap: Record<string, ReconciliationAdjustment[]>;
|
||||
/** 是否抹零 */
|
||||
roundOffEnabled?: boolean;
|
||||
/** 抹零值变化回调 */
|
||||
onRoundOffChange?: (enabled: boolean) => void;
|
||||
/** 抹零金额 */
|
||||
roundOffAmount?: number;
|
||||
/** 抹零金额变化回调 */
|
||||
onRoundOffAmountChange?: (amount: number | null) => void;
|
||||
/** 抹零备注 */
|
||||
roundOffRemark?: string;
|
||||
/** 抹零备注变化回调 */
|
||||
onRoundOffRemarkChange?: (remark: string) => void;
|
||||
/** 抹零数据 */
|
||||
roundOff?: RoundOff;
|
||||
/** 抹零注变化回调 */
|
||||
onFinish?: (roundOff: RoundOff) => void;
|
||||
}
|
||||
|
||||
@ -1209,6 +1209,32 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
dealerAccountRecord: {
|
||||
column: {
|
||||
dealer: '经销商',
|
||||
order: '采购单',
|
||||
orderShip: '发货单',
|
||||
recordSn: '流水编号',
|
||||
targetType: '变动类型',
|
||||
beforeAmount: '变动前金额',
|
||||
amount: '变动金额',
|
||||
afterAmount: '变动后金额',
|
||||
remark: '备注',
|
||||
createdAt: '创建时间',
|
||||
option: '操作',
|
||||
},
|
||||
targetType: {
|
||||
originPurchaseShip: '产地采购发货单',
|
||||
marketPurchaseShip: '市场采购发货单',
|
||||
marketTransferShip: '市场调货发货单',
|
||||
},
|
||||
modal: {
|
||||
view: {
|
||||
title: '查看账款明细',
|
||||
button: '详情',
|
||||
},
|
||||
},
|
||||
},
|
||||
boxSpec: {
|
||||
column: {
|
||||
name: '规格名称',
|
||||
@ -2117,6 +2143,8 @@ export default {
|
||||
shippingDate: '发货日期',
|
||||
estimatedArrivalDate: '预计到仓时间',
|
||||
watermelonGrade: '西瓜品级',
|
||||
receivableAmount: '应收金额(元)',
|
||||
adjustedAmount: '调整金额(元)',
|
||||
company: '入账公司',
|
||||
type: '发货单类型',
|
||||
'type.enum.purchaseShip': '采购发货单',
|
||||
|
||||
5
packages/app-operation/src/pages/ReceivablesDetail.tsx
Normal file
5
packages/app-operation/src/pages/ReceivablesDetail.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { DealerAccountRecordList } from '@/components';
|
||||
|
||||
export default function Page() {
|
||||
return <DealerAccountRecordList />;
|
||||
}
|
||||
@ -2,15 +2,15 @@ import {
|
||||
OrderShipSelectList,
|
||||
PageContainer,
|
||||
ReconciliationAdjustment,
|
||||
ReconciliationShipCard,
|
||||
ReconciliationSummary,
|
||||
ReconciliationSummaryProps,
|
||||
} from '@/components';
|
||||
import DealerModal from '@/components/Dealer/DealerModal';
|
||||
import OrderShipModal from '@/components/Order/OrderShipModal';
|
||||
import { formatCurrency } from '@/utils/format';
|
||||
import { ProCard, ProFormTextArea } from '@ant-design/pro-components';
|
||||
import { Button, Col, Row, Space, Steps, Table, Tag } from 'antd';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function Page() {
|
||||
const [current, setCurrent] = useState(0);
|
||||
@ -35,45 +35,47 @@ export default function Page() {
|
||||
);
|
||||
const [roundOffRemark, setRoundOffRemark] = useState('');
|
||||
|
||||
// 添加调整项
|
||||
const handleAddAdjustment = useCallback((shipOrderId: string) => {
|
||||
const newAdjustment: ReconciliationAdjustment = {
|
||||
id: `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
|
||||
type: 'LOSS',
|
||||
quantity: 0,
|
||||
unitPrice: 0,
|
||||
amount: 0,
|
||||
remark: '',
|
||||
};
|
||||
setAdjustmentsMap((prev) => ({
|
||||
...prev,
|
||||
[shipOrderId]: [...(prev[shipOrderId] || []), newAdjustment],
|
||||
}));
|
||||
}, []);
|
||||
|
||||
// 删除调整项
|
||||
const handleRemoveAdjustment = useCallback(
|
||||
(shipOrderId: string, adjustmentId: string) => {
|
||||
setAdjustmentsMap((prev) => ({
|
||||
...prev,
|
||||
[shipOrderId]: (prev[shipOrderId] || []).filter(
|
||||
(adj) => adj.id !== adjustmentId,
|
||||
),
|
||||
}));
|
||||
},
|
||||
[],
|
||||
);
|
||||
// // 添加调整项
|
||||
// const handleAddAdjustment = useCallback((shipOrderId: string) => {
|
||||
// const newAdjustment: ReconciliationAdjustment = {
|
||||
// id: `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
|
||||
// type: 'LOSS',
|
||||
// quantity: 0,
|
||||
// unitPrice: 0,
|
||||
// amount: 0,
|
||||
// remark: '',
|
||||
// };
|
||||
// setAdjustmentsMap((prev) => ({
|
||||
// ...prev,
|
||||
// [shipOrderId]: [...(prev[shipOrderId] || []), newAdjustment],
|
||||
// }));
|
||||
// }, []);
|
||||
//
|
||||
// // 删除调整项
|
||||
// const handleRemoveAdjustment = useCallback(
|
||||
// (shipOrderId: string, adjustmentId: string) => {
|
||||
// setAdjustmentsMap((prev) => ({
|
||||
// ...prev,
|
||||
// [shipOrderId]: (prev[shipOrderId] || []).filter(
|
||||
// (adj) => adj.id !== adjustmentId,
|
||||
// ),
|
||||
// }));
|
||||
// },
|
||||
// [],
|
||||
// );
|
||||
|
||||
let receivableAmount =
|
||||
selectedShipOrderList?.reduce(
|
||||
(sum, item) => sum + (item.receivableAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
let adjustedAmount =
|
||||
selectedShipOrderList?.reduce(
|
||||
(sum, item) => sum + (item.adjustedAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
// 计算总金额
|
||||
const totalAmount = selectedShipOrderList.reduce((sum, order) => {
|
||||
// 使用发货单明细的总金额
|
||||
const orderTotal =
|
||||
order.orderShipItemList?.reduce(
|
||||
(total, item) => total + (item.totalAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
return sum + orderTotal;
|
||||
}, 0);
|
||||
|
||||
const orderCount = selectedShipOrderList.length;
|
||||
|
||||
return (
|
||||
@ -144,16 +146,6 @@ export default function Page() {
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div>
|
||||
<div style={{ color: '#999', marginBottom: 4 }}>
|
||||
经销商全称
|
||||
</div>
|
||||
<div style={{ fontWeight: 'bold' }}>
|
||||
{selectedDealer.fullName || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div>
|
||||
<div style={{ color: '#999', marginBottom: 4 }}>
|
||||
@ -166,6 +158,16 @@ export default function Page() {
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div>
|
||||
<div style={{ color: '#999', marginBottom: 4 }}>
|
||||
应收金额
|
||||
</div>
|
||||
<div style={{ fontWeight: 'bold' }}>
|
||||
¥{selectedDealer.receivable || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
) : (
|
||||
<div
|
||||
@ -222,6 +224,8 @@ export default function Page() {
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 80,
|
||||
render: (_: any, record: BusinessAPI.OrderShipVO) => (
|
||||
<Button
|
||||
type="link"
|
||||
@ -249,24 +253,36 @@ export default function Page() {
|
||||
pagination={false}
|
||||
size="small"
|
||||
summary={(pageData) => {
|
||||
let totalAmount = 0;
|
||||
pageData.forEach((record) => {
|
||||
const total =
|
||||
record.orderShipItemList?.reduce(
|
||||
(sum, item) => sum + (item.totalAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
totalAmount += total;
|
||||
});
|
||||
let receivableAmount =
|
||||
pageData?.reduce(
|
||||
(sum, item) => sum + (item.receivableAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
let adjustedAmount =
|
||||
pageData?.reduce(
|
||||
(sum, item) => sum + (item.adjustedAmount || 0),
|
||||
0,
|
||||
) || 0;
|
||||
return (
|
||||
<Table.Summary fixed>
|
||||
<Table.Summary.Row>
|
||||
<Table.Summary.Cell index={0} colSpan={3}>
|
||||
<Table.Summary.Cell index={0} colSpan={9}>
|
||||
<strong>合计</strong>
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={1}>
|
||||
<strong style={{ color: '#ff4d4f' }}>
|
||||
{formatCurrency(totalAmount)}
|
||||
<strong className="text-blue-600 font-medium">
|
||||
¥{formatCurrency(receivableAmount)}
|
||||
</strong>
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={1}>
|
||||
<strong
|
||||
className={
|
||||
adjustedAmount >= 0
|
||||
? 'text-green-600'
|
||||
: 'text-red-600'
|
||||
}
|
||||
>
|
||||
¥{formatCurrency(adjustedAmount)}
|
||||
</strong>
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={2} />
|
||||
@ -316,7 +332,7 @@ export default function Page() {
|
||||
对账总额
|
||||
</div>
|
||||
<div style={{ fontWeight: 'bold', color: '#ff4d4f' }}>
|
||||
{formatCurrency(totalAmount)}
|
||||
¥{formatCurrency(receivableAmount - adjustedAmount)}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
@ -356,31 +372,35 @@ export default function Page() {
|
||||
{current === 2 && (
|
||||
<>
|
||||
{/* 对账车次清单 */}
|
||||
<ProCard title={'对账车次清单'} style={{ marginTop: 16 }} bordered>
|
||||
{selectedShipOrderList.map((shipOrder) => (
|
||||
<ReconciliationShipCard
|
||||
key={shipOrder.orderShipId}
|
||||
shipOrder={shipOrder}
|
||||
adjustments={adjustmentsMap[shipOrder.orderShipId] || []}
|
||||
onAddAdjustment={handleAddAdjustment}
|
||||
onRemoveAdjustment={handleRemoveAdjustment}
|
||||
/>
|
||||
))}
|
||||
</ProCard>
|
||||
{/*<ProCard title={'对账车次清单'} style={{ marginTop: 16 }} bordered>*/}
|
||||
{/* {selectedShipOrderList.map((shipOrder) => (*/}
|
||||
{/* <ReconciliationShipCard*/}
|
||||
{/* key={shipOrder.orderShipId}*/}
|
||||
{/* shipOrder={shipOrder}*/}
|
||||
{/* adjustments={adjustmentsMap[shipOrder.orderShipId] || []}*/}
|
||||
{/* onAddAdjustment={handleAddAdjustment}*/}
|
||||
{/* onRemoveAdjustment={handleRemoveAdjustment}*/}
|
||||
{/* />*/}
|
||||
{/* ))}*/}
|
||||
{/*</ProCard>*/}
|
||||
|
||||
{/* 对账汇总 */}
|
||||
<ProCard title={'对账汇总'} style={{ marginTop: 16 }} bordered>
|
||||
<ReconciliationSummary
|
||||
shipOrders={selectedShipOrderList}
|
||||
adjustmentsMap={adjustmentsMap}
|
||||
roundOffEnabled={roundOffEnabled}
|
||||
onRoundOffChange={setRoundOffEnabled}
|
||||
roundOffAmount={roundOffAmount}
|
||||
onRoundOffAmountChange={(value) =>
|
||||
setRoundOffAmount(value ?? undefined)
|
||||
}
|
||||
roundOffRemark={roundOffRemark}
|
||||
onRoundOffRemarkChange={setRoundOffRemark}
|
||||
roundOff={{
|
||||
roundOffEnabled: roundOffEnabled,
|
||||
roundOffAmount: roundOffAmount,
|
||||
roundOffRemark: roundOffRemark,
|
||||
}}
|
||||
onFinish={(
|
||||
roundOff: ReconciliationSummaryProps['roundOff'],
|
||||
) => {
|
||||
setRoundOffEnabled(roundOff?.roundOffEnabled || false);
|
||||
setRoundOffAmount(roundOff?.roundOffAmount);
|
||||
setRoundOffRemark(roundOff?.roundOffRemark || '');
|
||||
}}
|
||||
/>
|
||||
</ProCard>
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ declare namespace AuthAPI {
|
||||
/** 用户ID */
|
||||
userId: string;
|
||||
/** 角色ID */
|
||||
roleIdList: number[];
|
||||
roleIdList: string[];
|
||||
/** 角色信息 */
|
||||
userRoleList?: UserRoleVO[];
|
||||
};
|
||||
@ -195,7 +195,7 @@ declare namespace AuthAPI {
|
||||
|
||||
type RoleMenuTreeQry = {
|
||||
/** 角色权限 */
|
||||
roleId?: number[];
|
||||
roleId?: string[];
|
||||
/** 平台ID */
|
||||
platformId: string;
|
||||
};
|
||||
@ -329,7 +329,7 @@ declare namespace AuthAPI {
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 客户标签 */
|
||||
labelId?: number[];
|
||||
labelId?: string[];
|
||||
/** 用户ID */
|
||||
userId: string;
|
||||
};
|
||||
|
||||
@ -208,7 +208,7 @@ declare namespace BusinessAPI {
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
specIds?: string[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
@ -279,7 +279,7 @@ declare namespace BusinessAPI {
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
specIds?: string[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
@ -296,7 +296,7 @@ declare namespace BusinessAPI {
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
specIds?: string[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
@ -1021,7 +1021,7 @@ declare namespace BusinessAPI {
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 成本项ID */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
};
|
||||
|
||||
type CostDestroyCmd = {
|
||||
@ -1249,7 +1249,7 @@ declare namespace BusinessAPI {
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 成本项ID */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
};
|
||||
|
||||
type CostVO = {
|
||||
@ -1280,7 +1280,7 @@ declare namespace BusinessAPI {
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 项目id集合 */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
/** 项目列表 */
|
||||
@ -1364,6 +1364,19 @@ declare namespace BusinessAPI {
|
||||
status?: boolean;
|
||||
/** 经销商账款明细ID */
|
||||
dealerAccountRecordId?: string;
|
||||
/** 流水编号 */
|
||||
recordSn?: string;
|
||||
/** 经销商ID */
|
||||
dealerId?: string;
|
||||
/** 订单ID */
|
||||
orderId?: string;
|
||||
/** 变动对象ID */
|
||||
targetId?: string;
|
||||
/** 变动类型:1-产地采购发货单;2-市场采购发货单;3-市场调货发货单; */
|
||||
targetType?:
|
||||
| 'ORIGIN_PURCHASE_SHIP'
|
||||
| 'MARKET_PURCHASE_SHIP'
|
||||
| 'MARKET_TRANSFER_SHIP';
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
@ -1426,6 +1439,12 @@ declare namespace BusinessAPI {
|
||||
remark?: string;
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
/** 经销商信息 */
|
||||
dealerVO?: DealerVO;
|
||||
/** 订单信息 */
|
||||
orderVO?: OrderVO;
|
||||
/** 发货单信息 */
|
||||
orderShipVO?: OrderShipVO;
|
||||
};
|
||||
|
||||
type DealerCreateCmd = {
|
||||
@ -2080,7 +2099,7 @@ declare namespace BusinessAPI {
|
||||
/** 登录密码 */
|
||||
password: string;
|
||||
/** 角色ID */
|
||||
roleId: number[];
|
||||
roleId: string[];
|
||||
};
|
||||
|
||||
type EmployeeDestroyCmd = {
|
||||
@ -2173,7 +2192,7 @@ declare namespace BusinessAPI {
|
||||
/** 用户ID */
|
||||
userId: string;
|
||||
/** 角色ID */
|
||||
roleIdList: number[];
|
||||
roleIdList: string[];
|
||||
/** 角色信息 */
|
||||
userRoleList?: UserRoleVO[];
|
||||
};
|
||||
@ -2610,7 +2629,7 @@ declare namespace BusinessAPI {
|
||||
/** 平台id */
|
||||
platformId: string;
|
||||
/** 角色Id */
|
||||
roleId?: number[];
|
||||
roleId?: string[];
|
||||
/** 是否隐藏 */
|
||||
hideInMenu?: boolean;
|
||||
/** 权限Id */
|
||||
@ -2683,7 +2702,7 @@ declare namespace BusinessAPI {
|
||||
/** 平台id */
|
||||
platformId: string;
|
||||
/** 角色Id */
|
||||
roleId?: number[];
|
||||
roleId?: string[];
|
||||
/** 是否隐藏 */
|
||||
hideInMenu?: boolean;
|
||||
/** 权限Id */
|
||||
@ -3110,7 +3129,7 @@ declare namespace BusinessAPI {
|
||||
| 'LOGISTICS_TYPE'
|
||||
| 'EXPENSE_TYPE';
|
||||
/** 关联项目id */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
/** 是否选中 */
|
||||
selected: boolean;
|
||||
/** 是否已付款 */
|
||||
@ -3147,7 +3166,7 @@ declare namespace BusinessAPI {
|
||||
| 'LOGISTICS_TYPE'
|
||||
| 'EXPENSE_TYPE';
|
||||
/** 关联项目id */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
/** 是否付款 */
|
||||
isPaid?: boolean;
|
||||
};
|
||||
@ -3280,7 +3299,7 @@ declare namespace BusinessAPI {
|
||||
| 'LOGISTICS_TYPE'
|
||||
| 'EXPENSE_TYPE';
|
||||
/** 关联项目id */
|
||||
costItemIds?: number[];
|
||||
costItemIds?: string[];
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 采购订单状态: 0_草稿;1_审核中;2_已完成;3_已关闭; */
|
||||
@ -3878,9 +3897,9 @@ declare namespace BusinessAPI {
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 应收金额(元) */
|
||||
receivableAmount?: number;
|
||||
receivableAmount: number;
|
||||
/** 调整总额(元) */
|
||||
adjustedAmount?: number;
|
||||
adjustedAmount: number;
|
||||
/** 创建人ID */
|
||||
createdBy: string;
|
||||
/** 创建人姓名 */
|
||||
@ -4018,7 +4037,7 @@ declare namespace BusinessAPI {
|
||||
/** 产品名称 */
|
||||
productName?: string;
|
||||
/** 关联费用id */
|
||||
costIds?: number[];
|
||||
costIds?: string[];
|
||||
/** 成本模板 */
|
||||
costTemplate?: string;
|
||||
/** 是否已付定金 */
|
||||
@ -5349,7 +5368,7 @@ declare namespace BusinessAPI {
|
||||
/** 产品名称 */
|
||||
name: string;
|
||||
/** 关联成本费用id */
|
||||
costIds?: number[];
|
||||
costIds?: string[];
|
||||
/** 成本模板 */
|
||||
costTemplate?: string;
|
||||
/** 备注 */
|
||||
@ -5416,7 +5435,7 @@ declare namespace BusinessAPI {
|
||||
/** 产品名称 */
|
||||
name: string;
|
||||
/** 关联成本费用id */
|
||||
costIds?: number[];
|
||||
costIds?: string[];
|
||||
/** 成本模板 */
|
||||
costTemplate?: string;
|
||||
/** 备注 */
|
||||
@ -5441,7 +5460,7 @@ declare namespace BusinessAPI {
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 成本ID集合 */
|
||||
costIds?: number[];
|
||||
costIds?: string[];
|
||||
/** 成本费用 */
|
||||
costVOList?: CostVO[];
|
||||
/** 成本模板 */
|
||||
@ -5468,7 +5487,7 @@ declare namespace BusinessAPI {
|
||||
/** 角色详情 */
|
||||
description?: string;
|
||||
/** 角色id */
|
||||
menuId: number[];
|
||||
menuId: string[];
|
||||
};
|
||||
|
||||
type RoleDestroyCmd = {
|
||||
@ -5490,7 +5509,7 @@ declare namespace BusinessAPI {
|
||||
/** 角色编号 */
|
||||
roleId?: string;
|
||||
/** 应用角色Id */
|
||||
roleIdList?: number[];
|
||||
roleIdList?: string[];
|
||||
/** 平台Id */
|
||||
platformId?: string;
|
||||
/** 平台Id */
|
||||
@ -5537,7 +5556,7 @@ declare namespace BusinessAPI {
|
||||
/** 角色详情 */
|
||||
description?: string;
|
||||
/** 角色id */
|
||||
menuId: number[];
|
||||
menuId: string[];
|
||||
/** 角色ID */
|
||||
roleId: string;
|
||||
};
|
||||
@ -5558,9 +5577,9 @@ declare namespace BusinessAPI {
|
||||
/** 平台 */
|
||||
platformVO?: PlatformVO;
|
||||
/** 权限列表 */
|
||||
permissionId: number[];
|
||||
permissionId: string[];
|
||||
/** 菜单列表 */
|
||||
menuId: number[];
|
||||
menuId: string[];
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
};
|
||||
@ -6445,7 +6464,7 @@ declare namespace BusinessAPI {
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 客户标签 */
|
||||
labelId?: number[];
|
||||
labelId?: string[];
|
||||
};
|
||||
|
||||
type UserDestroyCmd = {
|
||||
@ -6467,7 +6486,7 @@ declare namespace BusinessAPI {
|
||||
/** 状态:1_启用;0_禁用; */
|
||||
status?: boolean;
|
||||
/** 用户ID */
|
||||
userIdList?: number[];
|
||||
userIdList?: string[];
|
||||
/** 用户名 */
|
||||
name?: string;
|
||||
};
|
||||
@ -6510,9 +6529,9 @@ declare namespace BusinessAPI {
|
||||
/** 是否是管理员 */
|
||||
isAdmin?: boolean;
|
||||
/** 会员id列表 */
|
||||
userIdList?: number[];
|
||||
userIdList?: string[];
|
||||
/** 排除的用户id列表 */
|
||||
excludeUserIdList?: number[];
|
||||
excludeUserIdList?: string[];
|
||||
/** 小区id */
|
||||
communityId?: number;
|
||||
offset?: number;
|
||||
@ -6522,7 +6541,7 @@ declare namespace BusinessAPI {
|
||||
/** 用户ID */
|
||||
userId: string;
|
||||
/** 角色ID */
|
||||
roleIdList?: number[];
|
||||
roleIdList?: string[];
|
||||
/** 是否覆盖 */
|
||||
cover: boolean;
|
||||
};
|
||||
@ -6567,7 +6586,7 @@ declare namespace BusinessAPI {
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 客户标签 */
|
||||
labelId?: number[];
|
||||
labelId?: string[];
|
||||
/** 用户ID */
|
||||
userId: string;
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user