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

feat(s0): N7 PriorityCode contract sync + UUID fix

- s0SalesApi.ts: id string, orderBy boolean, removed scope/company/factory fields
- OrderPriorityRuleList.vue: contract sync + @closed guard prevents race condition on re-open
- AdoS0OrderPriorityRulesController: assign Guid on Create (varchar(36) PK needs explicit UUID)
YY968XX 3 месяцев назад
Родитель
Сommit
6e696d450b

+ 7 - 18
Web/src/views/aidop/s0/api/s0SalesApi.ts

@@ -206,14 +206,12 @@ export interface S0ItemMasterUpsert {
 }
 
 export interface S0PriorityCodeRow {
-	id: number;
-	companyRefId?: string;
-	factoryRefId?: string;
+	id: string;
 	domainCode?: string | null;
 	descr: string;
 	value?: string | null;
 	priority: number;
-	orderByCode: number;
+	orderBy?: boolean | null;
 	/** 列表/详情展示:正序/倒序 */
 	orderByText?: string | null;
 	sourceTable?: string | null;
@@ -222,9 +220,6 @@ export interface S0PriorityCodeRow {
 	sourceId?: string | null;
 	valueType?: string | null;
 	valueId?: string | null;
-	scopeCustClass?: string | null;
-	scopeOrderType?: string | null;
-	scopeDueDaysMax?: number | null;
 	isActive: boolean;
 	createUser?: string | null;
 	createTime?: string;
@@ -233,23 +228,17 @@ export interface S0PriorityCodeRow {
 }
 
 export interface S0PriorityCodeUpsert {
-	companyRefId?: string;
-	factoryRefId?: string;
 	domainCode?: string;
 	descr: string;
 	value?: string;
 	priority: number;
-	/** 0=倒序,非0=正序 */
-	orderByCode: number;
+	orderBy?: boolean | null;
 	sourceTable?: string;
 	sourceColumn?: string;
 	sourceType?: string;
 	sourceId?: string;
 	valueType?: string;
 	valueId?: string;
-	scopeCustClass?: string;
-	scopeOrderType?: string;
-	scopeDueDaysMax?: number | null;
 	isActive: boolean;
 	createUser?: string;
 	updateUser?: string;
@@ -336,14 +325,14 @@ export const s0MaterialsApi = {
 export const s0OrderPriorityRulesApi = {
 	list: (params: Record<string, unknown>) =>
 		service.get<Paged<S0PriorityCodeRow>>('/api/s0/sales/order-priority-rules', { params }).then(unwrap),
-	get: (id: number) =>
+	get: (id: string) =>
 		service.get<S0PriorityCodeRow>(`/api/s0/sales/order-priority-rules/${id}`).then(unwrap),
 	create: (body: S0PriorityCodeUpsert) =>
 		service.post<S0PriorityCodeRow>('/api/s0/sales/order-priority-rules', body).then(unwrap),
-	update: (id: number, body: S0PriorityCodeUpsert) =>
+	update: (id: string, body: S0PriorityCodeUpsert) =>
 		service.put<S0PriorityCodeRow>(`/api/s0/sales/order-priority-rules/${id}`, body).then(unwrap),
-	delete: (id: number) => service.delete(`/api/s0/sales/order-priority-rules/${id}`).then(unwrap),
-	toggleEnabled: (id: number, body: PriorityCodeToggleActiveBody) =>
+	delete: (id: string) => service.delete(`/api/s0/sales/order-priority-rules/${id}`).then(unwrap),
+	toggleEnabled: (id: string, body: PriorityCodeToggleActiveBody) =>
 		service.patch<S0PriorityCodeRow>(`/api/s0/sales/order-priority-rules/${id}/toggle-enabled`, body).then(unwrap),
 };
 

+ 8 - 131
Web/src/views/aidop/s0/sales/OrderPriorityRuleList.vue

@@ -7,16 +7,6 @@
 			<el-form-item label="域编码">
 				<el-input v-model="query.domainCode" clearable style="width: 120px" />
 			</el-form-item>
-			<el-form-item label="公司">
-				<el-select v-model="query.companyRefId" clearable filterable placeholder="全部" style="width: 160px">
-					<el-option v-for="item in companyOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
-				</el-select>
-			</el-form-item>
-			<el-form-item label="工厂">
-				<el-select v-model="query.factoryRefId" clearable filterable placeholder="全部" style="width: 160px">
-					<el-option v-for="item in filteredFactoryOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
-				</el-select>
-			</el-form-item>
 			<el-form-item label="名称">
 				<el-input v-model="query.descr" clearable style="width: 140px" />
 			</el-form-item>
@@ -32,15 +22,6 @@
 			<el-form-item label="工单字段">
 				<el-input v-model="query.value" clearable style="width: 120px" />
 			</el-form-item>
-			<el-form-item label="客户类型">
-				<el-input v-model="query.scopeCustClass" clearable style="width: 120px" />
-			</el-form-item>
-			<el-form-item label="订单类型">
-				<el-input v-model="query.scopeOrderType" clearable style="width: 120px" />
-			</el-form-item>
-			<el-form-item label="交期上限(天)">
-				<el-input-number v-model="query.scopeDueDaysMax" :min="0" clearable controls-position="right" style="width: 130px" />
-			</el-form-item>
 			<el-form-item label="生效">
 				<el-select v-model="query.isActive" clearable placeholder="全部" style="width: 100px">
 					<el-option label="是" :value="true" />
@@ -65,9 +46,6 @@
 			<el-table-column prop="value" label="工单字段" width="120" show-overflow-tooltip />
 			<el-table-column prop="valueType" label="工单类型" width="100" show-overflow-tooltip />
 			<el-table-column prop="valueId" label="工单关联" width="110" show-overflow-tooltip />
-			<el-table-column prop="scopeCustClass" label="客户类型" width="110" show-overflow-tooltip />
-			<el-table-column prop="scopeOrderType" label="订单类型" width="110" show-overflow-tooltip />
-			<el-table-column prop="scopeDueDaysMax" label="交期上限(天)" width="120" align="right" show-overflow-tooltip />
 			<el-table-column label="生效" width="72" align="center">
 				<template #default="{ row }">
 					<el-tag :type="row.isActive ? 'success' : 'info'" size="small">{{ row.isActive ? '是' : '否' }}</el-tag>
@@ -96,23 +74,9 @@
 			/>
 		</div>
 
-		<el-dialog v-model="dialogVisible" :title="dialogTitle" width="760px" destroy-on-close @closed="resetForm">
+		<el-dialog v-model="dialogVisible" :title="dialogTitle" width="760px" destroy-on-close @closed="() => { if (!dialogVisible) resetForm(); }">
 			<el-form ref="formRef" :model="form" :rules="rules" label-width="130px">
 				<el-row :gutter="16">
-					<el-col :span="12">
-						<el-form-item label="公司" prop="companyRefId">
-							<el-select v-model="form.companyRefId" filterable style="width: 100%">
-								<el-option v-for="item in companyOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
-							</el-select>
-						</el-form-item>
-					</el-col>
-					<el-col :span="12">
-						<el-form-item label="工厂" prop="factoryRefId">
-							<el-select v-model="form.factoryRefId" filterable style="width: 100%" @change="syncDomainCodeFromFactory">
-								<el-option v-for="item in formFactoryOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
-							</el-select>
-						</el-form-item>
-					</el-col>
 					<el-col :span="12">
 						<el-form-item label="名称 Descr" prop="descr">
 							<el-input v-model="form.descr" />
@@ -125,9 +89,9 @@
 					</el-col>
 					<el-col :span="12">
 						<el-form-item label="排序 OrderBy">
-							<el-select v-model="form.orderByCode" style="width: 100%">
-								<el-option label="倒序 (0)" :value="0" />
-								<el-option label="正序 (1)" :value="1" />
+							<el-select v-model="form.orderBy" style="width: 100%">
+								<el-option label="正序" :value="true" />
+								<el-option label="倒序" :value="false" />
 							</el-select>
 						</el-form-item>
 					</el-col>
@@ -139,13 +103,6 @@
 					<el-col :span="12"><el-form-item label="工单字段 Value"><el-input v-model="form.value" /></el-form-item></el-col>
 					<el-col :span="12"><el-form-item label="工单类型"><el-input v-model="form.valueType" /></el-form-item></el-col>
 					<el-col :span="12"><el-form-item label="工单关联"><el-input v-model="form.valueId" /></el-form-item></el-col>
-					<el-col :span="12"><el-form-item label="客户类型"><el-input v-model="form.scopeCustClass" placeholder="可空=不限" /></el-form-item></el-col>
-					<el-col :span="12"><el-form-item label="订单类型"><el-input v-model="form.scopeOrderType" placeholder="可空=不限" /></el-form-item></el-col>
-					<el-col :span="12">
-						<el-form-item label="交期上限(天)">
-							<el-input-number v-model="form.scopeDueDaysMax" :min="0" clearable controls-position="right" style="width: 100%" />
-						</el-form-item>
-					</el-col>
 				</el-row>
 			</el-form>
 			<template #footer>
@@ -162,9 +119,7 @@ import { useRoute } from 'vue-router';
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
 import AidopDemoShell from '../../components/AidopDemoShell.vue';
 import {
-	loadOrgList,
 	s0OrderPriorityRulesApi,
-	type OrgOption,
 	type S0PriorityCodeRow,
 	type S0PriorityCodeUpsert,
 } from '../api/s0SalesApi';
@@ -175,16 +130,11 @@ const pageTitle = computed(() => (route.meta?.title as string) || '订单优先
 const query = reactive({
 	keyword: '',
 	domainCode: '',
-	companyRefId: undefined as string | undefined,
-	factoryRefId: undefined as string | undefined,
 	descr: '',
 	priority: undefined as number | undefined,
 	sourceTable: '',
 	sourceColumn: '',
 	value: '',
-	scopeCustClass: '',
-	scopeOrderType: '',
-	scopeDueDaysMax: undefined as number | undefined,
 	isActive: undefined as boolean | undefined,
 	page: 1,
 	pageSize: 20,
@@ -195,31 +145,23 @@ const rows = ref<S0PriorityCodeRow[]>([]);
 const total = ref(0);
 const dialogVisible = ref(false);
 const dialogTitle = ref('新增规则');
-const editingId = ref<number | null>(null);
+const editingId = ref<string | null>(null);
 const saving = ref(false);
 const formRef = ref<FormInstance>();
 
-const companyOptions = ref<OrgOption[]>([]);
-const factoryOptions = ref<OrgOption[]>([]);
-
 function emptyForm(): S0PriorityCodeUpsert {
 	return {
-		companyRefId: undefined,
-		factoryRefId: undefined,
 		domainCode: '',
 		descr: '',
 		value: '',
 		priority: 1,
-		orderByCode: 1,
+		orderBy: true,
 		sourceTable: '',
 		sourceColumn: '',
 		sourceType: '',
 		sourceId: '',
 		valueType: '',
 		valueId: '',
-		scopeCustClass: '',
-		scopeOrderType: '',
-		scopeDueDaysMax: null,
 		isActive: true,
 		createUser: '',
 		updateUser: '',
@@ -229,44 +171,9 @@ function emptyForm(): S0PriorityCodeUpsert {
 const form = reactive<S0PriorityCodeUpsert>(emptyForm());
 
 const rules: FormRules = {
-	companyRefId: [{ required: true, message: '请选择公司', trigger: 'change' }],
-	factoryRefId: [{ required: true, message: '请选择工厂', trigger: 'change' }],
 	descr: [{ required: true, message: '请填写名称', trigger: 'blur' }],
 };
 
-const filteredFactoryOptions = computed(() => {
-	if (!query.companyRefId) return factoryOptions.value;
-	return factoryOptions.value.filter((item) => item.pid === query.companyRefId);
-});
-
-const formFactoryOptions = computed(() => {
-	if (!form.companyRefId) return factoryOptions.value;
-	return factoryOptions.value.filter((item) => item.pid === form.companyRefId);
-});
-
-function syncDomainCodeFromFactory() {
-	const f = factoryOptions.value.find((item) => item.id === form.factoryRefId);
-	form.domainCode = f?.code ?? '';
-}
-
-watch(
-	() => form.companyRefId,
-	() => {
-		if (!formFactoryOptions.value.some((item) => item.id === form.factoryRefId)) {
-			form.factoryRefId = undefined;
-		}
-	}
-);
-
-watch(
-	() => query.companyRefId,
-	() => {
-		if (!filteredFactoryOptions.value.some((item) => item.id === query.factoryRefId)) {
-			query.factoryRefId = undefined;
-		}
-	}
-);
-
 async function loadList() {
 	loading.value = true;
 	try {
@@ -275,16 +182,11 @@ async function loadList() {
 			pageSize: query.pageSize,
 			keyword: query.keyword || undefined,
 			domainCode: query.domainCode || undefined,
-			companyRefId: query.companyRefId || undefined,
-			factoryRefId: query.factoryRefId || undefined,
 			descr: query.descr || undefined,
 			priority: query.priority,
 			sourceTable: query.sourceTable || undefined,
 			sourceColumn: query.sourceColumn || undefined,
 			value: query.value || undefined,
-			scopeCustClass: query.scopeCustClass || undefined,
-			scopeOrderType: query.scopeOrderType || undefined,
-			scopeDueDaysMax: query.scopeDueDaysMax,
 			isActive: query.isActive,
 		});
 		rows.value = data.list;
@@ -301,16 +203,11 @@ function resetQuery() {
 	Object.assign(query, {
 		keyword: '',
 		domainCode: '',
-		companyRefId: undefined,
-		factoryRefId: undefined,
 		descr: '',
 		priority: undefined,
 		sourceTable: '',
 		sourceColumn: '',
 		value: '',
-		scopeCustClass: '',
-		scopeOrderType: '',
-		scopeDueDaysMax: undefined,
 		isActive: undefined,
 		page: 1,
 	});
@@ -325,22 +222,17 @@ function resetForm() {
 
 function rowToForm(row: S0PriorityCodeRow) {
 	Object.assign(form, {
-		companyRefId: row.companyRefId,
-		factoryRefId: row.factoryRefId,
 		domainCode: row.domainCode ?? '',
 		descr: row.descr,
 		value: row.value ?? '',
 		priority: row.priority,
-		orderByCode: row.orderByCode,
+		orderBy: row.orderBy ?? true,
 		sourceTable: row.sourceTable ?? '',
 		sourceColumn: row.sourceColumn ?? '',
 		sourceType: row.sourceType ?? '',
 		sourceId: row.sourceId ?? '',
 		valueType: row.valueType ?? '',
 		valueId: row.valueId ?? '',
-		scopeCustClass: row.scopeCustClass ?? '',
-		scopeOrderType: row.scopeOrderType ?? '',
-		scopeDueDaysMax: row.scopeDueDaysMax ?? null,
 		isActive: row.isActive,
 		createUser: row.createUser ?? '',
 		updateUser: row.updateUser ?? '',
@@ -402,23 +294,8 @@ function toggleActive(row: S0PriorityCodeRow) {
 		.catch(() => {});
 }
 
-async function loadOptions() {
-	try {
-		const [companies, factories] = await Promise.all([loadOrgList('201'), loadOrgList('501')]);
-		companyOptions.value = companies;
-		factoryOptions.value = factories;
-		if (!companies.length || !factories.length) {
-			ElMessage.warning('公司或工厂组织数据加载失败,请检查组织种子');
-		}
-	} catch (e) {
-		console.warn('[OrderPriorityRule] loadOptions failed', e);
-		companyOptions.value = [];
-		factoryOptions.value = [];
-	}
-}
-
 onMounted(async () => {
-	await Promise.all([loadList(), loadOptions()]);
+	await loadList();
 });
 </script>
 

+ 1 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Controllers/S0/Sales/AdoS0OrderPriorityRulesController.cs

@@ -68,6 +68,7 @@ public class AdoS0OrderPriorityRulesController : ControllerBase
         var now = DateTime.Now;
         var entity = new AdoS0PriorityCode
         {
+            Id = Guid.NewGuid().ToString("D").ToUpperInvariant(),
             DomainCode = dto.DomainCode,
             Descr = dto.Descr ?? string.Empty,
             Value = dto.Value,