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

fix(s0): add skill dropdown for person skill assignments

YY968XX 4 дней назад
Родитель
Сommit
c7a4cfeee4

+ 1 - 1
Web/package.json

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

+ 26 - 1
Web/src/views/aidop/s0/api/s0ManufacturingApi.ts

@@ -473,7 +473,32 @@ export const s0MfgProductionLinesApi = {
 };
 export const s0MfgSopFileTypesApi = crud(`${mfg}/sop-file-types`);
 export const s0MfgElementParamsApi = crud(`${mfg}/element-params`);
-export const s0MfgPersonSkillsApi = crud(`${mfg}/person-skills`);
+
+export interface S0PersonSkillOptionRow {
+	value: string;
+	label: string;
+	code: string;
+	name: string;
+	skillLevel?: string | null;
+	companyRefId: string;
+	factoryRefId: string;
+	isEnabled: boolean;
+}
+
+export interface S0PersonSkillOptionsQuery {
+	companyRefId?: string;
+	factoryRefId?: string;
+	keyword?: string;
+	isEnabled?: boolean;
+	limit?: number;
+}
+
+const personSkillsBase = `${mfg}/person-skills`;
+export const s0MfgPersonSkillsApi = {
+	...crud(personSkillsBase),
+	options: (params?: S0PersonSkillOptionsQuery) =>
+		service.get<S0PersonSkillOptionRow[]>(`${personSkillsBase}/options`, { params }).then(unwrap),
+};
 export const s0MfgWorkCentersApi = crud(`${mfg}/work-centers`);
 export const s0MfgLineMaterialsApi = crud(`${mfg}/line-materials`);
 export const s0MfgProcessFlowCardsApi = crud(`${mfg}/process-flow-cards`);

+ 55 - 6
Web/src/views/aidop/s0/manufacturing/PersonSkillAssignmentList.vue

@@ -11,7 +11,15 @@
 				<el-input v-model="query.employee" clearable style="width: 140px" />
 			</el-form-item>
 			<el-form-item label="技能编码">
-				<el-input v-model="query.skillNo" clearable style="width: 140px" />
+				<el-select
+					v-model="query.skillNo"
+					filterable
+					clearable
+					placeholder="请选择技能编码"
+					style="width: 220px"
+				>
+					<el-option v-for="opt in skillOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
+				</el-select>
 			</el-form-item>
 			<el-form-item>
 				<el-button type="primary" @click="loadList">查询</el-button>
@@ -23,7 +31,11 @@
 		<el-table :data="rows" v-loading="loading" border stripe max-height="calc(100vh - 260px)">
 			<el-table-column prop="employee" label="人员编号" width="140" show-overflow-tooltip />
 			<el-table-column prop="site" label="工作组" width="120" show-overflow-tooltip />
-			<el-table-column prop="skillNo" label="技能编码" width="140" show-overflow-tooltip />
+			<el-table-column label="技能编码" width="180" show-overflow-tooltip>
+				<template #default="{ row }">
+					{{ skillNoDisplay(row.skillNo) }}
+				</template>
+			</el-table-column>
 			<el-table-column prop="skillLevel" label="技能等级" width="110" show-overflow-tooltip />
 			<el-table-column prop="efficiencyCoefficient" label="生产效率" width="110" align="right" />
 			<el-table-column prop="domain" label="工厂域" width="120" show-overflow-tooltip />
@@ -62,7 +74,9 @@
 					</el-col>
 					<el-col :span="12">
 						<el-form-item label="技能编码" prop="skillNo">
-							<el-input v-model="form.skillNo" />
+							<el-select v-model="form.skillNo" filterable clearable placeholder="请选择技能编码" style="width: 100%">
+								<el-option v-for="opt in skillOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
+							</el-select>
 						</el-form-item>
 					</el-col>
 					<el-col :span="12">
@@ -100,7 +114,17 @@ import { computed, onMounted, reactive, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
 import AidopDemoShell from '../../components/AidopDemoShell.vue';
-import { s0MfgEmpSkillsApi, type S0EmpSkillsUpsert } from '../api/s0ManufacturingApi';
+import {
+	s0MfgEmpSkillsApi,
+	s0MfgPersonSkillsApi,
+	type S0EmpSkillsUpsert,
+	type S0PersonSkillOptionRow,
+} from '../api/s0ManufacturingApi';
+
+const PERSON_SKILL_SCOPE = {
+	companyRefId: '1329900200001',
+	factoryRefId: '1329900200002',
+} as const;
 
 const route = useRoute();
 const pageTitle = computed(() => (route.meta?.title as string) || '人员技能维护');
@@ -138,10 +162,35 @@ const form = reactive({
 
 const rules: FormRules = {
 	employee: [{ required: true, message: '请填写人员编号', trigger: 'blur' }],
-	skillNo: [{ required: true, message: '请填写技能编码', trigger: 'blur' }],
+	skillNo: [{ required: true, message: '请选择技能编码', trigger: 'change' }],
 	domain: [{ required: true, message: '请填写工厂域', trigger: 'blur' }],
 };
 
+const skillOptions = ref<S0PersonSkillOptionRow[]>([]);
+const skillLabelMap = computed(() => {
+	const map = new Map<string, string>();
+	for (const opt of skillOptions.value) map.set(opt.value, opt.label);
+	return map;
+});
+function skillNoDisplay(code: string | null | undefined): string {
+	if (!code) return '';
+	return skillLabelMap.value.get(code) ?? code;
+}
+
+async function loadSkillOptions() {
+	try {
+		const list = await s0MfgPersonSkillsApi.options({
+			companyRefId: PERSON_SKILL_SCOPE.companyRefId,
+			factoryRefId: PERSON_SKILL_SCOPE.factoryRefId,
+			isEnabled: true,
+			limit: 100,
+		});
+		skillOptions.value = Array.isArray(list) ? list : [];
+	} catch {
+		skillOptions.value = [];
+	}
+}
+
 async function loadList() {
 	loading.value = true;
 	try {
@@ -252,7 +301,7 @@ function onDelete(row: Row) {
 }
 
 onMounted(async () => {
-	await loadList();
+	await Promise.all([loadList(), loadSkillOptions()]);
 });
 </script>
 

+ 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.125</AssemblyVersion>
-    <FileVersion>1.0.125</FileVersion>
-    <Version>1.0.125</Version>
+    <AssemblyVersion>1.0.126</AssemblyVersion>
+    <FileVersion>1.0.126</FileVersion>
+    <Version>1.0.126</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 35 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Controllers/S0/Manufacturing/AdoS0MfgPersonSkillsController.cs

@@ -44,6 +44,41 @@ public class AdoS0MfgPersonSkillsController : ControllerBase
         return item == null ? NotFound() : Ok(item);
     }
 
+    [HttpGet("options")]
+    public async Task<IActionResult> GetOptionsAsync(
+        [FromQuery] long? companyRefId,
+        [FromQuery] long? factoryRefId,
+        [FromQuery] string? keyword,
+        [FromQuery] bool? isEnabled,
+        [FromQuery] int? limit)
+    {
+        var enabledFilter = isEnabled ?? true;
+        var take = Math.Clamp(limit ?? 100, 1, 200);
+
+        var list = await _rep.AsQueryable()
+            .WhereIF(companyRefId.HasValue, x => x.CompanyRefId == companyRefId!.Value)
+            .WhereIF(factoryRefId.HasValue, x => x.FactoryRefId == factoryRefId!.Value)
+            .WhereIF(!string.IsNullOrWhiteSpace(keyword),
+                x => x.Code.Contains(keyword!) || x.Name.Contains(keyword!))
+            .Where(x => x.IsEnabled == enabledFilter)
+            .OrderBy(x => x.Code)
+            .Take(take)
+            .Select(x => new S0PersonSkillOptionRow
+            {
+                Value = x.Code,
+                Label = x.Code + " / " + x.Name,
+                Code = x.Code,
+                Name = x.Name,
+                SkillLevel = x.SkillLevel,
+                CompanyRefId = x.CompanyRefId,
+                FactoryRefId = x.FactoryRefId,
+                IsEnabled = x.IsEnabled
+            })
+            .ToListAsync();
+
+        return Ok(list);
+    }
+
     [HttpPost]
     public async Task<IActionResult> CreateAsync([FromBody] AdoS0MfgPersonSkillUpsertDto dto)
     {

+ 15 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Dto/S0/Manufacturing/AdoS0ManufacturingDtos.cs

@@ -431,6 +431,21 @@ public class AdoS0MfgPersonSkillUpsertDto
     public bool IsEnabled { get; set; } = true;
 }
 
+/// <summary>
+/// 人员技能字典下拉项。供「人员技能分配」页 SkillNo 字段联动使用,按 PersonSkill.Code 作为业务值。
+/// </summary>
+public class S0PersonSkillOptionRow
+{
+    public string Value { get; set; } = string.Empty;
+    public string Label { get; set; } = string.Empty;
+    public string Code { get; set; } = string.Empty;
+    public string Name { get; set; } = string.Empty;
+    public string? SkillLevel { get; set; }
+    public long CompanyRefId { get; set; }
+    public long FactoryRefId { get; set; }
+    public bool IsEnabled { get; set; }
+}
+
 public class AdoS0MfgPersonSkillAssignmentUpsertDto
 {
     public long CompanyRefId { get; set; }