1.完成生产管理-电量分析静态界面
2.完成综合管理-人员排班管理交互 3.修改部分逻辑和样式
This commit is contained in:
@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<!-- 人员排班弹窗 -->
|
||||
<el-dialog
|
||||
:model-value="manageAttendDialogVisible"
|
||||
@update:model-value="handleDialogVisibleChange"
|
||||
title="管理考勤"
|
||||
width="500"
|
||||
>
|
||||
<el-form :model="attendForm" label-width="100px">
|
||||
<el-form-item label="选择日期">
|
||||
<el-date-picker
|
||||
v-model="attendForm.date"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
style="width: 100%;"
|
||||
:disabled-date="(time) => time.getTime() < Date.now() - 8.64e7"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 动态排班表单 -->
|
||||
<div v-for="(item, index) in attendForm.shifts" :key="index" class="dynamic-shift-item">
|
||||
<el-form-item :label="index === 0 ? '排班设置' : ''" :required="index === 0">
|
||||
<div class="shift-form-row">
|
||||
<!-- 排班类型选择 -->
|
||||
<el-select
|
||||
v-model="item.type"
|
||||
placeholder="请选择排班类型"
|
||||
style="width: 40%; margin-right: 10px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in availableShiftOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 人员选择 -->
|
||||
<el-select
|
||||
v-model="item.personnel"
|
||||
placeholder="请选择人员"
|
||||
style="width: 50%; margin-right: 10px;"
|
||||
multiple
|
||||
filterable
|
||||
>
|
||||
<el-option label="张三" value="1"></el-option>
|
||||
<el-option label="李四" value="2"></el-option>
|
||||
<el-option label="王五" value="3"></el-option>
|
||||
<el-option label="赵六" value="4"></el-option>
|
||||
<el-option label="钱七" value="5"></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 删除按钮 (仅在不是第一个项目时显示) -->
|
||||
<el-button
|
||||
v-if="index > 0"
|
||||
type="danger"
|
||||
icon="CircleCloseFilled"
|
||||
circle
|
||||
@click="removeShiftItem(index)"
|
||||
></el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 添加排班类型按钮 -->
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="CirclePlusFilled"
|
||||
@click="addShiftItem"
|
||||
:disabled="attendForm.shifts.length >= shiftTypes.length"
|
||||
>
|
||||
添加排班类型
|
||||
</el-button>
|
||||
<div v-if="attendForm.shifts.length > 0" class="form-tip">
|
||||
提示:已添加 {{ attendForm.shifts.length }}/{{ shiftTypes.length }} 种排班类型
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
// 定义组件的props
|
||||
const props = defineProps({
|
||||
manageAttendDialogVisible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
// 定义组件的emits
|
||||
const emit = defineEmits<{
|
||||
'update:manageAttendDialogVisible': [value: boolean];
|
||||
'confirm': [formData: any];
|
||||
}>();
|
||||
|
||||
// 排班类型列表
|
||||
const shiftTypes = [
|
||||
{ label: '早班', value: '早班' },
|
||||
{ label: '中班', value: '中班' },
|
||||
{ label: '晚班', value: '晚班' },
|
||||
{ label: '休息', value: '休息' }
|
||||
];
|
||||
|
||||
// 考勤表单数据
|
||||
const attendForm = ref({
|
||||
date: '',
|
||||
shifts: [
|
||||
{ type: '', personnel: [] }
|
||||
]
|
||||
});
|
||||
|
||||
// 获取可用的排班类型选项(排除已添加的类型)
|
||||
const availableShiftOptions = ref(shiftTypes);
|
||||
|
||||
// 监听排班类型变化,更新可用选项
|
||||
const setupWatchers = () => {
|
||||
attendForm.value.shifts.forEach((item) => {
|
||||
watch(() => item.type, (newType) => {
|
||||
updateAvailableShiftOptions();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化时设置监听器
|
||||
setupWatchers();
|
||||
|
||||
// 更新可用的排班类型选项
|
||||
const updateAvailableShiftOptions = () => {
|
||||
const usedTypes = attendForm.value.shifts
|
||||
.map(item => item.type)
|
||||
.filter(type => type !== '');
|
||||
|
||||
availableShiftOptions.value = shiftTypes.filter(type =>
|
||||
!usedTypes.includes(type.value)
|
||||
);
|
||||
};
|
||||
|
||||
// 添加新的排班类型项
|
||||
const addShiftItem = () => {
|
||||
// 检查是否还有可用的排班类型
|
||||
if (attendForm.value.shifts.length < shiftTypes.length) {
|
||||
attendForm.value.shifts.push({ type: '', personnel: [] });
|
||||
|
||||
// 为新添加的项添加监听器
|
||||
const newItem = attendForm.value.shifts[attendForm.value.shifts.length - 1];
|
||||
watch(() => newItem.type, (newType) => {
|
||||
updateAvailableShiftOptions();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 删除排班类型项
|
||||
const removeShiftItem = (index: number) => {
|
||||
if (attendForm.value.shifts.length > 1) {
|
||||
attendForm.value.shifts.splice(index, 1);
|
||||
updateAvailableShiftOptions();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理取消
|
||||
const handleCancel = () => {
|
||||
emit('update:manageAttendDialogVisible', false);
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// 处理弹窗可见性变化
|
||||
const handleDialogVisibleChange = (newVisible: boolean) => {
|
||||
emit('update:manageAttendDialogVisible', newVisible);
|
||||
if (!newVisible) {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理确认
|
||||
const handleConfirm = () => {
|
||||
// 提交表单数据给父组件
|
||||
emit('confirm', attendForm.value);
|
||||
emit('update:manageAttendDialogVisible', false);
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
attendForm.value = {
|
||||
date: '',
|
||||
shifts: [
|
||||
{ type: '', personnel: [] }
|
||||
]
|
||||
};
|
||||
updateAvailableShiftOptions();
|
||||
// 重新设置监听器
|
||||
setupWatchers();
|
||||
};
|
||||
|
||||
// 监听弹窗显示状态变化,在显示时重置表单
|
||||
watch(() => props.manageAttendDialogVisible, (newVisible) => {
|
||||
if (newVisible) {
|
||||
resetForm();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 动态排班表单样式 */
|
||||
.dynamic-shift-item {
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.shift-form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.shift-form-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.shift-form-row .el-select {
|
||||
width: 100% !important;
|
||||
margin-right: 0 !important;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.shift-form-row .el-button {
|
||||
align-self: flex-start;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -26,6 +26,15 @@
|
||||
<div class="week-day">{{ dateInfo.weekDay }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div
|
||||
class="schedule-cell"
|
||||
:style="{ color: getShiftColor(scope.row[`day${index + 1}`]) }"
|
||||
@click="handleCellClick(scope.row, {...dateInfo, index}, scope)"
|
||||
>
|
||||
{{ scope.row[`day${index + 1}`] }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
@ -34,6 +43,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
|
||||
const emit = defineEmits<{
|
||||
'edit-schedule': [rowData: any, columnData: any, cellEvent: any]
|
||||
}>();
|
||||
|
||||
// 员工列表
|
||||
const employees = [
|
||||
{ name: '张三', position: '水泥工', weeklyHours: 142 },
|
||||
@ -51,6 +64,19 @@ const employees = [
|
||||
// 排班类型
|
||||
const shifts = ['早班', '中班', '晚班', '休息'];
|
||||
|
||||
// 排班类型与颜色的映射关系
|
||||
const shiftColorMap = {
|
||||
'早班': '#67c23a', // 绿色
|
||||
'中班': '#e6a23c', // 橙色
|
||||
'晚班': '#409eff', // 蓝色
|
||||
'休息': '#909399' // 灰色
|
||||
};
|
||||
|
||||
// 根据排班类型获取对应的颜色
|
||||
const getShiftColor = (shiftType: string) => {
|
||||
return shiftColorMap[shiftType as keyof typeof shiftColorMap] || '#333';
|
||||
};
|
||||
|
||||
// 获取当前月的日期信息
|
||||
const currentMonthDates = ref<any[]>([]);
|
||||
|
||||
@ -112,6 +138,11 @@ const scheduleData = computed(() => {
|
||||
onMounted(() => {
|
||||
currentMonthDates.value = getCurrentMonthDates();
|
||||
});
|
||||
|
||||
// 处理单元格点击事件
|
||||
const handleCellClick = (rowData: any, columnData: any, cellEvent: any) => {
|
||||
emit('edit-schedule', rowData, columnData, cellEvent);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -165,6 +196,18 @@ onMounted(() => {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* 排班单元格样式 */
|
||||
.schedule-cell {
|
||||
padding: 8px 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.schedule-cell:hover {
|
||||
background-color: #f5f7fa;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.date-number {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user