This commit is contained in:
BianLzhaoMin 2025-08-19 10:59:45 +08:00
parent 527d0ce3c1
commit ad055f2554
4 changed files with 242 additions and 132 deletions

View File

@ -60,26 +60,26 @@ export const getPostTypeSelectListAPI = () => {
// 获取标段工程下拉列表 ----- 携带查询条件的 // 获取标段工程下拉列表 ----- 携带查询条件的
export function getLotProjectSelectListByConditionAPI(data) { export function getLotProjectSelectListByConditionAPI(data) {
return request({ return request({
url: '/bmw/pmProject/listAll', url: '/bmw/select/selectPro',
method: 'GET', method: 'POST',
params: data, data,
}) })
} }
// 获取分包商下拉列表 ----- 携带查询条件的 // 获取分包商下拉列表 ----- 携带查询条件的
export const getSubSelectListByConditionAPI = (data) => { export const getSubSelectListByConditionAPI = (data) => {
return request({ return request({
url: '/bmw/pmSub/listAll', url: '/bmw/select/selectSub',
method: 'GET', method: 'POST',
params: data, data,
}) })
} }
// 获取班组下拉列表 ----- 携带查询条件的 // 获取班组下拉列表 ----- 携带查询条件的
export const getTeamSelectListByConditionAPI = (data) => { export const getTeamSelectListByConditionAPI = (data) => {
return request({ return request({
url: '/bmw/pmSubTeam/listAll', url: '/bmw/select/selectTeam',
method: 'GET', method: 'POST',
params: data, data,
}) })
} }

View File

@ -1,7 +1,6 @@
<template> <template>
<div class="attendance-calendar"> <div class="attendance-calendar">
<!-- 图例说明 --> <div class="legend">
<div class="legend" v-if="isShowLegend">
<div class="legend-item"> <div class="legend-item">
<span class="legend-mark active"></span> <span class="legend-mark active"></span>
<span>已打卡</span> <span>已打卡</span>
@ -17,9 +16,9 @@
</div> </div>
<!-- 循环展示每个月份的日历 --> <!-- 循环展示每个月份的日历 -->
<div <div
v-for="(monthData, index) in monthDataList"
:key="index" :key="index"
class="month-calendar" class="month-calendar"
v-for="(monthData, index) in monthDataListNew"
> >
<!-- 月份标题 --> <!-- 月份标题 -->
<div class="calendar-header"> <div class="calendar-header">
@ -28,48 +27,32 @@
<!-- 星期标题 --> <!-- 星期标题 -->
<div class="week-days"> <div class="week-days">
<div class="week-day" v-for="day in weekDays" :key="day">{{ <div class="week-day" v-for="day in weekDays" :key="day">
day {{ day }}
}}</div> </div>
</div> </div>
<!-- 日历主体 --> <!-- 日历主体 -->
<div class="calendar-grid"> <div class="calendar-grid">
<!-- 空白占位月初 -->
<div <div
class="calendar-day empty" class="calendar-day empty"
:key="'empty-start-' + i" :key="'empty-start-' + i"
v-for="(empty, i) in getFirstMonthEmptyDays(monthData)" v-for="(empty, i) in monthData.emptyStartDays"
> >
</div> </div>
<!-- 本月日期 -->
<div <div
:key="day" :key="day.dayIndex"
class="calendar-day current-month" class="calendar-day current-month"
v-for="day in getDaysInMonth(monthData)" :class="getDayClass(day)"
:class="getDayClass(monthData, day)" v-for="day in monthData.currentMonthDays"
> >
<span class="day-number">{{ day }}</span> <span class="day-number">{{ day.dayIndex }}</span>
<!-- 当isActive为1时显示复选框 -->
<!-- <el-checkbox
v-if="getDayInfo(monthData, day)?.isActive === 1"
class="day-checkbox"
v-model="
checkedDays[
`${monthData.year}-${monthData.month}-${day}`
]
"
@change="handleCheckboxChange(monthData, day, $event)"
></el-checkbox> -->
<el-checkbox v-model="checked" />
</div> </div>
<!-- 空白占位月末 -->
<div <div
class="calendar-day empty" class="calendar-day empty"
v-for="(empty, i) in getLastMonthEmptyDays(monthData)" v-for="(empty, i) in monthData.emptyEndDays"
:key="'empty-end-' + i" :key="'empty-end-' + i"
> >
</div> </div>
@ -82,16 +65,16 @@
export default { export default {
name: 'AttendanceCalendar', name: 'AttendanceCalendar',
props: { props: {
// //
monthDataList: { timeRange: {
type: Array, type: Array,
default: () => [], default: () => [],
required: true,
}, },
isShowLegend: { //
type: Boolean, attendanceList: {
default: false, type: Array,
default: () => [],
}, },
}, },
data() { data() {
@ -99,12 +82,10 @@ export default {
weekDays: ['日', '一', '二', '三', '四', '五', '六'], weekDays: ['日', '一', '二', '三', '四', '五', '六'],
checkedDays: {}, // checkedDays: {}, //
checked: false, checked: false,
monthDataListNew: [], //
} }
}, },
created() {
//
this.initCheckedDays()
},
methods: { methods: {
// //
initCheckedDays() { initCheckedDays() {
@ -118,11 +99,110 @@ export default {
}) })
}, },
//
initCalendar(timeRange) {
const startMonth = timeRange[0].split('-')[1]
const endMonth = timeRange[1].split('-')[1]
const year = timeRange[0].split('-')[0]
this.monthDataListNew = []
if (startMonth !== endMonth) {
this.monthDataListNew.push({
month: startMonth,
year,
emptyStartDays: this.getFirstMonthEmptyDays({
month: startMonth,
year,
}),
emptyEndDays: this.getLastMonthEmptyDays({
month: startMonth,
year,
}),
currentMonthDays: this.getDaysInMonthNew({
month: startMonth,
year,
}),
})
this.monthDataListNew.push({
month: endMonth,
year,
emptyStartDays: this.getFirstMonthEmptyDays({
month: endMonth,
year,
}),
emptyEndDays: this.getLastMonthEmptyDays({
month: endMonth,
year,
}),
currentMonthDays: this.getDaysInMonthNew({
month: endMonth,
year,
}),
})
} else {
this.monthDataListNew.push({
month: startMonth,
year,
emptyStartDays: this.getFirstMonthEmptyDays({
month: startMonth,
year,
}),
emptyEndDays: this.getLastMonthEmptyDays({
month: startMonth,
year,
}),
currentMonthDays: this.getDaysInMonthNew({
month: startMonth,
year,
}),
})
}
},
//
initAttendanceList(attendanceList) {
if (attendanceList.length > 0) {
attendanceList.forEach((item) => {
const year = item.einDay.split('-')[0]
const month = item.einDay.split('-')[1]
this.monthDataListNew.forEach((j) => {
if (j.year == year && j.month == month) {
j.currentMonthDays.forEach((k) => {
if (k.zeroIndex == item.einDay.split('-')[2]) {
k.isAtt = item.isAtt
k.isRepair = item.isRepair
}
})
}
})
})
}
},
// //
getDaysInMonth(monthData) { getDaysInMonth(monthData) {
const year = parseInt(monthData.year) const year = parseInt(monthData.year)
const month = parseInt(monthData.month) const month = parseInt(monthData.month)
return new Date(year, month, 0).getDate() const days = new Date(year, month, 0).getDate()
return days
},
getDaysInMonthNew(monthData) {
const year = parseInt(monthData.year)
const month = parseInt(monthData.month)
const days = new Date(year, month, 0).getDate()
const dayList = []
for (let i = 1; i <= days * 1; i++) {
dayList.push({
dayIndex: i,
isAtt: null,
isRepair: false,
zeroIndex: i > 10 ? i : `0${i}`,
})
}
return dayList
}, },
// //
@ -136,10 +216,11 @@ export default {
getFirstMonthEmptyDays(monthData) { getFirstMonthEmptyDays(monthData) {
return this.getFirstDayOfMonth(monthData) return this.getFirstDayOfMonth(monthData)
}, },
// //
getLastMonthEmptyDays(monthData) { getLastMonthEmptyDays(monthData) {
console.log(monthData, 'monthData----')
const totalDays = this.getDaysInMonth(monthData) const totalDays = this.getDaysInMonth(monthData)
const lastDay = new Date( const lastDay = new Date(
parseInt(monthData.year), parseInt(monthData.year),
parseInt(monthData.month) - 1, parseInt(monthData.month) - 1,
@ -148,46 +229,29 @@ export default {
return 6 - lastDay return 6 - lastDay
}, },
//
getDayInfo(monthData, day) {
const dayStr = String(day).padStart(2, '0')
return monthData.day.find((item) => item.dayIndex === dayStr)
},
// //
getDayClass(monthData, day) { getDayClass(day) {
const dayInfo = this.getDayInfo(monthData, day) if (!day.isRepair && day.isAtt === 0) return 'inactive'
if (day.isRepair && day.isAtt === 1) return 'active'
// if (!day.isRepair) return 'is-no-att'
if (!dayInfo) {
return 'not-in-range'
}
return {
'not-in-range': !dayInfo.isRange,
active: dayInfo.isActive === 1,
inactive: dayInfo.isActive === 0,
}
},
//
handleCheckboxChange(monthData, day, checked) {
const dayStr = String(day).padStart(2, '0')
this.$emit('checkbox-change', {
year: monthData.year,
month: monthData.month,
day: dayStr,
checked,
})
}, },
}, },
watch: { watch: {
// timeRange: {
monthDataList: { handler(newVal) {
deep: true, console.log(newVal, 'newVal')
handler() { this.initCalendar(newVal)
this.initCheckedDays()
}, },
deep: true,
immediate: true,
},
attendanceList: {
handler(newVal) {
this.initAttendanceList(newVal)
},
deep: true,
}, },
}, },
} }
@ -196,9 +260,9 @@ export default {
<style scoped> <style scoped>
.attendance-calendar { .attendance-calendar {
font-family: 'Arial', sans-serif; font-family: 'Arial', sans-serif;
max-width: 700px; max-width: 90%;
min-width: 460px; min-width: 460px;
margin: 0 auto;
padding: 20px; padding: 20px;
border: 1px solid #e0e0e0; border: 1px solid #e0e0e0;
border-radius: 8px; border-radius: 8px;
@ -241,7 +305,7 @@ export default {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: #666; color: #666;
padding: 10px 0; padding: 2px 0;
} }
.calendar-grid { .calendar-grid {
@ -304,8 +368,8 @@ export default {
.legend { .legend {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 20px; gap: 10px;
margin-bottom: 20px; margin-bottom: 10px;
padding-bottom: 10px; padding-bottom: 10px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
@ -320,23 +384,24 @@ export default {
.legend-mark { .legend-mark {
display: inline-block; display: inline-block;
width: 36px; width: 24px;
height: 36px; height: 24px;
border-radius: 3px; border-radius: 3px;
} }
.legend-mark.active { .legend-mark.active {
background-color: #19be6b; background-color: #19be6b;
/* border: 1px solid #4cd964; */
} }
.legend-mark.inactive { .legend-mark.inactive {
background-color: #f56c6c; background-color: #f56c6c;
/* border: 1px solid #ff3b30; */
} }
.legend-mark.not-in-range { .legend-mark.not-in-range {
background-color: #ff9900; background-color: #ff9900;
/* border: 1px solid #ddd; */ }
.is-no-att {
background-color: #999;
} }
</style> </style>

View File

@ -7,7 +7,6 @@
size="small" size="small"
ref="queryFormRef" ref="queryFormRef"
label-width="auto" label-width="auto"
:model="queryParams"
> >
<el-form-item> <el-form-item>
<el-date-picker <el-date-picker
@ -17,7 +16,9 @@
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
end-placeholder="结束日期" end-placeholder="结束日期"
start-placeholder="开始日期" start-placeholder="开始日期"
v-model="queryParams.timeRange" @change="onHandleChangeTime"
v-model="timeRange"
:picker-options="pickerOptions"
/> />
</el-form-item> </el-form-item>
@ -55,7 +56,10 @@
<el-row :gutter="6"> <el-row :gutter="6">
<!-- 左侧考勤日历 --> <!-- 左侧考勤日历 -->
<el-col :span="12"> <el-col :span="12">
<!-- <AttendanceCalendar /> --> <AttendanceCalendar
:timeRange="timeRange"
:attendanceList="attendanceList"
/>
</el-col> </el-col>
<!-- 右侧考勤表格 --> <!-- 右侧考勤表格 -->
@ -109,12 +113,12 @@
</template> </template>
<script> <script>
// import AttendanceCalendar from '@/components/AttendanceCalendar' import AttendanceCalendar from '@/components/AttendanceCalendar'
import { getAttendanceDetailsListAPI } from '@/api/construction-person/attendance-manage/attendance-count' import { getAttendanceDetailsListAPI } from '@/api/construction-person/attendance-manage/attendance-count'
export default { export default {
name: 'AttendanceDetails', name: 'AttendanceDetails',
components: { components: {
// AttendanceCalendar, AttendanceCalendar,
}, },
props: { props: {
teamId: { teamId: {
@ -132,12 +136,10 @@ export default {
}, },
data() { data() {
return { return {
queryParams: { timeRange: [
timeRange: [ new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0], new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0], ],
],
},
attendanceList: [], attendanceList: [],
tableColumns: [ tableColumns: [
{ {
@ -162,22 +164,42 @@ export default {
t_props: 'deviceName', t_props: 'deviceName',
}, },
], ],
//
pickerOptions: {
disabledDate: (time) => {
//
return time.getTime() > Date.now()
},
onPick: ({ maxDate, minDate }) => {
//
this.pickerOptions.minDate = minDate
if (minDate) {
const maxRangeDate = new Date(minDate)
maxRangeDate.setMonth(minDate.getMonth() + 1)
this.pickerOptions.maxDate = maxRangeDate
} else {
this.pickerOptions.maxDate = null
}
},
},
} }
}, },
methods: { methods: {
// //
handleQuery() { handleQuery() {
console.log('查询')
this.getAttendanceDetailsListData() this.getAttendanceDetailsListData()
}, },
// //
resetQuery() { resetQuery() {
this.queryParams.timeRange = [] this.timeRange = [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
]
this.getAttendanceDetailsListData()
}, },
// //
onHandleExportAttendanceDetails() { onHandleExportAttendanceDetails() {},
console.log('导出')
},
// //
async getAttendanceDetailsListData() { async getAttendanceDetailsListData() {
@ -185,12 +207,36 @@ export default {
teamId: this.teamId, teamId: this.teamId,
proId: this.proId, proId: this.proId,
idNumber: this.idNumber, idNumber: this.idNumber,
startDate: this.queryParams.timeRange[0], startDate: this.timeRange[0],
endDate: this.queryParams.timeRange[1], endDate: this.timeRange[1],
} }
const { rows: res } = await getAttendanceDetailsListAPI(params) const { rows: res } = await getAttendanceDetailsListAPI(params)
this.attendanceList = res this.attendanceList = res
}, },
// change
onHandleChangeTime(e) {
if (e && e.length === 2) {
const [start, end] = e
const startDate = new Date(start)
const endDate = new Date(end)
//
const diffTime = Math.abs(endDate - startDate)
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
// 31
if (diffDays > 31) {
const newEndDate = new Date(startDate)
newEndDate.setDate(startDate.getDate() + 31)
this.timeRange = [
start,
newEndDate.toISOString().split('T')[0],
]
this.$message.warning(
'选择的时间范围不能超过31天已自动调整',
)
}
}
},
}, },
created() { created() {

View File

@ -921,16 +921,7 @@ export default {
}, },
// //
proSelectList: [ proSelectList: [],
{
label: '工程1',
value: '1',
},
{
label: '工程2',
value: '2',
},
],
// //
postSelectList: [], postSelectList: [],
// //
@ -1226,11 +1217,17 @@ export default {
onChangeProId(val) { onChangeProId(val) {
if (!val) { if (!val) {
this.keyInfoForm.proName = '' this.keyInfoForm.proName = ''
this.keyInfoForm.subId = ''
this.keyInfoForm.teamId = ''
this.subSelectList = []
this.teamSelectList = []
return return
} }
this.keyInfoForm.proName = this.proSelectList.find( this.keyInfoForm.proName = this.proSelectList.find(
(item) => item.value === val, (item) => item.value === val,
).label ).label
this.getSubSelectList({ proId: val })
}, },
// //
onChangePostId(val) { onChangePostId(val) {
@ -1246,11 +1243,15 @@ export default {
onChangeSubId(val) { onChangeSubId(val) {
if (!val) { if (!val) {
this.keyInfoForm.subName = '' this.keyInfoForm.subName = ''
this.keyInfoForm.teamId = ''
this.teamSelectList = []
return return
} }
this.keyInfoForm.subName = this.subSelectList.find( this.keyInfoForm.subName = this.subSelectList.find(
(item) => item.value === val, (item) => item.value === val,
).label ).label
this.getTeamSelectList({ subId: val })
}, },
// //
onChangeTeamId(val) { onChangeTeamId(val) {
@ -1391,33 +1392,33 @@ export default {
// //
async getLotProjectSelectList() { async getLotProjectSelectList() {
const { rows: res } = await getLotProjectSelectListByConditionAPI( const { data: res } = await getLotProjectSelectListByConditionAPI(
{}, {},
) )
this.proSelectList = res.map((item) => { this.proSelectList = res.map((item) => {
return { return {
value: item.id, value: item.id,
label: item.proName, label: item.name,
} }
}) })
}, },
// //
async getSubSelectList() { async getSubSelectList(data) {
const { rows: res } = await getSubSelectListByConditionAPI({}) const { data: res } = await getSubSelectListByConditionAPI(data)
this.subSelectList = res.map((item) => { this.subSelectList = res.map((item) => {
return { return {
value: item.id, value: item.id,
label: item.subName, label: item.name,
} }
}) })
}, },
// //
async getTeamSelectList() { async getTeamSelectList(data) {
const { rows: res } = await getTeamSelectListByConditionAPI({}) const { data: res } = await getTeamSelectListByConditionAPI(data)
this.teamSelectList = res.map((item) => { this.teamSelectList = res.map((item) => {
return { return {
value: item.id, value: item.id,
label: item.teamName, label: item.name,
} }
}) })
}, },
@ -1449,8 +1450,6 @@ export default {
} }
}) })
this.getSubSelectList()
this.getTeamSelectList()
this.getLotProjectSelectList() this.getLotProjectSelectList()
}, },