From fdd6bb96d8aad1ab796ce10038d170b47a19f661 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 13 十一月 2025 13:45:41 +0800
Subject: [PATCH] 1.排班管理-班次、加一个午休时间(h)、人员多选、人员从用户管理获取,加一条列表也只展示一条 2.薪资管理-只要,人员、薪资、月份三个字段

---
 src/views/personnelManagement/scheduling/index.vue |  301 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 181 insertions(+), 120 deletions(-)

diff --git a/src/views/personnelManagement/scheduling/index.vue b/src/views/personnelManagement/scheduling/index.vue
index 251dbe9..7c6324f 100644
--- a/src/views/personnelManagement/scheduling/index.vue
+++ b/src/views/personnelManagement/scheduling/index.vue
@@ -11,34 +11,14 @@
               style="width: 150px"
           />
         </el-form-item>
-        <el-form-item label="鐝绫诲瀷锛�">
-          <el-select v-model="filterForm.shiftType" placeholder="璇烽�夋嫨鐝" clearable style="width: 120px">
-            <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="鏃ユ湡鑼冨洿锛�">
-          <el-date-picker
-              v-model="filterForm.dateRange"
-              type="daterange"
-              range-separator="鑷�"
-              start-placeholder="寮�濮嬫棩鏈�"
-              end-placeholder="缁撴潫鏃ユ湡"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              style="width: 250px"
-          />
-        </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleFilter">
-            <el-icon><Search/></el-icon>
-            绛涢��
+            鎼滅储
           </el-button>
           <el-button @click="resetFilter">
-            <el-icon><Refresh/></el-icon>
             閲嶇疆
           </el-button>
           <el-button @click="handleExport">
-            <el-icon><Download/></el-icon>
             瀵煎嚭
           </el-button>
           <el-button type="primary" @click="openScheduleDialog('add')">
@@ -61,48 +41,53 @@
           @selection-change="handleSelectionChange"
       >
         <el-table-column type="selection" width="55"/>
-        <el-table-column prop="staffName" label="鍛樺伐濮撳悕" width="120"/>
-        <el-table-column prop="staffNo" label="鍛樺伐宸ュ彿" width="100"/>
-        <el-table-column prop="department" label="閮ㄩ棬" width="120">
+        <el-table-column prop="staffName" label="鍛樺伐濮撳悕"/>
+        <!-- <el-table-column prop="staffNo" label="鍛樺伐宸ュ彿" width="100"/> -->
+        <!-- <el-table-column prop="department" label="閮ㄩ棬" width="120">
           <template #default="scope">
               {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }}
           </template>
-        </el-table-column>
-        <el-table-column prop="shiftType" label="鐝绫诲瀷" width="100">
+        </el-table-column> -->
+        <!-- <el-table-column prop="shiftType" label="鐝绫诲瀷" width="100">
           <template #default="scope">
             <el-tag :type="getShiftTagType(scope.row.shiftType)">
               {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }}
             </el-tag>
           </template>
+        </el-table-column> -->
+        <!-- <el-table-column prop="workDate" label="宸ヤ綔鏃ユ湡" width="120"/> -->
+        <el-table-column prop="workStartTime" label="寮�濮嬫椂闂�"/>
+        <el-table-column prop="workEndTime" label="缁撴潫鏃堕棿"/>
+        <el-table-column prop="lunchTime" label="鍗堜紤鏃堕棿(h)">
+          <template #default="scope">
+            {{ scope.row.lunchTime }}灏忔椂
+          </template>
         </el-table-column>
-        <el-table-column prop="workDate" label="宸ヤ綔鏃ユ湡" width="120"/>
-        <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="100"/>
-        <el-table-column prop="endTime" label="缁撴潫鏃堕棿" width="100"/>
-        <el-table-column prop="workHours" label="宸ヤ綔鏃堕暱" width="100">
+        <!-- <el-table-column prop="workHours" label="宸ヤ綔鏃堕暱" width="100">
           <template #default="scope">
             {{ scope.row.workHours }}灏忔椂
           </template>
-        </el-table-column>
-        <el-table-column prop="status" label="鐘舵��" width="100">
+        </el-table-column> -->
+        <!-- <el-table-column prop="status" label="鐘舵��" width="100">
           <template #default="scope">
             <el-tag :type="getStatusTagType(scope.row.status)">
               {{ (schedule_status.find(i => i.value === String(scope.row.status)) || {}).label }}
             </el-tag>
           </template>
-        </el-table-column>
-        <el-table-column prop="remark" label="澶囨敞" min-width="150"/>
-        <el-table-column label="鎿嶄綔" width="200" fixed="right">
+        </el-table-column> -->
+        <!-- <el-table-column prop="remark" label="澶囨敞" min-width="150"/> -->
+        <el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
           <template #default="scope">
             <el-button
-                type="primary"
-                size="small"
+							link
+							type="primary"
                 @click="openScheduleDialog('edit', scope.row)"
             >
               缂栬緫
             </el-button>
             <el-button
-                type="danger"
-                size="small"
+							link
+							type="danger"
                 @click="handleDelete(scope.row)"
             >
               鍒犻櫎
@@ -144,22 +129,26 @@
           label-width="120px"
       >
         <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="鍛樺伐濮撳悕锛�" prop="staffId">
-              <el-select v-model="scheduleForm.staffId" placeholder="璇疯緭鍏ュ憳宸ュ鍚�" style="width: 100%"
+          <el-col :span="24">
+            <el-form-item label="鍛樺伐濮撳悕锛�" prop="staffIds">
+          <el-select v-model="scheduleForm.staffIds" placeholder="璇烽�夋嫨鍛樺伐濮撳悕" style="width: 100%"
+                         multiple filterable collapse-tags-tooltip
                          @change="handleSelectStaff">
-                <el-option v-for="item in personList" :label="item.staffName" :value="item.id" :key="item.id"/>
-              </el-select>
-            </el-form-item>
+            <el-option v-for="item in personList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
+          </el-select>
+        </el-form-item>
           </el-col>
+        </el-row>
+
+        <!-- <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="鍛樺伐宸ュ彿锛�" prop="staffNo">
               <el-input :disabled="true" v-model="scheduleForm.staffNo" placeholder=""/>
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
 
-        <el-row :gutter="20">
+        <!-- <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="閮ㄩ棬锛�" prop="department">
               <el-select v-model="scheduleForm.department" placeholder="璇烽�夋嫨閮ㄩ棬" style="width: 100%">
@@ -174,9 +163,9 @@
               </el-select>
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
 
-        <el-row :gutter="20">
+        <!-- <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="宸ヤ綔鏃ユ湡锛�" prop="workDate">
               <el-date-picker
@@ -196,34 +185,49 @@
               </el-select>
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
 
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="寮�濮嬫椂闂达細" prop="startTime">
+            <el-form-item label="寮�濮嬫椂闂达細" prop="workStartTime">
               <el-time-picker
-                  v-model="scheduleForm.startTime"
+                  v-model="scheduleForm.workStartTime"
                   placeholder="閫夋嫨寮�濮嬫椂闂�"
                   style="width: 100%"
                   format="HH:mm"
-                  value-format="HH:mm"
+                  value-format="YYYY-MM-DD HH:mm:ss"
               />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="缁撴潫鏃堕棿锛�" prop="endTime">
+            <el-form-item label="缁撴潫鏃堕棿锛�" prop="workEndTime">
               <el-time-picker
-                  v-model="scheduleForm.endTime"
+                  v-model="scheduleForm.workEndTime"
                   placeholder="閫夋嫨缁撴潫鏃堕棿"
                   style="width: 100%"
                   format="HH:mm"
-                  value-format="HH:mm"
+                  value-format="YYYY-MM-DD HH:mm:ss"
               />
             </el-form-item>
           </el-col>
         </el-row>
 
         <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍗堜紤鏃堕棿(h)锛�" prop="lunchTime">
+              <el-input-number
+                  v-model="scheduleForm.lunchTime"
+                  :min="0"
+                  :max="8"
+                  :step="0.5"
+                  placeholder="璇疯緭鍏ュ崍浼戞椂闂�"
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- <el-row :gutter="20">
           <el-col :span="24">
             <el-form-item label="澶囨敞锛�" prop="remark">
               <el-input
@@ -234,7 +238,7 @@
               />
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
       </el-form>
 
       <template #footer>
@@ -248,7 +252,7 @@
 </template>
 
 <script setup>
-import {ref, reactive, computed, onMounted, getCurrentInstance} from 'vue'
+import {ref, reactive, computed, onMounted, getCurrentInstance, watch} from 'vue'
 import {ElMessage, ElMessageBox} from 'element-plus'
 import {useDict} from "@/utils/dict.js"
 import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue'
@@ -256,6 +260,7 @@
 import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
 import dayjs from "dayjs";
 import pagination from "@/components/PIMTable/Pagination.vue";
+import {listUser} from "@/api/system/user.js";
 
 const { proxy } = getCurrentInstance();
 
@@ -269,8 +274,6 @@
 // 绛涢�夎〃鍗�
 const filterForm = reactive({
   staffName: '',
-  shiftType: '',
-  dateRange: [],
   current:1,
   size: 10
 })
@@ -278,29 +281,31 @@
 // 鎺掔彮琛ㄥ崟
 const scheduleForm = reactive({
   id: '',
-  staffId: '',
-  staffNo: '',
-  department: '',
-  shiftType: '',
-  workDate: '',
-  startTime: '',
-  endTime: '',
+  staffIds: [],
+  // staffNo: '',
+  // department: '',
+  // shiftType: '',
+  // workDate: '',
   workStartTime: '',
   workEndTime: '',
-  workHours: 0,
-  status: '',
-  remark: ''
+  lunchTime: 3,
+  // workStartTime: '',
+  // workEndTime: '',
+  // workHours: 0,
+  // status: '',
+  // remark: ''
 })
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const scheduleRules = reactive({
-  staffId: [{required: true, message: '璇烽�夋嫨鍛樺伐', trigger: 'change'}],
-  department: [{required: true, message: '璇烽�夋嫨閮ㄩ棬', trigger: 'change'}],
-  shiftType: [{required: true, message: '璇烽�夋嫨鐝绫诲瀷', trigger: 'change'}],
-  workDate: [{required: true, message: '璇烽�夋嫨宸ヤ綔鏃ユ湡', trigger: 'change'}],
-  startTime: [{required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change'}],
-  endTime: [{required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change'}],
-  status: [{required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change'}]
+  staffIds: [{required: true, message: '璇烽�夋嫨鍛樺伐', trigger: 'change'}],
+  // department: [{required: true, message: '璇烽�夋嫨閮ㄩ棬', trigger: 'change'}],
+  // shiftType: [{required: true, message: '璇烽�夋嫨鐝绫诲瀷', trigger: 'change'}],
+  // workDate: [{required: true, message: '璇烽�夋嫨宸ヤ綔鏃ユ湡', trigger: 'change'}],
+  workStartTime: [{required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change'}],
+  workEndTime: [{required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change'}],
+  lunchTime: [{required: true, message: '璇疯緭鍏ュ崍浼戞椂闂�', trigger: 'blur'}],
+  // status: [{required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change'}]
 })
 const tableLoading = ref(false)
 
@@ -317,9 +322,9 @@
  * 鑾峰彇褰撳墠鍦ㄨ亴浜哄憳鍒楄〃
  */
 const getPersonList = () => {
-  getStaffOnJob().then(res => {
-    personList.value = res.data
-  })
+	listUser().then(res => {
+		personList.value = res.rows
+	})
 };
 const paginationChange = (obj) => {
   filterForm.current = obj.page;
@@ -328,9 +333,9 @@
 };
 
 const handleSelectStaff = (val) => {
-  let obj = personList.value.find(item => item.id === val)
-  scheduleForm.staffNo = obj.staffNo
-
+  // 澶氶�夊憳宸ワ紝涓嶅啀鑷姩璁剧疆鍛樺伐宸ュ彿
+  // let obj = personList.value.find(item => item.id === val)
+  // scheduleForm.staffNo = obj.staffNo
 }
 
 // 鑾峰彇鐝鏍囩绫诲瀷
@@ -349,19 +354,19 @@
 const handleFilter = async () => {
   tableLoading.value = true
   let searchForm = {
-    ...filterForm,
-    ...(filterForm.dateRange.length > 0 && {
-      startDate: filterForm.dateRange[0],
-      endDate: filterForm.dateRange[1],
-    })
+    ...filterForm
   }
   let resp = await listPage(searchForm)
   tableCount.value = resp.data.total
   scheduleList.value = resp.data.records.map(it => {
     return {
       ...it,
-      'startTime': dayjs(it.workStartTime).format('HH:mm'),
-      'endTime': dayjs(it.workEndTime).format('HH:mm'),
+      // 淇濆瓨鍘熷鏃堕棿鏍煎紡鐢ㄤ簬缂栬緫
+      'originalWorkStartTime': it.workStartTime,
+      'originalWorkEndTime': it.workEndTime,
+      // 鏍煎紡鍖栨椂闂寸敤浜庤〃鏍兼樉绀�
+      'workStartTime': dayjs(it.workStartTime).format('HH:mm'),
+      'workEndTime': dayjs(it.workEndTime).format('HH:mm'),
     }
   })
   tableLoading.value = false
@@ -371,8 +376,6 @@
 // 閲嶇疆绛涢��
 const resetFilter = () => {
   filterForm.staffName = ''
-  filterForm.shiftType = ''
-  filterForm.dateRange = []
 }
 
 // 鎵撳紑鎺掔彮瀵硅瘽妗�
@@ -381,16 +384,29 @@
   scheduleDialog.value = true
   getPersonList()
   if (type === 'edit' && data) {
-    // 缂栬緫妯″紡锛屽鍒舵暟鎹�
-    Object.assign(scheduleForm, {...data})
-  } else {
-    // 鏂板妯″紡锛岄噸缃〃鍗�
-    Object.keys(scheduleForm).forEach(key => {
-      scheduleForm[key] = ''
+    // 缂栬緫妯″紡锛屽鍒舵暟鎹紝灏嗗憳宸D瀛楃涓茶浆鎹负鏁扮粍鏍煎紡锛屽苟澶勭悊鏃堕棿瀛楁
+    Object.assign(scheduleForm, {
+      ...data,
+		lunchTime: Number(data.lunchTime),
+      staffIds: data.staffId ? data.staffId.split(',').map(id => parseInt(id)) : [],
+      // 浣跨敤鍘熷鏃堕棿瀛楃涓诧紝鍥犱负琛ㄦ牸涓樉绀虹殑鏄牸寮忓寲鍚庣殑HH:mm
+      workStartTime: data.originalWorkStartTime || '',
+      workEndTime: data.originalWorkEndTime || ''
     })
-    // scheduleForm.status = '宸插畨鎺�'
-    scheduleForm.workDate = new Date().toISOString().split('T')[0]
-  }
+  } else {
+      // 鏂板妯″紡锛岄噸缃〃鍗�
+      Object.keys(scheduleForm).forEach(key => {
+        if (key === 'staffIds') {
+          scheduleForm[key] = []
+        } else if (key === 'lunchTime') {
+          scheduleForm[key] = 3
+        } else {
+          scheduleForm[key] = ''
+        }
+      })
+      // scheduleForm.status = '宸插畨鎺�'
+      // scheduleForm.workDate = new Date().toISOString().split('T')[0]
+    }
 }
 
 // 鍏抽棴鎺掔彮瀵硅瘽妗�
@@ -401,37 +417,86 @@
 
 // 璁$畻宸ヤ綔鏃堕暱
 const calculateWorkHours = () => {
-  if (scheduleForm.workDate && scheduleForm.startTime && scheduleForm.endTime) {
-    // 浣跨敤 workDate 涓� startTime 鍜� endTime 缁勫悎
-    const startDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.startTime}`)
-    const endDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.endTime}`)
+  if (!scheduleForm.workStartTime || !scheduleForm.workEndTime) {
+    return;
+  }
+
+  try {
+    // 浣跨敤dayjs姝g‘瑙f瀽鏃堕棿
+    const startDayjs = dayjs(scheduleForm.workStartTime);
+    const endDayjs = dayjs(scheduleForm.workEndTime);
+
+    if (!startDayjs.isValid() || !endDayjs.isValid()) {
+      return;
+    }
+
+    const startDateTime = startDayjs.toDate();
+    const endDateTime = endDayjs.toDate();
 
     // 澶勭悊璺ㄥぉ鎯呭喌锛堢粨鏉熸椂闂存棭浜庡紑濮嬫椂闂达級
     if (endDateTime < startDateTime) {
       // 璺ㄥぉ锛屽皢缁撴潫鏃ユ湡鍔犱竴澶�
-      endDateTime.setDate(endDateTime.getDate() + 1)
+      endDateTime.setDate(endDateTime.getDate() + 1);
     }
-    // 璁$畻宸ヤ綔鏃堕暱锛堝皬鏃讹級
-    const diffMs = endDateTime - startDateTime
-    const diffHours = diffMs / (1000 * 60 * 60)
-    scheduleForm.workHours = Math.round(diffHours * 100) / 100
-    scheduleForm.workStartTime = dayjs(startDateTime).format("YYYY-MM-DD HH:mm:ss")
-    scheduleForm.workEndTime = dayjs(endDateTime).format("YYYY-MM-DD HH:mm:ss")
 
+    // 璁$畻宸ヤ綔鏃堕暱锛堝皬鏃讹級
+    const diffMs = endDateTime - startDateTime;
+    const diffHours = diffMs / (1000 * 60 * 60);
+    scheduleForm.workHours = Math.round(diffHours * 100) / 100;
+  } catch (error) {
+    console.error('鏃堕棿璁$畻閿欒:', error);
   }
 }
+
+// 鐩戝惉鏃堕棿瀛楁鍙樺寲锛岃嚜鍔ㄨ绠楀伐浣滄椂闀�
+watch(
+  () => [scheduleForm.workStartTime, scheduleForm.workEndTime],
+  () => {
+    calculateWorkHours()
+  },
+  { deep: true }
+)
 
 // 鎻愪氦鎺掔彮琛ㄥ崟
 const submitScheduleForm = async () => {
   const valid = await scheduleFormRef.value.validate()
   if (!valid) return
 
-  calculateWorkHours()
-  const newSchedule = {...scheduleForm}
+  // 鐢变簬鍛樺伐鏄閫夛紝闇�瑕佷负姣忎釜閫変腑鐨勫憳宸ュ垱寤烘帓鐝褰�
+  const selectedStaffIds = scheduleForm.staffIds || []
+  
+  if (selectedStaffIds.length === 0) {
+    ElMessage.warning('璇疯嚦灏戦�夋嫨涓�涓憳宸�')
+    return
+  }
 
   try {
+    // 鑾峰彇閫変腑鐨勫憳宸ュ鍚嶅垪琛�
+    const selectedStaffNames = selectedStaffIds.map(staffId => {
+      const staff = personList.value.find(item => item.userId === staffId)
+      return staff ? staff.nickName : ''
+    }).filter(name => name !== '')
+    
+    // 灏嗗憳宸ュ鍚嶇粍瑁呮垚閫楀彿鍒嗛殧鐨勫瓧绗︿覆
+    const staffNameString = selectedStaffNames.join(',')
+    
+    // 鍒涘缓鎺掔彮璁板綍锛屽皢鍛樺伐濮撳悕淇濆瓨涓哄瓧绗︿覆鏍煎紡
+    const newSchedule = {
+      ...scheduleForm,
+      staffName: staffNameString,
+      staffId: selectedStaffIds.join(','), // 灏嗗憳宸D涔熶繚瀛樹负閫楀彿鍒嗛殧鐨勫瓧绗︿覆
+      // 璁剧疆鍏朵粬蹇呰瀛楁鐨勯粯璁ゅ��
+      staffNo: '', // 鍙互鏍规嵁闇�瑕佷粠personList涓幏鍙�
+      department: '',
+      shiftType: '',
+      workDate: '',
+      status: '',
+      remark: ''
+    }
+    
     await save(newSchedule)
-    ElMessage.success('淇濆瓨鎺掔彮鎴愬姛')
+    
+    ElMessage.success(`鎴愬姛涓� ${selectedStaffNames.length} 涓憳宸ュ垱寤烘帓鐝璥)
 
     handleFilter()
     closeScheduleDialog()
@@ -491,11 +556,7 @@
 // 瀵煎嚭
 const handleExport = () => {
   let searchForm = {
-    ...filterForm,
-    ...(filterForm.dateRange.length > 0 && {
-      startDate: filterForm.dateRange[0],
-      endDate: filterForm.dateRange[1],
-    })
+    ...filterForm
   }
   proxy.download('/staff/staffScheduling/export', {}, '浜哄憳鎺掔彮.xlsx')
 }

--
Gitblit v1.9.3