1689 lines
60 KiB
Vue
1689 lines
60 KiB
Vue
<template>
|
||
<page-meta :page-style="'overflow:' + (showPopup ? 'hidden' : 'visible')"></page-meta>
|
||
<view class="main" :style="{ paddingTop: (menu.bottom + 14) + '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.SAName ? serviceInfo.SAName :
|
||
'' }}
|
||
</view>
|
||
<!-- <p class="area">{{ serviceInfo.SPREGIONTYPE_NAME ? serviceInfo.SPREGIONTYPE_NAME : '' }} -->
|
||
<!-- </p> -->
|
||
<image class="rightArrow"
|
||
src="https://eshangtech.com/ShopICO/ahyd-BID/commercial/rightArrow.svg"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 服务区的信息 -->
|
||
<view class="serviceDetail" style="margin-top: 16rpx;">
|
||
<view class="detailTop">
|
||
<view class="serviceImg" v-if="serviceInfo.fileId && serviceInfo.fileId.length > 0">
|
||
<swiper scroll-x="true" circular="true" class="banner" indicator-dots="true"
|
||
indicator-active-color="#272625" autoplay interval="3000" :current="pageMsg.current"
|
||
style="width: 100%; height: 100%">
|
||
<swiper-item v-for="(img, i) in serviceInfo.fileId" :key="i" style="width: 100%; height: 100%">
|
||
<image style="width: 100%; height: 100%" mode="aspectFill" lazy-load="true"
|
||
:src="img.fileID ? 'https://fwqznxj.yciccloud.com:9081/fileDownloadApi/bsys/document/docDownloadAction?fileId=' + img.fileID : 'https://eshangtech.com/ShopICO/ahyd-BID/service/default.png'">
|
||
</image>
|
||
</swiper-item>
|
||
</swiper>
|
||
</view>
|
||
<view v-else class="serviceImg">
|
||
<image style="width: 100%; height: 100%" mode="aspectFill" lazy-load="true"
|
||
:src="'https://eshangtech.com/ShopICO/ahyd-BID/service/default.png'">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<!-- <view class="detailBottom">
|
||
<view class="detailFirst">
|
||
<text class="serviceName">{{
|
||
serviceInfo.SERVERPART_NAME || ""
|
||
}}</text>
|
||
<text class="serviceStatus">营业中</text>
|
||
</view>
|
||
<view class="detailSecond">
|
||
<image class="detailFixedIcon" src="/static/images/home/address.png" />
|
||
<text class="address">
|
||
<text class="distance">{{
|
||
serviceInfo.SERVERPART_DISTANCE === 0
|
||
? 0
|
||
: serviceInfo.SERVERPART_DISTANCE || "-"
|
||
}}km</text>
|
||
<text class="addressText">{{ serviceInfo.ServerpartInfo.SERVERPART_ADDRESS || "-"
|
||
}}{{ serviceInfo.ServerpartInfo.EXPRESSWAY_NAME || "-" }}</text>
|
||
</text>
|
||
</view>
|
||
<view class="navigationBox" @click="handleGomap">
|
||
<image class="navigationIcon" src="/static/images/home/navigationIcon.svg" />
|
||
</view>
|
||
</view> -->
|
||
</view>
|
||
|
||
<!-- 插入日历 即悬浮框 -->
|
||
<uni-calendar ref="calendar" class="selectDateCalendar" :mask-closable="true" :clear-date="true"
|
||
:date="selectDate" :insert="false" :startDate="info.startDate" :range="info.range"
|
||
@confirm="handleChangeTime" />
|
||
|
||
|
||
<view class="thingBox">
|
||
<!-- 特情事件提醒横幅 -->
|
||
<view class="emergency-banner" @click="showEmergencyDetails(1)">
|
||
<view class="emergency-header">
|
||
<view class="emergency-title">
|
||
<text>🚨 应急事件</text>
|
||
<view class="emergency-count">{{ emergencyListLength }}</view>
|
||
</view>
|
||
<!-- <text>👉</text> -->
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<!-- 一般警告提醒 -->
|
||
<view class="warning-banner" @click="showEmergencyDetails(2)">
|
||
<view class="emergency-header">
|
||
<view class="emergency-title">
|
||
<text>⚠️ 日常问题</text>
|
||
<view class="emergency-count">{{ dailyListLength }}</view>
|
||
</view>
|
||
<!-- <text>👉</text> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 人员类型的tab -->
|
||
<view class="personTabBox">
|
||
<view :class="selectTab === 1 ? 'personItem personItemSelect' : 'personItem '" @click="handleChangeTab(1)">
|
||
<view class="personValue">{{ onDutyPersonList && onDutyPersonList.length > 0 ? onDutyPersonList.length :
|
||
0 }}
|
||
</view>
|
||
<view class="personLabel">在岗人员</view>
|
||
</view>
|
||
|
||
<view :class="selectTab === 2 ? 'personItem personItemSelect' : 'personItem '" @click="handleChangeTab(2)">
|
||
<view class="personValue">{{ EmployeesOnLeaveList && EmployeesOnLeaveList.length > 0 ?
|
||
EmployeesOnLeaveList.length : 0 }}</view>
|
||
<view class="personLabel">请假人员</view>
|
||
</view>
|
||
|
||
<!-- <view :class="selectTab === 3 ? 'personItem personItemSelect' : 'personItem '" @click="handleChangeTab(3)">
|
||
<view class="personValue">1</view>
|
||
<view class="personLabel">值班经理</view>
|
||
</view> -->
|
||
</view>
|
||
|
||
<!-- 在岗人员 -->
|
||
<view class="onDutyPersonBox">
|
||
<view class="onDutyPersonBoxHeader">
|
||
<text class="title">{{ selectTab === 1 ? "👥 当前在岗人员" : selectTab === 2 ? "📋 请假人员列表" : selectTab === 3
|
||
? "👑 值班经理信息" : ""
|
||
}}</text>
|
||
|
||
|
||
<!-- 居中的日历时间 -->
|
||
<view class="dateBox">
|
||
<view class="centerDateBox">
|
||
<image class="arrowIcon" src="https://eshangtech.com/cyy_DIB/leftArrowIcon.png"
|
||
@click="handleChangeDate(2)" />
|
||
<view class="center" @click="open">
|
||
<text class="date-text">{{ selectDate }}</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="tab-indicators">
|
||
<view class="tab-dot" :class="{ active: selectTab === 1 }"></view>
|
||
<view class="tab-dot" :class="{ active: selectTab === 2 }"></view>
|
||
</view> -->
|
||
</view>
|
||
|
||
<!-- 当前在岗人员 -->
|
||
<view class="onDutyPersonList" v-if="selectTab === 1">
|
||
<view class="onDutyPersonItem" v-for="(item, index) in onDutyPersonList" :key="index"
|
||
@click="viewStaffDetails(item)">
|
||
<view class="avatar" v-if="!item.phone">{{ item.userName ? item.userName.slice(0, 1) : "" }}</view>
|
||
<image class="avatar" v-else
|
||
:src="`https://fwqznxj.yciccloud.com:9081/fileDownloadApi/bsys/file/thumbnail/download/${item.phone}`" />
|
||
<view class="staffInfo">
|
||
<view class="staffInfoLeft">
|
||
<view class="staffInfoTop">
|
||
<view class="staff-name">{{ item.userName || "" }}</view>
|
||
<view class="staff-role" v-if="item.userJob">{{ item.userJob }}</view>
|
||
</view>
|
||
<view class="staff-status">
|
||
<view class="status-badge status-online" v-if="item.workType">{{ item.workType }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="staffInfoRight" @click.stop="handleCallPhone(item.phone)">
|
||
<image class="phoneIcon" src="https://eshangtech.com/cyy_DIB/phoneIcon.png" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 请假人员 -->
|
||
<view class="EmployeesOnLeaveList" v-if="selectTab === 2">
|
||
<view class="EmployeesOnLeaveItem" v-for="(item, index) in EmployeesOnLeaveList" :key="index"
|
||
@click="viewStaffDetails(item)">
|
||
<view class="avatar" v-if="!item.phone">{{ item.userName ? item.userName.slice(0, 1) : "" }}</view>
|
||
<image class="avatar" v-else
|
||
:src="`https://fwqznxj.yciccloud.com:9081/fileDownloadApi/bsys/file/thumbnail/download/${item.phone}`" />
|
||
<view class="staffInfo">
|
||
<view class="staffInfoLeft">
|
||
<view class="staffInfoTop">
|
||
<view class="staff-name">{{ item.userName || "" }}</view>
|
||
<view class="staff-role">{{ item.userJob || "" }}</view>
|
||
</view>
|
||
<view class="staff-status">
|
||
<view class="status-badge status-rest" v-if="item.workType">{{ item.workType }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="staffInfoRight" @click.stop="handleCallPhone(item.phone)">
|
||
<image class="phoneIcon" src="https://eshangtech.com/cyy_DIB/phoneIcon.png" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 值班经理 -->
|
||
<view class="dutyManagerList" v-if="selectTab === 3">
|
||
<view class="dutyManagerItem" v-for="(item, index) in dutyManagerList" :key="index"
|
||
@click="viewStaffDetails(item)">
|
||
<view class="avatar manager-avatar" v-if="!item.phone">{{ item.userName ? item.userName.slice(0, 1)
|
||
: "" }}</view>
|
||
<image class="avatar manager-avatar" v-else
|
||
:src="`https://fwqznxj.yciccloud.com:9081/fileDownloadApi/bsys/file/thumbnail/download/${item.phone}`" />
|
||
<view class="staffInfoBox">
|
||
<view class="staffInfo">
|
||
<view class="staffInfoLeft">
|
||
<view class="staffInfoTop">
|
||
<view class="staff-name manager-name">{{ item.name || "" }}</view>
|
||
<view class="staff-role manager-role">👑{{ item.post || "-" }}</view>
|
||
</view>
|
||
<view class="staff-status">
|
||
<view class="status-badge status-manager">值班中</view>
|
||
</view>
|
||
</view>
|
||
<view class="staffInfoRight" @click.stop="handleCallPhone(item.phone)">
|
||
<image class="phoneIcon" src="https://eshangtech.com/cyy_DIB/phoneIcon.png" />
|
||
</view>
|
||
</view>
|
||
<view class="staff-address">{{ item.address }}</view>
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<!-- 其他跳转链接 -->
|
||
<view class="otherJumpUrl">
|
||
<view class="jumpItem" v-for="(item, index) in jumpItemList" :key="index"
|
||
@click="handleClickJump(item.value)">
|
||
<image class="jumpIcon" :src="item.url" />
|
||
<view class="jumpText">{{ item.label }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 会员详情 -->
|
||
<uni-popup ref="popup" border-radius="10px 10px 0 0" @change="handlePopupChange">
|
||
<view class="userPopupBox" v-if="userDetail">
|
||
<view class="userBoxTitle">人员详情</view>
|
||
<view class="userDetailBox">
|
||
<view class="userAvatar">
|
||
<image class="userAvatarIcon" v-if="userDetail.phone"
|
||
:src="`https://fwqznxj.yciccloud.com:9081/fileDownloadApi/bsys/file/thumbnail/download/${userDetail.phone}`" />
|
||
<view class="userAvatarBox" v-else>{{ userDetail.userName ? userDetail.userName.slice(0, 1) : ""
|
||
}}
|
||
</view>
|
||
</view>
|
||
<view class="userDetailRight">
|
||
<view class="userDetailTop">
|
||
<view class="userDetailName">{{ userDetail.userName || "" }}</view>
|
||
<view class="userDetailStatus" v-if="userDetail.workType" :style="{
|
||
background: userDetail.workType === '班' || userDetail.workType === '差' || userDetail.workType === '出' ? '#27B25F' : '#F6F6F6',
|
||
color: userDetail.workType === '班' || userDetail.workType === '差' || userDetail.workType === '出' ? '#fff' : '#9FA6A3',
|
||
}">{{ userDetail.workType }}</view>
|
||
</view>
|
||
<view class="userDetailPostBox">
|
||
<span class="userDetailLabel">岗位:</span>
|
||
<span class="userDetailValue">{{ userDetail.userJob || "-" }}</span>
|
||
</view>
|
||
<view class="userDetailPhoneBox">
|
||
<span class="userDetailLabel">电话:</span>
|
||
<span class="userDetailValue">{{ userDetail.phone || "" }}</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="line"></view>
|
||
|
||
<view class="userBoxTitle">当前出勤情况</view>
|
||
<view class="attendanceStatusBox">
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">当前排班信息:</view>
|
||
<view class="attendanceStatusValue" v-if="userDetail.workType">{{ userDetail.workType }}</view>
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">上班打卡地:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.dutyClockInPlace || "" }}</view>
|
||
<!-- dutyClockInPlace -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">上班打卡时间:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.dutyClockInTime || "" }}</view>
|
||
<!-- dutyClockInTime -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">迟到时长:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.lateNum || "" }}</view>
|
||
<!-- lateNum -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">下班打卡地:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.offDutyClockInPlace || "" }}</view>
|
||
<!-- offDutyClockInPlace -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">下班打卡时间:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.offDutyClockInTime || "" }}</view>
|
||
<!-- offDutyClockInTime -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">早退时长:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.earlyNum || "" }}</view>
|
||
<!-- earlyNum -->
|
||
</view>
|
||
</view>
|
||
<view class="line"></view>
|
||
|
||
|
||
<view class="userBoxTitle">考勤统计</view>
|
||
<view class="attendanceStatusBox">
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">当月排班天数:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.scheduleTotal || "" }}</view>
|
||
<!-- scheduleTotal -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">出勤天数:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.attendTotal || "" }}</view>
|
||
<!-- attendTotal -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">休息天数:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.restTotal || "" }}</view>
|
||
<!-- restTotal -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">迟到天数:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.lateTotal || "" }}</view>
|
||
<!-- lateTotal -->
|
||
</view>
|
||
<view class="attendanceStatusItem">
|
||
<view class="attendanceStatusLabel">早退天数:</view>
|
||
<view class="attendanceStatusValue">{{ userDetail.earlyTotal || "" }}</view>
|
||
<!-- earlyTotal -->
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import request from "@/util/index.js";
|
||
import { formatTime } from '@/util/dateTime/index.js'
|
||
export default {
|
||
data() {
|
||
const nowDay = this.$util.cutDate(new Date(), 'YYYY-MM-DD') // 有数据的最近日期
|
||
return {
|
||
menu: {},
|
||
serviceInfo: {},
|
||
selectDate: nowDay,// 选中的时间
|
||
info: {
|
||
startDate: "2025-01-01"
|
||
},
|
||
selectTab: 1,
|
||
onDutyPersonList: [],// 在岗人员 1 在岗 2 休息 3 调休 4 请假 5 旷工 6 迟到
|
||
EmployeesOnLeaveList: [],// 请假人员列表
|
||
dutyManagerList: [
|
||
// { name: "王五", post: "经理", status: 1, phone: "6666", address: "G56杭瑞高速主干道昆明至滇西方向" },
|
||
],// 值班经理
|
||
jumpItemList: [
|
||
// { label: "应急事件", value: 1, url: "https://eshangtech.com/cyy_DIB/funIcon1.png" },
|
||
{ label: "设施状态", value: 2, url: "https://eshangtech.com/cyy_DIB/funIcon2.png" },
|
||
{ label: "考勤统计", value: 3, url: "https://eshangtech.com/cyy_DIB/funIcon3.png" },
|
||
{ label: "排班表", value: 5, url: "https://eshangtech.com/cyy_DIB/funIcon5.png" },
|
||
// { label: "请假管理", value: 4, url: "https://eshangtech.com/cyy_DIB/funIcon4.png" },
|
||
// { label: "通知公告", value: 6, url: "https://eshangtech.com/cyy_DIB/funIcon6.png" },
|
||
],
|
||
showPopup: false,
|
||
userDetail: null,
|
||
isFirst: true,
|
||
emergencyListLength: 0,
|
||
dailyListLength: 0,
|
||
};
|
||
},
|
||
onLoad() {
|
||
this.menu = uni.getMenuButtonBoundingClientRect()
|
||
let currentService = uni.getStorageSync('currentService')
|
||
console.log('currentServicecurrentServicecurrentService', currentService);
|
||
|
||
// 防护:确保 currentService 存在
|
||
if (currentService && (currentService.SAName || currentService.SACode)) {
|
||
this.serviceInfo = {
|
||
...currentService,
|
||
}
|
||
this.handleGetCurrentServiceAttendanceData(currentService.SAName)
|
||
this.handleGetEventsData(currentService.SAName)
|
||
} else {
|
||
console.warn('onLoad: currentService 为空或无效')
|
||
// 可以考虑跳转回服务区选择页面或显示错误提示
|
||
}
|
||
},
|
||
onShow() {
|
||
let currentService = uni.getStorageSync('currentService')
|
||
console.log('onShowonShowonShowonShow', currentService);
|
||
|
||
// 防护:检查 currentService 是否有效
|
||
if (!currentService || (!currentService.SACode)) {
|
||
console.warn('currentService 为空或无效,跳过更新');
|
||
this.isFirst = false;
|
||
return;
|
||
}
|
||
|
||
// 获取统一的服务区ID
|
||
const currentServiceId = currentService.SACode;
|
||
const currentServiceName = currentService.SAName;
|
||
|
||
// 只有当服务区真正发生变化且不是首次加载时才更新
|
||
if (currentServiceId && currentServiceId !== this.serviceInfo.SACode && !this.isFirst) {
|
||
this.emergencyListLength = 0
|
||
this.dailyListLength = 0
|
||
this.serviceInfo = {
|
||
...currentService,
|
||
}
|
||
// this.handleGetServerpartDetail(currentServiceId);
|
||
this.handleGetCurrentServiceAttendanceData(currentServiceName);
|
||
this.handleGetEventsData(currentServiceName)
|
||
} else {
|
||
this.isFirst = false;
|
||
}
|
||
},
|
||
methods: {
|
||
// 现在异步调用一个方法 拿到 该服务区应急事件、日常事件
|
||
async handleGetEventsData(saName) {
|
||
const req = {
|
||
bsessionKey: "EA65F66FA29B47FD8072A4AFC66967B3",
|
||
saName: saName || this.serviceInfo.SAName
|
||
}
|
||
console.log('reqreq', req);
|
||
|
||
const data = await new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: "https://fwqznxj.yciccloud.com:9081/ynjt/pushManage/queryEmergency",
|
||
method: "POST",
|
||
data: req,
|
||
header: {
|
||
"content-type": "application/x-www-form-urlencoded",
|
||
},
|
||
success(res) {
|
||
resolve(res.data.data)
|
||
},
|
||
});
|
||
});
|
||
let emergencyList = data
|
||
|
||
|
||
const req2 = {
|
||
bsessionKey: "0DAF3A5982D54A619D4B63A34CA20C55",
|
||
saName: saName || this.serviceInfo.SAName
|
||
}
|
||
const data2 = await new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: "https://fwqznxj.yciccloud.com:9081/ynjt/pushManage/queryQuestions",
|
||
method: "POST",
|
||
data: req2,
|
||
header: {
|
||
"content-type": "application/x-www-form-urlencoded",
|
||
},
|
||
success(res) {
|
||
resolve(res.data.data)
|
||
},
|
||
});
|
||
});
|
||
let dailyList = data2
|
||
|
||
|
||
console.log('emergencyListemergencyListemergencyList', emergencyList);
|
||
console.log('dailyListdailyListdailyListdailyListdailyList', dailyList);
|
||
|
||
|
||
this.emergencyListLength = emergencyList && emergencyList.length > 0 ? emergencyList.length : "0"
|
||
this.dailyListLength = dailyList && dailyList.length > 0 ? dailyList.length : "0"
|
||
|
||
},
|
||
// 拿到当前服务区的考勤数据
|
||
async handleGetCurrentServiceAttendanceData(SERVERPART_NAME) {
|
||
// 防护:如果服务区名称为空,则不执行请求
|
||
if (!SERVERPART_NAME) {
|
||
return;
|
||
}
|
||
|
||
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()
|
||
|
||
this.onDutyPersonList = []
|
||
this.EmployeesOnLeaveList = []
|
||
// 当前服务区的人员信息
|
||
let list = data
|
||
console.log("listlistlistlistlistlistlistlist", list);
|
||
|
||
// 上班人员信息
|
||
let workPersonList = []
|
||
// 请假人员信息
|
||
let leaveList = []
|
||
|
||
if (list && list.length > 0) {
|
||
list.forEach((item) => {
|
||
item.dutyClockInTime = item.dutyClockInTime ? formatTime(item.dutyClockInTime) : ""
|
||
item.offDutyClockInTime = item.offDutyClockInTime ? formatTime(item.offDutyClockInTime) : ""
|
||
if (item.workType === '班' || item.workType === '差' || item.workType === '出') {
|
||
workPersonList.push(item)
|
||
} else {
|
||
leaveList.push(item)
|
||
}
|
||
})
|
||
}
|
||
this.onDutyPersonList = workPersonList
|
||
this.EmployeesOnLeaveList = leaveList
|
||
|
||
},
|
||
// 修改日期
|
||
async handleChangeDate(type) {
|
||
// type 1 加一天 2 减一天
|
||
// 兼容 iOS,把 2025-08-15 转成 2025/08/15
|
||
const date = new Date(this.selectDate.replace(/-/g, "/"));
|
||
|
||
if (type === 1) {
|
||
date.setDate(date.getDate() + 1); // 加一天
|
||
} else if (type === 2) {
|
||
date.setDate(date.getDate() - 1); // 减一天
|
||
}
|
||
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||
const day = String(date.getDate()).padStart(2, "0");
|
||
|
||
this.selectDate = `${year}-${month}-${day}`;
|
||
|
||
console.log('serviceInfo', this.serviceInfo);
|
||
await this.handleGetCurrentServiceAttendanceData(this.serviceInfo.SAName)
|
||
},
|
||
// 查询服务区详情
|
||
async handleGetServerpartDetail(id) {
|
||
// 防护:如果ID为空,则不执行请求
|
||
if (!id) {
|
||
console.warn('handleGetServerpartDetail: id 为空,跳过请求');
|
||
return;
|
||
}
|
||
|
||
let currentService = uni.getStorageSync("currentService");
|
||
let seatInfo = uni.getStorageSync("seatInfo");
|
||
this.seatInfo = JSON.parse(seatInfo || '{}');
|
||
let req = {
|
||
ServerpartId: id,
|
||
latitude: this.seatInfo.latitude || 0,
|
||
longitude: this.seatInfo.longitude || 0,
|
||
};
|
||
console.log('req', req);
|
||
|
||
uni.showLoading({
|
||
title: "加载中...",
|
||
});
|
||
|
||
const data = await request.$webGet(
|
||
"/CommercialApi/BaseInfo/GetServerpartInfo",
|
||
req
|
||
);
|
||
uni.hideLoading();
|
||
|
||
let obj = data.Result_Data;
|
||
this.serviceInfo = obj;
|
||
this.$forceUpdate();
|
||
|
||
console.log('this.serviceInfo', this.serviceInfo);
|
||
|
||
},
|
||
// 打开导航
|
||
handleGomap() {
|
||
let obj = this.serviceInfo;
|
||
uni.openLocation({
|
||
latitude: obj.latitude ? obj.latitude * 1 : obj.SERVERPART_Y * 1,
|
||
longitude: obj.longitude ? obj.longitude * 1 : obj.SERVERPART_X * 1,
|
||
scale: 16, // 缩放比例
|
||
name: obj.SAName,
|
||
// address: "", // 这个可能会影响地图的定位,所以可以选择不填
|
||
success(data) {
|
||
},
|
||
fail(err) {
|
||
},
|
||
});
|
||
},
|
||
handleChangeService() {
|
||
this.$util.toNextRoute("navigateTo", "/pages/map/index?type=attendanceStatus");
|
||
},
|
||
open() {
|
||
this.$refs.calendar.open()
|
||
},
|
||
handlePopupChange(e) {
|
||
this.showPopup = e.show
|
||
console.log('e', e);
|
||
if (!e.show) {
|
||
this.userDetail = null
|
||
}
|
||
},
|
||
handleBack() {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
},
|
||
// 改变查询时间
|
||
async handleChangeTime(e) {
|
||
console.log('e', e);
|
||
// this.selectDate = e.detail.value
|
||
this.selectDate = e.fulldate
|
||
|
||
await this.handleGetCurrentServiceAttendanceData(this.serviceInfo.SAName)
|
||
},
|
||
// 切换tab
|
||
handleChangeTab(e) {
|
||
this.selectTab = e
|
||
},
|
||
// 打电话
|
||
handleCallPhone(phone) {
|
||
uni.makePhoneCall({
|
||
phoneNumber: phone
|
||
});
|
||
},
|
||
// 跳转应急事件页面
|
||
showEmergencyDetails(type) {
|
||
// type 1 应急事件 2 日常问题
|
||
this.$util.toNextRoute("navigateTo", `/pages/attendanceStatus/emergencyEvents?type=${type}`);
|
||
},
|
||
// 跳转其他页面
|
||
handleClickJump(value) {
|
||
if (value === 1) {
|
||
this.showEmergencyDetails(1)
|
||
} else if (value === 2) {
|
||
// this.$util.toNextRoute("navigateTo", `/pages/attendanceStatus/serviceFacility`);
|
||
this.$util.toNextRoute('navigateTo', `/pages/summaryOfPortraits/index?index=0`)
|
||
} else if (value === 3) {
|
||
this.$util.toNextRoute('navigateTo', `/pages/attendanceStatus/attendanceStatistics`)
|
||
} else if (value === 5) {
|
||
this.$util.toNextRoute('navigateTo', `/pages/attendanceStatus/roster`)
|
||
}
|
||
},
|
||
// 会员详情信息
|
||
viewStaffDetails(obj) {
|
||
this.$refs.popup.open('center')
|
||
this.userDetail = obj
|
||
}
|
||
},
|
||
|
||
onUnload() {
|
||
|
||
}
|
||
};
|
||
</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-image: url("https://eshangtech.com/minTestImg/pageBg.png");
|
||
background-color: #F5F5F5;
|
||
box-sizing: border-box;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
|
||
.summaryTab {
|
||
position: fixed;
|
||
left: 0;
|
||
top: 0;
|
||
width: 100vw;
|
||
// background: #fff;
|
||
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;
|
||
// left: 16px;
|
||
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: 14px;
|
||
font-family: PingFangSC-Semibold, PingFang SC;
|
||
font-weight: 600;
|
||
color: #160002;
|
||
line-height: 50rpx;
|
||
height: 50rpx;
|
||
}
|
||
|
||
.area {
|
||
font-size: 12px;
|
||
font-family: PingFangSC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
color: #786B6C;
|
||
line-height: 40px;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
.rightArrow {
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
|
||
.noticeText {
|
||
font-size: 24rpx;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
color: #B6BACB;
|
||
line-height: 40rpx;
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
.serviceDetail {
|
||
width: calc(100% - 64rpx);
|
||
background: #ffffff;
|
||
border-radius: 16rpx;
|
||
margin-left: 32rpx;
|
||
|
||
.detailTop {
|
||
width: 100%;
|
||
height: 320rpx;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
|
||
.serviceImg {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.detailBottom {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 4rpx 24rpx 24rpx;
|
||
position: relative;
|
||
|
||
.detailFirst {
|
||
width: 100%;
|
||
|
||
.serviceName {
|
||
width: calc(100% - 190rpx);
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 600;
|
||
font-size: 30rpx;
|
||
color: #130f05;
|
||
line-height: 52rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.serviceStatus {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
color: #009f43;
|
||
line-height: 32rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
display: inline-block;
|
||
padding: 2rpx 6rpx;
|
||
background: #e9f8ee;
|
||
border-radius: 4rpx;
|
||
}
|
||
}
|
||
|
||
.detailSecond {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.detailFixedIcon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 4rpx;
|
||
}
|
||
|
||
.address {
|
||
width: calc(100% - 120rpx);
|
||
display: inline-block;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
|
||
.distance {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #130f05;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.addressText {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
.navigationBox {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
position: absolute;
|
||
right: 24rpx;
|
||
top: 32rpx;
|
||
|
||
.navigationIcon {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
.selectDateCalendar {
|
||
/deep/ .uni-calendar-item__weeks-box-item {
|
||
width: calc(100% / 7);
|
||
}
|
||
|
||
/deep/ .uni-calendar-item--checked {
|
||
background-color: #3CC071;
|
||
}
|
||
|
||
/deep/ .uni-calendar-item--isDay {
|
||
background-color: #3CC071;
|
||
color: #fff !important;
|
||
}
|
||
|
||
/deep/ .uni-calendar-item--isDay-text {
|
||
white-space: nowrap;
|
||
color: #000;
|
||
}
|
||
|
||
/deep/ .uni-calendar__backtoday {
|
||
background-color: #3CC071;
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
.personTabBox {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 0 32rpx;
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 16rpx;
|
||
margin-top: 24rpx;
|
||
|
||
.personItem {
|
||
background: #fff;
|
||
padding: 30rpx;
|
||
border-radius: 24rpx;
|
||
text-align: center;
|
||
box-shadow: @shadow;
|
||
|
||
.personValue {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: @primary;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.personLabel {
|
||
font-size: 24rpx;
|
||
color: @muted;
|
||
}
|
||
}
|
||
|
||
.personItemSelect {
|
||
background: linear-gradient(135deg, @primary, @primary2);
|
||
color: #fff;
|
||
|
||
.personValue {
|
||
color: #fff;
|
||
}
|
||
|
||
.personLabel {
|
||
color: rgba(255, 255, 255, .9);
|
||
}
|
||
}
|
||
}
|
||
|
||
.thingBox {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 0 32rpx;
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 16rpx;
|
||
margin-top: 24rpx;
|
||
|
||
.emergency-banner {
|
||
background: linear-gradient(135deg, @danger, #ff3838);
|
||
color: #fff;
|
||
padding: 20rpx 30rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 12rpx rgba(255, 71, 87, .3);
|
||
border-left: 8rpx solid #ff1744;
|
||
|
||
.emergency-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
// margin-bottom: 10rpx;
|
||
|
||
.emergency-title {
|
||
font-weight: 700;
|
||
font-size: 28rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.emergency-count {
|
||
background: rgba(255, 255, 255, .3);
|
||
padding: 4rpx 16rpx;
|
||
border-radius: 24rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
.emergency-preview {
|
||
font-size: 24rpx;
|
||
opacity: .9;
|
||
}
|
||
}
|
||
|
||
.warning-banner {
|
||
background: linear-gradient(135deg, @warn, #ff8c00);
|
||
color: #fff;
|
||
padding: 20rpx 30rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 12rpx rgba(255, 159, 67, .3);
|
||
border-left: 8rpx solid #ff8c00;
|
||
|
||
.emergency-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
// margin-bottom: 10rpx;
|
||
}
|
||
|
||
.emergency-title {
|
||
font-weight: 700;
|
||
font-size: 28rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.emergency-count {
|
||
background: rgba(255, 255, 255, .3);
|
||
padding: 4rpx 16rpx;
|
||
border-radius: 24rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.emergency-preview {
|
||
font-size: 24rpx;
|
||
opacity: .9;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
.onDutyPersonBox {
|
||
width: calc(100% - 64rpx);
|
||
margin: 32rpx;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
box-shadow: @shadow;
|
||
|
||
.onDutyPersonBoxHeader {
|
||
background: @bg;
|
||
padding: 10rpx 30rpx;
|
||
border-bottom: 1rpx solid #e9ecef;
|
||
font-weight: 700;
|
||
font-size: 28rpx;
|
||
color: #2c3e50;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.tab-indicators {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.tab-dot {
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
border-radius: 50%;
|
||
background: #ddd;
|
||
|
||
&.active {
|
||
background: @primary;
|
||
}
|
||
}
|
||
}
|
||
|
||
.dateBox {
|
||
box-sizing: border-box;
|
||
padding: 16rpx 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.centerDateBox {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
padding: 10rpx 20rpx;
|
||
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;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.onDutyPersonList {
|
||
.onDutyPersonItem {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #f1f3f4;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.avatar {
|
||
width: 90rpx;
|
||
height: 90rpx;
|
||
border-radius: 50%;
|
||
background: linear-gradient(270deg, #27B25F 0%, #4CCC7F 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
font-weight: 700;
|
||
margin-right: 30rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.staffInfo {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.staffInfoLeft {
|
||
flex: 1;
|
||
|
||
.staffInfoTop {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 8rpx;
|
||
|
||
.staff-name {
|
||
font-weight: 600;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.staff-role {
|
||
color: @muted;
|
||
font-size: 24rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
|
||
.staff-status {
|
||
font-size: 24rpx;
|
||
|
||
.status-badge {
|
||
display: inline-block;
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
|
||
&.status-online {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
}
|
||
|
||
&.status-absentee {
|
||
background: #ff0000;
|
||
color: #fff;
|
||
}
|
||
|
||
&.status-beLate {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.staffInfoRight {
|
||
width: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.phoneIcon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-left: 8rpx;
|
||
background-color: #fff;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.EmployeesOnLeaveList {
|
||
.EmployeesOnLeaveItem {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #f1f3f4;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.avatar {
|
||
width: 90rpx;
|
||
height: 90rpx;
|
||
border-radius: 50%;
|
||
background: linear-gradient(270deg, #27B25F 0%, #4CCC7F 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
font-weight: 700;
|
||
margin-right: 30rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.staffInfo {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.staffInfoLeft {
|
||
flex: 1;
|
||
|
||
.staffInfoTop {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 8rpx;
|
||
|
||
.staff-name {
|
||
font-weight: 600;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.staff-role {
|
||
color: @muted;
|
||
font-size: 24rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
|
||
.staff-status {
|
||
font-size: 24rpx;
|
||
|
||
.status-badge {
|
||
display: inline-block;
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
|
||
&.status-rest {
|
||
background: #F6F6F6;
|
||
color: #9FA6A3;
|
||
}
|
||
|
||
&.status-adjust {
|
||
background: #fff3cd;
|
||
color: #856404;
|
||
}
|
||
|
||
&.status-leave {
|
||
background: #FF8B3F;
|
||
color: #fff;
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.staffInfoRight {
|
||
width: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.phoneIcon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-left: 8rpx;
|
||
background-color: #fff;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.dutyManagerList {
|
||
.dutyManagerItem {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #f1f3f4;
|
||
background: #E7F8EE;
|
||
border: 4rpx solid #27B25F;
|
||
border-radius: 24rpx;
|
||
margin: 20rpx;
|
||
box-shadow: 0 8rpx 24rpx #E7F8EE;
|
||
|
||
.avatar {
|
||
width: 90rpx;
|
||
height: 90rpx;
|
||
border-radius: 50%;
|
||
background: linear-gradient(270deg, #27B25F 0%, #4CCC7F 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
font-weight: 700;
|
||
margin-right: 30rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.manager-avatar {
|
||
background: linear-gradient(135deg, #27B25F, #4CCC7F);
|
||
border: 6rpx solid #27B25F;
|
||
box-shadow: 0 4rpx 16rpx #E7F8EE;
|
||
}
|
||
|
||
.manager-name {
|
||
color: #27B25F;
|
||
font-size: 36rpx;
|
||
}
|
||
|
||
.manager-role {
|
||
color: #ff9800;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.manager-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
|
||
.contact-btn,
|
||
.locate-btn {
|
||
background: linear-gradient(135deg, #ff9800, #f57c00);
|
||
border: none;
|
||
color: #fff;
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32rpx;
|
||
}
|
||
}
|
||
|
||
.staffInfoBox {
|
||
flex: 1;
|
||
|
||
.staffInfo {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 6rpx;
|
||
|
||
.staffInfoLeft {
|
||
flex: 1;
|
||
|
||
.staffInfoTop {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 6rpx;
|
||
|
||
.staff-name {
|
||
font-weight: 700;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.staff-role {
|
||
color: @muted;
|
||
font-size: 26rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
|
||
.staff-status {
|
||
font-size: 24rpx;
|
||
margin-bottom: 6rpx;
|
||
|
||
.status-badge {
|
||
display: inline-block;
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
|
||
&.status-online {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
}
|
||
|
||
&.status-break {
|
||
background: #fff3cd;
|
||
color: #856404;
|
||
}
|
||
|
||
&.status-offline {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
}
|
||
|
||
&.status-manager {
|
||
background: linear-gradient(135deg, #27B25F, #4CCC7F);
|
||
color: #fff;
|
||
border: 1rpx solid #27B25F;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.staffInfoRight {
|
||
width: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.phoneIcon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-left: 8rpx;
|
||
background-color: #E7F8EE;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
}
|
||
|
||
.staff-address {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716F69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
.otherJumpUrl {
|
||
width: calc(100% - 64rpx);
|
||
margin: 0 32rpx;
|
||
background-color: #fff;
|
||
box-shadow: @shadow;
|
||
box-sizing: border-box;
|
||
padding: 24rpx;
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
|
||
.jumpItem {
|
||
width: 25%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.jumpIcon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.jumpText {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716F69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
.userPopupBox {
|
||
width: 90vw;
|
||
height: 80vh;
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
box-sizing: border-box;
|
||
padding: 24rpx;
|
||
overflow-y: auto;
|
||
|
||
.userBoxTitle {
|
||
width: 100%;
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.userDetailBox {
|
||
width: 100%;
|
||
margin-top: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.userAvatar {
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
margin-right: 20rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.userAvatarIcon {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.userAvatarBox {
|
||
width: 70%;
|
||
height: 70%;
|
||
border-radius: 50%;
|
||
background: linear-gradient(270deg, #27B25F 0%, #4CCC7F 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
font-weight: 700;
|
||
margin-right: 30rpx;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
|
||
.userDetailRight {
|
||
flex: 1;
|
||
|
||
.userDetailTop {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.userDetailName {
|
||
display: inline-block;
|
||
max-width: 70%;
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.userDetailStatus {
|
||
display: inline-block;
|
||
padding: 0 8rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
|
||
.userDetailPostBox,
|
||
.userDetailPhoneBox {
|
||
.userDetailLabel {
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.userDetailValue {
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.line {
|
||
width: 100%;
|
||
height: 2rpx;
|
||
background-color: #e4e3e3;
|
||
margin: 16rpx 0;
|
||
}
|
||
|
||
.attendanceStatusBox {
|
||
width: 100%;
|
||
margin-top: 24rpx;
|
||
|
||
.attendanceStatusItem {
|
||
width: 100%;
|
||
margin-bottom: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.attendanceStatusLabel {
|
||
width: 200rpx;
|
||
text-align: left;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.attendanceStatusValue {
|
||
flex: 1;
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 通用 */
|
||
.muted {
|
||
color: @muted;
|
||
}
|
||
|
||
.ml8 {
|
||
margin-left: 8px;
|
||
}
|
||
|
||
.h1 {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.pad15 {
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.m15 {
|
||
margin: 30rpx;
|
||
}
|
||
|
||
.p15 {
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.noMargin {
|
||
margin: 0;
|
||
}
|
||
|
||
.noPad {
|
||
padding: 0;
|
||
}
|
||
</style>
|