更新灌溉计划页面,添加灌溉计划列表刷新标记,优化项目选择器和时间选择器的逻辑;更新样式以提升用户体验,确保在切换标签时只加载必要的数据。
| | |
| | | JYG: 'https://irrigate.dayuyanjiuyuan.top/', // 嘉峪关项目 |
| | | MQ: 'https://shifanqu1.dayuyanjiuyuan.top/', // 民勤项目 |
| | | TEST: 'https://no253541tf71.vicp.fun/', // test项目 |
| | | SCHOOL: 'https://school.dayuyanjiuyuan.top/' // 学校项目 |
| | | SCHOOL: 'https://school.dayuyanjiuyuan.top/', // 学校项目 |
| | | JC:'https://shifanqu1.dayuyanjiuyuan.top/', |
| | | GSCLT:'https://irrigate.dayuyanjiuyuan.top/'//甘肃农科院崔龙天 |
| | | // TEST:'http://192.168.40.182:8087/'// test项目 |
| | | // MQ: 'https://no253541tf71.vicp.fun/' // 民勤项目 |
| | | // TEST: 'http://192.168.40.166:54321/' |
| | |
| | | operator:"2025030416200600006", |
| | | clientId:"", |
| | | AppID:"wxbc2b6a00dd904ead", |
| | | vcId:"" |
| | | vcId:"", |
| | | needRefreshIrrigationList: false // 用于标记是否需要刷新灌溉计划列表 |
| | | } |
| | | }) |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" fill="none" stroke="#1890FF" stroke-width="4" stroke-linejoin="round"/><path d="M24.0084 12.0001L24.0072 24.0089L32.4866 32.4883" stroke="#1890FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg> |
| | |
| | | const app = getApp(); |
| | | const { get, post } = require('../../api/request'); |
| | | const { |
| | | get, |
| | | post |
| | | } = require('../../api/request'); |
| | | const dayjs = require('dayjs'); |
| | | |
| | | Page({ |
| | | /** |
| | | * 页面的初始数据 |
| | | */ |
| | | data: { |
| | | // 表单数据 |
| | | planCode: '', // 计划编号 |
| | | startTime: '', // 灌溉开始时间 |
| | | pickerValue: '', // 时间选择器的值 |
| | | timePickerVisible: false, // 时间选择器是否可见 |
| | | timeInfoVisible: false, // 时间提示弹窗是否可见 |
| | | // 项目选择器相关 |
| | | projectPickerVisible: false, |
| | | projectPickerValue: [], |
| | | selectedProject: null, |
| | | projectOptions: [], |
| | | totalDuration: 0, // 添加总灌溉时间 |
| | | // 项目列表 |
| | | projectList: [], |
| | | // 时间选择器选项 |
| | | timeOptions: [], |
| | | // 轮灌组列表刷新状态 |
| | | isRefreshing: false |
| | | }, |
| | | /** |
| | | * 页面的初始数据 |
| | | */ |
| | | data: { |
| | | // 表单数据 |
| | | planCode: '', // 计划编号 |
| | | startTime: '', // 灌溉开始时间 |
| | | pickerValue: '', // 时间选择器的值 |
| | | timePickerVisible: false, // 时间选择器是否可见 |
| | | timeInfoVisible: false, // 时间提示弹窗是否可见 |
| | | // 项目选择器相关 |
| | | projectPickerVisible: false, |
| | | projectPickerValue: [], |
| | | selectedProject: null, |
| | | projectOptions: [], |
| | | totalDuration: 0, // 添加总灌溉时间 |
| | | // 项目列表 |
| | | projectList: [], |
| | | // 时间选择器选项 |
| | | timeOptions: [], |
| | | // 轮灌组列表刷新状态 |
| | | isRefreshing: false |
| | | }, |
| | | |
| | | /** |
| | | * 生命周期函数--监听页面加载 |
| | | */ |
| | | onLoad: function (options) { |
| | | // 生成计划编号 |
| | | this.generatePlanCode(); |
| | | // 设置时间选择器的初始值 |
| | | const now = dayjs(); |
| | | this.setData({ |
| | | pickerValue: now.add(8.5, 'hour').format('YYYY-MM-DD HH:mm') |
| | | }); |
| | | // 获取项目列表 |
| | | this.fetchProjects(); |
| | | }, |
| | | /** |
| | | * 生命周期函数--监听页面加载 |
| | | */ |
| | | onLoad: function (options) { |
| | | // 生成计划编号 |
| | | this.generatePlanCode(); |
| | | // 设置时间选择器的初始值 |
| | | const now = dayjs(); |
| | | this.setData({ |
| | | pickerValue: now.add(8.5, 'hour').format('YYYY-MM-DD HH:mm') |
| | | }); |
| | | // 获取项目列表 |
| | | this.fetchProjects(); |
| | | }, |
| | | |
| | | /** |
| | | * 生成计划编号 |
| | | */ |
| | | generatePlanCode: function () { |
| | | const now = dayjs(); |
| | | const dateStr = now.format('YYYYMMDD'); |
| | | const randomNum = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); |
| | | const planCode = `${dateStr}${randomNum}`; |
| | | this.setData({ planCode }); |
| | | }, |
| | | /** |
| | | * 生成计划编号 |
| | | */ |
| | | generatePlanCode: function () { |
| | | const now = dayjs(); |
| | | const dateStr = now.format('YYYY-MM-DD'); |
| | | const randomNum = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); |
| | | const planCode = `${dateStr}${-randomNum}`; |
| | | this.setData({ |
| | | planCode |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取项目列表 |
| | | */ |
| | | fetchProjects: function () { |
| | | return get({ |
| | | url: '/wx/irrigation/getSimpleProjects', |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | const projectList = res.content.map(project => ({ |
| | | id: project.projectId, |
| | | name: project.projectName, |
| | | groupCount: project.groupCount, |
| | | groups: [] |
| | | })); |
| | | |
| | | const projectOptions = projectList.map(project => ({ |
| | | label: project.name, |
| | | value: project.id |
| | | })); |
| | | |
| | | this.setData({ |
| | | projectList, |
| | | projectOptions |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取项目列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(new Error(res.msg || '获取项目列表失败')); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取项目列表失败:', err); |
| | | wx.showToast({ |
| | | title: '获取项目列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(err); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取轮灌组列表 |
| | | */ |
| | | fetchGroups: function (projectId) { |
| | | return get({ |
| | | url: '/wx/irrigation/getSimpleGroups', |
| | | data: { |
| | | projectId: projectId, |
| | | }, |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | console.log('轮灌组数据:', res.content.obj); |
| | | |
| | | // 更新选中项目的轮灌组信息 |
| | | const projectList = this.data.projectList.map(project => { |
| | | if (project.id === projectId) { |
| | | return { |
| | | ...project, |
| | | groups: res.content.obj.map(group => ({ |
| | | id: group.groupId, |
| | | name: group.groupCode, |
| | | duration: group.defaultDuration || 0, |
| | | selected: false, |
| | | intakeCount: group.intakeCount |
| | | })) |
| | | }; |
| | | } |
| | | return project; |
| | | }); |
| | | |
| | | // 更新选中的项目 |
| | | const selectedProject = projectList.find(project => project.id === projectId); |
| | | console.log('更新后的选中项目:', selectedProject); |
| | | |
| | | this.setData({ |
| | | projectList, |
| | | selectedProject |
| | | }, () => { |
| | | // 计算总时间 |
| | | this.calculateTotalDuration(); |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取轮灌组列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(new Error(res.msg || '获取轮灌组列表失败')); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取轮灌组列表失败:', err); |
| | | wx.showToast({ |
| | | title: '获取轮灌组列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(err); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 显示时间选择器 |
| | | */ |
| | | showTimePicker: function () { |
| | | // 如果没有选择时间,使用当前时间 |
| | | if (!this.data.pickerValue) { |
| | | const now = dayjs(); |
| | | this.setData({ |
| | | pickerValue: now.format('YYYY-MM-DD HH:mm') |
| | | }); |
| | | } |
| | | |
| | | this.setData({ |
| | | timePickerVisible: true |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 时间选择器确认回调 |
| | | */ |
| | | onTimePickerConfirm: function (e) { |
| | | const { value } = e.detail; |
| | | this.setData({ |
| | | timePickerVisible: false, |
| | | startTime: value |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 时间选择器取消回调 |
| | | */ |
| | | onTimePickerCancel: function () { |
| | | this.setData({ |
| | | timePickerVisible: false |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换项目展开/折叠状态 |
| | | */ |
| | | toggleProject: function (e) { |
| | | const index = e.currentTarget.dataset.index; |
| | | const currentValue = this.data.projectList[index].expanded; |
| | | |
| | | // 创建新的项目列表,先将所有项目设为折叠状态 |
| | | const newProjectList = this.data.projectList.map((item, idx) => { |
| | | return { |
| | | ...item, |
| | | expanded: false |
| | | }; |
| | | }); |
| | | |
| | | // 如果当前点击的项目已经是展开状态,则保持所有项目折叠 |
| | | // 否则,将当前点击的项目设为展开状态 |
| | | if (!currentValue) { |
| | | newProjectList[index].expanded = true; |
| | | } |
| | | |
| | | this.setData({ |
| | | projectList: newProjectList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换轮灌组选中状态 |
| | | */ |
| | | toggleGroupSelection: function (e) { |
| | | const projectIndex = e.currentTarget.dataset.projectIndex; |
| | | const groupIndex = e.currentTarget.dataset.groupIndex; |
| | | const key = `projectList[${projectIndex}].groups[${groupIndex}].selected`; |
| | | const currentValue = this.data.projectList[projectIndex].groups[groupIndex].selected; |
| | | |
| | | this.setData({ |
| | | [key]: !currentValue |
| | | }); |
| | | |
| | | // 更新项目总时长 |
| | | this.updateProjectTotalDuration(projectIndex); |
| | | }, |
| | | |
| | | /** |
| | | * 处理时长输入 |
| | | */ |
| | | onDurationInput: function (e) { |
| | | const { groupIndex } = e.currentTarget.dataset; |
| | | const duration = parseInt(e.detail.value) || 0; |
| | | |
| | | const selectedProject = { ...this.data.selectedProject }; |
| | | selectedProject.groups[groupIndex].duration = duration; |
| | | |
| | | this.setData({ |
| | | selectedProject |
| | | }, () => { |
| | | // 输入时长后重新计算总时间 |
| | | this.calculateTotalDuration(); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 计算并更新项目总时长 |
| | | */ |
| | | updateProjectTotalDuration: function (projectIndex) { |
| | | const project = this.data.projectList[projectIndex]; |
| | | let totalDuration = 0; |
| | | |
| | | // 计算所有选中的轮灌组的时长总和 |
| | | project.groups.forEach(group => { |
| | | if (group.selected) { |
| | | totalDuration += parseInt(group.duration) || 0; |
| | | } |
| | | }); |
| | | |
| | | // 更新项目总时长 |
| | | const totalDurationKey = `projectList[${projectIndex}].totalDuration`; |
| | | this.setData({ |
| | | [totalDurationKey]: totalDuration |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 阻止事件冒泡 |
| | | */ |
| | | stopPropagation: function (e) { |
| | | if (e && e.stopPropagation) { |
| | | e.stopPropagation(); |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | /** |
| | | * 跳转到轮灌组详情页 |
| | | */ |
| | | navigateToGroupDetail: function (e) { |
| | | const { groupIndex } = e.currentTarget.dataset; |
| | | // TODO: 实现跳转逻辑 |
| | | }, |
| | | |
| | | /** |
| | | * 确认按钮点击事件 |
| | | */ |
| | | onConfirm: function () { |
| | | const { planCode, startTime, selectedProject } = this.data; |
| | | |
| | | if (!planCode) { |
| | | wx.showToast({ |
| | | title: '请输入计划编号', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!selectedProject) { |
| | | wx.showToast({ |
| | | title: '请选择项目', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 构建上报数据 |
| | | const schedules = selectedProject.groups.map(group => ({ |
| | | groupId: group.id, |
| | | duration: parseInt(group.duration) || 0 |
| | | /** |
| | | * 获取项目列表 |
| | | */ |
| | | fetchProjects: function (isShowDiaolog) { |
| | | return get({ |
| | | url: '/wx/irrigation/getSimpleProjects', |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | const projectList = res.content.map(project => ({ |
| | | id: project.projectId, |
| | | name: project.projectName, |
| | | groupCount: project.groupCount, |
| | | groups: [] |
| | | })); |
| | | |
| | | const requestData = { |
| | | projectId: selectedProject.id, |
| | | planName: planCode, |
| | | startupMode: startTime ? 2 : 1, |
| | | operatorId: app.globalData.clientId, |
| | | schedules: schedules |
| | | }; |
| | | const projectOptions = projectList.map(project => ({ |
| | | label: project.name, |
| | | value: project.id |
| | | })); |
| | | |
| | | // 如果有开始时间,添加到请求数据中 |
| | | if (startTime) { |
| | | requestData.planStartTime = startTime; |
| | | } |
| | | |
| | | // 发送请求 |
| | | post({ |
| | | url: '/wx/plan/createPlan', |
| | | data: requestData, |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | wx.showToast({ |
| | | title: '创建成功', |
| | | icon: 'success' |
| | | }); |
| | | // 返回上一页 |
| | | setTimeout(() => { |
| | | wx.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '创建失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.error('创建计划失败:', err); |
| | | wx.showToast({ |
| | | title: '创建失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // 显示项目选择器 |
| | | showProjectPicker() { |
| | | this.setData({ |
| | | projectList, |
| | | projectOptions |
| | | }); |
| | | if (isShowDiaolog) { |
| | | this.setData({ |
| | | projectPickerVisible: true |
| | | }); |
| | | }, |
| | | |
| | | // 项目选择器确认 |
| | | onProjectPickerConfirm(e) { |
| | | const { value } = e.detail; |
| | | console.log('选择的项目ID:', value[0]); // 添加日志查看数据 |
| | | const selectedProject = this.data.projectList.find(project => project.id === value[0]); |
| | | console.log('找到的项目:', selectedProject); // 添加日志查看数据 |
| | | |
| | | this.setData({ |
| | | projectPickerVisible: false, |
| | | selectedProject: selectedProject, |
| | | projectPickerValue: value |
| | | }, () => { |
| | | // 选择项目后获取轮灌组列表 |
| | | if (selectedProject) { |
| | | this.fetchGroups(selectedProject.id); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 项目选择器取消 |
| | | onProjectPickerCancel() { |
| | | this.setData({ |
| | | projectPickerVisible: false |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 计算总灌溉时间 |
| | | */ |
| | | calculateTotalDuration: function () { |
| | | if (!this.data.selectedProject) return; |
| | | |
| | | const totalDuration = this.data.selectedProject.groups.reduce((sum, group) => { |
| | | return sum + (parseInt(group.duration) || 0); |
| | | }, 0); |
| | | |
| | | this.setData({ |
| | | totalDuration |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 轮灌组列表下拉刷新 |
| | | */ |
| | | onGroupListRefresh: function () { |
| | | if (!this.data.selectedProject) { |
| | | this.setData({ isRefreshing: false }); |
| | | return; |
| | | }); |
| | | } |
| | | |
| | | this.setData({ isRefreshing: true }); |
| | | |
| | | this.fetchGroups(this.data.selectedProject.id) |
| | | .then(() => { |
| | | this.setData({ isRefreshing: false }); |
| | | }) |
| | | .catch(() => { |
| | | this.setData({ isRefreshing: false }); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 显示时间提示弹窗 |
| | | */ |
| | | showTimeInfo: function () { |
| | | this.setData({ |
| | | timeInfoVisible: true |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取项目列表失败', |
| | | icon: 'none' |
| | | }); |
| | | }, |
| | | return Promise.reject(new Error(res.msg || '获取项目列表失败')); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取项目列表失败:', err); |
| | | wx.showToast({ |
| | | title: '获取项目列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(err); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 关闭时间提示弹窗 |
| | | */ |
| | | onTimeInfoConfirm: function () { |
| | | this.setData({ |
| | | timeInfoVisible: false |
| | | /** |
| | | * 获取轮灌组列表 |
| | | */ |
| | | fetchGroups: function (projectId) { |
| | | return get({ |
| | | url: '/wx/irrigation/getSimpleGroups', |
| | | data: { |
| | | projectId: projectId, |
| | | }, |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | console.log('轮灌组数据:', res.content); |
| | | |
| | | // 更新选中项目的轮灌组信息 |
| | | const projectList = this.data.projectList.map(project => { |
| | | if (project.id === projectId) { |
| | | return { |
| | | ...project, |
| | | groups: res.content.map(group => ({ |
| | | id: group.groupId, |
| | | name: group.groupCode, |
| | | duration: group.defaultDuration || 0, |
| | | selected: false, |
| | | intakeCount: group.intakeCount |
| | | })) |
| | | }; |
| | | } |
| | | return project; |
| | | }); |
| | | }, |
| | | }); |
| | | |
| | | // 更新选中的项目 |
| | | const selectedProject = projectList.find(project => project.id === projectId); |
| | | console.log('更新后的选中项目:', selectedProject); |
| | | |
| | | this.setData({ |
| | | projectList, |
| | | selectedProject |
| | | }, () => { |
| | | // 计算总时间 |
| | | this.calculateTotalDuration(); |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取轮灌组列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(new Error(res.msg || '获取轮灌组列表失败')); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取轮灌组列表失败:', err); |
| | | wx.showToast({ |
| | | title: '获取轮灌组列表失败', |
| | | icon: 'none' |
| | | }); |
| | | return Promise.reject(err); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 显示时间选择器 |
| | | */ |
| | | showTimePicker: function () { |
| | | // 如果没有选择时间,使用当前时间 |
| | | if (!this.data.pickerValue) { |
| | | const now = dayjs(); |
| | | this.setData({ |
| | | pickerValue: now.format('YYYY-MM-DD HH:mm') |
| | | }); |
| | | } |
| | | |
| | | this.setData({ |
| | | timePickerVisible: true |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 时间选择器确认回调 |
| | | */ |
| | | onTimePickerConfirm: function (e) { |
| | | const { |
| | | value |
| | | } = e.detail; |
| | | this.setData({ |
| | | timePickerVisible: false, |
| | | startTime: value |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 时间选择器取消回调 |
| | | */ |
| | | onTimePickerCancel: function () { |
| | | this.setData({ |
| | | timePickerVisible: false |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换项目展开/折叠状态 |
| | | */ |
| | | toggleProject: function (e) { |
| | | const index = e.currentTarget.dataset.index; |
| | | const currentValue = this.data.projectList[index].expanded; |
| | | |
| | | // 创建新的项目列表,先将所有项目设为折叠状态 |
| | | const newProjectList = this.data.projectList.map((item, idx) => { |
| | | return { |
| | | ...item, |
| | | expanded: false |
| | | }; |
| | | }); |
| | | |
| | | // 如果当前点击的项目已经是展开状态,则保持所有项目折叠 |
| | | // 否则,将当前点击的项目设为展开状态 |
| | | if (!currentValue) { |
| | | newProjectList[index].expanded = true; |
| | | } |
| | | |
| | | this.setData({ |
| | | projectList: newProjectList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换轮灌组选中状态 |
| | | */ |
| | | toggleGroupSelection: function (e) { |
| | | const projectIndex = e.currentTarget.dataset.projectIndex; |
| | | const groupIndex = e.currentTarget.dataset.groupIndex; |
| | | const key = `projectList[${projectIndex}].groups[${groupIndex}].selected`; |
| | | const currentValue = this.data.projectList[projectIndex].groups[groupIndex].selected; |
| | | |
| | | this.setData({ |
| | | [key]: !currentValue |
| | | }); |
| | | |
| | | // 更新项目总时长 |
| | | this.updateProjectTotalDuration(projectIndex); |
| | | }, |
| | | |
| | | /** |
| | | * 处理时长输入 |
| | | */ |
| | | onDurationInput: function (e) { |
| | | const { |
| | | groupIndex |
| | | } = e.currentTarget.dataset; |
| | | const duration = parseInt(e.detail.value) || 0; |
| | | |
| | | const selectedProject = { |
| | | ...this.data.selectedProject |
| | | }; |
| | | selectedProject.groups[groupIndex].duration = duration; |
| | | |
| | | this.setData({ |
| | | selectedProject |
| | | }, () => { |
| | | // 输入时长后重新计算总时间 |
| | | this.calculateTotalDuration(); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 计算并更新项目总时长 |
| | | */ |
| | | updateProjectTotalDuration: function (projectIndex) { |
| | | const project = this.data.projectList[projectIndex]; |
| | | let totalDuration = 0; |
| | | |
| | | // 计算所有选中的轮灌组的时长总和 |
| | | project.groups.forEach(group => { |
| | | if (group.selected) { |
| | | totalDuration += parseInt(group.duration) || 0; |
| | | } |
| | | }); |
| | | |
| | | // 更新项目总时长 |
| | | const totalDurationKey = `projectList[${projectIndex}].totalDuration`; |
| | | this.setData({ |
| | | [totalDurationKey]: totalDuration |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 阻止事件冒泡 |
| | | */ |
| | | stopPropagation: function (e) { |
| | | if (e && e.stopPropagation) { |
| | | e.stopPropagation(); |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | /** |
| | | * 跳转到轮灌组详情页 |
| | | */ |
| | | navigateToGroupDetail: function (e) { |
| | | const { |
| | | groupIndex |
| | | } = e.currentTarget.dataset; |
| | | // TODO: 实现跳转逻辑 |
| | | }, |
| | | |
| | | /** |
| | | * 确认按钮点击事件 |
| | | */ |
| | | onConfirm: function () { |
| | | const { |
| | | planCode, |
| | | startTime, |
| | | selectedProject |
| | | } = this.data; |
| | | |
| | | if (!planCode) { |
| | | wx.showToast({ |
| | | title: '请输入计划编号', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!selectedProject) { |
| | | wx.showToast({ |
| | | title: '请选择项目', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 构建上报数据 |
| | | const schedules = selectedProject.groups.map(group => ({ |
| | | groupId: group.id, |
| | | duration: parseInt(group.duration) || 0 |
| | | })); |
| | | |
| | | const requestData = { |
| | | projectId: selectedProject.id, |
| | | planName: planCode, |
| | | startupMode: startTime ? 2 : 1, |
| | | operatorId: app.globalData.clientId, |
| | | schedules: schedules |
| | | }; |
| | | |
| | | // 如果有开始时间,添加到请求数据中 |
| | | if (startTime) { |
| | | requestData.planStartTime = startTime; |
| | | } |
| | | |
| | | // 发送请求 |
| | | post({ |
| | | url: '/wx/plan/createPlan', |
| | | data: requestData, |
| | | isShowLoding: true |
| | | }).then(res => { |
| | | if (res.success) { |
| | | wx.showToast({ |
| | | title: '创建成功', |
| | | icon: 'success' |
| | | }); |
| | | // 返回上一页,并传递参数指示需要刷新列表并切换到当前计划列表 |
| | | setTimeout(() => { |
| | | // 使用全局变量标记需要刷新 |
| | | const app = getApp(); |
| | | app.globalData.needRefreshIrrigationList = true; |
| | | |
| | | // 直接返回上一页 |
| | | wx.navigateBack({ |
| | | delta: 1 |
| | | }); |
| | | }, 1500); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '创建失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.error('创建计划失败:', err); |
| | | wx.showToast({ |
| | | title: '创建失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // 显示项目选择器 |
| | | showProjectPicker() { |
| | | this.fetchProjects(true) |
| | | |
| | | }, |
| | | |
| | | // 项目选择器确认 |
| | | onProjectPickerConfirm(e) { |
| | | const { |
| | | value |
| | | } = e.detail; |
| | | console.log('选择的项目ID:', value[0]); // 添加日志查看数据 |
| | | const selectedProject = this.data.projectList.find(project => project.id === value[0]); |
| | | console.log('找到的项目:', selectedProject); // 添加日志查看数据 |
| | | |
| | | this.setData({ |
| | | projectPickerVisible: false, |
| | | selectedProject: selectedProject, |
| | | projectPickerValue: value |
| | | }, () => { |
| | | // 选择项目后获取轮灌组列表 |
| | | if (selectedProject) { |
| | | this.fetchGroups(selectedProject.id); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 项目选择器取消 |
| | | onProjectPickerCancel() { |
| | | this.setData({ |
| | | projectPickerVisible: false |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 计算总灌溉时间 |
| | | */ |
| | | calculateTotalDuration: function () { |
| | | if (!this.data.selectedProject) return; |
| | | |
| | | const totalDuration = this.data.selectedProject.groups.reduce((sum, group) => { |
| | | return sum + (parseInt(group.duration) || 0); |
| | | }, 0); |
| | | |
| | | this.setData({ |
| | | totalDuration |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 轮灌组列表下拉刷新 |
| | | */ |
| | | onGroupListRefresh: function () { |
| | | if (!this.data.selectedProject) { |
| | | this.setData({ |
| | | isRefreshing: false |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | this.setData({ |
| | | isRefreshing: true |
| | | }); |
| | | |
| | | this.fetchGroups(this.data.selectedProject.id) |
| | | .then(() => { |
| | | this.setData({ |
| | | isRefreshing: false |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | this.setData({ |
| | | isRefreshing: false |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 显示时间提示弹窗 |
| | | */ |
| | | showTimeInfo: function () { |
| | | this.setData({ |
| | | timeInfoVisible: true |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 关闭时间提示弹窗 |
| | | */ |
| | | onTimeInfoConfirm: function () { |
| | | this.setData({ |
| | | timeInfoVisible: false |
| | | }); |
| | | }, |
| | | }); |
| | |
| | | <block wx:for="{{selectedProject.groups}}" wx:key="id" wx:for-item="group" wx:for-index="groupIndex"> |
| | | <view class="group-item {{group.selected ? 'selected' : ''}}" bindtap="navigateToGroupDetail" data-group-index="{{groupIndex}}"> |
| | | <view class="group-info"> |
| | | <view class="group-name">{{group.name || '未命名轮灌组'}} (共{{group.intakeCount}}个取水口)</view> |
| | | <text class="group-index">{{groupIndex + 1}}.</text> |
| | | <view class="group-name"> |
| | | <text class="group-name-text">{{group.name || '未命名轮灌组'}}</text> |
| | | <text class="group-intake-count">(共{{group.intakeCount}}个取水口)</text> |
| | | </view> |
| | | </view> |
| | | <view class="group-duration"> |
| | | <input |
| | |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .group-index { |
| | | color: #1890FF; |
| | | margin-right: 8rpx; |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | .group-name { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | position: relative; |
| | | padding-left: 10rpx; |
| | | background-color: rgba(24, 144, 255, 0.1); |
| | | padding: 4rpx 20rpx; |
| | | background-color: rgba(24, 144, 255, 0.1); |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .group-name-text { |
| | | color: #333; |
| | | margin-right: 8rpx; |
| | | } |
| | | |
| | | .group-intake-count { |
| | | color: #999; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | .group-hint { |
| | | font-size: 22rpx; |
| | | color: #1890FF; |
| | |
| | | |
| | | console.log('设置后的数据:', this.data); |
| | | |
| | | // 设置导航栏标题 |
| | | wx.setNavigationBarTitle({ |
| | | title: this.data.groupName || '轮灌组详情' |
| | | }); |
| | | |
| | | this.loadWaterOutletData(); |
| | | } |
| | | }, |
| | |
| | | }) |
| | | } |
| | | }, |
| | | calculateScrollViewHeight: function () { |
| | | wx.createSelectorQuery().selectAll('.list-item').boundingClientRect((rects) => { |
| | | let totalHeight = rects.reduce((sum, rect) => sum + rect.height, 0); |
| | | this.setData({ |
| | | scrollViewHeight: totalHeight, |
| | | }); |
| | | }).exec(); |
| | | }, |
| | | // calculateScrollViewHeight: function () { |
| | | // wx.createSelectorQuery().selectAll('.list-item').boundingClientRect((rects) => { |
| | | // let totalHeight = rects.reduce((sum, rect) => sum + rect.height, 0); |
| | | // this.setData({ |
| | | // scrollViewHeight: totalHeight, |
| | | // }); |
| | | // }).exec(); |
| | | // }, |
| | | startPullDownRefresh() { |
| | | if (getApp().globalData.isLoggedIn) { |
| | | if (!this.data.isWXRefreshing) { |
| | |
| | | }) |
| | | }, |
| | | openValveList() { |
| | | // wx.navigateTo({ |
| | | // url: '/pages/valveList/valveList', |
| | | // }) |
| | | wx.showToast({ |
| | | title: '暂未开放', |
| | | icon: 'none' |
| | | }) |
| | | const app = getApp(); |
| | | if (app.globalData.isLoggedIn) { |
| | | wx.navigateTo({ |
| | | url: '/pages/valveList/valveList', |
| | | }) |
| | | } else { |
| | | wx.showToast({ |
| | | title: '请先登录', |
| | | icon: 'error' |
| | | }) |
| | | } |
| | | }, |
| | | feedBack() { |
| | | wx.showToast({ |
| | |
| | | isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成 |
| | | isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成 |
| | | }); |
| | | this.updateDisplayText(); |
| | | |
| | | // 成功获取数据后刷新UI高度 |
| | | setTimeout(() => { |
| | | this.calculateScrollViewHeight(); |
| | | }, 200); |
| | | }).catch(err => { |
| | | console.error('获取列表数据失败:', err); |
| | | // 错误回调 |
| | |
| | | console.log('continueInitPage: 从页面数据中检测到isFromLogin=true'); |
| | | fromLogin = true; |
| | | } |
| | | |
| | | // 判断本地是否保存sessionId |
| | | // 使用 wx.nextTick 等待页面渲染完成 |
| | | wx.nextTick(() => { |
| | | this.calculateScrollViewHeight(); |
| | | }); |
| | | |
| | | // 当开阀成功后调用刷新 |
| | | if (options && options.param) { |
| | | console.log("开阀成功参数:", options.param); |
| | |
| | | showInfoDialog: false |
| | | }) |
| | | }, |
| | | //强制删除 |
| | | onDelete(e) { |
| | | const item = e.currentTarget.dataset.item; |
| | | const that = this; |
| | | |
| | | if (this.data.useTestData) { |
| | | // 测试数据模式下,模拟删除操作 |
| | | wx.showLoading({ |
| | | title: '正在强制删除请稍候...', |
| | | mask: true |
| | | }); |
| | | |
| | | // 模拟请求延迟 |
| | | setTimeout(() => { |
| | | wx.hideLoading(); |
| | | |
| | | // 从列表中移除被删除的项 |
| | | const updatedList = this.data.listData.filter(listItem => |
| | | listItem.orderNo !== item.orderNo |
| | | ); |
| | | |
| | | this.setData({ |
| | | listData: updatedList |
| | | }); |
| | | |
| | | wx.showToast({ |
| | | title: '删除成功', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }); |
| | | }, 1500); |
| | | return; |
| | | } |
| | | |
| | | wx.showLoading({ |
| | | title: '正在强制删除请稍候...', // 加载提示文字 |
| | | mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false |
| | | }); |
| | | const data = { |
| | | vcNum: item.vcNum, //取水口ID |
| | | rtuAddr: item.rtuAddr, //阀控器地址 |
| | | }; |
| | | post({ |
| | | url: "wx/valve/deleteUnclosed", |
| | | data: data, |
| | | timeout: 180000 |
| | | }).then(response => { |
| | | // 处理成功响应 |
| | | console.log('请求成功:', response); |
| | | // 加载完成后隐藏加载动画 |
| | | wx.hideLoading(); |
| | | //重新获取列表刷新数据 |
| | | this.getOpenList(); |
| | | }).catch(error => { |
| | | // 加载完成后隐藏加载动画 |
| | | wx.hideLoading(); |
| | | // 处理错误响应 |
| | | console.error('请求失败:', error); |
| | | }); |
| | | }, |
| | | //修改按钮文字 |
| | | updateDisplayText() { |
| | | const updatedList = this.data.listData.map(item => { |
| | | let displayText = ''; |
| | | if (item.planned) { |
| | | displayText = '取消'; |
| | | } else { |
| | | displayText = "关阀" |
| | | } |
| | | let deleteText = "删除" |
| | | let time; |
| | | if (!item.dt) { |
| | | time = "暂无" |
| | | } else { |
| | | time = this.extractTime(item.dt) |
| | | } |
| | | if (item.waterInstant===null) { |
| | | item.waterInstant = "暂无" |
| | | } |
| | | |
| | | return { |
| | | ...item, |
| | | displayText, |
| | | deleteText, |
| | | time |
| | | }; // 保留所有其他字段,并添加 displayText 字段 |
| | | }); |
| | | // 更新列表数据 |
| | | this.setData({ |
| | | listData: updatedList |
| | | }); |
| | | }, |
| | | //处理时间去掉年月日 |
| | | extractTime(datetimeString) { |
| | | const formattedDate = datetimeString.replace(" ", "T"); |
| | | const date = new Date(formattedDate); |
| | | // 获取小时、分钟和秒 |
| | | const hours = date.getHours().toString().padStart(2, '0'); |
| | | const minutes = date.getMinutes().toString().padStart(2, '0'); |
| | | const seconds = date.getSeconds().toString().padStart(2, '0'); |
| | | return `${hours}:${minutes}:${seconds}`; |
| | | }, |
| | | |
| | | }) |
| | |
| | | "component": true, |
| | | "usingComponents": { |
| | | "t-avatar": "tdesign-miniprogram/avatar/avatar", |
| | | "t-switch": "tdesign-miniprogram/switch/switch", |
| | | "t-swipe-cell": "tdesign-miniprogram/swipe-cell/swipe-cell", |
| | | "t-dialog": "tdesign-miniprogram/dialog/dialog" |
| | | }, |
| | | "navigationBarTitleText": "大禹节水", |
| | |
| | | </view> |
| | | <text class="refresh-button" bind:tap="startPullDownRefresh">刷新</text> |
| | | </view> |
| | | <view class="divider"></view> |
| | | <!-- refresher-enabled="true" refresher-threshold="50" --> |
| | | <scroll-view class="scroll-view" scroll-x="false" scroll-y="true" refresher-enabled="{{isRefreshing==false?true:false}}" refresher-threshold="50" bindrefresherrefresh="onPullDownRefresh" refresher-triggered="{{isWXRefreshing}}"> |
| | | <view wx:if="{{isRefreshing}}" class="refresh-view"> |
| | |
| | | <view class="dot"></view> |
| | | </view> |
| | | <view class="scroll-bg"> |
| | | <view wx:if="{{listData.length > 0}}" class="list-item" wx:for="{{listData}}" wx:key="index"> |
| | | <view class="item-left"> |
| | | <!-- <image class="item-img" src="/images/pipeline.svg" /> --> |
| | | <text>{{item.intakeNum}}</text> |
| | | <image class="item-img" src="{{item.isOnLine ? '/images/wifi_no.svg' : '/images/wifi_off.svg'}}" /> |
| | | </view> |
| | | <view> |
| | | <!-- <t-switch class="switch" data-item="{{item}}" bindchange="handleChange" value="{{true}}" label="{{['开', '关']}}" slot="note" /> --> |
| | | <text class="item-button" bind:tap="handleChange" data-item="{{item}}">关阀</text> |
| | | </view> |
| | | <view wx:if="{{listData.length > 0}}" wx:for="{{listData}}" wx:key="index"> |
| | | <t-swipe-cell> |
| | | <view class="swipe-cell"> |
| | | <view class="list-item"> |
| | | <view class="item-left"> |
| | | <view class="left-intake-name"> |
| | | <image class="item-img-left" src="/images/valve.svg" /> |
| | | <text class="water-intake-name">{{item.intakeNum}}</text> |
| | | <image class="item-img" src="{{item.isOnLine ? '/images/wifi_no.svg' : '/images/wifi_off.svg'}}" /> |
| | | </view> |
| | | <view class="left-time"> |
| | | <image class="item-img" src="/images/time.svg" /> |
| | | <text class="flow-time">{{item.time}}</text> |
| | | <text class="flow-rate">瞬时流量:{{item.waterInstant}} m³/h</text> |
| | | </view> |
| | | </view> |
| | | <view class="item-right"> |
| | | <text class="item-button" bind:tap="handleChange" data-item="{{item}}">关阀</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view slot="right" class="delete-btn" bind:tap="onDelete" data-item="{{item}}">{{item.deleteText}}</view> |
| | | </t-swipe-cell> |
| | | </view> |
| | | </view> |
| | | <view wx:if="{{listData.length === 0}}" class="noMore-View-home"> |
| | |
| | | <radio value="SCHOOL" checked="{{selectedProject === 'SCHOOL'}}" color="#1890FF" /> |
| | | <text>学校项目</text> |
| | | </label> |
| | | <label class="project-radio {{selectedProject === 'JC' ? 'project-radio-selected' : ''}}"> |
| | | <radio value="JC" checked="{{selectedProject === 'JC'}}" color="#1890FF" /> |
| | | <text>金昌项目</text> |
| | | </label> |
| | | <label class="project-radio {{selectedProject === 'GSCLT' ? 'project-radio-selected' : ''}}"> |
| | | <radio value="GSCLT" checked="{{selectedProject === 'GSCLT'}}" color="#1890FF" /> |
| | | <text>甘肃农科院-崔</text> |
| | | </label> |
| | | </radio-group> |
| | | </view> |
| | | <view class="project-modal-footer"> |
| | |
| | | <scroll-view slot="content" type="list" scroll-y class="long-content"> |
| | | <view class="content-container"> |
| | | <text class="content-container"> |
| | | 1.网络等不可抗力因素可能导致设备状态显示延迟或错误。 |
| | | 1.网络等不可抗力因素可能导致设备状态显示延迟或错误。(当进行了开阀或关阀操作后会有一定延时才可确认是否操作成功) |
| | | 2.当提示您操作失败后您可稍后尝试重新操作。 |
| | | 3.在定时或定量开阀的预约式开阀后,只有阀门到达约定的时间成功开阀后未关阀记录才会显示。 |
| | | 4.我们诚挚地邀请您通过意见反馈渠道提出宝贵的建议或意见。 |
| | |
| | | /* 允许垂直滚动 */ |
| | | z-index: 0; |
| | | /* 确保 scroll-view 在头部和 center-wrapper 之下 */ |
| | | background-color: #f5f5f5; |
| | | margin-top: 0; |
| | | padding-top: 0; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .scroll-bg { |
| | | padding: 20rpx 0; |
| | | box-sizing: border-box; |
| | | padding-top: 0; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 确保所有含宽度的元素使用相同的计算方式 */ |
| | | .bottom-title, |
| | | .scroll-bg > view { |
| | | width: calc(100% - 40rpx); |
| | | margin-left: 20rpx; |
| | | margin-right: 20rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .scroll-bg > view { |
| | | margin-bottom: 20rpx; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | t-swipe-cell { |
| | | display: block; |
| | | width: 100%; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .swipe-cell { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | background-color: #fff; |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .list-item { |
| | | background-color: #fff; |
| | | margin-bottom: 2rpx; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding-left: 30rpx; |
| | | padding-right: 30rpx; |
| | | padding-top: 30rpx; |
| | | padding-bottom: 30rpx; |
| | | padding: 30rpx; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | flex: 1; |
| | | width: 100%; |
| | | } |
| | | |
| | | .left-intake-name { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | padding-left: 4rpx; |
| | | } |
| | | |
| | | .item-img-left { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .item-img { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .left-intake-name .item-img { |
| | | margin-left: 8rpx; |
| | | } |
| | | |
| | | .water-intake-name { |
| | | font-size: 42rpx !important; |
| | | margin-left: 16rpx; |
| | | margin-right: 15rpx; |
| | | white-space: nowrap; /* 防止文本换行 */ |
| | | font-weight: 500; |
| | | color: #333; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .left-time { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #666; |
| | | flex-wrap: nowrap; |
| | | overflow: hidden; |
| | | padding-right: 10rpx; |
| | | padding-left: 4rpx; |
| | | } |
| | | |
| | | .flow-time { |
| | | font-size: 28rpx !important; |
| | | margin-left: 16rpx; |
| | | margin-right: 2rpx; |
| | | white-space: nowrap; |
| | | color: #666; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .flow-rate { |
| | | font-size: 28rpx !important; |
| | | margin-left: 6rpx; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | flex: 1; |
| | | color: #666; |
| | | } |
| | | |
| | | .item-right { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-left: 20rpx; |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | .item-button { |
| | | display: flex; |
| | | height: 70rpx; |
| | | padding: 0 40rpx; |
| | | background-color: #1890FF; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 35rpx; |
| | | font-size: 30rpx !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | white-space: nowrap; /* 确保文字不换行 */ |
| | | box-shadow: 0 4rpx 8rpx rgba(24, 144, 255, 0.2); |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .item-button:active { |
| | | background-color: #1378d8; |
| | | transform: scale(0.98); |
| | | } |
| | | |
| | | .delete-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 140rpx; |
| | | height: 100%; |
| | | color: white; |
| | | background-color: #e34d59; |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | .list-item text { |
| | |
| | | } |
| | | |
| | | .bottom-title { |
| | | border-radius: 5px 5px 0 0; |
| | | border-radius: 12rpx 12rpx 0 0; |
| | | background-color: #fff; |
| | | display: flex; |
| | | align-items: center; |
| | | /* 垂直方向居中 */ |
| | | justify-content: space-between; |
| | | /* 子元素在主轴上的对齐方式 */ |
| | | padding: 10px; |
| | | padding: 30rpx; |
| | | /* 容器的内边距 */ |
| | | width: calc(100% - 40rpx); |
| | | margin-left: 20rpx; |
| | | margin-right: 20rpx; |
| | | margin-top: 20rpx; |
| | | margin-bottom: 0; |
| | | box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.03); |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | border-bottom: 1rpx solid #e7e7e7; |
| | | } |
| | | |
| | | .bottom-title-text { |
| | | margin-right: 10rpx; |
| | | /* 给文本和图标之间添加一些间距 */ |
| | | font-size: 35rpx; |
| | | font-size: 34rpx; |
| | | /* 字体大小 */ |
| | | color: #333; |
| | | /* 字体颜色 */ |
| | | } |
| | | |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .refresh-button { |
| | | margin-left: auto; |
| | | /* 将按钮推到容器的最右侧 */ |
| | | font-size: 30rpx; |
| | | font-size: 28rpx; |
| | | /* 按钮文字的字体大小 */ |
| | | color: #fff; |
| | | /* 按钮文字颜色 */ |
| | |
| | | /* 按钮背景颜色 */ |
| | | border: none; |
| | | /* 去掉按钮边框 */ |
| | | border-radius: 5px; |
| | | border-radius: 30rpx; |
| | | /* 按钮圆角 */ |
| | | padding-left: 25rpx; |
| | | padding-right: 25rpx; |
| | | padding-top: 15rpx; |
| | | padding: 15rpx 30rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding-bottom: 15rpx; |
| | | box-shadow: 0 4rpx 8rpx rgba(24, 144, 255, 0.2); |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .refresh-button:active { |
| | | background-color: #7c7c7c; |
| | | /* Change to a darker color when pressed */ |
| | | background-color: #1378d8; |
| | | transform: scale(0.98); |
| | | } |
| | | |
| | | .refresh-view { |
| | | text-align: center; |
| | | padding: 30rpx; |
| | | padding: 40rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .dot { |
| | | width: 20rpx; |
| | | height: 20rpx; |
| | | background-color: #333; |
| | | width: 16rpx; |
| | | height: 16rpx; |
| | | background-color: #1890FF; |
| | | border-radius: 50%; |
| | | margin: 0 5px; |
| | | margin: 0 8rpx; |
| | | animation: blink 1.4s infinite both; |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .dot:nth-child(2) { |
| | |
| | | } |
| | | |
| | | @keyframes blink { |
| | | |
| | | 0%, |
| | | 80%, |
| | | 100% { |
| | | opacity: 0; |
| | | 0% { |
| | | opacity: 0.2; |
| | | transform: scale(0.8); |
| | | } |
| | | |
| | | 40% { |
| | | 50% { |
| | | opacity: 1; |
| | | transform: scale(1.2); |
| | | } |
| | | 100% { |
| | | opacity: 0.2; |
| | | transform: scale(0.8); |
| | | } |
| | | } |
| | | |
| | |
| | | --td-switch-checked-color: #1890FF; |
| | | } |
| | | |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .item-left text { |
| | | font-size: 40rpx; |
| | | /* 修改选择器,使其不会影响flow-time */ |
| | | .item-left .water-intake-name { |
| | | min-width: 150rpx; |
| | | } |
| | | |
| | | .item-img { |
| | | width: 40rpx; |
| | | /* 根据需要调整图标大小 */ |
| | | height: 40rpx; |
| | | /* 根据需要调整图标大小 */ |
| | | margin-left: 20rpx; |
| | | } |
| | | |
| | | .dialog { |
| | |
| | | .noMore-View-home { |
| | | display: flex; |
| | | flex-direction: column; |
| | | /* 确保子元素纵向排列 */ |
| | | justify-content: center; |
| | | /* 垂直居中 */ |
| | | align-items: center; |
| | | /* 水平居中 */ |
| | | height: 100%; |
| | | /* 让容器高度占满父元素 */ |
| | | } |
| | | |
| | | .item-button { |
| | | display: flex; |
| | | height: 80rpx; |
| | | padding: 0 60rpx; |
| | | background-color: #1890FF; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 20rpx; |
| | | font-size: 30rpx; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-top: 80rpx; |
| | | padding: 40rpx; |
| | | } |
| | | |
| | | .item-button:active { |
| | | background-color: #7c7c7c; |
| | | /* Change to a darker color when pressed */ |
| | | .noMore-img { |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | margin-bottom: 20rpx; |
| | | opacity: 0.7; |
| | | } |
| | | |
| | | .divider { |
| | | width: 100%; |
| | | margin-top: 2rpx; |
| | | /* background-color: #e0e0e0; */ |
| | | .noMore-text { |
| | | font-size: 32rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | |
| | | .error-dialog { |
| | | --td-dialog-title-color: red; |
| | |
| | | } |
| | | |
| | | .long-content { |
| | | height: 450rpx; |
| | | height: 500rpx; |
| | | margin-top: 16rpx; |
| | | font-size: 32rpx; |
| | | color: #888; |
| | |
| | | /** |
| | | * 生命周期函数--监听页面显示 |
| | | */ |
| | | // onShow: function () { |
| | | // // 设置页面为加载中状态 |
| | | // wx.showLoading({ |
| | | // title: '加载中', |
| | | // mask: true |
| | | // }); |
| | | onShow: function () { |
| | | // 检查全局变量,判断是否需要刷新列表并切换到当前计划 |
| | | const app = getApp(); |
| | | |
| | | // // 先加载当前页面所需的数据 |
| | | // const currentTab = this.data.currentTab; |
| | | // if (currentTab === 0) { |
| | | // // 当前标签是"当前灌溉计划",加载这个 |
| | | // this.loadIrrigationData() |
| | | // .then(() => { |
| | | // wx.hideLoading(); |
| | | // }) |
| | | // .catch(() => { |
| | | // wx.hideLoading(); |
| | | // }); |
| | | // } else { |
| | | // // 当前标签是"历史计划" |
| | | // // 只加载第一页数据,保留分页状态 |
| | | // if (this.data.completedList.length === 0) { |
| | | // // 如果历史列表为空,重置分页状态 |
| | | // this.setData({ |
| | | // pageCurr: 1, |
| | | // hasMoreData: true |
| | | // }); |
| | | // } |
| | | // 刷新所有数据(当前计划和历史计划),确保数据最新 |
| | | wx.showLoading({ |
| | | title: '刷新数据中', |
| | | mask: true |
| | | }); |
| | | |
| | | // 同时获取当前计划和历史计划数据 |
| | | Promise.all([ |
| | | this.loadIrrigationData(), |
| | | this.loadCompletedIrrigationData(true) // 传入true表示是重新加载第一页 |
| | | ]).then(() => { |
| | | wx.hideLoading(); |
| | | |
| | | // this.loadCompletedIrrigationData() |
| | | // .then(() => { |
| | | // wx.hideLoading(); |
| | | // }) |
| | | // .catch(() => { |
| | | // wx.hideLoading(); |
| | | // }); |
| | | // } |
| | | // }, |
| | | // 如果需要刷新并切换到当前计划 |
| | | if (app.globalData.needRefreshIrrigationList) { |
| | | // 重置全局变量 |
| | | app.globalData.needRefreshIrrigationList = false; |
| | | |
| | | console.log('检测到需要刷新灌溉计划列表'); |
| | | |
| | | // 切换到当前灌溉计划标签页 |
| | | if (this.data.currentTab !== 0) { |
| | | this.setData({ |
| | | currentTab: 0, |
| | | currentList: this.data.activeList |
| | | }); |
| | | } |
| | | } |
| | | }).catch(() => { |
| | | wx.hideLoading(); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 加载轮灌数据 |
| | |
| | | /** |
| | | * 加载已完成的轮灌数据 |
| | | */ |
| | | loadCompletedIrrigationData: function () { |
| | | loadCompletedIrrigationData: function (isFirstPage) { |
| | | // 如果正在加载或没有更多数据,则不再请求 |
| | | if (this.data.loadingMore && !this.data.hasMoreData) { |
| | | return Promise.resolve(); |
| | | } |
| | | |
| | | // 如果是重新加载第一页,重置页码和状态 |
| | | if (isFirstPage) { |
| | | this.setData({ |
| | | pageCurr: 1, |
| | | hasMoreData: true |
| | | }); |
| | | } |
| | | |
| | | // 设置加载状态 |
| | |
| | | |
| | | // 导航到灌溉详情页面,并传递参数 |
| | | wx.navigateTo({ |
| | | url: `/pages/irrigationDetail/irrigationDetail?planId=${id}&fromList=true` |
| | | url: `/pages/irrigationDetail/irrigationDetail?planId=${id}&fromList=true&status=${status}` |
| | | }); |
| | | }, |
| | | |
| | |
| | | } |
| | | }).catch(err => { |
| | | console.error('发布失败:', err); |
| | | wx.showToast({ |
| | | title: '发布失败', |
| | | icon: 'none' |
| | | }); |
| | | if(err.code==='1003'){ |
| | | wx.showToast({ |
| | | title: err.msg || '发布失败', |
| | | icon: 'none' |
| | | }); |
| | | }else{ |
| | | wx.showToast({ |
| | | title: '发布失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | |
| | | title: '终止成功', |
| | | icon: 'success' |
| | | }); |
| | | // 刷新数据 |
| | | this.loadIrrigationData(); |
| | | // 同时刷新当前计划列表和历史计划列表 |
| | | Promise.all([ |
| | | this.loadIrrigationData(), |
| | | this.loadCompletedIrrigationData(true) // 传入true表示重新加载第一页 |
| | | ]).catch(err => { |
| | | console.error('刷新数据失败:', err); |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '终止失败', |
| | |
| | | console.error('加载更多历史数据失败:', err); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 从创建灌溉计划页面返回时,切换到当前计划列表并刷新数据 |
| | | */ |
| | | switchToCurrentPlans: function() { |
| | | console.log('从创建页面返回,切换到当前计划列表并刷新'); |
| | | |
| | | // 如果当前不在 "当前灌溉计划" 标签页,先切换到该标签页 |
| | | if (this.data.currentTab !== 0) { |
| | | this.setData({ |
| | | currentTab: 0, |
| | | currentList: this.data.activeList |
| | | }); |
| | | } |
| | | |
| | | // 显示加载提示 |
| | | wx.showLoading({ |
| | | title: '刷新数据中', |
| | | mask: true |
| | | }); |
| | | |
| | | // 刷新当前灌溉计划数据 |
| | | this.loadIrrigationData() |
| | | .then(() => { |
| | | wx.hideLoading(); |
| | | }) |
| | | .catch(() => { |
| | | wx.hideLoading(); |
| | | }); |
| | | } |
| | | }) |
| | |
| | | </view> |
| | | |
| | | <!-- 操作按钮区域 --> |
| | | <view class="action-section" catchtap="stopPropagation" wx:if="{{item.status !== '4'}}"> |
| | | <view class="action-section" catchtap="stopPropagation" wx:if="{{item.status === '1'||item.status === '2'||item.status === '3'}}"> |
| | | <block wx:if="{{item.status === '1'}}"> |
| | | <view class="action-buttons"> |
| | | <button class="action-button delete-button" hover-class="delete-button-hover" bindtap="onDelete" data-id="{{item.id}}"> |
| | |
| | | planId: '', |
| | | planStatusText: '', |
| | | planStatusClass: '', |
| | | failureCount: 0 |
| | | failureCount: 0, |
| | | realStopTime: '', |
| | | originalStatus: '', |
| | | currentStatus: null |
| | | }, |
| | | |
| | | /** |
| | |
| | | this.setData({ |
| | | planId: options.planId |
| | | }); |
| | | this.fetchIrrigationData(options.planId); |
| | | |
| | | // 获取最新状态 |
| | | this.fetchPlanLatestState(options.planId).then(res => { |
| | | if (res.success) { |
| | | const currentStatus = res.content; |
| | | this.setData({ |
| | | currentStatus: currentStatus, |
| | | originalStatus: currentStatus |
| | | }); |
| | | |
| | | // 根据最新状态调用相应的接口 |
| | | if (currentStatus === 5) { |
| | | this.fetchTerminatedIrrigationData(options.planId); |
| | | } else { |
| | | this.fetchNormalIrrigationData(options.planId); |
| | | } |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取状态失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取状态失败:', err); |
| | | wx.showToast({ |
| | | title: '获取状态失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: '缺少计划ID', |
| | |
| | | }, |
| | | |
| | | /** |
| | | * 获取灌溉计划数据 |
| | | * 获取常规灌溉计划详细数据 |
| | | */ |
| | | fetchIrrigationData: function(planId) { |
| | | fetchNormalIrrigationData: function(planId) { |
| | | const { get } = require('../../api/request'); |
| | | |
| | | const data = { |
| | |
| | | }, |
| | | |
| | | /** |
| | | * 获取已终止灌溉计划详细数据 |
| | | */ |
| | | fetchTerminatedIrrigationData: function(planId) { |
| | | const { get } = require('../../api/request'); |
| | | |
| | | const data = { |
| | | planId: planId || this.data.planId, |
| | | }; |
| | | |
| | | get({ |
| | | url: 'wx/plan/getTerminateResults', |
| | | isShowLoding: true, |
| | | useParams: true, |
| | | data: data |
| | | }).then(res => { |
| | | if (res.success) { |
| | | this.processIrrigationData(res.content); |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取数据失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.error('请求失败:', err); |
| | | wx.showToast({ |
| | | title: '请求失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取计划最新状态 |
| | | */ |
| | | fetchPlanLatestState: function(planId) { |
| | | const { get } = require('../../api/request'); |
| | | |
| | | const data = { |
| | | planId: planId || this.data.planId, |
| | | }; |
| | | |
| | | return get({ |
| | | url: 'wx/plan/getPlanLatestState', |
| | | isShowLoding: true, |
| | | useParams: true, |
| | | data: data |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 处理接口返回的数据 |
| | | */ |
| | | processIrrigationData: function(data) { |
| | |
| | | const statusMap = { |
| | | 2: {status: 'pending', statusText: '未开始'}, |
| | | 3: {status: 'in_progress', statusText: '灌溉中'}, |
| | | 4: {status: 'completed', statusText: '已结束'} |
| | | 4: {status: 'completed', statusText: '已结束'}, |
| | | 5: {status: 'terminated', statusText: '中途关阀'}, |
| | | 6: {status: 'canceled', statusText: '取消开阀'} |
| | | }; |
| | | |
| | | // 处理计划状态 |
| | |
| | | projectName: data.projectName, |
| | | startTime: data.planStartTime, |
| | | stopTime: data.planStopTime, |
| | | realStopTime: data.realStopTime || '', |
| | | groupList: groupList, |
| | | planStatusText: planStatusText, |
| | | planStatusClass: planStatusClass, |
| | |
| | | this.setData({ |
| | | isRefreshing: true |
| | | }); |
| | | |
| | | this.fetchIrrigationData(this.data.planId); |
| | | |
| | | // 完成刷新 |
| | | setTimeout(() => { |
| | | // 获取最新状态并刷新数据 |
| | | this.fetchPlanLatestState(this.data.planId).then(res => { |
| | | if (res.success) { |
| | | const currentStatus = res.content; |
| | | this.setData({ |
| | | currentStatus: currentStatus |
| | | }); |
| | | |
| | | if (currentStatus === 5) { |
| | | this.fetchTerminatedIrrigationData(this.data.planId); |
| | | } else { |
| | | this.fetchNormalIrrigationData(this.data.planId); |
| | | } |
| | | } else { |
| | | wx.showToast({ |
| | | title: res.msg || '获取状态失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | |
| | | // 完成刷新 |
| | | this.setData({ |
| | | isRefreshing: false |
| | | }); |
| | | }, 1000); |
| | | }).catch(err => { |
| | | console.error('获取状态失败:', err); |
| | | wx.showToast({ |
| | | title: '获取状态失败', |
| | | icon: 'none' |
| | | }); |
| | | this.setData({ |
| | | isRefreshing: false |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | |
| | | <text class="value">{{stopTime}}</text> |
| | | </view> |
| | | |
| | | <!-- 实际中止时间信息 --> |
| | | <view class="time-info" wx:if="{{planStatusClass === 'terminated' && realStopTime}}"> |
| | | <text class="label">实际中止时间:</text> |
| | | <text class="value highlight-text">{{realStopTime}}</text> |
| | | </view> |
| | | |
| | | <!-- 取水口命令发布失败数 --> |
| | | <view class="time-info" wx:if="{{failureCount > 0}}"> |
| | | <text class="label">命令发布失败数:</text> |
| | |
| | | <!-- 轮灌组信息 --> |
| | | <view class="group-info"> |
| | | <view class="group-name-row"> |
| | | <text class="group-index">{{index + 1}}.</text> |
| | | <text class="group-label">轮灌组:</text> |
| | | <text class="group-name">{{group.name}}</text> |
| | | <!-- 轮灌组状态标识 --> |
| | |
| | | <text class="status-text">{{group.statusText}}</text> |
| | | </view> |
| | | </view> |
| | | <view class="group-time-info"> |
| | | <!-- 轮灌时间信息 - 只有在取消开阀状态时不显示时间信息 --> |
| | | <!-- 其他所有状态(包括中途关阀)都显示时间信息 --> |
| | | <view class="group-time-info" wx:if="{{group.status !== 'canceled'}}"> |
| | | <view class="time-row"> |
| | | <text class="time-label">开始时间:</text> |
| | | <text class="time-value">{{group.startTime}}</text> |
| | |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* 实际中止时间高亮样式 */ |
| | | .time-info .highlight-text { |
| | | color: #F44336; |
| | | font-weight: bold; |
| | | background-color: rgba(244, 67, 54, 0.1); |
| | | padding: 4rpx 12rpx; |
| | | border-radius: 4rpx; |
| | | } |
| | | |
| | | /* 命令发布失败数样式 */ |
| | | .time-info .error-text { |
| | | color: #ff4d4f; |
| | |
| | | background-color: #2196F3; |
| | | } |
| | | |
| | | .group-item.terminated .status-dot { |
| | | background-color: #F44336; |
| | | } |
| | | |
| | | .group-item.canceled .status-dot { |
| | | background-color: #9E9E9E; |
| | | } |
| | | |
| | | .status-text { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | |
| | | color: #2196F3; |
| | | } |
| | | |
| | | .group-item.terminated .status-text { |
| | | color: #F44336; |
| | | } |
| | | |
| | | .group-item.canceled .status-text { |
| | | color: #9E9E9E; |
| | | } |
| | | |
| | | /* 根据不同状态显示不同背景色 */ |
| | | .group-item.pending .group-status-indicator { |
| | | background-color: rgba(255, 215, 0, 0.1); |
| | |
| | | background-color: rgba(33, 150, 243, 0.1); |
| | | } |
| | | |
| | | .group-item.terminated .group-status-indicator { |
| | | background-color: rgba(244, 67, 54, 0.1); |
| | | } |
| | | |
| | | .group-item.canceled .group-status-indicator { |
| | | background-color: rgba(158, 158, 158, 0.1); |
| | | } |
| | | |
| | | /* 轮灌组信息样式 */ |
| | | .group-info { |
| | | margin-top: 12rpx; |
| | |
| | | align-items: center; |
| | | margin-bottom: 12rpx; |
| | | width: 100%; |
| | | } |
| | | |
| | | .group-index { |
| | | color: #1890FF; |
| | | margin-right: 8rpx; |
| | | font-size: 32rpx; |
| | | } |
| | | |
| | | .group-label { |
| | |
| | | .time-label { |
| | | color: #666; |
| | | font-size: 26rpx; |
| | | width: 160rpx; |
| | | width: 140rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .time-value { |
| | |
| | | // pages/valveList/valveList.js 开关阀记录 |
| | | const { |
| | | get, |
| | | post |
| | | } = require('../../api/request.js'); |
| | | |
| | | Page({ |
| | | |
| | | /** |
| | | * 页面的初始数据 |
| | | */ |
| | | data: { |
| | | listData: [{ |
| | | intakeNum: "1023356646612" |
| | | }, { |
| | | intakeNum: "1023356646612" |
| | | }, { |
| | | intakeNum: "1023356646612" |
| | | }, { |
| | | intakeNum: "1023356646612" |
| | | }, { |
| | | intakeNum: "1023356646612" |
| | | }] |
| | | listVirtualData: [], |
| | | listPhysicalData: [], |
| | | currentTab: 0, |
| | | isVirtualRefreshing: false, //虚拟卡刷新中 |
| | | isPhysicalRefreshing: false, //实体卡刷新中 |
| | | physicalPageCurr: 1, //实体卡当前页数 |
| | | pageSize: 20, |
| | | virtualPageCurr: 1, //虚拟卡当前页数 |
| | | virtualhasMore: true, |
| | | physicalHasMore: true, |
| | | virtualIsLoding: false, |
| | | physicalIsLoding: false, |
| | | useTestData: false, // 添加测试数据标志 |
| | | }, |
| | | |
| | | /** |
| | |
| | | * 生命周期函数--监听页面初次渲染完成 |
| | | */ |
| | | onReady() { |
| | | |
| | | this.getPhysicalListData(); |
| | | this.getVirtualListData(); |
| | | }, |
| | | |
| | | /** |
| | |
| | | */ |
| | | onShareAppMessage() { |
| | | |
| | | }, |
| | | switchTab(e) { |
| | | const tab = parseInt(e.currentTarget.dataset.tab); |
| | | this.setData({ |
| | | currentTab: tab |
| | | }); |
| | | }, |
| | | //虚拟卡刷新 |
| | | onPullVirtualDownRefresh() { |
| | | this.setData({ |
| | | isVirtualRefreshing: true, |
| | | }) |
| | | this.getVirtualListData(true); |
| | | }, |
| | | //实体卡刷新 |
| | | onPullPhysicalDownRefresh() { |
| | | this.setData({ |
| | | isPhysicalRefreshing: true, |
| | | }) |
| | | this.getPhysicalListData(true); |
| | | }, |
| | | // 生成虚拟卡测试数据 |
| | | generateVirtualTestData() { |
| | | return Array(10).fill().map((_, index) => ({ |
| | | expense: (Math.random() * 100).toFixed(2), |
| | | cardNum: `VC${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, |
| | | intakeNum: `IN${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`, |
| | | openType: ['手动开阀', '自动开阀', '计划开阀'][Math.floor(Math.random() * 3)], |
| | | openTime: this.generateRandomTime(), |
| | | closeTime: this.generateRandomTime(), |
| | | duration: Math.floor(Math.random() * 120), |
| | | amount: (Math.random() * 50).toFixed(2) |
| | | })); |
| | | }, |
| | | |
| | | // 生成实体卡测试数据 |
| | | generatePhysicalTestData() { |
| | | return Array(10).fill().map((_, index) => ({ |
| | | expense: (Math.random() * 100).toFixed(2), |
| | | cardNum: `PC${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, |
| | | intakeNum: `IN${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`, |
| | | openType: ['手动开阀', '自动开阀', '计划开阀'][Math.floor(Math.random() * 3)], |
| | | openTime: this.generateRandomTime(), |
| | | closeTime: this.generateRandomTime(), |
| | | duration: Math.floor(Math.random() * 120), |
| | | amount: (Math.random() * 50).toFixed(2) |
| | | })); |
| | | }, |
| | | |
| | | // 生成随机时间 |
| | | generateRandomTime() { |
| | | const now = new Date(); |
| | | const randomHours = Math.floor(Math.random() * 24); |
| | | const randomMinutes = Math.floor(Math.random() * 60); |
| | | const randomSeconds = Math.floor(Math.random() * 60); |
| | | |
| | | const date = new Date(now); |
| | | date.setHours(randomHours); |
| | | date.setMinutes(randomMinutes); |
| | | date.setSeconds(randomSeconds); |
| | | |
| | | return date.toLocaleString(); |
| | | }, |
| | | |
| | | //获取实体卡列表 |
| | | getPhysicalListData(isRefresh) { |
| | | if (this.data.useTestData) { |
| | | // 使用测试数据 |
| | | const testData = this.generatePhysicalTestData(); |
| | | this.setData({ |
| | | listPhysicalData: isRefresh ? testData : this.data.listPhysicalData.concat(testData), |
| | | isPhysicalRefreshing: false, |
| | | physicalIsLoding: false, |
| | | physicalHasMore: this.data.physicalPageCurr < 3 // 模拟3页数据 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | get({ |
| | | url: 'wx/intake/getCardOpenClose', |
| | | data: { |
| | | clientId: getApp().globalData.clientId, |
| | | pageCurr: this.data.physicalPageCurr, |
| | | pageSize: this.data.pageSize |
| | | } |
| | | }) |
| | | .then((data) => { |
| | | this.setData({ |
| | | isPhysicalRefreshing: false, |
| | | physicalIsLoding: false |
| | | }); |
| | | if (data.success && data.code === "0001") { |
| | | const filteredData = data.content.obj.filter(item => item.openTime !== null && item.closeTime !== null); |
| | | this.setData({ |
| | | listPhysicalData: isRefresh ? filteredData : this.data.listPhysicalData.concat(filteredData), |
| | | physicalHasMore: this.data.physicalPageCurr < data.content.pageTotal, |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: data.msg, |
| | | }) |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | this.setData({ |
| | | isPhysicalRefreshing: false |
| | | }); |
| | | console.error('Failed to add item:', error); |
| | | }); |
| | | }, |
| | | |
| | | //获取虚拟卡开关阀记录 |
| | | getVirtualListData(isRefresh) { |
| | | if (this.data.useTestData) { |
| | | // 使用测试数据 |
| | | const testData = this.generateVirtualTestData(); |
| | | this.setData({ |
| | | listVirtualData: isRefresh ? testData : this.data.listVirtualData.concat(testData), |
| | | isVirtualRefreshing: false, |
| | | virtualIsLoding: false, |
| | | virtualhasMore: this.data.virtualPageCurr < 3 // 模拟3页数据 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | get({ |
| | | url: 'wx/intake/getVcCardOpenClose', |
| | | data: { |
| | | clientId: getApp().globalData.clientId, |
| | | pageCurr: this.data.physicalPageCurr, |
| | | pageSize: this.data.pageSize |
| | | } |
| | | }) |
| | | .then((data) => { |
| | | this.setData({ |
| | | isVirtualRefreshing: false, |
| | | virtualIsLoding: false |
| | | }); |
| | | if (data.success && data.code === "0001") { |
| | | const filteredData = data.content.obj.filter(item => item.openTime !== null && item.closeTime !== null); |
| | | this.setData({ |
| | | listVirtualData: isRefresh ? filteredData : this.data.listVirtualData.concat(filteredData), |
| | | virtualhasMore: this.data.virtualPageCurr < data.content.pageTotal, |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: data.msg, |
| | | }) |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | this.setData({ |
| | | isVirtualRefreshing: false |
| | | }); |
| | | console.error('Failed to add item:', error); |
| | | }); |
| | | }, |
| | | //加载更多的实体卡 |
| | | loadPhysicalMore() { |
| | | if (this.data.physicalHasMore) { |
| | | this.setData({ |
| | | physicalIsLoding: true, |
| | | physicalPageCurr: this.data.physicalPageCurr + 1 |
| | | }) |
| | | this.getPhysicalListData(); |
| | | } |
| | | }, |
| | | //加载更多的虚拟卡 |
| | | loadVirtualMore() { |
| | | if (this.data.virtualhasMore) { |
| | | this.setData({ |
| | | virtualIsLoding: true, |
| | | virtualPageCurr: this.data.virtualPageCurr + 1 |
| | | }) |
| | | this.getVirtualListData(); |
| | | } |
| | | |
| | | } |
| | | |
| | | }) |
| | |
| | | <!--pages/valveList/valveList.wxml 开关阀记录--> |
| | | <view> |
| | | <scroll-view class="list-container" scroll-y="true" scroll-x="false"> |
| | | <block wx:if="{{listData.length > 0}}" wx:for="{{listData}}" wx:key="index"> |
| | | <view class="list-item" wx:for="{{listData}}" wx:for-item="item" wx:for-index="index"> |
| | | <view class="container"> |
| | | <!-- 顶部 Tabs --> |
| | | <view class="tabs"> |
| | | <view class="tab" bindtap="switchTab" data-tab="0" id="tab0"> |
| | | 虚拟卡 |
| | | <view class="indicator" wx:if="{{currentTab === 0}}"></view> |
| | | </view> |
| | | <view class="tab" bindtap="switchTab" data-tab="1" id="tab1"> |
| | | 水卡 |
| | | <view class="indicator" wx:if="{{currentTab === 1}}"></view> |
| | | </view> |
| | | </view> |
| | | <scroll-view class="list-container" enable-flex="true" wx:if="{{currentTab === 0}}" scroll-y="true" scroll-x="false" refresher-enabled="true" bindrefresherrefresh="onPullVirtualDownRefresh" refresher-triggered="{{isVirtualRefreshing}}" bindscrolltolower="loadVirtualMore"> |
| | | <block wx:if="{{listVirtualData.length > 0}}" wx:for="{{listVirtualData}}" wx:key="index"> |
| | | <view class="list-item" > |
| | | <!-- <image class="item-img" src="/images/pipeline.svg" /> --> |
| | | <view class="item-time"> |
| | | <text class="item-text">消费金额:</text> |
| | | <view> |
| | | <text class="item-morny">50</text> |
| | | <text class="item-morny">{{item.expense}}</text> |
| | | <text class="item-text"> 元</text> |
| | | </view> |
| | | </view> |
| | | <text class="item-text">虚拟卡编号:{{item.intakeNum}}</text> |
| | | <text class="item-text">取水口编号:</text> |
| | | <text class="item-text">开阀时间:</text> |
| | | <text class="item-text">关阀时间:</text> |
| | | <text class="item-text">水卡编号:{{item.cardNum}}</text> |
| | | <text class="item-text">取水口编号:{{item.intakeNum}}</text> |
| | | <text class="item-text">开阀类型:{{item.openType}}</text> |
| | | <text class="item-text">开阀时间:{{item.openTime}}</text> |
| | | <text class="item-text">关阀时间:{{item.closeTime}}</text> |
| | | <view class="item-time"> |
| | | <text class="item-text">用水时长:120 分钟</text> |
| | | <text class="item-text">用水量:2 m³</text> |
| | | <text class="item-text">用水时长:{{item.duration}}分钟</text> |
| | | <text class="item-text">用水量:{{item.amount}} m³</text> |
| | | </view> |
| | | |
| | | </view> |
| | | </block> |
| | | <view wx:if="{{listData.length === 0}}" class="noMore-View"> |
| | | <view wx:if="{{listVirtualData.length === 0}}" class="noMore-View"> |
| | | <image class="noMore-img" src="/images/no_more.svg" /> |
| | | <text class="noMore-text">没有数据</text> |
| | | </view> |
| | | <view wx:if="{{virtualIsLoding}}" class="loading">加载中...</view> <!-- 加载指示器 --> |
| | | <view wx:if="{{ !virtualhasMore && listVirtualData.length > 0}}" class="no-more-data"> |
| | | <text>— 已加载全部数据 —</text> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <scroll-view class="list-container" wx:else enable-flex="true" scroll-y="true" scroll-x="false" refresher-enabled="true" bindrefresherrefresh="onPullPhysicalDownRefresh" scroll-x="false" refresher-triggered="{{isPhysicalRefreshing}}" bindscrolltolower="loadPhysicalMore"> |
| | | <block wx:if="{{listPhysicalData.length > 0}}" wx:for="{{listPhysicalData}}" wx:key="index"> |
| | | <view class="list-item" > |
| | | <!-- <image class="item-img" src="/images/pipeline.svg" /> --> |
| | | <view class="item-time"> |
| | | <text class="item-text">消费金额:</text> |
| | | <view> |
| | | <text class="item-morny">{{item.expense}}</text> |
| | | <text class="item-text"> 元</text> |
| | | </view> |
| | | </view> |
| | | <text class="item-text">水卡编号:{{item.cardNum}}</text> |
| | | <text class="item-text">取水口编号:{{item.intakeNum}}</text> |
| | | <text class="item-text">开阀类型:{{item.openType}}</text> |
| | | <text class="item-text">开阀时间:{{item.openTime}}</text> |
| | | <text class="item-text">关阀时间:{{item.closeTime}}</text> |
| | | <view class="item-time"> |
| | | <text class="item-text">用水时长:{{item.duration}}分钟</text> |
| | | <text class="item-text">用水量:{{item.amount}} m³</text> |
| | | </view> |
| | | |
| | | </view> |
| | | </block> |
| | | <view wx:if="{{listPhysicalData.length === 0}}" class="noMore-View"> |
| | | <image class="noMore-img" src="/images/no_more.svg" /> |
| | | <text class="noMore-text">没有数据</text> |
| | | </view> |
| | | <view wx:if="{{physicalIsLoding}}" class="loading">加载中...</view> <!-- 加载指示器 --> |
| | | <view wx:if="{{!physicalHasMore && listPhysicalData.length > 0}}" class="no-more-data"> |
| | | <text>— 已加载全部数据 —</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | |
| | | /* pages/valveList/valveList.wxss */ |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100vh; |
| | | width: 100%; |
| | | padding-left: 20rpx; |
| | | padding-right: 20rpx; |
| | | padding-top: 5rpx; |
| | | padding-bottom: 5rpx; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .list-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | |
| | | color: #FFFF00; |
| | | font-size: 50rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .tab { |
| | | font-size: 35rpx; |
| | | padding: 10px; |
| | | cursor: pointer; |
| | | position: relative; |
| | | width: 50%; |
| | | /* Tabs 平分整个横向屏幕 */ |
| | | text-align: center; |
| | | /* 文字居中 */ |
| | | } |
| | | |
| | | .tabs { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | position: relative; |
| | | width: 100%; |
| | | border-bottom: 1px solid #eee; |
| | | /* Tabs 占满整个横向屏幕 */ |
| | | } |
| | | |
| | | .list-container { |
| | | flex: 1; |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .noMore-View { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | padding: 40rpx 0; |
| | | width: 100%; |
| | | text-align: center; |
| | | } |
| | | |
| | | .noMore-img { |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .noMore-text { |
| | | font-size: 32rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .indicator { |
| | | width: 100%; |
| | | height: 3px; |
| | | background-color: #1890FF; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | transform: translateX(0); |
| | | /* 初始化位置 */ |
| | | } |
| | | |
| | | .no-more-data { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | color: #999; |
| | | font-size: 28rpx; |
| | | width: 100%; |
| | | text-align: center; |
| | | } |
| | |
| | | "component": true, |
| | | "usingComponents": { |
| | | "t-avatar": "tdesign-miniprogram/avatar/avatar", |
| | | "t-switch": "tdesign-miniprogram/switch/switch", |
| | | |
| | | "t-button": "tdesign-miniprogram/button/button", |
| | | "t-dialog": "tdesign-miniprogram/dialog/dialog", |
| | | "t-input": "tdesign-miniprogram/input/input", |
| | |
| | | JYG: { |
| | | tag: 'ym', |
| | | displayName: '嘉峪关项目', |
| | | needLogin: true // 需要登录 |
| | | operatorId: '2025040415305200007', // 统一ID用于operator和clientId |
| | | needLogin: false // 不需要登录 |
| | | }, |
| | | MQ: { |
| | | tag: 'mq', |
| | |
| | | tag: 'XX', |
| | | displayName: '学校项目', |
| | | operatorId: '2025040215305200006', // 统一ID用于operator和clientId |
| | | needLogin: true // 不需要登录 |
| | | needLogin: false // 不需要登录 |
| | | }, |
| | | JC: { |
| | | tag: 'jc', |
| | | displayName: '金昌项目', |
| | | operatorId: '2025041710412400006', // 统一ID用于operator和clientId |
| | | needLogin: false // 不需要登录 |
| | | }, |
| | | GSCLT:{ |
| | | tag: 'test', |
| | | displayName: '甘肃农科院-崔', |
| | | operatorId: '2025041912201400006', // 统一ID用于operator和clientId |
| | | needLogin: false // 不需要登录 |
| | | } |
| | | }; |
| | | |