652 lines
20 KiB
Vue
652 lines
20 KiB
Vue
<template>
|
|
<div class="main-box config-container">
|
|
<el-tabs v-model="activeTab" class="config-tabs">
|
|
<el-tab-pane label="动态填写字段" name="fields">
|
|
<div class="tab-card-wrapper">
|
|
<div class="toolbar">
|
|
<el-button type="primary" icon="Plus" @click="openFieldCreate">
|
|
新增字段
|
|
</el-button>
|
|
</div>
|
|
|
|
<el-table :data="fields" border stripe>
|
|
<el-table-column prop="fieldCode" label="字段编码" min-width="140" />
|
|
<el-table-column prop="fieldName" label="字段名称" min-width="150" />
|
|
<el-table-column prop="dataType" label="数据类型" width="120" align="center">
|
|
<template #default="scope">
|
|
<el-tag size="small" type="info">{{ scope.row.dataType }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="placeholder" label="提示语" min-width="160" />
|
|
<el-table-column prop="status" label="状态" width="100" align="center">
|
|
<template #default="scope">
|
|
<el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'">
|
|
{{ scope.row.status === 'enable' ? '启用' : '停用' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="操作" width="150" fixed="right">
|
|
<template #default="scope">
|
|
<el-button link type="primary" icon="Edit" @click="openFieldEdit(scope.row)">
|
|
编辑
|
|
</el-button>
|
|
|
|
<el-button link type="danger" icon="Delete" @click="removeField(scope.row)">
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="上传资料类型" name="materials">
|
|
<div class="tab-card-wrapper">
|
|
<div class="toolbar">
|
|
<el-button type="primary" icon="Plus" @click="openMaterialCreate">
|
|
新增资料类型
|
|
</el-button>
|
|
</div>
|
|
|
|
<el-table :data="materialTypes" border stripe>
|
|
<el-table-column prop="materialCode" label="资料编码" min-width="140" />
|
|
<el-table-column prop="materialName" label="资料名称" min-width="150" />
|
|
<el-table-column prop="allowedExtensions" label="允许扩展名" min-width="140">
|
|
<template #default="scope">
|
|
<code>{{ scope.row.allowedExtensions || '不限' }}</code>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="maxFileCount" label="最大数量" width="100" align="center" />
|
|
<el-table-column prop="maxFileSizeMb" label="最大限制(MB)" width="120" align="center" />
|
|
<el-table-column prop="status" label="状态" width="100" align="center">
|
|
<template #default="scope">
|
|
<el-tag size="small" :type="scope.row.status === 'enable' ? 'success' : 'info'">
|
|
{{ scope.row.status === 'enable' ? '启用' : '停用' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="操作" width="150" fixed="right">
|
|
<template #default="scope">
|
|
<el-button link type="primary" icon="Edit" @click="openMaterialEdit(scope.row)">
|
|
编辑
|
|
</el-button>
|
|
|
|
<el-button link type="danger" icon="Delete" @click="removeMaterial(scope.row)">
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="公司岗位要求" name="requirements">
|
|
<div class="tab-card-wrapper">
|
|
<el-alert title="请先选择公司,再为全公司或某个岗位分别配置员工必填信息和上传资料。" type="info" :closable="false" class="hint" />
|
|
|
|
<el-select v-model="selectedCompanyId" placeholder="请选择公司" filterable @change="loadRequirements">
|
|
<el-option v-for="company in companies" :key="company.id" :label="company.companyName" :value="company.id" />
|
|
</el-select>
|
|
|
|
<template v-if="selectedCompanyId">
|
|
<el-divider />
|
|
|
|
<el-tabs v-model="requirementTab">
|
|
<el-tab-pane label="填写字段要求" name="form">
|
|
<div class="toolbar">
|
|
<el-button type="primary" @click="openRequirementCreate('form')">
|
|
新增填写要求
|
|
</el-button>
|
|
</div>
|
|
|
|
<el-table :data="formRequirements" border>
|
|
<el-table-column label="字段">
|
|
<template #default="scope">
|
|
{{ fieldName(scope.row.fieldId) }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="岗位">
|
|
<template #default="scope">
|
|
{{ positionName(scope.row.positionId) }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="必填">
|
|
<template #default="scope">
|
|
{{ scope.row.required ? "是" : "否" }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="sortCode" label="排序" />
|
|
|
|
<el-table-column label="操作" width="140">
|
|
<template #default="scope">
|
|
<el-button link type="primary" @click="openRequirementEdit('form', scope.row)">
|
|
编辑
|
|
</el-button>
|
|
|
|
<el-button link type="danger" @click="removeRequirement('form', scope.row)">
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="上传资料要求" name="material">
|
|
<div class="toolbar">
|
|
<el-button type="primary" @click="openRequirementCreate('material')">
|
|
新增资料要求
|
|
</el-button>
|
|
</div>
|
|
|
|
<el-table :data="materialRequirements" border>
|
|
<el-table-column label="资料类型">
|
|
<template #default="scope">
|
|
{{ materialName(scope.row.materialTypeId) }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="岗位">
|
|
<template #default="scope">
|
|
{{ positionName(scope.row.positionId) }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="必传">
|
|
<template #default="scope">
|
|
{{ scope.row.required ? "是" : "否" }}
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="sortCode" label="排序" />
|
|
|
|
<el-table-column label="操作" width="140">
|
|
<template #default="scope">
|
|
<el-button link type="primary" @click="openRequirementEdit('material', scope.row)">
|
|
编辑
|
|
</el-button>
|
|
|
|
<el-button link type="danger" @click="removeRequirement('material', scope.row)">
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</template>
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
|
|
<el-dialog v-model="fieldVisible" :title="fieldForm.id ? '编辑字段' : '新增字段'" width="560px" destroy-on-close>
|
|
<el-form :model="fieldForm" label-width="110px">
|
|
<el-form-item label="字段编码" required>
|
|
<el-input v-model="fieldForm.fieldCode" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="字段名称" required>
|
|
<el-input v-model="fieldForm.fieldName" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="数据类型" required>
|
|
<el-select v-model="fieldForm.dataType">
|
|
<el-option label="文本" value="string" />
|
|
<el-option label="日期" value="date" />
|
|
<el-option label="整数" value="int" />
|
|
<el-option label="数字" value="number" />
|
|
<el-option label="金额" value="decimal" />
|
|
<el-option label="下拉选择" value="select" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="提示语">
|
|
<el-input v-model="fieldForm.placeholder" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="选项JSON">
|
|
<el-input v-model="fieldForm.optionsJson" type="textarea" placeholder="下拉/多选字段可填写选项JSON" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="校验规则">
|
|
<el-input v-model="fieldForm.validationRule" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="状态">
|
|
<el-select v-model="fieldForm.status">
|
|
<el-option label="启用" value="enable" />
|
|
<el-option label="停用" value="disable" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
<el-button @click="fieldVisible = false">
|
|
取消
|
|
</el-button>
|
|
|
|
<el-button type="primary" @click="saveField">
|
|
保存
|
|
</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="materialVisible" :title="materialForm.id ? '编辑资料类型' : '新增资料类型'" width="560px" destroy-on-close>
|
|
<el-form :model="materialForm" label-width="120px">
|
|
<el-form-item label="资料编码" required>
|
|
<el-input v-model="materialForm.materialCode" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="资料名称" required>
|
|
<el-input v-model="materialForm.materialName" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="允许扩展名">
|
|
<el-input v-model="materialForm.allowedExtensions" placeholder="如:jpg,png,pdf" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="最大文件数量">
|
|
<el-input-number v-model="materialForm.maxFileCount" :min="1" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="最大大小(MB)">
|
|
<el-input-number v-model="materialForm.maxFileSizeMb" :min="1" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="状态">
|
|
<el-select v-model="materialForm.status">
|
|
<el-option label="启用" value="enable" />
|
|
<el-option label="停用" value="disable" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
<el-button @click="materialVisible = false">
|
|
取消
|
|
</el-button>
|
|
|
|
<el-button type="primary" @click="saveMaterial">
|
|
保存
|
|
</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="requirementVisible" :title="requirementKind === 'form' ? '填写字段要求' : '上传资料要求'" width="560px"
|
|
destroy-on-close>
|
|
<el-form :model="requirementForm" label-width="110px">
|
|
<el-form-item label="所属公司">
|
|
<el-select v-model="requirementForm.companyId" disabled>
|
|
<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="适用岗位">
|
|
<el-select v-model="requirementForm.positionId" clearable placeholder="不选表示全公司">
|
|
<el-option v-for="position in positions" :key="position.id" :label="position.positionName"
|
|
:value="position.id" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item v-if="requirementKind === 'form'" label="填写字段" required>
|
|
<el-select v-model="requirementForm.fieldId">
|
|
<el-option v-for="field in enabledFields" :key="field.id" :label="field.fieldName" :value="field.id" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item v-else label="资料类型" required>
|
|
<el-select v-model="requirementForm.materialTypeId">
|
|
<el-option v-for="material in enabledMaterials" :key="material.id" :label="material.materialName"
|
|
:value="material.id" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="是否必填/必传">
|
|
<el-switch v-model="requirementForm.required" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="排序">
|
|
<el-input-number v-model="requirementForm.sortCode" :min="0" />
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
<el-button @click="requirementVisible = false">
|
|
取消
|
|
</el-button>
|
|
|
|
<el-button type="primary" @click="saveRequirement">
|
|
保存
|
|
</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts" name="onboardingEntryConfig">
|
|
import {
|
|
onboardingTaskApi,
|
|
type OnboardingCompanyOption,
|
|
type OnboardingFormField,
|
|
type OnboardingFormRequirement,
|
|
type OnboardingMaterialRequirement,
|
|
type OnboardingMaterialType,
|
|
type OnboardingPositionOption
|
|
} from "@/api/modules/biz/onboarding";
|
|
|
|
const activeTab = ref("fields");
|
|
const requirementTab = ref("form");
|
|
|
|
const fields = ref<OnboardingFormField[]>([]);
|
|
const materialTypes = ref<OnboardingMaterialType[]>([]);
|
|
const companies = ref<OnboardingCompanyOption[]>([]);
|
|
const positions = ref<OnboardingPositionOption[]>([]);
|
|
|
|
const formRequirements = ref<OnboardingFormRequirement[]>([]);
|
|
const materialRequirements = ref<OnboardingMaterialRequirement[]>([]);
|
|
|
|
const selectedCompanyId = ref<number>();
|
|
|
|
const fieldVisible = ref(false);
|
|
const materialVisible = ref(false);
|
|
const requirementVisible = ref(false);
|
|
|
|
const requirementKind = ref<"form" | "material">("form");
|
|
|
|
const fieldForm = reactive<Partial<OnboardingFormField>>({});
|
|
const materialForm = reactive<Partial<OnboardingMaterialType>>({});
|
|
const requirementForm = reactive<any>({});
|
|
|
|
const enabledFields = computed(() =>
|
|
fields.value.filter(item => item.status === "enable")
|
|
);
|
|
|
|
const enabledMaterials = computed(() =>
|
|
materialTypes.value.filter(item => item.status === "enable")
|
|
);
|
|
|
|
async function loadBase() {
|
|
const [
|
|
fieldResult,
|
|
materialResult,
|
|
companyResult
|
|
] = await Promise.all([
|
|
onboardingTaskApi.listFormFields(),
|
|
onboardingTaskApi.listMaterialTypes(),
|
|
onboardingTaskApi.listCompanies()
|
|
]);
|
|
|
|
fields.value = fieldResult.data;
|
|
materialTypes.value = materialResult.data;
|
|
companies.value = companyResult.data;
|
|
}
|
|
|
|
async function loadRequirements() {
|
|
if (!selectedCompanyId.value) return;
|
|
|
|
const [
|
|
formResult,
|
|
materialResult,
|
|
positionResult
|
|
] = await Promise.all([
|
|
onboardingTaskApi.listFormRequirements(selectedCompanyId.value),
|
|
onboardingTaskApi.listMaterialRequirements(selectedCompanyId.value),
|
|
onboardingTaskApi.listPositions(selectedCompanyId.value)
|
|
]);
|
|
|
|
formRequirements.value = formResult.data;
|
|
materialRequirements.value = materialResult.data;
|
|
positions.value = positionResult.data;
|
|
}
|
|
|
|
function resetField() {
|
|
Object.assign(fieldForm, {
|
|
id: undefined,
|
|
fieldCode: "",
|
|
fieldName: "",
|
|
dataType: "string",
|
|
placeholder: "",
|
|
optionsJson: "",
|
|
validationRule: "",
|
|
status: "enable"
|
|
});
|
|
}
|
|
|
|
function resetMaterial() {
|
|
Object.assign(materialForm, {
|
|
id: undefined,
|
|
materialCode: "",
|
|
materialName: "",
|
|
allowedExtensions: "",
|
|
maxFileCount: 1,
|
|
maxFileSizeMb: undefined,
|
|
status: "enable"
|
|
});
|
|
}
|
|
|
|
function openFieldCreate() {
|
|
resetField();
|
|
fieldVisible.value = true;
|
|
}
|
|
|
|
function openFieldEdit(row: OnboardingFormField) {
|
|
Object.assign(fieldForm, row);
|
|
fieldVisible.value = true;
|
|
}
|
|
|
|
async function saveField() {
|
|
if (
|
|
!fieldForm.fieldCode ||
|
|
!fieldForm.fieldName ||
|
|
!fieldForm.dataType
|
|
) {
|
|
return ElMessage.warning(
|
|
"请填写字段编码、名称和数据类型"
|
|
);
|
|
}
|
|
|
|
await onboardingTaskApi.saveFormField(fieldForm);
|
|
|
|
fieldVisible.value = false;
|
|
|
|
await loadBase();
|
|
}
|
|
|
|
function openMaterialCreate() {
|
|
resetMaterial();
|
|
materialVisible.value = true;
|
|
}
|
|
|
|
function openMaterialEdit(row: OnboardingMaterialType) {
|
|
Object.assign(materialForm, row);
|
|
materialVisible.value = true;
|
|
}
|
|
|
|
async function saveMaterial() {
|
|
if (
|
|
!materialForm.materialCode ||
|
|
!materialForm.materialName
|
|
) {
|
|
return ElMessage.warning(
|
|
"请填写资料编码和名称"
|
|
);
|
|
}
|
|
|
|
await onboardingTaskApi.saveMaterialType(materialForm);
|
|
|
|
materialVisible.value = false;
|
|
|
|
await loadBase();
|
|
}
|
|
|
|
async function removeField(row: OnboardingFormField) {
|
|
await ElMessageBox.confirm(
|
|
`确认删除字段“${row.fieldName}”?`,
|
|
"删除确认"
|
|
);
|
|
|
|
await onboardingTaskApi.deleteFormFields([row.id]);
|
|
|
|
await loadBase();
|
|
}
|
|
|
|
async function removeMaterial(row: OnboardingMaterialType) {
|
|
await ElMessageBox.confirm(
|
|
`确认删除资料类型“${row.materialName}”?`,
|
|
"删除确认"
|
|
);
|
|
|
|
await onboardingTaskApi.deleteMaterialTypes([row.id]);
|
|
|
|
await loadBase();
|
|
}
|
|
|
|
function resetRequirement() {
|
|
Object.assign(requirementForm, {
|
|
id: undefined,
|
|
companyId: selectedCompanyId.value,
|
|
positionId: undefined,
|
|
fieldId: undefined,
|
|
materialTypeId: undefined,
|
|
required: true,
|
|
sortCode: 0
|
|
});
|
|
}
|
|
|
|
function openRequirementCreate(
|
|
kind: "form" | "material"
|
|
) {
|
|
requirementKind.value = kind;
|
|
|
|
resetRequirement();
|
|
|
|
requirementVisible.value = true;
|
|
}
|
|
|
|
function openRequirementEdit(
|
|
kind: "form" | "material",
|
|
row: any
|
|
) {
|
|
requirementKind.value = kind;
|
|
|
|
Object.assign(requirementForm, row);
|
|
|
|
requirementVisible.value = true;
|
|
}
|
|
|
|
async function saveRequirement() {
|
|
if (
|
|
requirementKind.value === "form" &&
|
|
!requirementForm.fieldId
|
|
) {
|
|
return ElMessage.warning("请选择填写字段");
|
|
}
|
|
|
|
if (
|
|
requirementKind.value === "material" &&
|
|
!requirementForm.materialTypeId
|
|
) {
|
|
return ElMessage.warning("请选择资料类型");
|
|
}
|
|
|
|
if (requirementKind.value === "form") {
|
|
await onboardingTaskApi.saveFormRequirement(
|
|
requirementForm
|
|
);
|
|
} else {
|
|
await onboardingTaskApi.saveMaterialRequirement(
|
|
requirementForm
|
|
);
|
|
}
|
|
|
|
requirementVisible.value = false;
|
|
|
|
await loadRequirements();
|
|
}
|
|
|
|
async function removeRequirement(
|
|
kind: "form" | "material",
|
|
row: any
|
|
) {
|
|
await ElMessageBox.confirm(
|
|
"确认删除该要求?",
|
|
"删除确认"
|
|
);
|
|
|
|
if (kind === "form") {
|
|
await onboardingTaskApi.deleteFormRequirements([
|
|
row.id
|
|
]);
|
|
} else {
|
|
await onboardingTaskApi.deleteMaterialRequirements([
|
|
row.id
|
|
]);
|
|
}
|
|
|
|
await loadRequirements();
|
|
}
|
|
|
|
const fieldName = (id: number) =>
|
|
fields.value.find(item => item.id === id)?.fieldName || id;
|
|
|
|
const materialName = (id: number) =>
|
|
materialTypes.value.find(item => item.id === id)?.materialName || id;
|
|
|
|
const positionName = (id?: number) =>
|
|
!id
|
|
? "全公司"
|
|
: positions.value.find(item => item.id === id)?.positionName || id;
|
|
|
|
onMounted(loadBase);
|
|
</script>
|
|
|
|
<style scoped>
|
|
.config-container {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-sizing: border-box;
|
|
padding: 0 !important;
|
|
background: transparent !important;
|
|
}
|
|
|
|
.config-tabs {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: transparent;
|
|
}
|
|
|
|
.config-tabs :deep(.el-tabs__header) {
|
|
background: #fff;
|
|
padding: 10px 16px 0;
|
|
margin: 0 0 10px 0;
|
|
border-radius: 8px;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.config-tabs :deep(.el-tabs__content) {
|
|
flex: 1;
|
|
overflow: auto;
|
|
}
|
|
|
|
.tab-card-wrapper {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.toolbar {
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.hint {
|
|
margin-bottom: 14px;
|
|
}
|
|
</style> |