Explorar el Código

feat: 发货单表单多项优化 — 销售单号/部门下拉回显编号+名称、发货单号SH自动生成、状态禁用、隐藏行号列、修复部门列表不显示(去掉Domain JOIN条件)

Pengxy hace 5 meses
padre
commit
42f0a06276

+ 1 - 1
Web/package.json

@@ -1,7 +1,7 @@
 {
 	"name": "admin.net",
 	"type": "module",
-	"version": "2.4.156",
+	"version": "2.4.157",
 	"packageManager": "pnpm@10.32.1",
 	"lastBuildTime": "2026.03.15",
 	"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",

+ 3 - 0
Web/src/views/aidop/api/asnShipper.ts

@@ -38,8 +38,11 @@ export interface AsnShipperDetail {
 	recID: number;
 	id?: string | null;
 	ordNbr?: string | null;
+	ordNbrName?: string | null;
 	soldTo?: string | null;
+	soldToName?: string | null;
 	department?: string | null;
+	departmentName?: string | null;
 	shipDate?: string | null;
 	status?: string | null;
 	remark?: string | null;

+ 27 - 10
Web/src/views/aidop/business/asnShipperForm.vue

@@ -4,7 +4,7 @@
 			<el-row :gutter="16">
 				<el-col :span="8">
 					<el-form-item label="发货单号" prop="id">
-						<el-input v-model="form.id" :disabled="isView" placeholder="请输入发货单号" />
+						<el-input v-model="form.id" :disabled="isView || isCreate" placeholder="保存后自动生成" />
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
@@ -69,7 +69,7 @@
 				</el-col>
 				<el-col :span="8">
 					<el-form-item label="状态" prop="status">
-						<el-input v-model="form.status" :disabled="isView" />
+						<el-input v-model="form.status" disabled />
 					</el-form-item>
 				</el-col>
 				<el-col :span="24">
@@ -86,9 +86,6 @@
 			</div>
 
 			<el-table :data="form.details" border stripe style="width: 100%" max-height="380">
-				<el-table-column label="行号" width="60" align="center">
-					<template #default="{ $index }">{{ $index + 1 }}</template>
-				</el-table-column>
 				<el-table-column label="项次" width="80" align="center">
 					<template #default="{ row, $index }">
 						<span>{{ row.line ?? $index + 1 }}</span>
@@ -247,6 +244,7 @@ const emit = defineEmits<{
 }>();
 
 const isView = computed(() => props.mode === 'view');
+const isCreate = computed(() => props.mode === 'create');
 const loading = ref(false);
 const saving = ref(false);
 const formRef = ref<FormInstance>();
@@ -346,13 +344,22 @@ async function loadDetail() {
 
 		// 回填下拉选项,确保已选值显示正常
 		if (form.ordNbr) {
-			salesOrdOptions.value = [{ value: form.ordNbr, label: form.ordNbr }];
+			const ordLabel = d.ordNbrName
+				? `${form.ordNbr}_${d.ordNbrName}`
+				: form.ordNbr;
+			salesOrdOptions.value = [{ value: form.ordNbr, label: ordLabel }];
 		}
 		if (form.soldTo) {
-			customerOptions.value = [{ value: form.soldTo, label: form.soldTo }];
+			const custLabel = d.soldToName
+				? `${form.soldTo} ${d.soldToName}`
+				: form.soldTo;
+			customerOptions.value = [{ value: form.soldTo, label: custLabel }];
 		}
 		if (form.department) {
-			deptOptions.value = [{ value: form.department, label: form.department }];
+			const deptLabel = d.departmentName
+				? `${form.department} ${d.departmentName}`
+				: form.department;
+			deptOptions.value = [{ value: form.department, label: deptLabel }];
 		}
 	} finally {
 		loading.value = false;
@@ -404,8 +411,18 @@ function applyPresetRows() {
 	form.soldTo = first.customNo ?? null;
 	form.shipDate = first.shippingDate ? first.shippingDate.slice(0, 10) : null;
 	// 回填下拉可选项,保证已选值能正常显示
-	if (form.ordNbr) salesOrdOptions.value = [{ value: form.ordNbr, label: form.ordNbr }];
-	if (form.soldTo) customerOptions.value = [{ value: form.soldTo, label: form.soldTo }];
+	if (form.ordNbr) {
+		const ordLabel = first.customName
+			? `${form.ordNbr}_${first.customName}`
+			: form.ordNbr;
+		salesOrdOptions.value = [{ value: form.ordNbr, label: ordLabel }];
+	}
+	if (form.soldTo) {
+		const custLabel = first.customName
+			? `${form.soldTo} ${first.customName}`
+			: form.soldTo;
+		customerOptions.value = [{ value: form.soldTo, label: custLabel }];
+	}
 	// 预填明细
 	form.details = props.presetRows.map((r, idx) => ({
 		recID: null,

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.121</AssemblyVersion>
-    <FileVersion>1.0.121</FileVersion>
-    <Version>1.0.121</Version>
+    <AssemblyVersion>1.0.122</AssemblyVersion>
+    <FileVersion>1.0.122</FileVersion>
+    <Version>1.0.122</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 64 - 3
server/Plugins/Admin.NET.Plugin.AiDOP/Order/AsnShipperService.cs

@@ -1,5 +1,8 @@
 namespace Admin.NET.Plugin.AiDOP.Order;
 
+using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse;
+using Admin.NET.Plugin.AiDOP.Universal;
+
 /// <summary>
 /// 订单发货服务 🚚
 /// 路由前缀:/api/Order/asnshipper/...
@@ -77,7 +80,7 @@ public class AsnShipperService : IDynamicApiController, ITransient
                 a.Remark
             FROM ASNBOLShipperMaster a
             LEFT JOIN DepartmentMaster b
-                ON a.Department = b.Department AND a.Domain = b.Domain
+                ON a.Department = b.Department
             {whereClause}
             """;
 
@@ -102,6 +105,26 @@ public class AsnShipperService : IDynamicApiController, ITransient
         var master = await _masterRep.GetFirstAsync(u => u.RecID == id)
                      ?? throw Oops.Oh("发货单不存在");
 
+        // 查询客户名称,用于前端下拉回显"编号+名称"
+        var soldToName = (await _db.Queryable<CustMaster>()
+            .Where(u => u.Cust == master.SoldTo)
+            .Select(u => u.SortName)
+            .FirstAsync()) ?? string.Empty;
+
+        // 查询销售单客户名称,用于前端下拉回显"编号_客户名称"
+        var ordNbrName = string.IsNullOrWhiteSpace(master.OrdNbr) ? string.Empty
+            : ((await _db.Queryable<SeOrder>()
+                .Where(u => u.BillNo == master.OrdNbr)
+                .Select(u => u.CustomName)
+                .FirstAsync()) ?? string.Empty);
+
+        // 查询部门描述,用于前端下拉回显"编号+描述"
+        var deptName = string.IsNullOrWhiteSpace(master.Department) ? string.Empty
+            : ((await _db.Queryable<AdoS0DepartmentMaster>()
+                .Where(u => u.Department == master.Department)
+                .Select(u => u.Descr)
+                .FirstAsync()) ?? string.Empty);
+
         // 主键关联:ASNBOLShipperDetail.ASNBOLShipperRecID = 主表 RecID
         var details = await _detailRep.GetListAsync(u => u.AsnShipperRecID == id);
         // 兼容历史数据:若外键未写入或曾用错误方式取 RecID,则按业务单号 Id + 销售单号 OrdNbr 兜底
@@ -116,10 +139,13 @@ public class AsnShipperService : IDynamicApiController, ITransient
             recID = master.RecID,
             id = master.Id,
             ordNbr = master.OrdNbr,
+            ordNbrName = ordNbrName,
             soldTo = master.SoldTo,
+            soldToName = soldToName,
             department = master.Department,
+            departmentName = deptName,
             shipDate = master.ShipDate?.ToString("yyyy-MM-dd"),
-            status = master.Status,
+            status = master.Status ?? string.Empty,
             remark = master.Remark,
             details = details.OrderBy(d => d.Line).Select(d => new
             {
@@ -155,9 +181,16 @@ public class AsnShipperService : IDynamicApiController, ITransient
         if (input.RecID is null or 0)
         {
             // ── 新增:参照 SysJobService.AddJobDetail ──
+            // 若发货单号为空则自动生成 SH+当前日期+四位流水号
+            var shipId = input.Id;
+            if (string.IsNullOrWhiteSpace(shipId))
+            {
+                shipId = await GenerateShipIdAsync(_userManager.TenantId);
+            }
+
             var entity = new AsnShipperMaster
             {
-                Id = input.Id,
+                Id = shipId,
                 OrdNbr = input.OrdNbr,
                 SoldTo = input.SoldTo,
                 Department = input.Department,
@@ -383,6 +416,34 @@ public class AsnShipperService : IDynamicApiController, ITransient
         return list;
     }
 
+    // ──────────────── 号生成 ────────────────
+
+    /// <summary>
+    /// 生成发货单号:SH + yyyyMMdd + 4位流水号,例如 SH202605210001
+    /// </summary>
+    private async Task<string> GenerateShipIdAsync(long tenantId)
+    {
+        var today = DateTime.Now.ToString("yyyyMMdd");
+        var prefix = $"SH{today}";
+
+        // 查询当天已有的最大发货单号
+        var maxId = await _db.Queryable<AsnShipperMaster>()
+            .Where(u => u.Id!.StartsWith(prefix) && u.IsActive == 1 && u.TenantId == tenantId)
+            .OrderBy(u => u.Id, OrderByType.Desc)
+            .Select(u => u.Id)
+            .FirstAsync();
+
+        if (string.IsNullOrEmpty(maxId))
+            return $"{prefix}0001";
+
+        // 取后4位转为数字并加1,不足4位补零
+        var last4 = maxId.Length >= 4 ? maxId[^4..] : maxId;
+        if (int.TryParse(last4, out var serial))
+            return $"{prefix}{(serial + 1).ToString().PadLeft(4, '0')}";
+
+        return $"{prefix}0001";
+    }
+
     // ──────────────── 内部查询结果映射类 ────────────────
 
     private sealed class AsnShipperListRow

+ 2 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Order/OrderDeliveryService.cs

@@ -631,10 +631,10 @@ public class OrderDeliveryService : IDynamicApiController, ITransient
             SELECT
                 ROW_NUMBER() OVER (ORDER BY ad.Id) AS Sno,
                 ad.Id,
-                ad.location AS Location,
+                lm.Descr AS Location,
                 ad.UpdateTime AS ShipDate,
                 CAST(ad.QtyToShip AS DECIMAL(18,2)) AS QtyToShip,
-                lm.LocationCode,
+                lm.location as LocationCode,
                 ad.RealQty
             FROM ASNBOLShipperDetail ad
             INNER JOIN ASNBOLShipperMaster am ON ad.ASNBOLShipperRecID = am.RecID