ylj20011123 a6692879e0 update
2025-08-19 17:22:15 +08:00

626 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 排班表 -->
<template>
<view class="main" :style="{ paddingTop: (menu.bottom + 28) + 'px' }">
<view class="summaryTab" :style="{ height: (menu.bottom + 14) + 'px' }">
<view class="leftArrow" :style="{ top: (menu.top + ((menu.height - 24) / 2)) + 'px' }">
<image class="img" src="https://eshangtech.com/ShopICO/ahyd-BID/commercial/navigation-left.svg"
@click="handleBack"></image>
<view class="picker" :style="{ top: (menu.bottom + 24) + 'px' }" @click="handleChangeService">
<view class="selectService">
<image class="img" src="https://eshangtech.com/ShopICO/ahyd-BID/commercial/fixed.svg"></image>
<view class="select">
<view class="content">
<view class="uni-input">{{ serviceInfo.SERVERPART_NAME ? serviceInfo.SERVERPART_NAME :
'' }}
</view>
<image class="rightArrow"
src="https://eshangtech.com/ShopICO/ahyd-BID/commercial/rightArrow.svg"></image>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="rosterContent">
<!-- 月份和员工选择器 -->
<view class="selectorRow">
<view class="dateBox">
<view class="centerDateBox">
<image class="arrowIcon" src="https://eshangtech.com/cyy_DIB/leftArrowIcon.png"
@click="handleChangeDate(2)" />
<view class="center">
<text class="date-text">{{ selectDate ? $util.cutDate(new Date(selectDate), 'YYYY-MM') :
""
}}</text>
<!-- <text class="date-icon">📅</text> -->
</view>
<image class="arrowIcon" src="https://eshangtech.com/cyy_DIB/rightArrowIcon.png"
@click="handleChangeDate(1)" />
</view>
</view>
<!-- 员工选择器 -->
<view class="employeeSelector">
<picker @change="handleEmployeeChange" :value="selectedEmployeeIndex" :range="userList"
:range-key="'userName'">
<view class="employeePickerBox">
<view class="selectedEmployee">{{ userList[selectedEmployeeIndex] ?
userList[selectedEmployeeIndex].userName :
'请选择员工' }}
</view>
<image class="rightArrow"
src="https://eshangtech.com/ShopICO/ahyd-BID/commercial/rightArrow.svg"></image>
</view>
</picker>
</view>
</view>
<!-- 员工信息 -->
<view v-if="selectedEmployee" class="employeeDetail">
<view class="employeeCard">
<view class="employeeInfo">
<view class="employeeName">{{ selectedEmployee.userName }}</view>
<view class="employeeJob">{{ selectedEmployee.psnJob }}</view>
<image class="phoneIcon" src="https://eshangtech.com/cyy_DIB/phoneIcon.png" />
<view class="employeePhone">{{ selectedEmployee.phone }}</view>
</view>
</view>
</view>
<!-- 日历格式排班表 -->
<view v-if="selectedEmployee" class="calendarRoster">
<view class="weekHeader">
<view v-for="(weekName, index) in weekNames" :key="index" class="weekHeaderItem"
:class="{ 'weekend': index === 0 || index === 6 }">
{{ weekName }}
</view>
</view>
<view class="calendarGrid">
<view v-for="i in firstDayOfWeek" :key="`empty-${i}`" class="calendarCell empty"></view>
<view v-for="day in monthDays" :key="day.date" class="calendarCell" :class="{
'weekend': day.isWeekend,
'today': day.isToday
}">
<view class="dateNumber">{{ day.day }}</view>
<view class="scheduleInfo" :class="{
'work': selectedEmployee && selectedEmployee[`day${day.day}`] && !selectedEmployee[`day${day.day}`].toString().toLowerCase().includes('休'),
'rest': selectedEmployee && selectedEmployee[`day${day.day}`] && selectedEmployee[`day${day.day}`].toString().toLowerCase().includes('休'),
'empty': !selectedEmployee || !selectedEmployee[`day${day.day}`]
}">
{{ selectedEmployee && selectedEmployee[`day${day.day}`] ?
(selectedEmployee[`day${day.day}`].toString().toLowerCase().includes('休') ? '休' : '班') : ''
}}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
const now = new Date()
const currentYear = now.getFullYear()
const currentMonthIndex = now.getMonth()
const nowDay = this.$util.cutDate(new Date(), 'YYYY-MM-DD') // 有数据的最近日期
return {
menu: {},
selectDate: nowDay,// 选中的时间
serviceInfo: {},
currentYear: currentYear,
currentMonth: currentMonthIndex,
selectedEmployeeIndex: 0,
selectedEmployee: null,
weekNames: ['日', '一', '二', '三', '四', '五', '六'],
// 模拟排班数据,实际使用时从接口获取
rosterData: [],
userList: [],// 员工的数组
selectUser: "",//当前选择的员工
isFirst: true,
monthDays: [],
firstDayOfWeek: ""
}
},
computed: {
// 获取月份第一天是星期几 (0=周日, 1=周一, ..., 6=周六)
// firstDayOfWeek() {
// const firstDay = new Date(this.currentYear, this.currentMonth, 1)
// return firstDay.getDay()
// }
},
onLoad() {
this.menu = uni.getMenuButtonBoundingClientRect()
let currentService = uni.getStorageSync('currentService')
this.serviceInfo = currentService
this.handleGetNewMonthData()
// 加载排班数据
this.loadRosterData(currentService.SERVERPART_NAME)
},
onShow() {
let currentService = uni.getStorageSync('currentService')
console.log('currentService', currentService);
// 防护:检查 currentService 是否有效
if (!currentService || (!currentService.Serverpart_ID && !currentService.SERVERPART_ID)) {
console.warn('currentService 为空或无效,跳过更新');
this.isFirst = false;
return;
}
// 获取统一的服务区ID
const currentServiceId = currentService.Serverpart_ID || currentService.SERVERPART_ID;
const currentServiceName = currentService.SERVERPART_NAME;
// 只有当服务区真正发生变化且不是首次加载时才更新
if (currentServiceId && currentServiceId !== this.serviceInfo.SERVERPART_ID && !this.isFirst) {
this.serviceInfo = currentService
this.rosterData = []
this.userList = []
this.selectUser = null
this.loadRosterData(currentServiceName)
} else {
this.isFirst = false;
}
},
methods: {
handleGetNewMonthData() {
const year = this.currentYear
const month = this.currentMonth
console.log('yearyearyear', year);
console.log('monthmonthmonthmonth', month);
const daysInMonth = new Date(year, month + 1, 0).getDate()
const today = new Date()
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
const days = []
const weekTexts = ['日', '一', '二', '三', '四', '五', '六']
for (let day = 1; day <= daysInMonth; day++) {
const date = new Date(year, month, day)
const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`
const weekDay = date.getDay()
days.push({
day: day,
date: dateStr,
weekDay: weekDay,
weekText: weekTexts[weekDay],
isWeekend: weekDay === 0 || weekDay === 6,
isToday: dateStr === todayStr
})
}
this.monthDays = days
const firstDay = new Date(this.currentYear, this.currentMonth, 1)
this.firstDayOfWeek = firstDay.getDay()
},
handleChangeService() {
this.$util.toNextRoute("navigateTo", "/pages/map/index?type=attendanceStatus");
},
// 修改日期
async handleChangeDate(type) {
// type 1 加一天 2 减一天
// 兼容 iOS把 2025-08-15 转成 2025/08/15
const cur = new Date((this.selectDate || '').replace(/-/g, '/'));
if (Number.isNaN(cur.getTime())) return;
// 1加一月2减一月其他不变
const delta = type === 1 ? 1 : (type === 2 ? -1 : 0);
// 目标月份的最后一天new Date(年, 目标月+1, 0)
const last = new Date(cur.getFullYear(), cur.getMonth() + delta + 1, 0);
const y = last.getFullYear();
const m = String(last.getMonth() + 1).padStart(2, '0');
const d = String(last.getDate()).padStart(2, '0');
this.selectDate = `${y}-${m}-${d}`;
// 修复currentMonth应该是数字类型0-11而不是字符串
this.currentYear = y
this.currentMonth = last.getMonth() // 使用数字类型的月份索引
this.handleGetNewMonthData()
this.handleGetCurrentUserScheduleInfo()
},
// 返回上一页
handleBack() {
uni.navigateBack()
},
// 员工选择变化
handleEmployeeChange(e) {
console.log('eee', e);
this.selectedEmployeeIndex = Number(e.detail.value)
this.selectUser = this.userList && this.userList.length > 0 ? this.userList[this.selectedEmployeeIndex] : ""
this.handleGetCurrentUserScheduleInfo()
},
// 加载排班数据
async loadRosterData(SERVERPART_NAME) {
// 先拿到人员列表
let req = {
bsessionKey: "0B30475A94674D608022885F7763959B",
workTime: new Date(this.selectDate).getTime(),
saName: SERVERPART_NAME || "",// 服务区名称
phone: "",// 手机号码
}
uni.showLoading({
title: "加载中..."
})
const data = await new Promise((resolve, reject) => {
uni.request({
url: "https://fwqznxj.yciccloud.com:9081/ynjt/pushManage/queryUserSchedule",
method: "POST",
data: req,
header: {
"content-type": "application/x-www-form-urlencoded",
},
success(res) {
resolve(res.data.data)
},
});
});
uni.hideLoading()
console.log('人员列表', data);
this.userList = data
this.selectedEmployeeIndex = 0
this.selectUser = data && data.length > 0 ? data[0] : ""
console.log('this.selectUserthis.selectUserthis.selectUser', this.selectUser);
await this.handleGetCurrentUserScheduleInfo()
},
// 拿到当前用户的排班信息
async handleGetCurrentUserScheduleInfo() {
this.selectedEmployee = null
let req = {
bsessionKey: "20ED2B50179D4877853C4DED45D8179E",
date: new Date(this.selectDate).getTime(),
phone: this.selectUser.phone
}
const data = await new Promise((resolve, reject) => {
uni.request({
url: "https://fwqznxj.yciccloud.com:9081/ynjt/pushManage/queryWorkDetails",
method: "POST",
data: req,
header: {
"content-type": "application/x-www-form-urlencoded",
},
success(res) {
resolve(res.data.data)
},
});
});
console.log('datadatadatadatadata', data);
this.selectedEmployee = data[0]
}
}
}
</script>
<style lang="less" scoped>
@bg: #f8f9fa;
@muted: #666;
@card: #fff;
@shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
@primary: #27B25F;
@primary2: #4CCC7F;
@ok: #2ed573;
@warn: #ff9f43;
@danger: #ff4757;
.main {
width: 100vw;
min-height: 100vh;
background-color: #f0f2f3;
box-sizing: border-box;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
padding: 16rpx 32rpx 0;
.summaryTab {
position: fixed;
left: 0;
top: 0;
width: 100vw;
background-image: url("https://eshangtech.com/minTestImg/pageBg.png");
z-index: 99;
display: flex;
align-items: center;
box-sizing: border-box;
padding-bottom: 16px;
.leftArrow {
width: 100%;
height: 24px;
position: absolute;
z-index: 99999999999;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0 32rpx;
.img {
width: 24px;
height: 24px;
margin-right: 8px;
z-index: 99;
}
.picker {
.selectService {
display: flex;
align-items: center;
.img {
width: 40px;
height: 40px;
z-index: 2;
}
.select {
height: 32px;
background: #fff;
border-radius: 0 16px 16px 0;
transform: translateX(-40px);
box-sizing: border-box;
padding-left: 35px;
padding-right: 8rpx;
display: flex;
align-items: center;
.content {
display: flex;
align-items: center;
.uni-input {
padding: 0;
background: transparent;
font-size: 28rpx;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #160002;
}
.rightArrow {
width: 12px;
height: 12px;
}
}
}
}
}
}
}
.rosterContent {
width: 100%;
background-color: #fff;
box-sizing: border-box;
padding: 0 24rpx 8rpx;
border-radius: 8rpx;
/* 选择器行布局 */
.selectorRow {
display: flex;
gap: 24rpx;
padding: 24rpx 0;
align-items: center;
justify-content: space-between;
}
.dateBox {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
.centerDateBox {
display: flex;
align-items: center;
gap: 10rpx;
border-radius: 30rpx;
background-color: #fff;
// border: 2rpx solid #27B35F;
// background: rgba(255, 255, 255, .15);
.arrowIcon {
width: 40rpx;
height: 40rpx;
}
.center {
.date-text {
font-size: 28rpx;
font-weight: 700;
}
}
}
}
/* 员工选择器 */
.employeeSelector {
.employeePickerBox {
display: flex;
align-items: center;
justify-content: space-between;
// padding: 20rpx 24rpx;
// background: #f8f9fa;
border-radius: 30rpx;
// border: 2rpx solid #e0e0e0;
.selectedEmployee {
font-size: 24rpx;
font-weight: 400;
color: #000;
margin-right: 8rpx;
}
.rightArrow {
width: 26rpx;
height: 26rpx;
}
}
}
/* 员工信息卡片 */
.employeeDetail {
margin-bottom: 32rpx;
.employeeCard {
background: #fff;
border-radius: 12rpx;
padding: 16rpx 24rpx;
box-shadow: @shadow;
.employeeInfo {
display: flex;
align-items: center;
.employeeName {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-right: 24rpx;
}
.employeeJob {
font-size: 24rpx;
color: @primary;
background: rgba(39, 178, 95, 0.1);
padding: 0 16rpx;
border-radius: 20rpx;
margin-right: 24rpx;
}
.phoneIcon {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
}
.employeePhone {
font-size: 24rpx;
color: #666;
}
}
}
}
/* 日历格式排班表 */
.calendarRoster {
background: #fff;
border-radius: 12rpx;
// padding: 32rpx;
box-shadow: @shadow;
margin-bottom: 32rpx;
/* 星期标题 */
.weekHeader {
display: flex;
border-bottom: 2rpx solid #e0e0e0;
// margin-bottom: 16rpx;
.weekHeaderItem {
flex: 1;
text-align: center;
padding: 16rpx 0;
font-size: 28rpx;
font-weight: 600;
color: #333;
&.weekend {
color: @danger;
}
}
}
/* 日历网格 */
.calendarGrid {
display: flex;
flex-wrap: wrap;
width: 100%;
.calendarCell {
width: 14.28%;
height: 120rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1rpx solid #f0f0f0;
box-sizing: border-box;
position: relative;
&.empty {
background-color: #fafafa;
}
&.today {
background-color: rgba(39, 178, 95, 0.1);
border: 2rpx solid @primary;
}
&.weekend {
.dateNumber {
// color: @danger;
}
}
.dateNumber {
font-size: 24rpx;
font-weight: 500;
color: #333;
margin-bottom: 4rpx;
}
.scheduleInfo {
font-size: 24rpx;
padding: 2rpx 4rpx;
border-radius: 4rpx;
font-weight: 500;
text-align: center;
line-height: 1;
&.work {
// background-color: #333;
color: #000;
}
&.rest {
// background-color: #f5f5f5;
// color: #999;
color: red;
}
&.empty {
visibility: hidden;
}
}
}
}
}
}
}
</style>