From f183bfe5089af532b539360e40a312e74da8c2d6 Mon Sep 17 00:00:00 2001 From: fuenmao <980740792@qq.com> Date: Mon, 9 Nov 2026 17:08:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=96=B9=E5=BC=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useOnboardingScopeOptions.ts | 59 ++++ src/views/biz/onboarding/contract/index.vue | 129 +++----- src/views/biz/onboarding/employee/index.vue | 136 +++------ .../components/OnboardingTemplatePanel.vue | 123 +++----- .../biz/onboarding/entry-config/index.vue | 24 +- src/views/biz/onboarding/setup/index.vue | 21 +- src/views/biz/onboarding/task/index.vue | 135 +++------ tests/onboarding-scope-loading.test.mjs | 278 ++++++++++++++++++ 8 files changed, 510 insertions(+), 395 deletions(-) create mode 100644 src/hooks/useOnboardingScopeOptions.ts create mode 100644 tests/onboarding-scope-loading.test.mjs diff --git a/src/hooks/useOnboardingScopeOptions.ts b/src/hooks/useOnboardingScopeOptions.ts new file mode 100644 index 0000000..8b2b65a --- /dev/null +++ b/src/hooks/useOnboardingScopeOptions.ts @@ -0,0 +1,59 @@ +import { ref } from "vue"; +import { + onboardingTaskApi, + type OnboardingDepartmentOption, + type OnboardingPositionOption +} from "@/api/modules/biz/onboarding"; + +type ScopeSelection = { companyId?: number; departmentId?: number; positionId?: number }; + +/** 公司、部门、岗位只按当前选择加载;过期响应不能覆盖新选择。 */ +export function useOnboardingScopeOptions( + getSelection: () => ScopeSelection | undefined, + syncOptions?: () => void +) { + const departments = ref([]); + const positions = ref([]); + let companyRequest = 0; + let departmentRequest = 0; + + function reset() { + companyRequest++; + departmentRequest++; + departments.value = []; + positions.value = []; + const selection = getSelection(); + if (selection) { + selection.departmentId = undefined; + selection.positionId = undefined; + } + syncOptions?.(); + } + + async function onCompanyChange(companyId?: number) { + reset(); + if (!companyId) return; + const request = companyRequest; + const { data } = await onboardingTaskApi.listDepartments(companyId).catch(() => ({ data: [] })); + if (request !== companyRequest || getSelection()?.companyId !== companyId) return; + departments.value = data || []; + syncOptions?.(); + } + + async function onDepartmentChange(departmentId?: number) { + const request = ++departmentRequest; + positions.value = []; + const selection = getSelection(); + if (selection) selection.positionId = undefined; + syncOptions?.(); + const companyId = selection?.companyId; + if (!companyId || !departmentId) return; + const { data } = await onboardingTaskApi.listPositionsByDepartment(departmentId).catch(() => ({ data: [] })); + const current = getSelection(); + if (request !== departmentRequest || current?.companyId !== companyId || current?.departmentId !== departmentId) return; + positions.value = data || []; + syncOptions?.(); + } + + return { departments, positions, onCompanyChange, onDepartmentChange, reset }; +} diff --git a/src/views/biz/onboarding/contract/index.vue b/src/views/biz/onboarding/contract/index.vue index ec346f2..57c8862 100644 --- a/src/views/biz/onboarding/contract/index.vue +++ b/src/views/biz/onboarding/contract/index.vue @@ -5,6 +5,7 @@ title="签署材料模板列表" :columns="templateColumns" :request-api="onboardingTaskApi.templatePage" + @reset="resetSearchScope" > diff --git a/src/views/biz/onboarding/entry-config/index.vue b/src/views/biz/onboarding/entry-config/index.vue index 28d2b44..fd5f791 100644 --- a/src/views/biz/onboarding/entry-config/index.vue +++ b/src/views/biz/onboarding/entry-config/index.vue @@ -1,13 +1,13 @@  diff --git a/src/views/biz/onboarding/setup/index.vue b/src/views/biz/onboarding/setup/index.vue index 2d1efcb..535903e 100644 --- a/src/views/biz/onboarding/setup/index.vue +++ b/src/views/biz/onboarding/setup/index.vue @@ -2,7 +2,7 @@
- +
- +
- +