zhang_nuo
6 天以前 c9cc00d09c756f126710168f81eb7ceba0959ec2
feat(personnel,production): 新增年龄自动计算及工单数量支持小数

- 员工档案模块新增年龄根据出生日期自动计算功能,涉及列表
展示、新增/编辑表单、基本信息组件,年龄字段设为只读
- 统一各组件的年龄计算逻辑,基于 dayjs 实现周岁计算
- 调整员工档案列表页代码缩进格式,移除调试日志
- 工单管理模块生产合格数量和报废数量支持三位小数输入,
移除整数校验及取整逻辑,适配小数业务场景
已修改4个文件
138 ■■■■■ 文件已修改
src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/employeeRecord/index.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrderManagement/index.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
@@ -79,12 +79,14 @@
            placeholder="请选择"
            style="width: 100%"
            clearable
            @change="handleBirthDateChange"
          />
        </el-form-item>
      </el-col>
      <el-col :span="5">
        <el-form-item label="年龄" prop="age">
          <el-input-number
              disabled
            v-model="form.age"
            :min="0"
            :max="150"
@@ -158,6 +160,7 @@
<script setup>
import { toRefs } from "vue";
import dayjs from "dayjs";
const props = defineProps({
  form: { type: Object, required: true },
@@ -166,6 +169,21 @@
});
const { form, operationType, roleOptions } = toRefs(props);
const calcAge = (birth) => {
  if (!birth) return undefined;
  const birthDay = dayjs(birth);
  const now = dayjs();
  let age = now.year() - birthDay.year();
  if (now.month() < birthDay.month() || (now.month() === birthDay.month() && now.date() < birthDay.date())) {
    age--;
  }
  return age;
};
const handleBirthDateChange = (val) => {
  form.value.age = calcAge(val);
};
</script>
<style scoped>
src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
@@ -40,7 +40,9 @@
  onMounted,
  getCurrentInstance,
  nextTick,
  computed,
} from "vue";
import dayjs from "dayjs";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { findPostOptions } from "@/api/system/post.js";
import { deptTreeSelect, getUser } from "@/api/system/user.js";
@@ -160,6 +162,17 @@
const { form, rules, postOptions, deptOptions } = toRefs(state);
const roleOptions = ref([]);
const calcAge = (birth) => {
  if (!birth) return undefined;
  const birthDay = dayjs(birth);
  const now = dayjs();
  let age = now.year() - birthDay.year();
  if (now.month() < birthDay.month() || (now.month() === birthDay.month() && now.date() < birthDay.date())) {
    age--;
  }
  return age;
};
const resetForm = () => {
  Object.assign(form.value, createDefaultForm());
  nextTick(() => {
@@ -238,6 +251,7 @@
      if (form.value.sysDeptId === 0) {
        form.value.sysDeptId = undefined;
      }
      form.value.age = calcAge(form.value.birthDate);
    });
  }
};
src/views/personnelManagement/employeeRecord/index.vue
@@ -12,21 +12,21 @@
            :prefix-icon="Search"
        />
        <span class="search_title search_title2">部门:</span>
          <el-tree-select
        <el-tree-select
            v-model="searchForm.sysDeptId"
            :data="deptOptions"
            check-strictly
            :render-after-expand="false"
            style="width: 240px"
            placeholder="请选择"
          />
          <span class="search_title search_title2">入职日期:</span>
          <el-date-picker
        />
        <span class="search_title search_title2">入职日期:</span>
        <el-date-picker
            v-model="searchForm.contractStartTime"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            placeholder="请选择"
          />
        />
        <!-- <span  style="margin-left: 10px" class="search_title">合同结束日期:</span> -->
        <!-- <el-date-picker  v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                         placeholder="请选择" clearable @change="changeDaterange" /> -->
@@ -56,24 +56,27 @@
        <template #positiveDate="{ row }">
          <span :class="getPositiveDateClass(row.positiveDate)">{{ row.positiveDate }}</span>
        </template>
        <template #age="{ row }">
          <span>{{ calcAge(row.birthDate) }}</span>
        </template>
      </PIMTable>
    </div>
    <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia>
    <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia>
    <!-- 导入对话框 -->
    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
      <el-upload
        ref="uploadRef"
        :limit="1"
        accept=".xlsx, .xls"
        :headers="upload.headers"
        :action="upload.url"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
          ref="uploadRef"
          :limit="1"
          accept=".xlsx, .xls"
          :headers="upload.headers"
          :action="upload.url"
          :disabled="upload.isUploading"
          :on-progress="handleFileUploadProgress"
          :on-success="handleFileSuccess"
          :auto-upload="false"
          drag
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
@@ -96,7 +99,7 @@
<script setup>
import { Search, UploadFilled } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import {onMounted, ref, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
import {ElMessageBox} from "element-plus";
import { deptTreeSelect } from "@/api/system/user.js";
import {batchDeleteStaffOnJobs, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
@@ -109,6 +112,8 @@
const data = reactive({
  searchForm: {
    staffName: "",
    sysDeptId: undefined,
    contractStartTime: undefined,
    entryDate: undefined, // 录入日期
    entryDateStart: undefined,
    entryDateEnd: undefined,
@@ -185,6 +190,8 @@
  {
    label: "年龄",
    prop: "age",
    dataType: "slot",
    slot: "age"
  },
  {
    label: "籍贯",
@@ -244,6 +251,23 @@
  url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import"
})
/**
 * 根据出生日期字符串计算周岁
 * @param {String} birth  YYYY‑MM‑DD
 * @returns {string|number}
 */
const calcAge = (birth) => {
  if (!birth) return "-";
  const birthDay = dayjs(birth);
  const now = dayjs();
  let age = now.year() - birthDay.year();
  // 生日还没过,减一岁
  if (now.month() < birthDay.month() || (now.month() === birthDay.month() && now.date() < birthDay.date())) {
    age--;
  }
  return age;
};
// 判断转正日期是否在7天内
const getPositiveDateClass = (positiveDate) => {
  if (!positiveDate) return '';
@@ -261,24 +285,23 @@
};
const fetchDeptOptions = () => {
    deptTreeSelect().then(response => {
      console.log(response.data)
      deptOptions.value = filterDisabledDept(
  deptTreeSelect().then(response => {
    deptOptions.value = filterDisabledDept(
        JSON.parse(JSON.stringify(response.data))
      );
    });
  };
    );
  });
};
const filterDisabledDept = deptList => {
    return deptList.filter(dept => {
      if (dept.disabled) {
        return false;
      }
      if (dept.children && dept.children.length) {
        dept.children = filterDisabledDept(dept.children);
      }
      return true;
    });
  };
  return deptList.filter(dept => {
    if (dept.disabled) {
      return false;
    }
    if (dept.children && dept.children.length) {
      dept.children = filterDisabledDept(dept.children);
    }
    return true;
  });
};
const changeDaterange = (value) => {
  searchForm.value.entryDateStart = undefined;
  searchForm.value.entryDateEnd = undefined;
src/views/productionManagement/workOrderManagement/index.vue
@@ -133,7 +133,7 @@
          <el-input v-model.number="reportForm.quantity"
                    type="number"
                    min="0"
                    step="1"
                    step="0.001"
                    style="width: 300px"
                    placeholder="请输入生产合格数量"
                    @input="handleQuantityInput" />
@@ -446,7 +446,7 @@
    }
    const num = Number(value);
    // 整数且大于等于1
    if (isNaN(num) || !Number.isInteger(num) || num < 0) {
    if (isNaN(num) || num < 0) {
      callback(new Error("生产合格数量必须大于等于0"));
      return;
    }
@@ -461,7 +461,7 @@
    }
    const num = Number(value);
    // 整数且大于等于0
    if (isNaN(num) || !Number.isInteger(num) || num < 0) {
    if (isNaN(num) || num < 0) {
      callback(new Error("报废数量必须大于等于0"));
      return;
    }
@@ -487,17 +487,6 @@
    // 如果小于1,清除
    if (num < 0) {
      reportForm.quantity = null;
      return;
    }
    // 如果是小数取整数部分
    if (!Number.isInteger(num)) {
      const intValue = Math.floor(num);
      // 如果取整后小于1,清除
      if (intValue < 0) {
        reportForm.quantity = null;
        return;
      }
      reportForm.quantity = intValue;
      return;
    }
    reportForm.quantity = num;