<template>
|
<div class="app-container subsidy-config-container">
|
<el-row :gutter="20">
|
<!-- 左侧配置表单 -->
|
<el-col :span="16">
|
<el-card class="config-card"
|
shadow="hover">
|
<template #header>
|
<div class="card-header">
|
<div class="header-title">
|
<el-icon class="header-icon">
|
<Setting />
|
</el-icon>
|
<span>补贴标准配置</span>
|
</div>
|
<div class="header-ops">
|
<el-button type="primary"
|
:loading="loading"
|
@click="submitForm">
|
<el-icon>
|
<Check />
|
</el-icon> 保存配置
|
</el-button>
|
</div>
|
</div>
|
</template>
|
<el-form ref="formRef"
|
:model="form"
|
:rules="rules"
|
label-position="top"
|
class="subsidy-form">
|
<div class="config-section">
|
<div class="section-title">
|
<el-icon>
|
<Food />
|
</el-icon> 餐补设置
|
</div>
|
<el-row :gutter="40">
|
<el-col :span="12">
|
<el-form-item label="补贴标准金额"
|
style="margin-right:20px"
|
prop="mealAmount">
|
<el-input-number v-model="form.mealAmount"
|
:precision="2"
|
:step="1"
|
:min="0"
|
controls-position="right"
|
class="full-width-input" />
|
<span class="input-unit">元/天</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<div class="quick-info">
|
<div class="info-item">
|
<span class="label">适用对象:</span>
|
<el-tag size="small"
|
type="warning">回族员工</el-tag>
|
</div>
|
<div class="info-item">
|
<span class="label">计算范围:</span>
|
<span>白班 + 夜班</span>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
<el-divider />
|
<div class="config-section">
|
<div class="section-title">
|
<el-icon>
|
<Moon />
|
</el-icon> 夜班补助设置
|
</div>
|
<el-row :gutter="40">
|
<el-col :span="12">
|
<el-form-item label="补助标准金额"
|
style="margin-right:20px"
|
prop="nightAmount">
|
<el-input-number v-model="form.nightAmount"
|
:precision="2"
|
:step="1"
|
:min="0"
|
controls-position="right"
|
class="full-width-input" />
|
<span class="input-unit">元/天</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<div class="quick-info">
|
<div class="info-item">
|
<span class="label">适用对象:</span>
|
<el-tag size="small">全员(排班为夜班)</el-tag>
|
</div>
|
<div class="info-item">
|
<span class="label">计算范围:</span>
|
<span>仅限夜班</span>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
</el-form>
|
</el-card>
|
<!-- 计算示例卡片 -->
|
<el-card class="example-card"
|
shadow="never">
|
<template #header>
|
<div class="card-header-small">
|
<el-icon>
|
<InfoFilled />
|
</el-icon>
|
<span>薪资计算逻辑说明</span>
|
</div>
|
</template>
|
<div class="example-content">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<div class="example-box meal">
|
<h5>餐补计算示例</h5>
|
<p>若标准为 <strong>{{ form.mealAmount }}元/天</strong></p>
|
<p>某回族员工:白班10天,夜班10天</p>
|
<div class="formula">
|
计算:(10 + 10) * {{ form.mealAmount }} = <span>{{ (20 * form.mealAmount).toFixed(2) }}元</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="example-box night">
|
<h5>夜班补助计算示例</h5>
|
<p>若标准为 <strong>{{ form.nightAmount }}元/天</strong></p>
|
<p>某员工:当月夜班10天</p>
|
<div class="formula">
|
计算:10 * {{ form.nightAmount }} = <span>{{ (10 * form.nightAmount).toFixed(2) }}元</span>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
</el-card>
|
</el-col>
|
<!-- 右侧规则说明 -->
|
<el-col :span="8">
|
<el-card class="rule-card"
|
shadow="hover">
|
<template #header>
|
<div class="card-header">
|
<span>业务规则详情</span>
|
</div>
|
</template>
|
<el-scrollbar height="500px">
|
<div class="rule-item">
|
<div class="rule-header">
|
<span class="dot warning"></span>
|
<h6>关于餐补的标准与发放</h6>
|
</div>
|
<p>1. 系统将自动识别员工档案中的【民族】字段,仅对标注为“回族”的员工计算此项补贴。</p>
|
<p>2. 发放依据以考勤系统中的实际出勤天数为准,包含所有正常班次(白班、夜班)。</p>
|
<p>3. 请假、旷工等非出勤天数不计入计算范围。</p>
|
</div>
|
<el-divider />
|
<div class="rule-item">
|
<div class="rule-header">
|
<span class="dot primary"></span>
|
<h6>关于夜班补助的标准与发放</h6>
|
</div>
|
<p>1. 只要员工的排班班次被定义为“夜班”,且有实际出勤记录,即可享受此补助。</p>
|
<p>2. 补助按天计算,不区分岗位职级,统一执行此标准配置。</p>
|
<p>3. 此补助与餐补可同时享受(若符合餐补条件)。</p>
|
</div>
|
<el-alert title="配置生效说明"
|
type="info"
|
:closable="false"
|
show-icon
|
style="margin-top: 20px">
|
修改后的标准将在下一次执行“工资结算”任务时正式生效,不会影响已结算的历史薪资数据。
|
</el-alert>
|
</el-scrollbar>
|
</el-card>
|
</el-col>
|
</el-row>
|
</div>
|
</template>
|
|
<script setup name="SubsidyConfig">
|
import { ref, onMounted } from "vue";
|
import {
|
Setting,
|
Check,
|
RefreshRight,
|
Food,
|
Moon,
|
InfoFilled,
|
} from "@element-plus/icons-vue";
|
import {
|
listSubsidyConfiguration,
|
saveSubsidyConfiguration,
|
} from "@/api/personnelManagement/subsidyConfig.js";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
const formRef = ref(null);
|
const loading = ref(false);
|
|
const form = ref({
|
id: undefined,
|
mealAmount: 0,
|
nightAmount: 0,
|
tenantId: undefined,
|
createTime: undefined,
|
});
|
|
const rules = {
|
mealAmount: [{ required: true, message: "请输入餐补标准", trigger: "blur" }],
|
nightAmount: [
|
{ required: true, message: "请输入夜班补助标准", trigger: "blur" },
|
],
|
};
|
|
/** 查询配置 */
|
const getConfig = async () => {
|
try {
|
const res = await listSubsidyConfiguration();
|
if (res.data && res.data.length > 0) {
|
const config = res.data[0];
|
form.value = {
|
id: config.id,
|
mealAmount: config.mealAmount || 0,
|
nightAmount: config.nightAmount || 0,
|
tenantId: config.tenantId,
|
createTime: config.createTime,
|
};
|
}
|
} catch (error) {
|
console.error("获取配置失败", error);
|
}
|
};
|
|
/** 提交表单 */
|
const submitForm = async () => {
|
if (!formRef.value) return;
|
|
await formRef.value.validate(async valid => {
|
if (valid) {
|
loading.value = true;
|
try {
|
await saveSubsidyConfiguration(form.value);
|
ElMessage.success("标准配置已更新");
|
getConfig(); // 重新加载以获取可能的更新(如id)
|
} catch (error) {
|
console.error("保存失败", error);
|
} finally {
|
loading.value = false;
|
}
|
}
|
});
|
};
|
|
onMounted(() => {
|
getConfig();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.subsidy-config-container {
|
padding: 20px;
|
background-color: #f5f7fa;
|
min-height: calc(100vh - 84px);
|
|
.config-card {
|
margin-bottom: 20px;
|
border-radius: 8px;
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
|
.header-title {
|
display: flex;
|
align-items: center;
|
font-size: 18px;
|
font-weight: 600;
|
color: #303133;
|
|
.header-icon {
|
margin-right: 8px;
|
color: #409eff;
|
}
|
}
|
}
|
}
|
|
.subsidy-form {
|
padding: 10px 20px;
|
|
.config-section {
|
.section-title {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
font-size: 16px;
|
font-weight: 500;
|
margin-bottom: 20px;
|
color: #606266;
|
|
.el-icon {
|
color: #409eff;
|
}
|
}
|
}
|
|
.full-width-input {
|
width: 100% !important;
|
}
|
|
.input-unit {
|
position: absolute;
|
right: -45px;
|
top: 0;
|
color: #909399;
|
font-size: 14px;
|
}
|
|
.quick-info {
|
background: #fdf6ec;
|
border-radius: 4px;
|
padding: 15px;
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
gap: 10px;
|
|
.info-item {
|
font-size: 14px;
|
color: #666;
|
.label {
|
font-weight: 500;
|
}
|
}
|
}
|
}
|
|
.example-card {
|
background: #fff;
|
border: 1px dashed #dcdfe6;
|
|
.card-header-small {
|
display: flex;
|
align-items: center;
|
gap: 6px;
|
font-size: 14px;
|
color: #909399;
|
}
|
|
.example-box {
|
padding: 15px;
|
border-radius: 6px;
|
|
h5 {
|
margin: 0 0 10px 0;
|
font-size: 14px;
|
color: #303133;
|
}
|
|
p {
|
margin: 5px 0;
|
font-size: 13px;
|
color: #606266;
|
}
|
|
.formula {
|
margin-top: 10px;
|
padding-top: 10px;
|
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
font-size: 13px;
|
font-weight: bold;
|
|
span {
|
color: #f56c6c;
|
font-size: 16px;
|
}
|
}
|
|
&.meal {
|
background-color: #f0f9eb;
|
}
|
&.night {
|
background-color: #ecf5ff;
|
}
|
}
|
}
|
|
.rule-card {
|
height: 100%;
|
|
.rule-item {
|
padding: 5px 0;
|
|
.rule-header {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
margin-bottom: 10px;
|
|
.dot {
|
width: 8px;
|
height: 8px;
|
border-radius: 50%;
|
&.warning {
|
background: #e6a23c;
|
}
|
&.primary {
|
background: #409eff;
|
}
|
}
|
|
h6 {
|
margin: 0;
|
font-size: 15px;
|
color: #303133;
|
}
|
}
|
|
p {
|
font-size: 13px;
|
line-height: 1.8;
|
color: #606266;
|
margin: 5px 0 5px 16px;
|
}
|
}
|
}
|
}
|
|
:deep(.el-divider--horizontal) {
|
margin: 24px 0;
|
}
|
</style>
|