ZN
4 天以前 b461c6527e3a85e9af59e7680e792bcb5ffb6b7e
src/views/personnelManagement/socialSecuritySet/components/formDia.vue
@@ -15,7 +15,10 @@
          <el-col :span="8">
            <el-form-item label="适用人员:" prop="deptIds">
              <div class="dept-checkbox-wrap">
                <el-checkbox-group v-model="form.deptIds">
                <el-checkbox-group
                  v-model="form.deptIds"
                  :disabled="isDetail"
                >
                  <div
                    v-for="dept in deptList"
                    :key="dept.deptId"
@@ -41,7 +44,12 @@
                <el-icon class="card-collapse"><ArrowUp /></el-icon>
              </template>
              <el-form-item label="方案标题:" prop="title">
                <el-input v-model="form.title" placeholder="请输入" clearable />
                <el-input
                  v-model="form.title"
                  placeholder="请输入"
                  clearable
                  :disabled="isDetail"
                />
              </el-form-item>
              <el-form-item label="备注:" prop="remark">
                <el-input
@@ -50,6 +58,7 @@
                  :rows="2"
                  placeholder="请输入"
                  clearable
                  :disabled="isDetail"
                />
              </el-form-item>
            </el-card>
@@ -58,7 +67,12 @@
            <el-card class="form-card" shadow="never">
              <template #header>
                <span class="card-title"><span class="card-title-line">|</span> 保险类型</span>
                <el-button type="primary" size="small" @click="addInsuranceBenefit">
                <el-button
                  v-if="!isDetail"
                  type="primary"
                  size="small"
                  @click="addInsuranceBenefit"
                >
                  添加保险福利
                </el-button>
              </template>
@@ -72,7 +86,7 @@
                    <div class="insurance-benefit-title">
                      保险福利{{ index + 1 }}
                      <el-button
                        v-if="form.insuranceBenefits.length > 1"
                        v-if="!isDetail && form.insuranceBenefits.length > 1"
                        type="danger"
                        link
                        size="small"
@@ -92,6 +106,7 @@
                        placeholder="请选择"
                        clearable
                        style="width: 100%"
                        :disabled="isDetail"
                      >
                        <el-option
                          v-for="opt in insuranceTypeOptions"
@@ -102,9 +117,23 @@
                      </el-select>
                    </el-form-item>
                    <el-form-item label="缴费基数:" label-width="100px">
                      <div class="checkbox-group-inline">
                        <el-checkbox v-model="item.baseOnSalary">根据基本工资缴纳</el-checkbox>
                        <el-checkbox v-model="item.useBasicSalary">调用基本工资</el-checkbox>
                      <div class="base-salary-wrap">
                        <el-input
                          v-model="item.paymentBase"
                          placeholder="根据基本工资缴纳"
                          clearable
                          style="width: 120px"
                          type="number"
                          :disabled="isDetail || item.useBasicSalary"
                          @input="handlePaymentBaseInput(item)"
                        />
                        <el-checkbox
                          v-model="item.useBasicSalary"
                          @change="handleUseBasicSalaryChange(item)"
                          :disabled="isDetail"
                        >
                          调用基本工资
                        </el-checkbox>
                      </div>
                    </el-form-item>
                    <el-form-item label="个人缴费比例:" label-width="100px">
@@ -115,6 +144,7 @@
                          clearable
                          style="width: 100px"
                          type="number"
                          :disabled="isDetail"
                        />
                        <span class="ratio-unit">(%)</span>
                        <span class="ratio-plus">+</span>
@@ -124,6 +154,7 @@
                          clearable
                          style="width: 100px"
                          type="number"
                          :disabled="isDetail"
                        />
                      </div>
                    </el-form-item>
@@ -139,15 +170,11 @@
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
import { ref, reactive, toRefs, getCurrentInstance, nextTick, computed } from "vue";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { ArrowUp } from "@element-plus/icons-vue";
import { listDept } from "@/api/system/dept.js";
import {
  socialSecurityInfo,
  socialSecurityAdd,
  socialSecurityUpdate,
} from "@/api/personnelManagement/socialSecuritySet.js";
import { socialSecurityAdd, socialSecurityUpdate } from "@/api/personnelManagement/socialSecuritySet.js";
const emit = defineEmits(["close"]);
const { proxy } = getCurrentInstance();
@@ -157,22 +184,29 @@
const formRef = ref(null);
const deptList = ref([]);
const isDetail = computed(() => operationType.value === "detail");
const dialogTitle = () =>
  operationType.value === "add" ? "新增方案" : "编辑方案";
  operationType.value === "add"
    ? "新增方案"
    : operationType.value === "edit"
    ? "编辑方案"
    : "方案详情";
// 保险类型选项(可按字典替换)
const insuranceTypeOptions = [
  { label: "养老保险", value: "pension" },
  { label: "医疗保险", value: "medical" },
  { label: "失业保险", value: "unemployment" },
  { label: "工伤保险", value: "work_injury" },
  { label: "生育保险", value: "maternity" },
  { label: "养老保险", value: "养老保险" },
  { label: "医疗保险", value: "医疗保险" },
  { label: "失业保险", value: "失业保险" },
  { label: "工伤保险", value: "工伤保险" },
  { label: "生育保险", value: "生育保险" },
  { label: "公积金", value: "公积金" },
];
const defaultBenefit = () => ({
  _key: Math.random().toString(36).slice(2),
  insuranceType: "",
  baseOnSalary: false,
  paymentBase: "",
  useBasicSalary: false,
  personalRatio: "",
  personalFixed: "",
@@ -231,6 +265,18 @@
  form.value.insuranceBenefits.splice(index, 1);
};
const handleUseBasicSalaryChange = (item) => {
  if (item.useBasicSalary) {
    item.paymentBase = "";
  }
};
const handlePaymentBaseInput = (item) => {
  if (item.paymentBase !== "" && item.paymentBase != null) {
    item.useBasicSalary = false;
  }
};
const resetForm = () => {
  form.value = {
    id: undefined,
@@ -246,32 +292,77 @@
  dialogFormVisible.value = true;
  loadDeptList();
  resetForm();
  if (type === "edit" && row?.id) {
    socialSecurityInfo(row.id).then((res) => {
      const d = res.data || {};
      form.value.id = d.id;
      form.value.title = d.title;
      form.value.remark = d.remark ?? "";
      form.value.deptIds = d.deptIds ?? [];
      form.value.insuranceBenefits =
        (d.insuranceBenefits && d.insuranceBenefits.length)
          ? d.insuranceBenefits.map((b) => ({
              ...b,
              _key: b._key || Math.random().toString(36).slice(2),
            }))
          : [defaultBenefit()];
    });
  if ((type === "edit" || type === "detail") && row) {
    const d = row || {};
    form.value.id = d.id;
    form.value.title = d.title;
    form.value.remark = d.remark ?? "";
    // deptIds 后端可能是逗号分隔字符串或数组,这里统一转为数组并尽量还原数值类型
    if (d.deptIds) {
      form.value.deptIds = String(d.deptIds)
        .split(",")
        .filter((v) => v !== "")
        .map((v) => {
          const num = Number(v);
          return Number.isNaN(num) ? v : num;
        });
    } else {
      form.value.deptIds = [];
    }
    const detailList = d.schemeInsuranceDetailList || [];
    form.value.insuranceBenefits =
      detailList.length > 0
        ? detailList.map((b) => ({
            _key: Math.random().toString(36).slice(2),
            insuranceType: b.insuranceType || "",
            paymentBase: b.paymentBase ?? "",
            useBasicSalary: b.useBasicSalary === 2,
            personalRatio: b.personalRatio ?? "",
            personalFixed: b.personalFixed ?? "",
          }))
        : [defaultBenefit()];
  }
};
const submitForm = () => {
  // 详情模式下不提交,只关闭弹窗
  if (operationType.value === "detail") {
    closeDia();
    return;
  }
  formRef.value?.validate((valid) => {
    if (!valid) return;
    const deptIds =
      Array.isArray(form.value.deptIds) && form.value.deptIds.length
        ? form.value.deptIds.join(",")
        : "";
    const schemeInsuranceDetailList = (form.value.insuranceBenefits || []).map(
      ({ _key, ...rest }) => ({
        ...rest,
        useBasicSalary: rest.useBasicSalary ? 2 : 1,
      })
    );
    const insuranceTypes = schemeInsuranceDetailList
      .map((item) => item.insuranceType)
      .filter((v) => v)
      .join(",");
    // 部门名称,多个使用逗号隔开(根据选中的 deptIds 与 deptList 计算)
    const deptNames = (deptList.value || [])
      .filter((d) =>
        (form.value.deptIds || []).some(
          (id) => String(id) === String(d.deptId)
        )
      )
      .map((d) => d.deptName)
      .join(",");
    const submitData = {
      ...form.value,
      insuranceBenefits: form.value.insuranceBenefits.map(
        ({ _key, ...rest }) => rest
      ),
      id: form.value.id,
      title: form.value.title,
      remark: form.value.remark ?? "",
      deptIds,
      insuranceTypes,
      deptNames,
      schemeInsuranceDetailList,
    };
    if (operationType.value === "add") {
      socialSecurityAdd(submitData).then(() => {
@@ -356,6 +447,16 @@
  flex-wrap: wrap;
  gap: 16px;
}
.base-salary-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.base-salary-text {
  color: #606266;
  font-size: 14px;
}
.personal-ratio-wrap {
  display: flex;
  align-items: center;