Files
OnboardXFront/src/views/biz/onboarding/entry-config/index.vue
T
2026-09-11 10:39:17 +08:00

260 lines
7.9 KiB
Vue

<template>
<div class="main-box config-container">
<el-tabs v-model="activeTab" class="config-tabs">
<el-tab-pane label="合同变量字典" name="variables">
<div class="tab-card-wrapper">
<VariableDefinitionPanel />
</div>
</el-tab-pane>
<el-tab-pane label="上传资料类型" name="materials">
<div class="tab-card-wrapper material-tab-wrapper">
<div class="toolbar">
<el-button v-auth="'onboardingEntryConfigAdd'" type="primary" icon="Plus" @click="openMaterialCreate">
新增资料类型
</el-button>
</div>
<el-table :data="materialTypes" border stripe height="100%">
<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="160">
<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" align="center">
<template #default="scope">
<el-button
v-auth="'onboardingEntryConfigEdit'"
link
type="primary"
icon="Edit"
:disabled="!canManage(scope.row)"
:title="disabledReason(scope.row)"
@click="openMaterialEdit(scope.row)"
>
编辑
</el-button>
<el-button
v-auth="'onboardingEntryConfigDelete'"
link
type="danger"
icon="Delete"
:disabled="!canManage(scope.row)"
:title="disabledReason(scope.row)"
@click="removeMaterial(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
<el-tab-pane label="入职模板" name="templates">
<div class="tab-card-wrapper">
<OnboardingTemplatePanel />
</div>
</el-tab-pane>
</el-tabs>
<!-- 资料类型弹窗 -->
<el-dialog v-model="materialVisible" :title="materialForm.id ? '编辑资料类型' : '新增资料类型'" width="560px" destroy-on-close>
<el-form :model="materialForm" label-width="120px" class="material-form">
<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="逗号分隔,如:png,jpg,jpeg,pdf" />
</el-form-item>
<el-form-item label="最大文件数">
<el-input-number v-model="materialForm.maxFileCount" :min="1" :max="10" />
<span class="unit-suffix">个</span>
</el-form-item>
<el-form-item label="单文件大小">
<el-input-number v-model="materialForm.maxFileSizeMb" :min="1" :max="100" />
<span class="unit-suffix">MB</span>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="materialForm.status">
<el-radio label="enable">启用</el-radio>
<el-radio label="disable">停用</el-radio>
</el-radio-group>
</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>
</div>
</template>
<script setup lang="ts" name="onboardingEntryConfig">
import { onMounted, reactive, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
OnboardingMaterialType,
onboardingTaskApi
} from "@/api/modules/biz/onboarding";
import { isMessageBoxConfirmed } from "@/utils/messageBox";
import OnboardingTemplatePanel from "./components/OnboardingTemplatePanel.vue";
import VariableDefinitionPanel from "./components/VariableDefinitionPanel.vue";
import { useOnboardingPermission } from "@/utils/onboardingPermission";
const { canManage, disabledReason } = useOnboardingPermission("onboardingEntryConfigManageAll");
const activeTab = ref("variables");
const materialTypes = ref<OnboardingMaterialType[]>([]);
const materialVisible = ref(false);
const materialForm = reactive<Partial<OnboardingMaterialType>>({
materialCode: "",
materialName: "",
allowedExtensions: "png,jpg,jpeg,pdf",
maxFileCount: 3,
maxFileSizeMb: 10,
status: "enable"
});
async function loadMaterials() {
const res = await onboardingTaskApi.listMaterialTypes();
materialTypes.value = res.data || [];
}
function openMaterialCreate() {
Object.assign(materialForm, {
id: undefined,
materialCode: "",
materialName: "",
allowedExtensions: "png,jpg,jpeg,pdf",
maxFileCount: 3,
maxFileSizeMb: 10,
status: "enable"
});
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);
ElMessage.success("资料类型保存成功");
materialVisible.value = false;
await loadMaterials();
}
async function removeMaterial(row: OnboardingMaterialType) {
const confirmed = await isMessageBoxConfirmed(
ElMessageBox.confirm(`确认删除资料类型“${row.materialName}”吗?`, "删除确认", { type: "warning" })
);
if (!confirmed) return;
await onboardingTaskApi.deleteMaterialTypes([row.id!]);
ElMessage.success("删除成功");
await loadMaterials();
}
onMounted(() => {
loadMaterials();
});
</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;
height: 0;
overflow: hidden;
}
.config-tabs :deep(.el-tab-pane) {
height: 100%;
display: flex;
flex-direction: column;
}
.tab-card-wrapper {
height: 100%;
width: 100%;
background: #fff;
border-radius: 8px;
padding: 16px;
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
}
.material-tab-wrapper {
display: flex;
flex-direction: column;
}
.toolbar {
margin-bottom: 12px;
}
.material-form :deep(.el-form-item__label) {
white-space: nowrap;
}
.unit-suffix {
margin-left: 10px;
color: var(--el-text-color-secondary);
font-size: 13px;
}
</style>