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