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
+302
View File
@@ -0,0 +1,302 @@
// pages/device_maintenance/create/index.js
const { deviceApi, deviceMaintenanceApi, dictionaryApi } = require("../../../utils/api");
const dayjs = require("../../../miniprogram_npm/dayjs/index");
Page({
data: {
loading: true,
submitting: false,
isEditMode: false,
maintenanceId: null,
subDevice: {}, // 子设备信息
maintenanceTypes: [], // 保养类型
typeIndex: -1,
form: {
sub_device_id: "",
maintenance_type: "",
start_time: "",
start_time_display: "",
end_time: "",
end_time_display: "",
notes: "",
},
customType: "", // 自定义类型
showCustomInput: false,
// 选择器可见性
typePickerVisible: false,
startTimePickerVisible: false,
endTimePickerVisible: false,
currentDate: dayjs().format("YYYY-MM-DD HH:mm"),
},
onLoad: function (options) {
const sub_device_id = options.sub_device_id;
const maintenance_id = options.maintenance_id;
this.setData({
isEditMode: !!maintenance_id,
maintenanceId: maintenance_id || null,
"form.sub_device_id": parseInt(sub_device_id),
});
wx.setNavigationBarTitle({
title: this.data.isEditMode ? "编辑保养记录" : "创建保养记录",
});
this.initializePage(sub_device_id, maintenance_id);
},
async initializePage(sub_device_id, maintenance_id) {
try {
await this.loadMaintenanceTypes();
if (this.data.isEditMode) {
await this.loadMaintenanceData(maintenance_id);
} else {
await this.loadSubDeviceInfo(sub_device_id);
this.setData({
"form.start_time": new Date().getTime(),
"form.start_time_display": dayjs().format("YYYY-MM-DD HH:mm"),
});
}
} catch (error) {
this.showMessage("页面加载失败,请返回重试", "error");
} finally {
this.setData({ loading: false });
}
},
async loadMaintenanceTypes() {
try {
const res = await dictionaryApi.getDictionaryByType("maintenance_type");
if (res.code === 200) {
const types = res.data.map(item => ({
value: item.value,
label: item.value,
}));
types.push({ value: "custom", label: "手动输入" });
this.setData({ maintenanceTypes: types });
if (!this.data.isEditMode && types.length > 1) {
this.setData({
typeIndex: 0,
"form.maintenance_type": types[0].value,
});
} else if (types.length === 1) {
// 只有手动输入选项
this.setData({
typeIndex: 0,
showCustomInput: true,
"form.maintenance_type": "",
});
}
}
} catch (error) {
this.setData({
maintenanceTypes: [{ value: "custom", label: "手动输入" }],
typeIndex: 0,
showCustomInput: true,
"form.maintenance_type": "",
});
}
},
async loadSubDeviceInfo(sub_device_id) {
try {
const res = await deviceApi.getSubDeviceById(sub_device_id);
if (res.code === 200 || res.code === 0) {
this.setData({ subDevice: res.data });
} else {
throw new Error('获取子设备信息失败');
}
} catch (error) {
this.showMessage("加载设备信息失败", "error");
this.setData({ subDevice: { name: '加载失败' } });
}
},
async loadMaintenanceData(maintenance_id) {
try {
const res = await deviceMaintenanceApi.getMaintenance(maintenance_id);
if (res.code === 200) {
const maintenance = res.data;
await this.loadSubDeviceInfo(maintenance.sub_device_id);
this.setData({
form: {
sub_device_id: maintenance.sub_device_id,
maintenance_type: maintenance.maintenance_type,
start_time: new Date(maintenance.start_time).getTime(),
start_time_display: dayjs(maintenance.start_time).format("YYYY-MM-DD HH:mm"),
end_time: maintenance.end_time ? new Date(maintenance.end_time).getTime() : "",
end_time_display: maintenance.end_time ? dayjs(maintenance.end_time).format("YYYY-MM-DD HH:mm") : "",
notes: maintenance.notes || "",
},
});
} else {
throw new Error('获取保养记录失败');
}
} catch (error) {
this.showMessage("加载保养记录失败", "error");
}
},
showTypePicker() {
this.setData({ typePickerVisible: true });
},
showStartTimePicker() {
this.setData({ startTimePickerVisible: true });
},
showEndTimePicker() {
this.setData({ endTimePickerVisible: true });
},
onTypeConfirm(e) {
const selectedValue = e.detail.value[0];
const selectedIndex = this.data.maintenanceTypes.findIndex(type => type.value === selectedValue);
const selectedType = this.data.maintenanceTypes[selectedIndex];
if (!selectedType) {
this.showMessage("选择的保养类型无效", "error");
return;
}
if (selectedType.value === "custom") {
this.setData({
typeIndex: selectedIndex,
showCustomInput: true,
"form.maintenance_type": "",
typePickerVisible: false,
});
} else {
this.setData({
typeIndex: selectedIndex,
showCustomInput: false,
"form.maintenance_type": selectedType.value,
typePickerVisible: false,
});
}
},
onTypePickerCancel() {
this.setData({ typePickerVisible: false });
},
onTypeChange(e) {
const selectedValue = e.detail.value[0];
const selectedIndex = this.data.maintenanceTypes.findIndex(type => type.value === selectedValue);
this.setData({ typeIndex: selectedIndex });
},
onCustomTypeChange(e) {
const customType = e.detail.value;
this.setData({
customType: customType,
"form.maintenance_type": customType,
});
},
onStartTimeConfirm(e) {
const { value } = e.detail;
// 将ISO格式转换为iOS兼容格式
const formattedValue = value.replace('T', ' ').substring(0, 16);
this.setData({
"form.start_time": new Date(value).getTime(),
"form.start_time_display": dayjs(value).format("YYYY-MM-DD HH:mm"),
startTimePickerVisible: false,
});
},
onStartTimeCancel() {
this.setData({ startTimePickerVisible: false });
},
onEndTimeConfirm(e) {
const { value } = e.detail;
// 将ISO格式转换为iOS兼容格式
const formattedValue = value.replace('T', ' ').substring(0, 16);
this.setData({
"form.end_time": new Date(value).getTime(),
"form.end_time_display": dayjs(value).format("YYYY-MM-DD HH:mm"),
endTimePickerVisible: false,
});
},
onEndTimeCancel() {
this.setData({ endTimePickerVisible: false });
},
onNotesChange(e) {
this.setData({ "form.notes": e.detail.value });
},
validateForm() {
const { sub_device_id, maintenance_type, start_time } = this.data.form;
if (!sub_device_id) {
this.showMessage("子设备信息加载失败", "error");
return false;
}
if (!maintenance_type) {
this.showMessage("请选择或输入保养类型", "error");
return false;
}
if (!start_time) {
this.showMessage("请选择开始时间", "error");
return false;
}
return true;
},
async submitForm() {
if (!this.validateForm()) {
return;
}
this.setData({ submitting: true });
try {
const formData = {
sub_device_id: this.data.form.sub_device_id,
maintenance_type: this.data.form.maintenance_type,
start_time: dayjs(this.data.form.start_time).format("YYYY-MM-DD HH:mm:ss"),
end_time: this.data.form.end_time ? dayjs(this.data.form.end_time).format("YYYY-MM-DD HH:mm:ss") : null,
notes: this.data.form.notes || '',
};
let res;
if (this.data.isEditMode) {
res = await deviceMaintenanceApi.updateMaintenance(this.data.maintenanceId, formData);
} else {
res = await deviceMaintenanceApi.createMaintenance(formData);
}
if (res.code === 200 || res.code === 0) {
this.showMessage(this.data.isEditMode ? "更新成功" : "添加成功", "success");
setTimeout(() => {
wx.navigateBack();
}, 1500);
} else {
throw new Error(res.message || (this.data.isEditMode ? "更新失败" : "添加失败"));
}
} catch (error) {
this.showMessage(error.message || (this.data.isEditMode ? "更新失败" : "添加失败"), "error");
} finally {
this.setData({ submitting: false });
}
},
showMessage(message, type = "info") {
wx.showToast({
title: message,
icon: type === "success" ? "success" : type === "error" ? "error" : "none",
duration: 2000,
});
},
});
@@ -0,0 +1,14 @@
{
"navigationBarTitleText": "创建保养记录",
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button",
"t-input": "tdesign-miniprogram/input/input",
"t-textarea": "tdesign-miniprogram/textarea/textarea",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-message": "tdesign-miniprogram/message/message",
"t-loading": "tdesign-miniprogram/loading/loading",
"t-picker": "tdesign-miniprogram/picker/picker",
"t-picker-item": "tdesign-miniprogram/picker-item/picker-item",
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker"
}
}
+141
View File
@@ -0,0 +1,141 @@
<view class="container">
<t-message id="t-message" />
<!-- 加载状态 -->
<view class="loading-container" wx:if="{{loading}}">
<t-loading theme="circular" size="40rpx" loading />
<text>加载中...</text>
</view>
<!-- 表单内容 -->
<block wx:else>
<view class="form-group">
<!-- 子设备信息显示 -->
<view class="form-item">
<text class="label">子设备 <text class="required">*</text></text>
<t-input
value="{{subDevice.name || '加载中...'}}"
placeholder="加载中..."
disabled
/>
</view>
<!-- 保养类型选择 -->
<view class="form-item">
<text class="label">保养类型 <text class="required">*</text></text>
<view class="datetime-picker-wrapper" bindtap="showTypePicker">
<t-cell
title="{{form.maintenance_type || '请选择保养类型'}}"
arrow
hover
note="{{form.maintenance_type ? '' : '必选'}}"
t-class="picker-cell"
/>
</view>
</view>
<!-- 手动输入保养类型 -->
<view class="form-item" wx:if="{{showCustomInput}}">
<text class="label">自定义类型</text>
<t-input
value="{{customType}}"
placeholder="请输入自定义保养类型"
bind:change="onCustomTypeChange"
/>
</view>
<!-- 开始时间选择 -->
<view class="form-item">
<text class="label">开始时间 <text class="required">*</text></text>
<view class="datetime-picker-wrapper" bindtap="showStartTimePicker">
<t-cell
title="{{form.start_time_display || '请选择开始时间'}}"
arrow
hover
note="{{form.start_time ? '' : '必选'}}"
t-class="picker-cell"
/>
</view>
</view>
<!-- 结束时间选择 -->
<view class="form-item">
<text class="label">结束时间</text>
<view class="datetime-picker-wrapper" bindtap="showEndTimePicker">
<t-cell
title="{{form.end_time_display || '请选择结束时间'}}"
arrow
hover
note="{{form.end_time ? '' : '可选'}}"
t-class="picker-cell"
/>
</view>
</view>
<!-- 备注信息 -->
<view class="form-item">
<text class="label">备注</text>
<t-textarea
value="{{form.notes}}"
placeholder="请输入保养备注信息(选填)"
maxlength="200"
indicator
bind:change="onNotesChange"
/>
</view>
</view>
<view class="submit-container">
<t-button
theme="primary"
size="large"
loading="{{submitting}}"
disabled="{{submitting}}"
bind:tap="submitForm"
block
>{{isEditMode ? '更新保养记录' : '添加保养记录'}}</t-button>
</view>
</block>
<!-- 保养类型选择器 -->
<t-picker
title="选择保养类型"
visible="{{typePickerVisible}}"
value="{{[form.maintenance_type]}}"
bind:change="onTypeChange"
bind:cancel="onTypePickerCancel"
bind:confirm="onTypeConfirm"
>
<t-picker-item options="{{maintenanceTypes}}" />
</t-picker>
<!-- 开始时间选择器 -->
<t-date-time-picker
title="选择开始时间"
visible="{{startTimePickerVisible}}"
mode="minute"
format="YYYY-MM-DD HH:mm"
value="{{form.start_time || currentDate}}"
confirm-btn="确认"
cancel-btn="取消"
bind:confirm="onStartTimeConfirm"
bind:cancel="onStartTimeCancel"
auto-close
show-week
/>
<!-- 结束时间选择器 -->
<t-date-time-picker
title="选择结束时间"
visible="{{endTimePickerVisible}}"
mode="minute"
format="YYYY-MM-DD HH:mm"
value="{{form.end_time || currentDate}}"
confirm-btn="确认"
cancel-btn="取消"
bind:confirm="onEndTimeConfirm"
bind:cancel="onEndTimeCancel"
auto-close
show-week
/>
</view>
+246
View File
@@ -0,0 +1,246 @@
/* pages/surgery/create/index.wxss */
.container {
padding: 30rpx;
background-color: #f6f6f6;
min-height: 100vh;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300rpx;
}
.form-group {
background-color: #fff;
border-radius: 12rpx;
padding: 20rpx 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
}
.form-item {
margin-bottom: 30rpx;
}
.label {
display: block;
font-size: 28rpx;
margin-bottom: 16rpx;
color: #333;
}
.required {
color: #e34d59;
}
.picker-cell {
padding: 20rpx !important;
border-radius: 8rpx;
background-color: #f8f8f8 !important;
}
/* 原生选择器样式 */
.picker-view {
padding: 24rpx;
background-color: #f8f8f8;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
position: relative;
}
.time-picker {
margin-top: 16rpx;
}
.picker-note {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
padding-left: 24rpx;
}
/* 设备选择相关样式 - 更新 */
.device-selection-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
}
.device-selection-header text {
font-size: 28rpx;
font-weight: bold;
}
.add-device-btn {
color: #06a56c;
font-size: 26rpx;
padding: 10rpx 20rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.selected-devices-list {
margin-top: 12rpx;
background-color: #f8f8f8;
border-radius: 8rpx;
padding: 12rpx;
display: block; /* 确保设备列表容器显示 */
}
.device-item {
background-color: #fff;
border-radius: 8rpx;
margin-bottom: 12rpx;
padding: 8rpx;
box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.05);
display: block; /* 确保设备项显示 */
}
.device-item:last-child {
margin-bottom: 0;
}
.device-item-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx;
}
.device-info {
flex: 1;
}
.device-name {
font-size: 28rpx;
color: #333;
}
.device-action {
display: flex;
align-items: center;
}
.delete-btn {
padding: 8rpx 20rpx;
background-color: #e34d59;
color: #fff;
border-radius: 4rpx;
font-size: 24rpx;
}
.remove-icon {
padding: 10rpx;
color: #e34d59;
}
.no-devices {
text-align: center;
color: #999;
font-size: 26rpx;
padding: 30rpx 0;
background-color: #f8f8f8;
border-radius: 8rpx;
}
.submit-container {
margin-top: 60rpx;
padding-bottom: 40rpx;
}
/* 年月日时分秒选择器样式 */
.datetime-picker-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.datetime-picker-container {
position: fixed;
bottom: -500rpx;
left: 0;
width: 100%;
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
z-index: 1001;
transition: all 0.3s ease;
}
.datetime-picker-container.show {
bottom: 0;
}
.datetime-picker-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.datetime-picker-header .title {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.datetime-picker-header .cancel-btn,
.datetime-picker-header .confirm-btn {
font-size: 28rpx;
padding: 8rpx 10rpx;
}
.datetime-picker-header .cancel-btn {
color: #999;
}
.datetime-picker-header .confirm-btn {
color: #0052d9;
}
.datetime-picker-body {
padding: 20rpx 0;
height: 300rpx;
}
.picker-item {
line-height: 50px;
text-align: center;
}
.time-display {
padding: 20rpx;
background-color: #f8f8f8;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
}
/* 自定义级联选择器样式 */
:host {
--td-cascader-active-color: #0052d9;
}
/* 设备选择器的自定义样式 */
.custom-picker {
--td-picker-confirm-color: #0052d9;
}
.custom-confirm-btn {
color: #0052d9 !important;
}
.custom-cancel-btn {
color: #999 !important;
}