前端第一版
This commit is contained in:
@@ -0,0 +1,525 @@
|
||||
<template>
|
||||
<div class="main-box setup-container">
|
||||
<el-tabs v-model="activeTab" class="setup-tabs">
|
||||
<!-- 1. 入职公司管理 -->
|
||||
<el-tab-pane label="入职公司" name="company">
|
||||
<div class="table-wrapper">
|
||||
<ProTable
|
||||
ref="companyTable"
|
||||
title="入职公司列表"
|
||||
:columns="companyColumns"
|
||||
:request-api="onboardingTaskApi.companyPage"
|
||||
:search-col="5"
|
||||
>
|
||||
<template #tableHeader>
|
||||
<el-button type="primary" icon="Plus" @click="openCompanyCreate">
|
||||
新增入职公司
|
||||
</el-button>
|
||||
</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="openCompanyEdit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
|
||||
<el-button link type="danger" icon="Delete" @click="removeCompany(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 2. 入职岗位管理 -->
|
||||
<el-tab-pane label="入职岗位" name="position">
|
||||
<div class="table-wrapper">
|
||||
<ProTable
|
||||
ref="positionTable"
|
||||
title="入职岗位列表"
|
||||
:columns="positionColumns"
|
||||
:request-api="onboardingTaskApi.positionPage"
|
||||
:search-col="5"
|
||||
>
|
||||
<template #tableHeader>
|
||||
<el-button type="primary" icon="Plus" @click="openPositionCreate">
|
||||
新增入职岗位
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<template #companyId="scope">
|
||||
<el-tag effect="plain" type="primary">
|
||||
{{ 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="openPositionEdit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
|
||||
<el-button link type="danger" icon="Delete" @click="removePosition(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 新增 / 编辑弹窗 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="680px"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
>
|
||||
<el-form v-if="dialogKind === 'company'" :model="companyForm" label-width="140px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司编码" required>
|
||||
<el-input v-model="companyForm.companyCode" placeholder="如:TECH_CORP" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司简称/名称" required>
|
||||
<el-input v-model="companyForm.companyName" placeholder="如:总公司 / 科技分部" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="合同甲方全称" required>
|
||||
<el-input v-model="companyForm.legalName" placeholder="用于合同填写的法定主体全称" />
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="统一社会信用代码">
|
||||
<el-input v-model="companyForm.unifiedSocialCreditCode" placeholder="18位统一信用代码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="法定代表人">
|
||||
<el-input v-model="companyForm.legalRepresentative" placeholder="法定代表人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="companyForm.contactPhone" placeholder="企业联系电话" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" required>
|
||||
<el-select v-model="companyForm.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="companyForm.registeredAddress" placeholder="企业法定注册地址" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="companyForm.remark" type="textarea" :rows="2" placeholder="备注信息" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<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">
|
||||
<el-option
|
||||
v-for="company in companies"
|
||||
:key="company.id"
|
||||
:label="company.companyName"
|
||||
:value="company.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位编码" required>
|
||||
<el-input v-model="positionForm.positionCode" placeholder="如:DEV_FRONTEND" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位名称" required>
|
||||
<el-input v-model="positionForm.positionName" 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="positionForm.defaultContractYears" :min="1" :max="20" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认试用期(月)">
|
||||
<el-input-number v-model="positionForm.defaultProbationMonths" :min="0" :max="12" class="w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="状态" required>
|
||||
<el-select v-model="positionForm.status" class="w-full">
|
||||
<el-option label="启用" value="enable" />
|
||||
<el-option label="停用" value="disable" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="positionForm.remark" type="textarea" :rows="2" placeholder="备注信息" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="onboardingSetup">
|
||||
import { ref, reactive, computed, onMounted } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Plus, Edit, Delete } from "@element-plus/icons-vue";
|
||||
import {
|
||||
onboardingTaskApi,
|
||||
type OnboardingCompany,
|
||||
type OnboardingCompanyOption,
|
||||
type OnboardingPosition
|
||||
} from "@/api/modules/biz/onboarding";
|
||||
import type { ColumnProps, ProTableInstance, EnumProps } from "@/components/ProTable/interface";
|
||||
|
||||
const activeTab = ref("company");
|
||||
|
||||
const companyTable = ref<ProTableInstance>();
|
||||
const positionTable = ref<ProTableInstance>();
|
||||
|
||||
const companies = ref<OnboardingCompanyOption[]>([]);
|
||||
const companyOptions = computed<EnumProps[]>(() =>
|
||||
companies.value.map(c => ({
|
||||
label: c.companyName,
|
||||
value: c.id
|
||||
}))
|
||||
);
|
||||
|
||||
const getCompanyName = (companyId?: number) => {
|
||||
if (!companyId) return "-";
|
||||
const found = companies.value.find(c => c.id === companyId);
|
||||
return found ? found.companyName : String(companyId);
|
||||
};
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const dialogKind = ref<"company" | "position">("company");
|
||||
const editing = ref(false);
|
||||
|
||||
const emptyCompany = (): Partial<OnboardingCompany> => ({
|
||||
companyCode: "",
|
||||
companyName: "",
|
||||
legalName: "",
|
||||
unifiedSocialCreditCode: "",
|
||||
legalRepresentative: "",
|
||||
registeredAddress: "",
|
||||
contactPhone: "",
|
||||
status: "enable",
|
||||
remark: ""
|
||||
});
|
||||
|
||||
const emptyPosition = (): Partial<OnboardingPosition> => ({
|
||||
companyId: undefined,
|
||||
positionCode: "",
|
||||
positionName: "",
|
||||
defaultContractYears: 3,
|
||||
defaultProbationMonths: 3,
|
||||
status: "enable",
|
||||
remark: ""
|
||||
});
|
||||
|
||||
const companyForm = reactive<Partial<OnboardingCompany>>(emptyCompany());
|
||||
const positionForm = reactive<Partial<OnboardingPosition>>(emptyPosition());
|
||||
|
||||
const dialogTitle = computed(
|
||||
() => `${editing.value ? "编辑" : "新增"}${dialogKind.value === "company" ? "入职公司" : "入职岗位"}`
|
||||
);
|
||||
|
||||
const companyColumns: ColumnProps<OnboardingCompany>[] = [
|
||||
{
|
||||
prop: "companyCode",
|
||||
label: "公司编码",
|
||||
width: 140,
|
||||
search: { el: "input" }
|
||||
},
|
||||
{
|
||||
prop: "companyName",
|
||||
label: "公司名称",
|
||||
minWidth: 180,
|
||||
search: { el: "input" }
|
||||
},
|
||||
{
|
||||
prop: "legalName",
|
||||
label: "合同甲方全称",
|
||||
minWidth: 220
|
||||
},
|
||||
{
|
||||
prop: "unifiedSocialCreditCode",
|
||||
label: "统一社会信用代码",
|
||||
minWidth: 180
|
||||
},
|
||||
{
|
||||
prop: "legalRepresentative",
|
||||
label: "法定代表人",
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: "contactPhone",
|
||||
label: "联系电话",
|
||||
width: 140
|
||||
},
|
||||
{
|
||||
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: 200,
|
||||
enum: companyOptions,
|
||||
search: {
|
||||
el: "select",
|
||||
props: { filterable: true, placeholder: "请选择所属公司" }
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: "positionCode",
|
||||
label: "岗位编码",
|
||||
width: 150,
|
||||
search: { el: "input" }
|
||||
},
|
||||
{
|
||||
prop: "positionName",
|
||||
label: "岗位名称",
|
||||
minWidth: 180,
|
||||
search: { el: "input" }
|
||||
},
|
||||
{
|
||||
prop: "defaultContractYears",
|
||||
label: "默认合同年限",
|
||||
width: 130,
|
||||
align: "center",
|
||||
render: scope => `${scope.row.defaultContractYears || 3} 年`
|
||||
},
|
||||
{
|
||||
prop: "defaultProbationMonths",
|
||||
label: "默认试用期",
|
||||
width: 130,
|
||||
align: "center",
|
||||
render: scope => `${scope.row.defaultProbationMonths ?? 0} 个月`
|
||||
},
|
||||
{
|
||||
prop: "status",
|
||||
label: "状态",
|
||||
width: 100,
|
||||
align: "center",
|
||||
enum: [
|
||||
{ label: "启用", value: "enable" },
|
||||
{ label: "停用", value: "disable" }
|
||||
],
|
||||
search: { el: "select" }
|
||||
},
|
||||
{
|
||||
prop: "operation",
|
||||
label: "操作",
|
||||
fixed: "right",
|
||||
width: 160
|
||||
}
|
||||
];
|
||||
|
||||
async function loadCompanies() {
|
||||
const { data } = await onboardingTaskApi.listCompanies();
|
||||
companies.value = data;
|
||||
}
|
||||
|
||||
function resetCompany() {
|
||||
Object.assign(companyForm, emptyCompany());
|
||||
}
|
||||
|
||||
function resetPosition() {
|
||||
Object.assign(positionForm, emptyPosition());
|
||||
}
|
||||
|
||||
function openCompanyCreate() {
|
||||
dialogKind.value = "company";
|
||||
editing.value = false;
|
||||
resetCompany();
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
function openPositionCreate() {
|
||||
dialogKind.value = "position";
|
||||
editing.value = false;
|
||||
resetPosition();
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
async function openCompanyEdit(row: OnboardingCompany) {
|
||||
const { data } = await onboardingTaskApi.companyDetail({ id: row.id });
|
||||
dialogKind.value = "company";
|
||||
editing.value = true;
|
||||
Object.assign(companyForm, data);
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
async function openPositionEdit(row: OnboardingPosition) {
|
||||
const { data } = await onboardingTaskApi.positionDetail({ id: row.id });
|
||||
dialogKind.value = "position";
|
||||
editing.value = true;
|
||||
Object.assign(positionForm, data);
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (dialogKind.value === "company") {
|
||||
if (!companyForm.companyCode || !companyForm.companyName || !companyForm.legalName) {
|
||||
return ElMessage.warning("请填写公司编码、公司名称和合同甲方全称");
|
||||
}
|
||||
|
||||
await onboardingTaskApi.saveCompany(companyForm, editing.value);
|
||||
companyTable.value?.refresh();
|
||||
await loadCompanies();
|
||||
} else {
|
||||
if (!positionForm.companyId || !positionForm.positionCode || !positionForm.positionName) {
|
||||
return ElMessage.warning("请填写所属公司、岗位编码和岗位名称");
|
||||
}
|
||||
|
||||
await onboardingTaskApi.savePosition(positionForm, editing.value);
|
||||
positionTable.value?.refresh();
|
||||
}
|
||||
|
||||
dialogVisible.value = false;
|
||||
ElMessage.success("保存成功");
|
||||
}
|
||||
|
||||
async function removeCompany(row: OnboardingCompany) {
|
||||
await ElMessageBox.confirm(`确认删除公司“${row.companyName}”?`, "删除确认", { type: "warning" });
|
||||
await onboardingTaskApi.deleteCompany([row.id]);
|
||||
companyTable.value?.refresh();
|
||||
await loadCompanies();
|
||||
}
|
||||
|
||||
async function removePosition(row: OnboardingPosition) {
|
||||
await ElMessageBox.confirm(`确认删除岗位“${row.positionName}”?`, "删除确认", { type: "warning" });
|
||||
await onboardingTaskApi.deletePosition([row.id]);
|
||||
positionTable.value?.refresh();
|
||||
}
|
||||
|
||||
onMounted(loadCompanies);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.setup-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.setup-tabs {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.setup-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);
|
||||
}
|
||||
|
||||
.setup-tabs :deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.setup-tabs :deep(.el-tab-pane) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-wrapper :deep(.table-search) {
|
||||
margin-bottom: 12px !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.table-wrapper :deep(.table-search .search-isOpen) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.table-wrapper :deep(.table-search .el-form-item) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.table-wrapper :deep(.table-search .el-select),
|
||||
.table-wrapper :deep(.table-search .el-input) {
|
||||
max-width: 200px !important;
|
||||
}
|
||||
|
||||
.table-wrapper :deep(.table-main) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user