first commit
This commit is contained in:
@@ -0,0 +1,970 @@
|
||||
// pages/surgery/create/index.js
|
||||
const { surgeryApi, doctorApi, deviceApi } = require("../../../utils/api");
|
||||
const dayjs = require("../../../miniprogram_npm/dayjs/index");
|
||||
|
||||
Page({
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
loading: true, // 页面加载状态
|
||||
submitting: false, // 表单提交状态
|
||||
isEditMode: false, // 是否为编辑模式
|
||||
surgeryId: null, // 编辑模式下的手术ID
|
||||
|
||||
// 表单数据
|
||||
formData: {
|
||||
surgery_id: "", // 手术编号
|
||||
surgery_name: "", // 手术名称
|
||||
patient: "", // 患者姓名
|
||||
surgery_time: "", // 完整手术时间戳
|
||||
surgery_time_display: "", // 显示的完整手术时间
|
||||
},
|
||||
|
||||
// 主刀医生相关
|
||||
doctors: [], // 医生列表
|
||||
selectedDoctor: null, // 已选择的医生
|
||||
selectedDoctorValue: "", // 级联选择器选中的医生值
|
||||
doctorSelectorVisible: false, // 医生选择器弹窗可见性
|
||||
departmentDoctors: [], // 按科室分组的医生列表
|
||||
activeTabIndex: 0, // 当前激活的科室标签索引
|
||||
|
||||
// 设备相关
|
||||
devices: [], // 设备列表
|
||||
deviceTree: [], // 树形结构的设备数据
|
||||
selectedSubDevices: [], // 已选择的设备
|
||||
selectedDeviceValues: [], // 已选择的设备值数组
|
||||
selectedDeviceValue: "", // 当前选中的设备值
|
||||
deviceSelectorVisible: false, // 设备选择器弹窗可见性
|
||||
|
||||
// 新增:设备状态追踪
|
||||
deviceStatus: {}, // 记录设备状态 {id: {status: 0/1, inUse: bool}}
|
||||
|
||||
// TreeSelect 组件所需的自定义键名配置
|
||||
treeSelectKeys: {
|
||||
label: "label",
|
||||
value: "value",
|
||||
children: "children",
|
||||
},
|
||||
|
||||
// 级联选择器
|
||||
cascaderVisible: false, // 级联选择器可见性
|
||||
doctorCascaderOptions: [], // 医生级联选择器选项
|
||||
|
||||
// 日期时间选择器相关
|
||||
dateTimePickerVisible: false, // 日期时间选择器可见性
|
||||
currentDate: "", // 当前日期时间用于默认值
|
||||
minDate: "", // 新增:允许的最小日期时间(当前时间)
|
||||
|
||||
// 设备时间选择器相关
|
||||
deviceStartTimePickerVisible: false, // 设备开始时间选择器可见性
|
||||
deviceEndTimePickerVisible: false, // 设备结束时间选择器可见性
|
||||
currentDeviceTimeIndex: -1, // 当前正在设置时间的设备索引
|
||||
currentDeviceStartTime: "", // 当前设备开始时间
|
||||
currentDeviceEndTime: "", // 当前设备结束时间
|
||||
},
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
// 设置当前时间作为默认值和最小时间限制
|
||||
this.setCurrentDateTime();
|
||||
// 手术记录回显
|
||||
let formData = wx.getStorageSync("surgery_formData")
|
||||
let that = this
|
||||
if (formData) {
|
||||
wx.showModal({
|
||||
title: "是否显示未保存记录 ",
|
||||
cancelText: "否",
|
||||
confirmText: "是",
|
||||
success (res) {
|
||||
if (res.confirm) {
|
||||
that.setData({
|
||||
formData: {...formData},
|
||||
selectedDoctor: formData.doctor
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
wx.removeStorageSync('surgery_formData')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 检查是否为编辑模式
|
||||
if (options && options.id && options.mode === "edit") {
|
||||
const surgeryId = options.id;
|
||||
this.setData({
|
||||
isEditMode: true,
|
||||
surgeryId: surgeryId,
|
||||
});
|
||||
wx.setNavigationBarTitle({
|
||||
title: "编辑手术记录",
|
||||
});
|
||||
} else {
|
||||
wx.setNavigationBarTitle({
|
||||
title: "创建手术记录",
|
||||
});
|
||||
}
|
||||
|
||||
// 并行加载医生和设备数据
|
||||
Promise.all([this.fetchDoctors(), this.fetchDevices()])
|
||||
.then(() => {
|
||||
// 如果是编辑模式,加载现有手术数据
|
||||
if (this.data.isEditMode && this.data.surgeryId) {
|
||||
this.fetchSurgeryDetails(this.data.surgeryId);
|
||||
} else {
|
||||
this.setData({ loading: false });
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setData({ loading: false });
|
||||
});
|
||||
},
|
||||
/*
|
||||
* 保存表单数据到本地
|
||||
*/
|
||||
saveData (doctor) {
|
||||
let formData = {...this.data.formData}
|
||||
if (doctor) formData.doctor = doctor
|
||||
wx.setStorageSync("surgery_formData", formData)
|
||||
},
|
||||
/**
|
||||
* 获取手术详情
|
||||
*/
|
||||
async fetchSurgeryDetails(surgeryId) {
|
||||
try {
|
||||
const res = await surgeryApi.getSurgeryById(surgeryId);
|
||||
|
||||
const surgery = res.data;
|
||||
if (!surgery) {
|
||||
throw new Error("未找到手术记录");
|
||||
}
|
||||
|
||||
// 格式化日期显示 - 使用安全的日期解析
|
||||
const surgeryTime = this.safeParseDate(surgery.surgery_time);
|
||||
const timestamp = surgeryTime.getTime();
|
||||
const formattedDateTime = dayjs(surgeryTime).format("YYYY年MM月DD日 HH:mm:ss");
|
||||
|
||||
// 更新表单数据
|
||||
this.setData({
|
||||
formData: {
|
||||
surgery_id: surgery.surgery_id || "",
|
||||
surgery_name: surgery.surgery_name || "",
|
||||
patient: surgery.patient || "",
|
||||
surgery_time: timestamp,
|
||||
surgery_time_display: formattedDateTime,
|
||||
},
|
||||
});
|
||||
|
||||
// 设置选中的医生
|
||||
if (surgery.doctor) {
|
||||
|
||||
// 检查选项中是否包含当前医生
|
||||
const targetDoctorId = surgery.doctor.id;
|
||||
const findDoctorInOptions = (options) => {
|
||||
for (const dept of options) {
|
||||
for (const doctor of dept.children || []) {
|
||||
if (doctor.doctor && doctor.doctor.id === targetDoctorId) {
|
||||
return doctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const foundDoctor = findDoctorInOptions(this.data.doctorCascaderOptions);
|
||||
|
||||
this.setSelectedDoctor(surgery.doctor);
|
||||
} else {
|
||||
// 手术数据中没有医生信息
|
||||
}
|
||||
|
||||
// 设置选中的设备
|
||||
if (surgery.surgerySubDevices && Array.isArray(surgery.surgerySubDevices)) {
|
||||
const selectedDevices = [];
|
||||
|
||||
surgery.surgerySubDevices.forEach((surgerySubDevice) => {
|
||||
if (surgerySubDevice.subDevice) {
|
||||
// 为子设备添加设备名称和时间信息
|
||||
const subDevice = {
|
||||
...surgerySubDevice.subDevice,
|
||||
device_name: surgerySubDevice.subDevice.device ? surgerySubDevice.subDevice.device.name : "未知设备",
|
||||
// 添加设备时间信息
|
||||
startTime: surgerySubDevice.start_time || null,
|
||||
endTime: surgerySubDevice.end_time || null,
|
||||
startTimeDisplay: surgerySubDevice.start_time ? dayjs(surgerySubDevice.start_time).format('YYYY-MM-DD HH:mm') : '点击设置',
|
||||
endTimeDisplay: surgerySubDevice.end_time ? dayjs(surgerySubDevice.end_time).format('YYYY-MM-DD HH:mm') : '点击设置',
|
||||
};
|
||||
|
||||
selectedDevices.push(subDevice);
|
||||
|
||||
// 更新设备状态
|
||||
if (this.data.deviceStatus[subDevice.id]) {
|
||||
const updatedDeviceStatus = { ...this.data.deviceStatus };
|
||||
updatedDeviceStatus[subDevice.id].inUse = true;
|
||||
this.setData({
|
||||
deviceStatus: updatedDeviceStatus,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.setData({
|
||||
selectedSubDevices: selectedDevices,
|
||||
});
|
||||
} else {
|
||||
// 手术数据中没有设备信息
|
||||
}
|
||||
|
||||
this.setData({ loading: false });
|
||||
} catch (error) {
|
||||
this.showMessage("获取手术详情失败,请返回重试", "error");
|
||||
this.setData({ loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据医生数据设置选中的医生
|
||||
*/
|
||||
setSelectedDoctor(doctor) {
|
||||
if (!doctor || !doctor.id) return;
|
||||
|
||||
// 查找并设置医生级联选择器的值
|
||||
const doctorValue = `doctor_${doctor.id}`;
|
||||
|
||||
this.setData({
|
||||
selectedDoctor: doctor,
|
||||
selectedDoctorValue: doctorValue,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 安全的日期解析函数
|
||||
*/
|
||||
safeParseDate(dateStr) {
|
||||
if (!dateStr) return new Date();
|
||||
|
||||
// 尝试不同的日期格式
|
||||
const formats = [
|
||||
dateStr, // 原始格式
|
||||
dateStr.replace(' ', 'T'), // ISO格式
|
||||
dateStr.replace(' ', 'T') + '+08:00', // 带时区的ISO格式
|
||||
new Date(dateStr) // 直接解析
|
||||
];
|
||||
|
||||
for (let i = 0; i < formats.length; i++) {
|
||||
try {
|
||||
const date = typeof formats[i] === 'string' ? new Date(formats[i]) : formats[i];
|
||||
if (!isNaN(date.getTime())) {
|
||||
return date;
|
||||
}
|
||||
} catch (e) {
|
||||
// 日期格式解析失败
|
||||
}
|
||||
}
|
||||
|
||||
// 如果都失败了,返回当前时间
|
||||
return new Date();
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置当前日期时间作为默认值和最小时间限制
|
||||
*/
|
||||
setCurrentDateTime() {
|
||||
const now = new Date();
|
||||
const formattedDateTime = dayjs(now).format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
this.setData({
|
||||
currentDate: formattedDateTime,
|
||||
minDate: formattedDateTime, // 设置最小时间为当前时间
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取医生列表
|
||||
*/
|
||||
async fetchDoctors() {
|
||||
try {
|
||||
// 调用API获取医生列表数据
|
||||
const res = await doctorApi.getDoctors();
|
||||
|
||||
// 后端返回的是分页格式:{list: [...], total: ...}
|
||||
const doctorData = res.data;
|
||||
if (!doctorData || !doctorData.list || !Array.isArray(doctorData.list)) {
|
||||
throw new Error("获取医生数据格式错误");
|
||||
}
|
||||
|
||||
// 过滤确保医生数据完整(包含科室信息)
|
||||
const validDoctors = doctorData.list.filter((doctor) => doctor && doctor.id && doctor.name && doctor.department && doctor.department.name);
|
||||
|
||||
// 按科室分组医生,为级联选择器准备数据
|
||||
const departmentsMap = new Map();
|
||||
validDoctors.forEach((doctor) => {
|
||||
const deptId = doctor.department.id;
|
||||
const deptName = doctor.department.name;
|
||||
|
||||
if (!departmentsMap.has(deptId)) {
|
||||
departmentsMap.set(deptId, {
|
||||
label: deptName,
|
||||
value: `dept_${deptId}`,
|
||||
children: [],
|
||||
});
|
||||
}
|
||||
|
||||
// 将医生添加到对应科室的children中
|
||||
departmentsMap.get(deptId).children.push({
|
||||
label: doctor.name,
|
||||
value: `doctor_${doctor.id}`,
|
||||
// 保存原始医生对象用于选中后的数据处理
|
||||
doctor: doctor,
|
||||
});
|
||||
});
|
||||
|
||||
// 将Map转换为数组
|
||||
const doctorCascaderOptions = Array.from(departmentsMap.values());
|
||||
|
||||
this.setData({
|
||||
loading: false,
|
||||
doctors: validDoctors,
|
||||
doctorCascaderOptions,
|
||||
});
|
||||
} catch (error) {
|
||||
this.setData({ loading: false });
|
||||
this.showMessage("获取医生列表失败,请重试", "error");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取设备数据并构建树形结构
|
||||
*/
|
||||
async fetchDevices() {
|
||||
try {
|
||||
// 调用API获取所有设备数据
|
||||
const res = await deviceApi.getDevices();
|
||||
|
||||
// 后端返回的是分页格式:{list: [...], total: ...}
|
||||
const deviceData = res.data;
|
||||
if (!deviceData || !deviceData.list || !Array.isArray(deviceData.list)) {
|
||||
throw new Error("获取设备数据格式错误");
|
||||
}
|
||||
|
||||
const devices = deviceData.list;
|
||||
|
||||
// 获取所有子设备
|
||||
const subDevicesRes = await deviceApi.getAllSubDevices();
|
||||
const subDevicesData = subDevicesRes.data;
|
||||
|
||||
// 后端返回的是分页格式:{list: [...], total: ...}
|
||||
const subDevices = subDevicesData.list || [];
|
||||
|
||||
// 构建设备状态字典
|
||||
const deviceStatus = {};
|
||||
subDevices.forEach((subDevice) => {
|
||||
deviceStatus[subDevice.id] = {
|
||||
status: subDevice.status || 0, // 0表示可用,1表示占用
|
||||
inUse: false, // 当前表单中是否被选择
|
||||
};
|
||||
});
|
||||
|
||||
// 构建树形结构数据
|
||||
const deviceTree = devices.map((device) => {
|
||||
// 找出该设备下的所有子设备
|
||||
const children = subDevices
|
||||
.filter((sub) => sub.device_id === device.id)
|
||||
.map((sub) => {
|
||||
const subDeviceName = sub.name || `设备${sub.id}`;
|
||||
const statusText = sub.status === 1 ? " (占用中)" : "";
|
||||
return {
|
||||
label: `${subDeviceName}${statusText}`, // 显示占用状态
|
||||
value: `subdevice_${sub.id}`,
|
||||
// 移除基于状态的禁用设置,允许选择占用中的设备
|
||||
// 保存完整的子设备数据
|
||||
subDevice: {
|
||||
...sub,
|
||||
name: sub.name || `设备${sub.id}`, // 确保有名称
|
||||
device_name: device.name, // 添加设备名称,方便显示
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
label: device.name,
|
||||
value: `device_${device.id}`,
|
||||
// 只有当没有子设备时才禁用主设备选择,不再因子设备被占用而禁用
|
||||
disabled: children.length === 0,
|
||||
children,
|
||||
};
|
||||
});
|
||||
|
||||
this.setData({
|
||||
devices,
|
||||
deviceTree,
|
||||
deviceStatus,
|
||||
});
|
||||
} catch (error) {
|
||||
this.showMessage("获取设备数据失败,请重试", "warning");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理输入框内容变更
|
||||
*/
|
||||
onInputChange(e) {
|
||||
const { field } = e.currentTarget.dataset;
|
||||
const { value } = e.detail;
|
||||
this.setData({
|
||||
[`formData.${field}`]: value,
|
||||
});
|
||||
this.saveData()
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示日期时间选择器
|
||||
*/
|
||||
showDateTimePicker() {
|
||||
this.setData({
|
||||
dateTimePickerVisible: true,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 日期时间选择器确认事件
|
||||
*/
|
||||
onDateTimeConfirm(e) {
|
||||
// 使用 dayjs 格式化日期时间显示
|
||||
const formattedDateTime = dayjs(e.detail.value).format("YYYY年MM月DD日 HH:mm:ss");
|
||||
const timestamp = new Date(e.detail.value).getTime();
|
||||
|
||||
this.setData({
|
||||
"formData.surgery_time": timestamp,
|
||||
"formData.surgery_time_display": formattedDateTime,
|
||||
dateTimePickerVisible: false,
|
||||
});
|
||||
this.saveData()
|
||||
},
|
||||
|
||||
/**
|
||||
* 日期时间选择器取消事件
|
||||
*/
|
||||
onDateTimeCancel() {
|
||||
this.setData({
|
||||
dateTimePickerVisible: false,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 日期时间选择器变化事件
|
||||
*/
|
||||
onDateTimeChange(e) {
|
||||
// 日期时间选择器变化事件
|
||||
},
|
||||
|
||||
/**
|
||||
* 日期时间选择器选择事件
|
||||
*/
|
||||
onDateTimePick(e) {
|
||||
// 日期时间选择器选择事件
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示医生选择器弹窗 - 使用级联选择器选项卡风格
|
||||
*/
|
||||
showDoctorSelector() {
|
||||
if (this.data.doctorCascaderOptions.length === 0) {
|
||||
this.showMessage("暂无可选医生", "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
doctorSelectorVisible: true,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 级联选择器关闭事件
|
||||
*/
|
||||
onDoctorCascaderClose(e) {
|
||||
this.setData({
|
||||
doctorSelectorVisible: false,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 级联选择器变更事件
|
||||
*/
|
||||
onDoctorCascaderChange(e) {
|
||||
const { value, selectedOptions } = e.detail;
|
||||
|
||||
if (value && value.startsWith("doctor_")) {
|
||||
// 获取医生 ID
|
||||
const doctorId = Number(value.split("_")[1]);
|
||||
|
||||
// 查找选中的医生数据
|
||||
const findDoctor = (options, doctorId) => {
|
||||
for (const dept of options) {
|
||||
for (const doctorOption of dept.children || []) {
|
||||
if (doctorOption.doctor && doctorOption.doctor.id === doctorId) {
|
||||
return doctorOption.doctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const selectedDoctor = findDoctor(this.data.doctorCascaderOptions, doctorId);
|
||||
|
||||
if (selectedDoctor) {
|
||||
this.setData({
|
||||
selectedDoctor,
|
||||
selectedDoctorValue: value,
|
||||
doctorSelectorVisible: false, // 选择后自动关闭选择器
|
||||
});
|
||||
this.showMessage(`已选择医生:${selectedDoctor.name}(${selectedDoctor.department.name})`, "success");
|
||||
}
|
||||
this.saveData(selectedDoctor)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 级联选择器选择事件
|
||||
*/
|
||||
onDoctorCascaderPick(e) {
|
||||
// 级联选择器选择事件
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理设备选择变更事件
|
||||
*/
|
||||
onDeviceChange(e) {
|
||||
const { value } = e.detail;
|
||||
|
||||
// 找出选中的子设备
|
||||
const selectedSubDevices = [];
|
||||
const findSubDevices = (tree, values) => {
|
||||
if (!tree || !values) return;
|
||||
|
||||
for (const node of tree) {
|
||||
if (node.children) {
|
||||
for (const child of node.children) {
|
||||
if (values.includes(child.value) && child.subDevice) {
|
||||
selectedSubDevices.push(child.subDevice);
|
||||
}
|
||||
}
|
||||
|
||||
// 递归检查子节点
|
||||
findSubDevices(node.children, values);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
findSubDevices(this.data.deviceTree, value);
|
||||
|
||||
this.setData({
|
||||
selectedDeviceValues: value,
|
||||
selectedSubDevices,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示设备选择器
|
||||
*/
|
||||
showDeviceSelector() {
|
||||
if (this.data.deviceTree.length === 0) {
|
||||
this.showMessage("暂无可选设备", "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
deviceSelectorVisible: true,
|
||||
selectedDeviceValue: "", // 重置选择值,确保每次打开时都从顶层开始选择
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备选择器关闭事件
|
||||
*/
|
||||
onDeviceCascaderClose(e) {
|
||||
this.setData({
|
||||
deviceSelectorVisible: false,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备级联选择器变更事件
|
||||
*/
|
||||
onDeviceCascaderChange(e) {
|
||||
const { value, selectedOptions } = e.detail;
|
||||
|
||||
if (value && value.startsWith("subdevice_")) {
|
||||
// 获取子设备 ID
|
||||
const subDeviceId = Number(value.split("_")[1]);
|
||||
|
||||
// 查找选中的子设备数据
|
||||
const findSubDevice = (options, subDeviceId) => {
|
||||
for (const device of options) {
|
||||
for (const subDeviceOption of device.children || []) {
|
||||
if (subDeviceOption.subDevice && subDeviceOption.subDevice.id === subDeviceId) {
|
||||
return subDeviceOption.subDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const selectedSubDevice = findSubDevice(this.data.deviceTree, subDeviceId);
|
||||
|
||||
if (selectedSubDevice) {
|
||||
|
||||
// 删除设备占用的判断,允许选择任何设备
|
||||
// 原有代码:
|
||||
// if (selectedSubDevice.status === 1) {
|
||||
// this.showMessage(`设备 ${selectedSubDevice.sub_device_name} 当前已占用,请选择其他设备`, "warning");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// 检查是否已经选择过该设备
|
||||
const existingDeviceIndex = this.data.selectedSubDevices.findIndex((device) => device.id === selectedSubDevice.id);
|
||||
|
||||
if (existingDeviceIndex === -1) {
|
||||
// 如果是新设备,添加到已选择的设备列表中
|
||||
const updatedDevices = [...this.data.selectedSubDevices, {
|
||||
...selectedSubDevice,
|
||||
startTime: this.data.formData.surgery_time || new Date().getTime(),
|
||||
startTimeDisplay: this.data.formData.surgery_time_display || dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
endTime: null,
|
||||
endTimeDisplay: "未设置",
|
||||
}];
|
||||
|
||||
// 更新设备状态为已选择
|
||||
const updatedDeviceStatus = { ...this.data.deviceStatus };
|
||||
updatedDeviceStatus[selectedSubDevice.id].inUse = true;
|
||||
|
||||
this.setData({
|
||||
selectedSubDevices: updatedDevices,
|
||||
selectedDeviceValue: value,
|
||||
deviceSelectorVisible: false,
|
||||
deviceStatus: updatedDeviceStatus,
|
||||
});
|
||||
|
||||
// 添加后延迟提示,确保界面已更新
|
||||
setTimeout(() => {
|
||||
this.showMessage(`已添加设备: ${selectedSubDevice.device_name}-${selectedSubDevice.name}`, "success");
|
||||
}, 100);
|
||||
} else {
|
||||
this.showMessage("该设备已被选择", "warning");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备级联选择器选择事件
|
||||
*/
|
||||
onDeviceCascaderPick(e) {
|
||||
// 设备级联选择器选择事件
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示设备开始时间选择器
|
||||
*/
|
||||
showDeviceStartTimePicker(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const device = this.data.selectedSubDevices[index];
|
||||
|
||||
this.setData({
|
||||
currentDeviceTimeIndex: index,
|
||||
currentDeviceStartTime: device.startTime || this.data.formData.surgery_time || this.data.currentDate,
|
||||
deviceStartTimePickerVisible: true,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示设备结束时间选择器
|
||||
*/
|
||||
showDeviceEndTimePicker(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const device = this.data.selectedSubDevices[index];
|
||||
|
||||
this.setData({
|
||||
currentDeviceTimeIndex: index,
|
||||
currentDeviceEndTime: device.endTime || this.data.currentDate,
|
||||
deviceEndTimePickerVisible: true,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备开始时间选择器确认事件
|
||||
*/
|
||||
onDeviceStartTimeConfirm(e) {
|
||||
const { currentDeviceTimeIndex } = this.data;
|
||||
|
||||
if (currentDeviceTimeIndex === -1) return;
|
||||
|
||||
// 格式化时间显示
|
||||
const formattedDateTime = dayjs(e.detail.value).format("YYYY-MM-DD HH:mm:ss");
|
||||
const timestamp = new Date(e.detail.value).getTime();
|
||||
|
||||
// 更新设备时间信息
|
||||
const updatedDevices = [...this.data.selectedSubDevices];
|
||||
updatedDevices[currentDeviceTimeIndex] = {
|
||||
...updatedDevices[currentDeviceTimeIndex],
|
||||
startTime: timestamp,
|
||||
startTimeDisplay: formattedDateTime,
|
||||
};
|
||||
|
||||
this.setData({
|
||||
selectedSubDevices: updatedDevices,
|
||||
deviceStartTimePickerVisible: false,
|
||||
currentDeviceTimeIndex: -1,
|
||||
});
|
||||
|
||||
this.showMessage(`设备开始时间已设置: ${formattedDateTime}`, "success");
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备开始时间选择器取消事件
|
||||
*/
|
||||
onDeviceStartTimeCancel() {
|
||||
this.setData({
|
||||
deviceStartTimePickerVisible: false,
|
||||
currentDeviceTimeIndex: -1,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备结束时间选择器确认事件
|
||||
*/
|
||||
onDeviceEndTimeConfirm(e) {
|
||||
const { currentDeviceTimeIndex } = this.data;
|
||||
|
||||
if (currentDeviceTimeIndex === -1) return;
|
||||
|
||||
// 格式化时间显示
|
||||
const formattedDateTime = dayjs(e.detail.value).format("YYYY-MM-DD HH:mm:ss");
|
||||
const timestamp = new Date(e.detail.value).getTime();
|
||||
|
||||
// 更新设备时间信息
|
||||
const updatedDevices = [...this.data.selectedSubDevices];
|
||||
updatedDevices[currentDeviceTimeIndex] = {
|
||||
...updatedDevices[currentDeviceTimeIndex],
|
||||
endTime: timestamp,
|
||||
endTimeDisplay: formattedDateTime,
|
||||
};
|
||||
|
||||
this.setData({
|
||||
selectedSubDevices: updatedDevices,
|
||||
deviceEndTimePickerVisible: false,
|
||||
currentDeviceTimeIndex: -1,
|
||||
});
|
||||
|
||||
this.showMessage(`设备结束时间已设置: ${formattedDateTime}`, "success");
|
||||
},
|
||||
|
||||
/**
|
||||
* 设备结束时间选择器取消事件
|
||||
*/
|
||||
onDeviceEndTimeCancel() {
|
||||
this.setData({
|
||||
deviceEndTimePickerVisible: false,
|
||||
currentDeviceTimeIndex: -1,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除已选择的设备
|
||||
*/
|
||||
removeDevice(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const removedDevice = this.data.selectedSubDevices[index];
|
||||
|
||||
const newSelectedDevices = [...this.data.selectedSubDevices];
|
||||
newSelectedDevices.splice(index, 1);
|
||||
|
||||
// 更新设备状态为未选择
|
||||
const updatedDeviceStatus = { ...this.data.deviceStatus };
|
||||
updatedDeviceStatus[removedDevice.id].inUse = false;
|
||||
|
||||
this.setData({
|
||||
selectedSubDevices: newSelectedDevices,
|
||||
deviceStatus: updatedDeviceStatus,
|
||||
});
|
||||
|
||||
this.showMessage(`已删除设备: ${removedDevice.device_name}-${removedDevice.name}`, "warning");
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证表单数据
|
||||
*/
|
||||
validateForm() {
|
||||
const { surgery_id, surgery_name, patient, surgery_time } = this.data.formData;
|
||||
const { selectedDoctor } = this.data;
|
||||
console.log(1, surgery_id);
|
||||
|
||||
// 验证手术编号
|
||||
if (!surgery_id) {
|
||||
this.showMessage("请填写手术编号", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof surgery_id !== "string" || surgery_id.trim().length < 3 || surgery_id.trim().length > 50) {
|
||||
this.showMessage("手术编号格式不正确,长度应在3-50个字符之间", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证手术名称
|
||||
if (!surgery_name) {
|
||||
this.showMessage("请填写手术名称", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证患者姓名
|
||||
if (!patient) {
|
||||
this.showMessage("请填写患者姓名", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证手术时间
|
||||
if (!surgery_time) {
|
||||
this.showMessage("请选择手术时间", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证医生选择
|
||||
if (!selectedDoctor) {
|
||||
this.showMessage("请选择主刀医生", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理表单提交
|
||||
*/
|
||||
async handleSubmit() {
|
||||
if (!this.validateForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ submitting: true });
|
||||
|
||||
try {
|
||||
const { surgery_id, surgery_name, patient, surgery_time } = this.data.formData;
|
||||
const { selectedDoctor, selectedSubDevices } = this.data;
|
||||
|
||||
// 将时间转换为数据库需要的格式(YYYY-MM-DD HH:mm:ss)
|
||||
const formattedDateTime = dayjs(surgery_time).format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
// 构建提交数据,确保与网页端数据结构一致
|
||||
const submitData = {
|
||||
surgery_id, // 手术编号
|
||||
surgery_name, // 手术名称
|
||||
surgery_time: formattedDateTime, // 手术时间(本地时间格式)
|
||||
surgery_doctor_id: selectedDoctor.id, // 主刀医生ID
|
||||
patient, // 患者姓名
|
||||
sub_device_ids: selectedSubDevices.map((device) => device.id), // 使用设备ID列表
|
||||
// 添加设备时间信息
|
||||
device_times: selectedSubDevices.map((device) => ({
|
||||
sub_device_id: device.id,
|
||||
start_time: device.startTime ? dayjs(device.startTime).format('YYYY-MM-DD HH:mm:ss') : null,
|
||||
end_time: device.endTime ? dayjs(device.endTime).format('YYYY-MM-DD HH:mm:ss') : null,
|
||||
})),
|
||||
};
|
||||
let res;
|
||||
if (this.data.isEditMode) {
|
||||
// 调用更新手术API
|
||||
res = await surgeryApi.updateSurgery(this.data.surgeryId, submitData);
|
||||
this.showMessage("更新手术记录成功", "success");
|
||||
} else {
|
||||
// 调用创建手术API
|
||||
res = await surgeryApi.createSurgery(submitData);
|
||||
this.showMessage("创建手术记录成功", "success");
|
||||
}
|
||||
|
||||
// 延迟返回上一页,让用户看到成功提示
|
||||
setTimeout(() => {
|
||||
// 通过全局变量通知列表页面数据已变更
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
const prevPage = pages[pages.length - 2];
|
||||
// 如果上一个页面是手术列表页,标记数据已变更
|
||||
if (prevPage.route === 'pages/surgery/index' && prevPage.markDataChanged) {
|
||||
prevPage.markDataChanged();
|
||||
}
|
||||
}
|
||||
wx.removeStorageSync("surgery_formData")
|
||||
wx.navigateBack();
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
// 简化错误处理,使错误信息更简洁
|
||||
let errorMessage = this.data.isEditMode ? "更新失败,请稍后重试" : "创建失败,请稍后重试";
|
||||
|
||||
// 检查error.message直接是否包含错误信息
|
||||
if (error.message && typeof error.message === "string") {
|
||||
|
||||
if (error.message.includes("手术编号已存在") || error.message.includes("该手术编号已存在")) {
|
||||
errorMessage = `手术编号已重复,请更换`;
|
||||
} else if (error.message.includes("医生") && error.message.includes("时间")) {
|
||||
errorMessage = `医生时间冲突,请调整`;
|
||||
} else {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
}
|
||||
// 检查error.data.message(原有逻辑)
|
||||
else if (error.data && error.data.message) {
|
||||
|
||||
if (error.data.message.includes("手术编号已存在") || error.data.message.includes("该手术编号已存在")) {
|
||||
errorMessage = `手术编号已重复,请更换`;
|
||||
} else if (error.data.message.includes("医生") && error.data.message.includes("时间")) {
|
||||
errorMessage = `医生时间冲突,请调整`;
|
||||
} else {
|
||||
errorMessage = error.data.message;
|
||||
}
|
||||
}
|
||||
// 检查error.data.msg(后端返回的标准格式)
|
||||
else if (error.data && error.data.msg) {
|
||||
|
||||
if (error.data.msg.includes("手术编号已存在") || error.data.msg.includes("该手术编号已存在")) {
|
||||
errorMessage = `手术编号已重复,请更换`;
|
||||
} else if (error.data.msg.includes("医生") && error.data.msg.includes("时间")) {
|
||||
errorMessage = `医生时间冲突,请调整`;
|
||||
} else {
|
||||
errorMessage = error.data.msg;
|
||||
}
|
||||
}
|
||||
|
||||
this.showMessage(errorMessage, "error");
|
||||
} finally {
|
||||
this.setData({ submitting: false });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示消息提示
|
||||
*/
|
||||
showMessage(message, type = "info") {
|
||||
// 确保消息显示
|
||||
|
||||
// 先尝试使用 t-message 组件
|
||||
const t = this.selectComponent("#t-message");
|
||||
if (t && typeof t.show === "function") {
|
||||
wx.nextTick(() => {
|
||||
t.show({
|
||||
message,
|
||||
type,
|
||||
duration: 3000,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 如果组件不可用,降级使用原生toast
|
||||
let icon = "none";
|
||||
if (type === "success") icon = "success";
|
||||
if (type === "error") icon = "error";
|
||||
|
||||
wx.showToast({
|
||||
title: message,
|
||||
icon: icon,
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"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-cascader": "tdesign-miniprogram/cascader/cascader",
|
||||
"t-calendar": "tdesign-miniprogram/calendar/calendar",
|
||||
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker",
|
||||
"t-tree-select": "tdesign-miniprogram/tree-select/tree-select"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<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="{{formData.surgery_id}}"
|
||||
placeholder="请输入手术编号"
|
||||
bindchange="onInputChange"
|
||||
data-field="surgery_id"
|
||||
maxlength="50"
|
||||
disabled="{{isEditMode}}"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">手术名称 <text class="required">*</text></text>
|
||||
<t-input
|
||||
value="{{formData.surgery_name}}"
|
||||
placeholder="请输入手术名称"
|
||||
bindchange="onInputChange"
|
||||
data-field="surgery_name"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">患者姓名 <text class="required">*</text></text>
|
||||
<t-input
|
||||
value="{{formData.patient}}"
|
||||
placeholder="请输入患者姓名"
|
||||
bindchange="onInputChange"
|
||||
data-field="patient"
|
||||
maxlength="50"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 手术时间选择 -->
|
||||
<view class="form-item">
|
||||
<text class="label">手术时间 <text class="required">*</text></text>
|
||||
<view class="datetime-picker-wrapper" bindtap="showDateTimePicker">
|
||||
<t-cell
|
||||
title="{{formData.surgery_time_display || '请选择手术时间'}}"
|
||||
arrow
|
||||
hover
|
||||
data-mode="formData.surgery_time"
|
||||
note="{{formData.surgery_time ? '' : '必选'}}"
|
||||
t-class="picker-cell"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">主刀医生 <text class="required">*</text></text>
|
||||
<t-cell
|
||||
title="{{selectedDoctor ? selectedDoctor.name : '请选择主刀医生'}}"
|
||||
arrow
|
||||
hover
|
||||
note="{{selectedDoctor ? selectedDoctor.department.name : '必选'}}"
|
||||
bind:click="showDoctorSelector"
|
||||
t-class="picker-cell"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 设备选择部分 - 使用与手术详情页一致的样式 -->
|
||||
<view class="form-item">
|
||||
<view class="device-selection-header">
|
||||
<text>设备列表</text>
|
||||
<view class="add-device-btn" bind:tap="showDeviceSelector">添加设备</view>
|
||||
</view>
|
||||
|
||||
<!-- 已选择的设备列表 - 新样式 -->
|
||||
<view class="selected-devices-list" wx:if="{{selectedSubDevices.length > 0}}">
|
||||
<block wx:for="{{selectedSubDevices}}" wx:key="id">
|
||||
<view class="device-item">
|
||||
<view class="device-item-content">
|
||||
<view class="device-info">
|
||||
<view class="device-name">{{item.device_name}}-{{item.name}}</view>
|
||||
</view>
|
||||
<view class="device-action">
|
||||
<view class="delete-btn" bind:tap="removeDevice" data-index="{{index}}">删除</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 设备时间选择 -->
|
||||
<view class="device-time-section">
|
||||
<view class="time-picker-group">
|
||||
<view class="time-picker-item">
|
||||
<text class="time-label">开始时间</text>
|
||||
<view class="time-picker" bindtap="showDeviceStartTimePicker" data-index="{{index}}">
|
||||
<text class="time-value">{{item.startTimeDisplay || '点击设置'}}</text>
|
||||
<text class="picker-arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="time-picker-item">
|
||||
<text class="time-label">结束时间</text>
|
||||
<view class="time-picker" bindtap="showDeviceEndTimePicker" data-index="{{index}}">
|
||||
<text class="time-value">{{item.endTimeDisplay || '点击设置'}}</text>
|
||||
<text class="picker-arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 无设备提示 -->
|
||||
<view class="no-devices" wx:else>
|
||||
<text>暂无选择设备,请点击"添加设备"按钮添加</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="submit-container">
|
||||
<t-button
|
||||
theme="primary"
|
||||
size="large"
|
||||
loading="{{submitting}}"
|
||||
disabled="{{submitting}}"
|
||||
bind:tap="handleSubmit"
|
||||
block>{{isEditMode ? '保存修改' : '创建手术记录'}}</t-button>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 日期时间选择器 -->
|
||||
<t-date-time-picker
|
||||
title="选择手术时间"
|
||||
visible="{{dateTimePickerVisible}}"
|
||||
mode="second"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value="{{formData.surgery_time || currentDate}}"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
bind:confirm="onDateTimeConfirm"
|
||||
bind:cancel="onDateTimeCancel"
|
||||
bind:pick="onDateTimePick"
|
||||
bind:change="onDateTimeChange"
|
||||
auto-close
|
||||
show-week
|
||||
|
||||
/>
|
||||
|
||||
<!-- 医生选择器 - 使用级联选择器选项卡风格 -->
|
||||
<t-cascader
|
||||
visible="{{doctorSelectorVisible}}"
|
||||
options="{{doctorCascaderOptions}}"
|
||||
title="选择主刀医生"
|
||||
theme="tab"
|
||||
value="{{selectedDoctorValue}}"
|
||||
bind:change="onDoctorCascaderChange"
|
||||
bind:pick="onDoctorCascaderPick"
|
||||
bind:close="onDoctorCascaderClose"
|
||||
/>
|
||||
|
||||
<!-- 设备选择器 - 使用级联选择器选项卡风格 -->
|
||||
<t-cascader
|
||||
visible="{{deviceSelectorVisible}}"
|
||||
options="{{deviceTree}}"
|
||||
title="选择使用设备"
|
||||
theme="tab"
|
||||
value="{{selectedDeviceValue}}"
|
||||
bind:change="onDeviceCascaderChange"
|
||||
bind:pick="onDeviceCascaderPick"
|
||||
bind:close="onDeviceCascaderClose"
|
||||
/>
|
||||
|
||||
<!-- 设备开始时间选择器 -->
|
||||
<t-date-time-picker
|
||||
title="选择设备开始使用时间"
|
||||
visible="{{deviceStartTimePickerVisible}}"
|
||||
mode="second"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value="{{currentDeviceStartTime || currentDate}}"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
bind:confirm="onDeviceStartTimeConfirm"
|
||||
bind:cancel="onDeviceStartTimeCancel"
|
||||
auto-close
|
||||
show-week
|
||||
/>
|
||||
|
||||
<!-- 设备结束时间选择器 -->
|
||||
<t-date-time-picker
|
||||
title="选择设备结束使用时间"
|
||||
visible="{{deviceEndTimePickerVisible}}"
|
||||
mode="second"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value="{{currentDeviceEndTime || currentDate}}"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
bind:confirm="onDeviceEndTimeConfirm"
|
||||
bind:cancel="onDeviceEndTimeCancel"
|
||||
auto-close
|
||||
show-week
|
||||
/>
|
||||
</view>
|
||||
@@ -0,0 +1,305 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 设备时间选择部分样式 */
|
||||
.device-time-section {
|
||||
margin-top: 16rpx;
|
||||
padding: 16rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.time-picker-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.time-picker-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12rpx 16rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 6rpx;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.time-picker-item .time-label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 8rpx 12rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4rpx;
|
||||
border: 1px solid #dee2e6;
|
||||
min-width: 200rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.time-picker .time-value {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.time-picker .picker-arrow {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.time-picker:active .picker-arrow {
|
||||
transform: translateX(4rpx);
|
||||
}
|
||||
Reference in New Issue
Block a user