From 98aec80d71f93e8dadcb30bf21bcbf836e1300d3 Mon Sep 17 00:00:00 2001 From: zlwu Date: Sun, 28 Jun 2026 21:00:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(pl):=20=E8=BF=90=E8=B4=B9=E7=BB=93?= =?UTF-8?q?=E7=AE=97=E5=AE=A1=E6=89=B9=E5=88=86=E6=B5=81=E4=B8=8E=E8=BD=A6?= =?UTF-8?q?=E8=BE=86=E6=8C=82=E8=BD=A6=E5=8F=B7=E7=AD=89=20PL=20=E8=83=BD?= =?UTF-8?q?=E5=8A=9B=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 拆分运费审批/出款页面,补充结算发票附件与菜单 SQL,并同步前后端模型与车辆相关展示。 Co-authored-by: Cursor --- backend/app/models/pl_models.py | 2 + backend/app/schemas/pl/base_data.py | 2 + backend/app/schemas/pl/freight.py | 4 + ..._freight_settlement_invoice_attachment.sql | 3 + ...60628_pl_freight_settlement_split_menu.sql | 99 ++++++ docs/sql/20260628_pl_vehicle_menu_order.sql | 26 ++ docs/sql/20260628_pl_vehicle_trailer_no.sql | 32 ++ docs/sql/pl_tables.sql | 1 + docs/sql/shanxia2.0.sql | 6 +- ...6-28-pl-freight-settlement-split-design.md | 32 ++ web-admin/src/api/pl/index.ts | 7 +- .../pl-freight-disburse-dialog/index.vue | 330 ++++++++++++++---- .../index.vue | 108 ++++-- .../index.vue | 170 +++++++-- .../business/pl-plan-arrange-dialog/index.vue | 8 +- .../business/pl-plan-form-dialog/index.vue | 8 +- .../business/pl-plan-view-dialog/index.vue | 4 +- .../business/pl-plan-view-tabs/index.vue | 13 +- .../pl-vehicle-summary-strip/index.vue | 3 + .../business/pl-vehicle-view-dialog/index.vue | 1 + .../business/pl-vehicle-view-panel/index.vue | 1 + .../composables/usePlPlanArrangeActions.ts | 27 +- web-admin/src/router/modules/pl.ts | 28 +- web-admin/src/utils/db-site-summary.ts | 9 +- web-admin/src/utils/download-attachment.ts | 18 + web-admin/src/utils/pl-display.ts | 15 +- .../src/views/pl/freight-approval/index.vue | 41 +++ .../src/views/pl/freight-disburse/index.vue | 47 +++ .../freight/components/ApprovalDonePanel.vue | 176 ++++++++++ .../components/ApprovalPendingPanel.vue | 184 ++++++++++ .../components/SettlementBillPanel.vue | 74 ++-- .../freight/components/UnsettledPlanPanel.vue | 26 +- .../src/views/pl/freight/freight-status.ts | 2 +- web-admin/src/views/pl/freight/index.vue | 20 +- web-admin/src/views/pl/plan-archive/index.vue | 6 - web-admin/src/views/pl/self-vehicle/index.vue | 12 + web-admin/src/views/pl/vehicle/index.vue | 12 + 37 files changed, 1362 insertions(+), 195 deletions(-) create mode 100644 docs/sql/20260628_pl_freight_settlement_invoice_attachment.sql create mode 100644 docs/sql/20260628_pl_freight_settlement_split_menu.sql create mode 100644 docs/sql/20260628_pl_vehicle_menu_order.sql create mode 100644 docs/sql/20260628_pl_vehicle_trailer_no.sql create mode 100644 docs/superpowers/specs/2026-06-28-pl-freight-settlement-split-design.md create mode 100644 web-admin/src/views/pl/freight-approval/index.vue create mode 100644 web-admin/src/views/pl/freight-disburse/index.vue create mode 100644 web-admin/src/views/pl/freight/components/ApprovalDonePanel.vue create mode 100644 web-admin/src/views/pl/freight/components/ApprovalPendingPanel.vue diff --git a/backend/app/models/pl_models.py b/backend/app/models/pl_models.py index 0765600a7..367a15579 100644 --- a/backend/app/models/pl_models.py +++ b/backend/app/models/pl_models.py @@ -56,6 +56,7 @@ class PlVehicle(Base): carrier_id = Column(String(64), nullable=True, comment="承运商ID(类型为承运商时必填)") carrier_name = Column(String(200), nullable=True, comment="承运商名称(冗余)") license_plate = Column(String(20), nullable=False, unique=True, comment="车牌号") + trailer_no = Column(String(20), nullable=True, comment="挂车号") default_driver_id = Column(String(64), nullable=True, comment="默认司机ID") default_driver_name = Column(String(100), nullable=True, comment="默认司机姓名(冗余)") load_capacity = Column(DECIMAL(10, 2), nullable=True, comment="载重(吨)") @@ -533,6 +534,7 @@ class PlFreightSettlement(Base): # 发票信息 invoice_no = Column(String(50), nullable=True, comment="发票号") invoice_date = Column(Date, nullable=True, comment="开票日期") + invoice_attachment_urls = Column(Text, nullable=True, comment="发票附件URLs,逗号分隔") # 结算状态 settlement_status = Column(String(20), nullable=False, default="pending", comment="结算状态 pending-待提交 submitted-已提交 approved-审核通过 confirmed-已确认") diff --git a/backend/app/schemas/pl/base_data.py b/backend/app/schemas/pl/base_data.py index e39270b38..d85f52c62 100644 --- a/backend/app/schemas/pl/base_data.py +++ b/backend/app/schemas/pl/base_data.py @@ -92,6 +92,7 @@ class VehicleBase(BaseModel): carrier_id: Optional[str] = Field(default=None, alias="carrierId", description="承运商ID") carrier_name: Optional[str] = Field(default=None, max_length=200, alias="carrierName", description="承运商名称") license_plate: str = Field(..., max_length=20, alias="licensePlate", description="车牌号") + trailer_no: Optional[str] = Field(default=None, max_length=20, alias="trailerNo", description="挂车号") default_driver_id: Optional[str] = Field(default=None, alias="defaultDriverId", description="默认司机ID(只读兼容)") default_driver_name: Optional[str] = Field(default=None, max_length=100, alias="defaultDriverName", description="默认司机姓名(只读兼容)") load_capacity: Optional[Decimal] = Field(default=None, alias="loadCapacity", description="载重(吨)") @@ -110,6 +111,7 @@ class VehicleUpdate(BaseModel): carrier_id: Optional[str] = Field(default=None, alias="carrierId") carrier_name: Optional[str] = Field(default=None, max_length=200, alias="carrierName") license_plate: Optional[str] = Field(default=None, max_length=20, alias="licensePlate") + trailer_no: Optional[str] = Field(default=None, max_length=20, alias="trailerNo") load_capacity: Optional[Decimal] = Field(default=None, alias="loadCapacity") vehicle_status: Optional[str] = Field(default=None, max_length=20, alias="vehicleStatus") remark: Optional[str] = None diff --git a/backend/app/schemas/pl/freight.py b/backend/app/schemas/pl/freight.py index 601702ab2..084acd572 100644 --- a/backend/app/schemas/pl/freight.py +++ b/backend/app/schemas/pl/freight.py @@ -16,6 +16,9 @@ class FreightSettlementBase(BaseModel): invoice_amount: Optional[Decimal] = Field(default=None, alias="invoiceAmount", description="发票金额") invoice_no: Optional[str] = Field(default=None, max_length=50, alias="invoiceNo", description="发票号") invoice_date: Optional[date] = Field(default=None, alias="invoiceDate", description="开票日期") + invoice_attachment_urls: Optional[str] = Field( + default=None, alias="invoiceAttachmentUrls", description="发票附件URLs,逗号分隔" + ) settlement_status: str = Field(default="pending", alias="settlementStatus", description="结算状态") remark: Optional[str] = None @@ -36,6 +39,7 @@ class FreightSettlementUpdate(BaseModel): invoice_amount: Optional[Decimal] = Field(default=None, alias="invoiceAmount") invoice_no: Optional[str] = Field(default=None, max_length=50, alias="invoiceNo") invoice_date: Optional[date] = Field(default=None, alias="invoiceDate") + invoice_attachment_urls: Optional[str] = Field(default=None, alias="invoiceAttachmentUrls") remark: Optional[str] = None model_config = {"populate_by_name": True} diff --git a/docs/sql/20260628_pl_freight_settlement_invoice_attachment.sql b/docs/sql/20260628_pl_freight_settlement_invoice_attachment.sql new file mode 100644 index 000000000..201e08b63 --- /dev/null +++ b/docs/sql/20260628_pl_freight_settlement_invoice_attachment.sql @@ -0,0 +1,3 @@ +-- 运费结算:发票附件字段 +ALTER TABLE `pl_freight_settlement` + ADD COLUMN `invoice_attachment_urls` text DEFAULT NULL COMMENT '发票附件URLs,逗号分隔' AFTER `invoice_date`; diff --git a/docs/sql/20260628_pl_freight_settlement_split_menu.sql b/docs/sql/20260628_pl_freight_settlement_split_menu.sql new file mode 100644 index 000000000..cd3e88767 --- /dev/null +++ b/docs/sql/20260628_pl_freight_settlement_split_menu.sql @@ -0,0 +1,99 @@ +-- ============================================================================= +-- 运费结算 · 拆分为三菜单(结算 / 审批 / 财务发放) +-- 执行库:shanxia2.0 门户库 +-- 说明:可重复执行;执行后重新登录刷新菜单 +-- ============================================================================= + +SET NAMES utf8mb4; + +-- ----------------------------------------------------------------------------- +-- 1. 新增菜单 +-- ----------------------------------------------------------------------------- + +INSERT INTO `sys_menu` ( + `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, + `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, + `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag` +) VALUES +( + 'PL_FREIGHT_APPROVAL', '运费结算审批', 'PL_MENU_ROOT', 'C', + 'freight-approval', 'pl/freight-approval/index', 'pl:freight-approval:list', + 1, '1', '1', 'shanxia2.0', 31, '待审批与已审批结算单', + 'system', '', NOW(), NULL, NOW(), 0 +), +( + 'PL_FREIGHT_APPROVAL_Q', '查询', 'PL_FREIGHT_APPROVAL', 'F', + '', '', 'pl:freight-approval:query', + 1, '1', '1', 'shanxia2.0', 1, NULL, + 'system', '', NOW(), NULL, NOW(), 0 +), +( + 'PL_FREIGHT_DISBURSE_MENU', '运费财务发放', 'PL_MENU_ROOT', 'C', + 'freight-disburse', 'pl/freight-disburse/index', 'pl:freight-disburse:list', + 1, '1', '1', 'shanxia2.0', 32, '待发放与已发放结算单', + 'system', '', NOW(), NULL, NOW(), 0 +), +( + 'PL_FREIGHT_DISBURSE_Q', '查询', 'PL_FREIGHT_DISBURSE_MENU', 'F', + '', '', 'pl:freight-disburse:query', + 1, '1', '1', 'shanxia2.0', 1, NULL, + 'system', '', NOW(), NULL, NOW(), 0 +) +ON DUPLICATE KEY UPDATE + `menu_name` = VALUES(`menu_name`), + `parent_id` = VALUES(`parent_id`), + `menu_type` = VALUES(`menu_type`), + `path` = VALUES(`path`), + `component` = VALUES(`component`), + `perms` = VALUES(`perms`), + `visible` = VALUES(`visible`), + `status` = VALUES(`status`), + `order_num` = VALUES(`order_num`), + `update_time` = NOW(), + `del_flag` = 0; + +-- 运费结算菜单排序保持在审批、发放之前 +UPDATE `sys_menu` +SET `order_num` = 30, `update_time` = NOW() +WHERE `id` = 'PL_FREIGHT' AND `del_flag` = 0; + +-- ----------------------------------------------------------------------------- +-- 2. 为已拥有「运费结算」菜单的角色自动授权新菜单 +-- ----------------------------------------------------------------------------- + +INSERT INTO `sys_role_menu` ( + `id`, `role_id`, `menu_id`, `tenant_no`, `order_num`, `remark`, + `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag` +) +SELECT + REPLACE(UUID(), '-', ''), + rm.`role_id`, + m.`menu_id`, + rm.`tenant_no`, + m.`order_num`, + 'pl freight split menus auto grant', + 'system', + '', + NOW(), + NULL, + NOW(), + 0 +FROM `sys_role_menu` rm +INNER JOIN ( + SELECT 'PL_FREIGHT_APPROVAL' AS menu_id, 31 AS order_num UNION ALL + SELECT 'PL_FREIGHT_APPROVAL_Q', 1 UNION ALL + SELECT 'PL_FREIGHT_DISBURSE_MENU', 32 UNION ALL + SELECT 'PL_FREIGHT_DISBURSE_Q', 1 +) m ON 1 = 1 +WHERE rm.`menu_id` = 'PL_FREIGHT' + AND rm.`del_flag` = 0 + AND NOT EXISTS ( + SELECT 1 FROM `sys_role_menu` x + WHERE x.`role_id` = rm.`role_id` AND x.`menu_id` = m.`menu_id` AND x.`del_flag` = 0 + ); + +SELECT `id`, `menu_name`, `path`, `component`, `perms`, `order_num` +FROM `sys_menu` +WHERE `id` IN ('PL_FREIGHT', 'PL_FREIGHT_APPROVAL', 'PL_FREIGHT_DISBURSE_MENU') + AND `del_flag` = 0 +ORDER BY `order_num`; diff --git a/docs/sql/20260628_pl_vehicle_menu_order.sql b/docs/sql/20260628_pl_vehicle_menu_order.sql new file mode 100644 index 000000000..96aed70fb --- /dev/null +++ b/docs/sql/20260628_pl_vehicle_menu_order.sql @@ -0,0 +1,26 @@ +-- ============================================================================= +-- 运输管理 · 调整「山峡自有车辆」与「车辆管理」菜单排序 +-- 执行库:shanxia2.0 门户库(与 web-admin 同库) +-- 说明:可重复执行;交换 order_num,使「山峡自有车辆」排在「车辆管理」之上 +-- 执行后:重新登录或刷新菜单缓存 +-- ============================================================================= + +SET NAMES utf8mb4; + +UPDATE `sys_menu` +SET `order_num` = 2, `update_time` = NOW() +WHERE `id` = 'PL_SELF_VEHICLE' + AND `del_flag` = 0 + AND (`order_num` IS NULL OR `order_num` <> 2); + +UPDATE `sys_menu` +SET `order_num` = 4, `update_time` = NOW() +WHERE `id` = 'PL_VEHICLE' + AND `del_flag` = 0 + AND (`order_num` IS NULL OR `order_num` <> 4); + +SELECT `id`, `menu_name`, `parent_id`, `order_num` +FROM `sys_menu` +WHERE `id` IN ('PL_SELF_VEHICLE', 'PL_VEHICLE') + AND `del_flag` = 0 +ORDER BY `order_num`; diff --git a/docs/sql/20260628_pl_vehicle_trailer_no.sql b/docs/sql/20260628_pl_vehicle_trailer_no.sql new file mode 100644 index 000000000..1a71b1f41 --- /dev/null +++ b/docs/sql/20260628_pl_vehicle_trailer_no.sql @@ -0,0 +1,32 @@ +-- ============================================================================= +-- 运输管理 · 车辆表增加挂车号 +-- 执行库:shanxia2.0 门户库(与 web-admin 同库) +-- 说明:可重复执行;挂车号为车辆主数据属性,地磅/出入库仍使用 license_plate +-- ============================================================================= + +SET NAMES utf8mb4; + +SET @col_exists := ( + SELECT COUNT(*) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'pl_vehicle' + AND COLUMN_NAME = 'trailer_no' +); + +SET @ddl := IF( + @col_exists = 0, + 'ALTER TABLE `pl_vehicle` ADD COLUMN `trailer_no` varchar(20) DEFAULT NULL COMMENT ''挂车号'' AFTER `license_plate`', + 'SELECT ''trailer_no already exists'' AS message' +); + +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_COMMENT +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'pl_vehicle' + AND COLUMN_NAME IN ('license_plate', 'trailer_no') +ORDER BY ORDINAL_POSITION; diff --git a/docs/sql/pl_tables.sql b/docs/sql/pl_tables.sql index cd6b993f6..4b823727e 100644 --- a/docs/sql/pl_tables.sql +++ b/docs/sql/pl_tables.sql @@ -417,6 +417,7 @@ CREATE TABLE `pl_freight_settlement` ( `invoice_amount` decimal(15,2) DEFAULT NULL COMMENT '发票金额', `invoice_no` varchar(50) DEFAULT NULL COMMENT '发票号', `invoice_date` date DEFAULT NULL COMMENT '开票日期', + `invoice_attachment_urls` text DEFAULT NULL COMMENT '发票附件URLs,逗号分隔', `settlement_status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '结算状态 pending-待提交 submitted-已提交 approved-审核通过 confirmed-已确认', `tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号', `order_num` int(11) DEFAULT NULL COMMENT '排序号', diff --git a/docs/sql/shanxia2.0.sql b/docs/sql/shanxia2.0.sql index aa7d91479..80c1f8dfb 100644 --- a/docs/sql/shanxia2.0.sql +++ b/docs/sql/shanxia2.0.sql @@ -2425,6 +2425,7 @@ CREATE TABLE `pl_freight_settlement` ( `invoice_amount` decimal(15,2) DEFAULT NULL COMMENT '发票金额', `invoice_no` varchar(50) DEFAULT NULL COMMENT '发票号', `invoice_date` date DEFAULT NULL COMMENT '开票日期', + `invoice_attachment_urls` text DEFAULT NULL COMMENT '发票附件URLs,逗号分隔', `settlement_status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '结算状态 pending-待提交 submitted-已提交 approved-审核通过 confirmed-已确认', `tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号', `order_num` int(11) DEFAULT NULL COMMENT '排序号', @@ -2993,6 +2994,7 @@ CREATE TABLE `pl_vehicle` ( `carrier_id` varchar(64) DEFAULT NULL COMMENT '承运商ID(类型为承运商时必填)', `carrier_name` varchar(200) DEFAULT NULL COMMENT '承运商名称(冗余)', `license_plate` varchar(20) NOT NULL COMMENT '车牌号', + `trailer_no` varchar(20) DEFAULT NULL COMMENT '挂车号', `default_driver_id` varchar(64) DEFAULT NULL COMMENT '默认司机ID', `default_driver_name` varchar(100) DEFAULT NULL COMMENT '默认司机姓名(冗余)', `load_capacity` decimal(10,2) DEFAULT NULL COMMENT '载重(吨)', @@ -8499,9 +8501,9 @@ INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `co INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_PLAN_ARCHIVE_E', '编辑', 'PL_PLAN_ARCHIVE', 'F', '', '', 'pl:plan-archive:edit', 1, '1', '1', 'shanxia2.0', 2, NULL, 'system', '', '2026-06-25 12:00:00', NULL, '2026-06-25 12:00:00', 0); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_PLAN_ARCHIVE_A', '归档', 'PL_PLAN_ARCHIVE', 'F', '', '', 'pl:plan-archive:archive', 1, '1', '1', 'shanxia2.0', 3, NULL, 'system', '', '2026-06-25 12:00:00', NULL, '2026-06-25 12:00:00', 0); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_PLAN_CERT', '危化品证上传', 'PL_MENU_ROOT', 'C', 'plan-cert', 'pl/plan-cert/index', 'pl:plan-cert:list', 1, '1', '1', 'shanxia2.0', 12, '危化品购买证/运输证上传', 'system', '', '2026-06-20 18:18:10', NULL, '2026-06-20 18:18:10', 0); -INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_SELF_VEHICLE', '山峡自有车辆', 'PL_MENU_ROOT', 'C', 'self-vehicle', 'pl/self-vehicle/index', 'pl:self-vehicle:list', 1, '1', '1', 'shanxia2.0', 4, '展示全部自有类型车辆', 'system', '', '2026-06-20 08:07:00', NULL, '2026-06-20 08:07:00', 0); +INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_SELF_VEHICLE', '山峡自有车辆', 'PL_MENU_ROOT', 'C', 'self-vehicle', 'pl/self-vehicle/index', 'pl:self-vehicle:list', 1, '1', '1', 'shanxia2.0', 2, '展示全部自有类型车辆', 'system', '', '2026-06-20 08:07:00', NULL, '2026-06-20 08:07:00', 0); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_TRANSPORT', '运输管理', 'PL_MENU_ROOT', 'C', 'transport', 'pl/transport/index', 'pl:transport:list', 1, '0', '1', 'shanxia2.0', 20, NULL, 'system', '', '2026-06-11 05:17:13', NULL, '2026-06-20 21:42:04', 0); -INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_VEHICLE', '车辆管理', 'PL_MENU_ROOT', 'C', 'vehicle', 'pl/vehicle/index', 'pl:vehicle:list', 1, '1', '1', 'shanxia2.0', 2, NULL, 'system', '', '2026-06-11 05:17:12', NULL, '2026-06-11 05:17:12', 0); +INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('PL_VEHICLE', '车辆管理', 'PL_MENU_ROOT', 'C', 'vehicle', 'pl/vehicle/index', 'pl:vehicle:list', 1, '1', '1', 'shanxia2.0', 4, NULL, 'system', '', '2026-06-11 05:17:12', NULL, '2026-06-11 05:17:12', 0); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('SYSB000000000000000000000000000001', '系统基础信息', '2', 'M', '/system-base', '/index/index', NULL, 1, '1', '1', 'shanxia2.0', 11, NULL, NULL, '', '2026-05-27 16:26:30', NULL, '2026-05-30 18:16:14', 1); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('SYSM000000000000000000000000000001', '系统管理', '2', 'M', '/system', '/index/index', NULL, 1, '1', '1', 'shanxia2.0', 13, NULL, NULL, '', '2026-05-27 16:26:30', NULL, '2026-05-30 17:06:32', 0); INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('WKF00000000000000000000000000001', '工作流管理', '2', 'M', '/workflow', '/index/index', NULL, 1, '1', '1', 'shanxia2.0', 12, NULL, NULL, '', '2026-05-27 16:26:30', NULL, '2026-05-30 17:06:32', 0); diff --git a/docs/superpowers/specs/2026-06-28-pl-freight-settlement-split-design.md b/docs/superpowers/specs/2026-06-28-pl-freight-settlement-split-design.md new file mode 100644 index 000000000..2c008aebf --- /dev/null +++ b/docs/superpowers/specs/2026-06-28-pl-freight-settlement-split-design.md @@ -0,0 +1,32 @@ +# 运费结算三菜单拆分 — 设计文档 + +> **日期**: 2026-06-28 +> **状态**: 已确认 +> **前置**: `docs/superpowers/specs/2026-06-25-pl-freight-settlement-design.md` + +## 目标 + +将原「运费结算」单页四 Tab 拆为三个独立菜单,按角色分离:计划专员组单/结算、审批人审批、财务发放。 + +## 菜单结构 + +| 菜单 | 路由 | Tab | 数据范围 | +|------|------|-----|----------| +| 运费结算 | `/#/pl/freight` | 未结算计划 / 结算单 | 计划;结算单 `pending`/`approving`/`approved` | +| 运费结算审批 | `/#/pl/freight-approval` | 待审批 / 已审批 | `approving`;`approved`+`confirmed`(全部) | +| 运费财务发放 | `/#/pl/freight-disburse` | 待发放 / 已发放 | `approved`;`confirmed` | + +## 关键决策 + +- **已审批 Tab**:展示租户内全部审批已完成结算单(选项 A) +- **发票信息**:审批通过后(`approved`)在「运费结算 → 结算单」Tab 维护 +- **后端 tab 参数**:`bills` | `approval_pending` | `approval_done` | `disburse` | `settled` +- **编辑权限**:`pending` 全字段编辑;`approved` 仅发票字段 + 备注 + +## 业务流程 + +未结算计划 → 组单(草稿)→ 提交审批 → 审批页通过 → 结算页补发票 → 财务页发放 → 已发放 + +## SQL + +`docs/sql/20260628_pl_freight_settlement_split_menu.sql` diff --git a/web-admin/src/api/pl/index.ts b/web-admin/src/api/pl/index.ts index 6af33beec..56101254e 100644 --- a/web-admin/src/api/pl/index.ts +++ b/web-admin/src/api/pl/index.ts @@ -67,6 +67,7 @@ export interface Vehicle { carrierId?: string carrierName?: string licensePlate: string + trailerNo?: string defaultDriverId?: string defaultDriverName?: string personnelSummary?: string @@ -86,6 +87,7 @@ export interface VehiclePayload { carrierId?: string carrierName?: string licensePlate: string + trailerNo?: string loadCapacity?: number | null vehicleStatus: string remark?: string @@ -575,6 +577,7 @@ export interface UnsettledPlanItem { export interface UnsettledPlanQuery { q?: string + carrierId?: string planType?: string licensePlate?: string page?: number @@ -624,6 +627,7 @@ export interface FreightSettlement { invoiceAmount?: number invoiceNo?: string invoiceDate?: string + invoiceAttachmentUrls?: string settlementStatus: string remark?: string createBy?: string @@ -647,8 +651,9 @@ export interface FreightSettlement { export interface FreightSettlementQuery { q?: string + carrierId?: string settlementStatus?: string - tab?: 'bills' | 'disburse' | 'settled' + tab?: 'bills' | 'approval_pending' | 'approval_done' | 'disburse' | 'settled' page?: number pageSize?: number } diff --git a/web-admin/src/components/business/pl-freight-disburse-dialog/index.vue b/web-admin/src/components/business/pl-freight-disburse-dialog/index.vue index d5fd504f6..1b9ef5d91 100644 --- a/web-admin/src/components/business/pl-freight-disburse-dialog/index.vue +++ b/web-admin/src/components/business/pl-freight-disburse-dialog/index.vue @@ -2,7 +2,7 @@ - -
- - - - - - - - - - - - - +
+
+

结算摘要

+
+
+ 结算单号 + {{ settlement.settlementNo }} +
+
+ 运费合计(元) + {{ + formatAmount(settlement.totalFreight) + }} +
+
+
+ +
+

发票信息

+
+
+ 发票号 + {{ settlement.invoiceNo || '—' }} +
+
+ 开票日期 + {{ settlement.invoiceDate || '—' }} +
+
+ 发票金额(元) + {{ + settlement.invoiceAmount ? formatAmount(settlement.invoiceAmount) : '—' + }} +
+
+
+ 发票附件 - - - - -
- +
+ + +
+

发放登记

+ +
+ + + + + + + + + + + + +
+
+
+ +
+

关联运输信息

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
@@ -143,8 +157,6 @@ diff --git a/web-admin/src/views/pl/plan-archive/index.vue b/web-admin/src/views/pl/plan-archive/index.vue index fb6034b4b..e913fa6d6 100644 --- a/web-admin/src/views/pl/plan-archive/index.vue +++ b/web-admin/src/views/pl/plan-archive/index.vue @@ -133,11 +133,6 @@ - - -