feat: 排班管理

This commit is contained in:
fyy
2025-08-11 11:05:47 +08:00
parent effcb9ef86
commit 0a77934d8b
5 changed files with 71 additions and 37 deletions

View File

@@ -78,3 +78,17 @@ export function arrangmentList(params?: arrangmentListQuery) {
{ params },
);
}
/**
* 查询某天排班人员详情列表(班表视图)
* @param params
* @returns 排班列表
*/
export function queryScheduleView(params?: arrangmentListQuery) {
return requestClient.get<PageResult<AttendanceUserGroup>>(
'/property/AttendanceUserGroup/queryScheduleView',
{ params },
);
}

View File

@@ -40,9 +40,9 @@ export interface ArrangementVO {
* 状态0-未生效1-已生效
*/
status?: number;
userGroupList?:any[];
attendanceGroup?:any;
dateType?:number
userGroupList?: any[];
attendanceGroup?: any;
dateType?: number;
}
export interface ArrangementForm extends BaseEntity {
@@ -138,5 +138,6 @@ export interface ArrangementQuery extends PageQuery {
month?: string;
}
export interface arrangmentListQuery extends PageQuery {
currentDate:string//某天的日期
currentDate: string; //某天的日期
}
export interface AttendanceUserGroup {}

View File

@@ -15,7 +15,7 @@ import {
import { Modal } from 'ant-design-vue';
const emit = defineEmits<{
(e: 'changeView', value: boolean): void;
(e: 'changeView', value: 'calender' | 'schedule'): void;
}>();
const props = defineProps<{
viewMode: 'calender' | 'schedule';
@@ -24,20 +24,15 @@ const selectedDate = ref();
const calendarData = reactive<any[]>([]);
const loading = ref(false);
// 查询日历数据
const fetchCalendarData = async (month?: string) => {
const fetchCalendarData = async () => {
try {
loading.value = true;
const params = {
month:
month ||
selectedDate.value?.format('YYYY-MM') ||
dayjs().format('YYYY-MM'),
month: selectedDate.value?.format('YYYY-MM') || dayjs().format('YYYY-MM'),
};
const res = await arrangementCalender(params);
const currentMonth =
month ||
selectedDate.value?.format('YYYY-MM') ||
dayjs().format('YYYY-MM'); //当前月份的开始日期
selectedDate.value?.format('YYYY-MM') || dayjs().format('YYYY-MM'); //当前月份的开始日期
// 清空之前的数据
calendarData.length = 0;
@@ -171,7 +166,6 @@ const scheduleData: {
];
// 切换视图模式
function handleViewModeChange(e: RadioChangeEvent): void {
// 将父组件的isCalenderView变为true
emit('changeView', e.target.value);
}

View File

@@ -82,34 +82,51 @@ export const columns: VxeGridProps['columns'] = [
},
{
title: '人员',
field: 'scheduleName',
field: 'employeeName',
width: 120,
// width: 'auto',
},
{
title: '单位',
field: 'scheduleName',
field: 'deptName',
width: 'auto',
},
{
title: '排班名称',
field: 'scheduleName',
minWidth: 120,
},
// {
// title: '排班名称',
// field: 'attendanceArrangement.scheduleName',
// minWidth: 120,
// },
{
title: '考勤组',
field: 'groupId',
field: 'attendanceGroup.groupName',
minWidth: 120,
},
{
title: '考勤类型',
field: 'scheduleType',
field: 'attendanceGroup.attendanceType',
slots: {
default: ({ row }) => {
return renderDict(String(row.attendanceGroup.attendanceType),'wy_kqlx')
},
},
width: 'auto',
},
{
title: '考勤时间',
field: 'dateType',
field: 'attendanceShift',
minWidth: 200,
slots: {
default: ({ row }) => {
if (row.attendanceShift.startTime && row.attendanceShift.endTime) {
if(row.attendanceShift.restEndTime&&row.attendanceShift.restStartTime){
return `${row.attendanceShift.startTime}${row.attendanceShift.endTime} ${row.shift.restStartTime}${row.shift.restEndTime}`;
}else{
return `${row.attendanceShift.startTime}${row.attendanceShift.endTime}`;
}
}
return '/';
},
},
},
{
field: 'action',
@@ -289,7 +306,7 @@ export const workforceDayDetailColumns:VxeGridProps['columns'] =[
default: ({ row }) => {
if (row.shift.startTime && row.shift.endTime) {
if(row.shift.restEndTime&&row.shift.restStartTime){
return `${row.shift.restStartTime}${row.shift.restEndTime} ${row.shift.startTime}${row.shift.endTime}`;
return `${row.shift.startTime}${row.shift.endTime} ${row.shift.restStartTime}${row.shift.restEndTime}`;
}else{
return `${row.shift.startTime}${row.shift.endTime}`;
}

View File

@@ -7,24 +7,28 @@ import { columns } from './data';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { getVxePopupContainer } from '@vben/utils';
import {
arrangementList,
queryScheduleView,
arrangementRemove,
} from '#/api/property/attendanceManagement/arrangement';
import arrangementModal from './arrangement-modal.vue';
import type { ArrangementForm } from '#/api/property/attendanceManagement/arrangement/model';
import { Page, useVbenModal } from '@vben/common-ui';
import { Popconfirm, Space } from 'ant-design-vue';
const emit = defineEmits<{ (e: 'changeView', value: boolean): void }>();
import dayjs from 'dayjs';
const emit = defineEmits<{
(e: 'changeView', value: 'calender' | 'schedule'): void;
}>();
const props = defineProps<{
viewMode: 'calender' | 'schedule';
}>();
const value = ref<Dayjs>();
const onPanelChange = (value: Dayjs, mode: string) => {
console.log(value, mode);
const onSelect = (value: Dayjs) => {
currentDate.value = dayjs(value).format('YYYY-MM-DD');
tableApi.query();
};
let currentDate = ref<string>(dayjs().format('YYYY-MM-DD'));
// 切换视图模式
function handleViewModeChange(e: RadioChangeEvent): void {
// 将父组件的isCalenderView变为false
emit('changeView', e.target.value);
}
@@ -45,11 +49,11 @@ const gridOptions: VxeGridProps = {
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
return await arrangementList({
query: async ({ page }) => {
return await queryScheduleView({
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
currentDate: currentDate.value,
});
},
},
@@ -115,7 +119,7 @@ async function handleDelete(row: Required<ArrangementForm>) {
v-model:value="value"
:fullscreen="false"
:mode="'month'"
@panelChange="onPanelChange"
@select="onSelect"
/>
</div>
</div>
@@ -133,7 +137,7 @@ async function handleDelete(row: Required<ArrangementForm>) {
<Popconfirm
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认除?"
title="确认除?"
@confirm="handleDelete(row)"
>
<ghost-button
@@ -141,7 +145,7 @@ async function handleDelete(row: Required<ArrangementForm>) {
v-access:code="['property:arrangement:remove']"
@click.stop=""
>
{{ $t('pages.common.delete') }}
移除
</ghost-button>
</Popconfirm>
</Space>
@@ -153,4 +157,8 @@ async function handleDelete(row: Required<ArrangementForm>) {
<ArrangementModal @reload="tableApi.query()" />
</div>
</template>
<style></style>
<style scoped>
:deep(.ant-radio-group) {
display: none;
}
</style>