| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- <template>
- <div class="system-status">
- <!-- 搜索条件 -->
- <div class="search-conditions">
- <div class="time-range-switch">
- <div class="time-range-label">切换时间范围:</div>
- <div class="time-range-buttons">
- <button v-for="range in timeRanges" :key="range.value" :class="{ active: activeTimeRange === range.value }"
- @click="handleTimeRangeChange(range.value)">
- {{ range.label }}
- </button>
- </div>
- </div>
- <div class="custom-time-range">
- <div class="custom-time-label">自定义时间范围:</div>
- <div class="date-pickers" :class="{ 'custom-time-range-active': !!activeTimeRange }">
- <el-date-picker class="date-picker" v-model="startDate" type="date" style="width:110px" placeholder="开始时间"
- @change="handleDateChange" />
- <span class="date-separator">-</span>
- <el-date-picker class="date-picker" v-model="endDate" type="date" style="width:110px" placeholder="结束时间"
- @change="handleDateChange" />
- </div>
- </div>
- </div>
- <!-- 今日上岗科长 -->
- <div class="today-duty-section" v-if="dutySectionMaster">
- <div class="duty-label">今日上岗科长:</div>
- <div class="duty-name">{{ dutySectionMaster }}</div>
- </div>
- <!-- 遍历数组展示 -->
- <div class="quantity-overview">
- <div class="quantity-overview-item" v-for="item in attendanceItems" :key="item.id">
- <div>{{ item.label }}</div>
- <div style="font-size: 32px;">{{ item.value }}{{ item.unit }}</div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, reactive, onMounted, computed } from 'vue'
- import { getAttendanceStats, getAccuracyStatistics, selectUserListByRoleKey } from '@/api/largeScreen/largeScreen'
- import useUserStore from '@/store/modules/user'
- // 定义事件
- const emit = defineEmits(['timeRangeChange', 'dateChange'])
- // 时间范围选项
- const timeRanges = [
- { label: '近一周', value: 'week' },
- { label: '近一月', value: 'month' },
- { label: '近三月', value: 'quarter' },
- { label: '近半年', value: 'halfYear' },
- { label: '近一年', value: 'year' }
- ]
- // 内部状态管理
- const activeTimeRange = ref('year')
- const startDate = ref('')
- const endDate = ref('')
- // 出勤相关数据
- const attendanceStats = ref({})
- const accuracyStatistics = ref({})
- const userStore = useUserStore()
- // 今日上岗科长数据
- const dutySectionMaster = ref('')
- // 获取今日上岗科长数据
- const fetchDutySectionMaster = async () => {
- try {
- // 调用接口获取今日上岗用户列表
- const response = await selectUserListByRoleKey(['kezhang']) // 假设角色标识为'kezhang'
- const userList = response.data || []
- // 将数组中的userName拼接成字符串
- if (userList.length > 0) {
- const names = userList.map(user => user.nickName)
- dutySectionMaster.value = names.join('、')
- } else {
- // 如果没有数据,使用默认值
- dutySectionMaster.value = '暂无科长上岗'
- }
- } catch (error) {
- console.error('获取今日上岗科长数据失败:', error)
- // 出错时使用默认值
- dutySectionMaster.value = ''
- }
- }
- // 计算属性:用户角色
- const role = computed(() => {
- return userStore.roles || []
- })
- // 计算属性:当前用户信息
- const currentUser = computed(() => {
- return userStore.userInfo || {}
- })
- // 计算属性:是否为班组视图
- const isTeamView = computed(() => {
- return role.value.includes('banzuzhang') ? false : role.value.includes('banzuzhang')
- })
- // 计算属性:是否为个人视图
- const isIndividualView = computed(() => {
- return role.value.includes('banzuzhang') ? false : role.value.includes('SecurityCheck')
- })
- // 计算属性:出勤信息数组
- const attendanceItems = computed(() => {
- let res = {}
- if (role.value.includes('kezhang') || role.value.includes('test') || role.value.includes('zhijianke') || role.value.includes('admin')) {
- res = attendanceStats.value.stationLeaderStats || {}
- return [
- { id: 1, label: `在岗大队`, value: res?.dutyDeptName, unit: '' },
- { id: 2, label: '在岗班组', value: res?.onDutyTeamCount, unit: '' },
- { id: 3, label: '在岗人员', value: res?.onDutyPersonnelCount, unit: '' },
- { id: 4, label: '今日查获上报', value: res?.todaySeizureReportCount, unit: '' },
- { id: 5, label: '今日巡检问题', value: res?.todayCheckCorrectionCount, unit: '' },
- { id: 6, label: '今日抽问抽答', value: `${accuracyStatistics.value?.todayTaskCompletion?.completedCount || 0}/${accuracyStatistics.value?.todayTaskCompletion?.totalCount || 0}`, unit: '' }
- ]
- } else {
- res = attendanceStats.value.teamLeaderStats || attendanceStats.value.securityCheckStats || {}
- // 个人视图或非班组长角色
- return [
- { id: 1, label: '出勤班组', value: res?.attendanceTeamName, unit: '' },
- { id: 2, label: '出勤通道', value: res?.attendanceChannel, unit: '' },
- { id: 3, label: '出勤时间', value: res?.attendanceTime || res?.attendanceTimeTips, unit: '' }
- ]
- }
- })
- const handleTimeRangeChange = (range) => {
- activeTimeRange.value = range
- emit('timeRangeChange', range)
- }
- // 处理日期变化
- const handleDateChange = () => {
- if (startDate.value && endDate.value) {
- // 当选择自定义时间时,将activeTimeRange置为空
- activeTimeRange.value = ''
- emit('dateChange', {
- startDate: startDate.value,
- endDate: endDate.value
- })
- }
- }
- // 获取出勤统计数据
- const fetchAttendanceStats = async () => {
- try {
- const response = await getAttendanceStats({})
- attendanceStats.value = response.data || {}
- } catch (error) {
- console.error('获取出勤统计数据失败:', error)
- }
- }
- // 获取正确率统计数据
- const fetchAccuracyStatistics = async () => {
- try {
- const response = await getAccuracyStatistics({})
- accuracyStatistics.value = response.data || {}
- } catch (error) {
- console.error('获取正确率统计数据失败:', error)
- }
- }
- // 组件挂载时获取数据
- onMounted(() => {
- fetchAttendanceStats()
- fetchAccuracyStatistics()
- fetchDutySectionMaster()
- })
- </script>
- <style lang="scss" scoped>
- .system-status {
- height: 100%;
- display: flex;
- flex-direction: column;
- gap: 10px;
- .search-conditions {
- justify-content: center;
- display: flex;
- align-items: center;
- gap: 20px;
- padding: 15px 15px 0 15px;
- // background: rgba(255, 255, 255, 0.05);
- border-radius: 8px;
- .time-range-switch {
- display: flex;
- align-items: center;
- gap: 10px;
- .time-range-label {
- font-size: 14px;
- color: #fff;
- white-space: nowrap;
- }
- .time-range-buttons {
- display: flex;
- gap: 4px;
- button {
- padding: 3px 9px;
- border: none;
- background: rgba(255, 255, 255, 0.1);
- color: #797979;
- background-color: #0A3551;
- border-radius: 4px;
- cursor: pointer;
- font-size: 12px;
- transition: all 0.3s;
- // &:hover {
- // background: rgba(255, 255, 255, 0.2);
- // }
- &.active {
- background: #0C4F7A;
- color: #fff;
- }
- }
- }
- }
- .custom-time-range {
- display: flex;
- align-items: center;
- gap: 10px;
- .custom-time-label {
- font-size: 14px;
- color: #fff;
- white-space: nowrap;
- }
- .custom-time-range-active {
- :deep(.el-input__wrapper) {
- background-color: #0A3551 !important;
- border: none;
- box-shadow: none;
- .el-input__inner {
- color: #797979;
- }
- }
- }
- .date-pickers {
- display: flex;
- align-items: center;
- gap: 8px;
-
- .date-separator {
- color: #fff;
- font-size: 12px;
- }
- :deep(.el-input__icon) {
- display: none;
- }
- :deep(.el-input__wrapper) {
- background-color: #0C4F7A;
- border: none;
- box-shadow: none;
- .el-input__inner {
- // color: #797979;
- }
- }
- }
- }
- }
- .today-duty-section {
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 10px 15px;
- background: rgba(255, 255, 255, 0.05);
- border: 1px solid #044878;
- border-radius: 8px;
- color: #fff;
- font-size: 16px;
- .duty-label {
- font-weight: bold;
- color: #35D8FF;
- }
- .duty-name {
- color: #70D3EE;
- font-weight: bold;
- }
- }
- .quantity-overview {
- height: 100%;
- width: 100%;
- display: flex;
- flex-wrap: wrap;
- column-gap: 25px;
- row-gap: 15px;
- // padding: 20px 20px 10px;
- box-sizing: border-box;
- color: #fff;
- font-size: 20px;
- .quantity-overview-item {
- flex: 0 0 calc(33.333% - 16.67px);
- // min-height:100px;
- background: #051E40;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- row-gap: 10px;
- border-radius: 5px;
- font-weight: bold;
- }
- }
- }
- </style>
|