first commit

This commit is contained in:
chz
2026-01-15 15:05:29 +08:00
commit 0ec405e137
66 changed files with 8572 additions and 0 deletions
+402
View File
@@ -0,0 +1,402 @@
const { deviceApi } = require("../../utils/api");
const Toast = require("../../miniprogram_npm/tdesign-miniprogram/toast/index");
Page({
data: {
device: null,
device_id: null,
loading: true,
loadError: false,
// 设备状态相关
deviceStatus: 'normal',
deviceStatusMap: {
normal: '正常',
maintenance: '保养中',
repair: '维修中',
fault: '故障',
},
statusDialogVisible: false,
selectedStatus: 'normal',
// 设备编辑相关
editDialogVisible: false,
editForm: {
name: '',
description: '',
},
// 子设备相关
subDevices: [],
subDeviceLoading: false,
// 保养记录相关
maintenanceStats: {
total: 0,
completed: 0,
inProgress: 0,
},
// 操作选项
actions: [
{
icon: 'setting',
text: '更改状态',
color: '#0052d9',
action: 'changeStatus'
},
{
icon: 'add-circle',
text: '添加保养记录',
color: '#06a56c',
action: 'addMaintenance'
},
{
icon: 'time',
text: '保养记录',
color: '#fa8c16',
action: 'viewMaintenance'
},
{
icon: 'edit',
text: '编辑设备',
color: '#722ed1',
action: 'editDevice'
},
{
icon: 'view-list',
text: '管理子设备',
color: '#0052d9',
action: 'manageSubDevices'
},
{
icon: 'delete',
text: '删除设备',
color: '#e34d59',
action: 'deleteDevice'
}
]
},
onLoad(options) {
if (options.device_id) {
this.setData({ device_id: options.device_id });
this.loadDeviceInfo();
this.loadSubDevices();
this.loadMaintenanceStats();
} else {
Toast({
context: this,
selector: '#t-toast',
message: '缺少设备ID',
theme: 'error',
});
wx.navigateBack();
}
},
onShow() {
// 页面显示时刷新数据
if (this.data.device_id) {
this.loadDeviceInfo();
this.loadSubDevices();
this.loadMaintenanceStats();
}
},
// 加载设备信息
async loadDeviceInfo() {
this.setData({ loading: true, loadError: false });
try {
const response = await deviceApi.getDevices();
const deviceList = response.data.list || response.data || [];
const device = deviceList.find(d => d.id === parseInt(this.data.device_id));
if (device) {
// 计算子设备数量
const subDeviceCount = device.sub_devices ? device.sub_devices.length : 0;
this.setData({
device: { ...device, subDeviceCount },
deviceStatus: device.status || 'normal',
selectedStatus: device.status || 'normal',
editForm: {
name: device.name,
description: device.description || '',
},
loading: false,
});
} else {
this.setData({
loadError: true,
loading: false,
});
}
} catch (error) {
this.setData({
loadError: true,
loading: false,
});
}
},
// 加载子设备
async loadSubDevices() {
this.setData({ subDeviceLoading: true });
try {
const response = await deviceApi.getSubDevicesByDeviceId(this.data.device_id);
const subDevices = response.data.list || response.data || [];
this.setData({
subDevices: subDevices,
subDeviceLoading: false,
});
} catch (error) {
this.setData({
subDevices: [],
subDeviceLoading: false,
});
}
},
// 加载保养记录统计
async loadMaintenanceStats() {
try {
// 这里可以调用保养记录统计API
// 目前使用模拟数据
this.setData({
maintenanceStats: {
total: 0,
completed: 0,
inProgress: 0,
}
});
} catch (error) {
// 加载保养统计失败,使用默认值
}
},
// 处理操作按钮点击
handleAction(e) {
const action = e.currentTarget.dataset.action;
switch (action) {
case 'changeStatus':
this.showStatusDialog();
break;
case 'addMaintenance':
this.addMaintenance();
break;
case 'viewMaintenance':
this.viewMaintenance();
break;
case 'editDevice':
this.showEditDialog();
break;
case 'manageSubDevices':
this.manageSubDevices();
break;
case 'deleteDevice':
this.deleteDevice();
break;
}
},
// 显示状态更改弹窗
showStatusDialog() {
this.setData({
statusDialogVisible: true,
selectedStatus: this.data.deviceStatus,
});
},
// 关闭状态更改弹窗
closeStatusDialog() {
this.setData({
statusDialogVisible: false,
});
},
// 选择状态
selectStatus(e) {
const status = e.currentTarget.dataset.status;
this.setData({
selectedStatus: status,
});
},
// 确认状态更改
async confirmStatusChange() {
const { selectedStatus, device } = this.data;
try {
await deviceApi.updateDevice(device.id, { status: selectedStatus });
this.setData({
deviceStatus: selectedStatus,
statusDialogVisible: false,
});
Toast({
context: this,
selector: '#t-toast',
message: '状态更新成功',
theme: 'success',
});
// 刷新设备信息
this.loadDeviceInfo();
} catch (error) {
Toast({
context: this,
selector: '#t-toast',
message: '状态更新失败',
theme: 'error',
});
}
},
// 显示编辑弹窗
showEditDialog() {
this.setData({
editDialogVisible: true,
});
},
// 关闭编辑弹窗
closeEditDialog() {
this.setData({
editDialogVisible: false,
});
},
// 确认编辑
async confirmEdit() {
const { editForm, device } = this.data;
if (!editForm.name.trim()) {
Toast({
context: this,
selector: '#t-toast',
message: '请输入设备名称',
theme: 'warning',
});
return;
}
try {
await deviceApi.updateDevice(device.id, {
name: editForm.name.trim(),
description: editForm.description.trim(),
});
this.setData({
editDialogVisible: false,
});
Toast({
context: this,
selector: '#t-toast',
message: '设备信息更新成功',
theme: 'success',
});
// 刷新设备信息
this.loadDeviceInfo();
} catch (error) {
Toast({
context: this,
selector: '#t-toast',
message: '更新失败',
theme: 'error',
});
}
},
// 添加保养记录
addMaintenance() {
wx.navigateTo({
url: `/pages/device_maintenance/create/index?device_id=${this.data.device_id}`,
});
},
// 查看保养记录
viewMaintenance() {
wx.navigateTo({
url: `/pages/device_maintenance/index?device_id=${this.data.device_id}`,
});
},
// 管理子设备
manageSubDevices() {
wx.navigateTo({
url: `/pages/device_subdevices/index?device_id=${this.data.device_id}`,
});
},
// 查看子设备详情
viewSubDeviceDetail(e) {
const subDevice = e.currentTarget.dataset.subdevice;
wx.navigateTo({
url: `/pages/device_subdevices/index?device_id=${this.data.device_id}&sub_device_id=${subDevice.id}`,
});
},
// 删除设备
deleteDevice() {
wx.showModal({
title: '确认删除',
content: '确定要删除此设备吗?此操作不可撤销。',
success: (res) => {
if (res.confirm) {
this.confirmDelete();
}
},
});
},
// 确认删除
async confirmDelete() {
const { device } = this.data;
try {
await deviceApi.deleteDevice(device.id);
Toast({
context: this,
selector: '#t-toast',
message: '删除成功',
theme: 'success',
});
// 返回设备管理页面
wx.navigateBack();
} catch (error) {
Toast({
context: this,
selector: '#t-toast',
message: '删除失败',
theme: 'error',
});
}
},
// 返回上一页
onBack() {
wx.navigateBack();
},
// 下拉刷新
onPullDownRefresh() {
Promise.all([
this.loadDeviceInfo(),
this.loadSubDevices(),
this.loadMaintenanceStats(),
]).then(() => {
wx.stopPullDownRefresh();
}).catch(() => {
wx.stopPullDownRefresh();
});
},
});
+19
View File
@@ -0,0 +1,19 @@
{
"navigationBarTitleText": "设备管理详情",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f7f8fa",
"enablePullDownRefresh": true,
"usingComponents": {
"t-toast": "tdesign-miniprogram/toast/toast",
"t-dialog": "tdesign-miniprogram/dialog/dialog",
"t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
"t-empty": "tdesign-miniprogram/empty/empty",
"t-icon": "tdesign-miniprogram/icon/icon",
"t-button": "tdesign-miniprogram/button/button",
"t-tag": "tdesign-miniprogram/tag/tag",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-input": "tdesign-miniprogram/input/input",
"t-textarea": "tdesign-miniprogram/textarea/textarea"
}
}
+72
View File
@@ -0,0 +1,72 @@
<view class="device-detail-page">
<!-- 页面头部 -->
<view class="page-header">
<view class="header-left">
<view class="back-btn" bind:tap="onBack">
<t-icon name="chevron-left" size="48rpx" />
</view>
<view class="device-info">
<view class="device-name">{{device.name}}</view>
<view class="device-meta">
<text class="device-id">ID: {{device.id}}</text>
<text class="subdevice-count">子设备: {{device.subDeviceCount || 0}}个</text>
</view>
</view>
</view>
</view>
<!-- 加载状态 -->
<block wx:if="{{loading}}">
<view class="loading-container">
<t-skeleton theme="paragraph" loading />
<t-skeleton theme="paragraph" loading />
<t-skeleton theme="paragraph" loading />
</view>
</block>
<!-- 错误状态 -->
<block wx:elif="{{loadError}}">
<view class="error-container">
<t-empty icon="error-circle" description="加载失败,请下拉刷新重试" />
</view>
</block>
<!-- 主要内容 -->
<block wx:elif="{{device}}">
<!-- 子设备列表 -->
<view class="subdevices-section">
<view class="section-title">
子设备列表
<text class="subdevice-count">({{subDevices.length}})</text>
</view>
<view wx:if="{{subDeviceLoading}}" class="loading-container">
<t-loading theme="circular" size="40rpx" />
<text class="loading-text">加载中...</text>
</view>
<block wx:elif="{{subDevices.length > 0}}">
<view
wx:for="{{subDevices}}"
wx:key="id"
class="subdevice-item"
bind:tap="viewSubDeviceDetail"
data-subdevice="{{item}}">
<view class="subdevice-info">
<view class="subdevice-name">{{item.name}}</view>
<view class="subdevice-meta">
<text class="subdevice-id">ID: {{item.id}}</text>
<text class="subdevice-usage">使用: {{item.usage_count || 0}}次</text>
<text class="subdevice-status">
状态: <text class="status-badge status-{{item.status || 'normal'}}">{{deviceStatusMap[item.status || 'normal']}}</text>
</text>
</view>
</view>
<t-icon name="chevron-right" size="32rpx" color="#999" />
</view>
</block>
<t-empty wx:else description="暂无子设备" />
</view>
</block>
<!-- Toast 消息提示 -->
<t-toast id="t-toast" />
</view>
+331
View File
@@ -0,0 +1,331 @@
.device-detail-page {
padding: 0;
background: #f5f5f5;
min-height: 100vh;
}
/* 页面头部 */
.page-header {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #e8e8e8;
}
.header-left {
display: flex;
align-items: center;
flex: 1;
}
.back-btn {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.device-info {
flex: 1;
}
.device-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.device-meta {
display: flex;
align-items: center;
gap: 20rpx;
font-size: 24rpx;
color: #666;
}
.device-id {
color: #999;
}
.device-status {
display: flex;
align-items: center;
}
.status-badge {
font-size: 24rpx;
padding: 2rpx 8rpx;
border-radius: 4rpx;
display: inline-block;
font-weight: 500;
margin-left: 8rpx;
}
.status-normal {
color: #06a56c;
background-color: #e8f6f1;
}
.status-maintenance {
color: #fa8c16;
background-color: #fff7e6;
}
.status-repair {
color: #722ed1;
background-color: #f9f0ff;
}
.status-fault {
color: #e34d59;
background-color: #fff1f0;
}
/* 加载和错误状态 */
.loading-container, .error-container {
padding: 100rpx 30rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.loading-text {
margin-top: 20rpx;
font-size: 28rpx;
color: #666;
}
/* 内容区块 */
.info-section, .stats-section, .actions-section, .subdevices-section {
margin: 20rpx 0;
padding: 0 30rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
}
.subdevice-count {
font-size: 28rpx;
color: #666;
font-weight: normal;
margin-left: 10rpx;
}
/* 信息卡片 */
.info-card {
background: #fff;
border-radius: 12rpx;
padding: 30rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.info-item:last-child {
border-bottom: none;
}
.info-label {
font-size: 28rpx;
color: #666;
}
.info-value {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
/* 统计信息 */
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20rpx;
}
.stat-card {
background: #fff;
border-radius: 12rpx;
padding: 30rpx;
text-align: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}
.stat-number {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.stat-number.in-progress {
color: #fa8c16;
}
.stat-number.completed {
color: #06a56c;
}
.stat-label {
font-size: 24rpx;
color: #666;
}
/* 操作按钮 */
.actions-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20rpx;
}
.action-item {
background: #fff;
border-radius: 12rpx;
padding: 30rpx 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.action-item:active {
transform: scale(0.95);
box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.1);
}
.action-icon {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
}
.action-text {
font-size: 26rpx;
color: #333;
text-align: center;
}
/* 子设备列表 */
.subdevice-item {
background: #fff;
border-radius: 12rpx;
padding: 24rpx 30rpx;
margin-bottom: 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}
.subdevice-info {
flex: 1;
}
.subdevice-name {
font-size: 28rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.subdevice-meta {
display: flex;
flex-direction: column;
gap: 8rpx;
font-size: 24rpx;
color: #666;
}
.subdevice-id {
color: #999;
}
.subdevice-usage {
color: #0052d9;
}
.subdevice-status {
display: flex;
align-items: center;
}
.status-badge {
font-size: 24rpx;
padding: 2rpx 8rpx;
border-radius: 4rpx;
display: inline-block;
font-weight: 500;
margin-left: 8rpx;
}
/* 状态选择器 */
.status-options {
display: flex;
flex-direction: column;
gap: 16rpx;
padding: 20rpx 0;
}
.status-option {
display: flex;
align-items: center;
padding: 24rpx 32rpx;
border-radius: 8rpx;
background-color: #f7f8fa;
border: 2rpx solid transparent;
transition: all 0.3s ease;
}
.status-option.selected {
background-color: #eef4ff;
border-color: #0052d9;
}
.status-option:active {
background-color: #e7e9eb;
}
.status-option text {
margin-left: 16rpx;
font-size: 28rpx;
color: #333;
}
.status-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
display: inline-block;
}
/* 编辑表单 */
.edit-form {
padding: 20rpx 0;
}
.t-input, .t-textarea {
margin-bottom: 20rpx;
}