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

fix(s0): align contract review KPI node configuration

- 默认选中第一个工厂(私有云单工厂口径),解除请选择工厂对 KPI/PI 录入与同步开关的阻塞
- 列表收敛为单工厂 5 个父级节点(消除多工厂重复),新增父级节点/节点编码列
- 主列表节点可选中,下钻区改为节点驱动(parentStageCode 跟随选中节点,不再写死 feedback)
- 仅开放 KPI/PI 字段编辑(主:标准时长+启用;下钻:标准时长+顺序+启用),结构字段只读
- 移除新增/删除/新增下钻等结构性按钮
- chore: bump version Web 2.4.194
YY968XX 2 недель назад
Родитель
Сommit
4cf1ad3676
2 измененных файлов с 115 добавлено и 149 удалено
  1. 1 1
      Web/package.json
  2. 114 148
      Web/src/views/aidop/s0/sales/ContractReviewCycleList.vue

+ 1 - 1
Web/package.json

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

+ 114 - 148
Web/src/views/aidop/s0/sales/ContractReviewCycleList.vue

@@ -19,7 +19,7 @@
 				</el-select>
 			</el-form-item>
 			<el-form-item label="工厂">
-				<el-select v-model="query.factoryRefId" clearable filterable placeholder="全部" style="width: 180px">
+				<el-select v-model="query.factoryRefId" filterable placeholder="请选择工厂" style="width: 180px" @change="loadList">
 					<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>
@@ -35,13 +35,23 @@
 			<el-form-item>
 				<el-button type="primary" @click="loadList">查询</el-button>
 				<el-button @click="resetQuery">重置</el-button>
-				<el-button type="success" @click="openCreate">新增</el-button>
 			</el-form-item>
 		</el-form>
 
-		<el-table :data="rows" v-loading="loading" border stripe style="width: 100%" max-height="calc(100vh - 260px)">
-			<el-table-column prop="stageCode" label="阶段编码" width="160" show-overflow-tooltip />
-			<el-table-column prop="stageName" label="阶段名称" min-width="160" show-overflow-tooltip />
+		<el-table
+			ref="mainTableRef"
+			:data="rows"
+			v-loading="loading"
+			border
+			stripe
+			row-key="id"
+			highlight-current-row
+			style="width: 100%"
+			max-height="calc(100vh - 300px)"
+			@current-change="onStageSelect"
+		>
+			<el-table-column prop="stageName" label="父级节点" min-width="160" show-overflow-tooltip />
+			<el-table-column prop="stageCode" label="节点编码" width="160" show-overflow-tooltip />
 			<el-table-column prop="stdHours" label="标准时长(h)" width="120" align="right" />
 			<el-table-column prop="orderNo" label="顺序" width="80" align="center" />
 			<el-table-column label="启用" width="80" align="center">
@@ -51,13 +61,13 @@
 					</el-tag>
 				</template>
 			</el-table-column>
-			<el-table-column label="操作" width="200" fixed="right" align="center">
+			<el-table-column label="操作" width="240" fixed="right" align="center">
 				<template #default="{ row }">
-					<el-button link type="primary" @click="openEdit(row)">编辑</el-button>
-					<el-button link :type="row.isActive ? 'warning' : 'success'" @click="toggleActive(row)">
+					<el-button link type="primary" @click.stop="onStageSelect(row)">查看下钻</el-button>
+					<el-button link type="primary" @click.stop="openEdit(row)">编辑</el-button>
+					<el-button link :type="row.isActive ? 'warning' : 'success'" @click.stop="toggleActive(row)">
 						{{ row.isActive ? '禁用' : '启用' }}
 					</el-button>
-					<el-button link type="danger" @click="onDelete(row)">删除</el-button>
 				</template>
 			</el-table-column>
 		</el-table>
@@ -74,18 +84,17 @@
 			/>
 		</div>
 
-		<!-- ── 意见反馈下钻配置 ──────────────────────────────────────── -->
+		<!-- ── 子级节点:当前父节点 — 部门/组 PI 配置 ───────────────────── -->
 		<section class="breakdown-section">
 			<div class="breakdown-section__head">
-				<h3 class="breakdown-section__title">意见反馈 — 部门/组 PI 配置</h3>
+				<h3 class="breakdown-section__title">{{ breakdownTitle }}</h3>
 				<div class="breakdown-section__actions">
-					<el-button :disabled="!query.factoryRefId" @click="loadBreakdown">刷新</el-button>
-					<el-button type="success" :disabled="!query.factoryRefId" @click="openBreakdownCreate">新增下钻</el-button>
+					<el-button :disabled="!currentStageCode" @click="loadBreakdown">刷新</el-button>
 				</div>
 			</div>
 
-			<div v-if="!query.factoryRefId" class="breakdown-section__hint">
-				请先选择工厂后维护意见反馈下钻配置
+			<div v-if="!currentStageCode" class="breakdown-section__hint">
+				请选择上方父级节点查看其部门/组 PI 配置
 			</div>
 			<el-table
 				v-else
@@ -96,8 +105,8 @@
 				size="small"
 				style="width: 100%"
 			>
+				<el-table-column prop="groupName" label="子级节点(部门/组)" min-width="180" class-name="breakdown-section__wrap-cell" />
 				<el-table-column prop="groupCode" label="组编码" width="160" class-name="breakdown-section__wrap-cell" />
-				<el-table-column prop="groupName" label="组名称" min-width="160" class-name="breakdown-section__wrap-cell" />
 				<el-table-column prop="stdHours" label="标准时长(h)" width="130" align="right" />
 				<el-table-column prop="orderNo" label="顺序" width="80" align="center" />
 				<el-table-column label="是否启用" width="100" align="center">
@@ -107,49 +116,43 @@
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="操作" width="220" fixed="right" align="center">
+				<el-table-column label="操作" width="200" fixed="right" align="center">
 					<template #default="{ row }">
 						<el-button link type="primary" @click="openBreakdownEdit(row)">编辑</el-button>
 						<el-button link :type="row.isActive ? 'warning' : 'success'" @click="breakdownToggleActive(row)">
 							{{ row.isActive ? '禁用' : '启用' }}
 						</el-button>
-						<el-button link type="danger" @click="onBreakdownDelete(row)">删除</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
 		</section>
 
+		<!-- ── 父级节点 KPI/PI 编辑(结构字段只读) ─────────────────────── -->
 		<el-dialog v-model="dialogVisible" :title="dialogTitle" width="640px" destroy-on-close @closed="resetForm">
 			<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
 				<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-form-item label="公司">
+							<el-select v-model="form.companyRefId" disabled 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="syncDomainCode">
-								<el-option v-for="item in formFactoryOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
+						<el-form-item label="工厂">
+							<el-select v-model="form.factoryRefId" disabled style="width: 100%">
+								<el-option v-for="item in factoryOptions" :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="stageCode">
-							<el-select v-model="form.stageCode" filterable style="width: 100%" @change="onStageCodeChange">
-								<el-option label="意见评审" value="opinion_review" />
-								<el-option label="意见反馈" value="feedback" />
-								<el-option label="二次评审" value="second_review" />
-								<el-option label="领导意见" value="leader_opinion" />
-								<el-option label="合同盖章" value="sign" />
-							</el-select>
+						<el-form-item label="节点编码">
+							<el-input :model-value="form.stageCode" disabled />
 						</el-form-item>
 					</el-col>
 					<el-col :span="12">
-						<el-form-item label="阶段名称" prop="stageName">
-							<el-input v-model="form.stageName" />
+						<el-form-item label="节点名称">
+							<el-input v-model="form.stageName" disabled />
 						</el-form-item>
 					</el-col>
 					<el-col :span="12">
@@ -159,7 +162,7 @@
 					</el-col>
 					<el-col :span="12">
 						<el-form-item label="顺序">
-							<el-input-number v-model="form.orderNo" :min="1" style="width: 100%" />
+							<el-input-number v-model="form.orderNo" :min="1" style="width: 100%" disabled />
 						</el-form-item>
 					</el-col>
 					<el-col :span="12">
@@ -175,7 +178,7 @@
 			</template>
 		</el-dialog>
 
-		<!-- ── 下钻 新增/编辑 弹窗 ──────────────────────────────────── -->
+		<!-- ── 子级节点 KPI/PI 编辑(结构字段只读) ─────────────────────── -->
 		<el-dialog
 			v-model="breakdownDialogVisible"
 			:title="breakdownDialogTitle"
@@ -184,14 +187,14 @@
 			@closed="resetBreakdownForm"
 		>
 			<el-form ref="breakdownFormRef" :model="breakdownForm" :rules="breakdownRules" label-width="110px">
-				<el-form-item label="父阶段">
-					<el-input :model-value="STAGE_NAME_MAP[BREAKDOWN_PARENT_STAGE_CODE]" disabled />
+				<el-form-item label="父级节点">
+					<el-input :model-value="STAGE_NAME_MAP[breakdownForm.parentStageCode] ?? breakdownForm.parentStageCode" disabled />
 				</el-form-item>
-				<el-form-item label="组编码" prop="groupCode">
-					<el-input v-model="breakdownForm.groupCode" placeholder="例如:market" />
+				<el-form-item label="组编码">
+					<el-input v-model="breakdownForm.groupCode" disabled />
 				</el-form-item>
-				<el-form-item label="组名称" prop="groupName">
-					<el-input v-model="breakdownForm.groupName" placeholder="例如:市场部" />
+				<el-form-item label="组名称">
+					<el-input v-model="breakdownForm.groupName" disabled />
 				</el-form-item>
 				<el-form-item label="标准时长(h)" prop="stdHours">
 					<el-input-number v-model="breakdownForm.stdHours" :min="0" :step="0.1" :precision="2" style="width: 100%" />
@@ -212,9 +215,9 @@
 </template>
 
 <script setup lang="ts" name="aidopS0SalesContractReviewCycle">
-import { computed, onMounted, reactive, ref, watch } from 'vue';
+import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
-import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
+import { ElMessage, ElMessageBox, type FormInstance, type FormRules, type TableInstance } from 'element-plus';
 import AidopDemoShell from '../../components/AidopDemoShell.vue';
 import {
 	loadOrgList,
@@ -251,8 +254,9 @@ const query = reactive({
 const loading = ref(false);
 const rows = ref<S0ContractReviewCycleRow[]>([]);
 const total = ref(0);
+const mainTableRef = ref<TableInstance>();
 const dialogVisible = ref(false);
-const dialogTitle = ref('新增');
+const dialogTitle = ref('编辑');
 const editingId = ref<number | null>(null);
 const saving = ref(false);
 const formRef = ref<FormInstance>();
@@ -269,26 +273,26 @@ const syncBarText = computed(() => {
 	return syncEnabled.value ? '当前工厂配置已同步到 S8' : '当前工厂未同步';
 });
 
-// ── 意见反馈下钻配置 ───────────────────────────────────────────────────
-const BREAKDOWN_PARENT_STAGE_CODE = 'feedback';
+// ── 子级节点:当前选中父节点驱动的部门/组 PI 配置 ─────────────────────
+const currentStageCode = ref<string>('');
+const currentStageName = ref<string>('');
 const breakdownRows = ref<S0ContractReviewCycleBreakdownRow[]>([]);
 const breakdownLoading = ref(false);
 const breakdownDialogVisible = ref(false);
-const breakdownDialogTitle = ref('新增下钻');
+const breakdownDialogTitle = ref('编辑');
 const breakdownEditingId = ref<number | null>(null);
 const breakdownSaving = ref(false);
 const breakdownFormRef = ref<FormInstance>();
 
+const breakdownTitle = computed(() =>
+	currentStageName.value ? `${currentStageName.value} — 部门/组 PI 配置` : '部门/组 PI 配置'
+);
+
 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 emptyForm(): S0ContractReviewCycleUpsert {
 	return {
 		companyRefId: undefined,
@@ -306,11 +310,9 @@ function emptyForm(): S0ContractReviewCycleUpsert {
 
 const form = reactive<S0ContractReviewCycleUpsert>(emptyForm());
 
+// 仅 KPI/PI 字段参与校验;结构字段(工厂/阶段编码/名称/顺序)编辑态只读,不再校验。
 const rules: FormRules = {
-	companyRefId: [{ required: true, message: '请选择公司', trigger: 'change' }],
-	factoryRefId: [{ required: true, message: '请选择工厂', trigger: 'change' }],
-	stageCode: [{ required: true, message: '请选择阶段编码', trigger: 'change' }],
-	stageName: [{ required: true, message: '请填写阶段名称', trigger: 'blur' }],
+	stdHours: [{ required: true, message: '请填写标准时长', trigger: 'change' }],
 };
 
 function emptyBreakdownForm(): S0ContractReviewCycleBreakdownUpsert {
@@ -318,7 +320,7 @@ function emptyBreakdownForm(): S0ContractReviewCycleBreakdownUpsert {
 		companyRefId: undefined,
 		factoryRefId: undefined,
 		domainCode: '',
-		parentStageCode: BREAKDOWN_PARENT_STAGE_CODE,
+		parentStageCode: '',
 		groupCode: '',
 		groupName: '',
 		stdHours: 0,
@@ -332,41 +334,20 @@ function emptyBreakdownForm(): S0ContractReviewCycleBreakdownUpsert {
 const breakdownForm = reactive<S0ContractReviewCycleBreakdownUpsert>(emptyBreakdownForm());
 
 const breakdownRules: FormRules = {
-	groupCode: [{ required: true, message: '请填写组编码', trigger: 'blur' }],
-	groupName: [{ required: true, message: '请填写组名称', trigger: 'blur' }],
 	stdHours: [{ required: true, message: '请填写标准时长', trigger: 'change' }],
 };
 
-function syncDomainCode() {
-	const f = factoryOptions.value.find((item) => item.id === form.factoryRefId);
-	form.domainCode = f?.code ?? '';
-}
-
-function onStageCodeChange(val: string) {
-	if (STAGE_NAME_MAP[val]) {
-		form.stageName = STAGE_NAME_MAP[val];
-	}
-}
-
-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;
+			query.factoryRefId = filteredFactoryOptions.value[0]?.id;
 		}
 	}
 );
 
-// 工厂切换时重新读取该工厂的 sync flag 和意见反馈下钻(未选工厂时清空)
+// 工厂切换:重新读取该工厂的 sync flag 与当前父节点的子级配置
 watch(
 	() => query.factoryRefId,
 	() => {
@@ -381,6 +362,15 @@ async function loadOptions() {
 	factoryOptions.value = factories;
 }
 
+// 默认选中第一个工厂(私有云单工厂口径),公司随之带出,杜绝多工厂重复列表
+function applyDefaultFactory() {
+	if (query.factoryRefId) return;
+	const first = factoryOptions.value[0];
+	if (!first) return;
+	query.companyRefId = first.pid ?? query.companyRefId;
+	query.factoryRefId = first.id;
+}
+
 async function loadList() {
 	loading.value = true;
 	try {
@@ -394,19 +384,50 @@ async function loadList() {
 		});
 		rows.value = data.list;
 		total.value = data.total;
+		await nextTick();
+		syncCurrentStageSelection();
 	} catch {
 		rows.value = [];
 		total.value = 0;
+		clearStageSelection();
 	} finally {
 		loading.value = false;
 	}
 }
 
+// 列表刷新后保持/重建父节点选中:优先保留原选中,否则默认首行
+function syncCurrentStageSelection() {
+	if (!rows.value.length) {
+		clearStageSelection();
+		return;
+	}
+	const keep = rows.value.find((r) => r.stageCode === currentStageCode.value);
+	const target = keep ?? rows.value[0];
+	mainTableRef.value?.setCurrentRow(target);
+	currentStageCode.value = target.stageCode;
+	currentStageName.value = target.stageName;
+	void loadBreakdown();
+}
+
+function clearStageSelection() {
+	mainTableRef.value?.setCurrentRow(undefined);
+	currentStageCode.value = '';
+	currentStageName.value = '';
+	breakdownRows.value = [];
+}
+
+function onStageSelect(row: S0ContractReviewCycleRow | null) {
+	if (!row) return;
+	mainTableRef.value?.setCurrentRow(row);
+	if (currentStageCode.value === row.stageCode) return;
+	currentStageCode.value = row.stageCode;
+	currentStageName.value = row.stageName;
+	void loadBreakdown();
+}
+
 function resetQuery() {
 	Object.assign(query, {
 		domainCode: '',
-		companyRefId: undefined,
-		factoryRefId: undefined,
 		isActive: undefined,
 		page: 1,
 	});
@@ -419,12 +440,6 @@ function resetForm() {
 	formRef.value?.clearValidate();
 }
 
-function openCreate() {
-	resetForm();
-	dialogTitle.value = '新增合同评审周期';
-	dialogVisible.value = true;
-}
-
 function openEdit(row: S0ContractReviewCycleRow) {
 	resetForm();
 	editingId.value = row.id;
@@ -446,16 +461,12 @@ function openEdit(row: S0ContractReviewCycleRow) {
 
 async function submitForm() {
 	await formRef.value?.validate();
+	if (editingId.value === null) return;
 	saving.value = true;
 	try {
 		const payload: S0ContractReviewCycleUpsert = { ...form };
-		if (editingId.value) {
-			await s0ContractReviewCyclesApi.update(editingId.value, payload);
-			ElMessage.success('已保存');
-		} else {
-			await s0ContractReviewCyclesApi.create(payload);
-			ElMessage.success('已创建');
-		}
+		await s0ContractReviewCyclesApi.update(editingId.value, payload);
+		ElMessage.success('已保存');
 		dialogVisible.value = false;
 		await loadList();
 	} finally {
@@ -463,16 +474,6 @@ async function submitForm() {
 	}
 }
 
-function onDelete(row: S0ContractReviewCycleRow) {
-	ElMessageBox.confirm(`确定删除「${row.stageName}」?`, '确认', { type: 'warning' })
-		.then(async () => {
-			await s0ContractReviewCyclesApi.delete(row.id);
-			ElMessage.success('已删除');
-			await loadList();
-		})
-		.catch(() => {});
-}
-
 function toggleActive(row: S0ContractReviewCycleRow) {
 	const next = !row.isActive;
 	const actionText = next ? '启用' : '禁用';
@@ -489,7 +490,6 @@ function toggleActive(row: S0ContractReviewCycleRow) {
 
 async function loadSyncFlag() {
 	if (!query.factoryRefId) {
-		// 未选工厂:reset 到关闭状态;不发请求
 		syncEnabled.value = false;
 		return;
 	}
@@ -504,7 +504,6 @@ async function loadSyncFlag() {
 async function onSyncChange(next: boolean | string | number) {
 	const nextBool = next === true;
 	if (!query.factoryRefId || !query.companyRefId) {
-		// 双保险:模板已 disabled,但工厂被外部清空时回滚
 		syncEnabled.value = !nextBool;
 		ElMessage.warning('请先选择公司与工厂');
 		return;
@@ -528,10 +527,10 @@ async function onSyncChange(next: boolean | string | number) {
 	}
 }
 
-// ── 意见反馈下钻加载与 CRUD ─────────────────────────────────────────
+// ── 子级节点(部门/组 PI)加载与 KPI 编辑 ───────────────────────────
 
 async function loadBreakdown() {
-	if (!query.factoryRefId) {
+	if (!query.factoryRefId || !currentStageCode.value) {
 		breakdownRows.value = [];
 		return;
 	}
@@ -539,7 +538,7 @@ async function loadBreakdown() {
 	try {
 		const data = await s0ContractReviewCycleBreakdownsApi.list({
 			factoryRefId: query.factoryRefId,
-			parentStageCode: BREAKDOWN_PARENT_STAGE_CODE,
+			parentStageCode: currentStageCode.value,
 			page: 1,
 			pageSize: 100,
 		});
@@ -557,21 +556,6 @@ function resetBreakdownForm() {
 	breakdownFormRef.value?.clearValidate();
 }
 
-function openBreakdownCreate() {
-	if (!query.factoryRefId || !query.companyRefId) {
-		ElMessage.warning('请先选择公司与工厂');
-		return;
-	}
-	resetBreakdownForm();
-	const factory = factoryOptions.value.find((item) => item.id === query.factoryRefId);
-	breakdownForm.companyRefId = query.companyRefId;
-	breakdownForm.factoryRefId = query.factoryRefId;
-	breakdownForm.domainCode = factory?.code ?? '';
-	breakdownForm.orderNo = breakdownRows.value.length + 1;
-	breakdownDialogTitle.value = '新增下钻';
-	breakdownDialogVisible.value = true;
-}
-
 function openBreakdownEdit(row: S0ContractReviewCycleBreakdownRow) {
 	resetBreakdownForm();
 	breakdownEditingId.value = row.id;
@@ -594,16 +578,12 @@ function openBreakdownEdit(row: S0ContractReviewCycleBreakdownRow) {
 
 async function submitBreakdownForm() {
 	await breakdownFormRef.value?.validate();
+	if (breakdownEditingId.value === null) return;
 	breakdownSaving.value = true;
 	try {
 		const payload: S0ContractReviewCycleBreakdownUpsert = { ...breakdownForm };
-		if (breakdownEditingId.value !== null) {
-			await s0ContractReviewCycleBreakdownsApi.update(breakdownEditingId.value, payload);
-			ElMessage.success('已保存');
-		} else {
-			await s0ContractReviewCycleBreakdownsApi.create(payload);
-			ElMessage.success('已创建');
-		}
+		await s0ContractReviewCycleBreakdownsApi.update(breakdownEditingId.value, payload);
+		ElMessage.success('已保存');
 		breakdownDialogVisible.value = false;
 		await loadBreakdown();
 	} catch {
@@ -613,20 +593,6 @@ async function submitBreakdownForm() {
 	}
 }
 
-function onBreakdownDelete(row: S0ContractReviewCycleBreakdownRow) {
-	ElMessageBox.confirm(`确认删除该部门/组 PI 配置吗?「${row.groupName}」`, '确认', { type: 'warning' })
-		.then(async () => {
-			try {
-				await s0ContractReviewCycleBreakdownsApi.delete(row.id);
-				ElMessage.success('已删除');
-				await loadBreakdown();
-			} catch {
-				ElMessage.error('删除失败,请稍后重试');
-			}
-		})
-		.catch(() => {});
-}
-
 function breakdownToggleActive(row: S0ContractReviewCycleBreakdownRow) {
 	const next = !row.isActive;
 	const actionText = next ? '启用' : '禁用';
@@ -645,9 +611,9 @@ function breakdownToggleActive(row: S0ContractReviewCycleBreakdownRow) {
 
 onMounted(async () => {
 	await loadOptions();
+	applyDefaultFactory();
 	await loadList();
 	await loadSyncFlag();
-	await loadBreakdown();
 });
 </script>