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) {
return request({
url: '/bmw/pmProject/listAll',
method: 'GET',
params: data,
url: '/bmw/select/selectPro',
method: 'POST',
data,
})
}
// 获取分包商下拉列表 ----- 携带查询条件的
export const getSubSelectListByConditionAPI = (data) => {
return request({
url: '/bmw/pmSub/listAll',
method: 'GET',
params: data,
url: '/bmw/select/selectSub',
method: 'POST',
data,
})
}
// 获取班组下拉列表 ----- 携带查询条件的
export const getTeamSelectListByConditionAPI = (data) => {
return request({
url: '/bmw/pmSubTeam/listAll',
method: 'GET',
params: data,
url: '/bmw/select/selectTeam',
method: 'POST',
data,
})
}

View File

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

View File

@ -7,7 +7,6 @@
size="small"
ref="queryFormRef"
label-width="auto"
:model="queryParams"
>
<el-form-item>
<el-date-picker
@ -17,7 +16,9 @@
value-format="yyyy-MM-dd"
end-placeholder="结束日期"
start-placeholder="开始日期"
v-model="queryParams.timeRange"
@change="onHandleChangeTime"
v-model="timeRange"
:picker-options="pickerOptions"
/>
</el-form-item>
@ -55,7 +56,10 @@
<el-row :gutter="6">
<!-- 左侧考勤日历 -->
<el-col :span="12">
<!-- <AttendanceCalendar /> -->
<AttendanceCalendar
:timeRange="timeRange"
:attendanceList="attendanceList"
/>
</el-col>
<!-- 右侧考勤表格 -->
@ -109,12 +113,12 @@
</template>
<script>
// import AttendanceCalendar from '@/components/AttendanceCalendar'
import AttendanceCalendar from '@/components/AttendanceCalendar'
import { getAttendanceDetailsListAPI } from '@/api/construction-person/attendance-manage/attendance-count'
export default {
name: 'AttendanceDetails',
components: {
// AttendanceCalendar,
AttendanceCalendar,
},
props: {
teamId: {
@ -132,12 +136,10 @@ export default {
},
data() {
return {
queryParams: {
timeRange: [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
],
},
timeRange: [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
],
attendanceList: [],
tableColumns: [
{
@ -162,22 +164,42 @@ export default {
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: {
//
handleQuery() {
console.log('查询')
this.getAttendanceDetailsListData()
},
//
resetQuery() {
this.queryParams.timeRange = []
this.timeRange = [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
]
this.getAttendanceDetailsListData()
},
//
onHandleExportAttendanceDetails() {
console.log('导出')
},
onHandleExportAttendanceDetails() {},
//
async getAttendanceDetailsListData() {
@ -185,12 +207,36 @@ export default {
teamId: this.teamId,
proId: this.proId,
idNumber: this.idNumber,
startDate: this.queryParams.timeRange[0],
endDate: this.queryParams.timeRange[1],
startDate: this.timeRange[0],
endDate: this.timeRange[1],
}
const { rows: res } = await getAttendanceDetailsListAPI(params)
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() {

View File

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