Просмотр исходного кода

feat(s5): 委外发料单只读骨架页 + 菜单重指 (S5-OUTSOURCE-ISSUE-PROTOTYPE-FIELD-MAP-1)

- 新增 outsourceIssueList.vue:委外发料单只读骨架页,列/查询/详情/明细结构来自旧系统截图与 sql.txt,
  空数据结构、无 mock、无假枚举、不开放新增/编辑/保存/物料卡写路径
- 1.0.205.sql:将菜单 1329015020001 的 Component 由 placeholder 重指到真实页面,仅 UPDATE 单条、幂等
- SysMenuSeedData.cs:委外发料单菜单 Component 同步(fresh install 用)
- chore: bump version Web 2.4.201 / server 1.0.205
YY968XX 21 часов назад
Родитель
Сommit
ed2872b9be

+ 1 - 1
Web/package.json

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

+ 177 - 0
Web/src/views/aidop/s5/warehouse/outsourceIssueList.vue

@@ -0,0 +1,177 @@
+<template>
+	<AidopDemoShell :title="pageTitle" subtitle="只读列表">
+		<!--
+			S5 委外发料单 · 只读骨架页(S5-OUTSOURCE-ISSUE-PROTOTYPE-FIELD-MAP-1)。
+			列名/查询项/详情结构均来自旧系统截图与 sql.txt(NbrMaster / NbrDetail),
+			真实业务数据源尚未定位(见字段对接表草案),本页不接真实接口、不写任何数据,
+			列表恒为空数据结构,仅承接页面与字段结构。
+		-->
+		<el-form :inline="true" :model="query" class="mb12" @submit.prevent>
+			<el-form-item label="发料单号">
+				<el-input v-model="query.nbr" clearable style="width: 200px" />
+			</el-form-item>
+			<el-form-item label="委外单号">
+				<el-input v-model="query.address" clearable style="width: 200px" />
+			</el-form-item>
+			<el-form-item label="发料日期">
+				<el-date-picker
+					v-model="dateRange"
+					type="daterange"
+					value-format="YYYY-MM-DD"
+					range-separator="-"
+					start-placeholder="开始日期"
+					end-placeholder="结束日期"
+					unlink-panels
+					style="width: 260px"
+				/>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" @click="doSearch">查询</el-button>
+				<el-button @click="resetQuery">重置</el-button>
+			</el-form-item>
+		</el-form>
+
+		<el-table :data="rows" row-key="id" border stripe>
+			<el-table-column type="index" label="#" width="60" align="center" />
+			<el-table-column prop="nbr" label="发料单号" min-width="180" show-overflow-tooltip resizable />
+			<el-table-column prop="date" label="发料日期" width="140" resizable />
+			<el-table-column prop="statusDescr" label="状态" width="90" resizable />
+			<el-table-column prop="address" label="委外单号" min-width="180" show-overflow-tooltip resizable />
+			<el-table-column prop="departmentDescr" label="部门" min-width="140" show-overflow-tooltip resizable />
+			<el-table-column prop="user1" label="发料人" width="120" resizable />
+			<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip resizable />
+			<el-table-column prop="createUser" label="创建用户" width="120" resizable />
+			<el-table-column prop="createTime" label="创建时间" width="160" resizable />
+			<el-table-column label="操作" width="220" fixed="right">
+				<template #default="{ row }">
+					<el-button link type="primary" @click="viewRow(row)">查看</el-button>
+					<el-button link disabled>编辑</el-button>
+					<el-button link disabled>物料卡</el-button>
+				</template>
+			</el-table-column>
+			<template #empty>
+				<el-empty description="暂无数据" />
+			</template>
+		</el-table>
+
+		<div class="pager">
+			<el-pagination
+				v-model:current-page="query.page"
+				v-model:page-size="query.pageSize"
+				:total="total"
+				:page-sizes="[10, 20, 50]"
+				layout="total, sizes, prev, pager, next"
+			/>
+		</div>
+
+		<!-- 查看详情骨架:基础信息 + 发料单明细结构(来自 4.png / 5.png),只读、空结构 -->
+		<el-dialog v-model="detailVisible" title="委外发料单" width="900px" append-to-body>
+			<el-descriptions :column="3" border title="基础信息">
+				<el-descriptions-item label="领料单号">{{ detail.nbr }}</el-descriptions-item>
+				<el-descriptions-item label="委外采购单">{{ detail.address }}</el-descriptions-item>
+				<el-descriptions-item label="发料日期">{{ detail.date }}</el-descriptions-item>
+				<el-descriptions-item label="部门">{{ detail.departmentDescr }}</el-descriptions-item>
+				<el-descriptions-item label="申请人">{{ detail.createUser }}</el-descriptions-item>
+				<el-descriptions-item label="发料人">{{ detail.user1 }}</el-descriptions-item>
+				<el-descriptions-item label="备注" :span="3">{{ detail.remark }}</el-descriptions-item>
+			</el-descriptions>
+
+			<div class="detail-section-title">发料单明细</div>
+			<el-table :data="detailLines" border stripe size="small">
+				<el-table-column type="index" label="项次" width="64" align="center" />
+				<el-table-column prop="itemNum" label="物料编码" min-width="140" />
+				<el-table-column prop="um" label="单位" width="80" />
+				<el-table-column prop="qtyOrd" label="工单需求数" width="110" />
+				<!-- 发料数量 / 已发数 / 批次号 的真实 NbrDetail 列名未确认(见待补字段表),仅承接表头结构,不绑定推测 key -->
+				<el-table-column label="发料数量" width="100" />
+				<el-table-column label="已发数" width="90" />
+				<el-table-column prop="locationFrom" label="转出库位" width="120" />
+				<el-table-column prop="locationTo" label="转入库位" width="120" />
+				<el-table-column label="批次号" width="120" />
+				<el-table-column prop="status" label="状态" width="80" />
+				<el-table-column prop="remark" label="备注" min-width="120" />
+				<template #empty>
+					<el-empty description="暂无数据" />
+				</template>
+			</el-table>
+		</el-dialog>
+	</AidopDemoShell>
+</template>
+
+<script setup lang="ts" name="aidopS5WarehouseOutsourceIssue">
+import { computed, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import AidopDemoShell from '/@/views/aidop/components/AidopDemoShell.vue';
+
+// 列表行结构(key 来自 sql.txt SELECT 列;本页不接真实接口,rows 恒为空)
+interface OutsourceIssueRow {
+	id?: number;
+	nbr?: string;
+	date?: string;
+	statusDescr?: string;
+	address?: string;
+	departmentDescr?: string;
+	user1?: string;
+	remark?: string;
+	createUser?: string;
+	createTime?: string;
+}
+
+const route = useRoute();
+const pageTitle = computed(() => (route.meta?.title as string) || '委外发料单');
+
+const query = reactive({
+	nbr: '',
+	address: '',
+	dateStart: '',
+	dateEnd: '',
+	page: 1,
+	pageSize: 10,
+});
+const dateRange = ref<[string, string] | null>(null);
+
+// 真实数据源待补证(见字段对接表草案):本页不发起请求,列表保持空数据结构。
+const rows = ref<OutsourceIssueRow[]>([]);
+const total = ref(0);
+
+const detailVisible = ref(false);
+const detail = reactive<OutsourceIssueRow>({});
+const detailLines = ref<Record<string, unknown>[]>([]);
+
+function doSearch() {
+	query.dateStart = dateRange.value?.[0] || '';
+	query.dateEnd = dateRange.value?.[1] || '';
+	query.page = 1;
+	// 真实查询接口未就绪,仅维持空结构,不构造任何假数据。
+}
+
+function resetQuery() {
+	query.nbr = '';
+	query.address = '';
+	dateRange.value = null;
+	query.dateStart = '';
+	query.dateEnd = '';
+	query.page = 1;
+}
+
+function viewRow(row: OutsourceIssueRow) {
+	Object.assign(detail, row);
+	detailLines.value = [];
+	detailVisible.value = true;
+}
+</script>
+
+<style scoped lang="scss">
+.mb12 {
+	margin-bottom: 12px;
+}
+.pager {
+	margin-top: 12px;
+	display: flex;
+	justify-content: flex-end;
+}
+.detail-section-title {
+	margin: 16px 0 8px;
+	font-weight: 600;
+}
+</style>

+ 6 - 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.204</AssemblyVersion>
-    <FileVersion>1.0.204</FileVersion>
-    <Version>1.0.204</Version>
+    <AssemblyVersion>1.0.205</AssemblyVersion>
+    <FileVersion>1.0.205</FileVersion>
+    <Version>1.0.205</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -187,6 +187,9 @@
     <None Update="UpdateScripts\1.0.203.sql">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="UpdateScripts\1.0.205.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>

+ 20 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.205.sql

@@ -0,0 +1,20 @@
+-- ============================================================
+-- 1.0.205.sql
+-- S5-OUTSOURCE-ISSUE-PROTOTYPE-FIELD-MAP-1
+--
+-- 业务目标:将「委外发料单」菜单(Id=1329015020001,仓储管理目录 1322000000016 下)
+--   的 Component 由 placeholder(/aidop/planning/index)重指到只读骨架真实页面
+--   /aidop/s5/warehouse/outsourceIssueList。
+--
+-- 安全保证:
+--   - 仅 UPDATE 该单条菜单的 Component / Remark / UpdateTime;
+--   - 不改 Path / Name / Pid / Title / Type / OrderNo;
+--   - 不 INSERT / DELETE / DROP / TRUNCATE;不动 SysTenantMenu / SysRoleMenu(该菜单已分配);
+--   - 不动其它 S0/S5/S6/S7/S8 菜单;幂等(重跑结果一致)。
+-- ============================================================
+
+UPDATE SysMenu
+SET Component  = '/aidop/s5/warehouse/outsourceIssueList',
+    Remark     = 'S5 委外发料单(只读骨架,真实数据源待补证)',
+    UpdateTime = NOW()
+WHERE Id = 1329015020001;

+ 1 - 1
server/Plugins/Admin.NET.Plugin.AiDOP/SeedData/SysMenuSeedData.cs

@@ -540,7 +540,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
         // 仓储管理 (1322000000016) 下 5 个三级
         const long warehouseDirId = 1322000000016L;
         const long warehouseBase = 1329015020000L;
-        yield return new SysMenu { Id = warehouseBase + 1, Pid = warehouseDirId, Title = "委外发料单", Path = "/aidop/s5/warehouse/outsource-issue", Name = "aidopS5WarehouseOutsourceIssue", Component = placeholderComponent, Icon = "ele-Document", Type = MenuTypeEnum.Menu, CreateTime = ct, OrderNo = 10, Remark = "S5 委外发料单(真实页面待交付)" };
+        yield return new SysMenu { Id = warehouseBase + 1, Pid = warehouseDirId, Title = "委外发料单", Path = "/aidop/s5/warehouse/outsource-issue", Name = "aidopS5WarehouseOutsourceIssue", Component = "/aidop/s5/warehouse/outsourceIssueList", Icon = "ele-Document", Type = MenuTypeEnum.Menu, CreateTime = ct, OrderNo = 10, Remark = "S5 委外发料单(只读骨架,真实数据源待补证)" };
         yield return new SysMenu { Id = warehouseBase + 2, Pid = warehouseDirId, Title = "采购收货单", Path = "/aidop/s5/warehouse/purchase-receipt", Name = "aidopS5WarehousePurchaseReceipt", Component = placeholderComponent, Icon = "ele-Document", Type = MenuTypeEnum.Menu, CreateTime = ct, OrderNo = 20, Remark = "S5 采购收货单(真实页面待交付)" };
         yield return new SysMenu { Id = warehouseBase + 3, Pid = warehouseDirId, Title = "生产领料单", Path = "/aidop/s5/warehouse/production-issue", Name = "aidopS5WarehouseProductionIssue", Component = placeholderComponent, Icon = "ele-Document", Type = MenuTypeEnum.Menu, CreateTime = ct, OrderNo = 30, Remark = "S5 生产领料单(真实页面待交付)" };
         yield return new SysMenu { Id = warehouseBase + 4, Pid = warehouseDirId, Title = "生产退料单", Path = "/aidop/s5/warehouse/production-return", Name = "aidopS5WarehouseProductionReturn", Component = placeholderComponent, Icon = "ele-Document", Type = MenuTypeEnum.Menu, CreateTime = ct, OrderNo = 40, Remark = "S5 生产退料单(真实页面待交付)" };