From a80c78c89ff189fa2085e5570618a1dab40e48f6 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期六, 14 三月 2026 10:20:37 +0800
Subject: [PATCH] fix: 设备保养:可以在app上面进行设备保养计划新增,可多选设备(不需要设备编号),计划新增后,需定时生成多条任务(根据选择的多个设备生成多个任务)
---
src/pages/equipmentManagement/upkeep/index.vue | 360 +++++++---
src/pages/index.vue | 31
src/pages.json | 11
src/pages/indexItem.vue | 5
src/api/equipmentManagement/inspection.js | 212 +++---
src/api/equipmentManagement/upkeep.js | 36 +
src/pages/equipmentManagement/upkeepTask/index.vue | 449 ++++++++++++++
src/pages/equipmentManagement/upkeepTask/components/formDia.vue | 659 +++++++++++++++++++++
src/pages/inspectionManagement/index.vue | 74 --
9 files changed, 1,539 insertions(+), 298 deletions(-)
diff --git a/src/api/equipmentManagement/inspection.js b/src/api/equipmentManagement/inspection.js
index c3113a8..7813bc2 100644
--- a/src/api/equipmentManagement/inspection.js
+++ b/src/api/equipmentManagement/inspection.js
@@ -1,6 +1,6 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
-// ==================== 宸℃浠诲姟绠$悊 ====================
+// ==================== 宸℃浠诲姟 ====================
/**
* @desc 鏌ヨ宸℃浠诲姟鍒楄〃
@@ -12,10 +12,10 @@
*/
export function getInspectionTaskList(query) {
return request({
- url: '/equipment/inspection/task/list',
- method: 'get',
- params: query
- })
+ url: "/equipment/inspection/task/list",
+ method: "get",
+ params: query,
+ });
}
/**
@@ -25,9 +25,9 @@
*/
export function getInspectionTask(id) {
return request({
- url: '/equipment/inspection/task/' + id,
- method: 'get'
- })
+ url: "/equipment/inspection/task/" + id,
+ method: "get",
+ });
}
/**
@@ -37,10 +37,10 @@
*/
export function createInspectionTask(data) {
return request({
- url: '/equipment/inspection/task',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/task",
+ method: "post",
+ data: data,
+ });
}
/**
@@ -50,10 +50,10 @@
*/
export function updateInspectionTask(data) {
return request({
- url: '/equipment/inspection/task',
- method: 'put',
- data: data
- })
+ url: "/equipment/inspection/task",
+ method: "put",
+ data: data,
+ });
}
/**
@@ -63,9 +63,9 @@
*/
export function deleteInspectionTask(id) {
return request({
- url: '/equipment/inspection/task/' + id,
- method: 'delete'
- })
+ url: "/equipment/inspection/task/" + id,
+ method: "delete",
+ });
}
/**
@@ -75,9 +75,9 @@
*/
export function startInspectionTask(taskId) {
return request({
- url: '/equipment/inspection/task/' + taskId + '/start',
- method: 'post'
- })
+ url: "/equipment/inspection/task/" + taskId + "/start",
+ method: "post",
+ });
}
/**
@@ -88,10 +88,10 @@
*/
export function completeInspectionTask(taskId, data) {
return request({
- url: '/equipment/inspection/task/' + taskId + '/complete',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/task/" + taskId + "/complete",
+ method: "post",
+ data: data,
+ });
}
// ==================== 宸℃璁板綍绠$悊 ====================
@@ -103,10 +103,10 @@
*/
export function submitInspectionRecord(data) {
return request({
- url: '/equipment/inspection/record/submit',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/record/submit",
+ method: "post",
+ data: data,
+ });
}
/**
@@ -116,10 +116,10 @@
*/
export function getInspectionRecordList(query) {
return request({
- url: '/equipment/inspection/record/list',
- method: 'get',
- params: query
- })
+ url: "/equipment/inspection/record/list",
+ method: "get",
+ params: query,
+ });
}
/**
@@ -129,9 +129,9 @@
*/
export function getInspectionRecord(id) {
return request({
- url: '/equipment/inspection/record/' + id,
- method: 'get'
- })
+ url: "/equipment/inspection/record/" + id,
+ method: "get",
+ });
}
// ==================== 鏂囦欢涓婁紶 ====================
@@ -143,13 +143,13 @@
*/
export function uploadInspectionImage(file) {
return request({
- url: '/equipment/inspection/upload/image',
- method: 'post',
+ url: "/equipment/inspection/upload/image",
+ method: "post",
data: file,
headers: {
- 'Content-Type': 'multipart/form-data'
- }
- })
+ "Content-Type": "multipart/form-data",
+ },
+ });
}
/**
@@ -159,13 +159,13 @@
*/
export function uploadInspectionVideo(file) {
return request({
- url: '/equipment/inspection/upload/video',
- method: 'post',
+ url: "/equipment/inspection/upload/video",
+ method: "post",
data: file,
headers: {
- 'Content-Type': 'multipart/form-data'
- }
- })
+ "Content-Type": "multipart/form-data",
+ },
+ });
}
/**
@@ -175,13 +175,13 @@
*/
export function batchUploadFiles(formData) {
return request({
- url: '/equipment/inspection/upload/batch',
- method: 'post',
+ url: "/equipment/inspection/upload/batch",
+ method: "post",
data: formData,
headers: {
- 'Content-Type': 'multipart/form-data'
- }
- })
+ "Content-Type": "multipart/form-data",
+ },
+ });
}
// ==================== 寮傚父鎶ュ绠$悊 ====================
@@ -193,10 +193,10 @@
*/
export function reportAbnormalSituation(data) {
return request({
- url: '/equipment/inspection/abnormal/report',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/abnormal/report",
+ method: "post",
+ data: data,
+ });
}
/**
@@ -206,10 +206,10 @@
*/
export function getAbnormalReportList(query) {
return request({
- url: '/equipment/inspection/abnormal/list',
- method: 'get',
- params: query
- })
+ url: "/equipment/inspection/abnormal/list",
+ method: "get",
+ params: query,
+ });
}
/**
@@ -219,9 +219,9 @@
*/
export function getAbnormalReport(id) {
return request({
- url: '/equipment/inspection/abnormal/' + id,
- method: 'get'
- })
+ url: "/equipment/inspection/abnormal/" + id,
+ method: "get",
+ });
}
/**
@@ -232,10 +232,10 @@
*/
export function handleAbnormalReport(id, data) {
return request({
- url: '/equipment/inspection/abnormal/' + id + '/handle',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/abnormal/" + id + "/handle",
+ method: "post",
+ data: data,
+ });
}
/**
@@ -246,10 +246,10 @@
*/
export function transferAbnormalReport(id, data) {
return request({
- url: '/equipment/inspection/abnormal/' + id + '/transfer',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/abnormal/" + id + "/transfer",
+ method: "post",
+ data: data,
+ });
}
/**
@@ -260,10 +260,10 @@
*/
export function closeAbnormalReport(id, data) {
return request({
- url: '/equipment/inspection/abnormal/' + id + '/close',
- method: 'post',
- data: data
- })
+ url: "/equipment/inspection/abnormal/" + id + "/close",
+ method: "post",
+ data: data,
+ });
}
// ==================== 缁熻鍒嗘瀽 ====================
@@ -275,10 +275,10 @@
*/
export function getInspectionStats(params) {
return request({
- url: '/equipment/inspection/stats',
- method: 'get',
- params: params
- })
+ url: "/equipment/inspection/stats",
+ method: "get",
+ params: params,
+ });
}
/**
@@ -288,10 +288,10 @@
*/
export function getAbnormalStats(params) {
return request({
- url: '/equipment/inspection/abnormal/stats',
- method: 'get',
- params: params
- })
+ url: "/equipment/inspection/abnormal/stats",
+ method: "get",
+ params: params,
+ });
}
/**
@@ -301,11 +301,11 @@
*/
export function exportInspectionReport(params) {
return request({
- url: '/equipment/inspection/export/report',
- method: 'get',
+ url: "/equipment/inspection/export/report",
+ method: "get",
params: params,
- responseType: 'blob'
- })
+ responseType: "blob",
+ });
}
/**
@@ -315,11 +315,11 @@
*/
export function exportAbnormalRecords(params) {
return request({
- url: '/equipment/inspection/abnormal/export',
- method: 'get',
+ url: "/equipment/inspection/abnormal/export",
+ method: "get",
params: params,
- responseType: 'blob'
- })
+ responseType: "blob",
+ });
}
// ==================== 璁惧浜岀淮鐮� ====================
@@ -332,8 +332,8 @@
export function getDeviceQRCode(deviceId) {
return request({
url: `/equipment/device/${deviceId}/qrcode`,
- method: 'get'
- })
+ method: "get",
+ });
}
/**
@@ -343,10 +343,10 @@
*/
export function verifyDeviceQRCode(data) {
return request({
- url: '/equipment/device/qrcode/verify',
- method: 'post',
- data: data
- })
+ url: "/equipment/device/qrcode/verify",
+ method: "post",
+ data: data,
+ });
}
// ==================== 妯℃澘绠$悊 ====================
@@ -358,10 +358,10 @@
*/
export function getInspectionTemplateList(query) {
return request({
- url: '/equipment/inspection/template/list',
- method: 'get',
- params: query
- })
+ url: "/equipment/inspection/template/list",
+ method: "get",
+ params: query,
+ });
}
/**
@@ -371,7 +371,7 @@
*/
export function getInspectionTemplate(id) {
return request({
- url: '/equipment/inspection/template/' + id,
- method: 'get'
- })
-}
\ No newline at end of file
+ url: "/equipment/inspection/template/" + id,
+ method: "get",
+ });
+}
diff --git a/src/api/equipmentManagement/upkeep.js b/src/api/equipmentManagement/upkeep.js
index d6814af..cf536f0 100644
--- a/src/api/equipmentManagement/upkeep.js
+++ b/src/api/equipmentManagement/upkeep.js
@@ -97,6 +97,42 @@
});
}
+// ---------- 璁惧淇濆吇瀹氭椂浠诲姟锛堝畾鏃朵换鍔$鐞嗭級 ----------
+/** 璁惧淇濆吇瀹氭椂浠诲姟鍒嗛〉鍒楄〃 */
+export const deviceMaintenanceTaskList = (params) => {
+ return request({
+ url: "/deviceMaintenanceTask/listPage",
+ method: "get",
+ params,
+ });
+};
+
+/** 鏂板璁惧淇濆吇瀹氭椂浠诲姟 */
+export const deviceMaintenanceTaskAdd = (data) => {
+ return request({
+ url: "/deviceMaintenanceTask/add",
+ method: "post",
+ data,
+ });
+};
+
+/** 淇敼璁惧淇濆吇瀹氭椂浠诲姟 */
+export const deviceMaintenanceTaskEdit = (data) => {
+ return request({
+ url: "/deviceMaintenanceTask/update",
+ method: "post",
+ data,
+ });
+};
+
+/** 鍒犻櫎璁惧淇濆吇瀹氭椂浠诲姟 */
+export const deviceMaintenanceTaskDel = (ids) => {
+ return request({
+ url: "/deviceMaintenanceTask/delete",
+ method: "delete",
+ data: Array.isArray(ids) ? ids : [ids],
+ });
+};
// 鏌ヨ澶囦欢閫夐」
export const getSparePartsOptions = (params) => {
diff --git a/src/pages.json b/src/pages.json
index a6d3cf9..d11cdea 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -541,6 +541,15 @@
}
},
{
+ "path": "pages/equipmentManagement/upkeepTask/index",
+ "style": {
+ "navigationBarTitleText": "璁惧淇濆吇浠诲姟",
+ "navigationStyle": "custom",
+ "enablePullDownRefresh": true,
+ "backgroundColor": "#f8f8f8"
+ }
+ },
+ {
"path": "pages/equipmentManagement/upkeep/detail",
"style": {
"navigationBarTitleText": "淇濆吇璇︽儏",
@@ -615,7 +624,7 @@
{
"path": "pages/inspectionManagement/index",
"style": {
- "navigationBarTitleText": "宸℃浠诲姟绠$悊",
+ "navigationBarTitleText": "宸℃浠诲姟",
"navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundColor": "#f8f8f8"
diff --git a/src/pages/equipmentManagement/upkeep/index.vue b/src/pages/equipmentManagement/upkeep/index.vue
index f14712f..7e043c3 100644
--- a/src/pages/equipmentManagement/upkeep/index.vue
+++ b/src/pages/equipmentManagement/upkeep/index.vue
@@ -1,92 +1,82 @@
<template>
- <view class="sales-account">
- <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+ <view class="upkeep-page">
<PageHeader title="璁惧淇濆吇"
@back="goBack" />
- <!-- 鎼滅储鍖哄煙 -->
- <view class="search-section">
- <view class="search-bar">
- <view class="search-input">
- <up-input class="search-text"
- placeholder="璇疯緭鍏ヨ澶囧悕绉版悳绱�"
- v-model="searchKeyword"
- @change="getList"
- clearable />
- </view>
- <view class="filter-button"
- @click="getList">
- <up-icon name="search"
- size="24"
- color="#999"></up-icon>
+ <view class="toolbar">
+ <view class="search-section">
+ <view class="search-bar">
+ <view class="search-input">
+ <up-input class="search-text"
+ placeholder="璇疯緭鍏ヨ澶囧悕绉版悳绱�"
+ v-model="searchKeyword"
+ clearable />
+ </view>
+ <view class="search-button"
+ @click="handleQuery">
+ <up-icon name="search"
+ size="24"
+ color="#999"></up-icon>
+ </view>
</view>
</view>
+ <view class="meta-bar">
+ <text class="meta-text">鍏� {{ total }} 鏉�</text>
+ </view>
</view>
- <!-- 璁惧淇濆吇鍒楄〃 -->
- <view class="ledger-list"
- v-if="upkeepList.length > 0">
+ <view class="list-section">
<view v-for="(item, index) in upkeepList"
- :key="index">
- <view class="ledger-item"
- @click="toggleSelection(item)">
- <view class="item-header">
- <view class="item-left">
- <view class="document-icon">
- <up-icon name="file-text"
- size="16"
- color="#ffffff"></up-icon>
- </view>
- <text class="item-id">璁惧鍚嶇О锛歿{ item.deviceName }}</text>
+ :key="item.id || index"
+ class="ledger-item">
+ <view class="item-header">
+ <view class="item-left">
+ <view class="document-icon">
+ <up-icon name="file-text"
+ size="14"
+ color="#ffffff"></up-icon>
</view>
- <view class="status-tag">
- <u-tag v-if="item.status === 1"
- type="success">瀹岀粨</u-tag>
- <u-tag v-if="item.status === 0"
- type="warning">寰呬繚鍏�</u-tag>
- <u-tag v-if="item.status === 2"
- type="error">澶辫触</u-tag>
- </view>
+ <text class="item-id">{{ item.deviceName || "--" }}</text>
+ </view>
+ <view class="item-right">
+ <u-tag v-if="item.status === 1"
+ type="success">瀹岀粨</u-tag>
+ <u-tag v-if="item.status === 0"
+ type="warning">寰呬繚鍏�</u-tag>
+ <u-tag v-if="item.status === 2"
+ type="error">澶辫触</u-tag>
+ </view>
+ </view>
+ <up-divider></up-divider>
+ <view class="item-details">
+ <view class="detail-row">
+ <text class="detail-label">瑙勬牸鍨嬪彿</text>
+ <text class="detail-value">{{ item.deviceModel || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">璁″垝淇濆吇鏃ユ湡</text>
+ <text class="detail-value">{{ formatDate(item.maintenancePlanTime) || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">褰曞叆浜�</text>
+ <text class="detail-value">{{ item.createUserName || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">褰曞叆鏃ユ湡</text>
+ <text class="detail-value">{{ formatDateTime(item.createTime) || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瀹為檯淇濆吇浜�</text>
+ <text class="detail-value">{{ item.maintenanceActuallyName || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">瀹為檯淇濆吇鏃ユ湡</text>
+ <text class="detail-value">{{ formatDateTime(item.maintenanceActuallyTime) || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">淇濆吇缁撴灉</text>
+ <text class="detail-value">{{ item.maintenanceResult || "--" }}</text>
</view>
<up-divider></up-divider>
- <view class="item-details">
- <view class="detail-row">
- <text class="detail-label">瑙勬牸鍨嬪彿</text>
- <text class="detail-value">{{ item.deviceModel || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">璁″垝淇濆吇鏃ユ湡</text>
- <text class="detail-value">{{ formatDate(item.maintenancePlanTime) || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">褰曞叆浜�</text>
- <text class="detail-value">{{ item.createUserName || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">褰曞叆鏃ユ湡</text>
- <text class="detail-value">{{ formatDateTime(item.createTime) || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">瀹為檯淇濆吇浜�</text>
- <text class="detail-value">{{ item.maintenanceActuallyName || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">瀹為檯淇濆吇鏃ユ湡</text>
- <text class="detail-value">{{ formatDateTime(item.maintenanceActuallyTime) || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">淇濆吇缁撴灉</text>
- <text class="detail-value">{{item.maintenanceResult || '-'}}
- </text>
- </view>
- </view>
- <!-- 鎸夐挳鍖哄煙 -->
- <view class="action-buttons">
- <!-- <u-button type="primary"
- size="small"
- class="action-btn"
- :disabled="item.status === 1"
- @click.stop="edit(item.id)">
- 缂栬緫
- </u-button> -->
+ <view class="card-actions">
<u-button type="warning"
size="small"
class="action-btn"
@@ -107,21 +97,14 @@
@click.stop="viewDetail(item)">
璇︽儏
</u-button>
- <!-- <u-button type="warning"
- size="small"
- class="action-btn"
- @click.stop="addFile(item.id)">
- 闄勪欢
- </u-button> -->
</view>
</view>
</view>
+ <view v-if="!loading && upkeepList.length === 0"
+ class="no-data">
+ <text>鏆傛棤璁惧淇濆吇鏁版嵁</text>
+ </view>
</view>
- <view v-else
- class="no-data">
- <text>鏆傛棤璁惧淇濆吇鏁版嵁</text>
- </view>
- <!-- 娴姩鏂板鎸夐挳 -->
<view class="fab-button"
@click="addPlan">
<up-icon name="plus"
@@ -154,7 +137,10 @@
// 璁惧淇濆吇鏁版嵁
const upkeepList = ref([]);
- // 澶氶�夊垪琛�
+ const total = ref(0);
+ const loading = ref(false);
+
+ // 澶氶�夊垪琛紙淇濆吇鎸夐挳鏈紶 id 鏃剁敤锛�
const multipleList = ref([]);
// 杩斿洖涓婁竴椤�
@@ -174,9 +160,13 @@
return dayjs(dateStr).format("YYYY-MM-DD HH:mm:ss");
};
+ const handleQuery = () => {
+ getList();
+ };
+
// 鏌ヨ鍒楄〃
const getList = () => {
- showLoadingToast("鍔犺浇涓�...");
+ loading.value = true;
const params = {
current: -1,
size: -1,
@@ -184,13 +174,16 @@
};
getUpkeepPage(params)
.then(res => {
- // 濡傛灉res.data涓嶆槸鏁扮粍锛岃缃负绌烘暟缁�
- upkeepList.value = res.records || res.data?.records || [];
- closeToast();
+ const records = res?.records ?? res?.data?.records ?? [];
+ upkeepList.value = records;
+ total.value = Array.isArray(records) ? records.length : Number(res?.total ?? res?.data?.total ?? 0);
})
.catch(() => {
- closeToast();
+ upkeepList.value = [];
showToast("鑾峰彇鏁版嵁澶辫触");
+ })
+ .finally(() => {
+ loading.value = false;
});
};
// 鏂板闄勪欢 - 璺宠浆鍒伴檮浠堕〉闈�
@@ -322,45 +315,182 @@
</script>
<style scoped lang="scss">
- @import "@/styles/sales-common.scss";
-
- // 璁惧淇濆吇鐗规湁鏍峰紡
- .sales-account {
- padding-bottom: 80px; // 涓烘诞鍔ㄦ寜閽暀鍑虹┖闂�
+ .upkeep-page {
+ min-height: 100vh;
+ background: #f6f7fb;
}
- .action-section {
- padding: 10px 20px;
+ .toolbar {
+ padding: 20rpx 24rpx;
+ background: #fff;
+ border-bottom: 1rpx solid #f0f0f0;
+ position: sticky;
+ top: 0;
+ z-index: 10;
+ }
+
+ .search-section {
+ margin-top: 0;
+ }
+
+ .search-bar {
+ display: flex;
+ align-items: center;
+ background: #f7f8fa;
+ border-radius: 14rpx;
+ padding: 8rpx 12rpx 8rpx 16rpx;
+ border: 1rpx solid #eef1f5;
+ }
+
+ .search-input {
+ flex: 1;
+ min-width: 0;
+ }
+
+ .search-text {
+ background: transparent !important;
+ }
+
+ :deep(.search-text .u-input__content),
+ :deep(.search-text .up-input__content) {
+ background: transparent !important;
+ padding: 0 !important;
+ }
+
+ .search-button {
+ width: 64rpx;
+ height: 64rpx;
+ border-radius: 12rpx;
background: #ffffff;
- border-bottom: 1px solid #f0f0f0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
- .action-section .action-buttons {
- gap: 8px; // 涓庡叕鍏辨牱寮忎腑鐨� 12px 涓嶅悓
- justify-content: flex-start;
+ .meta-bar {
+ margin-top: 16rpx;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background: #f7f9fc;
+ border-radius: 12rpx;
+ padding: 10rpx 16rpx;
}
- .checkbox-wrapper {
+ .meta-text {
+ color: #5c6b8a;
+ font-size: 22rpx;
+ }
+
+ .list-section {
+ padding: 20rpx 24rpx;
+ padding-bottom: calc(132rpx + env(safe-area-inset-bottom));
+ }
+
+ .ledger-item {
+ background: #ffffff;
+ border-radius: 20rpx;
+ margin-bottom: 16rpx;
+ overflow: hidden;
+ box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.05);
+ padding: 0 20rpx;
+ }
+
+ .item-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 22rpx 0;
+ }
+
+ .item-left {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ flex: 1;
+ min-width: 0;
+ }
+
+ .item-right {
display: flex;
align-items: center;
}
- .status-tag {
+ .document-icon {
+ width: 38rpx;
+ height: 38rpx;
+ border-radius: 8rpx;
+ background: #2979ff;
display: flex;
align-items: center;
+ justify-content: center;
+ }
+
+ .item-id {
+ font-size: 28rpx;
+ color: #1f1f1f;
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .item-details {
+ padding: 18rpx 0 20rpx;
+ }
+
+ .detail-row {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-bottom: 12rpx;
}
.detail-label {
- min-width: 80px; // 涓庡叕鍏辨牱寮忎腑鐨� 60px 涓嶅悓
+ min-width: 160rpx;
+ color: #777;
+ font-size: 24rpx;
}
.detail-value {
- display: flex;
- justify-content: flex-end;
- align-items: center;
+ flex: 1;
+ color: #333;
+ font-size: 24rpx;
+ text-align: right;
+ word-break: break-all;
+ margin-left: 12rpx;
}
- .ledger-item .action-buttons {
- gap: 8px; // 涓庡叕鍏辨牱寮忎腑鐨� 12px 涓嶅悓
+ .card-actions {
+ padding-top: 8rpx;
+ display: flex;
+ justify-content: flex-end;
+ flex-wrap: wrap;
+ gap: 12rpx;
+ }
+
+ .action-btn {
+ min-width: 100rpx;
+ }
+
+ .fab-button {
+ position: fixed;
+ bottom: calc(30px + env(safe-area-inset-bottom));
+ right: 30px;
+ width: 56px;
+ height: 56px;
+ background: #2979ff;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3);
+ z-index: 1000;
+ }
+
+ .no-data {
+ padding: 40rpx 0;
+ text-align: center;
+ color: #999;
}
</style>
\ No newline at end of file
diff --git a/src/pages/equipmentManagement/upkeepTask/components/formDia.vue b/src/pages/equipmentManagement/upkeepTask/components/formDia.vue
new file mode 100644
index 0000000..15fe952
--- /dev/null
+++ b/src/pages/equipmentManagement/upkeepTask/components/formDia.vue
@@ -0,0 +1,659 @@
+<template>
+ <u-popup :show="dialogVisitable"
+ mode="center"
+ :round="12"
+ :zIndex="900"
+ @close="cancel">
+ <view class="popup-content">
+ <view class="popup-title">{{ operationType === "add" ? "鏂板淇濆吇浠诲姟" : "缂栬緫淇濆吇浠诲姟" }}</view>
+ <view class="form-body">
+ <view class="form-item">
+ <text class="label">浠诲姟鍚嶇О</text>
+ <up-input v-model="form.taskName"
+ placeholder="璇疯緭鍏ヤ换鍔″悕绉�"
+ border="none"
+ customStyle="background: #f7f8fa; padding: 0 20rpx; min-height: 72rpx; border-radius: 12rpx;" />
+ </view>
+ <view class="form-item">
+ <text class="label">璁惧</text>
+ <view class="picker-value inspector-picker"
+ @click="openDevicePopup">
+ <text>{{ deviceNamesText || "璇烽�夋嫨璁惧" }}</text>
+ <u-icon name="arrow-right"
+ size="14"
+ color="#999" />
+ </view>
+ <view class="inspector-tags"
+ v-if="form.deviceIds?.length">
+ <view v-for="id in form.deviceIds"
+ :key="id"
+ class="inspector-tag"
+ @click="toggleDevice(id)">
+ <text>{{ getDeviceName(id) }}</text>
+ <u-icon name="close"
+ size="11"
+ color="#1677ff" />
+ </view>
+ </view>
+ </view>
+ <view class="form-item">
+ <text class="label">褰曞叆浜�</text>
+ <picker mode="selector"
+ :range="userList"
+ range-key="nickName"
+ :value="inspectorIndex"
+ @change="onInspectorChange">
+ <view class="picker-value">{{ form.registrant || "璇烽�夋嫨褰曞叆浜�" }}</view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <text class="label">鐧昏鏃堕棿</text>
+ <picker mode="date"
+ :value="form.registrationDate || todayStr"
+ @change="onRegistrationDateChange">
+ <view class="picker-value">{{ form.registrationDate || "璇烽�夋嫨鐧昏鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <text class="label">浠诲姟棰戠巼</text>
+ <picker mode="selector"
+ :range="frequencyOptions"
+ range-key="label"
+ :value="frequencyIndex"
+ @change="onFrequencyChange">
+ <view class="picker-value">{{ currentFrequencyLabel || "璇烽�夋嫨浠诲姟棰戠巼" }}</view>
+ </picker>
+ </view>
+ <view class="form-item"
+ v-if="form.frequencyType === 'DAILY'">
+ <text class="label">鏃堕棿</text>
+ <picker mode="time"
+ :value="form.frequencyDetail || '08:00'"
+ @change="onDailyTimeChange">
+ <view class="picker-value">{{ form.frequencyDetail || "璇烽�夋嫨鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item"
+ v-if="form.frequencyType === 'WEEKLY'">
+ <text class="label">姣忓懆鏃ユ湡</text>
+ <picker mode="selector"
+ :range="weekOptions"
+ range-key="label"
+ :value="weekIndex"
+ @change="onWeekChange">
+ <view class="picker-value">{{ currentWeekLabel || "璇烽�夋嫨鏄熸湡" }}</view>
+ </picker>
+ </view>
+ <view class="form-item"
+ v-if="form.frequencyType === 'WEEKLY'">
+ <text class="label">姣忓懆鏃堕棿</text>
+ <picker mode="time"
+ :value="form.time || '08:00'"
+ @change="onWeekTimeChange">
+ <view class="picker-value">{{ form.time || "璇烽�夋嫨鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item"
+ v-if="form.frequencyType === 'MONTHLY'">
+ <text class="label">姣忔湀鏃ユ湡涓庢椂闂�</text>
+ <picker mode="date"
+ fields="day"
+ :value="monthlyDate"
+ @change="onMonthlyDateChange">
+ <view class="picker-value">{{ monthlyDate || "璇烽�夋嫨鏃ユ湡" }}</view>
+ </picker>
+ <picker mode="time"
+ :value="monthlyTime"
+ @change="onMonthlyTimeChange">
+ <view class="picker-value">{{ monthlyTime || "璇烽�夋嫨鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item"
+ v-if="form.frequencyType === 'QUARTERLY'">
+ <text class="label">瀛e害鏃ユ湡涓庢椂闂�</text>
+ <picker mode="date"
+ :value="quarterlyDate"
+ @change="onQuarterlyDateChange">
+ <view class="picker-value">{{ quarterlyDate || "璇烽�夋嫨鏃ユ湡" }}</view>
+ </picker>
+ <picker mode="time"
+ :value="quarterlyTime"
+ @change="onQuarterlyTimeChange">
+ <view class="picker-value">{{ quarterlyTime || "璇烽�夋嫨鏃堕棿" }}</view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <text class="label">澶囨敞</text>
+ <u-textarea v-model="form.remarks"
+ placeholder="璇疯緭鍏ュ娉�"
+ :height="80"
+ count />
+ </view>
+ </view>
+ <view class="popup-footer">
+ <u-button @click="cancel">鍙栨秷</u-button>
+ <u-button type="primary"
+ @click="submitForm">淇濆瓨</u-button>
+ </view>
+ </view>
+ </u-popup>
+ <u-popup :show="showDevicePopup"
+ mode="bottom"
+ :round="16"
+ :zIndex="1100"
+ @close="closeDevicePopup">
+ <view class="inspector-popup">
+ <view class="inspector-header">
+ <text class="inspector-title">閫夋嫨璁惧</text>
+ </view>
+ <scroll-view scroll-y
+ class="inspector-list">
+ <view v-for="item in deviceOptions"
+ :key="item.id"
+ class="inspector-row"
+ @click="toggleDevice(item.id)">
+ <text class="inspector-name">{{ item.deviceName }}</text>
+ <u-icon v-if="(form.deviceIds || []).includes(item.id)"
+ name="checkmark-circle-fill"
+ color="#1677ff"
+ size="20" />
+ <u-icon v-else
+ name=""
+ color="#d5d8de"
+ size="20" />
+ </view>
+ </scroll-view>
+ <view class="inspector-footer">
+ <u-button @click="closeDevicePopup">纭畾</u-button>
+ </view>
+ </view>
+ </u-popup>
+</template>
+
+<script setup>
+ import { computed, reactive, ref } from "vue";
+ import useUserStore from "@/store/modules/user";
+ import {
+ deviceMaintenanceTaskAdd,
+ deviceMaintenanceTaskEdit,
+ } from "@/api/equipmentManagement/upkeep.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
+ import { getDeviceLedger } from "@/api/equipmentManagement/ledger.js";
+
+ const emit = defineEmits(["closeDia"]);
+ const userStore = useUserStore();
+ const dialogVisitable = ref(false);
+ const operationType = ref("add");
+ const deviceOptions = ref([]);
+ const userList = ref([]);
+ const showDevicePopup = ref(false);
+
+ const todayStr = ref("");
+ try {
+ const d = new Date();
+ todayStr.value = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
+ } catch (e) {}
+
+ const defaultForm = () => ({
+ id: undefined,
+ taskName: "",
+ deviceIds: [],
+ registrantId: undefined,
+ registrant: "",
+ registrationDate: "",
+ remarks: "",
+ frequencyType: "",
+ frequencyDetail: "",
+ week: "",
+ time: "",
+ });
+
+ const form = reactive(defaultForm());
+
+ const frequencyOptions = [
+ { label: "姣忔棩", value: "DAILY" },
+ { label: "姣忓懆", value: "WEEKLY" },
+ { label: "姣忔湀", value: "MONTHLY" },
+ { label: "瀛e害", value: "QUARTERLY" },
+ ];
+
+ const weekOptions = [
+ { label: "鍛ㄤ竴", value: "MON" },
+ { label: "鍛ㄤ簩", value: "TUE" },
+ { label: "鍛ㄤ笁", value: "WED" },
+ { label: "鍛ㄥ洓", value: "THU" },
+ { label: "鍛ㄤ簲", value: "FRI" },
+ { label: "鍛ㄥ叚", value: "SAT" },
+ { label: "鍛ㄦ棩", value: "SUN" },
+ ];
+
+ const monthlyDate = ref("");
+ const monthlyTime = ref("");
+ const quarterlyDate = ref("");
+ const quarterlyTime = ref("");
+
+ const frequencyIndex = computed(() => {
+ const index = frequencyOptions.findIndex(item => item.value === form.frequencyType);
+ return index >= 0 ? index : 0;
+ });
+
+ const weekIndex = computed(() => {
+ const index = weekOptions.findIndex(item => item.value === form.week);
+ return index >= 0 ? index : 0;
+ });
+
+ const currentFrequencyLabel = computed(() => {
+ return frequencyOptions.find(item => item.value === form.frequencyType)?.label || "";
+ });
+
+ const currentWeekLabel = computed(() => {
+ return weekOptions.find(item => item.value === form.week)?.label || "";
+ });
+
+ const inspectorIndex = computed(() => {
+ const index = userList.value.findIndex(item => String(item.userId) === String(form.registrantId));
+ return index >= 0 ? index : 0;
+ });
+
+ const deviceNamesText = computed(() => {
+ if (!form.deviceIds?.length) return "";
+ return form.deviceIds
+ .map(id => getDeviceName(id))
+ .filter(Boolean)
+ .join("銆�");
+ });
+
+ function getDeviceName(id) {
+ const d = deviceOptions.value.find(item => String(item.id) === String(id));
+ return d?.deviceName || "";
+ }
+
+ const resetForm = () => {
+ Object.assign(form, defaultForm());
+ monthlyDate.value = "";
+ monthlyTime.value = "";
+ quarterlyDate.value = "";
+ quarterlyTime.value = "";
+ showDevicePopup.value = false;
+ };
+
+ const normalizeIdList = val => {
+ if (!val) return [];
+ if (Array.isArray(val)) return val.map(v => (Number.isNaN(Number(v)) ? v : Number(v)));
+ if (typeof val === "string") {
+ const s = val.trim();
+ if (s.startsWith("[") && s.endsWith("]")) {
+ try {
+ const arr = JSON.parse(s);
+ return Array.isArray(arr) ? arr : [];
+ } catch {
+ return [];
+ }
+ }
+ return s.split(",").map(v => v.trim()).filter(Boolean).map(v => (Number.isNaN(Number(v)) ? v : Number(v)));
+ }
+ return [];
+ };
+
+ const parseWeeklyDetail = detail => {
+ if (!detail || typeof detail !== "string" || !detail.includes(",")) return;
+ const [week, time] = detail.split(",");
+ form.week = week || "";
+ form.time = time || "";
+ };
+
+ const parseMonthlyDetail = detail => {
+ if (!detail || typeof detail !== "string" || !detail.includes(",")) return;
+ const [day, time] = detail.split(",");
+ if (day) {
+ const y = new Date().getFullYear();
+ const m = new Date().getMonth() + 1;
+ monthlyDate.value = `${y}-${String(m).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
+ }
+ if (time) monthlyTime.value = time;
+ };
+
+ const parseQuarterlyDetail = detail => {
+ if (!detail || typeof detail !== "string") return;
+ const parts = detail.split(",");
+ if (parts.length >= 3) {
+ const [mm, dd, time] = parts;
+ const y = new Date().getFullYear();
+ quarterlyDate.value = `${y}-${String(mm).padStart(2, "0")}-${String(dd).padStart(2, "0")}`;
+ quarterlyTime.value = time || "";
+ }
+ };
+
+ const openDialog = async (type, row) => {
+ operationType.value = type;
+ dialogVisitable.value = true;
+ resetForm();
+ try {
+ const [userRes, deviceRes] = await Promise.all([
+ userListNoPageByTenantId(),
+ getDeviceLedger(),
+ ]);
+ userList.value = userRes?.data || [];
+ deviceOptions.value = deviceRes?.data || [];
+ if (type === "edit" && row) {
+ Object.assign(form, {
+ ...defaultForm(),
+ ...row,
+ deviceIds: normalizeIdList(row.deviceIds ?? row.taskIds ?? row.deviceIds),
+ });
+ if (!form.registrationDate && row.registrationDate) form.registrationDate = row.registrationDate;
+ if (row.registrantId) form.registrantId = row.registrantId;
+ if (row.registrant) form.registrant = row.registrant;
+ if (form.frequencyType === "WEEKLY") parseWeeklyDetail(form.frequencyDetail);
+ if (form.frequencyType === "MONTHLY") parseMonthlyDetail(form.frequencyDetail);
+ if (form.frequencyType === "QUARTERLY") parseQuarterlyDetail(form.frequencyDetail);
+ } else {
+ form.registrationDate = todayStr.value;
+ const userInfo = await userStore.getInfo();
+ if (userInfo?.user?.userId) {
+ form.registrantId = userInfo.user.userId;
+ form.registrant = userInfo.user.nickName || userInfo.user.userName || "";
+ }
+ }
+ } catch (error) {
+ uni.showToast({
+ title: "鍒濆鍖栧け璐�",
+ icon: "none",
+ });
+ }
+ };
+
+ const openDevicePopup = () => {
+ showDevicePopup.value = true;
+ };
+
+ const closeDevicePopup = () => {
+ showDevicePopup.value = false;
+ };
+
+ const toggleDevice = id => {
+ const ids = form.deviceIds || [];
+ if (ids.includes(id)) {
+ form.deviceIds = ids.filter(i => i !== id);
+ } else {
+ form.deviceIds = [...ids, id];
+ }
+ };
+
+ const onInspectorChange = e => {
+ const index = Number(e?.detail?.value ?? 0);
+ const user = userList.value[index];
+ if (user) {
+ form.registrantId = user.userId;
+ form.registrant = user.nickName || "";
+ }
+ };
+
+ const onRegistrationDateChange = e => {
+ form.registrationDate = e?.detail?.value || "";
+ };
+
+ const onFrequencyChange = e => {
+ const index = Number(e?.detail?.value ?? 0);
+ const selected = frequencyOptions[index];
+ form.frequencyType = selected?.value || "";
+ form.frequencyDetail = "";
+ form.week = "";
+ form.time = "";
+ monthlyDate.value = "";
+ monthlyTime.value = "";
+ quarterlyDate.value = "";
+ quarterlyTime.value = "";
+ };
+
+ const onDailyTimeChange = e => {
+ form.frequencyDetail = e?.detail?.value || "";
+ };
+
+ const onWeekChange = e => {
+ const index = Number(e?.detail?.value ?? 0);
+ const selected = weekOptions[index];
+ form.week = selected?.value || "";
+ };
+
+ const onWeekTimeChange = e => {
+ form.time = e?.detail?.value || "";
+ };
+
+ const onMonthlyDateChange = e => {
+ monthlyDate.value = e?.detail?.value || "";
+ };
+
+ const onMonthlyTimeChange = e => {
+ monthlyTime.value = e?.detail?.value || "";
+ };
+
+ const onQuarterlyDateChange = e => {
+ quarterlyDate.value = e?.detail?.value || "";
+ };
+
+ const onQuarterlyTimeChange = e => {
+ quarterlyTime.value = e?.detail?.value || "";
+ };
+
+ const validateForm = () => {
+ if (!form.taskName?.trim()) {
+ uni.showToast({ title: "璇疯緭鍏ヤ换鍔″悕绉�", icon: "none" });
+ return false;
+ }
+ if (!form.deviceIds?.length) {
+ uni.showToast({ title: "璇烽�夋嫨璁惧", icon: "none" });
+ return false;
+ }
+ if (!form.registrantId && !form.registrant) {
+ uni.showToast({ title: "璇烽�夋嫨褰曞叆浜�", icon: "none" });
+ return false;
+ }
+ if (!form.registrationDate) {
+ uni.showToast({ title: "璇烽�夋嫨鐧昏鏃堕棿", icon: "none" });
+ return false;
+ }
+ if (!form.frequencyType) {
+ uni.showToast({ title: "璇烽�夋嫨浠诲姟棰戠巼", icon: "none" });
+ return false;
+ }
+ if (form.frequencyType === "DAILY" && !form.frequencyDetail) {
+ uni.showToast({ title: "璇烽�夋嫨鏃堕棿", icon: "none" });
+ return false;
+ }
+ if (form.frequencyType === "WEEKLY" && (!form.week || !form.time)) {
+ uni.showToast({ title: "璇烽�夋嫨姣忓懆鏃ユ湡鍜屾椂闂�", icon: "none" });
+ return false;
+ }
+ if (form.frequencyType === "MONTHLY" && (!monthlyDate.value || !monthlyTime.value)) {
+ uni.showToast({ title: "璇烽�夋嫨姣忔湀鏃ユ湡鍜屾椂闂�", icon: "none" });
+ return false;
+ }
+ if (form.frequencyType === "QUARTERLY" && (!quarterlyDate.value || !quarterlyTime.value)) {
+ uni.showToast({ title: "璇烽�夋嫨瀛e害鏃ユ湡鍜屾椂闂�", icon: "none" });
+ return false;
+ }
+ return true;
+ };
+
+ const buildFrequencyDetail = () => {
+ if (form.frequencyType === "WEEKLY") return `${form.week},${form.time}`;
+ if (form.frequencyType === "MONTHLY") {
+ const day = monthlyDate.value.split("-")[2] || "";
+ return `${day},${monthlyTime.value}`;
+ }
+ if (form.frequencyType === "QUARTERLY") {
+ const [y, m, d] = (quarterlyDate.value || "").split("-");
+ return `${m},${d},${quarterlyTime.value}`;
+ }
+ return form.frequencyDetail || "";
+ };
+
+ const submitForm = async () => {
+ if (!validateForm()) return;
+ try {
+ const payload = {
+ id: form.id,
+ taskName: form.taskName.trim(),
+ deviceIds: JSON.stringify(form.deviceIds || []),
+ registrantId: form.registrantId,
+ registrant: form.registrant,
+ registrationDate: form.registrationDate,
+ frequencyType: form.frequencyType,
+ frequencyDetail: buildFrequencyDetail(),
+ remarks: form.remarks || "",
+ status: "0",
+ active: true,
+ deleted: 0,
+ };
+ if (operationType.value === "edit" && form.id) {
+ await deviceMaintenanceTaskEdit(payload);
+ } else {
+ delete payload.id;
+ await deviceMaintenanceTaskAdd(payload);
+ }
+ uni.showToast({
+ title: "鎻愪氦鎴愬姛",
+ icon: "success",
+ });
+ cancel();
+ } catch (error) {
+ uni.showToast({
+ title: "鎻愪氦澶辫触锛岃閲嶈瘯",
+ icon: "none",
+ });
+ }
+ };
+
+ const cancel = () => {
+ dialogVisitable.value = false;
+ resetForm();
+ emit("closeDia");
+ };
+
+ defineExpose({ openDialog });
+</script>
+
+<style scoped lang="scss">
+ :deep(.uni-picker-container) {
+ z-index: 1200 !important;
+ }
+
+ .popup-content {
+ width: 88vw;
+ max-height: 80vh;
+ background: #fff;
+ border-radius: 20rpx;
+ overflow: hidden;
+ }
+
+ .popup-title {
+ text-align: center;
+ font-size: 32rpx;
+ color: #1f1f1f;
+ font-weight: 600;
+ padding: 24rpx 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ }
+
+ .form-body {
+ padding: 24rpx;
+ max-height: 56vh;
+ overflow-y: auto;
+ }
+
+ .form-item {
+ margin-bottom: 20rpx;
+ }
+
+ .label {
+ display: block;
+ margin-bottom: 10rpx;
+ font-size: 24rpx;
+ color: #666;
+ }
+
+ .picker-value {
+ min-height: 72rpx;
+ background: #f7f8fa;
+ border-radius: 12rpx;
+ padding: 0 20rpx;
+ display: flex;
+ align-items: center;
+ color: #333;
+ font-size: 26rpx;
+ }
+
+ .inspector-picker {
+ justify-content: space-between;
+ }
+
+ .inspector-tags {
+ display: flex;
+ flex-wrap: wrap;
+ margin-top: 10rpx;
+ gap: 10rpx;
+ }
+
+ .inspector-tag {
+ display: flex;
+ align-items: center;
+ gap: 8rpx;
+ background: #edf3ff;
+ color: #1677ff;
+ font-size: 22rpx;
+ border-radius: 999rpx;
+ padding: 6rpx 14rpx;
+ }
+
+ .popup-footer {
+ display: flex;
+ gap: 16rpx;
+ padding: 20rpx 24rpx 24rpx;
+ border-top: 1rpx solid #f0f0f0;
+ }
+
+ .inspector-popup {
+ background: #fff;
+ border-radius: 24rpx 24rpx 0 0;
+ overflow: hidden;
+ max-height: 70vh;
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+
+ .inspector-header {
+ padding: 24rpx;
+ text-align: center;
+ border-bottom: 1rpx solid #f0f0f0;
+ }
+
+ .inspector-title {
+ color: #1f1f1f;
+ font-size: 30rpx;
+ font-weight: 600;
+ }
+
+ .inspector-list {
+ max-height: 46vh;
+ padding: 0 24rpx;
+ }
+
+ .inspector-row {
+ min-height: 82rpx;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1rpx solid #f5f5f5;
+ }
+
+ .inspector-name {
+ font-size: 26rpx;
+ color: #333;
+ }
+
+ .inspector-footer {
+ display: flex;
+ gap: 16rpx;
+ padding: 20rpx 24rpx 24rpx;
+ }
+</style>
diff --git a/src/pages/equipmentManagement/upkeepTask/index.vue b/src/pages/equipmentManagement/upkeepTask/index.vue
new file mode 100644
index 0000000..5f0181a
--- /dev/null
+++ b/src/pages/equipmentManagement/upkeepTask/index.vue
@@ -0,0 +1,449 @@
+<template>
+ <view class="upkeep-task-page">
+ <PageHeader title="瀹氭椂浠诲姟绠$悊"
+ @back="goBack" />
+ <view class="toolbar">
+ <view class="search-section">
+ <view class="search-bar">
+ <view class="search-input">
+ <up-input class="search-text"
+ placeholder="璇疯緭鍏ヤ繚鍏讳换鍔″悕绉�"
+ v-model="queryParams.taskName"
+ clearable />
+ </view>
+ <view class="search-button"
+ @click="handleQuery">
+ <up-icon name="search"
+ size="24"
+ color="#999"></up-icon>
+ </view>
+ </view>
+ </view>
+ <view class="meta-bar">
+ <text class="meta-text">鍏� {{ total }} 鏉�</text>
+ </view>
+ </view>
+ <view class="list-section">
+ <uni-swipe-action>
+ <uni-swipe-action-item v-for="item in tableData"
+ :key="item.id"
+ :right-options="swipeOptions"
+ @click="onSwipeActionClick($event, item)">
+ <view class="ledger-item">
+ <view class="item-header">
+ <view class="item-left">
+ <view class="document-icon">
+ <up-icon name="file-text"
+ size="14"
+ color="#ffffff"></up-icon>
+ </view>
+ <text class="item-id">{{ item.taskName || "--" }}</text>
+ </view>
+ <view class="item-right">
+ <u-tag :type="getFrequencyTagType(item.frequencyType)"
+ :text="formatFrequency(item.frequencyType) || '鏈煡棰戞'" />
+ </view>
+ </view>
+ <up-divider></up-divider>
+ <view class="item-details">
+ <view class="detail-row">
+ <text class="detail-label">浠诲姟缂栧彿</text>
+ <text class="detail-value">{{ item.id || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">璁惧</text>
+ <text class="detail-value">{{ item.deviceName || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">寮�濮嬫棩鏈熶笌鏃堕棿</text>
+ <text class="detail-value highlight">{{ formatFrequencyDetail(item.frequencyDetail) }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鐧昏浜�</text>
+ <text class="detail-value">{{ item.registrant || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鐧昏鏃ユ湡</text>
+ <text class="detail-value">{{ item.registrationDate || item.createTime || "--" }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">澶囨敞</text>
+ <text class="detail-value">{{ item.remarks || "鏃�" }}</text>
+ </view>
+ <up-divider></up-divider>
+ <view class="card-actions">
+ <u-button type="primary"
+ size="small"
+ class="action-btn"
+ @click.stop="handleAdd(item)">缂栬緫</u-button>
+ </view>
+ </view>
+ </view>
+ </uni-swipe-action-item>
+ </uni-swipe-action>
+ <uni-load-more :status="loadMoreStatus"></uni-load-more>
+ <view v-if="!loading && tableData.length === 0"
+ class="no-data">
+ <text>鏆傛棤鏁版嵁</text>
+ </view>
+ </view>
+ <view class="fab-button"
+ @click="handleAdd()">
+ <up-icon name="plus"
+ size="24"
+ color="#ffffff"></up-icon>
+ </view>
+ <form-dia ref="formDia"
+ @closeDia="handleQuery" />
+ </view>
+</template>
+
+<script setup>
+ import { ref, reactive, computed, nextTick } from "vue";
+ import { onShow, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
+ import PageHeader from "@/components/PageHeader.vue";
+ import FormDia from "@/pages/equipmentManagement/upkeepTask/components/formDia.vue";
+ import {
+ deviceMaintenanceTaskDel,
+ deviceMaintenanceTaskList,
+ } from "@/api/equipmentManagement/upkeep.js";
+
+ const formDia = ref();
+ const queryParams = reactive({
+ taskName: "",
+ });
+ const pageParams = reactive({
+ current: 1,
+ size: 10,
+ });
+ const total = ref(0);
+ const loading = ref(false);
+ const tableData = ref([]);
+ const swipeOptions = [
+ {
+ text: "鍒犻櫎",
+ style: {
+ backgroundColor: "#ee0a24",
+ },
+ },
+ ];
+
+ const noMore = computed(() => tableData.value.length >= total.value);
+ const loadMoreStatus = computed(() => {
+ if (loading.value) return "loading";
+ if (noMore.value) return "noMore";
+ return "more";
+ });
+
+ const goBack = () => {
+ uni.navigateBack();
+ };
+
+ const formatFrequency = value => {
+ if (value === "DAILY") return "姣忔棩";
+ if (value === "WEEKLY") return "姣忓懆";
+ if (value === "MONTHLY") return "姣忔湀";
+ if (value === "QUARTERLY") return "瀛e害";
+ return "";
+ };
+
+ const getFrequencyTagType = value => {
+ if (value === "DAILY") return "success";
+ if (value === "WEEKLY") return "primary";
+ if (value === "MONTHLY") return "warning";
+ return "info";
+ };
+
+ const formatFrequencyDetail = value => {
+ if (!value || typeof value !== "string") return "--";
+ return value.replace(
+ /MON|TUE|WED|THU|FRI|SAT|SUN/g,
+ item =>
+ ({
+ MON: "鍛ㄤ竴",
+ TUE: "鍛ㄤ簩",
+ WED: "鍛ㄤ笁",
+ THU: "鍛ㄥ洓",
+ FRI: "鍛ㄤ簲",
+ SAT: "鍛ㄥ叚",
+ SUN: "鍛ㄦ棩",
+ })[item] || item
+ );
+ };
+
+ const getList = async () => {
+ if (loading.value) return;
+ loading.value = true;
+ try {
+ const params = {
+ ...queryParams,
+ current: pageParams.current,
+ size: pageParams.size,
+ };
+ const res = await deviceMaintenanceTaskList(params);
+ const records = res?.data?.records || res?.records || [];
+ if (pageParams.current === 1) {
+ tableData.value = records;
+ } else {
+ tableData.value = [...tableData.value, ...records];
+ }
+ total.value = Number(res?.data?.total ?? res?.total ?? 0);
+ } catch (error) {
+ if (pageParams.current === 1) {
+ tableData.value = [];
+ }
+ uni.showToast({
+ title: "鑾峰彇鏁版嵁澶辫触",
+ icon: "none",
+ });
+ } finally {
+ loading.value = false;
+ }
+ };
+
+ const handleQuery = () => {
+ pageParams.current = 1;
+ total.value = 0;
+ getList();
+ };
+
+ const loadMore = () => {
+ if (loading.value || noMore.value) return;
+ pageParams.current += 1;
+ getList();
+ };
+
+ const handleAdd = row => {
+ nextTick(() => {
+ formDia.value?.openDialog(row ? "edit" : "add", row);
+ });
+ };
+
+ const deleteOne = async row => {
+ if (!row?.id) return;
+ const canDelete = await new Promise(resolve => {
+ uni.showModal({
+ title: "鎻愮ず",
+ content: "鏄惁纭鍒犻櫎璇ヤ繚鍏讳换鍔★紵",
+ success: modalRes => resolve(Boolean(modalRes.confirm)),
+ fail: () => resolve(false),
+ });
+ });
+ if (!canDelete) return;
+ try {
+ await deviceMaintenanceTaskDel([row.id]);
+ uni.showToast({
+ title: "鍒犻櫎鎴愬姛",
+ icon: "success",
+ });
+ handleQuery();
+ } catch (error) {
+ uni.showToast({
+ title: "鍒犻櫎澶辫触",
+ icon: "none",
+ });
+ }
+ };
+
+ const onSwipeActionClick = (event, row) => {
+ if (event?.position !== "right") return;
+ deleteOne(row);
+ };
+
+ onShow(() => {
+ handleQuery();
+ });
+
+ onReachBottom(() => {
+ loadMore();
+ });
+
+ onPullDownRefresh(() => {
+ handleQuery();
+ uni.stopPullDownRefresh();
+ });
+</script>
+
+<style scoped>
+ .upkeep-task-page {
+ min-height: 100vh;
+ background: #f6f7fb;
+ }
+
+ .toolbar {
+ padding: 20rpx 24rpx;
+ background: #fff;
+ border-bottom: 1rpx solid #f0f0f0;
+ position: sticky;
+ top: 0;
+ z-index: 10;
+ }
+
+ .search-section {
+ margin-top: 0;
+ }
+
+ .search-bar {
+ display: flex;
+ align-items: center;
+ background: #f7f8fa;
+ border-radius: 14rpx;
+ padding: 8rpx 12rpx 8rpx 16rpx;
+ border: 1rpx solid #eef1f5;
+ }
+
+ .search-input {
+ flex: 1;
+ min-width: 0;
+ }
+
+ .search-text {
+ background: transparent !important;
+ }
+
+ :deep(.search-text .u-input__content),
+ :deep(.search-text .up-input__content) {
+ background: transparent !important;
+ padding: 0 !important;
+ }
+
+ .search-button {
+ width: 64rpx;
+ height: 64rpx;
+ border-radius: 12rpx;
+ background: #ffffff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .meta-bar {
+ margin-top: 16rpx;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background: #f7f9fc;
+ border-radius: 12rpx;
+ padding: 10rpx 16rpx;
+ }
+
+ .meta-text {
+ color: #5c6b8a;
+ font-size: 22rpx;
+ }
+
+ .list-section {
+ padding: 20rpx 24rpx;
+ padding-bottom: calc(132rpx + env(safe-area-inset-bottom));
+ }
+
+ .ledger-item {
+ background: #ffffff;
+ border-radius: 20rpx;
+ margin-bottom: 16rpx;
+ overflow: hidden;
+ box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.05);
+ padding: 0 20rpx;
+ }
+
+ .item-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 22rpx 0;
+ }
+
+ .item-left {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ flex: 1;
+ min-width: 0;
+ }
+
+ .item-right {
+ display: flex;
+ align-items: center;
+ }
+
+ .document-icon {
+ width: 38rpx;
+ height: 38rpx;
+ border-radius: 8rpx;
+ background: #2979ff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .item-id {
+ font-size: 28rpx;
+ color: #1f1f1f;
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .item-details {
+ padding: 18rpx 0 20rpx;
+ }
+
+ .detail-row {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-bottom: 12rpx;
+ }
+
+ .detail-label {
+ min-width: 160rpx;
+ color: #777;
+ font-size: 24rpx;
+ }
+
+ .detail-value {
+ flex: 1;
+ color: #333;
+ font-size: 24rpx;
+ text-align: right;
+ word-break: break-all;
+ margin-left: 12rpx;
+ }
+
+ .detail-value.highlight {
+ color: #2979ff;
+ font-weight: 500;
+ }
+
+ .card-actions {
+ padding-top: 8rpx;
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ .action-btn {
+ min-width: 140rpx;
+ }
+
+ .fab-button {
+ position: fixed;
+ bottom: calc(30px + env(safe-area-inset-bottom));
+ right: 30px;
+ width: 56px;
+ height: 56px;
+ background: #2979ff;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3);
+ z-index: 1000;
+ }
+
+ .no-data {
+ padding: 40rpx 0;
+ text-align: center;
+ color: #999;
+ }
+</style>
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 127bcba..00f37cd 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -433,12 +433,13 @@
},
{
icon: "/static/images/icon/xunjianshangchuan@2x.png",
- label: "宸℃绠$悊",
+ label: "宸℃浠诲姟",
},
{
icon: "/static/images/icon/xunjianshangchuan@2x.png",
- label: "宸℃浠诲姟绠$悊",
- }
+ label: "宸℃绠$悊",
+ },
+
]);
// 澶勭悊甯哥敤鍔熻兘鐐瑰嚮
@@ -653,6 +654,11 @@
url: "/pages/equipmentManagement/repair/index",
});
break;
+ case "璁惧淇濆吇浠诲姟":
+ uni.navigateTo({
+ url: "/pages/equipmentManagement/upkeepTask/index",
+ });
+ break;
case "璁惧淇濆吇":
uni.navigateTo({
url: "/pages/equipmentManagement/upkeep/index",
@@ -663,7 +669,7 @@
url: "/pages/inspectionUpload/index",
});
break;
- case "宸℃浠诲姟绠$悊":
+ case "宸℃浠诲姟":
uni.navigateTo({
url: "/pages/inspectionManagement/index",
});
@@ -1040,17 +1046,26 @@
const originalEquipment = [
{ icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "杩愯绠$悊" },
{ icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "璁惧鎶ヤ慨" },
+ { icon: "/static/images/icon/shbeibaoyang@2x.png", label: "璁惧淇濆吇浠诲姟" },
{ icon: "/static/images/icon/shbeibaoyang@2x.png", label: "璁惧淇濆吇" },
+ { icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "宸℃浠诲姟" },
{ icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "宸℃绠$悊" },
- { icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "宸℃浠诲姟绠$悊" },
];
const filteredEquipment = originalEquipment.filter(item => {
return allowedMenuTitles.has(item.label);
});
+ if (filteredEquipment.some(i => i.label === "璁惧淇濆吇")) {
+ const upkeepTask = originalEquipment.find(i => i.label === "璁惧淇濆吇浠诲姟");
+ if (upkeepTask && !filteredEquipment.some(i => i.label === "璁惧淇濆吇浠诲姟")) {
+ const upkeepIndex = filteredEquipment.findIndex(i => i.label === "璁惧淇濆吇");
+ filteredEquipment.splice(upkeepIndex, 0, upkeepTask);
+ }
+ }
if (filteredEquipment.some(i => i.label === "宸℃绠$悊")) {
- const task = originalEquipment.find(i => i.label === "宸℃浠诲姟绠$悊");
- if (task && !filteredEquipment.some(i => i.label === "宸℃浠诲姟绠$悊")) {
- filteredEquipment.push(task);
+ const task = originalEquipment.find(i => i.label === "宸℃浠诲姟");
+ if (task && !filteredEquipment.some(i => i.label === "宸℃浠诲姟")) {
+ const manageIndex = filteredEquipment.findIndex(i => i.label === "宸℃绠$悊");
+ filteredEquipment.splice(manageIndex, 0, task);
}
}
equipmentItems.splice(0, equipmentItems.length, ...filteredEquipment);
diff --git a/src/pages/indexItem.vue b/src/pages/indexItem.vue
index 7e78b6b..b38db48 100644
--- a/src/pages/indexItem.vue
+++ b/src/pages/indexItem.vue
@@ -325,6 +325,11 @@
url: "/pages/equipmentManagement/repair/index",
});
break;
+ case "璁惧淇濆吇浠诲姟":
+ uni.navigateTo({
+ url: "/pages/equipmentManagement/upkeepTask/index",
+ });
+ break;
case "璁惧淇濆吇":
uni.navigateTo({
url: "/pages/equipmentManagement/upkeep/index",
diff --git a/src/pages/inspectionManagement/index.vue b/src/pages/inspectionManagement/index.vue
index 349d1d0..4fe2335 100644
--- a/src/pages/inspectionManagement/index.vue
+++ b/src/pages/inspectionManagement/index.vue
@@ -1,17 +1,8 @@
<template>
<view class="inspection-management-page">
- <PageHeader title="宸℃浠诲姟绠$悊"
+ <PageHeader title="瀹氭椂浠诲姟绠$悊"
@back="goBack" />
<view class="toolbar">
- <view class="tab-wrap">
- <view v-for="tab in tabs"
- :key="tab.name"
- class="tab-item"
- :class="{ active: activeTab === tab.name }"
- @click="switchTab(tab.name)">
- {{ tab.label }}
- </view>
- </view>
<view class="search-section">
<view class="search-bar">
<view class="search-input">
@@ -36,8 +27,7 @@
<uni-swipe-action>
<uni-swipe-action-item v-for="item in tableData"
:key="item.id"
- :right-options="activeTab === 'taskManage' ? swipeOptions : []"
- :disabled="activeTab !== 'taskManage'"
+ :right-options="swipeOptions"
@click="onSwipeActionClick($event, item)">
<view class="ledger-item">
<view class="item-header">
@@ -92,16 +82,10 @@
</view>
<up-divider></up-divider>
<view class="card-actions">
- <u-button v-if="activeTab === 'taskManage'"
- type="primary"
+ <u-button type="primary"
size="small"
class="action-btn"
@click.stop="handleAdd(item)">缂栬緫</u-button>
- <u-button v-else
- type="success"
- size="small"
- class="action-btn"
- @click.stop="viewFile(item)">鏌ョ湅闄勪欢</u-button>
</view>
</view>
</view>
@@ -113,8 +97,7 @@
<text>鏆傛棤鏁版嵁</text>
</view>
</view>
- <view v-if="activeTab === 'taskManage'"
- class="fab-button"
+ <view class="fab-button"
@click="handleAdd()">
<up-icon name="plus"
size="24"
@@ -122,7 +105,6 @@
</view>
<form-dia ref="formDia"
@closeDia="handleQuery" />
- <view-files ref="viewFiles" />
</view>
</template>
@@ -131,20 +113,12 @@
import { onShow, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
import PageHeader from "@/components/PageHeader.vue";
import FormDia from "@/pages/inspectionManagement/components/formDia.vue";
- import ViewFiles from "@/pages/inspectionManagement/components/viewFiles.vue";
import {
delTimingTask,
- inspectionTaskList,
timingTaskList,
} from "@/api/inspectionManagement/index.js";
const formDia = ref();
- const viewFiles = ref();
- const activeTab = ref("taskManage");
- const tabs = [
- { name: "taskManage", label: "瀹氭椂浠诲姟绠$悊" },
- { name: "task", label: "瀹氭椂浠诲姟璁板綍" },
- ];
const queryParams = reactive({
taskName: "",
});
@@ -219,12 +193,6 @@
return [String(val)];
};
- const switchTab = tabName => {
- if (activeTab.value === tabName) return;
- activeTab.value = tabName;
- handleQuery();
- };
-
const getList = async () => {
if (loading.value) return;
loading.value = true;
@@ -234,8 +202,7 @@
current: pageParams.current,
size: pageParams.size,
};
- const request = activeTab.value === "task" ? inspectionTaskList : timingTaskList;
- const res = await request(params);
+ const res = await timingTaskList(params);
const records = res?.data?.records || [];
const normalized = records.map(item => ({
...item,
@@ -278,12 +245,6 @@
});
};
- const viewFile = row => {
- nextTick(() => {
- viewFiles.value?.openDialog(row);
- });
- };
-
const deleteOne = async row => {
if (!row?.id) return;
const canDelete = await new Promise(resolve => {
@@ -311,7 +272,6 @@
};
const onSwipeActionClick = (event, row) => {
- if (activeTab.value !== "taskManage") return;
if (event?.position !== "right") return;
deleteOne(row);
};
@@ -345,30 +305,8 @@
z-index: 10;
}
- .tab-wrap {
- display: flex;
- background: #f4f5f8;
- border-radius: 16rpx;
- padding: 6rpx;
- }
-
- .tab-item {
- flex: 1;
- text-align: center;
- padding: 14rpx 0;
- font-size: 26rpx;
- color: #666;
- border-radius: 12rpx;
- }
-
- .tab-item.active {
- background: #1677ff;
- color: #fff;
- font-weight: 600;
- }
-
.search-section {
- margin-top: 20rpx;
+ margin-top: 0;
}
.search-bar {
--
Gitblit v1.9.3