代码优化

This commit is contained in:
fuenmao
2026-08-27 11:09:33 +08:00
parent c091fc92b6
commit 6d4ad7236f
7 changed files with 629 additions and 87 deletions
-34
View File
@@ -1,34 +0,0 @@
import { moduleRequest } from "@/api/request";
const http = moduleRequest("/open/onboarding/");
export const onboardingPublicApi = {
detail(token: string) {
return http.post("detail", { token });
},
saveEmployeeInfo(params: Record<string, unknown>) {
return http.post("save-employee-info", params);
},
saveDynamicValues(params: {
token: string;
values: Array<{
fieldId: number;
fieldValue: string;
}>;
}) {
return http.post("save-dynamic-values", params);
},
confirmContract(params: {
token: string;
taskContractId: number;
}) {
return http.post("confirm-contract", params);
},
submit(token: string) {
return http.post("submit", { token });
}
};
+90 -7
View File
@@ -9,10 +9,12 @@ export interface OnboardingTask {
id: number; id: number;
taskNo: string; taskNo: string;
companyId: number; companyId: number;
positionId: number;
onboardingTemplateId?: number;
companyName?: string; companyName?: string;
departmentId?: number;
departmentName?: string;
positionId: number;
positionName?: string; positionName?: string;
onboardingTemplateId?: number;
onboardingTemplateName?: string; onboardingTemplateName?: string;
taskStatus: string; taskStatus: string;
rejectReason?: string; rejectReason?: string;
@@ -34,6 +36,11 @@ export interface OnboardingCompanyOption {
companyName: string; companyName: string;
} }
export interface OnboardingDepartmentOption {
id: number;
departmentName: string;
}
export interface OnboardingPositionOption { export interface OnboardingPositionOption {
id: number; id: number;
positionName: string; positionName: string;
@@ -50,8 +57,21 @@ export interface OnboardingCompany extends OnboardingCompanyOption {
status: string; status: string;
} }
export interface OnboardingDepartment extends OnboardingDepartmentOption {
companyId: number;
companyName?: string;
departmentCode: string;
sortCode: number;
remark?: string;
status: string;
createTime?: string;
}
export interface OnboardingPosition extends OnboardingPositionOption { export interface OnboardingPosition extends OnboardingPositionOption {
companyId: number; companyId: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionCode: string; positionCode: string;
defaultContractYears?: number; defaultContractYears?: number;
defaultProbationMonths?: number; defaultProbationMonths?: number;
@@ -61,6 +81,12 @@ export interface OnboardingPosition extends OnboardingPositionOption {
export interface OnboardingContractTemplate { export interface OnboardingContractTemplate {
id: number; id: number;
companyId?: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionIds: number[];
positionNames?: string[];
templateCode: string; templateCode: string;
templateName: string; templateName: string;
contractType: string; contractType: string;
@@ -118,6 +144,8 @@ export interface OnboardingEmployee {
employeeNo?: string; employeeNo?: string;
employeeName: string; employeeName: string;
companyId: number; companyId: number;
departmentId?: number;
departmentName?: string;
positionId: number; positionId: number;
phone: string; phone: string;
idCardNumber: string; idCardNumber: string;
@@ -172,6 +200,8 @@ export interface OnboardingTemplate {
templateName: string; templateName: string;
companyId: number; companyId: number;
companyName?: string; companyName?: string;
departmentId: number;
departmentName?: string;
positionIds: number[]; positionIds: number[];
positionNames?: string[]; positionNames?: string[];
contracts: OnboardingTemplateContractConfig[]; contracts: OnboardingTemplateContractConfig[];
@@ -265,6 +295,12 @@ export const onboardingTaskApi = {
>("list-enabled"); >("list-enabled");
}, },
listDepartments(companyId: number) {
return moduleRequest("/biz/onboarding/department/").get<
OnboardingDepartmentOption[]
>("list-enabled", { companyId });
},
listPositions(companyId: number) { listPositions(companyId: number) {
return moduleRequest("/biz/onboarding/position/").get< return moduleRequest("/biz/onboarding/position/").get<
OnboardingPositionOption[] OnboardingPositionOption[]
@@ -301,12 +337,48 @@ export const onboardingTaskApi = {
); );
}, },
departmentPage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/department/").get<
ResPage<OnboardingDepartment>
>("page", params);
},
departmentDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/department/").get<OnboardingDepartment>(
"detail",
params
);
},
saveDepartment(
params: Partial<OnboardingDepartment>,
edit = false
) {
return moduleRequest("/biz/onboarding/department/").post(
edit ? "edit" : "add",
params
);
},
deleteDepartment(ids: number[]) {
return moduleRequest("/biz/onboarding/department/").post(
"delete",
{ ids }
);
},
positionPage(params: Record<string, unknown>) { positionPage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/position/").get< return moduleRequest("/biz/onboarding/position/").get<
ResPage<OnboardingPosition> ResPage<OnboardingPosition>
>("page", params); >("page", params);
}, },
listPositionsByDepartment(departmentId: number) {
return moduleRequest("/biz/onboarding/position/").get<
OnboardingPosition[]
>("list-by-department", { departmentId });
},
positionDetail(params: ReqId) { positionDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/position/").get<OnboardingPosition>( return moduleRequest("/biz/onboarding/position/").get<OnboardingPosition>(
"detail", "detail",
@@ -358,13 +430,27 @@ export const onboardingTaskApi = {
); );
}, },
listEnabledOnboardingTemplates(companyId: number, positionId: number) { listEnabledOnboardingTemplates(
companyId: number,
departmentId: number,
positionId: number
) {
return moduleRequest("/biz/onboarding/template/").get<OnboardingTemplate[]>( return moduleRequest("/biz/onboarding/template/").get<OnboardingTemplate[]>(
"list-enabled", "list-enabled",
{ companyId, positionId } { companyId, departmentId, positionId }
); );
}, },
listAvailableContractTemplates(params: {
companyId: number;
departmentId: number;
positionIds: number[];
}) {
return moduleRequest("/biz/onboarding/contract-template/").post<
OnboardingContractTemplate[]
>("list-available", params);
},
templatePage(params: Record<string, unknown>) { templatePage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/contract-template/").get< return moduleRequest("/biz/onboarding/contract-template/").get<
ResPage<OnboardingContractTemplate> ResPage<OnboardingContractTemplate>
@@ -555,9 +641,6 @@ export const onboardingPublicApi = {
saveEmployeeInfo(params: Record<string, unknown>) { saveEmployeeInfo(params: Record<string, unknown>) {
return publicHttp.post("save-employee-info", params); return publicHttp.post("save-employee-info", params);
}, },
saveMaterial(params: { token: string; materialTypeId: number; fileId: number }) {
return publicHttp.post("save-material", params);
},
confirmContract(params: { token: string; taskContractId: number }) { confirmContract(params: { token: string; taskContractId: number }) {
return publicHttp.post("confirm-contract", params); return publicHttp.post("confirm-contract", params);
}, },
+124 -5
View File
@@ -18,6 +18,14 @@
</el-tag> </el-tag>
</template> </template>
<template #positionNames="scope">
<el-space wrap>
<el-tag v-for="name in scope.row.positionNames || []" :key="name" size="small">
{{ name }}
</el-tag>
</el-space>
</template>
<template #status="scope"> <template #status="scope">
<el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'"> <el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'">
{{ scope.row.status === "enable" ? "启用" : "停用" }} {{ scope.row.status === "enable" ? "启用" : "停用" }}
@@ -43,11 +51,66 @@
<el-dialog <el-dialog
v-model="templateVisible" v-model="templateVisible"
:title="templateEditing ? '编辑合同模板' : '新增合同模板'" :title="templateEditing ? '编辑合同模板' : '新增合同模板'"
width="580px" width="720px"
destroy-on-close destroy-on-close
append-to-body append-to-body
> >
<el-form :model="templateForm" label-width="110px"> <el-form :model="templateForm" label-width="110px">
<el-form-item label="所属公司" required>
<el-select
v-model="templateForm.companyId"
filterable
class="w-full"
placeholder="请选择所属公司"
@change="onTemplateCompanyChange"
>
<el-option
v-for="company in companies"
:key="company.id"
:label="company.companyName"
:value="company.id"
/>
</el-select>
</el-form-item>
<el-form-item label="所属部门" required>
<el-select
v-model="templateForm.departmentId"
filterable
class="w-full"
placeholder="请先选择所属公司"
:disabled="!templateForm.companyId"
@change="onTemplateDepartmentChange"
>
<el-option
v-for="department in departments"
:key="department.id"
:label="department.departmentName"
:value="department.id"
/>
</el-select>
</el-form-item>
<el-form-item label="适用岗位" required>
<el-select
v-model="templateForm.positionIds"
multiple
filterable
collapse-tags
collapse-tags-tooltip
class="w-full"
placeholder="请选择该合同可适用的岗位"
:disabled="!templateForm.departmentId"
>
<el-option
v-for="position in positions"
:key="position.id"
:label="position.positionName"
:value="position.id"
/>
</el-select>
</el-form-item>
<el-form-item label="模板编码" required> <el-form-item label="模板编码" required>
<el-input v-model="templateForm.templateCode" placeholder="如:LABOR_CONTRACT" /> <el-input v-model="templateForm.templateCode" placeholder="如:LABOR_CONTRACT" />
</el-form-item> </el-form-item>
@@ -411,13 +474,16 @@
</template> </template>
<script setup lang="ts" name="onboardingContract"> <script setup lang="ts" name="onboardingContract">
import { computed, reactive, ref } from "vue"; import { computed, onMounted, reactive, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { Check } from "@element-plus/icons-vue"; import { Check } from "@element-plus/icons-vue";
import { import {
onboardingTaskApi, onboardingTaskApi,
type OnboardingCompanyOption,
type OnboardingContractTemplate, type OnboardingContractTemplate,
type OnboardingContractVersion, type OnboardingContractVersion,
type OnboardingDepartmentOption,
type OnboardingPositionOption,
type OnboardingTemplateVariable type OnboardingTemplateVariable
} from "@/api/modules/biz/onboarding"; } from "@/api/modules/biz/onboarding";
import type { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; import type { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
@@ -429,6 +495,9 @@ const drawerVisible = ref(false);
const drawerActiveTab = ref("versions"); const drawerActiveTab = ref("versions");
const templateVisible = ref(false); const templateVisible = ref(false);
const templateEditing = ref(false); const templateEditing = ref(false);
const companies = ref<OnboardingCompanyOption[]>([]);
const departments = ref<OnboardingDepartmentOption[]>([]);
const positions = ref<OnboardingPositionOption[]>([]);
const versions = ref<OnboardingContractVersion[]>([]); const versions = ref<OnboardingContractVersion[]>([]);
const versionVisible = ref(false); const versionVisible = ref(false);
const variablesVisible = ref(false); const variablesVisible = ref(false);
@@ -455,6 +524,9 @@ const variableCounts = computed(() => {
}); });
const emptyTemplate = (): Partial<OnboardingContractTemplate> => ({ const emptyTemplate = (): Partial<OnboardingContractTemplate> => ({
companyId: undefined,
departmentId: undefined,
positionIds: [],
templateCode: "", templateCode: "",
templateName: "", templateName: "",
contractType: "", contractType: "",
@@ -488,8 +560,11 @@ const versionForm = reactive<Partial<OnboardingContractVersion>>(emptyVersion())
const variableForm = reactive<Partial<OnboardingTemplateVariable>>(emptyVariable()); const variableForm = reactive<Partial<OnboardingTemplateVariable>>(emptyVariable());
const templateColumns: ColumnProps<OnboardingContractTemplate>[] = [ const templateColumns: ColumnProps<OnboardingContractTemplate>[] = [
{ prop: "companyName", label: "所属公司", minWidth: 160 },
{ prop: "departmentName", label: "所属部门", minWidth: 140 },
{ prop: "templateCode", label: "模板编码", minWidth: 160, search: { el: "input" } }, { prop: "templateCode", label: "模板编码", minWidth: 160, search: { el: "input" } },
{ prop: "templateName", label: "模板名称", minWidth: 200, search: { el: "input" } }, { prop: "templateName", label: "模板名称", minWidth: 200, search: { el: "input" } },
{ prop: "positionNames", label: "适用岗位", minWidth: 200 },
{ prop: "contractType", label: "合同类型", width: 140, search: { el: "input" } }, { prop: "contractType", label: "合同类型", width: 140, search: { el: "input" } },
{ {
prop: "status", prop: "status",
@@ -508,6 +583,33 @@ const templateColumns: ColumnProps<OnboardingContractTemplate>[] = [
function resetTemplate() { function resetTemplate() {
Object.assign(templateForm, emptyTemplate()); Object.assign(templateForm, emptyTemplate());
departments.value = [];
positions.value = [];
}
async function loadCompanies() {
const { data } = await onboardingTaskApi.listCompanies();
companies.value = data || [];
}
async function onTemplateCompanyChange(companyId?: number) {
templateForm.departmentId = undefined;
templateForm.positionIds = [];
departments.value = [];
positions.value = [];
if (!companyId) return;
const { data } = await onboardingTaskApi.listDepartments(companyId);
departments.value = data || [];
}
async function onTemplateDepartmentChange(departmentId?: number) {
templateForm.positionIds = [];
positions.value = [];
if (!departmentId) return;
const { data } = await onboardingTaskApi.listPositionsByDepartment(departmentId);
positions.value = data || [];
} }
function resetVersion() { function resetVersion() {
@@ -551,12 +653,27 @@ async function openTemplateEdit(row: OnboardingContractTemplate) {
const { data } = await onboardingTaskApi.templateDetail({ id: row.id }); const { data } = await onboardingTaskApi.templateDetail({ id: row.id });
templateEditing.value = true; templateEditing.value = true;
Object.assign(templateForm, data); Object.assign(templateForm, data);
if (data.companyId) {
const departmentResult = await onboardingTaskApi.listDepartments(data.companyId);
departments.value = departmentResult.data || [];
}
if (data.departmentId) {
const positionResult = await onboardingTaskApi.listPositionsByDepartment(data.departmentId);
positions.value = positionResult.data || [];
}
templateVisible.value = true; templateVisible.value = true;
} }
async function saveTemplate() { async function saveTemplate() {
if (!templateForm.templateCode || !templateForm.templateName || !templateForm.contractType) { if (
return ElMessage.warning("请填写模板编码、名称和合同类型"); !templateForm.companyId
|| !templateForm.departmentId
|| !templateForm.positionIds?.length
|| !templateForm.templateCode
|| !templateForm.templateName
|| !templateForm.contractType
) {
return ElMessage.warning("请完整填写公司、部门、适用岗位及合同模板基本信息");
} }
await onboardingTaskApi.saveTemplate(templateForm, templateEditing.value); await onboardingTaskApi.saveTemplate(templateForm, templateEditing.value);
templateVisible.value = false; templateVisible.value = false;
@@ -688,6 +805,8 @@ async function saveVariable() {
await loadVariables(); await loadVariables();
ElMessage.success("变量已确认并保存"); ElMessage.success("变量已确认并保存");
} }
onMounted(loadCompanies);
</script> </script>
<style scoped> <style scoped>
@@ -807,4 +926,4 @@ async function saveVariable() {
padding: 2px 6px; padding: 2px 6px;
border-radius: 4px; border-radius: 4px;
} }
</style> </style>
+6 -1
View File
@@ -193,6 +193,11 @@ const columns: ColumnProps<OnboardingEmployee>[] = [
minWidth: 160, minWidth: 160,
search: { el: "input" } search: { el: "input" }
}, },
{
prop: "departmentName",
label: "所属部门",
minWidth: 140
},
{ {
prop: "entryDate", prop: "entryDate",
label: "入职日期", label: "入职日期",
@@ -368,4 +373,4 @@ function download(fileId: number) {
color: #dc2626; color: #dc2626;
margin-top: 4px; margin-top: 4px;
} }
</style> </style>
@@ -20,6 +20,7 @@
<el-table-column prop="templateCode" label="模板编码" min-width="150" /> <el-table-column prop="templateCode" label="模板编码" min-width="150" />
<el-table-column prop="templateName" label="模板名称" min-width="180" /> <el-table-column prop="templateName" label="模板名称" min-width="180" />
<el-table-column prop="companyName" label="所属公司" min-width="160" /> <el-table-column prop="companyName" label="所属公司" min-width="160" />
<el-table-column prop="departmentName" label="所属部门" min-width="150" />
<el-table-column label="适用岗位" min-width="220"> <el-table-column label="适用岗位" min-width="220">
<template #default="scope"> <template #default="scope">
<el-space wrap> <el-space wrap>
@@ -86,7 +87,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="10"> <el-col :xs="24" :sm="8">
<el-form-item label="所属公司" required> <el-form-item label="所属公司" required>
<el-select v-model="form.companyId" filterable class="full-width" placeholder="请选择公司" <el-select v-model="form.companyId" filterable class="full-width" placeholder="请选择公司"
@change="onCompanyChange"> @change="onCompanyChange">
@@ -94,10 +95,20 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="14"> <el-col :xs="24" :sm="8">
<el-form-item label="所属部门" required>
<el-select v-model="form.departmentId" filterable class="full-width" placeholder="请先选择公司"
:disabled="!form.companyId" @change="onDepartmentChange">
<el-option v-for="item in departments" :key="item.id" :label="item.departmentName"
:value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="8">
<el-form-item label="适用岗位" required> <el-form-item label="适用岗位" required>
<el-select v-model="form.positionIds" multiple filterable collapse-tags collapse-tags-tooltip <el-select v-model="form.positionIds" multiple filterable collapse-tags collapse-tags-tooltip
class="full-width" :disabled="!form.companyId" placeholder="请选择适用的岗位(可多选)"> class="full-width" :disabled="!form.departmentId" placeholder="请选择适用的岗位(可多选)"
@change="onPositionSelectionChange">
<el-option v-for="item in positions" :key="item.id" :label="item.positionName" :value="item.id" /> <el-option v-for="item in positions" :key="item.id" :label="item.positionName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -118,7 +129,8 @@
<span class="block-title">关联合同文件</span> <span class="block-title">关联合同文件</span>
<span class="block-subtitle">选择该岗位入职时需要员工确认与签署的合同模板及版本</span> <span class="block-subtitle">选择该岗位入职时需要员工确认与签署的合同模板及版本</span>
</div> </div>
<el-button type="primary" plain icon="Plus" size="small" @click="addContract"> <el-button type="primary" plain icon="Plus" size="small" :disabled="!form.positionIds.length"
@click="addContract">
添加合同文件 添加合同文件
</el-button> </el-button>
</div> </div>
@@ -220,6 +232,7 @@ import {
OnboardingCompany, OnboardingCompany,
OnboardingContractTemplate, OnboardingContractTemplate,
OnboardingContractVersion, OnboardingContractVersion,
OnboardingDepartmentOption,
OnboardingMaterialType, OnboardingMaterialType,
OnboardingPosition, OnboardingPosition,
OnboardingTemplate, OnboardingTemplate,
@@ -233,6 +246,7 @@ const rows = ref<OnboardingTemplate[]>([]);
const total = ref(0); const total = ref(0);
const companies = ref<OnboardingCompany[]>([]); const companies = ref<OnboardingCompany[]>([]);
const departments = ref<OnboardingDepartmentOption[]>([]);
const positions = ref<OnboardingPosition[]>([]); const positions = ref<OnboardingPosition[]>([]);
const contractTemplates = ref<OnboardingContractTemplate[]>([]); const contractTemplates = ref<OnboardingContractTemplate[]>([]);
const materialTypes = ref<OnboardingMaterialType[]>([]); const materialTypes = ref<OnboardingMaterialType[]>([]);
@@ -250,6 +264,7 @@ const form = reactive<OnboardingTemplate>({
templateCode: "", templateCode: "",
templateName: "", templateName: "",
companyId: 0, companyId: 0,
departmentId: 0,
description: "", description: "",
status: "enable", status: "enable",
positionIds: [], positionIds: [],
@@ -259,13 +274,11 @@ const form = reactive<OnboardingTemplate>({
}); });
async function loadBaseData() { async function loadBaseData() {
const [companyRes, templateRes, materialRes] = await Promise.all([ const [companyRes, materialRes] = await Promise.all([
onboardingTaskApi.companyPage({ pageNum: 1, pageSize: 100, status: "enable" }).catch(() => ({ data: { list: [] } })), onboardingTaskApi.companyPage({ pageNum: 1, pageSize: 100, status: "enable" }).catch(() => ({ data: { list: [] } })),
onboardingTaskApi.templatePage({ pageNum: 1, pageSize: 100, status: "enable" }).catch(() => ({ data: { list: [] } })),
onboardingTaskApi.listMaterialTypes().catch(() => ({ data: [] })) onboardingTaskApi.listMaterialTypes().catch(() => ({ data: [] }))
]); ]);
companies.value = companyRes.data?.list || []; companies.value = companyRes.data?.list || [];
contractTemplates.value = templateRes.data?.list || [];
materialTypes.value = materialRes.data || []; materialTypes.value = materialRes.data || [];
} }
@@ -288,13 +301,49 @@ function resetQuery() {
} }
async function onCompanyChange(companyId: number) { async function onCompanyChange(companyId: number) {
form.departmentId = undefined as any;
form.positionIds = []; form.positionIds = [];
form.contracts = [];
departments.value = [];
contractTemplates.value = [];
positions.value = [];
if (!companyId) { if (!companyId) {
positions.value = [];
return; return;
} }
const res = await onboardingTaskApi.positionPage({ companyId, pageNum: 1, pageSize: 100, status: "enable" }); const res = await onboardingTaskApi.listDepartments(companyId);
positions.value = res.data?.list || []; departments.value = res.data || [];
}
async function onDepartmentChange(departmentId: number) {
form.positionIds = [];
form.contracts = [];
positions.value = [];
contractTemplates.value = [];
if (!departmentId) return;
const res = await onboardingTaskApi.listPositionsByDepartment(departmentId);
positions.value = res.data || [];
}
async function onPositionSelectionChange() {
await loadAvailableContractTemplates();
}
async function loadAvailableContractTemplates() {
if (!form.companyId || !form.departmentId || !form.positionIds.length) {
contractTemplates.value = [];
form.contracts = [];
return;
}
const res = await onboardingTaskApi.listAvailableContractTemplates({
companyId: form.companyId,
departmentId: form.departmentId,
positionIds: form.positionIds
});
contractTemplates.value = res.data || [];
const availableIds = new Set(contractTemplates.value.map(item => item.id));
form.contracts = form.contracts.filter(item => availableIds.has(item.contractTemplateId));
} }
async function onContractTemplateChange(row: any) { async function onContractTemplateChange(row: any) {
@@ -310,6 +359,15 @@ async function loadContractVersions(templateId: number) {
} }
function addContract() { function addContract() {
if (!form.positionIds.length) {
ElMessage.warning("请先选择适用岗位");
return;
}
if (!contractTemplates.value.length) {
ElMessage.warning("当前公司、部门和岗位没有可用的合同模板");
return;
}
form.contracts.push({ form.contracts.push({
contractTemplateId: undefined as any, contractTemplateId: undefined as any,
contractTemplateVersionId: undefined as any, contractTemplateVersionId: undefined as any,
@@ -344,6 +402,7 @@ async function openCreate() {
templateCode: "", templateCode: "",
templateName: "", templateName: "",
companyId: undefined as any, companyId: undefined as any,
departmentId: undefined as any,
description: "", description: "",
status: "enable", status: "enable",
positionIds: [], positionIds: [],
@@ -351,7 +410,9 @@ async function openCreate() {
formFields: [], formFields: [],
materials: [] materials: []
}); });
departments.value = [];
positions.value = []; positions.value = [];
contractTemplates.value = [];
visible.value = true; visible.value = true;
} }
@@ -364,6 +425,7 @@ async function openEdit(row: OnboardingTemplate) {
templateCode: detail.templateCode, templateCode: detail.templateCode,
templateName: detail.templateName, templateName: detail.templateName,
companyId: detail.companyId, companyId: detail.companyId,
departmentId: detail.departmentId,
description: detail.description, description: detail.description,
status: detail.status, status: detail.status,
positionIds: detail.positionIds || [], positionIds: detail.positionIds || [],
@@ -383,9 +445,14 @@ async function openEdit(row: OnboardingTemplate) {
}); });
if (form.companyId) { if (form.companyId) {
const posRes = await onboardingTaskApi.positionPage({ companyId: form.companyId, pageNum: 1, pageSize: 100, status: "enable" }); const departmentRes = await onboardingTaskApi.listDepartments(form.companyId);
positions.value = posRes.data?.list || []; departments.value = departmentRes.data || [];
} }
if (form.departmentId) {
const positionRes = await onboardingTaskApi.listPositionsByDepartment(form.departmentId);
positions.value = positionRes.data || [];
}
await loadAvailableContractTemplates();
for (const contract of form.contracts) { for (const contract of form.contracts) {
if (contract.contractTemplateId) { if (contract.contractTemplateId) {
await loadContractVersions(contract.contractTemplateId); await loadContractVersions(contract.contractTemplateId);
@@ -395,8 +462,14 @@ async function openEdit(row: OnboardingTemplate) {
} }
async function save() { async function save() {
if (!form.templateCode || !form.templateName || !form.companyId || !form.positionIds.length) { if (
return ElMessage.warning("请完整填写模板编码、名称、公司及适用岗位"); !form.templateCode
|| !form.templateName
|| !form.companyId
|| !form.departmentId
|| !form.positionIds.length
) {
return ElMessage.warning("请完整填写模板编码、名称、公司、部门及适用岗位");
} }
if (!form.contracts.length || form.contracts.some(item => !item.contractTemplateId || !item.contractTemplateVersionId)) { if (!form.contracts.length || form.contracts.some(item => !item.contractTemplateId || !item.contractTemplateVersionId)) {
return ElMessage.warning("请完整选择至少一份合同模板及版本"); return ElMessage.warning("请完整选择至少一份合同模板及版本");
+256 -16
View File
@@ -1,4 +1,4 @@
<template> <template>
<div class="main-box setup-container"> <div class="main-box setup-container">
<el-tabs v-model="activeTab" class="setup-tabs"> <el-tabs v-model="activeTab" class="setup-tabs">
<!-- 1. 入职公司管理 --> <!-- 1. 入职公司管理 -->
@@ -36,7 +36,48 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- 2. 入职岗位管理 --> <!-- 2. 入职部门管理 -->
<el-tab-pane label="入职部门" name="department">
<div class="table-wrapper">
<ProTable
ref="departmentTable"
title="入职部门列表"
:columns="departmentColumns"
:request-api="onboardingTaskApi.departmentPage"
:search-col="5"
>
<template #tableHeader>
<el-button type="primary" icon="Plus" @click="openDepartmentCreate">
新增入职部门
</el-button>
</template>
<template #companyId="scope">
<el-tag effect="plain" type="primary">
{{ scope.row.companyName || getCompanyName(scope.row.companyId) }}
</el-tag>
</template>
<template #status="scope">
<el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'">
{{ scope.row.status === "enable" ? "启用" : "停用" }}
</el-tag>
</template>
<template #operation="scope">
<el-button link type="primary" icon="Edit" @click="openDepartmentEdit(scope.row)">
编辑
</el-button>
<el-button link type="danger" icon="Delete" @click="removeDepartment(scope.row)">
删除
</el-button>
</template>
</ProTable>
</div>
</el-tab-pane>
<!-- 3. 入职岗位管理 -->
<el-tab-pane label="入职岗位" name="position"> <el-tab-pane label="入职岗位" name="position">
<div class="table-wrapper"> <div class="table-wrapper">
<ProTable <ProTable
@@ -54,10 +95,17 @@
<template #companyId="scope"> <template #companyId="scope">
<el-tag effect="plain" type="primary"> <el-tag effect="plain" type="primary">
{{ getCompanyName(scope.row.companyId) }} {{ scope.row.companyName || getCompanyName(scope.row.companyId) }}
</el-tag> </el-tag>
</template> </template>
<template #departmentName="scope">
<el-tag v-if="scope.row.departmentName" effect="light" type="warning">
{{ scope.row.departmentName }}
</el-tag>
<span v-else class="text-gray-400">-</span>
</template>
<template #status="scope"> <template #status="scope">
<el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'"> <el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'">
{{ scope.row.status === "enable" ? "启用" : "停用" }} {{ scope.row.status === "enable" ? "启用" : "停用" }}
@@ -86,6 +134,7 @@
destroy-on-close destroy-on-close
append-to-body append-to-body
> >
<!-- 1. 公司表单 -->
<el-form v-if="dialogKind === 'company'" :model="companyForm" label-width="140px"> <el-form v-if="dialogKind === 'company'" :model="companyForm" label-width="140px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
@@ -142,9 +191,10 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form v-else :model="positionForm" label-width="140px"> <!-- 2. 部门表单 -->
<el-form v-else-if="dialogKind === 'department'" :model="departmentForm" label-width="140px">
<el-form-item label="所属公司" required> <el-form-item label="所属公司" required>
<el-select v-model="positionForm.companyId" placeholder="请选择所属公司" filterable class="w-full"> <el-select v-model="departmentForm.companyId" placeholder="请选择所属公司" filterable class="w-full">
<el-option <el-option
v-for="company in companies" v-for="company in companies"
:key="company.id" :key="company.id"
@@ -154,6 +204,77 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="部门编码" required>
<el-input v-model="departmentForm.departmentCode" placeholder="如:DEPT_TECH" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门名称" required>
<el-input v-model="departmentForm.departmentName" placeholder="如:技术研发部" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="显示排序">
<el-input-number v-model="departmentForm.sortCode" :min="1" :max="999" class="w-full" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" required>
<el-select v-model="departmentForm.status" class="w-full">
<el-option label="启用" value="enable" />
<el-option label="停用" value="disable" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
<el-input v-model="departmentForm.remark" type="textarea" :rows="2" placeholder="备注信息" />
</el-form-item>
</el-form>
<!-- 3. 岗位表单 -->
<el-form v-else :model="positionForm" label-width="140px">
<el-form-item label="所属公司" required>
<el-select
v-model="positionForm.companyId"
placeholder="请选择所属公司"
filterable
class="w-full"
@change="onPositionCompanyChange"
>
<el-option
v-for="company in companies"
:key="company.id"
:label="company.companyName"
:value="company.id"
/>
</el-select>
</el-form-item>
<el-form-item label="所属部门" required>
<el-select
v-model="positionForm.departmentId"
placeholder="请先选择所属公司"
filterable
clearable
class="w-full"
:disabled="!positionForm.companyId"
>
<el-option
v-for="dept in formDepartments"
:key="dept.id"
:label="dept.departmentName"
:value="dept.id"
/>
</el-select>
</el-form-item>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="岗位编码" required> <el-form-item label="岗位编码" required>
@@ -208,6 +329,8 @@ import {
onboardingTaskApi, onboardingTaskApi,
type OnboardingCompany, type OnboardingCompany,
type OnboardingCompanyOption, type OnboardingCompanyOption,
type OnboardingDepartment,
type OnboardingDepartmentOption,
type OnboardingPosition type OnboardingPosition
} from "@/api/modules/biz/onboarding"; } from "@/api/modules/biz/onboarding";
import type { ColumnProps, ProTableInstance, EnumProps } from "@/components/ProTable/interface"; import type { ColumnProps, ProTableInstance, EnumProps } from "@/components/ProTable/interface";
@@ -215,9 +338,12 @@ import type { ColumnProps, ProTableInstance, EnumProps } from "@/components/ProT
const activeTab = ref("company"); const activeTab = ref("company");
const companyTable = ref<ProTableInstance>(); const companyTable = ref<ProTableInstance>();
const departmentTable = ref<ProTableInstance>();
const positionTable = ref<ProTableInstance>(); const positionTable = ref<ProTableInstance>();
const companies = ref<OnboardingCompanyOption[]>([]); const companies = ref<OnboardingCompanyOption[]>([]);
const formDepartments = ref<OnboardingDepartmentOption[]>([]);
const companyOptions = computed<EnumProps[]>(() => const companyOptions = computed<EnumProps[]>(() =>
companies.value.map(c => ({ companies.value.map(c => ({
label: c.companyName, label: c.companyName,
@@ -232,7 +358,7 @@ const getCompanyName = (companyId?: number) => {
}; };
const dialogVisible = ref(false); const dialogVisible = ref(false);
const dialogKind = ref<"company" | "position">("company"); const dialogKind = ref<"company" | "department" | "position">("company");
const editing = ref(false); const editing = ref(false);
const emptyCompany = (): Partial<OnboardingCompany> => ({ const emptyCompany = (): Partial<OnboardingCompany> => ({
@@ -247,8 +373,18 @@ const emptyCompany = (): Partial<OnboardingCompany> => ({
remark: "" remark: ""
}); });
const emptyDepartment = (): Partial<OnboardingDepartment> => ({
companyId: undefined,
departmentCode: "",
departmentName: "",
sortCode: 99,
status: "enable",
remark: ""
});
const emptyPosition = (): Partial<OnboardingPosition> => ({ const emptyPosition = (): Partial<OnboardingPosition> => ({
companyId: undefined, companyId: undefined,
departmentId: undefined,
positionCode: "", positionCode: "",
positionName: "", positionName: "",
defaultContractYears: 3, defaultContractYears: 3,
@@ -258,11 +394,15 @@ const emptyPosition = (): Partial<OnboardingPosition> => ({
}); });
const companyForm = reactive<Partial<OnboardingCompany>>(emptyCompany()); const companyForm = reactive<Partial<OnboardingCompany>>(emptyCompany());
const departmentForm = reactive<Partial<OnboardingDepartment>>(emptyDepartment());
const positionForm = reactive<Partial<OnboardingPosition>>(emptyPosition()); const positionForm = reactive<Partial<OnboardingPosition>>(emptyPosition());
const dialogTitle = computed( const dialogTitle = computed(() => {
() => `${editing.value ? "编辑" : "新增"}${dialogKind.value === "company" ? "入职公司" : "入职岗位"}` const prefix = editing.value ? "编辑" : "新增";
); if (dialogKind.value === "company") return `${prefix}入职公司`;
if (dialogKind.value === "department") return `${prefix}入职部门`;
return `${prefix}入职岗位`;
});
const companyColumns: ColumnProps<OnboardingCompany>[] = [ const companyColumns: ColumnProps<OnboardingCompany>[] = [
{ {
@@ -316,7 +456,7 @@ const companyColumns: ColumnProps<OnboardingCompany>[] = [
} }
]; ];
const positionColumns: ColumnProps<OnboardingPosition>[] = [ const departmentColumns: ColumnProps<OnboardingDepartment>[] = [
{ {
prop: "companyId", prop: "companyId",
label: "所属公司", label: "所属公司",
@@ -327,6 +467,59 @@ const positionColumns: ColumnProps<OnboardingPosition>[] = [
props: { filterable: true, placeholder: "请选择所属公司" } props: { filterable: true, placeholder: "请选择所属公司" }
} }
}, },
{
prop: "departmentCode",
label: "部门编码",
width: 160,
search: { el: "input" }
},
{
prop: "departmentName",
label: "部门名称",
minWidth: 180,
search: { el: "input" }
},
{
prop: "sortCode",
label: "显示排序",
width: 110,
align: "center"
},
{
prop: "status",
label: "状态",
width: 100,
align: "center",
enum: [
{ label: "启用", value: "enable" },
{ label: "停用", value: "disable" }
],
search: { el: "select" }
},
{
prop: "operation",
label: "操作",
fixed: "right",
width: 160
}
];
const positionColumns: ColumnProps<OnboardingPosition>[] = [
{
prop: "companyId",
label: "所属公司",
minWidth: 180,
enum: companyOptions,
search: {
el: "select",
props: { filterable: true, placeholder: "请选择所属公司" }
}
},
{
prop: "departmentName",
label: "所属部门",
minWidth: 180
},
{ {
prop: "positionCode", prop: "positionCode",
label: "岗位编码", label: "岗位编码",
@@ -374,13 +567,31 @@ const positionColumns: ColumnProps<OnboardingPosition>[] = [
async function loadCompanies() { async function loadCompanies() {
const { data } = await onboardingTaskApi.listCompanies(); const { data } = await onboardingTaskApi.listCompanies();
companies.value = data; companies.value = data || [];
}
async function loadDepartmentsForCompany(companyId?: number) {
if (!companyId) {
formDepartments.value = [];
return;
}
const { data } = await onboardingTaskApi.listDepartments(companyId);
formDepartments.value = data || [];
}
async function onPositionCompanyChange(companyId?: number) {
positionForm.departmentId = undefined;
await loadDepartmentsForCompany(companyId);
} }
function resetCompany() { function resetCompany() {
Object.assign(companyForm, emptyCompany()); Object.assign(companyForm, emptyCompany());
} }
function resetDepartment() {
Object.assign(departmentForm, emptyDepartment());
}
function resetPosition() { function resetPosition() {
Object.assign(positionForm, emptyPosition()); Object.assign(positionForm, emptyPosition());
} }
@@ -392,10 +603,18 @@ function openCompanyCreate() {
dialogVisible.value = true; dialogVisible.value = true;
} }
function openDepartmentCreate() {
dialogKind.value = "department";
editing.value = false;
resetDepartment();
dialogVisible.value = true;
}
function openPositionCreate() { function openPositionCreate() {
dialogKind.value = "position"; dialogKind.value = "position";
editing.value = false; editing.value = false;
resetPosition(); resetPosition();
formDepartments.value = [];
dialogVisible.value = true; dialogVisible.value = true;
} }
@@ -407,11 +626,22 @@ async function openCompanyEdit(row: OnboardingCompany) {
dialogVisible.value = true; dialogVisible.value = true;
} }
async function openDepartmentEdit(row: OnboardingDepartment) {
const { data } = await onboardingTaskApi.departmentDetail({ id: row.id });
dialogKind.value = "department";
editing.value = true;
Object.assign(departmentForm, data);
dialogVisible.value = true;
}
async function openPositionEdit(row: OnboardingPosition) { async function openPositionEdit(row: OnboardingPosition) {
const { data } = await onboardingTaskApi.positionDetail({ id: row.id }); const { data } = await onboardingTaskApi.positionDetail({ id: row.id });
dialogKind.value = "position"; dialogKind.value = "position";
editing.value = true; editing.value = true;
Object.assign(positionForm, data); Object.assign(positionForm, data);
if (data?.companyId) {
await loadDepartmentsForCompany(data.companyId);
}
dialogVisible.value = true; dialogVisible.value = true;
} }
@@ -420,15 +650,19 @@ async function save() {
if (!companyForm.companyCode || !companyForm.companyName || !companyForm.legalName) { if (!companyForm.companyCode || !companyForm.companyName || !companyForm.legalName) {
return ElMessage.warning("请填写公司编码、公司名称和合同甲方全称"); return ElMessage.warning("请填写公司编码、公司名称和合同甲方全称");
} }
await onboardingTaskApi.saveCompany(companyForm, editing.value); await onboardingTaskApi.saveCompany(companyForm, editing.value);
companyTable.value?.refresh(); companyTable.value?.refresh();
await loadCompanies(); await loadCompanies();
} else if (dialogKind.value === "department") {
if (!departmentForm.companyId || !departmentForm.departmentCode || !departmentForm.departmentName) {
return ElMessage.warning("请填写所属公司、部门编码和部门名称");
}
await onboardingTaskApi.saveDepartment(departmentForm, editing.value);
departmentTable.value?.refresh();
} else { } else {
if (!positionForm.companyId || !positionForm.positionCode || !positionForm.positionName) { if (!positionForm.companyId || !positionForm.departmentId || !positionForm.positionCode || !positionForm.positionName) {
return ElMessage.warning("请填写所属公司、岗位编码和岗位名称"); return ElMessage.warning("请填写所属公司、所属部门、岗位编码和岗位名称");
} }
await onboardingTaskApi.savePosition(positionForm, editing.value); await onboardingTaskApi.savePosition(positionForm, editing.value);
positionTable.value?.refresh(); positionTable.value?.refresh();
} }
@@ -444,6 +678,12 @@ async function removeCompany(row: OnboardingCompany) {
await loadCompanies(); await loadCompanies();
} }
async function removeDepartment(row: OnboardingDepartment) {
await ElMessageBox.confirm(`确认删除部门“${row.departmentName}”?`, "删除确认", { type: "warning" });
await onboardingTaskApi.deleteDepartment([row.id]);
departmentTable.value?.refresh();
}
async function removePosition(row: OnboardingPosition) { async function removePosition(row: OnboardingPosition) {
await ElMessageBox.confirm(`确认删除岗位“${row.positionName}”?`, "删除确认", { type: "warning" }); await ElMessageBox.confirm(`确认删除岗位“${row.positionName}”?`, "删除确认", { type: "warning" });
await onboardingTaskApi.deletePosition([row.id]); await onboardingTaskApi.deletePosition([row.id]);
@@ -522,4 +762,4 @@ onMounted(loadCompanies);
.w-full { .w-full {
width: 100%; width: 100%;
} }
</style> </style>
+66 -10
View File
@@ -149,8 +149,8 @@
<span class="title-tip">请选择新员工入职的公司主体、岗位及适用的入职模板</span> <span class="title-tip">请选择新员工入职的公司主体、岗位及适用的入职模板</span>
</div> </div>
<el-row :gutter="20"> <el-row :gutter="16">
<el-col :xs="24" :sm="8"> <el-col :xs="24" :sm="6">
<el-form-item label="所属公司" required> <el-form-item label="所属公司" required>
<el-select <el-select
v-model="form.companyId" v-model="form.companyId"
@@ -164,14 +164,29 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="8"> <el-col :xs="24" :sm="6">
<el-form-item label="所属部门" required>
<el-select
v-model="form.departmentId"
filterable
placeholder="请选择所属部门"
class="full-width"
:disabled="!form.companyId"
@change="onDepartmentChange"
>
<el-option v-for="item in departments" :key="item.id" :label="item.departmentName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="6">
<el-form-item label="入职岗位" required> <el-form-item label="入职岗位" required>
<el-select <el-select
v-model="form.positionId" v-model="form.positionId"
filterable filterable
placeholder="请选择岗位" placeholder="请选择岗位"
class="full-width" class="full-width"
:disabled="!form.companyId" :disabled="!form.departmentId"
@change="onPositionChange" @change="onPositionChange"
> >
<el-option v-for="item in positions" :key="item.id" :label="item.positionName" :value="item.id" /> <el-option v-for="item in positions" :key="item.id" :label="item.positionName" :value="item.id" />
@@ -179,7 +194,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="8"> <el-col :xs="24" :sm="6">
<el-form-item label="入职模板" required> <el-form-item label="入职模板" required>
<el-select <el-select
v-model="form.onboardingTemplateId" v-model="form.onboardingTemplateId"
@@ -335,6 +350,7 @@
</div> </div>
<div class="banner-meta-row"> <div class="banner-meta-row">
<span>所属公司:<strong>{{ detail.task.companyName || '-' }}</strong></span> <span>所属公司:<strong>{{ detail.task.companyName || '-' }}</strong></span>
<span>所属部门:<strong>{{ detail.task.departmentName || '-' }}</strong></span>
<span>入职岗位:<strong>{{ detail.task.positionName || '-' }}</strong></span> <span>入职岗位:<strong>{{ detail.task.positionName || '-' }}</strong></span>
<span>入职模板:<strong>{{ detail.task.onboardingTemplateName || '-' }}</strong></span> <span>入职模板:<strong>{{ detail.task.onboardingTemplateName || '-' }}</strong></span>
</div> </div>
@@ -878,6 +894,7 @@ import {
import { import {
onboardingTaskApi, onboardingTaskApi,
type OnboardingCompanyOption, type OnboardingCompanyOption,
type OnboardingDepartmentOption,
type OnboardingPositionOption, type OnboardingPositionOption,
type OnboardingTemplate, type OnboardingTemplate,
type OnboardingContractTemplate, type OnboardingContractTemplate,
@@ -889,6 +906,7 @@ import type { ColumnProps, ProTableInstance } from "@/components/ProTable/interf
const proTable = ref<ProTableInstance>(); const proTable = ref<ProTableInstance>();
const companies = ref<OnboardingCompanyOption[]>([]); const companies = ref<OnboardingCompanyOption[]>([]);
const departments = ref<OnboardingDepartmentOption[]>([]);
const positions = ref<OnboardingPositionOption[]>([]); const positions = ref<OnboardingPositionOption[]>([]);
const onboardingTemplates = ref<OnboardingTemplate[]>([]); const onboardingTemplates = ref<OnboardingTemplate[]>([]);
const contractTemplates = ref<OnboardingContractTemplate[]>([]); const contractTemplates = ref<OnboardingContractTemplate[]>([]);
@@ -977,6 +995,7 @@ const statusCounts = reactive({
const form = reactive({ const form = reactive({
companyId: undefined as number | undefined, companyId: undefined as number | undefined,
departmentId: undefined as number | undefined,
positionId: undefined as number | undefined, positionId: undefined as number | undefined,
onboardingTemplateId: undefined as number | undefined, onboardingTemplateId: undefined as number | undefined,
contractVariables: [] as Array<{ contractVariables: [] as Array<{
@@ -998,6 +1017,21 @@ const columns: ColumnProps<OnboardingTask>[] = [
minWidth: 200, minWidth: 200,
search: { el: "input" } search: { el: "input" }
}, },
{
prop: "companyName",
label: "所属公司",
minWidth: 160
},
{
prop: "departmentName",
label: "所属部门",
minWidth: 140
},
{
prop: "positionName",
label: "入职岗位",
minWidth: 140
},
{ {
prop: "taskStatus", prop: "taskStatus",
label: "当前状态", label: "当前状态",
@@ -1230,11 +1264,26 @@ async function loadCompanies() {
} }
async function onCompanyChange(companyId: number) { async function onCompanyChange(companyId: number) {
form.departmentId = undefined;
form.positionId = undefined; form.positionId = undefined;
form.onboardingTemplateId = undefined; form.onboardingTemplateId = undefined;
form.contractVariables = []; form.contractVariables = [];
positions.value = [];
onboardingTemplates.value = []; onboardingTemplates.value = [];
const { data } = await onboardingTaskApi.listPositions(companyId); departments.value = [];
if (!companyId) return;
const { data } = await onboardingTaskApi.listDepartments(companyId);
departments.value = data || [];
}
async function onDepartmentChange(departmentId: number) {
form.positionId = undefined;
form.onboardingTemplateId = undefined;
form.contractVariables = [];
positions.value = [];
onboardingTemplates.value = [];
if (!departmentId) return;
const { data } = await onboardingTaskApi.listPositionsByDepartment(departmentId);
positions.value = data || []; positions.value = data || [];
} }
@@ -1242,8 +1291,12 @@ async function onPositionChange(positionId: number) {
form.onboardingTemplateId = undefined; form.onboardingTemplateId = undefined;
form.contractVariables = []; form.contractVariables = [];
onboardingTemplates.value = []; onboardingTemplates.value = [];
if (!form.companyId || !positionId) return; if (!form.companyId || !form.departmentId || !positionId) return;
const { data } = await onboardingTaskApi.listEnabledOnboardingTemplates(form.companyId, positionId); const { data } = await onboardingTaskApi.listEnabledOnboardingTemplates(
form.companyId,
form.departmentId,
positionId
);
onboardingTemplates.value = data || []; onboardingTemplates.value = data || [];
if (onboardingTemplates.value.length === 1) { if (onboardingTemplates.value.length === 1) {
form.onboardingTemplateId = onboardingTemplates.value[0].id; form.onboardingTemplateId = onboardingTemplates.value[0].id;
@@ -1282,19 +1335,21 @@ async function onOnboardingTemplateChange(templateId: number) {
function openCreate() { function openCreate() {
Object.assign(form, { Object.assign(form, {
companyId: undefined, companyId: undefined,
departmentId: undefined,
positionId: undefined, positionId: undefined,
onboardingTemplateId: undefined, onboardingTemplateId: undefined,
contractVariables: [], contractVariables: [],
remark: "" remark: ""
}); });
departments.value = [];
positions.value = []; positions.value = [];
onboardingTemplates.value = []; onboardingTemplates.value = [];
createVisible.value = true; createVisible.value = true;
} }
async function createTask() { async function createTask() {
if (!form.companyId || !form.positionId || !form.onboardingTemplateId) { if (!form.companyId || !form.departmentId || !form.positionId || !form.onboardingTemplateId) {
return ElMessage.warning("请选择所属公司、入职岗位和入职模板"); return ElMessage.warning("请选择所属公司、所属部门、入职岗位和入职模板");
} }
const missingVariable = form.contractVariables.find( const missingVariable = form.contractVariables.find(
item => item.required && isBlankContractVariableValue(item.variableValue) item => item.required && isBlankContractVariableValue(item.variableValue)
@@ -1318,6 +1373,7 @@ async function createTask() {
const linkUrl = `${location.origin}/#/onboarding/fill?token=${result.linkToken}`; const linkUrl = `${location.origin}/#/onboarding/fill?token=${result.linkToken}`;
const selectedCompany = companies.value.find(c => c.id === form.companyId)?.companyName || ""; const selectedCompany = companies.value.find(c => c.id === form.companyId)?.companyName || "";
const selectedDepartment = departments.value.find(d => d.id === form.departmentId)?.departmentName || "";
const selectedPosition = positions.value.find(p => p.id === form.positionId)?.positionName || ""; const selectedPosition = positions.value.find(p => p.id === form.positionId)?.positionName || "";
createdTaskInfo.value = { createdTaskInfo.value = {