|
|
@@ -5,9 +5,9 @@
|
|
|
<view class="search-bar">
|
|
|
<view class="search-box">
|
|
|
<image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
|
|
|
- <input
|
|
|
- class="search-input"
|
|
|
- placeholder="搜索工单编号、风机编号"
|
|
|
+ <input
|
|
|
+ class="search-input"
|
|
|
+ placeholder="搜索工单编码、风机编号"
|
|
|
v-model="searchKeyword"
|
|
|
@confirm="handleSearch"
|
|
|
/>
|
|
|
@@ -18,22 +18,22 @@
|
|
|
<!-- 工单分类筛选 -->
|
|
|
<view class="status-bar">
|
|
|
<view class="status-box">
|
|
|
- <text
|
|
|
- class="status-txt"
|
|
|
+ <text
|
|
|
+ class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '' }"
|
|
|
@click="filterByOrderType('')"
|
|
|
>
|
|
|
全部
|
|
|
</text>
|
|
|
- <text
|
|
|
- class="status-txt"
|
|
|
+ <text
|
|
|
+ class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '1' }"
|
|
|
@click="filterByOrderType('1')"
|
|
|
>
|
|
|
维修工单
|
|
|
</text>
|
|
|
- <text
|
|
|
- class="status-txt"
|
|
|
+ <text
|
|
|
+ class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '2' }"
|
|
|
@click="filterByOrderType('2')"
|
|
|
>
|
|
|
@@ -47,22 +47,22 @@
|
|
|
<view class="stats-header">
|
|
|
<text class="stats-title">{{ timeRangeTitle }}工时统计</text>
|
|
|
<view class="time-filters">
|
|
|
- <text
|
|
|
- class="time-filter"
|
|
|
+ <text
|
|
|
+ class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'week' }"
|
|
|
@click="changeTimeRange('week')"
|
|
|
>
|
|
|
本周
|
|
|
</text>
|
|
|
- <text
|
|
|
- class="time-filter"
|
|
|
+ <text
|
|
|
+ class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'month' }"
|
|
|
@click="changeTimeRange('month')"
|
|
|
>
|
|
|
本月
|
|
|
</text>
|
|
|
- <text
|
|
|
- class="time-filter"
|
|
|
+ <text
|
|
|
+ class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'custom' }"
|
|
|
@click="showCustomDatePicker"
|
|
|
>
|
|
|
@@ -77,7 +77,7 @@
|
|
|
<text class="hours-value">{{ totalHours }}小时</text>
|
|
|
<text class="hours-label">{{ timeRangeTitle }}总工时</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="hours-breakdown">
|
|
|
<view v-if="orderTypeFilter !== '1'" class="breakdown-item">
|
|
|
<text class="breakdown-label">维保工时</text>
|
|
|
@@ -96,14 +96,14 @@
|
|
|
</view>
|
|
|
|
|
|
<!-- 工单列表 -->
|
|
|
- <common-list
|
|
|
- :dataList="orderList"
|
|
|
- :loading="loading"
|
|
|
- :refreshing="refreshing"
|
|
|
- :hasMore="hasMore"
|
|
|
- @refresh="handleRefresh"
|
|
|
- @loadMore="loadMore"
|
|
|
- @itemClick="handleItemClick"
|
|
|
+ <common-list
|
|
|
+ :dataList="orderList"
|
|
|
+ :loading="loading"
|
|
|
+ :refreshing="refreshing"
|
|
|
+ :hasMore="hasMore"
|
|
|
+ @refresh="handleRefresh"
|
|
|
+ @loadMore="loadMore"
|
|
|
+ @itemClick="handleItemClick"
|
|
|
class="list-with-padding"
|
|
|
>
|
|
|
<template #default="{ item, index }">
|
|
|
@@ -141,7 +141,7 @@
|
|
|
<text class="cancel-btn" @click="closeDatePicker">取消</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="date-picker-container">
|
|
|
<view class="date-picker-item">
|
|
|
<text class="date-label">开始时间</text>
|
|
|
@@ -149,7 +149,7 @@
|
|
|
{{ startDate != null && startDate != '' ? startDate : '请选择开始时间' }}
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="date-picker-item">
|
|
|
<text class="date-label">结束时间</text>
|
|
|
<view class="date-display" @click="openEndDatePicker">
|
|
|
@@ -159,27 +159,27 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</l-popup>
|
|
|
-
|
|
|
+
|
|
|
<!-- Start Date Picker -->
|
|
|
<l-popup v-model="showStartDatePicker" position="bottom">
|
|
|
- <l-date-time-picker
|
|
|
- :mode="7"
|
|
|
+ <l-date-time-picker
|
|
|
+ :mode="7"
|
|
|
format="YYYY-MM-DD"
|
|
|
:modelValue="startDate"
|
|
|
- confirm-btn="确定"
|
|
|
+ confirm-btn="确定"
|
|
|
cancel-btn="取消"
|
|
|
@confirm="onStartDateConfirm"
|
|
|
@cancel="showStartDatePicker = false">
|
|
|
</l-date-time-picker>
|
|
|
</l-popup>
|
|
|
-
|
|
|
+
|
|
|
<!-- End Date Picker -->
|
|
|
<l-popup v-model="showEndDatePicker" position="bottom">
|
|
|
- <l-date-time-picker
|
|
|
- :mode="7"
|
|
|
+ <l-date-time-picker
|
|
|
+ :mode="7"
|
|
|
format="YYYY-MM-DD"
|
|
|
:modelValue="endDate"
|
|
|
- confirm-btn="确定"
|
|
|
+ confirm-btn="确定"
|
|
|
cancel-btn="取消"
|
|
|
@confirm="onEndDateConfirm"
|
|
|
@cancel="showEndDatePicker = false">
|
|
|
@@ -196,7 +196,7 @@ import { ref, computed, onMounted } from 'vue'
|
|
|
import { listOrderHours, getOrderHourStatistics } from '@/api/worktime/index'
|
|
|
import { getDictDataByType } from '@/api/dict/index'
|
|
|
import type { SysDictData } from '@/types/dict'
|
|
|
-
|
|
|
+
|
|
|
// 数据状态
|
|
|
const searchKeyword = ref<string>('')
|
|
|
const orderTypeFilter = ref<string>('')
|
|
|
@@ -215,7 +215,7 @@ const totalRankingUsers = ref<number | null>(null)
|
|
|
// 弹窗显示状态
|
|
|
const showDatePickerPopup = ref<boolean>(false)
|
|
|
const showStartDatePicker = ref<boolean>(false)
|
|
|
-const showEndDatePicker = ref<boolean>(false)
|
|
|
+const showEndDatePicker = ref<boolean>(false)
|
|
|
|
|
|
// 自定义日期表单
|
|
|
const startDate = ref<string>('')
|
|
|
@@ -241,7 +241,7 @@ const timeRangeTitle = computed(() => {
|
|
|
default:
|
|
|
return '本月'
|
|
|
}
|
|
|
-})
|
|
|
+})
|
|
|
|
|
|
// 获取工单状态字典列表
|
|
|
const loadStatusDictList = async (): Promise<void> => {
|
|
|
@@ -251,7 +251,7 @@ const loadStatusDictList = async (): Promise<void> => {
|
|
|
if (resultObj['code'] == 200) {
|
|
|
const data = resultObj['data'] as any[]
|
|
|
const dictData: SysDictData[] = []
|
|
|
-
|
|
|
+
|
|
|
if (data != null && data.length > 0) {
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
const item = data[i] as UTSJSONObject
|
|
|
@@ -273,7 +273,7 @@ const loadStatusDictList = async (): Promise<void> => {
|
|
|
dictData.push(dictItem)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
statusDictList.value = dictData
|
|
|
dictLoaded.value = true
|
|
|
}
|
|
|
@@ -288,11 +288,11 @@ const loadInspectionTypeDictList = async (): Promise<void> => {
|
|
|
try {
|
|
|
const result = await getDictDataByType('gxt_inspection_type')
|
|
|
const resultObj = result as UTSJSONObject
|
|
|
-
|
|
|
+
|
|
|
if (resultObj['code'] == 200) {
|
|
|
const data = resultObj['data'] as any[]
|
|
|
const dictData: SysDictData[] = []
|
|
|
-
|
|
|
+
|
|
|
if (data != null && data.length > 0) {
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
const item = data[i] as UTSJSONObject
|
|
|
@@ -314,7 +314,7 @@ const loadInspectionTypeDictList = async (): Promise<void> => {
|
|
|
dictData.push(dictItem)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
inspectionTypeDictList.value = dictData
|
|
|
}
|
|
|
} catch (e: any) {
|
|
|
@@ -327,11 +327,11 @@ const loadMaintenanceTypeDictList = async (): Promise<void> => {
|
|
|
try {
|
|
|
const result = await getDictDataByType('gxt_maintenance_type')
|
|
|
const resultObj = result as UTSJSONObject
|
|
|
-
|
|
|
+
|
|
|
if (resultObj['code'] == 200) {
|
|
|
const data = resultObj['data'] as any[]
|
|
|
const dictData: SysDictData[] = []
|
|
|
-
|
|
|
+
|
|
|
if (data != null && data.length > 0) {
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
const item = data[i] as UTSJSONObject
|
|
|
@@ -353,7 +353,7 @@ const loadMaintenanceTypeDictList = async (): Promise<void> => {
|
|
|
dictData.push(dictItem)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
maintenanceTypeDictList.value = dictData
|
|
|
}
|
|
|
} catch (e: any) {
|
|
|
@@ -385,14 +385,14 @@ function getWorkOrderTypeText(orderType: string | null): string {
|
|
|
function getWorkOrderStatus(item: any | null): string | null {
|
|
|
if (item == null) return ''
|
|
|
const rawStatus = getPropertyValue(item, 'workOrderStatus')
|
|
|
-
|
|
|
+
|
|
|
if (rawStatus == null || rawStatus == '') return ''
|
|
|
-
|
|
|
+
|
|
|
// 如果字典尚未加载,返回原始值
|
|
|
if (!dictLoaded.value) {
|
|
|
return rawStatus
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 查找字典中对应的标签
|
|
|
const dictItem = statusDictList.value.find(dict => dict.dictValue == rawStatus)
|
|
|
return dictItem != null ? dictItem.dictLabel : rawStatus
|
|
|
@@ -413,16 +413,16 @@ function getStatistics() {
|
|
|
orderType: orderTypeFilter.value,
|
|
|
timeRange: timeRange.value
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (timeRange.value === 'custom') {
|
|
|
params.beginDate = startDate.value
|
|
|
params.endDate = endDate.value
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
getOrderHourStatistics(params).then((response: any) => {
|
|
|
const resultObj = response as UTSJSONObject
|
|
|
const responseData = resultObj['data'] as UTSJSONObject
|
|
|
-
|
|
|
+
|
|
|
if (responseData != null) {
|
|
|
totalHours.value = (responseData['totalHours'] != null) ? parseFloat((responseData['totalHours'] as number).toFixed(1)) : 0
|
|
|
maintenanceHours.value = (responseData['maintenanceHours'] != null) ? parseFloat((responseData['maintenanceHours'] as number).toFixed(1)) : 0
|
|
|
@@ -442,17 +442,17 @@ function getStatistics() {
|
|
|
// 方法
|
|
|
function loadData(isRefresh: boolean) {
|
|
|
const shouldRefresh = isRefresh
|
|
|
-
|
|
|
+
|
|
|
if (loading.value && !shouldRefresh) {
|
|
|
return
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+
|
|
|
loading.value = true
|
|
|
if (shouldRefresh) {
|
|
|
currentPage.value = 1
|
|
|
refreshing.value = true
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
const params: UTSJSONObject = {
|
|
|
pageNum: currentPage.value,
|
|
|
pageSize: 5,
|
|
|
@@ -460,26 +460,26 @@ function loadData(isRefresh: boolean) {
|
|
|
orderType: orderTypeFilter.value,
|
|
|
timeRange: timeRange.value
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (timeRange.value === 'custom') {
|
|
|
params.beginDate = startDate.value
|
|
|
params.endDate = endDate.value
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
listOrderHours(params).then((response: any) => {
|
|
|
// 提取响应数据
|
|
|
const resultObj = response as UTSJSONObject
|
|
|
console.log('API响应数据:', resultObj)
|
|
|
const responseData = resultObj['rows'] as any[]
|
|
|
const responseTotal = resultObj['total'] as number
|
|
|
-
|
|
|
+
|
|
|
if (shouldRefresh) {
|
|
|
orderList.value = Array.isArray(responseData) ? responseData : []
|
|
|
} else {
|
|
|
const currentRows = Array.isArray(responseData) ? responseData : []
|
|
|
orderList.value = [...orderList.value, ...currentRows]
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
hasMore.value = orderList.value.length < responseTotal
|
|
|
loading.value = false
|
|
|
refreshing.value = false
|
|
|
@@ -514,7 +514,7 @@ function changeTimeRange(range: string) {
|
|
|
|
|
|
function loadMore() {
|
|
|
if (!hasMore.value || loading.value) return
|
|
|
-
|
|
|
+
|
|
|
currentPage.value++
|
|
|
loadData(false)
|
|
|
}
|
|
|
@@ -531,7 +531,7 @@ function showCustomDatePicker() {
|
|
|
const month = (now.getMonth() + 1).toString().padStart(2, '0')
|
|
|
const day = now.getDate().toString().padStart(2, '0')
|
|
|
endDate.value = `${year}-${month}-${day}`
|
|
|
-
|
|
|
+
|
|
|
// 默认开始日期为7天前
|
|
|
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
|
|
const weekAgoYear = weekAgo.getFullYear()
|
|
|
@@ -539,8 +539,8 @@ function showCustomDatePicker() {
|
|
|
const weekAgoDay = weekAgo.getDate().toString().padStart(2, '0')
|
|
|
startDate.value = `${weekAgoYear}-${weekAgoMonth}-${weekAgoDay}`
|
|
|
}
|
|
|
-
|
|
|
- showDatePickerPopup.value = true
|
|
|
+
|
|
|
+ showDatePickerPopup.value = true
|
|
|
}
|
|
|
|
|
|
function closeDatePicker() {
|
|
|
@@ -554,12 +554,12 @@ function confirmCustomDate() {
|
|
|
uni.showToast({ title: '请选择开始时间和结束时间', icon: 'none' })
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (startDate.value != null && endDate.value != null && new Date(startDate.value as string) > new Date(endDate.value as string)) {
|
|
|
uni.showToast({ title: '开始时间不能大于结束时间', icon: 'none' })
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
closeDatePicker()
|
|
|
timeRange.value = 'custom'
|
|
|
loadData(true)
|
|
|
@@ -582,7 +582,7 @@ function onStartDateConfirm(value: string) {
|
|
|
uni.showToast({ title: '开始时间不能大于结束时间', icon: 'none' })
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
startDate.value = value
|
|
|
showStartDatePicker.value = false
|
|
|
}
|
|
|
@@ -593,7 +593,7 @@ function onEndDateConfirm(value: string) {
|
|
|
uni.showToast({ title: '结束时间不能小于开始时间', icon: 'none' })
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
endDate.value = value
|
|
|
showEndDatePicker.value = false
|
|
|
}
|
|
|
@@ -644,9 +644,9 @@ function formatNumber(value: number | null) {
|
|
|
// 获取工单类型相关信息(维保类型或检修类型)
|
|
|
function getWorkOrderTypeInfo(item: any | null): string {
|
|
|
if (item == null) return ''
|
|
|
-
|
|
|
+
|
|
|
const orderType = getPropertyValue(item, 'orderType')
|
|
|
-
|
|
|
+
|
|
|
// 维保工单显示维保类型
|
|
|
if (orderType == "2") {
|
|
|
const inspectionType = getPropertyValue(item, 'inspectionType')
|
|
|
@@ -655,12 +655,12 @@ function getWorkOrderTypeInfo(item: any | null): string {
|
|
|
if (inspectionTypeDictList.value.length == 0) {
|
|
|
return inspectionType
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 查找字典中对应的标签
|
|
|
const dictItem = inspectionTypeDictList.value.find(dict => dict.dictValue == inspectionType)
|
|
|
return (dictItem != null ? dictItem.dictLabel : inspectionType) as string
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
// 维修工单显示检修类型
|
|
|
else if (orderType == "1") {
|
|
|
const maintenanceType = getPropertyValue(item, 'maintenanceType')
|
|
|
@@ -669,16 +669,16 @@ function getWorkOrderTypeInfo(item: any | null): string {
|
|
|
if (maintenanceTypeDictList.value.length == 0) {
|
|
|
return maintenanceType
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 查找字典中对应的标签
|
|
|
const dictItem = maintenanceTypeDictList.value.find(dict => dict.dictValue == maintenanceType)
|
|
|
return (dictItem != null ? dictItem.dictLabel : maintenanceType) as string
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return ""
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 生命周期
|
|
|
onMounted(() => {
|
|
|
loadStatusDictList()
|
|
|
@@ -721,7 +721,7 @@ onMounted(() => {
|
|
|
font-size: 28rpx;
|
|
|
color: #333333;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.clear-icon {
|
|
|
margin-left: 12rpx;
|
|
|
font-size: 28rpx;
|
|
|
@@ -741,7 +741,7 @@ onMounted(() => {
|
|
|
align-items: center;
|
|
|
height: 72rpx;
|
|
|
flex: 1;
|
|
|
-
|
|
|
+
|
|
|
.status-txt {
|
|
|
padding: 8px 12px;
|
|
|
text-align: center;
|
|
|
@@ -750,7 +750,7 @@ onMounted(() => {
|
|
|
background-color: #fff;
|
|
|
font-size: 28rpx;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.stauts-sel {
|
|
|
background-color: #007AFF;
|
|
|
color: #fff;
|
|
|
@@ -815,7 +815,7 @@ onMounted(() => {
|
|
|
display: flex;
|
|
|
margin-bottom: 8rpx;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.hours-value {
|
|
|
display: flex;
|
|
|
font-size: 48rpx;
|
|
|
@@ -843,7 +843,7 @@ onMounted(() => {
|
|
|
line-height: 1.4;
|
|
|
}
|
|
|
|
|
|
- .breakdown-value {
|
|
|
+ .breakdown-value {
|
|
|
font-size: 28rpx;
|
|
|
color: #666;
|
|
|
display: flex;
|
|
|
@@ -888,12 +888,12 @@ onMounted(() => {
|
|
|
flex-direction: row;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
-
|
|
|
+
|
|
|
.info-label {
|
|
|
font-size: 26rpx;
|
|
|
color: #666;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.info-value {
|
|
|
font-size: 26rpx;
|
|
|
color: #666;
|
|
|
@@ -1031,4 +1031,4 @@ onMounted(() => {
|
|
|
.list-with-padding {
|
|
|
padding-bottom: 40rpx;
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|