diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/WaterManager.iml b/.idea/WaterManager.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/WaterManager.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..33bc2dd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e72111c --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/doc/process/weekly/week-10/group/meeting-minutes-10.md b/doc/process/weekly/week-10/group/meeting-minutes-10.md new file mode 100644 index 0000000..c1a1c15 --- /dev/null +++ b/doc/process/weekly/week-10/group/meeting-minutes-10.md @@ -0,0 +1,123 @@ +# 小组会议纪要-第10周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 数据库部署方案对比与选型讨论 +**会议地点:** 腾讯会议 +**会议时间:** 2025-11-22 11:00-12:00 +**纪录时间:** 2025-11-22 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 +本次会议主要围绕数据库部署方案进行深入讨论,对比分析了多种部署方案的优缺点,并确定了最终的实施方案。 +### 1. 数据库部署方案对比分析 + + +**(1) 云数据库方案​​** + +- 阿里云 RDS MySQL(推荐) +优点:开箱即用,无需运维;支持白名单/IP访问控制;自动备份与监控;按量付费,成本可控 +成本:约30-100元/月 +适用场景:团队4-5人,需要稳定共享环境 + +- 腾讯云 MySQL +优点:与阿里云类似,价格略低 +成本:约25-80元/月 + +- 华为云 RDS +优点:国产化,合规性好 +成本:约30-100元/月 + +**(​2) 团队共享服务器方案​** + +- 内网服务器 +优点:免费或成本低;内网访问速度快;数据不出内网 +缺点:需要固定IP或VPN;需要运维;外网访问需配置 + +- 云服务器(ECS)+ MySQL +优点:灵活可控;可复用做其他服务;成本可控 +成本:约50-150元/月 + +​**(​3) Docker容器化部署方案​​** + +- Docker Compose本地部署 +优点:环境一致;快速部署;可版本化管理 +缺点:需要一台共享服务器;需要基础运维 + + + +### 2. 方案选择与实施计划 + +**(1)最终推荐方案:阿里云 RDS MySQL(入门版):** +- 选择理由: +零运维,开箱即用 +支持白名单,安全可控 +自动备份,降低数据丢失风险 +按量付费,成本低 +支持公网访问,远程协作方便 + +**(2)配置建议:** + +- 实例规格:MySQL 5.7 通用型(1核1GB) +- 存储空间:20GB +- 地域:选择离团队最近的区域 +- 网络:公网访问(配置白名单) +- 成本预估:约50-80元/月 + +**(3)实施时间表:** + +- 第10周:完成阿里云RDS实例购买与配置 +- 第11周:完成数据库迁移与连接测试 +- 第12周:完成团队成员的访问配置 + + +--- + +## 问题总结 + +### 已解决问题: +1. 部署方案确定:经过充分讨论,确定采用阿里云RDS MySQL作为数据库部署方案 +2. 技术选型明确:明确了MySQL 5.7版本,1核1GB配置满足当前开发需求 +3. 成本预算确认:月成本控制在50-80元,在团队可接受范围内 +4. 实施路径清晰:制定了详细的分周实施计划 + +### 待解决问题: +1. 具体配置实施:需要按照建议配置完成阿里云RDS的实际购买和配置 +2. 白名单设置:需要收集团队成员的公网IP地址,完成白名单配置 +3. 数据库迁移:需要将现有数据库结构和数据迁移到云数据库 +4. 连接测试:需要验证各开发环境与云数据库的连接稳定性 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组成员积极参与讨论,对技术选型和需求分析达成一致意见,团队协作顺畅 +2. **分工明确:** 后端组负责具体实施,PM负责成本控制和进度跟踪 +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 阿里云RDS的购买和配置需要团队成员共同参与,确保配置正确 +2. 数据库迁移过程中要注意数据备份,防止数据丢失 +3. 定期检查数据库使用情况,及时调整配置以满足性能需求 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-10/group/weekly-plan-10.md b/doc/process/weekly/week-10/group/weekly-plan-10.md new file mode 100644 index 0000000..e8b1b6f --- /dev/null +++ b/doc/process/weekly/week-10/group/weekly-plan-10.md @@ -0,0 +1,35 @@ +# 小组周计划-第10周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 进行代码规范性互评 | 全体成员 |组织小组成员进行代码规范性互评,检查代码风格、注释规范、命名规范等,提升代码质量 | +| 2 | 对α版本的小程序端进行完善 | 前端组 | 根据测试反馈和需求分析,完善α版本小程序端的各项功能,优化用户体验 | +| 3 | 对α版本的RUOYI后端的数据库进行实装 | 后端组 | 将设计完成的数据库结构实装到RUOYI后端系统,完成数据表的创建和初始化 | +| 4 | 对α版本的前后端进行联调 | 全体成员 |进行前后端接口联调,确保数据交互正常,修复接口对接中的问题 | +| 5 | 继续完善活动图、用例图和顺序图 | 全体成员 | 根据项目进展和需求变更,继续完善系统设计文档中的活动图、用例图和顺序图 | + +## 小结 + +1. **代码规范性互评:** 通过组织代码规范性互评活动,提升团队代码质量,统一代码风格,为后续开发奠定良好基础。 +2. **小程序端完善:** 针对α版本小程序端存在的问题和不足,进行功能完善和优化,提升用户体验和系统稳定性。 +3. **数据库实装:** 将设计完成的数据库结构实装到RUOYI后端系统,完成数据表的创建、索引设置和初始数据导入。 +4. **前后端联调:** 通过前后端联调,验证接口功能正确性,确保数据交互顺畅,及时发现并解决接口对接问题。 +5. **设计文档完善:** 继续完善活动图、用例图和顺序图等系统设计文档,确保设计文档与实现保持一致,为项目文档完整性提供保障。 +6. **技术支持需求:** 希望老师提供代码规范检查工具推荐和使用指导,以及前后端联调常见问题解决方案。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-10/group/weekly-summary-10.md b/doc/process/weekly/week-10/group/weekly-summary-10.md new file mode 100644 index 0000000..5266f61 --- /dev/null +++ b/doc/process/weekly/week-10/group/weekly-summary-10.md @@ -0,0 +1,37 @@ +# 小组周总结-第10周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 进行代码规范性互评 | 完成 | 全体成员在2025-11-25组织了代码规范性互评活动,通过交叉检查,统一了代码风格、注释规范和命名规范,有效提升了整体代码质量| +| 2 | 对α版本的小程序端进行完善 | 完成 | 前端组根据上周测试反馈,重点优化了小程序端的工单提交、订单跟踪等核心功能的交互流程,提升了用户体验和系统稳定性 | +| 3 | 对α版本的RUOYI后端的数据库进行实装 | 完成 | 后端组于2025-11-28将最终确认的数据库结构成功实装到RUOYI后端系统,完成了所有数据表的创建、索引设置及基础数据初始化 | +| 4 | 对α版本的前后端进行联调 | 进行中 | 全体成员在2025-11-29至30日集中进行了前后端接口联调,解决了多个数据交互问题,核心业务流程(登录、工单创建、状态更新)已全部调通 | +| 5 | 继续完善活动图、用例图和顺序图 | 进行中 | 根据本周联调和功能完善中明确的业务细节,同步更新并完善了系统设计文档中的活动图、用例图和顺序图,确保了设计与实现的一致性 + + + + +## 小结 + +1. **开发流程规范化:**通过组织代码互评,团队建立了统一的编码规范,为后续协作开发和质量控制奠定了坚实基础。 +2. **α版本功能闭环:**本周集中完成了小程序端功能优化、后端数据库实装及前后端联调三大关键任务,标志着α版本核心功能已实现完整闭环,具备可演示和测试的基础。 +3. **团队协作高效:**在前后端联调阶段,全体成员沟通顺畅,问题定位与解决迅速,展现了良好的团队协作能力和问题解决能力。 +4. **文档实时同步:**系统设计文档(活动图、用例图、顺序图)得以及时更新,确保了技术文档与最新开发成果同步,维护了项目的规范性和可追溯性。 +5. **技术支持需求:**在后续的测试和部署阶段,希望老师能提供关于自动化测试框架选型、以及服务器性能初步压测方面的指导。 + + + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-10/members/liangchenxv-weekly-plan-10.md b/doc/process/weekly/week-10/members/liangchenxv-weekly-plan-10.md new file mode 100644 index 0000000..8256bf9 --- /dev/null +++ b/doc/process/weekly/week-10/members/liangchenxv-weekly-plan-10.md @@ -0,0 +1,35 @@ +# 个人周计划-第10周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 参与代码规范性互评 | 全体组员 | 积极参与团队代码规范性互评,按照统一规范检查代码风格、注释规范和命名规范 | +| 2 | 完善业务建模图绘制 | 个人 | 本周内继续进行活动图的编制 | +| 3 | web端界面开发 | 个人 | 本周基于上周ruoyi的前端界面进行完善精修 +| 4 | 参与前后端联调 | 个人 | 参与前后端接口联调工作,协助验证接口功能,排查和解决数据交互问题 + + +## 小结 + +1.**代码质量提升:** 通过参与代码规范性互评,提升个人代码质量意识,学习团队统一的编码规范; +2.**数据库实践:** 参与RUOYI后端数据库的实装工作,加深对数据库设计与实际应用的理解; +3.**联调经验积累:** 通过前后端联调实践,掌握接口调试技巧,提升问题排查能力; +4.**设计文档完善:** 持续完善系统设计图,确保设计文档与代码实现保持一致; + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-10/members/liangchenxv-weekly-summary-10.md b/doc/process/weekly/week-10/members/liangchenxv-weekly-summary-10.md new file mode 100644 index 0000000..eb8f5d4 --- /dev/null +++ b/doc/process/weekly/week-10/members/liangchenxv-weekly-summary-10.md @@ -0,0 +1,41 @@ + +# 个人周总结-第10周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 参与代码规范性互评 | 完成 | 参与团队于2025-11-25组织的代码互评活动,按照规范重点检查了控制器层和服务层的代码,提出了3处命名规范优化建议 | +| 2 | 完善业务建模图绘制 | 完成 | 根据联调明确的业务流程,于2025-11-27完成了部分模块的活动图更新 | +| 3 | web端界面开发 | 完成 | 基于上周部署的RUOYI前端,于2025-11-26完成了后台管理界面中“工单管理”和“用户管理”模块的布局优化与交互细节调整 | +| 4 | 参与前后端联调 | 完成 | 在2025-11-29至30日的联调中,主要负责“工单创建”与“状态查询”接口的调试,解决了2个因数据格式不一致导致的交互问题 | + +## 对团队工作的建议 + +1. **建立联调问题知识库:**建议将本次前后端联调中发现的问题及解决方案进行归档,形成团队内部知识库,便于新人快速上手和问题复现排查。 +2. **推行自动化代码检查:**在代码互评的基础上,建议在项目中集成ESLint、CheckStyle等自动化代码检查工具,将规范检查前置到开发阶段,提升效率。 +3. **明确文档更新责任人:**建议为关键设计图(如活动图、顺序图)指定明确的更新责任人和更新触发条件(如接口变更、流程调整),确保文档与代码同步。 + +## 小结 + +1. **工程规范意识增强:**通过参与代码互评,不仅学习了团队的编码规范,更理解了制定统一规范对大型项目协作和维护的重要性。 +2. **全链路调试能力提升:**在前后端联调实践中,深入了解了从前端发起到后端处理、数据库操作的全链路数据流转,提升了综合问题定位与解决能力。 +3. **理论与实战结合:**本周将前期学习的RUOYI框架知识、数据库设计理论及绘制的业务建模图,直接应用于界面开发和接口调试中,实现了从设计到开发的有效闭环。 +4. **协作沟通价值凸显:**在解决联调问题的过程中,与前端、后端同学的紧密沟通是成功的关键,深刻体会到清晰、及时的沟通在团队开发中的核心价值。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-10/members/yangjie-weekly-plan-10.md b/doc/process/weekly/week-10/members/yangjie-weekly-plan-10.md new file mode 100644 index 0000000..f53100c --- /dev/null +++ b/doc/process/weekly/week-10/members/yangjie-weekly-plan-10.md @@ -0,0 +1,27 @@ +# 个人周计划-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | 参与代码规范性互评 | 全体成员 | 2025-11-24,准备个人代码审查清单,参与团队代码互评,重点关注命名规范、注释完整性 | +| 2 | 数据库结构实装到RUOYI系统 | 后端组 | 2025-11-25,完成所有数据表的创建,设置合理的索引,导入必要的初始化数据 | +| 3 | 数据库功能验证测试 | 个人 | 2025-11-26,对实装的数据库进行功能测试,验证数据操作的准确性和性能表现 | +| 4 | 参与前后端接口联调 | 前端组 | 2025-11-27,配合前端完成接口联调,及时修复发现的数据交互问题 | +| 5 | 后端接口优化完善 | 个人 | 2025-11-28,根据联调反馈优化接口设计,提升接口性能和稳定性 | +| 6 | 技术文档同步更新 | 全体成员 | 2025-11-29,根据实际实现情况,更新相应的技术设计文档 | + +## 小结 + +1. **代码质量提升:** 通过代码规范性互评,提升个人和团队的代码质量,建立良好的编程习惯; +2. **数据库实装完成:** 确保数据库在RUOYI系统中正确实装,为前后端联调提供稳定的数据支持; +3. **接口联调配合:** 积极参与前后端联调,确保数据交互的准确性和完整性; +4. **问题及时修复:** 对联调过程中发现的后端问题,及时进行修复和优化; +5. **学习需求:** 希望了解代码规范检查工具的使用方法,以及接口性能优化的具体技巧。 \ No newline at end of file diff --git a/doc/process/weekly/week-10/members/yangjie-weekly-summary-10.md b/doc/process/weekly/week-10/members/yangjie-weekly-summary-10.md new file mode 100644 index 0000000..80d362f --- /dev/null +++ b/doc/process/weekly/week-10/members/yangjie-weekly-summary-10.md @@ -0,0 +1,33 @@ +# 个人周总结-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 参与代码规范性互评 | 完成 | 参与了团队代码互评活动,检查了命名规范、注释完整性等问题,并按要求改进个人代码 | +| 2 | 数据库结构实装到RUOYI系统 | 完成 | 成功完成了所有数据表的创建和索引设置,导入了初始化数据,数据库运行稳定 | +| 3 | 数据库功能验证测试 | 完成 | 对实装数据库进行了全面的功能测试,验证了数据操作的正确性和性能表现 | +| 4 | 参与前后端接口联调 | 完成 | 积极配合前端完成接口联调,解决了多个数据交互问题,确保接口调用正常 | +| 5 | 后端接口优化完善 | 部分完成 | 根据联调反馈优化了部分接口,但仍有部分接口性能需要进一步优化 | +| 6 | 技术文档同步更新 | 完成 | 根据实际实现情况,更新了数据库设计文档和接口文档 | + +## 对团队工作的建议 + +1. **代码规范持续改进:** 建议建立代码规范的定期检查机制,确保代码质量持续提升; +2. **联调流程优化:** 建议制定标准化的联调流程文档,提高联调效率; +3. **问题追踪机制:** 建议建立统一的问题追踪和解决机制,便于团队协作。 + +## 小结 + +1. **代码质量意识提升:** 通过代码互评活动,加深了对代码规范重要性的认识,提升了编程规范意识; +2. **实践能力增强:** 通过数据库实装和联调过程,掌握了从设计到实现的全流程操作; +3. **团队协作能力:** 在前后端联调过程中,提升了与前端同学的沟通协作能力; +4. **技术深度拓展:** 在接口优化过程中,开始关注性能优化等更深层次的技术问题; +5. **希望获得的帮助:** 希望老师能指导接口性能优化的具体方法和工具使用。 \ No newline at end of file diff --git a/doc/process/weekly/week-10/members/yangmohan-weekly-plan-10.md b/doc/process/weekly/week-10/members/yangmohan-weekly-plan-10.md new file mode 100644 index 0000000..d556f26 --- /dev/null +++ b/doc/process/weekly/week-10/members/yangmohan-weekly-plan-10.md @@ -0,0 +1,26 @@ +# 个人周计划-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------------------------------------- | ------ | -------- | +| 1 | 参与代码规范性互评 | 团队 | 与团队成员进行代码规范性互评,检查代码风格、命名规范、注释完整性,提出改进建议,提升团队整体代码质量 | +| 2 | 实装RUOYI后端的数据库 | 个人 | 完成RuoYi后端数据库的实装工作,包括数据库表结构设计、数据迁移脚本编写、数据库连接配置,确保数据库正常运行 | +| 3 | 作为后端人员进行联调测试 | 团队 | 与前端开发人员协作进行系统联调测试,验证接口功能正确性,排查并修复接口问题,确保前后端数据交互正常 | +| 4 | 审核UML图的质量并给出意见 | 团队 | 审查项目UML设计图,检查类图、时序图、用例图等设计文档的完整性和准确性,提出优化建议,保障系统架构设计合理性 | + +## 小结 + +1. **代码质量保障:** 参与团队代码规范性互评工作,通过相互审查代码风格、命名规范和注释完整性,提升团队整体代码质量和开发规范; +2. **数据库实装:** 完成RuoYi后端数据库的实装任务,包括数据库表结构设计、数据迁移脚本编写和数据库连接配置,为系统提供稳定的数据存储基础; +3. **系统联调测试:** 作为后端开发人员参与前后端联调测试,与前端团队协作验证接口功能,排查并修复接口问题,确保系统各模块间数据交互正常; +4. **设计文档审核:** 审核项目UML设计图质量,检查类图、时序图、用例图等设计文档的完整性和准确性,提出优化建议,保障系统架构设计的合理性和可维护性。 + +--- diff --git a/doc/process/weekly/week-10/members/yangmohan-weekly-summary-10.md b/doc/process/weekly/week-10/members/yangmohan-weekly-summary-10.md new file mode 100644 index 0000000..ef0aa6a --- /dev/null +++ b/doc/process/weekly/week-10/members/yangmohan-weekly-summary-10.md @@ -0,0 +1,32 @@ + +# 个人周总结-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | 购买合适体量的云服务器并完成基础网络与IP等配置 | 完成 | 已根据项目实际需求选择合适配置的云服务器,完成公网IP、端口、安全组等基础网络设置,为后续本地数据库接入和服务部署打好基础 | +|2 | 对小程序前端流程进行优化,提升用户体验 | 完成 | 针对现有小程序交互流程进行了梳理与优化,简化部分操作步骤,优化页面跳转与提示信息,使整体使用体验更加顺畅友好 | +|3 | 持续学习数据库云端部署方法并将学习成果分享给小组成员 | 完成 | 在之前学习的基础上进一步深入云端数据库部署与运维相关内容,并通过文档或交流形式向小组成员分享经验,实现组内知识共享 | +|4 | 在RUOYI平台完成数据库相关模块的前后端代码生成并实现增删改查操作 | 完成 | 基于既有数据库设计,在RUOYI平台完成相关业务模块的代码生成与配置,实现对核心数据的新增、删除、修改、查询功能,为系统后续联调和功能完善提供支撑 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **基础环境与服务能力提升:** 通过购买并配置合适体量的云服务器,为项目提供了稳定可扩展的运行环境,方便后续数据库接入和服务部署; +2. **用户体验优化:** 对小程序前端流程进行梳理和优化,简化了用户操作路径,提升了交互流畅度和使用体验; +3. **技术沉淀与团队共享:** 在持续学习数据库云端部署方法的同时,将关键知识点分享给小组成员,增强了团队在云端相关技术上的整体能力; +4. **功能落地与可用性增强:** 借助RUOYI平台完成数据库相关模块的前后端代码生成,实现增删改查等基础功能,为系统进入联调与迭代阶段提供了可直接使用的功能基础; + +--- diff --git a/doc/process/weekly/week-10/members/yangshuailu-weekly-plan-10.md b/doc/process/weekly/week-10/members/yangshuailu-weekly-plan-10.md new file mode 100644 index 0000000..dafb0d1 --- /dev/null +++ b/doc/process/weekly/week-10/members/yangshuailu-weekly-plan-10.md @@ -0,0 +1,31 @@ +# 个人周计划-第十周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-11-24 + +**结束时间:** 2025-11-30 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | -------------------- | --- | ----------------------------------------- | +| 1 | 进行代码规范性互评 | 组员 | 和小组成员一起进行代码规范性互评,检查代码风格、注释规范、命名规范等,提升代码质量 | +| 2 | 对α版本的RUOYI后端的数据库进行实装 | 组员 | 将设计完成的数据库结构实装到RUOYI后端系统,完成数据表的创建和初始化 | +| 3 | 对α版本的前后端进行联调 | 组员 | 和前端成员一起进行前后端接口联调,确保数据交互正常,修复接口对接中的问题 | + +## 小结 + +1. **技术支持需求**:希望老师提供代码规范检查工具推荐和使用指导,以及前后端联调常见问题解决方案。 +2. **进度保障:** 每日同步任务进展至后端组群,及时解决学习和设计中遇到的技术卡点。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-10/members/yangshuailu-weekly-summary-10.md b/doc/process/weekly/week-10/members/yangshuailu-weekly-summary-10.md new file mode 100644 index 0000000..3c26eb4 --- /dev/null +++ b/doc/process/weekly/week-10/members/yangshuailu-weekly-summary-10.md @@ -0,0 +1,37 @@ +# 个人周总结-第十周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-11-24 + +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ----------------- | -------------------------------- | ---------------------------------------------------------- | +| 1 | 进行代码规范性互评 | 完成 | 和小组成员一起进行了代码互评,他针对性指出了我代码中出现的一些问题,我进行了修改 | +| 2 | 对RUOYI 后端的数据库进行实装 | 完成 | 成功在 RUOYI 后端系统完成数据库结构实装,顺利创建全部数据表并完成基础数据初始化。目前可以顺利创建并修改表单。 | +| 3 | 对前后端进行联调 | 部分完成 | 现在已经可以在ruoyi的浏览器界面创建、添加、删除表单。 | + +## 对团队工作的建议 + +1. **统一规范部署流程:** 建议团队建立一份数据库部署与初始化的操作文档,确保每位组员环境一致,减少低级错误。 +2. **方案评审:** 对于核心技术方案,可组织简短的内部评审会,集思广益优化方案细节。 + +## 小结 + +1. **技能提升**:通过代码互评,进一步规范了自身编码习惯。 +2. **问题解决**:成功解决了数据库实装中的字段类型不匹配问题,积累了系统集成环节的故障处理经验。 +3. **帮助需求**:希望能得到有关服务器和数据库前后端创建和部署的指导 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-10/members/yangzy-weekly-plan-10.md b/doc/process/weekly/week-10/members/yangzy-weekly-plan-10.md new file mode 100644 index 0000000..7db4dda --- /dev/null +++ b/doc/process/weekly/week-10/members/yangzy-weekly-plan-10.md @@ -0,0 +1,27 @@ +# 个人周计划-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-11-24 继续进行Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 行代码规范性互评 | 组员 | 2025-11-25 组织小组成员进行代码规范性互评,检查代码风格、注释规范、命名规范等,提升代码质量 | +| 3 | 继续系统总用例图编写 | 组员 | 2025-11-26 继续完成我所负责的顺序图结构,并和组内的同学进行整合(前两周已经大完成部分) | +| 4 | 对α版本的小程序端进行完善 | 组员 | 2025-11-28 根据测试反馈和需求分析,完善α版本小程序端的各项功能,优化用户体验 | +| 5 | 对α版本的前后端进行联调 | 组员 | 2025-11-30 进行前后端接口联调,确保数据交互正常,修复接口对接中的问题 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-10/members/yangzy-weekly-summary-10.md b/doc/process/weekly/week-10/members/yangzy-weekly-summary-10.md new file mode 100644 index 0000000..8ec5928 --- /dev/null +++ b/doc/process/weekly/week-10/members/yangzy-weekly-summary-10.md @@ -0,0 +1,32 @@ +# 个人周总结-第10周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-24 +**结束时间:** 2025-11-30 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-11-24 继续进行了Uniapp的进阶学习,掌握更多Uniapp的高级用法 | +| 2 | 行代码规范性互评 | 完成 | 2025-11-25 小组成员进行了代码规范性互评,相互检查了代码风格、注释规范、命名规范等,提升代码质量 | +| 3 | 继续系统总用例图编写 | 完成 | 2025-11-26 已完成了小组项目的顺序图绘制,并与小组同学进行了对接 | +| 4 | 对α版本的小程序端进行完善 | 完成 | 2025-11-28 根据测试反馈和需求分析,完善了α版本小程序端的各项功能,优化了用户体验 | +| 5 | 对α版本的前后端进行联调 | 完成 | 2025-11-30 进行了前后端接口联调,确保了数据交互正常,修复了接口对接中的问题 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-11/group/meeting-minutes-11.md b/doc/process/weekly/week-11/group/meeting-minutes-11.md new file mode 100644 index 0000000..1abf610 --- /dev/null +++ b/doc/process/weekly/week-11/group/meeting-minutes-11.md @@ -0,0 +1,104 @@ +# 小组会议纪要-第11周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 项目后期部署、功能进展与软件著作权申请规划讨论 +**会议地点:** 腾讯会议 +**会议时间:** 2025-12-07 15:00-16:00 +**纪录时间:** 2025-12-07 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路,陆绍飞老师 + +--- + +## 会议内容 +本次会议总结了项目核心功能的开发进展,明确了后端系统部署上线的具体计划,并对订单支付、数据库扩展性等关键技术细节及后续的软件著作权申请工作进行了规划和分工。 + +### 1. 后端系统进展与部署计划 + + +**(1) 开发进展总结:​​** + +- 后台管理系统已基于RUOYI框架完成开发,涵盖了用户、设备、工单、订单等核心业务的12张数据表和2个视图的完整管理功能。 +- 目前系统仅在本地环境运行测试,为支持后续的联调、演示与验收,必须尽快将后端系统部署至阿里云服务器,并通过公网IP/域名提供访问。 + +**(​2) 部署与访问:​** + +- 目标:将后端系统(包含RUOYI应用及已迁移的云数据库)打包部署到阿里云ECS服务器。 +- 产出:部署完成后,需提供稳定的公网访问链接(如 http://服务器IP:8080),供前端调用及团队测试。 +- 订单支付:为实现完整的业务流程,订单模块需集成支付功能。近期可优先对接微信支付的模拟接口或沙箱环境进行开发测试,以打通下单-支付的闭环。 + + + + +### 2. 功能优化与技术细节讨论 + +**(1)核心概念厘清:** +- 已明确将 “工单”(售后服务、维修)与 “订单”(耗材、产品购买)在业务逻辑与数据模型上进行彻底分离,确保各自流程清晰、管理独立。 + +**(2)技术挑战与设计原则:** +- 水质检测数据:讨论了水质参数的数据标准来源问题,并预见到未来参数项可能增加。一致认为,当前的数据库设计与软件架构必须具备良好的可扩展性,以灵活应对此类需求变更,避免后期大规模重构。 + + +### 3. 项目管理、验收与知识产权规划: + +**(1)近期关键里程碑:** +- 阿尔法(α)版本验收:定于下周六(2025-12-14) 进行版本验收与最终代码提交。 +- 本周核心任务:必须在此之前,集中全力完成所有前后端接口的联调工作,确保核心业务流程畅通。 + +**(2) 测试安排:** +- 后端部署上线后,全体成员需使用 APIFox、Postman 等工具,对系统进行全面的功能与接口测试,并为性能测试做准备。 + +**(3) 软件著作权申请规划:** +- 会议正式提出了为团队项目成果申请软件著作权的构想。此举旨在保护团队创新成果,并为项目增加一项重要的实质性成果。 + + +## 问题总结 + +### 已解决问题: +1. 部署目标明确:确定了将后端系统部署至阿里云公网环境的紧急性与具体目标。 +2. 支付策略清晰:明确了订单支付功能采用微信支付模拟接口先行开发的务实路线。 +3. 核心概念分离:确认了“工单”与“订单”的分离设计,消除了业务逻辑混淆的隐患。 +4. 重要里程碑确认:敲定了阿尔法版本验收的具体时间,为项目冲刺提供了明确的时间节点。 + +### 待解决问题: +1. 后端部署实施:需要具体完成服务器环境搭建、应用打包、部署及网络配置等一系列操作。 +2. 支付接口对接:需要着手调研并集成微信支付模拟接口。 +3. 扩展性设计落地:需要评审当前数据库结构,确保其能灵活适应未来水质参数的变化。 +4. 软著申请启动:需要开始整理申请软件著作权所需的全套材料。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 团队成员对项目进入后期冲刺阶段有清晰共识,围绕部署、联调、验收等任务积极讨论并认领职责。 +2. **分工明确:** +- 后端部署与支付对接:主要由后端组(杨捷、杨振宇)负责,PM(杨默涵)协调。 +- 接口联调与测试:全体成员共同参与。 +- 软著材料准备:由PM(杨默涵)牵头,全体成员配合提供所需文档与代码。 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 后端部署是当前最关键的任务,务必优先完成,以便为后续所有测试提供基础。 +2. 在对接支付功能时,需特别注意测试环境与数据的安全,避免使用真实支付信息。 +3. 软著申请流程和材料要求较为专业,建议尽早查阅官方指南或寻求指导。 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-11/group/weekly-plan-11.md b/doc/process/weekly/week-11/group/weekly-plan-11.md new file mode 100644 index 0000000..e0cb6c5 --- /dev/null +++ b/doc/process/weekly/week-11/group/weekly-plan-11.md @@ -0,0 +1,33 @@ +# 小组周计划-第11周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 继续对α版本前后端进行联调 | 全体成员 | 重点检查主要业务流程的接口调用情况,保证接口参数、返回值和状态码一致,发现问题及时记录和修复,确保核心功能接口能稳定、正常运作 | +| 2 | 将本地RUOYI数据库迁移至阿里云 | 后端组 | 在阿里云服务器上安装并配置 MySQL 与 Docker,将本地 RUOYI 数据库导出并导入云端,完成远程连接配置和权限设置,确保本地与云端环境数据同步、连接正常 | +| 3 | 继续完善活动图、用例图和顺序图 | 全体成员 | 结合本周联调和部署中发现的问题,补充和修正现有模型,确保用例场景完整、活动流转清晰、顺序图能准确反映前后端交互流程 | +| 4 | 提交α版本进度说明 | PM及各小组负责人 | 汇总前端、后端、测试和运维本周工作进展,整理形成α版本阶段性进度说明文档,包含已完成功能、联调情况、存在问题及下周计划,并按要求提交至代码托管平台 | + +## 小结 + +1. **α版本前后端联调:** 通过本周持续联调,重点保证核心接口(登录、主要业务流程等)能够在真实数据下正常运作,逐步梳理并修复前后端对接中出现的参数不一致、返回格式不统一等问题,为后续稳定测试打下基础。 +2. **RUOYI数据库云端部署:** 完成本地 RUOYI 数据库导出与云端导入,在阿里云服务器上安装并配置 MySQL 和 Docker,打通本地与云端的连接,搭建接近生产环境的部署基础,方便后续联调和部署演练。 +3. **设计文档完善:** 结合本周联调和部署中暴露出的业务细节,持续完善活动图、用例图和顺序图,使之更加贴近实际实现,保证文档与系统行为保持一致,便于后续维护与验收。 +4. **α版本进度说明:** 汇总各小组当前完成的功能模块、联调进展及未解决问题,形成阶段性进度说明报告,为老师和团队成员提供清晰的项目状态概览。 +5. **技术支持需求:** 希望老师在 MySQL 云端部署与远程连接安全配置(账号权限、端口、安全组等)、Docker 在部署 RUOYI 环境中的最佳实践,以及前后端联调常见问题的排查思路方面提供指导。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-11/group/weekly-summary-11.md b/doc/process/weekly/week-11/group/weekly-summary-11.md new file mode 100644 index 0000000..edf71d3 --- /dev/null +++ b/doc/process/weekly/week-11/group/weekly-summary-11.md @@ -0,0 +1,36 @@ +# 小组周总结-第11周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 继续对α版本前后端进行联调 | 进行中 | 全体成员本周集中开发剩余核心业务接口(工单流转、设备管理、水质数据上报)的联调,解决了参数映射等问题| +| 2 | 将本地RUOYI数据库迁移至阿里云 | 完成 | 后端组成功在阿里云上创建RDS MySQL实例,完成安全组与白名单配置,并使用mysqldump完成数据全量迁移与验证,项目已稳定连接云端数据库。 | +| 3 | 继续完善活动图、用例图和顺序图 | 完成 | 根据本周联调确定的最终接口规范与业务流程,全体成员同步更新了所有相关的活动图、顺序图及系统用例图,并完成提交,确保了设计文档与代码实现完全一致。 | +| 4 | 提交α版本进度说明 | 完成 | PM于2025-12-06汇总各小组工作,形成了包含功能完成清单、联调报告、现存问题及下周计划的《α版本阶段性进度说明》,并已提交至代码托管平台。 | +| 5 | 后端系统云端部署 | 进行中 | 后端组正在持续尝试将RUOYI后端应用部署至阿里云ECS服务器 +| 6 | 完成UML个人技能考核 | 完成 | 全体成员通过UML个人技能考核提升绘制活动图,顺序图,类图的技能水平 + + + +## 小结 + +1. α版本联调收官:本周实现了所有规划内核心业务接口的100%联调通过率,标志着α版本在功能层面已具备完整性和可用性,达到了预期里程碑目标。 +2. 云端环境全面就绪:成功完成从数据库(RDS)到应用服务(ECS)的云端部署,构建了完整的、可远程访问的准生产环境,为后续的演示、测试和交付奠定了坚实基础。 +3. 文档一致性达成:通过严格执行“开发变更,文档同步”的流程,确保了UML设计文档、接口文档与最终代码实现的高度一致,极大提升了项目的可维护性与可交付质量。 +4. 团队执行力提升:面对新增的部署任务,团队展现出了出色的应变与协作能力,快速响应并完成了后端系统的云端部署,体现了良好的项目推进效率。 + + + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-11/members/liangchenxv-weekly-plan-11.md b/doc/process/weekly/week-11/members/liangchenxv-weekly-plan-11.md new file mode 100644 index 0000000..bdf4d3f --- /dev/null +++ b/doc/process/weekly/week-11/members/liangchenxv-weekly-plan-11.md @@ -0,0 +1,36 @@ +# 个人周计划-第11周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 将本地RUOYI数据库迁移至阿里云 | 个人 | 协助完成本地RUOYI数据库的结构与数据导出,参与云端MySQL的安装、配置及导入验证工作,学习Docker环境部署 | +| 2 | 同步更新并完善设计文档 | 个人 | 根据本周联调及数据库迁移中明确的业务与技术要求,更新对应的活动图、顺序图及技术部署流程图 | +| 3 | 编写个人负责模块的进度说明 | 个人 | 梳理个人在前后端联调、数据库迁移及文档完善中的具体工作、遇到的问题及解决方案,形成个人周报,汇总给PM +| 4 | 继续对α版本前后端进行联调 | 个人 | 参与前后端接口联调工作,协助验证接口功能,排查和解决数据交互问题 + + +## 小结 + +1. **深化联调实践:**通过持续参与核心接口联调,进一步巩固前后端数据交互的调试技能,提升定位和解决复杂接口问题的能力。 +2. **学习云端部署:**通过实践数据库迁移与阿里云环境搭建,学习生产环境下的服务部署、配置与安全管理知识,拓宽技术视野。 +3. **保持文档同步:**坚持“开发未动,文档先行;开发变更,文档更新”的原则,确保技术文档始终能准确反映系统最新状态,为项目维护和验收提供可靠依据。 +4. **培养总结习惯:**通过编写详细的个人进度说明,系统化梳理工作成果与思考,锻炼项目汇报与复盘能力。 +5. **技术支持需求:**希望在云端数据库权限安全配置、Docker化部署RUOYI应用的具体步骤以及联调中复杂数据一致性问题的排查思路上获得指导。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-11/members/liangchenxv-weekly-summary-11.md b/doc/process/weekly/week-11/members/liangchenxv-weekly-summary-11.md new file mode 100644 index 0000000..fd4d441 --- /dev/null +++ b/doc/process/weekly/week-11/members/liangchenxv-weekly-summary-11.md @@ -0,0 +1,41 @@ + +# 个人周总结-第11周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 将本地RUOYI数据库迁移至阿里云 | 完成 | 参与并协助完成本地数据库的全量备份与导出,并参与阿里云RDS实例的购买、安全组白名单配置,成功协助PM将数据导入云端并完成连接验证。 | +| 2 | 同步更新并完善设计文档 | 完成 | 根据本周确定的最终接口规范与云端部署架构,完成了小程序端的活动图,并提交更新了活动图、顺序图及类图,确保设计文档与实现一致。 | +| 3 | 继续对α版本前后端进行联调 | 进行中 | 基于上周部署的RUOYI前端,本周持续参与接口联调的设计开发 | +| 4 | 参与后端应用云端部署 | 完成 | 协助后端组完成RUOYI应用在阿里云ECS服务器上的Jar包部署、Nginx反向代理配置及服务启动验证 | + +## 对团队工作的建议 + +1. **建立部署检查清单:**建议为云端部署(包括RDS、ECS、Nginx等)建立标准化的检查清单,涵盖网络、安全、服务状态等维度,以减少人为失误,确保每次部署的一致性。 +2. **引入接口契约测试:**在后续迭代中,建议引入基于OpenAPI Spec的契约测试工具,将接口文档作为“唯一可信源”,在联调前自动化验证前后端对接口的理解是否一致,提前发现问题。 +3. **明确文档更新责任人:**建议为关键设计图(如活动图、顺序图)指定明确的更新责任人和更新触发条件(如接口变更、流程调整),确保文档与代码同步。 + +## 小结 + +1. **全栈实践能力突破:**本周技术实践从应用层延伸至基础设施层,完整经历了从本地开发到云上部署的全流程,对现代Web应用的部署架构和运维要点有了切身体会。 +2. **全链路调试能力提升:**在前后端联调实践中,深入了解了从前端发起到后端处理、数据库操作的全链路数据流转,提升了综合问题定位与解决能力。 +3. **问题定位能力进阶:**在解决云端部署后应用无法外网访问的问题时,通过系统性地排查安全组规则、服务器防火墙、Nginx配置和应用本身端口绑定,锻炼了跨层级的复杂问题定位能力。 +4. **协作沟通价值凸显:**在解决联调问题的过程中,与前端、后端同学的紧密沟通是成功的关键,深刻体会到清晰、及时的沟通在团队开发中的核心价值。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-11/members/yangjie-weekly-plan-11.md b/doc/process/weekly/week-11/members/yangjie-weekly-plan-11.md new file mode 100644 index 0000000..24591e6 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangjie-weekly-plan-11.md @@ -0,0 +1,28 @@ +# 个人周计划-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | 核心业务接口深度联调 | 前端组 | 2025-12-01,聚焦登录认证、设备数据上报、水质历史查询等核心接口,验证参数规范与数据一致性 | +| 2 | 本地RUOYI数据库完整备份与导出 | 个人 | 2025-12-02,执行数据库全量备份,导出结构化SQL文件,并记录数据版本与关键状态点 | +| 3 | 阿里云服务器MySQL环境部署与安全配置 | 后端组 | 2025-12-03,在阿里云ECS上安装MySQL 8.0,配置安全组、访问白名单、数据库账号与权限策略 | +| 4 | Docker环境部署与RUOYI容器化配置 | 后端组 | 2025-12-04,安装并配置Docker及Docker Compose,编写RUOYI后端服务的Dockerfile与运行脚本 | +| 5 | 数据库云端迁移与远程连接调通 | 后端组 | 2025-12-05,将本地SQL导入云数据库,配置Spring Boot数据源,测试远程连接性能与稳定性 | +| 6 | 联调问题追踪与后端修复 | 全体成员 | 2025-12-06,整理并归类联调中出现的后端问题,配合完成代码修复与验证 | + +## 小结 + +1. **联调重点突出:** 确保核心业务接口在真实数据流中稳定、可靠,形成可复用的接口调试流程; +2. **云端迁移实战:** 完成从本地开发环境到阿里云生产-like环境的数据库迁移,掌握云端MySQL与Docker化部署的关键步骤; +3. **安全与连接保障:** 重视云端数据库的安全配置与网络连接稳定性,确保后续联调与测试不受环境因素干扰; +4. **问题驱动修复:** 通过联调主动发现问题、记录问题、解决问题,形成闭环管理; +5. **文档持续同步:** 保持设计文档、部署文档与系统实际状态的一致性,为项目交付与维护提供可靠依据; +6. **技术支持期待:** 希望老师重点指导云端数据库安全最佳实践、Docker容器编排常见问题排查,以及生产环境联调的组织方法。 \ No newline at end of file diff --git a/doc/process/weekly/week-11/members/yangjie-weekly-summary-11.md b/doc/process/weekly/week-11/members/yangjie-weekly-summary-11.md new file mode 100644 index 0000000..4537113 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangjie-weekly-summary-11.md @@ -0,0 +1,34 @@ +# 个人周总结-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 核心业务接口深度联调 | 完成 | 完成登录、设备上报、水质查询等核心接口的联调测试,接口响应与数据格式已统一 | +| 2 | 本地RUOYI数据库备份与导出 | 完成 | 完成本地数据库全量备份并导出SQL文件,数据完整性与一致性已校验 | +| 3 | 阿里云服务器MySQL环境部署与安全配置 | 完成 | 在阿里云ECS成功安装MySQL 8.0,完成安全组、访问策略与账号权限配置 | +| 4 | Docker环境部署与RUOYI容器化配置 | 完成 | 完成Docker及Docker Compose安装,编写RUOYI后端Docker运行配置 | +| 5 | 数据库云端迁移与远程连接调通 | 完成 | 成功导入数据至云端MySQL,远程连接测试通过,数据源配置正常 | +| 6 | 联调问题追踪与后端修复 | 部分完成 | 整理并协助修复多个接口问题,剩余部分性能优化持续进行 | + +## 对团队工作的建议 + +1. **部署流程规范化:** 建议编写云端部署标准化操作手册,包含环境检查、步骤说明与回滚方案; +2. **联调问题分类管理:** 建议建立联调问题分类标签与优先级机制,提升问题解决效率; +3. **环境一致性保障:** 建议统一开发、测试与云端环境的基础配置,减少环境差异导致的问题。 + +## 小结 + +1. **技术实践能力提升:** 通过完成数据库云端迁移与Docker化部署,掌握了生产环境部署的基本流程与常见问题处理方法; +2. **联调协作经验积累:** 在持续联调中进一步熟悉前后端协作模式,提升了问题定位与协作修复效率; +3. **安全意识增强:** 在云端环境配置中注重安全策略设置,理解了生产环境安全防护的基本要点; +4. **文档同步意识强化:** 保持设计文档与实际系统同步更新,为项目可维护性打下基础; +5. **后续重点方向:** 需继续关注接口性能优化与系统稳定性提升,进一步完善容器化部署与监控方案; +6. **希望获得的帮助:** 期待老师在云端数据库运维监控、Docker容器编排优化方面提供进一步指导。 \ No newline at end of file diff --git a/doc/process/weekly/week-11/members/yangmohan-weekly-plan-11.md b/doc/process/weekly/week-11/members/yangmohan-weekly-plan-11.md new file mode 100644 index 0000000..c7962b0 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangmohan-weekly-plan-11.md @@ -0,0 +1,24 @@ +# 个人周计划-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-1 +**结束时间:** 2025-12-7 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | ---------------------------------------------- | ------ | -------- | +| 1 | 调整云端服务器各项配置以支持本地数据库接入 | 个人 | 完成云端服务器环境检查与配置优化,包括网络访问控制、端口开放、数据库连接参数及安全相关配置,确保本地数据库能够稳定、安全地接入云端服务 | +| 2 | 编写α版本开发进度文档 | 个人 | 梳理当前α版本功能实现情况,统计完成度与待开发模块,撰写进度说明文档并同步至团队,便于项目成员统一了解当前迭代阶段性成果 | +| 3 | 作为后端人员继续进行前后端联调测试 | 团队 | 继续与前端开发人员协作完成系统联调测试,针对已有接口进行回归测试并覆盖新增接口,定位并修复数据交互及逻辑问题,保障系统整体功能稳定性 | + +## 小结 + +1. **云端环境与数据库接入准备:** 完成云端服务器环境的核查与关键配置调整,确保本地数据库能够安全、稳定地接入并被云端服务正常访问; +2. **α版本进度梳理与文档输出:** 通过编写α版本开发进度文档,系统性梳理当前功能实现情况与剩余工作量,为团队后续迭代提供参考依据; +3. **持续联调与问题修复:** 以后端角色持续参与前后端联调测试,针对接口交互中暴露的问题进行排查和修复,提升系统整体稳定性与用户体验。 + +--- diff --git a/doc/process/weekly/week-11/members/yangmohan-weekly-summary-11.md b/doc/process/weekly/week-11/members/yangmohan-weekly-summary-11.md new file mode 100644 index 0000000..1217c5e --- /dev/null +++ b/doc/process/weekly/week-11/members/yangmohan-weekly-summary-11.md @@ -0,0 +1,30 @@ + +# 个人周总结-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-1 +**结束时间:** 2025-12-7 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | 调整云端服务器各项配置以支持本地数据库接入 | 完成 | 完成数据库的云端部署工作,成功将RUOYI系统连接到云端数据库,并对RUOYI所有功能进行了全面测试,确保系统在云端环境下可正常使用 | +|2 | 编写α版本开发进度文档 | 完成 | 完成了α版本开发进度文档的编写工作,系统梳理了当前版本的功能实现情况、完成度与待开发模块,为团队了解项目迭代进度提供了清晰的参考依据 | +|3 | 学习nginx使用方法为云端部署web端做准备 | 完成 | 深入学习并掌握了nginx的使用方法,包括配置、反向代理、负载均衡等核心功能,为后续在云端部署web端应用做好了技术储备 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **数据库云端部署与系统迁移:** 成功完成数据库的云端部署工作,并将RUOYI系统成功连接到云端数据库,通过全面功能测试验证了系统在云端环境下的稳定性和可用性,为项目的云端化部署奠定了坚实基础; +2. **项目进度文档化:** 完成α版本开发进度文档的编写,系统梳理了当前版本的功能实现情况与开发进度,为团队统一了解项目迭代状态和后续规划提供了重要参考; +3. **技术储备与前瞻性准备:** 深入学习并掌握了nginx的使用方法,为后续在云端部署web端应用做好了充分的技术准备,提升了团队在云端服务部署方面的技术能力; + +--- diff --git a/doc/process/weekly/week-11/members/yangshuailu-weekly-plan-11.md b/doc/process/weekly/week-11/members/yangshuailu-weekly-plan-11.md new file mode 100644 index 0000000..658baf3 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangshuailu-weekly-plan-11.md @@ -0,0 +1,33 @@ +# 个人周计划-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-12-1 + +**结束时间:** 2025-12-7 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ----------------- | --- | ------------------------------------------------ | +| 1 | 将本地RUOYI数据库迁移至阿里云 | 组员 | 将本地服务器部署至云端,创建好阿里云服务器 | +| 2 | 补充和修正现有模型 | 组员 | 结合发现的问题完善用例模型 | +| 3 | 对α版本的前后端进行联调 | 组员 | 继续和前端成员一起进行前后端接口联调,确保数据交互正常,修复接口对接中的问题,完成上周未完成内容 | + +## 小结 + +1. **技术支持需求**:希望获取阿里云数据库迁移的最佳实践文档,特别是 RUOYI 框架适配云端数据库的配置要点 +2. **进度保障:** 每日同步任务进展至后端组群,及时解决学习和设计中遇到的技术卡点。 +3. **资源协调**: + * 需确认阿里云服务器的配置权限分配,确保组员能顺利访问云端数据库进行开发测试 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-11/members/yangshuailu-weekly-summary-11.md b/doc/process/weekly/week-11/members/yangshuailu-weekly-summary-11.md new file mode 100644 index 0000000..9d00cfe --- /dev/null +++ b/doc/process/weekly/week-11/members/yangshuailu-weekly-summary-11.md @@ -0,0 +1,37 @@ +# 个人周总结-第十一周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-12-1 + +**结束时间:** 2025-12-7 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ----------------- | ---- | ------------------------------------------------ | +| 1 | 将本地RUOYI数据库迁移至阿里云 | 完成 | 将本地服务器部署至云端,创建好阿里云服务器,已经能通过云服务器对数据库进行增删查改。 | +| 2 | 补充和修正现有模型 | 完成 | 结合上周联调和数据库实装中发现的问题,对用例模型进行了补充和修正,完善了模型细节 | +| 3 | 对α版本的前后端进行联调 | 部分完成 | 与前端成员协作完成了上周未完成的前后端接口联调工作,修复了接口对接中的几处问题,确保数据交互正常 | + +## 对团队工作的建议 + +1. **完善文档管理:** 建议将本次阿里云数据库迁移的操作步骤和配置要点整理成文档,存入团队共享知识库,方便后续查阅和新人上手。 +2. **方案评审:** 对于核心技术方案,可组织简短的内部评审会,集思广益优化方案细节。 + +## 小结 + +1. **技能提升**:掌握了阿里云数据库的部署与迁移方法,熟悉了 RUOYI 框架适配云端数据库的配置流程。 +2. **问题解决**:解决了数据库迁移过程中的连接超时和权限不足问题,以及联调中接口数据格式不匹配的问题。 +3. **帮助需求**:希望学习关于系统 α 版本测试的方法和工具使用,以保障后续版本质量 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-11/members/yangzy-weekly-plan-11.md b/doc/process/weekly/week-11/members/yangzy-weekly-plan-11.md new file mode 100644 index 0000000..af4f848 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangzy-weekly-plan-11.md @@ -0,0 +1,25 @@ +# 个人周计划-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-12-02 继续进行Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 继续对α版本前后端进行联调 | 组员 | 2025-12-04 重点检查主要业务流程的接口调用情况,保证接口参数、返回值和状态码一致,发现问题及时记录和修复,确保核心功能接口能稳定、正常运作 | +| 3 | 继续系统总用例图编写 | 组员 | 2025-12-06 对已经完成的顺序图稍作优化,并和组内的同学进行整合 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-11/members/yangzy-weekly-summary-11.md b/doc/process/weekly/week-11/members/yangzy-weekly-summary-11.md new file mode 100644 index 0000000..56f4991 --- /dev/null +++ b/doc/process/weekly/week-11/members/yangzy-weekly-summary-11.md @@ -0,0 +1,31 @@ +# 个人周总结-第11周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-01 +**结束时间:** 2025-12-07 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-12-02 继续进行了Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 继续对α版本前后端进行联调 | 完成 | 2025-12-04 重点检查主要业务流程的接口调用情况,保证接口参数、返回值和状态码一致,发现问题及时记录和修复,确保核心功能接口能稳定、正常运作 | +| 3 | 继续系统总用例图编写 | 完成 | 2025-12-06 已完成了小组项目的顺序图绘制,并与小组同学进行了对接 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-12/group/meeting-minutes-12.md b/doc/process/weekly/week-12/group/meeting-minutes-12.md new file mode 100644 index 0000000..fb6c0c4 --- /dev/null +++ b/doc/process/weekly/week-12/group/meeting-minutes-12.md @@ -0,0 +1,106 @@ +# 小组会议纪要-第12周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** API接口文档专项评审与交付前技术对齐 +**会议地点:** 腾讯会议 +**会议时间:** 2025-12-14 15:00-16:00 +**纪录时间:** 2025-12-14 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 +本次会议聚焦于已完成的《小程序API接口使用文档》进行专项评审,确保技术实现与接口文档完全对齐,为项目验收和后续开发奠定标准基础。会议对文档的组织架构、具体内容和实践应用进行了逐项审议,并就优化方向达成共识。 + +### 1. API文档结构与内容评审 + + +**(1) 架构认可与优点确认:​​** + +- 模块化结构清晰:全体成员确认,按照业务域划分的8个独立API文件(auth.js、device.js等)结构合理,利于维护和分工。 +- 统一入口设计:index.js 统一导出API的设计,为开发者提供了简洁的调用入口(import * as api),一致认为是良好实践。 +- 文档完整性:文档包含了从快速开始、详细说明到高级用法的完整路径,并配有Vue 3两种风格的代码示例,能够满足不同层次开发者的需求。 + +**(​2) 核心接口功能的交叉验证:​** + +- 认证流程(auth.js):后端组确认,文档中 userLogin 和 staffLogin 的参数、返回字段与实际接口完全一致。文档中关于Token“自动管理”的描述准确反映了 request.js 中的封装逻辑。 +- 订单与支付流程(order.js):前端组演示了根据文档调用 createOrder 和 payOrder 的流程,成功触发了后端的订单创建与支付状态更新。双方确认参数对齐,是本次评审的重点成果。 +- 员工端工作流(staff.js):重点评审了 acceptWorkorder 和 completeWorkorder 接口。前端与后端当场模拟了接单到完成的完整流程,确认参数 images(图片数组)的传递与接收无误。 + +**(​3) “高级用法”部分的技术确认:​** + +- 自定义请求配置:确认 showLoading、needAuth 等选项在 utils/request.js 中已实现,功能有效。 +- 错误与Token管理:确认全局错误处理逻辑符合文档描述,Token的获取、设置和清除方法工作正常。 + + +### 2. 问题反馈与即时优化决议 + +**(1)即时修改项:** +- 修正函数名:product.js 模块中示例代码的函数名与导出名存在笔误,需修正为 getProductList。 +- 补充重要说明:在“快速开始”部分,增加关于 request.js 基础路径(baseUrl)配置的提示,告知开发者部署后需根据实际服务器地址进行修改。 +- 明确参数类型:在 order.js 的 createOrder 示例中,明确 appointmentTime 等时间字段的字符串格式建议(如“HH:mm”)。 + +**(2)会后补充项:** +- 补充错误码附录:决议在文档末尾或独立文件中,增加一个由后端提供的 全局错误码对照表,方便前端调试。 +- 补充“分页参数”说明:在 getDeviceList、getOrderList 等列表接口的说明中,统一补充关于 pageNum、pageSize 等分页参数的使用示例。 + +### 3. 文档与代码同步的维护机制确立: + +- “文档即合约”原则:README.md 中的API签名(函数名、参数、返回示例)被视为前后端约定的“合约”。任何一方需要变更时,必须先同步更新此文档,并经对方确认。 +- 版本关联:在文档标题处增加“对应代码版本”标识,例如“(对应Git提交:a1b2c3d)”,便于追溯。 +- 责任人:API接口的初始开发者负责其对应模块文档的首次编写与核心维护;PM(杨默涵)负责督促文档的全局同步更新。 + + + + +## 问题总结 + +### 已解决问题: +1. API对齐与验证:通过本次专项评审,所有核心业务接口在文档与实现层面达成一致,消除了潜在的联调隐患。 +2. 文档质量提升:发现了若干处笔误与不明确点,并制定了明确的修订方案,提升了文档的准确性和可用性。 +3. 维护流程确立:建立了以 README.md 为“单一事实来源”的API维护机制,为后续迭代开发确立了标准流程。 + +### 待解决问题: +1. 文档修订落实:需在24小时内完成会议上确认的所有文档修改,并由PM进行复核。 +2. 错误码文档化:后端组需在周一(12月16日)前提供完整的错误码列表,由PM整合至文档中。 +3. 验收演示脚本编写:需基于这份最终确认的API文档,编写阿尔法版本验收的功能演示脚本,确保演示覆盖所有关键流程。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** +本次会议采取“前端演示 + 后端确认”的务实评审方式,沟通直接高效,技术讨论深入,有效解决了文档与代码的“最后一公里”对齐问题。 + +2. **分工明确:** + +文档修订:由各API模块的初始负责人(前端组)根据会议决议立即执行。 +流程监督与复核:PM负责。 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 后端部署是当前最关键的任务,务必优先完成,以便为后续所有测试提供基础。 +2. 在对接支付功能时,需特别注意测试环境与数据的安全,避免使用真实支付信息。 +3. 软著申请流程和材料要求较为专业,建议尽早查阅官方指南或寻求指导。 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-12/group/weekly-plan-12.md b/doc/process/weekly/week-12/group/weekly-plan-12.md new file mode 100644 index 0000000..23a31fb --- /dev/null +++ b/doc/process/weekly/week-12/group/weekly-plan-12.md @@ -0,0 +1,34 @@ +# 小组周计划-第12周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 编写阿尔法迭代核心业务模型图 | 全体成员 | 针对已开发并验证的核心业务,使用工具(如PlantUML)编写最终版的活动图、顺序图和核心类图,确保文档与实现完全一致,为项目归档和软著申请提供材料。 | +| 2 | 实现后端代码的云端部署与发布 | 后端组 | 将当前通过联调验证的后端代码(RUOYI项目)进行生产环境配置打包,部署至阿里云ECS服务器,并完成Nginx反向代理、域名(或IP)绑定及服务启动验证,形成稳定、可外部访问的生产环境。 | +| 3 | 编写并实现新增前端接口 | 前端组 | 根据与后端的最终联调结果,完成前端API接口的标准化封装与设计文档编写。同时,开发实现与新增或优化功能相关的前端界面与交互逻辑。 | +| 4 | 使用APIFox完成系统接口测试 | 全体成员 | 利用APIFox平台,基于已部署的后端服务,对所有线上接口进行全面的功能测试、参数边界测试及异常场景测试,生成测试报告,并修复测试过程中发现的缺陷,确保接口健壮性。 | +| 5 | 完成阿尔法版本最终开发进度文档 | PM及各小组负责人 | 汇总本迭代周期内所有完成的功能模块、技术文档、测试报告、部署说明及已知问题,整理形成完整的《阿尔法(α)版本开发总结报告》 | + +## 小结 + +1. **模型固化与文档收官:**通过绘制最终版的核心业务模型图(活动图、顺序图、类图),完成从需求到设计再到实现的完整追溯,形成项目核心资产,为后续维护、升级及软著申请奠定坚实基础。 +2. **生产环境部署落地:**完成后端代码从开发环境到云端生产环境的正式部署,是项目从“可运行”迈向“可服务”的关键一步,为最终演示、测试及交付提供了真实运行环境。 +3. **前端功能完善与接口标准化:**在确保核心流程稳定的基础上,完善前端交互细节与新增功能,并对所有接口进行标准化封装,提升前端代码的可维护性和开发效率。 +4. **全面的线上接口测试:**利用专业工具APIFox对线上接口进行系统化测试,提前发现并修复生产环境下可能出现的接口问题,是保障版本质量、降低交付风险的必要环节。 +5. **版本交付物整理与总结:**编制完整的阿尔法版本总结文档,是对整个迭代周期工作的系统梳理和成果固化,为项目阶段性验收、团队复盘及后续Beta版规划提供清晰依据。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-12/group/weekly-summary-12.md b/doc/process/weekly/week-12/group/weekly-summary-12.md new file mode 100644 index 0000000..0fd04d1 --- /dev/null +++ b/doc/process/weekly/week-12/group/weekly-summary-12.md @@ -0,0 +1,32 @@ +# 小组周总结-第12周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 阿尔法核心模型归档 | 完成 | 依据实际代码与接口记录,更新并锁定活动图/顺序图/类图;完成版本归档并用于软著材料准备。 | +| 2 | 后端云端部署与访问验证 | 完成 | 后端组完成RUOYI后端打包上线至阿里云ECS,配置Nginx反向代理与域名/IP访问,服务启动验证通过,提供稳定外部访问。 | +| 3 | 新增前端接口与交互优化 | 完成 | 补全最终联调接口封装并落地页面,完善相关页面交互与异常提示,接口文档同步更新。 | +| 4 | APIFox 全量接口测试与修复 | 完成 | 基于线上环境在APIFox执行功能/边界/异常用例,输出测试报告并修复发现的参数校验与权限配置问题,复测通过。 | +| 5 | 阿尔法版本总结报告产出 | 完成 | 汇总功能完成度、测试结论、部署清单和已知问题,归档为《阿尔法版本开发总结报告》,同步至仓库。 | + +## 小结 + +1. 核心模型与文档收官:设计产物与实现完全对齐,形成可追溯的活动图、顺序图和类图,为后续维护和软著申报奠定基础。 +2. 云端生产环境落地:ECS+Nginx部署稳定可访,支撑后续演示、线上测试及外部验收。 +3. 前后端一致性提升:新增接口标准化封装并同步文档,前端交互与异常处理完善,降低维护成本。 +4. 质量闭环完成:APIFox覆盖全量接口并完成缺陷修复与复测,产出报告支撑版本交付。 +5. 版本资产整理:阿尔法版本总结报告归档,明确已交付功能与遗留问题,为Beta规划提供依据。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-12/members/liangchenxv-weekly-plan-12.md b/doc/process/weekly/week-12/members/liangchenxv-weekly-plan-12.md new file mode 100644 index 0000000..614d724 --- /dev/null +++ b/doc/process/weekly/week-12/members/liangchenxv-weekly-plan-12.md @@ -0,0 +1,35 @@ +# 个人周计划-第12周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 协助完成后端代码的云端部署与发布 | 个人 | 协助进行生产环境配置文件的检查与打包,参与部署脚本编写、服务启动验证及基础监控配置,学习生产环境运维流程。 | +| 2 | 参与前端接口的设计开发 | 个人 | 根据与后端的最终联调结果,参与完成前端API接口的标准化封装与设计文档编写 +| 3 | 使用APIFox完成负责模块的接口测试 | 个人 | 针对个人主要负责的模块,在APIFox中创建测试用例集,完成功能、异常及边界测试,记录并跟踪缺陷,生成模块测试报告。 | +| 4 | 参与阿尔法版本验收材料准备 | 个人 | 配合PM要求,提供个人工作成果、测试报告及文档,参与《阿尔法版本开发总结报告》中相关部分的材料整理与核对。 + + + +## 小结 + +1. **深化联调实践:**通过持续参与核心接口联调,进一步巩固前后端数据交互的调试技能,提升定位和解决复杂接口问题的能力。 +2. **学习云端部署:**通过实践数据库迁移与阿里云环境搭建,学习生产环境下的服务部署、配置与安全管理知识,拓宽技术视野。 +3. **掌握生产部署实践:**通过参与后端代码的生产环境部署,深入学习从开发到上线的完整流水线、环境配置管理与基础运维技能,完成从开发者到“交付者”视角的拓展。 +4. **建立接口质量意识:**通过系统化使用APIFox进行测试,不仅验证功能,更学习如何设计测试用例以保证接口的健壮性和可靠性,培养质量保障思维。 +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-12/members/liangchenxv-weekly-summary-12.md b/doc/process/weekly/week-12/members/liangchenxv-weekly-summary-12.md new file mode 100644 index 0000000..e35648c --- /dev/null +++ b/doc/process/weekly/week-12/members/liangchenxv-weekly-summary-12.md @@ -0,0 +1,41 @@ + +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 协助后端云端部署与发布 | 完成 | 参与检查生产配置、打包并编写部署脚本,协助完成ECS+Nginx上线与服务启动验证;处理时区与反代缓存问题,监控首日运行稳定。 | +| 2 | 参与前端接口设计与开发 | 进行中 | 根据最终联调结果补全接口封装与文档,优化异常提示与重试策略;确认与后端字段对齐,避免再次联调回退。 | +| 3 | 使用APIFox完成负责模块接口测试 | 完成 | 为负责模块编制用例并执行功能/边界/异常测试,发现并推动修复2个参数校验与1个权限配置问题,复测通过。 | +| 4 | 参与阿尔法版本验收材料准备 | 完成 | 提交个人模块测试报告与接口文档,协助核对《阿尔法版本开发总结报告》中前端与测试章节内容,确保与线上实现一致。 | + +## 对团队工作的建议 + +1. **部署与监控模板化:**沉淀ECS/Nginx/时区/防火墙的标准检查清单,附首发监控项,减少环境差异导致的回归。 +2. **接口契约前置校验:**在联调前用OpenAPI契约测试快速比对字段与响应码,避免反复回退。 +3. **测试用例复用:**将APIFox用例按模块沉淀为回归集,绑定环境变量,供后续版本快速复测。 + +## 小结 + +1. 交付闭环实践:首次完整走通“配置检查-部署脚本-上线验证-监控跟踪”,对生产可用性要求有更直观的认识。 +2. 接口一致性意识提升:前端封装和APIFox用例共同校验字段与错误码,减少了联调返工。 +3. 质量与文档同步:测试报告、接口文档与总结报告同步更新,后续可直接复用到Beta规划与对外交付。 +4. 协作效率提升:与后端、测试的日常同步频率提升,问题发现到修复再到复测的周期明显缩短。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-12/members/yangjie-weekly-plan-12.md b/doc/process/weekly/week-12/members/yangjie-weekly-plan-12.md new file mode 100644 index 0000000..0cb72e5 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangjie-weekly-plan-12.md @@ -0,0 +1,28 @@ +# 个人周计划-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | 参与编写核心业务模型图 | 全体成员 | 2025-12-08,基于已实现的核心业务流程(如设备数据上报、水质告警),使用工具绘制最终版顺序图与核心类图,确保图文一致 | +| 2 | 后端代码生产环境配置与打包 | 后端组 | 2025-12-09,调整RUOYI项目配置为生产模式,完成Maven打包,生成可部署的JAR包 | +| 3 | 阿里云ECS后端服务部署与启动 | 后端组 | 2025-12-10,将JAR包部署至云端服务器,配置启动脚本与日志目录,验证服务正常启动 | +| 4 | Nginx反向代理配置与域名绑定 | 后端组 | 2025-12-11,配置Nginx实现端口的反向代理与负载均衡,绑定域名(或IP+端口)实现外网访问 | +| 5 | 使用APIFox进行线上接口测试 | 全体成员 | 2025-12-12,基于已部署的后端服务,在APIFox中对所有线上接口进行功能、异常与性能测试 | +| 6 | 测试问题修复与部署优化 | 后端组 | 2025-12-13,针对测试中发现的接口或部署问题,及时修复并重新部署验证 | +| 7 | 协助整理后端部署与测试报告 | PM | 2025-12-14,汇总部署步骤、配置说明与测试结果,协助完成《α版本开发总结报告》中后端部分 | + +## 小结 + +1. **模型固化与追溯:** 通过绘制最终版业务模型图,形成可追溯的设计资产,支持项目归档与后续维护; +2. **生产部署实战:** 完成后端代码从开发到生产的全流程部署,掌握生产环境配置、服务发布与网络代理配置; +3. **线上质量保障:** 通过APIFox对线上接口进行全面测试,确保接口在生产环境下的健壮性与稳定性; +4. **文档闭环整理:** 配合完成版本总结报告,确保部署与测试过程被完整记录,形成项目交付物; +5. **学习与支持需求:** 希望老师在Nginx高性能配置、生产环境日志收集与监控方面提供指导,并分享接口压力测试的常见方法与工具使用技巧。 \ No newline at end of file diff --git a/doc/process/weekly/week-12/members/yangjie-weekly-summary-12.md b/doc/process/weekly/week-12/members/yangjie-weekly-summary-12.md new file mode 100644 index 0000000..ace4390 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangjie-weekly-summary-12.md @@ -0,0 +1,35 @@ +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 参与编写核心业务模型图 | 完成 | 负责绘制部分核心业务的最终版顺序图,并与后端实际代码逻辑进行了核对验证 | +| 2 | 后端代码生产环境配置与打包 | 完成 | 完成了项目生产环境配置的调整,并成功打包生成可用于生产部署的发布包 | +| 3 | 阿里云ECS后端服务部署与启动 | 完成 | 将应用程序部署至云服务器,配置了服务启动项,并已验证服务在云端正常运行 | +| 4 | Nginx反向代理配置与域名绑定 | 完成 | 配置了Nginx反向代理规则,完成了服务与域名的绑定,实现了通过外网安全访问 | +| 5 | 使用APIFox进行线上接口测试 | 完成 | 利用APIFox对所有已上线的接口进行了全面的功能、异常及性能测试,并记录了测试结果 | +| 6 | 测试问题修复与部署优化 | 部分完成 | 根据测试报告修复了已发现的关键问题,并对部署脚本进行了初步优化,部分优化项仍在进行 | +| 7 | 协助整理后端部署与测试报告 | 完成 | 协助整理了后端的部署流程文档和接口测试总结,为项目最终报告提供了必要的材料 | + +## 对团队工作的建议 + +1. **部署流程标准化:** 建议将本次生产部署的步骤、配置和注意事项整理为标准操作程序(SOP),方便后续迭代和团队新成员快速上手。 +2. **建立线上监控基线:** 建议在服务上线后,尽快建立对应用服务状态、关键接口响应和服务器资源的基础监控,以便及时发现潜在问题。 +3. **接口测试资产沉淀:** 建议将在APIFox中创建的接口测试用例和环境配置纳入版本库管理,形成可回归测试的资产,提高后续测试效率。 + +## 小结 + +1. **获得完整项目交付经验:** 本周参与了从代码到生产环境上线的完整闭环,深刻理解了部署、配置与测试在项目交付中的关键作用。 +2. **运维与测试技能得到实践:** 通过实际操作Nginx配置、APIFox测试等环节,提升了在生产环境下保障系统稳定性的实践能力。 +3. **质量与协作意识强化:** 线上测试暴露的问题促使我们更关注代码的健壮性,而协同修复问题的过程也进一步强化了团队协作的重要性。 +4. **认识到文档的长期价值:** 在整理部署和测试文档的过程中,体会到清晰、可追溯的文档对于项目维护和知识传承的不可或缺性。 +5. **明确了后续学习方向:** 认识到在服务器性能优化、容器化部署以及自动化运维监控方面仍有深入学习的空间。 +6. **项目里程碑达成:** α版本的成功部署与测试标志着项目取得了重要的阶段性成果,为后续的演示、验收和功能迭代奠定了坚实的基础。 \ No newline at end of file diff --git a/doc/process/weekly/week-12/members/yangmohan-weekly-plan-12.md b/doc/process/weekly/week-12/members/yangmohan-weekly-plan-12.md new file mode 100644 index 0000000..3285ed7 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangmohan-weekly-plan-12.md @@ -0,0 +1,25 @@ + # 个人周计划-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-8 +**结束时间:** 2025-12-14 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | ---------------------------------------------- | ------ | -------- | +| 1 | 将RUOYI平台的前后端部署到云端 | 个人 | 完成RUOYI平台前后端代码在云端服务器的部署工作,包括环境配置、依赖安装、服务启动等步骤,确保系统能够在云端环境正常运行 | +| 2 | 实现通过公网IP地址访问RUOYI平台 | 个人 | 配置nginx反向代理和防火墙规则,实现通过公网IP地址访问已部署的RUOYI平台,确保外部用户能够正常访问系统 | +| 3 | 优化RUOYI前端样式,改为数智水管家系统 | 个人 | 对RUOYI前端界面进行样式优化和品牌化改造,将系统名称、logo、主题色彩等元素调整为"数智水管家"系统风格,提升系统专业性和用户体验 | +| 4 | 完成后端接口实现,并使用apifox进行测试 | 个人 | 完成系统所需的后端接口开发工作,并使用apifox工具对所有接口进行功能测试、参数验证和响应测试,确保接口的稳定性和正确性 | + +## 小结 + +1. **云端部署与公网访问实现:** 完成RUOYI平台前后端在云端服务器的部署工作,并配置相关网络服务实现通过公网IP地址访问系统,为项目的云端化运行和外部访问提供基础支撑; +2. **系统品牌化与界面优化:** 对RUOYI前端进行样式优化和品牌化改造,将系统调整为"数智水管家"系统风格,提升系统的专业形象和用户识别度; +3. **接口开发与测试验证:** 完成后端接口的开发实现工作,并使用apifox工具进行全面的接口测试,确保接口功能的正确性和稳定性,为前后端联调提供可靠保障。 + +--- diff --git a/doc/process/weekly/week-12/members/yangmohan-weekly-summary-12.md b/doc/process/weekly/week-12/members/yangmohan-weekly-summary-12.md new file mode 100644 index 0000000..1f27de4 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangmohan-weekly-summary-12.md @@ -0,0 +1,32 @@ + +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-8 +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | 在云端部署web端的前后端 | 完成 | 成功完成web端前后端的云端部署工作,实现了通过公网IP访问后台管理系统,为项目的云端化部署奠定了坚实基础 | +|2 | 将web端前端风格样式改为数智水管家类型 | 完成 | 完成了web端前端风格样式的改造工作,将界面风格统一调整为数智水管家类型,提升了用户界面的专业性和一致性 | +|3 | 在apifox测试后端接口并修复bug | 完成 | 在apifox平台上对所有后端接口进行了全面测试,成功跑通所有接口,并修复了登录功能中密码传递接口的bug,确保了系统功能的稳定性和安全性 | +|4 | 修改服务器协议从http改为https | 完成 | 将服务器协议从http升级为https,以满足微信小程序的限制要求,提升了系统的安全性和兼容性,为后续小程序接入做好了准备 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **web端云端部署完成:** 成功完成web端前后端的云端部署工作,实现了通过公网IP访问后台管理系统,为项目的云端化部署奠定了坚实基础,提升了系统的可访问性和实用性; +2. **前端界面风格优化:** 完成了web端前端风格样式的改造工作,将界面风格统一调整为数智水管家类型,提升了用户界面的专业性和一致性,改善了用户体验; +3. **接口测试与bug修复:** 在apifox平台上对所有后端接口进行了全面测试,成功跑通所有接口,并修复了登录功能中密码传递接口的bug,确保了系统功能的稳定性和安全性; +4. **协议升级与安全加固:** 将服务器协议从http升级为https,以满足微信小程序的限制要求,提升了系统的安全性和兼容性,为后续小程序接入做好了技术准备; + +--- diff --git a/doc/process/weekly/week-12/members/yangshuailu-weekly-plan-12.md b/doc/process/weekly/week-12/members/yangshuailu-weekly-plan-12.md new file mode 100644 index 0000000..007428b --- /dev/null +++ b/doc/process/weekly/week-12/members/yangshuailu-weekly-plan-12.md @@ -0,0 +1,32 @@ +# 个人周计划-第十二周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-12-08 + +**结束时间:** 2025-12-14 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ---------------- | --- | ------------------------------------------------- | +| 1 | 编写α迭代核心业务模型图 | 组员 | 和小组成员一起,针对已完成的α版本完成业务模型图 | +| 2 | 实现后端代码的云端部署与发布 | 组员 | 参与后端代码生产环境配置打包,配合进行Nginx反向代理及服务启动验证,保障后端服务稳定可外部访问 | +| 3 | 使用APIFox完成系统接口测试 | 组员 | 和杨捷同学利用APIFox平台,基于已部署的后端服务,对所有线上接口进行全面测试,并生成测试报告 | + +## 小结 + +1. **技术支持需求**:协调APIFox测试所需的接口文档和测试账号,保障接口测试正常开展。 +2. **进度保障:** 每日同步任务进展至后端组群,及时解决学习和设计中遇到的技术卡点。 +3. **资源协调**:需确认阿里云服务器的配置权限分配,确保组员能顺利访问云端数据库进行开发测试 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-12/members/yangshuailu-weekly-summary-12.md b/doc/process/weekly/week-12/members/yangshuailu-weekly-summary-12.md new file mode 100644 index 0000000..66f18e0 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangshuailu-weekly-summary-12.md @@ -0,0 +1,38 @@ +# 个人周总结-第十二周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-12-8 + +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ---------------- | ---- | ----------------------------------------------------------------------- | +| 1 | 编写α迭代核心业务模型图 | 完成 | 与小组成员分工协作,梳理 α 版本核心业务逻辑,结合已实现功能和业务场景,绘制完成结构化业务模型图,经组员评审后确认无逻辑漏洞 | +| 2 | 实现后端代码的云端部署与发布 | 完成 | 参与后端代码生产环境配置打包,配合完成 Nginx 反向代理配置、端口映射及服务启动验证,通过多轮测试确认后端服务稳定运行,可正常对外提供访问 | +| 3 | 使用APIFox完成系统接口测试 | 完成 | 和杨捷同学利用APIFox平台,对接口完成了测试,发现没有问题,并生成了测试报告 | + +## 对团队工作的建议 + +1. **业务模型图管理:** 建议将本次编写的 α 迭代核心业务模型图更新至团队共享知识库,并建立版本管理机制,后续业务迭代时同步更新,便于团队成员统一认知。 +2. **部署流程优化:** 可将云端部署的配置步骤、命令脚本及常见问题解决方案整理成标准化文档,减少后续部署重复工作量,提升协作效率。 +3. **接口测试联动:** 建议建立接口测试与开发的联动机制,测试中发现的问题实时同步至对应开发成员,缩短问题修复周期。 + +## 小结 + +1. **技能提升**:学习掌握了APIFox 测试用例设计、接口测试执行及测试报告生成全流程。 +2. **问题解决**:协调解决了 APIFox 测试中接口文档缺失、测试账号权限不足的问题。。 +3. **帮助需求**:希望学习关于系统 α 版本测试的方法和工具使用,以保障后续版本质量 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-12/members/yangzy-weekly-plan-12.md b/doc/process/weekly/week-12/members/yangzy-weekly-plan-12.md new file mode 100644 index 0000000..dacc5e1 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangzy-weekly-plan-12.md @@ -0,0 +1,25 @@ +# 个人周计划-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-12-09 继续前端知识的学习 | +| 2 | 编写阿尔法迭代核心业务模型图 | 组员 | 2025-12-11 重点检查主要业务流程的接口调用情况,保证接口参数、返回值和状态码一致,发现问题及时记录和修复,确保核心功能接口能稳定、正常运作 | +| 3 | 编写并实现新增前端接口 | 组员 | 2025-12-12 根据与后端的最终联调结果,完成前端API接口的标准化封装与设计文档编写。同时,开发实现与新增或优化功能相关的前端界面与交互逻辑。 | +| 4 | 使用APIFox完成系统接口测试 | 组员 | 2025-12-13 利用APIFox平台,基于已部署的后端服务,对所有线上接口进行全面的功能测试、参数边界测试及异常场景测试,生成测试报告,并修复测试过程中发现的缺陷,确保接口健壮性。 | +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-12/members/yangzy-weekly-summary-12.md b/doc/process/weekly/week-12/members/yangzy-weekly-summary-12.md new file mode 100644 index 0000000..cf98a33 --- /dev/null +++ b/doc/process/weekly/week-12/members/yangzy-weekly-summary-12.md @@ -0,0 +1,32 @@ +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-08 +**结束时间:** 2025-12-14 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-12-09 继续进行了Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 编写阿尔法迭代核心业务模型图 | 完成 | 2025-12-11 重点检查了主要业务流程的接口调用情况,保证接口参数、返回值和状态码一致,发现了些许问题并及时记录和修复,确保了核心功能接口能稳定、正常运作 | +| 3 | 编写并实现新增前端接口 | 完成 | 2025-12-12 根据与后端的最终联调结果,完成前端API接口的标准化封装与设计文档编写。同时,开发实现与新增或优化功能相关的前端界面与交互逻辑。 | +| 4 | 使用APIFox完成系统接口测试 | 完成 | 2025-12-13 利用APIFox平台,基于已部署的后端服务,对所有线上接口进行全面的功能测试、参数边界测试及异常场景测试,生成测试报告,并修复测试过程中发现的缺陷,确保接口健壮性。 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-13/group/meeting-minutes-13.md b/doc/process/weekly/week-13/group/meeting-minutes-13.md new file mode 100644 index 0000000..51a3ce6 --- /dev/null +++ b/doc/process/weekly/week-13/group/meeting-minutes-13.md @@ -0,0 +1,105 @@ +# 小组会议纪要-第13周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 订单与工单分开管理方案评审 +**会议地点:** 腾讯会议 +**会议时间:** 2025-12-20 15:00-16:10 +**纪录时间:** 2025-12-20 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 +本次会议聚焦于“订单(客户付费)”与“工单(工作人员处理)”的分离管理方案,明确数据模型、接口职责和前端展现,降低耦合、便于统计和后续扩展。会议围绕需求背景、技术方案、迁移步骤及风险应对进行了评审与决策。 + +### 1. 业务与数据模型澄清 + + +**(1)订单与工单的边界:** +- 订单:面向用户,承载计费、支付、退款;状态:待支付/已支付/已关闭等。 +- 工单:面向工作人员,承载派工、处理、回执;状态:待分派/处理中/待回访/已完成/已关闭。 + +**(2)关键实体与关系:** +- 订单与工单一对多:一笔订单可拆分多个工单(如多设备/多地址)。 +- 工单可独立生命周期:允许在订单已完成后继续追踪售后工单。 + +**(3)数据字段初稿:** +- 订单新增:payStatus、refundStatus、amount、payChannel、payTime、closeReason。 +- 工单新增:assignUser、assignDept、serviceType、slaDeadline、onsiteTime、checklist、evidenceImgs、customerSign。 + + +### 2. 接口与前端改造决议 + +**(1)接口拆分:** +- order 控制器仅保留下单、支付、退款、订单查询,去除派工/处理逻辑。 +- workorder 控制器新增创建/分派/接单/处理/完工/回访接口;支持附件与图片上传。 + +**(2)前端改造:** +- 用户端:订单列表与支付流程保持不变;售后入口跳转工单列表(仅展示与本人相关的工单)。 +- 员工端:新增“工单池/我的工单”页面,独立于订单;处理页支持上传回执与签名。 + +**(3)统计与权限:** +- 统计口径拆分订单收入与工单履约;运营看板新增工单及时率、一次解决率。 +- 权限:工单操作需 staff 登录且具备角色;订单支付仍由 user 端发起。 + +### 3. 迁移与测试计划 +- 数据迁移:现有订单数据补齐与工单的关联字段;已存在的派工记录迁移为工单表。 +- 双轨期:一周内保留旧接口只读,前端切换完成后下线旧派工接口。 +- 回归测试:支付链路回归;工单全流程(分派-接单-处理-完工-回访)全场景测试;统计与权限回归。 + + + + +## 问题总结 + +### 已解决问题: +1. 订单/工单职责边界明确:确认订单仅承载支付与收费,工单承载履约与派工。 +2. 技术方案确定:接口拆分、前端页面改造、统计与权限口径均达成一致。 +3. 迁移与测试路径确定:形成数据迁移、双轨过渡与回归测试的执行计划。 + +### 待解决问题: +1. 数据迁移脚本与回滚预案:本周内完成设计与演练。 +2. 前端改版落地:员工端工单池/处理页、用户端售后入口改造需在下周完成开发并联调。 +3. 监控与告警:为工单链路补充接口日志、错误告警与SLA超时提醒。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** +本次会议聚焦订单与工单分离的核心改造,前后端及测试就数据模型、接口拆分、页面改造与测试计划达成一致,沟通充分、决策明确。 + +2. **分工明确:** + +后端:负责 order/workorder 接口拆分与迁移脚本;测试环境准备。 +前端:用户端售后入口、员工端工单池与处理页改造。 +测试:设计并执行工单全流程及支付回归用例。 +PM:跟踪迁移与双轨切换节奏,组织评审与复盘。 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论聚焦,决策高效。 + +--- + + +## 备注 + +1. 数据迁移与双轨需提前演练,避免生产切换风险。 +2. 支付相关测试继续使用沙箱与脱敏数据,避免真实支付。 +3. 工单SLA指标需在上线前配置好监控与提醒,确保运营可观察。 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-13/group/weekly-plan-13.md b/doc/process/weekly/week-13/group/weekly-plan-13.md new file mode 100644 index 0000000..7536922 --- /dev/null +++ b/doc/process/weekly/week-13/group/weekly-plan-13.md @@ -0,0 +1,33 @@ +# 小组周计划-第13周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 继续完善前端接口封装与联调 | 前端组 | 针对阿尔法版已有与新增接口,补齐参数校验、错误处理与文档,完成与后端的联调回归,确保核心流程可稳定演示。 | +| 2 | 完成阿尔法版本迭代并在小班讨论课展示 | 全体成员 | 汇总阿尔法版本全部功能、部署与演示脚本,准备课堂展示材料,现场演示开发完成情况并收集反馈。 | +| 3 | 启动贝塔版本编码与测试 | 后端组与测试组 | 选定贝塔版优先级高的功能点,搭建测试环境,编写初版代码并进行基础功能与接口测试,识别技术与质量风险。 | +| 4 | 更新迭代开发计划(第三稿) | PM与架构负责人 | 基于最新需求变更和阿尔法评审反馈,更新迭代计划第三稿,明确贝塔阶段里程碑、资源与风险预案。 | +| 5 | 需求规格说明书最终稿更新 | PM与需求负责人 | 对照修改后的需求与评审意见,补充或修正需求规格说明书,输出最终稿并同步至团队。 | + +## 小结 + +1. **阿尔法收尾与展示验证:**聚焦阿尔法版功能与演示准备,在小班讨论课展示成果并收集改进意见,为后续迭代提供一手反馈。 +2. **前端接口质量提升:**持续完善接口封装、校验与文档,确保与后端联调顺畅、演示稳定,为贝塔版功能扩展打好基础。 +3. **贝塔迭代启动与风险识别:**提前开启贝塔版高优先级功能的编码与基础测试,识别技术与质量风险,压缩后续交付周期。 +4. **计划与需求同步更新:**根据最新需求与评审反馈,完成迭代计划第三稿和需求规格说明书最终稿,确保团队对里程碑与需求范围有一致、最新的共识。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-13/group/weekly-summary-13.md b/doc/process/weekly/week-13/group/weekly-summary-13.md new file mode 100644 index 0000000..2a4a960 --- /dev/null +++ b/doc/process/weekly/week-13/group/weekly-summary-13.md @@ -0,0 +1,31 @@ +# 小组周总结-第13周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 继续完善前端接口封装与联调 | 完成 | 前端组完成阿尔法版接口的参数校验、错误处理与文档补充,与后端完成联调回归测试,核心流程演示稳定。 | +| 2 | 完成阿尔法版本迭代并在小班讨论课展示 | 完成 | 汇总阿尔法版本全部功能与部署情况,准备演示脚本与展示材料,在小班讨论课上成功展示开发完成情况并收集反馈意见。 | +| 3 | 启动贝塔版本编码与测试 | 进行中 | 后端组与测试组选定贝塔版高优先级功能点,搭建测试环境,完成初版代码编写并进行基础功能与接口测试,识别部分技术风险。 | +| 4 | 更新迭代开发计划(第三稿) | 完成 | PM与架构负责人基于最新需求变更和阿尔法评审反馈,完成迭代计划第三稿更新,明确贝塔阶段里程碑、资源分配与风险预案。 | +| 5 | 需求规格说明书最终稿更新 | 完成 | PM与需求负责人对照修改后的需求与评审意见,完成需求规格说明书最终稿的补充与修正,并同步至团队。 | + +## 小结 + +1. **阿尔法版本成功展示:**在小班讨论课上完成阿尔法版本功能演示,获得良好反馈,为后续迭代方向提供重要参考。 +2. **前端接口质量持续提升:**完善接口封装、校验与文档,完成联调回归,确保演示流程稳定,为贝塔版功能扩展奠定基础。 +3. **贝塔迭代顺利启动:**完成高优先级功能点的编码与基础测试,识别技术风险,为后续开发周期压缩做好准备。 +4. **计划与需求文档同步更新:**完成迭代开发计划第三稿和需求规格说明书最终稿,确保团队对里程碑与需求范围达成一致共识。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-13/members/liangchenxv-weekly-plan-13.md b/doc/process/weekly/week-13/members/liangchenxv-weekly-plan-13.md new file mode 100644 index 0000000..1a46cf3 --- /dev/null +++ b/doc/process/weekly/week-13/members/liangchenxv-weekly-plan-13.md @@ -0,0 +1,35 @@ +# 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 完善前端接口封装与联调 | 个人 | 对阿尔法版已有与新增接口补齐参数校验、异常处理与接口文档,配合后端完成回归联调,确保核心流程稳定可演示。 | +| 2 | 阿尔法版本展示材料与演示准备 | 个人 | 梳理本周接口改进点,整理演示脚本与录屏预案。 | +| 3 | 启动贝塔版优先功能编码与接口测试 | 个人 | 选定贝塔期高优先级功能(如用水告警/报修流转)进行前端接口封装与单元/接口测试,提交初版缺陷记录并跟踪。 | +| 4 | 支持迭代计划与需求文档更新 | 个人 | 提供接口清单、风险与人力估算,协助PM更新迭代计划第三稿及需求规格说明书相关接口章节,保持文档与实现一致。 | + + + +## 小结 + +1. **巩固接口质量能力:**聚焦参数校验、错误兜底与文档一致性,在联调中提升接口稳定性与可维护性。 +2. **演示与反馈循环:**通过阿尔法展示的脚本化准备和现场演示练习,提升表达与快速回应问题的能力,为贝塔阶段迭代提供一手反馈。 +3. **贝塔提前启动:**在高优先级功能上尽早编码与测试,形成接口与用例的初版资产,降低后续交付风险。 +4. **计划与需求对齐:**在迭代计划与需求更新中输出接口清单和风险,帮助团队对里程碑与范围形成一致预期。 +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-13/members/liangchenxv-weekly-summary-13.md b/doc/process/weekly/week-13/members/liangchenxv-weekly-summary-13.md new file mode 100644 index 0000000..05e387a --- /dev/null +++ b/doc/process/weekly/week-13/members/liangchenxv-weekly-summary-13.md @@ -0,0 +1,40 @@ +# 个人周总结-第13周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 完善前端接口封装与联调 | 完成 | 对阿尔法版已有与新增接口补齐参数校验、异常处理与接口文档,配合后端完成回归联调,确保核心流程稳定可演示。 | +| 2 | 阿尔法版本展示材料与演示准备 | 完成 | 梳理本周接口改进点,整理演示脚本与录屏预案。 | +| 3 | 启动贝塔版优先功能编码与接口测试 | 进行中 | 选定贝塔期高优先级功能(如用水告警/报修流转)进行前端接口封装与单元/接口测试,提交初版缺陷记录并跟踪。 | +| 4 | 支持迭代计划与需求文档更新 | 完成 | 提供接口清单、风险与人力估算,协助PM更新迭代计划第三稿及需求规格说明书相关接口章节,保持文档与实现一致。 | + +## 对团队工作的建议 + +1. **接口质量标准化:**建立参数校验、异常处理与文档更新的检查清单,确保每个接口在联调前达到可演示标准。 +2. **演示脚本模板化:**沉淀阿尔法演示的脚本模板与录屏预案,为后续版本展示提供可复用流程。 +3. **贝塔功能优先级管理:**建立高优先级功能的接口封装与测试跟踪机制,确保关键功能提前验证,降低交付风险。 + +## 小结 + +1. **巩固接口质量能力:**聚焦参数校验、错误兜底与文档一致性,在联调中提升接口稳定性与可维护性。 +2. **演示与反馈循环:**通过阿尔法展示的脚本化准备和现场演示练习,提升表达与快速回应问题的能力,为贝塔阶段迭代提供一手反馈。 +3. **贝塔提前启动:**在高优先级功能上尽早编码与测试,形成接口与用例的初版资产,降低后续交付风险。 +4. **计划与需求对齐:**在迭代计划与需求更新中输出接口清单和风险,帮助团队对里程碑与范围形成一致预期。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-13/members/yangjie-weekly-plan-13.md b/doc/process/weekly/week-13/members/yangjie-weekly-plan-13.md new file mode 100644 index 0000000..cd016f6 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangjie-weekly-plan-13.md @@ -0,0 +1,26 @@ +# 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| :--- | :------- | :----- | :------- | +| 1 | 协助进行接口联调回归测试 | 前端组 | 2025-12-15,配合前端完成对现有核心接口的最终联调,确保登录、数据上报等演示流程的稳定性 | +| 2 | 贝塔版本高优先级功能开发启动 | 后端组 | 2025-12-16至12-17,根据评审选定的功能点(如数据分析报表接口),进行数据库设计及Service层核心代码编写 | +| 3 | 贝塔版本功能基础接口测试 | 测试组/个人 | 2025-12-18,对新开发的功能接口进行基础的功能与参数校验测试,识别潜在的技术实现风险 | +| 4 | 阿尔法版本演示材料准备与支持 | 全体成员 | 2025-12-19,整理后端核心功能点说明,准备演示脚本中涉及后端交互环节的保障预案 | +| 5 | 参与迭代计划与需求文档评审 | PM/架构负责人 | 2025-12-20,基于开发实践对贝塔阶段的里程碑计划和更新后的需求文档提出技术可行性意见 | + +## 小结 + +1. **保障演示稳定:** 核心工作是确保阿尔法版本在课堂演示中的后端服务稳定、可靠,与前端配合无中断。 +2. **平滑启动贝塔迭代:** 在保障演示的同时,高效启动贝塔版本新功能的编码工作,进行早期测试以暴露风险。 +3. **技术评审与输入:** 基于前期开发经验,为更新后的项目计划和需求规格提供务实的技术视角和风险评估。 +4. **协作与衔接:** 本周处于版本交接期,需平衡好对阿尔法版的收尾支持与对贝塔版新任务的启动投入。 +5. **学习与支持需求:** 希望老师或团队能在如何高效管理并行任务(演示保障 vs 新功能开发)方面给予经验指导。 \ No newline at end of file diff --git a/doc/process/weekly/week-13/members/yangjie-weekly-summary-13.md b/doc/process/weekly/week-13/members/yangjie-weekly-summary-13.md new file mode 100644 index 0000000..a292515 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangjie-weekly-summary-13.md @@ -0,0 +1,28 @@ +# 个人周总结-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| :--- | :------- | :------- | :------- | +| 1 | 协助进行接口联调回归测试 | 完成 | 与前端同学配合,对所有演示相关的核心接口进行了最终联调与压力测试,确保了演示流程的顺畅 | +| 2 | 贝塔版本高优先级功能开发启动 | 部分完成 | 完成了新增数据分析模块的数据库表设计,并编写了核心服务层代码的初版,开发工作已按计划展开 | +| 3 | 贝塔版本功能基础接口测试 | 部分完成 | 对新编写的服务层方法进行了单元测试,完成了基础功能验证,完整的接口集成测试待前后端对接后开展 | +| 4 | 阿尔法版本演示材料准备与支持 | 完成 | 准备了后端服务部署架构与核心接口列表等演示素材,并在课堂演示期间值守,确保后端服务无异常 | +| 5 | 参与迭代计划与需求文档评审 | 完成 | 参与了团队内部迭代计划和最终版需求规格说明书的评审,从技术实现角度提出了优化建议 | + + + +## 小结 + +1. **关键交付保障:** 本周首要目标是保障阿尔法版本课堂演示的成功,通过充分的联调与现场支持,达成了这一目标,积累了应对演示的关键经验。 +2. **并行任务管理能力提升:** 在确保演示稳定的同时,启动了贝塔版本的开发工作,初步锻炼了在多重任务间进行优先级切换和精力分配的能力。 +3. **项目全周期参与深化:** 通过参与从演示(交付)到新需求评审(规划)的全过程,对软件项目的迭代周期有了更完整和深入的体会。 +4. **技术前瞻性思考:** 在新功能开发启动时,比以往更注重前期的设计评审与风险预估,这有助于提升后续开发阶段的工作效率与代码质量。 +5. **团队协作价值认同:** 演示的成功是前后端及全体成员紧密协作的结果,再次凸显了有效沟通与共同目标在团队项目中的核心作用。 \ No newline at end of file diff --git a/doc/process/weekly/week-13/members/yangmohan-weekly-plan-13.md b/doc/process/weekly/week-13/members/yangmohan-weekly-plan-13.md new file mode 100644 index 0000000..04aaa69 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangmohan-weekly-plan-13.md @@ -0,0 +1,24 @@ + # 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | ---------------------------------------------- | ------ | -------- | +| 1 | 完成小程序前端的接口设计 | 个人 | 完成小程序前端所需的接口设计工作,包括接口参数定义、请求响应格式设计、接口调用逻辑规划等,为小程序前后端数据交互提供规范化的接口标准 | +| 2 | 将小程序端的每个功能实现采用后端真实数据 | 个人 | 将小程序端各个功能模块从模拟数据改为调用后端真实接口获取数据,实现小程序与后端的完整数据对接,确保小程序功能的真实性和可靠性 | +| 3 | 进行前后端联调测试,争取将α版本上线 | 个人 | 对小程序前后端进行全面的联调测试,包括功能测试、接口测试、数据验证等,修复发现的问题,力争完成α版本的开发并成功上线 | + +## 小结 + +1. **小程序接口设计:** 完成小程序前端所需的接口设计工作,包括接口参数定义、请求响应格式设计等,为小程序前后端数据交互提供规范化的接口标准和设计依据; +2. **小程序数据对接:** 将小程序端各个功能模块从模拟数据改为调用后端真实接口获取数据,实现小程序与后端的完整数据对接,确保小程序功能的真实性和可靠性; +3. **前后端联调与版本发布:** 对小程序前后端进行全面的联调测试,包括功能测试、接口测试、数据验证等,修复发现的问题,力争完成α版本的开发并成功上线,为项目进入下一阶段奠定基础。 + +--- diff --git a/doc/process/weekly/week-13/members/yangmohan-weekly-summary-13.md b/doc/process/weekly/week-13/members/yangmohan-weekly-summary-13.md new file mode 100644 index 0000000..4576995 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangmohan-weekly-summary-13.md @@ -0,0 +1,42 @@ + +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | 在云端部署web端的前后端 | 完成 | 成功完成web端前后端的云端部署工作,实现了通过公网IP访问后台管理系统,为项目的云端化部署奠定了坚实基础 | +|2 | 将web端前端风格样式改为数智水管家类型 | 完成 | 完成了web端前端风格样式的改造工作,将界面风格统一调整为数智水管家类型,提升了用户界面的专业性和一致性 | +|3 | 在apifox测试后端接口并修复bug | 完成 | 在apifox平台上对所有后端接口进行了全面测试,成功跑通所有接口,并修复了登录功能中密码传递接口的bug,确保了系统功能的稳定性和安全性 | +|4 | 修改服务器协议从http改为https | 完成 | 将服务器协议从http升级为https,以满足微信小程序的限制要求,提升了系统的安全性和兼容性,为后续小程序接入做好了准备 | +|5 | 完成小程序前端的接口设计 | 完成 | 完成了小程序前端的接口设计工作,为小程序与后端的交互提供了规范化的接口定义,确保了前后端数据交互的标准化和一致性 | +|6 | 将小程序端的每个功能实现采用后端真实数据 | 完成 | 将小程序端的各个功能模块与后端真实数据进行了对接,实现了数据的实时交互,提升了小程序的功能完整性和实用性 | +|7 | 进行前后端联调测试,跑通小程序端的用户部分和工作人员部分的主要功能 | 完成 | 完成了小程序前后端联调测试工作,成功跑通了小程序端的用户部分和工作人员部分的主要功能,验证了系统的功能完整性和稳定性 | +|8 | 申请了域名的ISP认证 | 完成 | 完成了域名的ISP认证申请工作,为项目的正式上线和合规运营提供了必要的资质保障 | +|9 | 配置了微信小程序的上传下载权限 | 完成 | 完成了微信小程序的上传下载权限配置,确保了小程序文件传输功能的正常运行,为后续功能扩展提供了技术支撑 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **web端云端部署完成:** 成功完成web端前后端的云端部署工作,实现了通过公网IP访问后台管理系统,为项目的云端化部署奠定了坚实基础,提升了系统的可访问性和实用性; +2. **前端界面风格优化:** 完成了web端前端风格样式的改造工作,将界面风格统一调整为数智水管家类型,提升了用户界面的专业性和一致性,改善了用户体验; +3. **接口测试与bug修复:** 在apifox平台上对所有后端接口进行了全面测试,成功跑通所有接口,并修复了登录功能中密码传递接口的bug,确保了系统功能的稳定性和安全性; +4. **协议升级与安全加固:** 将服务器协议从http升级为https,以满足微信小程序的限制要求,提升了系统的安全性和兼容性,为后续小程序接入做好了技术准备; +5. **小程序接口设计完成:** 完成了小程序前端的接口设计工作,建立了规范化的前后端交互标准,为小程序功能的实现提供了清晰的数据交互框架; +6. **小程序数据对接实现:** 将小程序端的各个功能模块与后端真实数据进行了对接,实现了数据的实时交互,使小程序具备了完整的数据处理能力; +7. **前后端联调测试成功:** 完成了小程序前后端联调测试,成功跑通了用户部分和工作人员部分的主要功能,验证了系统的功能完整性和稳定性,为小程序上线做好了准备; +8. **域名ISP认证完成:** 完成了域名的ISP认证申请,为项目的正式上线和合规运营提供了必要的资质保障,确保了项目的合法性和规范性; +9. **小程序权限配置完成:** 完成了微信小程序的上传下载权限配置,确保了小程序文件传输功能的正常运行,为后续功能扩展和用户体验提升提供了技术支撑; + +--- diff --git a/doc/process/weekly/week-13/members/yangshuailu-weekly-plan-13.md b/doc/process/weekly/week-13/members/yangshuailu-weekly-plan-13.md new file mode 100644 index 0000000..bba2334 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangshuailu-weekly-plan-13.md @@ -0,0 +1,31 @@ +# 个人周计划-第十三周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-12-15 + +**结束时间:** 2025-12-21 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ---------------- | --- | ------------------------------------------- | +| 1 | 完成α版本迭代并在小班讨论课展示 | 组员 | 汇总α版本全部功能,与组员一起商量课堂展示流程。 | +| 2 | 启动β版本编码与测试 | 组员 | 和小组成员一起搭建测试环境,优化初版代码并进行基础功能与接口测试,识别技术与质量风险。 | + +## 小结 + +1. +2. **技术保障:** 聚焦阿尔法版功能与演示准备,在小班讨论课展示成果并收集改进意见,为后续迭代提供一手反馈。 +3. **资源协调**:组内协调开发进度,准备α版本验收 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-13/members/yangshuailu-weekly-summary-13.md b/doc/process/weekly/week-13/members/yangshuailu-weekly-summary-13.md new file mode 100644 index 0000000..1f71567 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangshuailu-weekly-summary-13.md @@ -0,0 +1,35 @@ +# 个人周总结-第十三周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-12-15 + +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ---------------- | ---- | --------------------------------------------------- | +| 1 | 完成α版本迭代并在小班讨论课展示 | 完成 | 与组员共同汇总 α 版本全部功能,梳理核心亮点与演示流程,在小班讨论课上顺利完成展示,同时收获老师意见 | +| 2 | 启动β版本编码与测试 | 完成 | 针对在小班讨论课上收集的意见,对项目代码进行一些修改 | + +## 对团队工作的建议 + +1. **展示材料沉淀:** 建议将本次 α 版本展示的演示及收集的反馈意见整理归档,作为后续版本展示的参考模板,提升展示效率与质量。 +2. **资源协调**:组内协调开发进度,完善β版本 + +## 小结 + +1. **技能提升**:通过小班展示锻炼了项目成果汇报能力。 +2. **问题解决**:协调解决了展示前功能演示环境不稳定、测试数据不一致的问题,保障了各项工作按计划推进。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-13/members/yangzy-weekly-plan-13.md b/doc/process/weekly/week-13/members/yangzy-weekly-plan-13.md new file mode 100644 index 0000000..c3c8dc8 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangzy-weekly-plan-13.md @@ -0,0 +1,25 @@ +# 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-12-16 继续前端知识的学习,精进个人能力 | +| 2 | 继续完善前端接口封装与联调 | 组员 | 2025-12-18 针对阿尔法版已有与新增接口,补齐参数校验、错误处理与文档,完成与后端的联调回归,确保核心流程可稳定演示。 | +| 3 | 完成阿尔法版本迭代并在小班讨论课展示 | 组员 | 2025-12-20 汇总阿尔法版本全部功能、部署与演示脚本,准备课堂展示材料,现场演示开发完成情况并收集反馈。 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-13/members/yangzy-weekly-summary-13.md b/doc/process/weekly/week-13/members/yangzy-weekly-summary-13.md new file mode 100644 index 0000000..f13fc05 --- /dev/null +++ b/doc/process/weekly/week-13/members/yangzy-weekly-summary-13.md @@ -0,0 +1,31 @@ +# 个人周总结-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-15 +**结束时间:** 2025-12-21 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-12-16 继续进行了Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 继续完善前端接口封装与联调 | 完成 | 2025-12-18 针对阿尔法版已有与新增接口,补齐了参数校验、错误处理与文档,完成与后端的联调回归,确保核心流程可稳定演示。 | +| 3 | 完成阿尔法版本迭代并在小班讨论课展示 | 完成 | 2025-12-20 汇总阿尔法版本全部功能、部署与演示脚本,准备课堂展示材料,现场演示开发完成情况并收集反馈。 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-14/group/meeting-minutes-14.md b/doc/process/weekly/week-14/group/meeting-minutes-14.md new file mode 100644 index 0000000..3aa897f --- /dev/null +++ b/doc/process/weekly/week-14/group/meeting-minutes-14.md @@ -0,0 +1,124 @@ +# 小组会议纪要-第14周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 工作计划评审与任务分工 +**会议地点:** 腾讯会议 +**会议时间:** 2025-12-28 15:00-16:30 +**纪录时间:** 2025-12-28 18:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 +本次会议基于项目收尾阶段的需求,对第15周(2025-12-29至2026-1-4)的工作计划进行了详细评审和任务分工。会议聚焦于用户手册编写、系统测试、bug修复、兼容性验证以及工作量统计等关键任务,确保项目能够高质量交付。 + +### 1. 第15周任务计划评审 + +**(1)任务内容确认:** +- 用户手册编写:涵盖系统介绍、功能说明、操作步骤、常见问题等完整内容 +- 系统测试:包括功能测试、性能测试、兼容性测试,形成完整的测试报告 +- 小程序端bug修复:梳理并修复所有已知bug,确保功能稳定可靠 +- 手机兼容性验证:审核通过后在真实手机环境中测试运行状态 +- 代码工作量统计:汇总各成员代码提交量和功能完成情况并上传 + +**(2)时间安排:** +- 开始时间:2025-12-29(本周一) +- 结束时间:2026-1-4(下周日) +- 各任务需在本周内完成,确保项目高质量交付 + +**(3)技术支持需求:** +- 用户手册编写规范指导 +- 测试用例设计方法指导 +- 小程序兼容性测试要点指导 +- 代码工作量统计标准指导 + + +### 2. 任务分工与执行计划 + +**(1)用户手册编写(全体成员):** +- 根据系统功能模块编写完整的用户操作手册 +- 包含系统介绍、功能说明、操作步骤、常见问题等内容 +- 确保用户能够按照手册顺利使用系统各项功能 + +**(2)测试工作(测试组):** +- 对系统进行全面测试,包括功能、性能、兼容性测试 +- 详细记录测试用例、测试结果和发现的问题 +- 形成完整的测试报告文档 + +**(3)小程序端bug修复(前端组):** +- 梳理并修复小程序端所有已知bug +- 包括功能异常、界面显示问题、交互逻辑错误等 +- 确保小程序端功能稳定可靠 + +**(4)手机运行状态验证(测试组及前端组):** +- 在审核通过后,在真实手机环境中进行运行测试 +- 验证小程序在不同型号手机上的兼容性和运行稳定性 +- 确保良好的用户体验 + +**(5)代码工作量统计(PM及各小组负责人):** +- 统计各小组成员的代码提交量、功能完成情况 +- 按照要求格式整理并上传至代码托管平台 +- 为项目考核提供依据 + +### 3. 质量保障与风险控制 +- 建立每日进度汇报机制,确保任务按计划推进 +- 设立技术问题及时沟通渠道,协调解决开发中的困难 +- 制定验收标准,确保各任务交付质量达标 + + + + +## 问题总结 + +### 已解决问题: +1. 第15周任务计划明确:确认了用户手册编写、系统测试、bug修复、兼容性验证和工作量统计等五项主要任务。 +2. 任务分工清晰:明确了各小组的具体职责和执行内容。 +3. 时间节点确定:制定了2025-12-29至2026-1-4的工作周期安排。 + +### 待解决问题: +1. 技术指导需求:需要老师在用户手册编写规范、测试用例设计方法、小程序兼容性测试要点、代码工作量统计标准等方面提供专业指导。 +2. 进度管控机制:建立每日进度跟踪和问题协调机制,确保项目按时高质量完成。 +3. 验收标准制定:明确各任务的交付标准和质量要求。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** +本次会议对第15周收尾工作进行了充分讨论,各小组成员积极参与,就任务分工、时间安排和技术支持需求达成一致共识,体现了良好的团队协作精神。 + +2. **分工明确:** + +全体成员:共同完成用户手册编写工作。 +测试组:负责系统测试和测试报告编写,手机运行状态验证。 +前端组:负责小程序端bug修复,配合测试组进行兼容性验证。 +PM及各小组负责人:负责代码工作量统计与上传。 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,积极参与讨论,会议氛围良好,决策过程民主高效。 + +--- + + +## 备注 + +1. 各小组成员需按时提交个人计划和总结给负责人。 +2. 周任务总结与计划是项目小组评分考核的重要依据,请认真填写并按时提交。 +3. 希望老师能在用户手册编写规范、测试用例设计方法、小程序兼容性测试要点、代码工作量统计标准等方面提供指导。 +4. 建立每日进度汇报机制,确保项目能够按计划高质量完成。 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-14/group/weekly-plan-14.md b/doc/process/weekly/week-14/group/weekly-plan-14.md new file mode 100644 index 0000000..dba8ac7 --- /dev/null +++ b/doc/process/weekly/week-14/group/weekly-plan-14.md @@ -0,0 +1,33 @@ +# 小组周计划-第14周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 全体开发人员 | 梳理并分析上周小班课老师提出的修改意见,制定改进方案,进行数智水管家贝塔版本的功能迭代开发,确保修改意见得到有效落实。 | +| 2 | 贝塔版本编码与测试 | 后端组、前端组与测试组 | 根据修改意见完成相关功能的编码实现,进行单元测试、集成测试和接口测试,确保代码质量和功能稳定性,修复测试中发现的问题。 | +| 3 | 完善迭代开发计划第三稿 | PM与架构负责人 | 结合小班课反馈意见和贝塔版本开发进展,继续更新迭代开发计划第三稿,明确后续开发任务、时间节点和资源分配,优化开发流程。 | +| 4 | 完善需求规格说明书最终稿 | PM与需求负责人 | 根据修改意见和开发过程中的需求变更,继续完善需求规格说明书最终稿,确保文档准确反映当前系统需求,为后续开发提供准确指导。 | +| 5 | 开发人员个人技能考核 | 全体开发人员 | 组织前端开发人员和后台开发人员分别进行个人技能考核,评估技术能力水平,识别技能短板,为后续人员培养和任务分配提供依据。 | + +## 小结 + +1. **贝塔版本迭代优化:**基于小班课老师的专业修改意见,系统性地改进数智水管家贝塔版本,提升产品质量和用户体验,确保项目符合预期目标。 +2. **质量保障与测试:**通过全面的编码测试,包括单元测试、集成测试和接口测试,及时发现和修复问题,保证贝塔版本的稳定性和可靠性。 +3. **文档完善与规范:**同步更新迭代开发计划第三稿和需求规格说明书最终稿,确保项目文档的完整性和准确性,为团队协作和项目管理提供有力支撑。 +4. **技能评估与提升:**通过个人技能考核,全面了解团队成员的技术水平,为后续任务分配和技能培训提供参考,促进团队整体能力的提升。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-14/group/weekly-summary-14.md b/doc/process/weekly/week-14/group/weekly-summary-14.md new file mode 100644 index 0000000..384ac70 --- /dev/null +++ b/doc/process/weekly/week-14/group/weekly-summary-14.md @@ -0,0 +1,31 @@ +# 小组周总结-第14周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 完成 | 全体开发人员梳理并分析小班课老师提出的修改意见,制定改进方案,基本完成数智水管家贝塔版本的功能迭代开发,修改意见得到有效落实。 | +| 2 | 贝塔版本编码与测试 | 完成 | 后端组、前端组与测试组根据修改意见完成相关功能的编码实现,通过接口测试,确保代码质量和功能稳定性,修复测试中发现的所有问题。 | +| 3 | 完善迭代开发计划第三稿 | 完成 | 结合小班课反馈意见和贝塔版本开发进展,完成迭代开发计划第三稿的更新,明确后续开发任务、时间节点和资源分配,优化开发流程。 | +| 4 | 完善需求规格说明书最终稿 | 完成 | 根据修改意见和开发过程中的需求变更,完成需求规格说明书最终稿的完善,确保文档准确反映当前系统需求,为后续开发提供准确指导。 | +| 5 | 开发人员个人技能考核 | 完成 | 本周进行个人技能考核,全面评估技术能力水平,识别技能短板,为后续人员培养和任务分配提供依据。 | + +## 小结 + +1. **贝塔版本迭代优化:**基于小班课老师的专业修改意见,系统性地改进数智水管家贝塔版本,提升产品质量和用户体验,确保项目符合预期目标。 +2. **质量保障与测试:**通过全面的编码测试,包括单元测试、集成测试和接口测试,及时发现和修复问题,保证贝塔版本的稳定性和可靠性。 +3. **文档完善与规范:**同步更新迭代开发计划第三稿和需求规格说明书最终稿,确保项目文档的完整性和准确性,为团队协作和项目管理提供有力支撑。 +4. **技能评估与提升:**通过个人技能考核,全面了解团队成员的技术水平,为后续任务分配和技能培训提供参考,促进团队整体能力的提升。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-14/members/liangchenxv-weekly-plan-14.md b/doc/process/weekly/week-14/members/liangchenxv-weekly-plan-14.md new file mode 100644 index 0000000..65721e5 --- /dev/null +++ b/doc/process/weekly/week-14/members/liangchenxv-weekly-plan-14.md @@ -0,0 +1,35 @@ +# 个人周计划-第14周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 进行贝塔版本前端功能迭代开发 | 个人 | 梳理并分析上周小班课老师提出的修改意见,制定前端改进方案,完成数智水管家贝塔版本相关前端功能的迭代开发,确保修改意见在前端得到有效落实。 | +| 2 | 参与贝塔版本前端编码与测试 | 个人 | 根据修改意见完成前端相关功能的编码实现,进行前端单元测试、组件测试和接口联调测试,确保代码质量和功能稳定性,修复测试中发现的前端问题。 | +| 3 | 参与支持迭代开发计划第三稿完善 | 全体成员 | 提供前端开发进度、接口清单和技术风险评估,协助PM和架构负责人继续更新迭代开发计划第三稿,确保前端任务和时间节点准确。 | +| 4 | 支持需求规格说明书最终稿完善 | 全体成员 | 提供前端需求实现情况和接口文档,协助PM和需求负责人继续完善需求规格说明书最终稿,确保前端相关需求描述准确完整。 | + + + +## 小结 + +1. **贝塔版本前端迭代优化:**基于小班课老师的专业修改意见,系统性地改进数智水管家贝塔版本的前端功能,提升用户界面体验和交互质量,确保前端实现符合预期目标。 +2. **前端质量保障与测试:**通过全面的前端编码测试,包括单元测试、组件测试和接口联调测试,及时发现和修复前端问题,保证贝塔版本前端功能的稳定性和可靠性。 +3. **文档支持与协作:**在迭代开发计划第三稿和需求规格说明书最终稿的完善过程中,提供前端开发进度和技术信息,确保项目文档的完整性和准确性。 +4. **技能评估与自我提升:**通过参加前端开发技能考核,全面了解自身技术水平,识别技能短板,为后续个人技能提升和团队任务分配提供参考。 +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-14/members/liangchenxv-weekly-summary-14.md b/doc/process/weekly/week-14/members/liangchenxv-weekly-summary-14.md new file mode 100644 index 0000000..88b9d89 --- /dev/null +++ b/doc/process/weekly/week-14/members/liangchenxv-weekly-summary-14.md @@ -0,0 +1,40 @@ +# 个人周总结-第14周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 进行贝塔版本前端功能迭代开发 | 完成 | 梳理并分析上周小班课老师提出的修改意见,协助制定前端改进方案,完成数智水管家贝塔版本相关前端功能的迭代开发,确保修改意见在前端得到有效落实。 | +| 2 | 参与贝塔版本前端编码与测试 | 完成 | 根据修改意见完成前端相关功能的编码实现,进行前端单元测试、组件测试和接口联调测试,确保代码质量和功能稳定性,修复测试中发现的前端问题。 | +| 3 | 编写完成迭代开发计划第三稿 | 完成 | 提供前端开发进度、接口清单和技术风险评估,继续更新迭代开发计划第三稿,确保前端任务和时间节点准确。 | +| 4 | 编写完成需求规格说明书最终稿 | 完成 | 根据所提供的前端需求实现情况和接口文档,完善需求规格说明书最终稿,确保前端相关需求描述准确完整。 | + +## 对团队工作的建议 + +1. **前端迭代优化流程化:**基于小班课老师修改意见,建立前端功能迭代的标准化流程,包括意见收集、方案制定、编码实现和测试验证,确保贝塔版本前端质量持续提升。 +2. **前端测试体系完善:**加强前端单元测试、组件测试和接口联调测试的覆盖范围,建立测试用例管理和缺陷跟踪机制,提升前端代码的稳定性和可靠性。 +3. **文档同步更新机制:**在迭代开发计划和需求规格说明书的完善过程中,建立前端进度和技术信息的定期同步机制,确保项目文档始终反映最新实现状态。 + +## 小结 + +1. **贝塔版本前端迭代优化:**基于小班课老师的专业修改意见,系统性地改进数智水管家贝塔版本的前端功能,提升用户界面体验和交互质量,确保前端实现符合预期目标。 +2. **前端质量保障与测试:**通过全面的前端编码测试,包括单元测试、组件测试和接口联调测试,及时发现和修复前端问题,保证贝塔版本前端功能的稳定性和可靠性。 +3. **文档支持与协作:**在迭代开发计划第三稿和需求规格说明书最终稿的完善过程中,提供前端开发进度和技术信息,确保项目文档的完整性和准确性。 +4. **技能评估与自我提升:**通过参加前端开发技能考核,全面了解自身技术水平,识别技能短板,为后续个人技能提升和团队任务分配提供参考。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-14/members/yangjie-weeekly-plan-14.md b/doc/process/weekly/week-14/members/yangjie-weeekly-plan-14.md new file mode 100644 index 0000000..4ea2b86 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangjie-weeekly-plan-14.md @@ -0,0 +1,26 @@ +# 个人周计划-第14周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| :--- | :------- | :----- | :------- | +| 1 | 梳理老师反馈并制定后端改进方案 | 后端组 | 集中讨论小班课老师对后端功能的修改意见,分析技术可行性,制定详细的改进任务清单 | +| 2 | 实施贝塔版本后端功能迭代开发 | 后端组 | 根据改进清单,完成核心业务逻辑优化、接口调整或新功能模块的编码工作 | +| 3 | 完成负责模块的单元测试与集成测试 | 个人/测试组 | 对自己开发或修改的代码进行充分的单元测试,并配合测试组完成相关接口的集成测试 | +| 4 | 参与迭代开发计划与需求文档评审 | PM/全体成员 | 参与团队会议,评审更新后的迭代开发计划与需求规格说明书,从技术实现角度提出意见 | +| 5 | 准备并参加后端开发个人技能考核 | 个人 | 复习核心后端技术栈(Spring Boot,RUOYI,MySQL,Redis等),完成技能考核,并总结个人技能短板 | + +## 小结 + +1. **聚焦反馈落实:** 本周核心工作是针对老师的专业意见,高效、高质量地完成后端功能的迭代与优化,确保贝塔版本质量显著提升。 +2. **质量内建:** 在开发过程中严格执行代码规范,并通过主动编写单元测试和参与集成测试,将质量保障融入开发环节,减少缺陷。 +3. **文档与计划同步:** 在推进开发的同时,积极参与项目文档和计划的更新评审,确保个人工作与团队整体方向和文档保持一致。 +4. **技能自检与提升:** 通过个人技能考核,系统性地审视自身技术能力,明确优势与不足,为后续的针对性学习和任务承接做好准备。 +5. **学习与支持需求:** 希望老师或团队能在复杂业务逻辑优化、高性能接口设计方面提供案例分享或技术指导,以更好地完成迭代任务。 \ No newline at end of file diff --git a/doc/process/weekly/week-14/members/yangjie-weekly-summary-14.md b/doc/process/weekly/week-14/members/yangjie-weekly-summary-14.md new file mode 100644 index 0000000..edfda55 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangjie-weekly-summary-14.md @@ -0,0 +1,27 @@ +# 个人周总结-第14周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| :--- | :------- | :------- | :------- | +| 1 | 梳理老师反馈并制定后端改进方案 | 完成 | 参与了小组讨论,将老师对数据一致性、接口响应等方面的意见整理为明确的后端技术改进项 | +| 2 | 实施贝塔版本后端功能迭代开发 | 完成 | 根据改进清单,完成了核心业务逻辑的优化与相关接口的调整,代码已提交至开发分支 | +| 3 | 完成负责模块的单元测试与集成测试 | 完成 | 对个人修改的代码模块补充了单元测试,并与测试组配合完成了相关接口的集成验证 | +| 4 | 参与迭代开发计划与需求文档评审 | 完成 | 参与了团队对更新后计划的评审,从技术实现复杂度和资源需求角度提供了反馈 | +| 5 | 准备并参加后端开发个人技能考核 | 完成 | 完成了考核,对Spring Boot应用架构和数据库优化相关题目进行了重点回顾与解答 | + + +## 小结 + +1. **问题导向的开发实践:** 本周工作紧密围绕外部反馈展开,深刻体会到以解决具体问题、满足明确需求为目标的开发模式,对提升产品实用性的重要性。 +2. **测试驱动意识增强:** 在修复和优化功能时,主动编写和运行测试用例,验证了“测试先行”或“及时测试”对保证修改正确性、防止回归问题的有效性。 +3. **技能的系统性复盘:** 通过准备和参与技能考核,对过去一个阶段所学的后端技术进行了系统性梳理,明确了理论知识与项目实践应用中的差距。 +4. **过程优化思考:** 在完成开发任务的同时,开始更积极地思考团队协作流程中的可优化点,认识到良好的过程是保障结果的重要前提。 +5. **持续迭代心态建立:** 认识到产品开发是一个持续迭代优化的过程,能够以更平和、积极的心态接受外部反馈,并将其视为进步的契机。 \ No newline at end of file diff --git a/doc/process/weekly/week-14/members/yangmohan-weekly-plan-14.md b/doc/process/weekly/week-14/members/yangmohan-weekly-plan-14.md new file mode 100644 index 0000000..886c7f0 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangmohan-weekly-plan-14.md @@ -0,0 +1,28 @@ + # 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | ---------------------------------------------- | ------ | -------- | +| 1 | 对β版本进行迭代开发 | 个人 | 基于前期开发成果,对β版本进行迭代开发,优化系统功能,提升用户体验,完善系统稳定性和性能表现 | +| 2 | 对用户端和员工端的功能进行完善 | 个人 | 针对用户端和员工端的功能模块进行深入完善,优化交互流程,修复已知问题,增强功能完整性和易用性 | +| 3 | 完成迭代开发第三稿 | 个人 | 完成迭代开发的第三稿工作,整理开发文档,记录开发进展和功能变更,为项目后续维护和迭代提供文档支撑 | +| 4 | 完成需求规格说明书最终稿 | 个人 | 完成需求规格说明书的最终稿编写工作,完善需求文档,明确系统功能需求和技术规范,为项目验收和后续开发提供标准依据 | +| 5 | 等待审核将小程序上线 | 个人 | 提交小程序审核申请,等待平台审核通过,完成小程序正式上线发布,实现项目的最终交付目标 | + +## 小结 + +1. **β版本迭代开发:** 基于前期开发成果,对β版本进行迭代开发,持续优化系统功能,提升用户体验,完善系统稳定性和性能表现,推动项目向更高版本演进; +2. **功能完善与优化:** 针对用户端和员工端的功能模块进行深入完善,优化交互流程,修复已知问题,增强功能完整性和易用性,提升整体系统质量; +3. **迭代开发文档整理:** 完成迭代开发的第三稿工作,整理开发文档,记录开发进展和功能变更,为项目后续维护和迭代提供完整的文档支撑; +4. **需求规格说明书定稿:** 完成需求规格说明书的最终稿编写工作,完善需求文档,明确系统功能需求和技术规范,为项目验收和后续开发提供标准依据; +5. **小程序上线准备:** 提交小程序审核申请,等待平台审核通过,完成小程序正式上线发布,实现项目的最终交付目标,为项目画上圆满句号。 + +--- diff --git a/doc/process/weekly/week-14/members/yangmohan-weekly-summary-14.md b/doc/process/weekly/week-14/members/yangmohan-weekly-summary-14.md new file mode 100644 index 0000000..61a2b40 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangmohan-weekly-summary-14.md @@ -0,0 +1,34 @@ + +# 个人周总结-第12周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | β版本基本开发完成 | 完成 | 成功完成β版本的基本开发工作,实现了系统核心功能的完整实现,为项目的正式发布奠定了坚实基础,提升了系统的功能完整性和稳定性 | +|2 | 小程序端修复若干bug,解决了request:fail问题 | 完成 | 完成了小程序端多个bug的修复工作,成功解决了request:fail问题,确保了小程序与后端接口的正常通信,提升了系统的稳定性和用户体验 | +|3 | 完成迭代开发第三稿 | 完成 | 完成了迭代开发第三稿的编写工作,对系统功能进行了进一步的优化和完善,为项目的持续迭代开发提供了清晰的技术路线和实施方案 | +|4 | 完成需求规格说明书最终稿 | 完成 | 完成了需求规格说明书的最终稿编写工作,明确了系统的功能需求、性能需求和非功能需求,为项目的规范化开发和管理提供了重要文档支撑 | +|5 | 再次提交了ICP审核 | 完成 | 完成了ICP审核的再次提交工作,为项目的合规运营和正式上线提供了必要的资质保障,确保了项目的合法性和规范性 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **β版本基本开发完成:** 成功完成β版本的基本开发工作,实现了系统核心功能的完整实现,为项目的正式发布奠定了坚实基础,提升了系统的功能完整性和稳定性,标志着项目开发进入新的里程碑阶段; +2. **小程序bug修复与优化:** 完成了小程序端多个bug的修复工作,成功解决了request:fail问题,确保了小程序与后端接口的正常通信,提升了系统的稳定性和用户体验,为小程序的稳定运行提供了技术保障; +3. **迭代开发第三稿完成:** 完成了迭代开发第三稿的编写工作,对系统功能进行了进一步的优化和完善,为项目的持续迭代开发提供了清晰的技术路线和实施方案,推动了项目的持续改进和优化; +4. **需求规格说明书最终稿完成:** 完成了需求规格说明书的最终稿编写工作,明确了系统的功能需求、性能需求和非功能需求,为项目的规范化开发和管理提供了重要文档支撑,确保了项目开发的规范性和可追溯性; +5. **ICP审核再次提交:** 完成了ICP审核的再次提交工作,为项目的合规运营和正式上线提供了必要的资质保障,确保了项目的合法性和规范性,为项目的正式发布做好了合规准备; + +--- diff --git a/doc/process/weekly/week-14/members/yangshuailu-weekly-plan-14.md b/doc/process/weekly/week-14/members/yangshuailu-weekly-plan-14.md new file mode 100644 index 0000000..c1108da --- /dev/null +++ b/doc/process/weekly/week-14/members/yangshuailu-weekly-plan-14.md @@ -0,0 +1,29 @@ +# 个人周计划-第十四周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-12-22 + +**结束时间:** 2025-12-28 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | --------------------- | --- | --------------------------------------- | +| 1 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 组员 | 梳理分析上周小班课教师提出的修改意见,制定改进方案,保障各项修改意见落地见效。 | +| 2 | 启动β版本编码与测试 | 组员 | 依据修改意见完成对应功能的编码开发,及时修复测试过程中暴露的各类问题。 | +| 3 | 个人技能考核 | 自己 | 进行个人技能考核,发现问题,完善个人后端能力。 | + +## 小结 + +1. **需求落地保障**:为避免对教师修改意见的理解偏差,建议召开组会,共同商议细节。 +2. **资源协调**:组内协调开发进度,完善β版本。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-14/members/yangshuailu-weekly-summary-14.md b/doc/process/weekly/week-14/members/yangshuailu-weekly-summary-14.md new file mode 100644 index 0000000..7800fad --- /dev/null +++ b/doc/process/weekly/week-14/members/yangshuailu-weekly-summary-14.md @@ -0,0 +1,36 @@ +# 个人周总结-第十四周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-12-22 + +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | --------------------- | ---- | --------------------------------- | +| 1 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 完成 | 针对性的梳理分析了小班课教师提出的修改意见,并进行了修改完善功能。 | +| 2 | 启动β版本编码与测试 | 完成 | 优化了部分功能,完善一些小问题 | +| 3 | 个人技能考核 | 完成 | 进行了个人技能考核 | + +## 对团队工作的建议 + +1. **展示材料沉淀:** 再次检查是否有bug或者功能是否完善。 +2. **资源协调**:组内协调开发进度,完善β版本 + +## 小结 + +1. **技能提升**:通过个人技能考核明确了个人后端技能的大致水平。 +2. **问题解决**:协调解决了展示前功能演示环境不稳定、测试数据不一致的问题,保障了各项工作按计划推进。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-14/members/yangzy-weekly-plan-14.md b/doc/process/weekly/week-14/members/yangzy-weekly-plan-14.md new file mode 100644 index 0000000..90639f4 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangzy-weekly-plan-14.md @@ -0,0 +1,26 @@ +# 个人周计划-第14周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-12-23 继续前端知识的学习,精进个人能力 | +| 2 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 组员 | 2025-12-24 梳理并分析上周小班课老师提出的修改意见,制定改进方案,进行数智水管家贝塔版本的功能迭代开发,确保修改意见得到有效落实。 | +| 3 | 贝塔版本编码与测试 | 组员 | 2025-12-26 根据修改意见完成相关功能的编码实现,进行单元测试、集成测试和接口测试,确保代码质量和功能稳定性,修复测试中发现的问题。 | +| 4 | 开发人员个人技能考核 | 组员 | 2025-12-28 组织前端开发人员和后台开发人员分别进行个人技能考核,评估技术能力水平,识别技能短板,为后续人员培养和任务分配提供依据。 + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-14/members/yangzy-weekly-summary-14.md b/doc/process/weekly/week-14/members/yangzy-weekly-summary-14.md new file mode 100644 index 0000000..340a8e4 --- /dev/null +++ b/doc/process/weekly/week-14/members/yangzy-weekly-summary-14.md @@ -0,0 +1,32 @@ +# 个人周总结-第14周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-22 +**结束时间:** 2025-12-28 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-12-23 继续了前端知识的学习,精进个人能力 | +| 2 | 针对小班课老师修改意见进行贝塔版本迭代开发 | 完成 | 2025-12-24 梳理并分析了上周小班课老师提出的修改意见,制定改进方案,进行数智水管家贝塔版本的功能迭代开发,确保修改意见得到有效落实。 | +| 3 | 贝塔版本编码与测试 | 完成 | 2025-12-26 根据修改意见完成了相关功能的编码实现,进行单元测试、集成测试和接口测试,确保代码质量和功能稳定性,修复测试中发现的问题。 | +| 4 | 开发人员个人技能考核 | 完成 | 2025-12-28 组织前端开发人员和后台开发人员分别进行个人技能考核,评估技术能力水平,识别技能短板,为后续人员培养和任务分配提供依据。 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-15/group/meeting-minutes-15.md b/doc/process/weekly/week-15/group/meeting-minutes-15.md new file mode 100644 index 0000000..de8b3eb --- /dev/null +++ b/doc/process/weekly/week-15/group/meeting-minutes-15.md @@ -0,0 +1,125 @@ +# 小组会议纪要-第15周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 项目分工及后续交付要求讨论 +**会议地点:** 腾讯会议 +**会议时间:** 2026-01-02 15:00-16:30 +**纪录时间:** 2026-01-02 18:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 +本次会议讨论了项目分工及后续交付要求,明确了各模块负责人和代码量评估标准。 + +## 小结 + +### 1. 项目分工 + +**小程序前端开发**: +- **杨捷**: 负责小程序端核心页面开发,包括客服页面、设备管理页面、首页、登录页面、消息页面、订单相关页面等 +- **杨帅路**: 负责小程序端扩展页面开发,包括支付页面、个人中心页面、商品购买页面、员工工作台页面、水质检测页面等,以及配送路径规划算法 + +**Web端开发**: +- **梁晨旭**: 负责Web端后端开发,包括用户管理、员工管理、设备管理、滤芯管理、水质检测管理、商品管理、订单管理等模块的Controller、实体类和前端页面 +- **杨默涵**: 负责Web端前后端及服务端部署(Docker, MySQL等) + +**接口开发**: +- **杨默涵**: 负责小程序端及外部端的接口逻辑开发 + +**系统消息**: +- **杨默涵**: 负责系统消息相关开发 + + +### 2. 项目进度与交付 + +各模块负责人需自行评估工作量,晚上确认是否足够,若不达到申请标准需及时沟通调整。 + + +## 待办 + +### 1. 各模块开发任务执行 + +整体项目分工和代码量评估已由杨默涵在会上明确。 + +各开发人员具体分工如下: +- **杨捷**: 完成小程序端核心页面开发(客服、设备管理、首页、登录、消息、订单等页面) +- **杨帅路**: 完成小程序端扩展页面开发(支付、个人中心、商品购买、员工工作台、水质检测等页面)及配送路径规划算法 +- **梁晨旭**: 完成Web端后端开发(用户、员工、设备、滤芯、水质、商品、订单管理等模块) + +### 2. 调度算法设计与开发 + +完成调度算法的编写,用于计算完成多个目标地点的最短路径,并确保其可以在后端环境中运行。 + +完成时间:周日之前。 + +### 3. 工作量评估与代码行数统计 + +各模块负责人需自行统计并核对其模块代码的行数。 + +### 4. 沟通与协调 + +在当晚11点之前,各负责人需在群里同步各自的完成情况及工作量评估。 + +若遇到困难,需及时向杨默涵反馈并寻求帮助。 + + + + +## 问题总结 + +### 已解决问题: +1. 项目分工明确:明确了杨捷负责小程序端核心页面、杨帅路负责小程序端扩展页面及算法、梁晨旭负责Web端后端、杨默涵负责部署和接口的具体分工。 +2. 调度算法任务补充:确定了调度算法的开发要求和提交时间节点。 +3. 交付要求明确:制定了项目进度评估和当晚11点交付截止时间。 + +### 待解决问题: +1. 小程序前端任务分配:小组成员需会后自行分配小程序前端开发任务。 +2. 代码量评估标准:各模块负责人需确认工作量是否足够,若不足需及时调整。 +3. 进度同步机制:建立当晚11点前在群里同步完成情况的沟通机制。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** +本次会议对项目分工及后续交付要求进行了充分讨论,各小组成员积极参与,就各模块负责人分配、调度算法开发要求、代码量评估标准等达成一致共识,体现了良好的团队协作精神。 + +2. **分工明确:** + +杨默涵:负责Web端前后端及服务端部署、接口逻辑开发、系统消息相关开发。 +杨捷:负责小程序端核心页面开发(客服、设备管理、首页、登录、消息、订单等页面)。 +杨帅路:负责小程序端扩展页面开发(支付、个人中心、商品购买、员工工作台、水质检测等页面)及配送路径规划算法。 +梁晨旭:负责Web端后端开发(用户、员工、设备、滤芯、水质、商品、订单管理等模块)。 +各模块负责人:负责工作量评估、代码行数统计,并在当晚11点前同步完成情况。 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,积极参与讨论,会议氛围良好,决策过程民主高效。 + +--- + + +## 备注 + +1. 各小组成员需按时提交个人计划和总结给负责人。 +2. 周任务总结与计划是项目小组评分考核的重要依据,请认真填写并按时提交。 +3. 小程序前端开发任务已明确分配:杨捷负责核心页面,杨帅路负责扩展页面及算法。 +4. 调度算法开发需在周日之前完成,并确保可在后端环境中运行。 +5. 各模块负责人务必在当晚11点前在群里同步完成情况和工作量评估。 +6. 若遇到困难或代码量不足,及时向杨默涵反馈寻求帮助。 + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-15/group/weekly-plan-15.md b/doc/process/weekly/week-15/group/weekly-plan-15.md new file mode 100644 index 0000000..ad041cf --- /dev/null +++ b/doc/process/weekly/week-15/group/weekly-plan-15.md @@ -0,0 +1,35 @@ +# 小组周计划-第11周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2025-1-4 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 完成用户手册的编写 | 全体成员 | 根据系统功能模块,编写完整的用户操作手册,包含系统介绍、功能说明、操作步骤、常见问题等内容,确保用户能够按照手册顺利使用系统各项功能 | +| 2 | 完成测试并编写测试报告 | 测试组 | 对系统进行全面测试,包括功能测试、性能测试、兼容性测试等,详细记录测试用例、测试结果和发现的问题,形成完整的测试报告文档 | +| 3 | 完成小程序端未解决的bug | 前端组 | 梳理并修复小程序端存在的所有已知bug,包括功能异常、界面显示问题、交互逻辑错误等,确保小程序端功能稳定可靠 | +| 4 | 测试审核通过后的手机运行状态 | 测试组及前端组 | 在审核通过后,在真实手机环境中进行运行测试,验证小程序在不同型号手机上的兼容性和运行稳定性,确保用户体验良好 | +| 5 | 上传小组成员的代码工作量 | PM及各小组负责人 | 统计并汇总各小组成员的代码提交量、功能完成情况等工作量数据,按照要求格式整理并上传至代码托管平台,为项目考核提供依据 | + +## 小结 + +1. **用户手册编写:** 本周将完成系统用户手册的编写工作,涵盖系统功能介绍、详细操作步骤、常见问题解答等内容,确保用户能够快速上手并正确使用系统各项功能,为系统交付和用户培训提供重要文档支持。 +2. **测试工作及测试报告:** 开展全面的系统测试工作,包括功能测试、性能测试、兼容性测试等多个维度,详细记录测试过程和结果,形成规范的测试报告,为系统质量评估和问题修复提供依据。 +3. **小程序端bug修复:** 集中解决小程序端遗留的各类bug,包括功能异常、界面显示问题、交互逻辑错误等,提升小程序端的稳定性和用户体验,确保系统能够正常运行。 +4. **手机运行状态验证:** 在审核通过后,在真实手机环境中进行运行测试,验证小程序在不同型号、不同系统版本的手机上能否正常运行,确保良好的兼容性和稳定性。 +5. **代码工作量统计与上传:** 统计各小组成员的代码提交量、功能完成情况等工作量数据,按照要求格式整理并上传,为项目考核和评估提供客观依据。 +6. **技术支持需求:** 希望老师在用户手册编写规范、测试用例设计方法、小程序兼容性测试要点、代码工作量统计标准等方面提供指导。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-15/group/weekly-summary-15.md b/doc/process/weekly/week-15/group/weekly-summary-15.md new file mode 100644 index 0000000..9c36491 --- /dev/null +++ b/doc/process/weekly/week-15/group/weekly-summary-15.md @@ -0,0 +1,33 @@ +# 小组周总结-第15周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-01-04 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 完成用户手册的编写 | 进行中 | 全体成员正在根据系统功能模块编写完整的用户操作手册,包含系统介绍、功能说明、操作步骤、常见问题等内容,确保用户能够按照手册顺利使用系统各项功能。 | +| 2 | 完成测试并编写测试报告 | 进行中 | 测试组正在对系统进行全面测试,包括功能测试、性能测试、兼容性测试等,详细记录测试用例、测试结果和发现的问题,形成完整的测试报告文档。 | +| 3 | 完成小程序端未解决的bug | 进行中 | 前端组正在梳理并修复小程序端存在的所有已知bug,包括功能异常、界面显示问题、交互逻辑错误等,确保小程序端功能稳定可靠。 | +| 4 | 测试审核通过后的手机运行状态 | 已完成 | 测试组及前端组计划在审核通过后,在真实手机环境中进行运行测试,验证小程序在不同型号手机上的兼容性和运行稳定性,确保用户体验良好。 | +| 5 | 上传小组成员的代码工作量 | 进行中 | PM及各小组负责人正在统计并汇总各小组成员的代码提交量、功能完成情况等工作量数据,按照要求格式整理并上传至代码托管平台,为项目考核提供依据。 | + +## 小结 + +1. **用户手册编写:** 全体成员正在编写完整的用户操作手册,涵盖系统功能介绍、详细操作步骤、常见问题解答等内容,确保用户能够快速上手并正确使用系统各项功能,为系统交付和用户培训提供重要文档支持。 +2. **测试工作及测试报告:** 测试组正在开展全面的系统测试工作,包括功能测试、性能测试、兼容性测试等多个维度,详细记录测试过程和结果,形成规范的测试报告,为系统质量评估和问题修复提供依据。 +3. **小程序端bug修复:** 前端组正在集中解决小程序端遗留的各类bug,包括功能异常、界面显示问题、交互逻辑错误等,提升小程序端的稳定性和用户体验,确保系统能够正常运行。 +4. **手机运行状态验证:** 测试组及前端组计划在审核通过后,在真实手机环境中进行运行测试,验证小程序在不同型号、不同系统版本的手机上能否正常运行,确保良好的兼容性和稳定性。 +5. **代码工作量统计与上传:** PM及各小组负责人正在统计各小组成员的代码提交量、功能完成情况等工作量数据,按照要求格式整理并上传,为项目考核和评估提供客观依据。 +6. **技术支持需求:** 希望老师在用户手册编写规范、测试用例设计方法、小程序兼容性测试要点、代码工作量统计标准等方面提供指导。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-15/members/liangchenxv-weekly-plan-15.md b/doc/process/weekly/week-15/members/liangchenxv-weekly-plan-15.md new file mode 100644 index 0000000..6a608f2 --- /dev/null +++ b/doc/process/weekly/week-15/members/liangchenxv-weekly-plan-15.md @@ -0,0 +1,36 @@ +# 个人周计划-第15周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2025-01-04 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 参与用户手册编写 | 个人 | 负责编写用户手册中与前端功能相关的操作说明,包括界面介绍、功能操作步骤、常见前端问题排查等,确保内容准确易懂 | +| 2 | 参与完成小程序端bug修复任务 | 全体成员 | 根据小组计划,负责修复小程序端已知bug,包括功能异常、界面适配问题、交互逻辑优化等,确保功能稳定 | +| 3 | 协助完成小程序兼容性测试 | 全体成员 | 在真实手机环境中配合测试组验证小程序在不同设备上的运行情况,提供前端技术支持与问题排查 | +| 4 | 参与测试报告评审与反馈 | 全体成员 | 协助评审测试报告,从前端角度提出改进建议,确保测试覆盖全面、问题记录清晰 | + + + +## 小结 + +1. **用户手册协作编写:**配合团队完成用户手册前端部分的撰写,确保操作说明清晰、实用,帮助用户快速掌握系统使用。 +2. **小程序bug修复与优化:** 集中解决小程序端遗留问题,提升界面交互体验与功能稳定性,为上线做好准备。 +3. **兼容性测试支持:** 协助测试组在真实手机环境中验证小程序运行情况,确保多设备兼容性良好。 +4. **工作量统计与提交:** 按时整理并提交个人开发工作量,为团队评估与考核提供数据支持。 +5. **测试文档协同审阅:** 参与测试报告评审,从前端视角提出补充建议,助力测试质量提升。 +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-15/members/liangchenxv-weekly-summary-15.md b/doc/process/weekly/week-15/members/liangchenxv-weekly-summary-15.md new file mode 100644 index 0000000..c5285d7 --- /dev/null +++ b/doc/process/weekly/week-15/members/liangchenxv-weekly-summary-15.md @@ -0,0 +1,41 @@ +# 个人周总结-第15周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-01-04 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 参与用户手册编写 | 进行中 | 负责编写用户手册中与前端功能相关的操作说明,包括界面介绍、功能操作步骤、常见前端问题排查等,确保内容准确易懂,帮助用户快速掌握系统使用。 | +| 2 | 参与完成小程序端bug修复任务 | 进行中 | 根据小组计划,负责修复小程序端已知bug,包括功能异常、界面适配问题、交互逻辑优化等,通过详细测试确保功能稳定,为小程序上线做好准备。 | +| 3 | 协助完成小程序兼容性测试 | 完成 | 在真实手机环境中配合测试组验证小程序在不同设备上的运行情况,提供前端技术支持与问题排查,确保多设备兼容性良好。 | +| 4 | 参与测试报告评审与反馈 | 完成 | 协助评审测试报告,从前端角度提出改进建议,确保测试覆盖全面、问题记录清晰,为提升测试质量提供专业意见。 | + +## 对团队工作的建议 + +1. **用户手册编写规范化:**建立用户手册编写规范和审核流程,确保前端功能说明的准确性和易读性,提升用户使用体验。 +2. **小程序bug修复流程优化:**建立小程序bug修复的优先级评估和跟踪机制,确保重要bug得到及时修复,提高小程序的稳定性和用户满意度。 +3. **兼容性测试体系完善:**加强多设备兼容性测试的覆盖范围,建立测试设备管理和问题跟踪机制,确保小程序在各种设备上都能正常运行。 +4. **测试报告评审机制:**完善测试报告的评审流程,从不同技术角度进行全面评估,确保测试质量和问题覆盖的全面性。 + +## 小结 + +1. **用户手册编写协作:**配合团队完成用户手册前端部分的撰写,确保操作说明清晰、实用,帮助用户快速掌握系统使用,提升产品的易用性。 +2. **小程序bug修复与优化:**集中解决小程序端遗留问题,提升界面交互体验与功能稳定性,为小程序顺利上线做好充分准备。 +3. **兼容性测试技术支持:**协助测试组在真实手机环境中验证小程序运行情况,提供专业前端技术支持,确保多设备兼容性良好。 +4. **测试文档质量提升:**参与测试报告评审,从前端技术角度提出建设性建议,助力提升测试质量和项目整体质量水平。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-15/members/yangjie-weekly-plan-15.md b/doc/process/weekly/week-15/members/yangjie-weekly-plan-15.md new file mode 100644 index 0000000..3ab34bf --- /dev/null +++ b/doc/process/weekly/week-15/members/yangjie-weekly-plan-15.md @@ -0,0 +1,25 @@ +# 个人周计划-第15周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-01-04 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| :--- | :------- | :----- | :------- | +| 1 | 参与编写用户手册后端系统部分 | 全体成员 | 负责撰写与后端服务相关的系统介绍、核心功能说明、API接口使用指引及常见问题排查章节。 | +| 2 | 协助进行系统全面测试 | 测试组 | 配合测试组对核心后端接口进行功能、性能及安全回归测试,并提供必要的技术说明与日志支持。 | +| 3 | 修复负责模块的遗留Bug | 个人/后端组 | 根据测试报告,定位并修复由自己开发或负责的模块中存在的功能异常或性能问题。 | +| 4 | 整理与提交个人代码工作量 | PM | 统计个人在本项目中的代码提交记录、主要功能贡献及问题修复清单,整理成文档按要求提交。 | +| 5 | 参与项目最终阶段评审与收尾会议 | 全体成员 | 参与团队周会,回顾本周工作完成情况,同步项目整体进度,并对最终交付物进行确认。 | + +## 小结 + +1. **文档收官:** 本周重点参与项目最终用户手册的编写,确保后端系统的使用说明清晰、准确、完整,为系统交付和用户支持提供基础。 +2. **质量保障:** 积极配合测试工作,主动修复已发现的后端缺陷,确保系统在最终阶段的稳定性和可靠性。 +3. **工作量化与总结:** 系统性地梳理个人在整个项目周期内的工作产出,完成工作量统计与提交,为项目考核和个人复盘提供依据。 +4. **项目收尾协同:** 参与最终阶段的团队同步与评审,确保个人工作与项目整体交付目标对齐,完成从开发到交付的完整闭环。 \ No newline at end of file diff --git a/doc/process/weekly/week-15/members/yangjie-weekly-summary-15.md b/doc/process/weekly/week-15/members/yangjie-weekly-summary-15.md new file mode 100644 index 0000000..c57f301 --- /dev/null +++ b/doc/process/weekly/week-15/members/yangjie-weekly-summary-15.md @@ -0,0 +1,26 @@ +# 个人周总结-第15周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-01-04 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| :--- | :------- | :------- | :------- | +| 1 | 参与编写用户手册后端系统部分 | 完成 | 负责撰写了后端系统架构、核心API接口调用说明以及常见错误码排查指南,内容已整合至用户手册初稿。 | +| 2 | 协助进行系统全面测试 | 完成 | 配合测试同学复现了数个边界场景下的接口问题,提供了后端日志分析和参数解释,支持了测试报告的完善。 | +| 3 | 修复负责模块的遗留Bug | 完成 | 根据测试报告,定位并修复了与数据查询性能和特定条件更新逻辑相关的两个关键问题。 | +| 4 | 整理与提交个人代码工作量 | 完成 | 已整理个人在项目周期内的主要提交记录、开发的功能模块及解决的Issue清单,并按要求提交。 | +| 5 | 参与项目最终阶段评审与收尾会议 | 完成 | 参与了团队最终周会,同步了个人工作完成状态,并对项目整体交付物清单进行了确认。 | + +## 小结 + +1. **项目全周期体验完成:** 本周标志着项目开发周期的正式结束,完整经历了从需求分析、设计、编码、测试到文档收尾的全部阶段,对软件开发流程有了全局性的认识。 +2. **技术文档撰写能力锻炼:** 通过编写用户手册的技术部分,学会了如何将复杂的技术实现转化为面向最终用户的、清晰易懂的操作说明,提升了技术沟通能力。 +3. **质量闭环意识巩固:** 在项目最后阶段,依然以严谨的态度对待测试与Bug修复,深刻理解了“质量贯穿始终”的含义,巩固了责任意识。 +4. **个人贡献系统化梳理:** 通过整理个人工作量,不仅是为了考核,更是一次有价值的自我复盘,清晰地看到了自己在团队中的定位与成长轨迹。 +5. **团队协作的成就感:** 看到项目从零到一地完整交付,最深的感触是个人努力融入团队协作后产生的巨大能量。感谢所有团队成员在整个项目过程中的支持与并肩作战。 \ No newline at end of file diff --git a/doc/process/weekly/week-15/members/yangmohan-weekly-plan-15.md b/doc/process/weekly/week-15/members/yangmohan-weekly-plan-15.md new file mode 100644 index 0000000..29ece5c --- /dev/null +++ b/doc/process/weekly/week-15/members/yangmohan-weekly-plan-15.md @@ -0,0 +1,28 @@ + # 个人周计划-第13周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2025-1-4 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | ---------------------------------------------- | ------ | -------- | +| 1 | 完成用户手册编写 | 个人 | 完成用户手册的编写工作,详细说明系统的使用方法和操作流程,为用户提供清晰的使用指导,提升用户体验和系统的易用性 | +| 2 | 完成测试报告编写 | 个人 | 完成测试报告的编写工作,记录系统测试过程、测试结果和问题修复情况,为项目验收和质量评估提供完整的测试文档支撑 | +| 3 | 针对手机端用户进行体验优化 | 个人 | 针对手机端用户的使用场景和需求,优化界面布局、交互流程和功能体验,提升手机端用户的使用满意度和操作便捷性 | +| 4 | 修复β版本中出现的bug | 个人 | 全面排查和修复β版本中出现的各类bug,确保系统功能的稳定性和可靠性,提升系统的整体质量和用户体验 | +| 5 | 上传最终版的代码 | 个人 | 整理并上传最终版本的代码,确保代码的完整性和规范性,为项目的最终交付和后续维护提供标准化的代码资源 | + +## 小结 + +1. **用户手册编写:** 完成用户手册的编写工作,详细说明系统的使用方法和操作流程,为用户提供清晰的使用指导,提升用户体验和系统的易用性,确保用户能够快速上手并有效使用系统; +2. **测试报告编写:** 完成测试报告的编写工作,记录系统测试过程、测试结果和问题修复情况,为项目验收和质量评估提供完整的测试文档支撑,确保项目的质量可追溯性和规范性; +3. **手机端用户体验优化:** 针对手机端用户的使用场景和需求,优化界面布局、交互流程和功能体验,提升手机端用户的使用满意度和操作便捷性,增强系统在移动端的竞争力; +4. **β版本bug修复:** 全面排查和修复β版本中出现的各类bug,确保系统功能的稳定性和可靠性,提升系统的整体质量和用户体验,为项目的正式发布做好技术准备; +5. **最终版代码上传:** 整理并上传最终版本的代码,确保代码的完整性和规范性,为项目的最终交付和后续维护提供标准化的代码资源,完成项目开发的收尾工作。 + +--- diff --git a/doc/process/weekly/week-15/members/yangmohan-weekly-summary-15.md b/doc/process/weekly/week-15/members/yangmohan-weekly-summary-15.md new file mode 100644 index 0000000..22091b6 --- /dev/null +++ b/doc/process/weekly/week-15/members/yangmohan-weekly-summary-15.md @@ -0,0 +1,36 @@ + +# 个人周总结-第15周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2025-1-4 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ---------------------------------------------------------------- | -------- | ------------------------------------------------------------ | +|1 | 完成用户手册编写 | 完成 | 完成了用户手册的编写工作,详细说明了系统的使用方法和操作流程,为用户提供了清晰的使用指导,提升了用户体验和系统的易用性 | +|2 | 完成测试报告编写 | 完成 | 完成了测试报告的编写工作,记录了系统测试过程、测试结果和问题修复情况,为项目验收和质量评估提供了完整的测试文档支撑 | +|3 | 针对手机端用户进行体验优化 | 完成 | 针对手机端用户的使用场景和需求,优化了界面布局、交互流程和功能体验,提升了手机端用户的使用满意度和操作便捷性 | +|4 | 修复β版本中出现的bug | 完成 | 全面排查和修复了β版本中出现的各类bug,确保了系统功能的稳定性和可靠性,提升了系统的整体质量和用户体验 | +|5 | 上传最终版的代码 | 完成 | 整理并上传了最终版本的代码,确保了代码的完整性和规范性,为项目的最终交付和后续维护提供了标准化的代码资源 | + +## 对团队工作的建议 + +1. **文档编写规范化:** 建立用户手册和测试报告的编写规范和审核流程,确保文档质量和一致性,为项目验收提供高质量的技术文档支撑; +2. **移动端体验优化机制:** 建立移动端用户体验优化的标准化流程,包括用户反馈收集、界面优化方案制定和效果验证,确保移动端用户满意度持续提升; +3. **Bug修复流程优化:** 建立bug修复的优先级评估和跟踪机制,确保重要bug得到及时修复,提高系统的稳定性和可靠性; +4. **代码管理规范:** 完善代码版本管理流程,确保最终版代码的完整性和可维护性,为后续项目维护和迭代开发提供良好基础; + +## 小结 + +1. **用户手册编写完成:** 完成了用户手册的编写工作,详细说明了系统的使用方法和操作流程,为用户提供了清晰的使用指导,提升了用户体验和系统的易用性,确保用户能够快速上手并有效使用系统; +2. **测试报告编写完成:** 完成了测试报告的编写工作,记录了系统测试过程、测试结果和问题修复情况,为项目验收和质量评估提供了完整的测试文档支撑,确保了项目的质量可追溯性和规范性; +3. **手机端用户体验优化:** 针对手机端用户的使用场景和需求,优化了界面布局、交互流程和功能体验,提升了手机端用户的使用满意度和操作便捷性,增强了系统在移动端的竞争力; +4. **β版本bug修复:** 全面排查和修复了β版本中出现的各类bug,确保了系统功能的稳定性和可靠性,提升了系统的整体质量和用户体验,为项目的正式发布做好了技术准备; +5. **最终版代码上传:** 整理并上传了最终版本的代码,确保了代码的完整性和规范性,为项目的最终交付和后续维护提供了标准化的代码资源,完成了项目开发的收尾工作。 + +--- diff --git a/doc/process/weekly/week-15/members/yangshuailu-weekly-plan-15.md b/doc/process/weekly/week-15/members/yangshuailu-weekly-plan-15.md new file mode 100644 index 0000000..8603912 --- /dev/null +++ b/doc/process/weekly/week-15/members/yangshuailu-weekly-plan-15.md @@ -0,0 +1,28 @@ +# 个人周计划-第十五周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-12-29 + +**结束时间:** 2025-1-4 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ------------------- | --- | ------------------------------- | +| 1 | 和小组成员一起用户手册的编写 | 组员 | 和小组成员一起编写用户操作文档,确保用户能够使用程序 | +| 2 | 协助前端一起完善小程序端未解决的bug | 组员 | 结合已知问题,和前端组的同学一起修改完善小程序端未解决的bug | + +## 小结 + +1. **技术支持需求:** 希望老师在用户手册编写规范、测试用例设计方法、小程序兼容性测试要点、代码工作量统计标准等方面提供指导。 +2. **资源协调**:组内协调开发进度,完善β版本。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-15/members/yangshuailu-weekly-summary-15.md b/doc/process/weekly/week-15/members/yangshuailu-weekly-summary-15.md new file mode 100644 index 0000000..4471278 --- /dev/null +++ b/doc/process/weekly/week-15/members/yangshuailu-weekly-summary-15.md @@ -0,0 +1,33 @@ +# 个人周总结-第十五周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-12-29 + +**结束时间:** 2025-1-4 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ------------------- | ---- | ------------------------------------ | +| 1 | 和小组成员一起用户手册的编写 | 完成 | 协助编写用户手册 | +| 2 | 协助前端一起完善小程序端未解决的bug | 完成 | 修复了部分已知bug,完善了一些小问题 | + +## 对团队工作的建议 + +1. **展示材料沉淀:** 再次检查是否有bug或者功能是否完善。 + +## 小结 + +1. **问题解决**:修复了部分已知bug,完善了一些小问题 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-15/members/yangzy-weekly-plan-15.md b/doc/process/weekly/week-15/members/yangzy-weekly-plan-15.md new file mode 100644 index 0000000..ff1c41d --- /dev/null +++ b/doc/process/weekly/week-15/members/yangzy-weekly-plan-15.md @@ -0,0 +1,26 @@ +# 个人周计划-第15周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-1-4 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-12-29 继续前端知识的学习,精进个人能力 | +| 2 | 完成用户手册的编写 | 组员 | 2025-12-31 根据系统功能模块,编写完整的用户操作手册,包含系统介绍、功能说明、操作步骤、常见问题等内容,确保用户能够按照手册顺利使用系统各项功能 | +| 3 | 完成小程序端未解决的bug | 组员 | 2025-1-2 梳理并修复小程序端存在的所有已知bug,包括功能异常、界面显示问题、交互逻辑错误等,确保小程序端功能稳定可靠 | +| 4 | 测试审核通过后的手机运行状态 | 组员 | 2025-1-4 在审核通过后,在真实手机环境中进行运行测试,验证小程序在不同型号手机上的兼容性和运行稳定性,确保用户体验良好 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-15/members/yangzy-weekly-summary-15.md b/doc/process/weekly/week-15/members/yangzy-weekly-summary-15.md new file mode 100644 index 0000000..611e1f0 --- /dev/null +++ b/doc/process/weekly/week-15/members/yangzy-weekly-summary-15.md @@ -0,0 +1,32 @@ +# 个人周总结-第15周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-12-29 +**结束时间:** 2026-1-4 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-12-29 继续了前端知识的学习,精进个人能力 | +| 2 | 完成用户手册的编写 | 完成 | 2025-12-31 根据系统功能模块,合作编写了完整的用户操作手册,包含系统介绍、功能说明、操作步骤、常见问题等内容,确保用户能够按照手册顺利使用系统各项功能 | +| 3 | 完成小程序端未解决的bug | 完成 | 2025-1-2 梳理并修复了小程序端存在的所有已知bug,包括功能异常、界面显示问题、交互逻辑错误等,还修复了一些本周新发现的bug,确保小程序端功能稳定可靠 | +| 4 | 测试审核通过后的手机运行状态 | 完成 | 2025-1-4 在审核通过后,在真实手机环境中进行了多次运行测试,验证小程序在不同型号手机上的兼容性和运行稳定性,确保用户体验良好 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-4/group/weekly-summary-04.md b/doc/process/weekly/week-4/group/weekly-summary-04.md new file mode 100644 index 0000000..3700d99 --- /dev/null +++ b/doc/process/weekly/week-4/group/weekly-summary-04.md @@ -0,0 +1,34 @@ +# 小组周总结-第4周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-13 +**结束时间:** 2025-10-19 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 原型页面分工 | 完成 | 2025-10-14,全体成员进行讨论,明确了各系统用户所需功能,并进行页面的分工 | +| 2 | 正式原型界面实现 | 未完成 | 延后到2025-10-23 ,使用墨刀原型开发工具完成原型界面实现 | +| 3 | 向指导老师展示原型界面并进行改进 | 未完成 | 延后至2025-10-24,对陆绍飞老师展示原型界面并寻求建议,进行改进 | +| 4 | 框架理解 | 完成 | 2025-10-09到2025-10-15,参考基于deepseek本地部署的糖健康系统客户端,基本理解本系统框架 | +| 5 | 确定开发环境 | 完成 | 2025-10-15,前后端人员完成开发工具,的统一与确定,前端微信开发者工具,后端ROUYI与网页端后台控制系统 | +| 6 | 软件开发专业知识的初步学习 | 完成 | 2025-10-13到2025-10-19,全体成员完成对各领域软件开发专业知识的初步学习 | +| 7 |需求文档的编写 | 完成 | 本周初步完成用例文档第一版的编写,等待原型设计结束后进一步完善 | + +## 小结 + +1. **沟通协作:** 小组成员应积极主动沟通,遇到困难及时寻求帮助,也可以主动向指导老师及研究生学长寻求建议。 +2. **学习安排:** 小组成员仍处于软件开发专业知识的初步学习阶段,应合理安排自主学习时间,以便后续开发的顺利进行。 +3. **项目管理:** 项目进度管理杨安然同学及时推进项目流程,确保项目有条不紊。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-4/members/liangchenxv-weekly-summary-04.md b/doc/process/weekly/week-4/members/liangchenxv-weekly-summary-04.md new file mode 100644 index 0000000..3e50e37 --- /dev/null +++ b/doc/process/weekly/week-4/members/liangchenxv-weekly-summary-04.md @@ -0,0 +1,38 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 完善原型界面细节 | 完成 | 2025-10-26统一系统大致模板,完善了登录界面和普通用户及工作人员界面的各种跳转逻辑和页面细节 | +| 2 | 个人技能:前端学习 | 完成 | 2025-10-25完成CSS核心知识学习,掌握布局和样式设计,熟练使用墨刀进行原型设计 | +| 3 | 学习原型设计知识 | 完成 | 2025-10-25 学习借鉴优秀界面设计案例,优化原型交互细节和视觉效果 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,建议每周组织原型设计评审会议,及时发现问题并优化改进;; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致; +## 小结 + +1. **原型制作:** 完成了原型框架的制作并实现各种细节; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-4/members/yangjie-weekly-summary-04.md b/doc/process/weekly/week-4/members/yangjie-weekly-summary-04.md new file mode 100644 index 0000000..7c768a9 --- /dev/null +++ b/doc/process/weekly/week-4/members/yangjie-weekly-summary-04.md @@ -0,0 +1,33 @@ +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-13 +**结束时间:** 2025-10-19 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 参与需求讨论和分析 | 完成 | 与全体组员完成需求讨论,深入理解滤芯管理、水质监控等模块的业务需求 | +| 2 | 墨刀原型设计与制作 | 部分完成 | 完成了设备管理、用户登录等基础页面的原型设计,核心业务页面仍在进行中 | +| 3 | 原型设计工具学习 | 完成 | 系统学习墨刀工具的基本操作方法,包括组件使用、页面布局等基础功能 | +| 4 | 参与原型评审与优化 | 完成 | 参与团队原型评审会议,听取反馈意见并对已完成部分进行优化调整 | +| 5 | 界面设计规范研究 | 进行中 | 开始研究水务系统的界面设计特点,收集相关设计参考和行业案例 | +| 6 | 交互逻辑梳理 | 进行中 | 初步梳理了基础功能的交互流程,复杂业务逻辑仍需进一步分析 | + +## 对团队工作的建议 + +1. **设计经验分享:** 建议有原型设计经验的成员分享设计技巧和效率提升方法; +2. **进度同步机制:** 建立更频繁的设计进度同步机制,及时发现和解决设计难点; +3. **设计资源整合:** 整理常用的设计资源和组件库,提高团队设计效率。 + +## 小结 + +1. **设计进展:** 完成了原型设计的基础学习和部分页面制作,为后续工作打下基础; +2. **技能入门:** 初步掌握了墨刀工具的基本操作,能够独立完成简单页面的原型设计; +3. **后续重点:** 需要加快剩余页面的原型设计进度,确保按时完成整体原型; +4. **学习需求:** 需要进一步加强复杂交互逻辑的设计能力; +5. **希望获得的帮助:** 希望有设计经验的同事能够指导复杂页面的设计思路,或组织原型设计技巧的专题分享。 \ No newline at end of file diff --git a/doc/process/weekly/week-4/members/yangmohan-weekly-summary-04.md b/doc/process/weekly/week-4/members/yangmohan-weekly-summary-04.md new file mode 100644 index 0000000..fc3423e --- /dev/null +++ b/doc/process/weekly/week-4/members/yangmohan-weekly-summary-04.md @@ -0,0 +1,32 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-13 +**结束时间:** 2025-10-19 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 个人技能:学习了html和css的各种用法并实操以及墨刀的基本使用 | 完成 | 2025-10-16完成前端的大部分学习,以及准备后续界面基本框架的构架 | +| 2 | 学习原型搭建知识 | 完成 | 2025-10-17持续学习墨刀的使用方法、并通过借鉴其他成熟的界面原型(比如学校的个人门户、教务系统,还有一些成熟商用软件的界面比如淘宝等)完善自己的设计 | +| 3 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-10-18在腾讯会议召开每周例会,并确定下周进度计划,需求 | +|4 | 编写用例文档第一版| 完成| 于10-19完成用例文档第一版的编写,等待原型设计后进一步完善| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了登录界面基本构架的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-4/members/yangshuailu-weekly-summary-04.md b/doc/process/weekly/week-4/members/yangshuailu-weekly-summary-04.md new file mode 100644 index 0000000..a50f4dd --- /dev/null +++ b/doc/process/weekly/week-4/members/yangshuailu-weekly-summary-04.md @@ -0,0 +1,41 @@ +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-10-13 + +**结束时间:** 2025-10-19 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | --------- | ---- | ------------------------------------------------------------- | +| 1 | 商讨原型界面 | 完成 | 和小组成员一起设计并绘制原型设计 | +| 2 | 个人技能:后端学习 | 完成 | 通过网络大致学习了有关ruoyi框架的知识 | +| 3 | 学习原型搭建知识 | 完成 | 持续学习墨刀的使用方法,并通过借鉴其他成熟的界面原型完善自己的设计 | +| 4 | 小组开会讨论 | 完成 | 小组成员召开小组会议共同商讨用例文档初步得出第一版 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; + +## 小结 + +1. **原型制作:** 初步完成了原型的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-4/members/yangzy-weekly-summary-04.md b/doc/process/weekly/week-4/members/yangzy-weekly-summary-04.md new file mode 100644 index 0000000..9a9155b --- /dev/null +++ b/doc/process/weekly/week-4/members/yangzy-weekly-summary-04.md @@ -0,0 +1,32 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-13 +**结束时间:** 2025-10-19 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 在墨刀上搭建原型图,创建登录界面的基本框架 | 完成 | 2025-10-15完成原型图,以及原型图的跳转,登录界面的基本框架已经搭建好 | +| 2 | 个人技能:前端学习和墨刀的基本使用 | 完成 | 2025-10-15完成墨刀的大部分学习,以及准备后续界面基本框架的构架 | +| 3 | 学习原型搭建知识 | 完成 | 2025-10-17持续学习墨刀的使用方法、并通过借鉴其他成熟的界面原型(比如学校的个人门户、教务系统,还有一些成熟商用软件的界面比如淘宝等)完善自己的设计 | +| 4 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-10-18在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了登录界面基本构架的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-5/group/meeting-minutes-05.md b/doc/process/weekly/week-5/group/meeting-minutes-05.md new file mode 100644 index 0000000..53fdff7 --- /dev/null +++ b/doc/process/weekly/week-5/group/meeting-minutes-05.md @@ -0,0 +1,113 @@ +# 小组会议纪要-第5周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 用例文档第一稿讨论 +**会议地点:** 腾讯会议 +**会议时间:** 2025-10-16 15:30-17:00 +**纪录时间:** 2025-10-16 18:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 + +本次会议主要围绕小程序的前端界面进行需求讨论,明确区分了普通用户和滤芯更换人员的功能角色,规划了首页、订单及滤芯状态管理等核心页面,研讨了订单处理流程、联系人界面以及“我的”页面的UI与功能设计。 + +**1. 用户身份与登录** +- 小程序用户分为两类:普通用户和滤芯更换人员。 +- 登录流程增加一个“选择身份”的前置界面,供用户在登录时进行身份选择。 + +**2. 首页功能规划** +- **普通用户**:首页将呈现关键数据、轮播图通知等内容。首页下方分为“我的设备”(可切换查看单台或多台设备状态)、用水量统计和滤芯状态三大模块。 +- **滤芯更换人员**:首页将展示今日剩余任务数、待处理事项及客户留言等数据。 +- **底边栏**:暂定包含“首页”、“消息/通知”、“我的设备”和“订单/评论”四个Tab。 + +**3. 订单与购买流程** +- 用户可根据设备滤芯寿命不足的状态,在小程序内下单并预约更换服务。 +- 下单后产生的订单记录将保存在个人订单页,支持查看、评价及打分。 +- “评论/评价”功能将在历史订单详情页进行整合。 + +**4. 滤芯更换方案** +- 当滤芯寿命到达阈值时,系统将提示用户并提供“立即更换”的功能选项。 +- 确定采用用户端通知与服务后台派单相结合的方式处理更换任务。 + +**5. 设备与地图展示** +- 对于尚未能直观显示多台设备及地图信息的问题,决定先保留页面原有逻辑。 +- 后续将专门设计一个更直观、全面的设备状态页面,以避免当前首页信息过载。 + +**6. 订单处理流程界面设计** +- **核心思路**:以“进行中的订单”为主,用户可通过列表选择具体订单,替代复杂地图派送追踪。 +- **核心功能点**: + - **订单选择**:提供对正在进行的多个订单进行筛选和选择的界面,支持按时间倒序排列。 + - **派送状态**:显示派送人员状态(如“是否开始派送”),以及派送人员队列中尚有几单。 + - **派送操作**:支持在派送开始前取消订单;支持联系线上工作人员进行沟通。 + - **订单修改**:支持修改部分备注,并支持微信、支付宝两种支付方式。 + +**7. 消息与聊天界面设计** +- **消息界面**:设计为独立的消息通知页,按收件人角色区分,采用类似QQ的界面样式,每则消息包含:对方身份、消息预览、发送时间和时间戳。 +- **详细聊天界面**: + - 基础聊天功能包括文字、语音、表情与图片发送。 + - 线下联系可拍照,点击顶部标签直接跳转至联系人对话语境。 + +**8. “我的”页面与设备管理设计** +- **页面结构**:首页导航栏包含“设备管理”、“我的订单”、“账户设置”等功能入口。 +- **设备管理**: + - **列表页**:采用列表形式展示设备,支持通过悬浮按钮快速添加新设备。 + - **详情页**:列表中的设备可直接下单,统一展示设备名称、地址等简要信息。 +- **个人信息**:可编辑昵称、电话号码,但强调用户接收的地址仅限于设备地址,非本人生活地址。 + + +## 待办 +**1. 历史订单页面优化** +- 完善历史订单的相关设计细节。 + +**2. 工作人员相关需求** +- 会后需进一步完善针对工作人员的功能设计和技术细节。 + +**3. 整体设计文档** +- 在充分讨论的基础上,将各模块设计整合成一份完整的设计文档。 + +**4. 整体需求文档更新** +- 需根据本次会议的讨论结果,全面更新需求文档,完善不同角色的界面功能。 + + + +## 问题总结 + +### 已解决问题: +1. 围绕前端界面进行需求讨论,明确区分了普通用户和滤芯更换人员的功能角色。 +2. 规划了首页、订单及滤芯状态管理等核心页面。 +3. 研讨了订单处理流程、联系人界面以及“我的”页面的UI与功能设计。 + + + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组协作情况良好。小组成员之间相互沟通,讨论热情高 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组纪律良好。考勤时全员到齐,会议时互通有无 + +--- + +## 备注 + +1. 项目目前的重点在于学习如何使用开发工具以及掌握开发知识 +2. 记录自己做项目的过程,已解决的部分做成一个手册 + +--- + +## 【注】 + +1. 本文档为"羊了个羊"小组软件过程会议记录,记录人员必须在会议后一个工作日之内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已经标上编号,记录人员如有增加或者减少编号的需要,在保证文档格式正确的前提下修改 +3. 本文档内容在填写完毕之后,在已有的文件名称后面加上"(会议记录-第几周)",如"meeting-minutes-04",如果一周有多次会议,命名为"meeting-minutes-04-01" \ No newline at end of file diff --git a/doc/process/weekly/week-5/group/weekly-plan-05.md b/doc/process/weekly/week-5/group/weekly-plan-05.md new file mode 100644 index 0000000..fc2dff3 --- /dev/null +++ b/doc/process/weekly/week-5/group/weekly-plan-05.md @@ -0,0 +1,33 @@ +# 小组周计划-第5周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 完善需求功能模块细节 | 全体成员 | 2025-10-20,全体成员在上周基础上进行讨论明确需求功能各种细节设定,在上周搭建的原型框架逐步实现功能细节 | +| 2 | 原型界面功能实现 | 全体成员 | 本周内 |杨默涵和梁晨旭负责完善滤芯更换工作人员的界面原型,杨振宇和杨帅路负责普通客户的界面原型,杨捷负责实现用户切换流程 +| 3 | 正式原型界面测试 | 全体成员 | 2025-10-26前,使用墨刀原型开发工具完成原型界面实现并测试通过各种功能 | +| 4 | 向指导老师展示原型界面并进行改进 | 全体成员 | 2025-10-26前,再次对陆绍飞老师展示原型界面并寻求建议,进行改进与调试修改 | +| 5 | 软件开发专业知识的初步学习 | 全体成员 | 2025-10-20到2025-10-26,全体成员对各领域软件开发专业知识的继续学习,复习数据库相关知识 | + +## 小结 + +1. **增强自信心:** 小组成员应增强自信心,发挥想象力和创造力,在原型设计环节积极思考。 +2. **沟通协作:** 小组成员应积极主动沟通,遇到困难及时寻求帮助,也可以主动向指导老师及研究生学长寻求建议。 +3. **学习安排:** 小组成员仍处于软件开发专业知识的初步学习阶段,应合理安排自主学习时间,以便后续开发的顺利进行。 +4. **项目管理:** PM及时监督并推进项目流程,确保项目有条不紊。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-5/group/weekly-summary-05.md b/doc/process/weekly/week-5/group/weekly-summary-05.md new file mode 100644 index 0000000..f4d06cc --- /dev/null +++ b/doc/process/weekly/week-5/group/weekly-summary-05.md @@ -0,0 +1,33 @@ +# 小组周总结-第5周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 完善需求功能模块细节 | 完成 | 2025-10-20,全体成员在上周基础上进行讨论,明确了需求功能的各种细节设定,为原型开发奠定基础 | +| 2 | 正式原型界面实现 | 完成 | 2025-10-26 ,使用墨刀原型开发工具完成原型界面实现 | +| 3 | 向指导老师展示原型界面并进行改进 | 未完成 | 延后至第六周,对陆绍飞老师展示原型界面并寻求建议,进行改进 | +| 4 | 正式原型界面测试 | 完成 | 2025-10-26前,使用墨刀原型开发工具完成原型界面实现,并通过各项功能测试 | +| 5 | 软件开发专业知识的初步学习 | 完成 | 2025-10-20到2025-10-26,全体成员对各领域软件开发专业知识进行了深入学习,重点复习了数据库相关知识 | + + +## 小结 + +1. **沟通协作:** 本周团队成员配合默契,按照分工顺利完成了各自负责的界面原型开发任务; +2. **学习安排:** 全体成员在软件开发专业知识学习方面取得良好进展,为后续开发工作做好了技术储备; +3. **项目管理:** 项目进度管理pm同学及时推进项目流程,确保项目有条不紊。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-5/members/liangchenxv-weekly-plan-05.md b/doc/process/weekly/week-5/members/liangchenxv-weekly-plan-05.md new file mode 100644 index 0000000..44c248d --- /dev/null +++ b/doc/process/weekly/week-5/members/liangchenxv-weekly-plan-05.md @@ -0,0 +1,34 @@ +# 个人周计划-第5周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 需求获取 | 组员 | 2025-10-20 与其他组员继续讨论推进原型界面的开发 | +| 2 | 学习前端知识 | 个人 | 周内持续学习css的相关知识以及墨刀使用 | +| 3 | 确定分工 | 组员 | 2025-10-21 开会细分确定原型界面的细节处理与完善 | +| 4 | 学习原型设计的相关知识 | 个人 | 周内持续学习墨刀的使用方法、并通过借鉴其他成熟的界面原型完善自己的设计 | +| 5 | 设计项目原型 | 组员 | 2025-10-26 通过学习借鉴优秀的原型界面设计模板,在上周基础上按照与老师沟通的需求完成原型界面 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计以及前端开发的教学; +2. **知识储备:** 提前学习后续需要使用的知识,为后续的前后端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-5/members/liangchenxv-weekly-summary-05.md b/doc/process/weekly/week-5/members/liangchenxv-weekly-summary-05.md new file mode 100644 index 0000000..c19831e --- /dev/null +++ b/doc/process/weekly/week-5/members/liangchenxv-weekly-summary-05.md @@ -0,0 +1,39 @@ + +# 个人周总结-第5周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 统一整体界面风格,完善登录界面和普通用户及工作人员界面 | 完成 | 2025-10-26完成原型界面需求,明确各模块功能要求和用户交互流程,以及完善各种跳转逻辑及其细节 | +| 2 | 个人技能:前端学习 | 完成 | 2025-10-25完成css的大部分学习,以及准备开展js的学习 | +| 3 | 学习原型设计知识 | 完成 | 2025-10-25熟练墨刀的使用方法、并通过借鉴其他成熟的界面原型(比如学校的个人门户、教务系统等)完善小组的设计并进行美化等 | +| 4 | 召开例会,讨论需求文档的编写 | 完成 | 整改出第一版原型界面 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致 +## 小结 + +1. **原型制作:** 完成了原型界面的设计与制作,包括登录界面、用户界面和工作人员界面; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-5/members/yangjie-weekly-plan-05.md b/doc/process/weekly/week-5/members/yangjie-weekly-plan-05.md new file mode 100644 index 0000000..07ee7a1 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangjie-weekly-plan-05.md @@ -0,0 +1,25 @@ +# 个人周计划-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | 完成剩余原型页面设计 | 个人 | 重点完成滤芯管理、水质监控等核心业务页面的原型设计,确保整体原型完整 | +| 2 | 完善界面交互逻辑 | 个人 | 细化所有页面的交互流程,确保用户体验的完整性和流畅性 | +| 3 | Java基础语法学习 | 个人 | 学习Java基础语法,包括数据类型、控制流程、面向对象等核心概念 | +| 4 | Spring Boot框架入门 | 个人 | 了解Spring Boot基本概念,学习项目创建和基本配置 | +| 5 | 数据库基础操作学习 | 个人 | 学习MySQL基础操作,掌握基本的SQL语句编写 | +| 6 | 参与技术架构讨论 | 全体组员 | 从全栈角度参与技术方案讨论,理解项目整体架构设计 | + +## 小结 + +1. **学习需求:** 希望了解Spring Boot项目开发的最佳实践和常用配置; +2. **协作需求:** 需要明确前后端数据交互的规范和技术选型; +3. **技术准备:** 提前研究项目可能用到的后端技术栈和相关工具。 \ No newline at end of file diff --git a/doc/process/weekly/week-5/members/yangjie-weekly-summary-05.md b/doc/process/weekly/week-5/members/yangjie-weekly-summary-05.md new file mode 100644 index 0000000..a72b119 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangjie-weekly-summary-05.md @@ -0,0 +1,33 @@ +# 个人周总结-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 完成剩余原型页面设计 | 完成 | 完成了滤芯管理、水质监控等核心业务页面的原型设计,确保整体原型完整 | +| 2 | 完善界面交互逻辑 | 完成 | 细化了所有页面的交互流程,确保用户体验的完整性和流畅性 | +| 3 | Java基础语法学习 | 完成 | 学习了Java基础语法,包括数据类型、控制流程、面向对象等核心概念 | +| 4 | Spring Boot框架入门 | 部分完成 | 掌握了Spring Boot基本概念和项目创建,部分配置内容仍需深入理解 | +| 5 | 数据库基础操作学习 | 完成 | 学习了MySQL基础操作,掌握了基本的SQL语句编写方法 | +| 6 | 参与技术架构讨论 | 完成 | 从全栈角度参与了技术方案讨论,加深了对项目整体架构设计的理解 | + +## 对团队工作的建议 + +1. **技术分享机制:** 建议建立定期技术分享机制,促进团队成员技术能力共同提升; +2. **开发规范统一:** 建议制定前后端开发规范,确保代码质量和团队协作效率; +3. **学习资源整合:** 整理技术学习资料和最佳实践,方便团队成员快速掌握项目所需技术。 + +## 小结 + +1. **原型设计完成:** 完成了所有核心业务页面的原型设计,为后续开发工作奠定了基础; +2. **技术学习进展:** 初步掌握了Java基础和Spring Boot框架,具备了基本的后端开发能力; +3. **架构理解加深:** 通过参与技术讨论,对项目整体技术架构有了更清晰的认识; +4. **后续重点:** 需要继续深入学习Spring Boot框架和数据库操作,提升后端开发能力; +5. **希望获得的帮助:** 希望有经验的同事能够指导Spring Boot项目实践,或组织后端开发技术的专题培训。 \ No newline at end of file diff --git a/doc/process/weekly/week-5/members/yangmohan-weekly-plan-05.md b/doc/process/weekly/week-5/members/yangmohan-weekly-plan-05.md new file mode 100644 index 0000000..5a40a27 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangmohan-weekly-plan-05.md @@ -0,0 +1,26 @@ +# 个人周计划-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 学习前端知识 | 个人 | 本周内持续学习js的相关知识 | +| 2 | 讨论接下来任务的分配 | 组员 | 2025-10-22 开会汇报组内各个同学的进展,讨论任务分配 | +| 3 | 学习RUOYI框架的相关知识 | 个人 | 本周内熟悉RUOYI框架以及各种功能,学习后端知识 | +| 4 | 设计项目原型 | 组员 | 2025-10-24 通过学习借鉴优秀的原型界面设计模板,在上周的基础上,按照与老师沟通的需求设计微信小程序原型Demo | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-5/members/yangmohan-weekly-summary-05.md b/doc/process/weekly/week-5/members/yangmohan-weekly-summary-05.md new file mode 100644 index 0000000..adbf489 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangmohan-weekly-summary-05.md @@ -0,0 +1,31 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +|1 | 完成工作人员界面原型设计并完善原型初稿| 完成| 完成了原型中工作人员界面的设计,整体完善了原型初稿| +|2 | 召开例会,讨论系统架构设计等下周任务| 完成| 召开了例会,讨论系统架构设计和下周任务安排| +|3 | 学习uniapp、vue以及RUOYI架构知识| 完成| 学习了uniapp和vue相关知识,以及RUOYI架构的使用方法| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了登录界面基本构架的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-5/members/yangshuailu-weekly-plan-05.md b/doc/process/weekly/week-5/members/yangshuailu-weekly-plan-05.md new file mode 100644 index 0000000..92f8e6d --- /dev/null +++ b/doc/process/weekly/week-5/members/yangshuailu-weekly-plan-05.md @@ -0,0 +1,32 @@ +# 个人周计划-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | -------------------------------------- | --- | ------------------------------- | +| 1 | 持续完成原型设计 | 组员 | 根据讨论出的用例文档继续完成原型设计 | +| 2 | 继续学习有关ruoyi知识 | 个人 | 学习一下ruoyi框架项目的开发方法 | +| 3 | 学习原型设计的相关知识 | 组员 | 周内持续学习各个工具的使用方法、并与组员讨论具体实现 | +| 4 | 学习后续有关后端知识 | 组员 | 探索ruoyi项目开发的各个环节和方法,与组员协作完成部分内容 | + +## 小结 + +1. **学习需求:** 希望能有对于ruoyi的教学; +2. **知识储备:** 提前学习后续需要使用的知识,为后续的后端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-5/members/yangshuailu-weekly-summary-05.md b/doc/process/weekly/week-5/members/yangshuailu-weekly-summary-05.md new file mode 100644 index 0000000..28eeacf --- /dev/null +++ b/doc/process/weekly/week-5/members/yangshuailu-weekly-summary-05.md @@ -0,0 +1,40 @@ +# 个人周总结-第五周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-10-20 + +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ----------- | ---- | ------------------------- | +| 1 | 学习完成原型设计 | 完成 | 基本已经能够使用墨刀进行原型设计 | +| 2 | 个人技能:后端学习 | 完成 | 通过网络大致学习了有关ruoyi框架的知识 | +| 3 | 搭建有关用户界面的内容 | 完成 | 和小组成员杨振宇一起共同完成有关用户界面的原型设计 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; + +## 小结 + +1. **原型制作:** 初步完成了原型的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-5/members/yangzy-weekly-plan-05.md b/doc/process/weekly/week-5/members/yangzy-weekly-plan-05.md new file mode 100644 index 0000000..0e4be87 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangzy-weekly-plan-05.md @@ -0,0 +1,27 @@ +# 个人周计划-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 需求获取 | 组员 | 2025-10-20 与组内其他同学面对面沟通确定各自的进展,接洽工作 | +| 2 | 学习前端知识 | 个人 | 本周内持续学习前端开发和墨刀的相关知识 | +| 3 | 确定分工 | 组员 | 2025-10-22 开会汇报组内各个同学的进展,确定本周的目标 | +| 4 | 学习原型设计的相关知识 | 个人 | 本周内持续学习墨刀的使用方法、并通过借鉴其他成熟的界面原型完善自己的设计 | +| 5 | 设计项目原型 | 组员 | 2025-10-24 通过学习借鉴优秀的原型界面设计模板,在上周的基础上,按照与老师沟通的需求设计微信小程序原型Demo | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-5/members/yangzy-weekly-summary-05.md b/doc/process/weekly/week-5/members/yangzy-weekly-summary-05.md new file mode 100644 index 0000000..7a42b21 --- /dev/null +++ b/doc/process/weekly/week-5/members/yangzy-weekly-summary-05.md @@ -0,0 +1,33 @@ + +# 个人周总结-第5周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-20 +**结束时间:** 2025-10-26 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 在新的墨刀账号上搭建原型图(之前那个是试用版),创建登录界面的基本框架 | 完成 | 2025-10-21完成原型图,以及原型图的跳转,登录界面的基本框架已经搭建好 | +| 2 | 个人技能:前端学习和墨刀的进阶使用 | 完成 | 2025-10-22完成墨刀的进阶学习,学会了墨刀的进阶用法 | +| 3 | 学习原型搭建知识 | 完成 | 2025-10-24持续学习墨刀的使用方法、并通过借鉴其他成熟的界面原型(比如学校的个人门户、教务系统,还有一些成熟商用软件的界面比如淘宝等)完善自己的设计 | +| 4 | 墨刀个人界面的框架设计和内容填充 |完成 | 2025-10-24基本完成了墨刀个人界面的框架设计和内容填充 | +| 5 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-10-25在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了登录界面基本构架的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-6/group/meeting-minutes-06.md b/doc/process/weekly/week-6/group/meeting-minutes-06.md new file mode 100644 index 0000000..d975ca3 --- /dev/null +++ b/doc/process/weekly/week-6/group/meeting-minutes-06.md @@ -0,0 +1,186 @@ +# 小组会议纪要-第6周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 杨默涵 +**会议主题:** 技术栈确认与需求文档编写讨论 +**会议地点:** 线上 +**会议时间:** 2025-10-26 14:00-16:00 +**纪录时间:** 2025-10-26 20:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路 + +--- + +## 会议内容 + +### 1. 技术栈最终确认 + +经过充分讨论,团队最终确认了前后端技术选型: + +**(1)前端技术栈:** +- 采用 **uniapp + Vue** 框架进行移动端开发 +- 原因:uniapp支持多端发布,具备良好的跨平台能力,便于后续扩展至小程序、H5等平台 +- Vue框架与团队已有技术基础相符,开发效率高 +- 与后端RuYi-APP架构能够良好对接 + +**(2)后端技术栈:** +- 采用 **RuoYi-APP** 作为后端框架 +- 沿用第四周确定的RuoYi核心模块(系统管理、菜单与权限、任务调度、监控审计、代码生成、数据字典等) +- 与前端uniapp通过RESTful API进行通信 + +**(3)技术优势:** +- uniapp + RuoYi-APP组合具有良好的生态支持 +- 前后端分离,便于团队并行开发 +- 代码复用率高,降低维护成本 + +### 2. 用户需求进一步明确 + +在前期需求调研基础上,进一步细化并明确用户需求: + +**(1)核心功能模块确认:** +- **滤芯管理模块**:滤芯信息的增删改查、更换周期管理、供应商信息维护 +- **用水监控模块**:实时用水量监控、用水数据统计分析、趋势展示 +- **水质感知模块**:水质指标实时监测(TDS、浊度、余氯等)、阈值预警 +- **设备维护模块**:设备状态监控、工单管理、维护记录 +- **用户权限管理**:基于RuoYi的角色权限体系,支持多角色管理 + +**(2)用户角色权限设计:** +- **系统管理员**:拥有全部权限,可管理系统配置、用户权限等 +- **滤芯更换工作人员**:负责滤芯更换工单执行,可查看工单详情、提交维护记录 +- **滤芯供应商**:管理供应商信息,查看设备使用情况 +- **运维人员**:监控设备状态,处理告警信息,查看统计报表 +- **普通用水用户**:查看用水数据、水质指标等基础信息 + +**(3)数据权限控制:** +- 基于RuoYi的数据权限功能,实现按部门、按设备、按区域的数据隔离 +- 敏感操作记录操作日志,支持审计追踪 + +### 3. 需求文档编写讨论 + +**(1)需求文档结构讨论:** +- **项目概述**:项目背景、目标、范围 +- **用户需求分析**:用户角色、使用场景、功能需求 +- **系统架构设计**:技术架构、系统架构、部署架构 +- **功能需求规格说明**:各功能模块的详细需求 +- **非功能需求**:性能、安全、可靠性要求 +- **接口设计规范**:前后端接口定义、数据格式 +- **数据库设计文档**:表结构、字段说明、关联关系 +- **UI/UX设计规范**:界面规范、交互规范 + +**(2)文档编写任务分工:** +- **需求分析文档**:由全体成员参与讨论,杨默涵负责汇总整理 +- **系统架构文档**:由杨帅路、杨捷负责,结合RuoYi框架特点 +- **接口文档**:前后端协作编写,梁晨旭负责整理 +- **数据库设计文档**:后端组负责完成 +- **UI设计稿**:前端组负责配合原型设计 + +**(3)文档编写要求:** +- 文档格式统一,使用Markdown格式 +- 文档需要保持版本控制,及时更新 +- 重要决策需要记录讨论过程和依据 +- 文档完成后需要团队评审通过 + +### 4. 后端界面编写需求讨论 + +**(1)后端管理界面开发计划:** +- 基于RuoYi-Vue框架开发管理端界面 +- 优先开发核心业务模块的后台管理页面 + +**(2)优先级排序:** +- **第一阶段**(高优先级): + - 用户与角色管理界面 + - 设备管理界面 + - 滤芯管理界面 + +- **第二阶段**(中优先级): + - 工单管理界面 + - 用水数据监控界面 + - 水质数据监控界面 + +- **第三阶段**(低优先级): + - 统计分析报表界面 + - 系统配置界面 + - 告警中心界面 + +**(3)界面设计要求:** +- 遵循RuoYi-UI设计规范,保持界面风格统一 +- 响应式布局,适配不同屏幕尺寸 +- 交互友好,操作流程清晰 +- 关键操作需要确认提示,防止误操作 + +**(4)开发任务分工:** +- **后端接口开发**:后端组负责RESTful API接口编写 +- **管理界面开发**:前端组负责Vue页面开发 +- **联调测试**:前后端协作完成接口联调 + +### 5. 开发计划调整 + +**(1)迭代计划调整:** +- 调整迭代0计划,增加需求文档编写时间 +- 将需求文档编写作为迭代0的核心任务之一 +- 原型设计和数据库设计同步推进 + +**(2)时间节点安排:** +- **本周末前**:完成需求文档初稿 +- **下周三前**:完成需求文档评审,确定最终版本 +- **下周末前**:完成数据库设计,开始代码生成 + +--- + +## 问题总结 + +### 已解决问题: +1. 确定前后端技术栈:前端使用uniapp+Vue,后端使用RuoYi-APP +2. 进一步明确用户需求,细化功能模块和用户角色 +3. 讨论需求文档结构,明确文档编写任务分工 +4. 明确后端界面编写需求,确定开发优先级 + +### 待解决问题: +1. 完善需求文档内容,需要各模块负责人提供详细的功能描述 +2. 确定具体的接口设计规范和数据格式标准 +3. 细化UI设计规范,完成主要页面的原型设计 +4. 制定详细的开发时间表和里程碑计划 + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组成员积极参与讨论,对技术选型和需求分析达成一致意见,团队协作顺畅 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + +## 下周计划 + +1. **任务安排:** + - 各模块负责人完成详细需求描述 + - 开始编写需求文档初稿 + - 继续完善原型设计 + - 开始数据库表设计工作 + +2. **重点事项:** + - 需求文档的质量直接关系到后续开发工作,需要认真对待 + - 保持前后端沟通,确保接口设计合理 + - 继续跟进RuoYi框架学习,掌握代码生成器使用 + +--- + +## 备注 + +1. 需求文档是项目的基础,需要充分讨论和细致编写 +2. 在文档编写过程中,如发现需求不明确的地方,需要及时沟通确认 +3. 注意记录需求变更,维护需求文档的版本 + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-6/group/weekly-plan-06.md b/doc/process/weekly/week-6/group/weekly-plan-06.md new file mode 100644 index 0000000..a1e9d7c --- /dev/null +++ b/doc/process/weekly/week-6/group/weekly-plan-06.md @@ -0,0 +1,36 @@ +# 小组周计划-第6周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | RUOYI框架学习 | 后端组 | 2025-10-28,全体成员深入学习RUOYI框架的架构、核心组件和使用方法,为后续开发奠定基础 | +| 2 | 数据库设计 | 后端组 | 2025-10-29,根据项目需求完成数据库表结构设计,包括用户表、设备表、数据表等核心表的设计 | +| 3 | 原型展示完善 | 全体成员 | 2025-10-30,完善原型界面设计,确保所有功能模块都有对应的原型展示 | +| 4 | UniApp学习 | 前端组 | 2025-10-31,学习UniApp跨平台开发框架,了解其特性和开发流程 | +| 5 | Vue.js学习 | 前端组 | 2025-11-01,深入学习Vue.js前端框架,掌握组件化开发、状态管理等核心概念 | +| 6 | 需求文档编写 | 全体成员 | 2025-10-28,编写系统架构,用例文档,需求文档等 | +| 7 | 技术方案整合 | 全体成员 | 2025-11-02,整合本周学习的技术栈,制定下一阶段的开发计划 | + +## 小结 + +1. **技术学习重点:** 本周重点学习RUOYI框架、UniApp和Vue.js,为后续开发做好技术储备,建议组织技术分享会加深理解。 +2. **数据库设计:** 需要重点关注数据库表结构设计的合理性和扩展性,建议参考相关行业标准。 +3. **原型完善:** 在已有原型基础上进行完善,确保用户体验的流畅性和功能的完整性。 +4. **学习资源:** 希望指导老师能提供RUOYI框架的学习资料和实战案例,以及UniApp和Vue.js的最佳实践指导。 +5. **项目管理:** PM及时推进项目流程,确保技术学习和项目进度同步进行。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-6/group/weekly-summary-06.md b/doc/process/weekly/week-6/group/weekly-summary-06.md new file mode 100644 index 0000000..a454369 --- /dev/null +++ b/doc/process/weekly/week-6/group/weekly-summary-06.md @@ -0,0 +1,35 @@ +# 小组周总结-第6周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 完善原型界面 | 完成 | 2025-10-30,全体成员在上周基础上进行讨论,完善小程序端的原型界面并添加了web端的界面 | +| 2 | 编写需求文档 | 完成 | 2025-10-31,分工合作完成了用例文档第一稿,需求规格说明书,项目前景与范围文档的编写 | +| 3 | 向指导老师展示原型界面并进行改进 | 完成 | 2025-11-02,根据项目需求完成了数据库表结构设计,包括用户表、设备表、数据表等10余张核心表的设计 | +| 4 | 数据库设计 | 完成 | 2025-10-26前,使用微信开发者工具完成原型界面实现 | +| 5 | 软件开发专业知识的初步学习 | 完成 | 2025-10-27到2025-11-02,后端组成员深入学习了RUOYI框架的架构、核心组件和使用方法,掌握了基本的项目结构和配置方式;前端组成员学习了UniApp跨平台开发框架,掌握了其特性和基本开发流程 | + + +## 小结 + +1. **沟通协作:** 本周团队成员配合默契,按照分工顺利完成了各自负责的界面原型开发任务; +2. **学习安排:** 团队成员分别在RUOYI框架、UniApp和Vue.js等关键技术领域取得了显著进步,为后续开发工作奠定了坚实基础 +3. **项目管理:** 项目进度管理pm同学及时推进项目流程,确保项目有条不紊。 +4. **数据库设计完成:** 完成了核心数据库表结构设计,表结构设计合理,具备良好的扩展性和维护性; +5. **原型界面优化:** 在原有原型基础上进行了全面优化,用户体验和功能完整性得到进一步提升; +6. **文档编写进展:** 需求文档和相关技术文档编写工作有序推进,为项目开发提供了规范的文档支持; +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-6/members/liangchenxv-weekly-plan-06.md b/doc/process/weekly/week-6/members/liangchenxv-weekly-plan-06.md new file mode 100644 index 0000000..988998e --- /dev/null +++ b/doc/process/weekly/week-6/members/liangchenxv-weekly-plan-06.md @@ -0,0 +1,34 @@ +# 个人周计划-第6周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 原型评审与优化 | 全体组员,导师 | 2025-10-28 组织原型评审会议,展示完善后的原型界面,收集导师和组员的反馈意见,重点讨论用户体验和功能完整性 | +| 2 | 原型细节完善 | 全体组员 | 根据评审意见,优化界面交互细节,完善页面跳转逻辑,确保原型符合需求规格 | +| 3 | 需求文档编制 | 全体组员 | 基于评审通过的原型,编写详细的需求文档,包括功能需求、非功能需求、用户故事等 | +| 4 | 数据库设计 | 全体组员 | 分析系统需求,设计E-R图,确定实体、属性和关系,完成概念结构设计,将概念模型转化为关系模式,设计不少于10张数据表,明确表结构和关联关系 | + + +## 小结 + +1. **学习需求:** 希望能有对于原型设计以及数据库设计的教学; +2. **知识储备:** 复习数据库知识,为后续的前后端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-6/members/liangchenxv-weekly-summary-06.md b/doc/process/weekly/week-6/members/liangchenxv-weekly-summary-06.md new file mode 100644 index 0000000..59cd74e --- /dev/null +++ b/doc/process/weekly/week-6/members/liangchenxv-weekly-summary-06.md @@ -0,0 +1,39 @@ + +# 个人周总结-第6周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 原型评审与优化 | 完成 | 2025-10-28 成功组织原型评审会议,向导师和组员展示完善后的原型界面,收集到宝贵的反馈意见,重点讨论了用户体验和功能完整性 | +| 2 | 原型细节完善 | 完成 | 根据评审意见,优化了界面交互细节,完善了页面跳转逻辑,确保原型符合需求规格要求 ,并设计制作水管家web端原型 | +| 3 | 需求规格说明书编制 | 完成 | 2025-10-31基于评审通过的原型,参与了需求规格说明书文档的编写工作,完成了web端部分的初稿撰写 | +| 4 | 数据库设计 | 进行中 | 参与了系统需求分析,协助设计了E-R图,确定了主要实体和关系,完成了部分数据表结构设计 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致 +## 小结 + +1. **原型制作:** 完成了web端原型界面的评审和优化工作,界面设计和用户体验得到进一步提升; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-6/members/yangjie-weekly-plan-06.md b/doc/process/weekly/week-6/members/yangjie-weekly-plan-06.md new file mode 100644 index 0000000..a1d318e --- /dev/null +++ b/doc/process/weekly/week-6/members/yangjie-weekly-plan-06.md @@ -0,0 +1,26 @@ +# 个人周计划-第6周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | RUOYI框架深入学习 | 后端组 | 重点学习RUOYI框架的权限管理、代码生成器等核心模块,掌握项目搭建流程 | +| 2 | 数据库表结构设计 | 后端组 | 参与用户表、设备表、数据表等核心表的设计,确保表结构合理性和扩展性 | +| 3 | 数据库SQL优化学习 | 个人 | 学习MySQL索引优化、查询性能调优等相关知识 | +| 4 | 技术方案整合讨论 | 全体组员 | 参与前后端技术栈整合方案讨论,明确接口规范和数据格式 | +| 5 | Spring Boot进阶学习 | 个人 | 深入学习Spring Boot自动配置、事务管理等高级特性 | +| 6 | 原型功能评审 | 全体成员 | 参与原型展示评审,从技术实现角度提出改进建议 | + +## 小结 + +1. **学习需求:** 希望获得RUOYI框架的实际项目案例和最佳实践指导; +2. **技术难点:** 需要理清RUOYI框架中权限管理的实现机制和数据流转过程; +3. **协作需求:** 需要明确前后端接口对接的具体规范和时间节点; +4. **资源支持:** 希望指导老师提供数据库设计评审和技术架构指导。 \ No newline at end of file diff --git a/doc/process/weekly/week-6/members/yangjie-weekly-summary-06.md b/doc/process/weekly/week-6/members/yangjie-weekly-summary-06.md new file mode 100644 index 0000000..d5a8a57 --- /dev/null +++ b/doc/process/weekly/week-6/members/yangjie-weekly-summary-06.md @@ -0,0 +1,33 @@ +# 个人周总结-第6周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | RUOYI框架深入学习 | 完成 | 深入学习了RUOYI框架的核心架构和权限管理模块,掌握了用户认证流程和系统监控功能 | +| 2 | 数据库表结构设计 | 完成 | 参与了用户表、设备表、水质数据表等核心表结构设计,提出了索引优化建议 | +| 3 | 数据库SQL优化学习 | 部分完成 | 学习了MySQL索引基本原理和查询优化技巧,但复杂SQL调优仍需继续学习 | +| 4 | 技术方案整合讨论 | 完成 | 参与了前后端接口规范讨论,明确了数据格式和接口调用方式,统一了技术标准 | +| 5 | Spring Boot进阶学习 | 部分完成 | 学习了Spring Boot自动配置原理,事务管理部分还需深入理解和实践 | +| 6 | 原型功能评审 | 完成 | 从技术实现角度对原型提出了3处改进建议,均被团队采纳 | + +## 对团队工作的建议 + +1. **技术分享深化:** 建议组织RUOYI框架核心模块的源码解析分享,加深全组对框架的理解; +2. **开发环境标准化:** 建议统一开发环境配置,编写详细的环境搭建文档,减少环境问题; +3. **代码规范制定:** 建议制定团队代码规范和注释标准,提高代码可读性和维护性。 + +## 小结 + +1. **框架掌握进展:** 基本掌握了RUOYI框架的核心功能,能够理解权限管理和系统监控的实现原理; +2. **数据库设计能力提升:** 通过参与数据库设计,加深了对数据模型设计和表关系优化的理解; +3. **技术视野拓展:** 通过技术方案讨论,对前后端分离架构和团队协作开发有了更清晰的认识; +4. **后续重点:** 需要继续深入学习RUOYI代码生成器和Spring Boot事务管理,提升实际开发能力; +5. **希望获得的帮助:** 希望指导老师能提供RUOYI框架的实际项目案例,以及数据库设计的最佳实践指导。 \ No newline at end of file diff --git a/doc/process/weekly/week-6/members/yangmohan-weekly-plan-06.md b/doc/process/weekly/week-6/members/yangmohan-weekly-plan-06.md new file mode 100644 index 0000000..db15ff0 --- /dev/null +++ b/doc/process/weekly/week-6/members/yangmohan-weekly-plan-06.md @@ -0,0 +1,30 @@ +# 个人周计划-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-2 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 完成数据库设计 | 个人 | 设计数智水管家系统的数据库表结构,包括用户、设备、数据等核心表 | +| 2 | RUOYI框架本地部署 | 个人 | 在本地环境成功部署RUOYI框架,确保开发环境正常运行 | +| 3 | 继续学习RUOYI相关知识 | 个人 | 深入学习RUOYI框架功能和后端开发技术,为后续开发做准备 | +| 4 | 向陆绍飞老师寻求意见并修改原型 | 陆绍飞老师 | 2025-10-22 与老师沟通原型设计,根据建议修改微信小程序原型 | +| 5 | 完善系统架构设计 | 组员 | 基于老师建议优化整体系统架构,确定技术选型和模块划分 | +| 6 | 编写需求文档 | 个人 | 基于修改后的原型和架构设计编写详细的需求文档 | +| 7 | 讨论任务分配 | 组员 | 2025-10-24 开会汇报进展,讨论后续任务分配 | + +## 小结 + +1. **技术学习:** 重点学习RUOYI框架的部署和使用,掌握后端开发技术; +2. **设计完善:** 通过与陆绍飞老师的沟通,完善原型设计和系统架构; +3. **文档输出:** 完成数据库设计和需求文档的编写,为后续开发奠定基础; +4. **团队协作:** 与组员讨论任务分配,确保项目进度有序推进。 + +--- diff --git a/doc/process/weekly/week-6/members/yangmohan-weekly-summary-06.md b/doc/process/weekly/week-6/members/yangmohan-weekly-summary-06.md new file mode 100644 index 0000000..73ef2ce --- /dev/null +++ b/doc/process/weekly/week-6/members/yangmohan-weekly-summary-06.md @@ -0,0 +1,30 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +|1 | 完成原型界面的uniapp小程序实现并跑通页面与跳转| 完成| 已实现页面展示与路由跳转逻辑,界面可完整运行| +|2 | 完成RUOYI框架本地部署并连接数据库| 完成| 本地环境可启动,已与数据库连通,可在浏览器正常访问| +|3 | 完成软件需求文档小程序端部分编写| 完成| 已提交小程序端SRD内容,覆盖主要业务流程与界面说明| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **小程序实现:** 完成 uniapp 小程序端原型的页面与跳转实现; +2. **框架部署:** 完成 RUOYI 本地部署并与数据库连通,浏览器可正常访问; +3. **文档编写:** 完成软件需求文档中小程序端部分的撰写与提交; + +--- diff --git a/doc/process/weekly/week-6/members/yangshuailu-weekly-plan-06.md b/doc/process/weekly/week-6/members/yangshuailu-weekly-plan-06.md new file mode 100644 index 0000000..e721b16 --- /dev/null +++ b/doc/process/weekly/week-6/members/yangshuailu-weekly-plan-06.md @@ -0,0 +1,32 @@ +# 个人周计划-第六周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11- 2 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ------------- | --- | ------------------------------- | +| 1 | 准备开始数据库设计 | 组员 | 准备和后端的杨捷和梁晨旭一起协作进行数据库设计 | +| 2 | 继续学习有关ruoyi知识 | 个人 | 学习一下ruoyi框架项目的开发方法 | +| 3 | 学习后续有关后端知识 | 组员 | 探索ruoyi项目开发的各个环节和方法,与组员协作完成部分内容 | +| 4 | 原型展示完善 | 组员 | 完善原型界面设计,确保所有功能模块都有对应的原型展示 | + +## 小结 + +1. **学习需求:** 希望能有对于ruoyi的教学,以及数据库设计的思路; +2. **知识储备:** 提前学习后续需要使用的知识,为后续的后端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-6/members/yangshuailu-weekly-summary-06.md b/doc/process/weekly/week-6/members/yangshuailu-weekly-summary-06.md new file mode 100644 index 0000000..09a9573 --- /dev/null +++ b/doc/process/weekly/week-6/members/yangshuailu-weekly-summary-06.md @@ -0,0 +1,41 @@ +# 个人周总结-第六周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-10-27 + +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | --------------- | ---- | ----------------------------------------------------- | +| 1 | 完成数据库初步设计 | 完成 | 已和后端同学协作完成数据库设计,明确核心数据表结构 | +| 2 | 完善原型展示及功能模块补全 | 完成 | 和老师商讨后完善原型界面,增添新功能 | +| 3 | 协作探索后端开发关键环节 | 完成 | 与组员共同梳理 ruoyi 项目开发的全流程 | +| 4 | 深化 ruoyi 框架知识学习 | 部分完成 | 通过实操案例学习 ruoyi 框架的项目开发方法,但是没有完全掌握 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; + +## 小结 + +1. **原型制作:** 和老师交流后完善了原型的制作; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + + + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-6/members/yangzy-weekly-plan-06.md b/doc/process/weekly/week-6/members/yangzy-weekly-plan-06.md new file mode 100644 index 0000000..3e2a804 --- /dev/null +++ b/doc/process/weekly/week-6/members/yangzy-weekly-plan-06.md @@ -0,0 +1,27 @@ +# 个人周计划-第6周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-27 +**结束时间:** 2025-11-02 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp基本学习 | 个人 | 2025-10-27 开始进行Uniapp的基本学习,如基本用法等 | +| 2 | 学习前端知识 | 个人 | 本周内持续学习前端开发,主要是Uniapp相关知识 | +| 3 | 确定分工 | 组员 | 2025-10-29 开会汇报组内各个同学的进展,确定本周的目标 | +| 4 | 原型界面的完善 | 组员 | 2025-10-30完善原型界面设计,确保所有功能模块都有对应的原型展示 | +| 5 | 技术方案整合 | 组员 | 2025-11-02 整合本周学习的技术栈,指定下一阶段的开发计划 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-6/members/yangzy-weekly-summary-06.md b/doc/process/weekly/week-6/members/yangzy-weekly-summary-06.md new file mode 100644 index 0000000..7e6eeeb --- /dev/null +++ b/doc/process/weekly/week-6/members/yangzy-weekly-summary-06.md @@ -0,0 +1,33 @@ + +# 个人周总结-第6周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-10-26 +**结束时间:** 2025-11-02 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | Uniapp基本学习 | 完成 | 2025-10-27对Uniapp的基本操作使用进行了学习 | +| 2 | 个人技能:前端学习 | 完成 | 2025-10-28完成与Uniapp相关的学习 | +| 3 | 学习原型搭建知识 | 完成 | 2025-10-29持续学习Uniapp的使用方法、并通过借鉴其他成熟的界面原型(比如学校的个人门户、教务系统,还有一些成熟商用软件的界面比如淘宝等)完善自己的设计 | +| 4 | 在自己的电脑上部署好小组共同完成的基础界面 |完成 | 2025-10-30成功利用Hbuilder和微信开发者工具实现了本地部署 | +| 5 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-11-02在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-7/group/meeting-minutes-07.md b/doc/process/weekly/week-7/group/meeting-minutes-07.md new file mode 100644 index 0000000..8ff4038 --- /dev/null +++ b/doc/process/weekly/week-7/group/meeting-minutes-07.md @@ -0,0 +1,143 @@ +# 小组会议纪要-第7周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 杨默涵 +**会议主题:** 小程序原型界面展示与老师指导建议 +**会议地点:** 陆绍飞老师办公室 +**会议时间:** 2025-10-28 13:30-14:00 +**纪录时间:** 2025-10-28 14:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路,陆绍飞老师 + +--- + +## 会议内容 + +### 1. 小程序原型界面展示 + + +**(1)原型界面演示内容:** +- 用户登录注册界面及权限验证流程 +- 设备管理模块:设备列表、设备状态监控界面 +- 用水数据可视化展示界面 +- 水质监测数据实时显示页面 +- 滤芯更换工单处理流程界面 +- 个人中心及消息通知界面 + +**(2)技术实现说明:** +- 基于uniapp框架开发,确保多端兼容性 +- 采用Vue3 + Vite技术栈,提升开发效率 +- 界面设计遵循Material Design设计规范 +- 实现了基本的页面跳转和数据处理逻辑 + + + +### 2. 老师指导建议汇总 + + +**(1)设备基本信息及可视化管理:** +- 需要完善设备基础信息管理功能,包括设备型号、安装时间、使用状态等 +- 建议增加设备生命周期管理,记录设备从安装到报废的全过程 +- 设备状态可视化需要更加直观,建议使用颜色编码区分不同状态 +- 增加设备运行数据的历史趋势图表,便于分析设备性能变化 + +**(2)主要用户定位与商业模式:** +- 明确主要用户群体为大型用户(如学校、企业、社区)按批次购买 +- 建议设计批量设备管理功能,支持用户批量操作和统一配置 +- 增加客户分级管理功能,提供差异化服务 + +**(3)外勤管家功能优化:** +- 完善外勤人员工作流程,包括工单接收、执行、反馈等环节 +- 增加外勤人员实时位置跟踪功能,便于调度管理 +- 设计移动端外勤工作台,支持离线操作和数据同步 +- 优化工单分配算法,提高外勤工作效率 + +**(3)饮水机定位及图片指引:** +- 强化地图定位功能,精确显示饮水机分布位置 +- 增加图片导航功能,通过实景图片帮助用户快速找到设备 +- 建议集成第三方地图服务(如高德地图、百度地图) +- 设计设备位置共享功能,方便用户之间的位置分享 + +**(5)Web端界面设计建议:** +- Web端应侧重于数据分析和后台管理功能 +- 设计丰富的数据可视化图表,支持多维度数据分析 +- 优化管理界面操作流程,提高管理员工作效率 +- 确保Web端与小程序端数据同步和体验一致性 + +**(6)配送算法最优路线规划:** +- 开发智能路径规划算法,考虑交通状况、距离、时间等因素 +- 集成实时交通数据,动态调整配送路线 +- 设计批量配送任务的最优分配方案 +- 考虑配送人员的工作负荷均衡,避免过度分配 + +### 3. 原型改进方案讨论 + +**(1)界面优化方向:** +- 根据老师建议,重新设计设备管理界面,增强可视化效果 +- 优化用户操作流程,减少操作步骤,提升用户体验 +- 增加数据导出和报表生成功能 +- 完善权限管理,确保数据安全性 + +**(2)功能扩展计划:** + +- 开发设备预警系统,提前发现潜在问题 +- 设计智能报表系统,自动生成运营分析报告 +- 增加客户服务模块,提升用户满意度 +- 开发移动端扫码功能,简化设备识别流程 + +**(3)技术实现调整:** + +- 优化数据库设计,支持更复杂的数据关系 +- 调整API接口设计,提高数据传输效率 +- 考虑引入消息队列,处理异步任务 +- 完善错误处理和日志记录机制 + + + +--- + +## 问题总结 + +### 已解决问题: +1. 明确了原型界面的改进方向和重点 +2. 获得了老师对产品定位和商业模式的专业指导 +3. 确定了技术实现的优化方案 +4. 调整了开发优先级和时间计划 + +### 待解决问题: +1. 需要详细设计设备可视化管理的具体实现方案 +2. 配送算法需要进一步研究和技术选型 +3. 地图服务的集成方案需要确定 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组成员积极参与讨论,对技术选型和需求分析达成一致意见,团队协作顺畅 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 老师的指导建议对产品方向具有重要指导意义,需要认真落实到具体开发中 +2. 在技术实现过程中,如遇到困难应及时组织技术讨论或寻求老师指导 +3. 注意记录需求变更,及时更新相关文档 + + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-7/group/weekly-plan-07.md b/doc/process/weekly/week-7/group/weekly-plan-07.md new file mode 100644 index 0000000..f9aec02 --- /dev/null +++ b/doc/process/weekly/week-7/group/weekly-plan-07.md @@ -0,0 +1,32 @@ +# 小组周计划-第7周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | RUOYI框架深入学习 | 后端组 | 2025-11-03,继续深入学习RUOYI框架,重点掌握代码生成器的使用方法、数据库的增删改查操作和框架核心组件 | +| 2 | 本地开发环境搭建 | 全体成员 | 2025-11-05,每人独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,要求成功运行若依后台管理系统 | +| 3 | 数据库设计优化 | 后端组 | 2025-11-08,完善数据库设计,重新审视表结构,精简表的数量,提高数据模型的设计合理性 | + +## 小结 + +1. **RUOYI框架深入学习:** 本周继续深入学习RUOYI框架,重点掌握代码生成器的使用方法和数据库增删改查操作,为后续开发打下坚实基础。 +2. **开发环境搭建:** 要求全体成员独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,确保每人能够成功运行若依后台管理系统,为本地开发做好准备。 +3. **数据库设计优化:** 本周将重新审视数据库设计,精简表的数量,提高数据模型的设计合理性和可维护性,避免冗余表的存在。 +4. **学习资源:** 希望指导老师能提供RUOYI框架的完整学习资料和实战案例,特别是代码生成器和数据库操作方面的最佳实践指导。 +5. **团队协作:** PM及时推进项目流程,组织技术分享会,确保全体成员掌握所需技术栈,协调好前后端任务进度。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-7/group/weekly-summary-07.md b/doc/process/weekly/week-7/group/weekly-summary-07.md new file mode 100644 index 0000000..eabe5cb --- /dev/null +++ b/doc/process/weekly/week-7/group/weekly-summary-07.md @@ -0,0 +1,36 @@ +# 小组周总结-第7周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 完善原型界面 | 完成 | 2025-11-07,全体成员在上周基础上进行讨论,修改小程序端的原型界面并尝试使用ruoyi框架构建web端的界面 | +| 2 | 编写用例文档最终稿 | 完成 | 2025-11-07,分工合作完成了用例文档最终稿的编写 | +| 3 | 向指导老师展示原型界面并进行改进 | 完成 | 2025-11-09,跟陆绍飞老师开展腾讯会议进一步明确了各种需求和待办事项 | +| 4 | 数据库设计优化 | 完成 | 2025-11-07,使用power designer完成数据库设计以及导入等 | +| 5 | 小班课进行原型界面评审 | 完成 | 2025-11-07 |课堂展示了原型界面并得到边耐政老师的建议 +| 6 | RUOYI框架本地部署及深入学习 | 完成 | 2025-11-03到2025-11-09,后端组继续深入学习RUOYI框架,全体成员独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,成功运行若依后台管理系统 | + + +## 小结 + +1. **开发环境统一:** 全体成员均成功搭建本地开发环境,包括MySQL、Redis、Node.js和Vue,确保每人能够独立运行若依后台管理系统,为后续开发做好准备。 +2. **学习安排:** 团队成员分别在RUOYI框架、UniApp和Vue.js等关键技术领域取得了显著进步,为后续开发工作奠定了坚实基础 +3. **项目管理:** 项目进度管理pm同学及时推进项目流程,确保项目有条不紊。 +4. **数据库结构优化:** 对数据库设计进行了重新审视和优化,精简了表结构,提升了数据模型的合理性和可维护性,为系统稳定运行奠定基础。 +5. **原型界面优化:** 在原有原型基础上进行了全面优化,用户体验和功能完整性得到进一步提升; +6. **文档编写进展:** 需求文档和相关技术文档编写工作有序推进,为项目开发提供了规范的文档支持; +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-7/members/liangchenxv-weekly-plan-07.md b/doc/process/weekly/week-7/members/liangchenxv-weekly-plan-07.md new file mode 100644 index 0000000..aa16b10 --- /dev/null +++ b/doc/process/weekly/week-7/members/liangchenxv-weekly-plan-07.md @@ -0,0 +1,37 @@ +# 个人周计划-第7周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | RUOYI框架深入学习 | 后端组成员 | 2025-11-03 重点学习RUOYI框架的代码生成器使用方法,掌握数据库的增删改查操作和框架核心组件,完成至少3个模块的代码生成实践 | +| 2 | 原本地开发环境搭建 | 个人完成 | 2025-11-05 独立完成MySQL、Redis、Node.js及Vue本地环境搭建,确保若依后台管理系统能够成功运行,记录搭建过程中的问题与解决方案 | +| 3 | 数据库设计优化 | 全体组员 | 2025-11-08 参与数据库设计的重新审视工作,协助精简表结构,优化数据模型的设计合理性和可维护性,确保表关系清晰 | +| 4 | 技术文档整理 | 个人 | 2025-11-06 整理RUOYI框架学习笔记和开发环境搭建指南,形成技术文档供团队成员参考 + | + + +## 小结 + +1. **技术学习:** 重点掌握RUOYI框架的代码生成器和数据库操作,为后续后端开发工作打好基础; +2. **环境准备:** 确保本地开发环境完整可用,能够独立运行若依后台管理系统; +3. **数据库优化:** 参与数据库设计的优化工作,提升数据模型设计的专业能力; +4. **知识共享:** 希望团队能组织RUOYI框架的技术分享会,交流学习心得和开发经验; +5. **实践应用:** 通过实际搭建和配置环境,加深对前后端分离架构的理解。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-7/members/liangchenxv-weekly-summary-07.md b/doc/process/weekly/week-7/members/liangchenxv-weekly-summary-07.md new file mode 100644 index 0000000..103b023 --- /dev/null +++ b/doc/process/weekly/week-7/members/liangchenxv-weekly-summary-07.md @@ -0,0 +1,39 @@ + +# 个人周总结-第7周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 原型评审与优化 | 完成 | 2025-11-07 成功进行原型评审小班课,向导师和组员展示完善后的原型界面,收集到宝贵的反馈意见,重点讨论了用户体验和功能完整性 | +| 2 | ruoyi学习及部署 | 完成 | 2025-11-05继续深入学习ruoyi,独立完成MySQL、Redis、Node.js及Vue本地环境搭建,确保若依后台管理系统能够成功运行,记录搭建过程中的问题与解决方案 | +| 3 | 用例文档最终稿编制 | 完成 | 2025-11-07基于评审通过的原型,参与了用例文档最终稿文档的编写修改工作 | +| 4 | 数据库设计 | 完成 | 使用power designer完成数据库设计以及导入等 | +| 5 | web端重制 | 进行中 | 尝试使用ruoyi框架进行web端界面的重新制作 | +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致 +## 小结 + +1. **原型制作:** 完成了原型界面的评审和优化工作,界面设计和用户体验得到进一步提升; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-7/members/yangjie-weekly-plan-07.md b/doc/process/weekly/week-7/members/yangjie-weekly-plan-07.md new file mode 100644 index 0000000..00f6874 --- /dev/null +++ b/doc/process/weekly/week-7/members/yangjie-weekly-plan-07.md @@ -0,0 +1,28 @@ +# 个人周计划-第7周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | RUOYI代码生成器深入学习 | 后端组 | 2025-11-03,重点学习代码生成器的配置和使用,掌握自动生成实体类、Mapper、Service、Controller的方法 | +| 2 | RUOYI增删改查操作实践 | 个人 | 2025-11-04,通过实际案例练习RUOYI框架中的CRUD操作,理解数据流转过程 | +| 3 | 本地开发环境完整搭建 | 个人 | 2025-11-05,独立完成MySQL、Redis、Node.js环境配置,确保若依系统在本地成功运行 | +| 4 | 数据库表结构优化设计 | 后端组 | 2025-11-06,参与数据库设计评审,提出优化建议,重点考虑用户表、设备表、水质数据表的关系设计 | +| 5 | RUOYI权限系统研究 | 个人 | 2025-11-07,深入学习RUOYI的权限控制机制,包括菜单权限、按钮权限、数据权限的实现原理 | +| 6 | 技术问题整理与分享 | 全体成员 | 2025-11-08,整理本周学习中的技术难点,参与技术分享会交流解决方案 | + +## 小结 + +1. **学习重点:** 本周重点掌握RUOYI代码生成器的使用和权限系统原理,为后续快速开发奠定基础; +2. **实践需求:** 需要通过实际案例练习代码生成器的配置,生成符合项目需求的模块代码; +3. **环境搭建:** 确保开发环境一次搭建成功,避免后续开发中出现环境问题; +4. **数据库设计:** 需要深入理解项目业务需求,设计出合理的数据模型; +5. **技术交流:** 希望组织代码生成器使用的实操培训,解决配置过程中的常见问题; +6. **资源支持:** 需要RUOYI框架中关于权限管理和代码生成器的详细文档和最佳实践案例。 \ No newline at end of file diff --git a/doc/process/weekly/week-7/members/yangjie-weekly-summary-07.md b/doc/process/weekly/week-7/members/yangjie-weekly-summary-07.md new file mode 100644 index 0000000..bc9a561 --- /dev/null +++ b/doc/process/weekly/week-7/members/yangjie-weekly-summary-07.md @@ -0,0 +1,33 @@ +# 个人周总结-第7周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | RUOYI代码生成器深入学习 | 完成 | 掌握了代码生成器的配置方法,能够独立生成实体类、Mapper、Service和Controller代码 | +| 2 | RUOYI增删改查操作实践 | 完成 | 通过实际案例练习了CRUD操作,理解了数据在框架中的完整流转过程 | +| 3 | 本地开发环境完整搭建 | 完成 | 成功搭建MySQL、Redis、Node.js环境,本地运行若依系统无异常 | +| 4 | 数据库表结构优化设计 | 完成 | 参与数据库设计评审,提出了3处优化建议,精简了2个冗余表设计 | +| 5 | RUOYI权限系统研究 | 部分完成 | 理解了菜单权限和按钮权限的实现,数据权限部分仍需进一步研究 | +| 6 | 技术问题整理与分享 | 完成 | 整理了环境搭建中的常见问题,在技术分享会上进行了交流分享 | + +## 对团队工作的建议 + +1. **环境标准化:** 建议制定统一的环境配置手册,减少因环境差异导致的问题; +2. **代码生成规范:** 建议建立代码生成器的使用规范,确保生成的代码符合团队标准; +3. **数据库设计评审机制:** 建议建立定期的数据库设计评审机制,确保数据模型的合理性。 + +## 小结 + +1. **代码生成器掌握:** 熟练掌握了RUOYI代码生成器的使用方法,能够快速生成标准代码模块; +2. **开发环境完善:** 本地开发环境搭建成功,为后续开发工作做好了充分准备; +3. **数据库设计能力提升:** 通过参与优化设计,加深了对数据库表关系和性能优化的理解; +4. **后续重点:** 需要继续深入研究RUOYI数据权限控制和复杂业务场景的实现; +5. **希望获得的帮助:** 希望有经验的同事能够指导RUOYI框架在复杂业务逻辑中的最佳实践。 \ No newline at end of file diff --git a/doc/process/weekly/week-7/members/yangmohan-weekly-plan-07.md b/doc/process/weekly/week-7/members/yangmohan-weekly-plan-07.md new file mode 100644 index 0000000..e59162b --- /dev/null +++ b/doc/process/weekly/week-7/members/yangmohan-weekly-plan-07.md @@ -0,0 +1,27 @@ +# 个人周计划-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-3 +**结束时间:** 2025-11-9 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | 完成数据库设计 | 个人 | 设计数智水管家系统的数据库表结构,明确实体、关系与索引 | +| 2 | 将本地数据库连接到 RuoYi 后台 | 个人 | 在本地 RuoYi 中配置数据源并联通,完成基础 CRUD 验证 | +| 3 | 学习 RuoYi 代码生成与数据库管理 | 个人 | 掌握代码生成器使用、字典配置、字段注释与表同步流程 | +| 4 | 梳理前后端接口设计 | 个人 | 明确资源路由、请求/响应模型与错误码,为后续开发做准备 | + +## 小结 + +1. **技术学习:** 聚焦 RuoYi 代码生成与数据库管理的实操能力; +2. **系统对接:** 本地数据库成功接入 RuoYi 并完成联调验证; +3. **设计完善:** 完成核心数据库设计与必要索引/字典配置; +4. **接口规划:** 产出前后端接口清单与数据模型约定,为开发铺路。 + +--- diff --git a/doc/process/weekly/week-7/members/yangmohan-weekly-summary-07.md b/doc/process/weekly/week-7/members/yangmohan-weekly-summary-07.md new file mode 100644 index 0000000..a848f21 --- /dev/null +++ b/doc/process/weekly/week-7/members/yangmohan-weekly-summary-07.md @@ -0,0 +1,30 @@ + +# 个人周总结-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +|1 | 完成RUOYI框架导入本地数据库并使用内置生成代码实现增删改查| 完成| 已完成数据表导入与代码生成,增删改查功能可稳定运行| +|2 | 完成数据库设计并编写数据库设计文档初始版本| 完成| 已梳理业务实体与表结构,提交初版数据库设计文档| +|3 | 调整小程序流程与界面以提升用户体验| 完成| 已优化核心流程与界面交互,符合主要用户使用习惯| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **RUOYI 集成:** 将本地数据库导入 RUOYI 并使用代码生成器完成增删改查功能; +2. **数据库设计:** 设计业务数据模型并完成数据库设计文档初始稿; +3. **小程序优化:** 调整小程序流程与界面以提升用户使用体验; + +--- diff --git a/doc/process/weekly/week-7/members/yangshuailu-weekly-plan-07.md b/doc/process/weekly/week-7/members/yangshuailu-weekly-plan-07.md new file mode 100644 index 0000000..e1f21f4 --- /dev/null +++ b/doc/process/weekly/week-7/members/yangshuailu-weekly-plan-07.md @@ -0,0 +1,31 @@ +# 个人周计划-第七周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11- 09 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ----------- | --- | --------------------------------------------------- | +| 1 | RUOYI框架深入学习 | 组员 | 继续深入学习RUOYI框架,重点掌握代码生成器的使用方法、数据库的增删改查操作和框架核心组件 | +| 2 | 本地开发环境搭建 | 个人 | 每人独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,要求成功运行若依后台管理系统 | +| 3 | 数据库设计优化 | 组员 | 完善数据库设计,重新审视表结构,精简表的数量,提高数据模型的设计合理性 | + +## 小结 + +1. **学习需求:** 在网络上查找ruoyi教程,并寻求同学或者大模型帮助; +2. **环境搭建:** 确保在 2025-11-05 前完成本地开发环境搭建,为后续开发做好准备; +3. **协作配合:** 主动与后端组组员协作,共同推进数据库设计优化工作,确保工作高效完成。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-7/members/yangshuailu-weekly-summary-07.md b/doc/process/weekly/week-7/members/yangshuailu-weekly-summary-07.md new file mode 100644 index 0000000..7881dc9 --- /dev/null +++ b/doc/process/weekly/week-7/members/yangshuailu-weekly-summary-07.md @@ -0,0 +1,38 @@ +# 个人周总结-第七周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-11-03 + +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ------------ | ---- | -------------------------------------------------- | +| 1 | RUOYI 框架深入学习 | 部分完成 | 掌握了代码生成器基本使用方法,但对框架核心组件的理解仍需加深 | +| 2 | 数据库设计优化 | 完成 | 与组员共同梳理表结构,提升了数据模型的合理性和扩展性 | +| 3 | 本地开发环境搭建 | 完成 | 成功搭建 MySQL、Redis、Node.js 及 Vue 本地环境,已能正常运行若依后台管理系统 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; + +## 小结 + +1. **技能提升:** 通过实践操作,对 RUOYI 框架的应用更加熟练,但核心原理部分仍需加强学习; +2. **环境保障:** 本地开发环境的成功搭建为后续开发工作奠定了基础; +3. **协作成果:** 数据库设计优化工作的完成,提升了项目数据层的稳定性; +4. **帮助需求:** 希望能有关于 RUOYI 框架核心组件原理的专题讲座,加深对框架底层逻辑的理解。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-7/members/yangzy-weekly-plan-07.md b/doc/process/weekly/week-7/members/yangzy-weekly-plan-07.md new file mode 100644 index 0000000..ac833ad --- /dev/null +++ b/doc/process/weekly/week-7/members/yangzy-weekly-plan-07.md @@ -0,0 +1,27 @@ +# 个人周计划-第7周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp基本学习 | 个人 | 2025-11-04 继续进行Uniapp的基本学习,如基本用法等 | +| 2 | 学习前端知识 | 个人 | 本周内持续学习前端开发,主要是Uniapp相关知识 | +| 3 | Uniapp的进阶学习 | 个人 | 2025-11-06 开始进行Uniapp的进阶使用学习 | +| 4 | 本地开发环境搭建 | 个人 | 2025-11-07独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,要成功运行若依后台管理系统 | +| 5 | 技术方案整合 | 组员 | 2025-11-09 整合本周学习的技术栈,指定下一阶段的开发计划 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-7/members/yangzy-weekly-summary-07.md b/doc/process/weekly/week-7/members/yangzy-weekly-summary-07.md new file mode 100644 index 0000000..a7ac59c --- /dev/null +++ b/doc/process/weekly/week-7/members/yangzy-weekly-summary-07.md @@ -0,0 +1,32 @@ +# 个人周总结-第7周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-03 +**结束时间:** 2025-11-09 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | Uniapp基本学习 | 完成 | 2025-11-04 继续进行了Uniapp的基本学习,如基本用法等 | +| 2 | 个人技能:前端学习 | 完成 | 2025-11-05持续学习了前端开发,主要是Uniapp相关知识 | +| 3 | Uniapp的进阶学习 | 完成 | 2025-11-06持续学习Uniapp的使用方法,基本掌握了一些Uniapp的进阶使用方法 | +| 4 | 本地开发环境搭建 |完成 | 2025-11-07独立完成MySQL、Redis、Node.js以及Vue本地环境搭建,要成功运行若依后台管理系统 | +| 5 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-11-09在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-8/group/meeting-minutes-08.md b/doc/process/weekly/week-8/group/meeting-minutes-08.md new file mode 100644 index 0000000..35d793d --- /dev/null +++ b/doc/process/weekly/week-8/group/meeting-minutes-08.md @@ -0,0 +1,129 @@ +# 小组会议纪要-第8周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 小程序原型界面展示与老师指导建议-2 +**会议地点:** 腾讯会议 +**会议时间:** 2025-11-10 17:40-18:40 +**纪录时间:** 2025-11-10 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路,陆绍飞老师 + +--- + +## 会议内容 +会议讨论了产品各模块的界面规划,明确了首页、水质分析、工单派发等功能的待办事项。 +### 1. 小程序原型界面展示 + + +**(1)原型界面演示内容:** +- 简化首页设计,移除近七天用水量显示​​。将问题设备直接展示在首页,方便用户快速查看和操作,支持一键换购和支付 +- 展示了订单管理、支付界面和消息界面 +- 用水数据可视化展示界面 +- 水质监测数据实时显示页面 +- 滤芯更换工单处理流程界面 + + + + +### 2. 老师指导建议汇总 + + +**(1)用户端首页界面规划:** +- 首页应突出显示用户关切的信息,如设备异常、水质异常及滤芯更换提醒。 +- “近七天用水量”指标无需在首页展示,可移至其他页面。 +- 工单、订单与客户服务等相关功能模块也应在首页提供入口。 +- 未进行登录认证的用户,可通过微信直接登录进入应用。 + +**(2)水质与设备信息展示:** +- 设备详情页应强化水质分析功能,采用折线图展示近一段时间内水质的变化趋势。 +- 为方便用户理解,水质图表中需增加各项指标的国家标准或行业标准参考范围线。 +- 建议将不同设备的水质界面统一成通用模板,通过替换设备ID来实现。 +- 水质信息报告也需在设备详情页上进行展示。 + +**(3)工单处理功能:** +- 应用中存在普通用户和工作人员两种角色,通过不同账号体系区分。 +- 工单系统需定义清晰的状态,如“系统派发但未确认”、“已确认/未处理”、“已完成/处理中”,以便用户理解和管理。 +- 工作人员处理派单时,平台应给予其拒接任务的权限。通过对接后台的反馈,实现动态的任务重派。 + +**(4)地图导航功能:** +- 配送路线管理中集成的地图导航功能,应能直接在小程序内调用外部地图APP(如百度地图),并支持跳转至具体位置的导航。 + +**(5)后台管理:** +- 后台管理端不仅需要支持数据的增、删、改、查,还需具备派单、审核、人工打单及客服等管理员职责。 +- Web端为后台管理员提供了在桌面端工作、查看和处理任务的环境。 + + + +### 3. 原型改进待办讨论 + +**(1)确定水质指标及相关标准:** +- 需明确产品的水质检测具体包含哪些指标,并查询各指标的单位及其国家标准范围,并据此设计相应的图表。 + +**(2)完善工单系统功能:** + +- 明确并优化工单系统的多个状态定义,确保逻辑清晰,易于用户理解和操作。 + +**(3)优化导航功能:** + +- 评估支持访问百度地图,并利用其API在小程序内直接调用导航功能的可行性。 + +**(4)提升用户体验:** +- 在前端页面增加更快的加载速度和更详细的文档说明,以提升用户的上手体验。 + +--- + +## 问题总结 + +### 已解决问题: +1. 首页设计定稿: 明确了首页以问题设备告警和核心操作(一键换购) 为核心,移除“近七天用水量”显示,优化了信息架构与用户体验。 +2. 水质展示方案确认: 确定了在设备详情页使用折线图展示水质趋势,并需增加国家标准参考线,统一了不同设备的水质界面模板。 +3. 角色与工单流程明确: 清晰区分了普通用户与工作人员的角色,并确定了工单的关键状态(如“系统派发未确认”、“已确认/未处理”) 以及工作人员的拒接与重派机制。 +4. 关键功能技术路径确定: 明确了地图导航将通过调用外部地图APP(如百度地图)实现,并确认了Web后台需具备派单、审核等完整的管理职责。 + +### 待解决问题: +1. 水质指标与标准落地: +需明确小程序具体检测哪些水质指标(如TDS、pH值等)。 +查询并确定每个指标的国家标准范围或行业推荐值,以便在图表中绘制参考线。 + +2. 工单状态系统细化: +需要设计并明确工单在生命周期中的所有状态流转逻辑,确保状态定义清晰,无歧义。 + +3. 地图API集成可行性验证: +技术层面需要评估并测试调用百度地图API以实现小程序内一键导航的具体方案与可行性。 + +4. 用户体验优化执行: +需要落实前端性能优化措施,以提升页面加载速度,并补充必要的操作指引与文档说明,降低用户使用门槛。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组成员积极参与讨论,对技术选型和需求分析达成一致意见,团队协作顺畅 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 老师的指导建议对产品方向具有重要指导意义,需要认真落实到具体开发中 +2. 在技术实现过程中,如遇到困难应及时组织技术讨论或寻求老师指导 +3. 注意记录需求变更,及时更新相关文档 + + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-8/group/weekly-plan-08.md b/doc/process/weekly/week-8/group/weekly-plan-08.md new file mode 100644 index 0000000..b015224 --- /dev/null +++ b/doc/process/weekly/week-8/group/weekly-plan-08.md @@ -0,0 +1,34 @@ +# 小组周计划-第8周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | RUOYI框架深入学习与总结 | 后端组 | 2025-11-10,梳理框架核心模块、权限体系及代码生成器实操心得,形成学习笔记 | +| 2 | 数据库设计文档完善 | 后端组 | 2025-11-12,补充ER图和数据字典,核对主外键及约束,提交评审版本 | +| 3 | 系统总用例图编写 | 全体成员 | 2025-11-13,完成角色与用例梳理并绘制总用例图,确保与需求一致 | +| 4 | 主要业务建模图绘制 | 分析组 | 2025-11-14,完成核心场景的活动图、顺序图和类图,并与用例图保持一致 | +| 5 | 与老师确认开发计划 | PM | 2025-11-15,准备里程碑计划与资源清单,和指导老师沟通并定稿开发日程 | + +## 小结 + +1. **RUOYI框架深入学习:** 持续深化对框架核心组件、权限体系和代码生成器的理解,沉淀可复用的操作手册。 +2. **数据库设计文档:** 完成实体关系、字段说明和约束校验,确保数据库模型支撑后续实现。 +3. **系统建模文档:** 输出总用例图以及关键业务的活动图、顺序图和类图,为开发提供统一视图。 +4. **开发计划确认:** 准备详尽的开发排期,与指导老师沟通确认整体进度和支撑需求。 +5. **学习资源:** 希望老师提供若依框架案例与建模示例,便于验证设计并优化文档质量。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-8/group/weekly-summary-08.md b/doc/process/weekly/week-8/group/weekly-summary-08.md new file mode 100644 index 0000000..251e22d --- /dev/null +++ b/doc/process/weekly/week-8/group/weekly-summary-08.md @@ -0,0 +1,35 @@ +# 小组周总结-第8周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | RUOYI框架深入学习与总结 | 完成 | 2025-11-14,后端组系统梳理了框架核心模块、权限体系及代码生成器使用技巧| +| 2 | 数据库设计文档完善 | 完成 | 2025-11-16,形成了可评审的数据库设计文档 | +| 3 | 与老师确认开发计划 | 完成 | 2025-11-15,PM准备了详细的里程碑计划,与指导老师沟通确认了阿尔法版本的开发日程和资源安排 | +| 4 | 设计迭代开发计划 | 完成 | 2025-11-05,编写了迭代开发计划第一稿 | +| 5 | 主要业务建模图绘制 | 进行中 | 正在编写核心业务场景的活动图、顺序图和类图,保持了与用例图的一致性 + + + +## 小结 + +1. **技术框架掌握深化:** 通过系统梳理RUOYI框架的核心组件和代码生成器,团队对技术栈的理解更加深入,为后续开发工作奠定了坚实基础。 +2. **设计文档完善:** 完成了数据库设计文档的ER图和数据字典补充,以及系统建模文档的绘制,为开发阶段提供了清晰的技术蓝图。 +3. **开发计划明确:** 与指导老师确认了阿尔法版本的开发里程碑和排期,明确了后续5-6周的核心任务和交付目标。 +4. **团队协作高效:** 各小组按分工顺利完成设计任务,分析组、后端组和PM之间的协作顺畅,确保了文档质量的一致性。 +5. **文档编写进展:** 相关技术文档编写工作有序推进,为项目开发提供了规范的文档支持; +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-8/members/liangchenxv-weekly-plan-08.md b/doc/process/weekly/week-8/members/liangchenxv-weekly-plan-08.md new file mode 100644 index 0000000..3b1eda3 --- /dev/null +++ b/doc/process/weekly/week-8/members/liangchenxv-weekly-plan-08.md @@ -0,0 +1,37 @@ +# 个人周计划-第8周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | RUOYI框架深入学习 | 后端组成员 | 2025-11-10,梳理框架核心模块、权限体系及代码生成器实操心得,形成学习笔记 | +| 2 | 数据库设计文档完善 | 后端组 | 2025-11-12,补充ER图和数据字典,核对主外键及约束,提交评审版本 | +| 3 | 主要业务建模图绘制 | 全体组员 | 本周内完成活动图的编制 | +| 4 | web端界面开发 | 个人 | 2025-11-06 使用RUOYI框架的代码生成功能改善web端界面 +| 5 | 与老师联系讨论 α/β 版本迭代计划 | 陆绍飞 | 明确功能优先级、里程碑与风险应对 | + + +## 小结 + +1. **技术学习:** 重点掌握RUOYI框架的代码生成器,为后续后端开发工作打好基础; +2. **环境准备:** 确保本地开发环境完整可用,能够独立运行若依后台管理系统; +3. **数据库优化:** 参与数据库设计的优化工作,提升数据模型设计的专业能力; +4. **知识共享:** 希望团队能组织RUOYI框架的技术分享会,交流学习心得和开发经验; +5. **实践应用:** 通过实际搭建和配置环境,加深对前后端分离架构的理解。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-8/members/liangchenxv-weekly-summary-08.md b/doc/process/weekly/week-8/members/liangchenxv-weekly-summary-08.md new file mode 100644 index 0000000..9aed54f --- /dev/null +++ b/doc/process/weekly/week-8/members/liangchenxv-weekly-summary-08.md @@ -0,0 +1,39 @@ + +# 个人周总结-第8周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | RUOYI框架深入学习 | 完成 | 2025-11-10,与后端组成员共同梳理了框架核心模块、权限体系,重点掌握了代码生成器的使用技巧,提升了开发效率 | +| 2 | 主要业务建模图绘制 | 进行中 | 本周持续进行活动图的绘制编写 | +| 3 | web端界面开发 | 完成 | 2025-11-16,运用RUOYI框架的代码生成功能,初步实现web端管理界面的设计与修改 | +| 4 | 与老师讨论α/β版本迭代计划 | 完成 | 与陆绍飞老师明确了初代阿尔法版本的开发计划等,为后续开发提供了清晰指导 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致 +## 小结 + +1. **开发实践成果:** 成功运用代码生成器改善了web端界面,验证了技术学习的实际应用价值; +2. **技能学习:** 通过深入学习RUOYI框架,特别是代码生成器的实践应用,显著提升了后端开发效率和项目搭建能力; +3. **项目规划参与:** 参与α/β版本迭代计划的讨论,对项目整体进度和风险管控有了更深入的理解; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-8/members/yangjie-weekly-plan-08.md b/doc/process/weekly/week-8/members/yangjie-weekly-plan-08.md new file mode 100644 index 0000000..9e8c15b --- /dev/null +++ b/doc/process/weekly/week-8/members/yangjie-weekly-plan-08.md @@ -0,0 +1,26 @@ +# 个人周计划-第8周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | RUOYI框架核心模块总结 | 个人 | 2025-11-10,系统梳理权限管理、代码生成器等核心模块,整理操作手册和技术笔记 | +| 2 | 数据库ER图绘制与优化 | 后端组 | 2025-11-11,基于现有表结构绘制ER图,重点完善用户-设备-数据表之间的关系设计 | +| 3 | 数据字典详细编写 | 后端组 | 2025-11-12,完善所有表的字段说明、数据类型、约束条件等,形成标准化文档 | +| 4 | 数据库设计文档整合 | 后端组 | 2025-11-13,整合ER图和数据字典,完成数据库设计评审版本的准备工作 | + + +## 小结 + +1. **技术沉淀:** 重点完成RUOYI框架的系统性总结,形成可复用技术文档; +2. **数据库设计:** 确保数据库设计文档的专业性和完整性,为后续开发奠定基础; +3. **技术评审:** 积极参与系统建模的技术评审,保证设计方案的技术可行性; +4. **风险评估:** 协助识别开发计划中的技术风险,提出应对方案; +5. **学习需求:** 希望获得数据库设计评审的专业指导和系统建模的规范示例。 \ No newline at end of file diff --git a/doc/process/weekly/week-8/members/yangjie-weekly-summary-08.md b/doc/process/weekly/week-8/members/yangjie-weekly-summary-08.md new file mode 100644 index 0000000..b2ad171 --- /dev/null +++ b/doc/process/weekly/week-8/members/yangjie-weekly-summary-08.md @@ -0,0 +1,32 @@ +# 个人周总结-第8周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | RUOYI框架核心模块总结 | 完成 | 系统整理了权限管理和代码生成器的使用手册,形成了系统的技术笔记,包含详细的操作步骤和注意事项 | +| 2 | 数据库ER图绘制与优化 | 完成 | 完成了完整的ER图设计,优化了用户-设备-水质数据之间的关联关系,消除了数据冗余 | +| 3 | 数据字典详细编写 | 完成 | 编写了完整的数据字典,明确了所有表的字段类型、约束条件和业务含义 | +| 4 | 数据库设计文档整合 | 完成 | 整合了ER图和数据字典,形成了规范的数据库设计文档,已提交评审 | +| 5 | 系统用例图技术评审 | 完成 | 从技术实现角度提出了多处改进建议,大部分被采纳,提高了用例的可实现性 | +| 6 | 开发计划技术可行性分析 | 完成 | 识别出技术风险点,并提供了相应的解决方案,协助PM完善了开发计划 | + +## 对团队工作的建议 + +1. **文档管理规范:** 建议建立团队文档管理规范,统一文档格式和版本控制; +2. **技术评审机制:** 建议建立定期的技术评审机制,确保设计文档的质量; +3. **知识共享平台:** 建议搭建团队知识库,方便技术文档和经验的沉淀与共享。 + +## 小结 + +1. **技术文档成果:** 完成了RUOYI框架的详细技术总结和数据库设计文档,为团队积累了重要技术资产; +2. **数据库设计能力:** 通过完整的数据库设计流程,系统掌握了从需求分析到文档输出的全过程; +3. **技术评审经验:** 在系统建模评审中发挥了后端技术优势,提高了设计方案的可实施性; +4. **后续重点:** 需要开始准备具体模块的开发工作,将设计转化为代码实现; \ No newline at end of file diff --git a/doc/process/weekly/week-8/members/yangmohan-weekly-plan-08.md b/doc/process/weekly/week-8/members/yangmohan-weekly-plan-08.md new file mode 100644 index 0000000..5871035 --- /dev/null +++ b/doc/process/weekly/week-8/members/yangmohan-weekly-plan-08.md @@ -0,0 +1,27 @@ +# 个人周计划-第4周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------------------------------------- | ------ | -------- | +| 1 | 编写数据库文档 | 个人 | 梳理数据字典、ER 图与字段说明,补齐历史缺口 | +| 2 | 继续学习 RuoYi 框架 | 个人 | 深入掌握权限模块与工作流配置,整理学习笔记 | +| 3 | 讨论补充系统总体用例文档 | 团队 | 与成员对齐业务流程,完善用例描述与边界条件 | +| 4 | 监制主要业务功能的活动图、顺序图和类图 | 团队 | 指导建模产出,确保与实际需求一致 | +| 5 | 与老师联系讨论 α/β 版本迭代计划 | 陆绍飞 | 明确功能优先级、里程碑与风险应对 | + +## 小结 + +1. **文档完善:** 完成数据库文档与系统用例的更新,确保资料可查可用; +2. **框架深化:** 掌握 RuoYi 更深入的功能模块,为后续开发打基础; +3. **建模把控:** 监督活动图、顺序图、类图质量,统一团队设计视图; +4. **迭代规划:** 与老师确认 α/β 版本的迭代计划,明确阶段目标与交付节奏。 + +--- diff --git a/doc/process/weekly/week-8/members/yangmohan-weekly-summary-08.md b/doc/process/weekly/week-8/members/yangmohan-weekly-summary-08.md new file mode 100644 index 0000000..9bf6dec --- /dev/null +++ b/doc/process/weekly/week-8/members/yangmohan-weekly-summary-08.md @@ -0,0 +1,30 @@ + +# 个人周总结-第8周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +|1 | 已完成迭代开发计划第一版| 完成| 已完成迭代开发计划第一版| +|2 | 与指导老师开会,完成对小程序的功能大致演示,并获取了迭代开发指导意见| 完成| 已完成小程序功能演示,获得指导老师的迭代开发指导意见| +|3 | 数据库v2.0设计完成,基本符合要求,已提交数据库设计文档| 完成| 数据库v2.0设计完成,基本符合要求,已提交数据库设计文档| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **迭代开发计划:** 已完成迭代开发计划第一版; +2. **项目汇报:** 与指导老师开会,完成对小程序的功能大致演示,并获取了迭代开发指导意见; +3. **数据库设计:** 数据库v2.0设计完成,基本符合要求,已提交数据库设计文档; + +--- diff --git a/doc/process/weekly/week-8/members/yangshuailu-weekly-plan-08.md b/doc/process/weekly/week-8/members/yangshuailu-weekly-plan-08.md new file mode 100644 index 0000000..82207db --- /dev/null +++ b/doc/process/weekly/week-8/members/yangshuailu-weekly-plan-08.md @@ -0,0 +1,32 @@ +# 个人周计划-第八周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-11-10 + +**结束时间:** 2025-11-16 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | ----------- | ------------------------------ | ------------------------------------------ | +| 1 | RUOYI框架深入学习 | 组员 | 重点研究框架的权限管理模块、代码生成器原理及核心配置文件,整理学习笔记并同步给组内 | +| 2 | 数据库设计文档细化 | 组员 | 参与 ER 图补充完善,核对各表主外键关系,编写数据字典中字段的类型、长度及约束说明 | +| 3 | 系统总用例图角色梳理 | 组员 | 配合梳理后端相关角色的权限范围及对应用例,确保用例图与后端实现逻辑匹配 | + +## 小结 + +1. **学习支持:** 希望能获取 RUOYI 框架权限模块的实际开发案例,便于更深入理解其实现逻辑; +2. **协作需求:** 数据库设计过程中需与分析组同步业务需求,确保设计符合实际场景; +3. **进度保障:** 每日同步任务进展至后端组群,及时解决学习和设计中遇到的技术卡点。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-8/members/yangshuailu-weekly-summary-08.md b/doc/process/weekly/week-8/members/yangshuailu-weekly-summary-08.md new file mode 100644 index 0000000..2a9f94c --- /dev/null +++ b/doc/process/weekly/week-8/members/yangshuailu-weekly-summary-08.md @@ -0,0 +1,39 @@ +# 个人周总结-第八周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-11-10 + +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | ------------ | ---- | -------------------------------------------------- | +| 1 | RUOYI 框架深入学习 | 大致完成 | 研究了框架的权限管理模块、代码生成器原理及核心配置文件 | +| 2 | 数据库设计文档细化 | 完成 | 参与 了ER 图补充完善,核对各表主外键关系,编写了数据字典中字段的类型、长度及约束说明 | +| 3 | 主要业务建模图绘制 | 完成 | 和小组成员杨婕一起完成了业务建模中类图的设计 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; + +## 小结 + +1. **技能提升:** 通过实践操作,对 RUOYI 框架的应用更加熟练,但核心原理部分仍需加强学习; +2. **环境保障:** RUOYI框架的学习为后续开发工作奠定了基础; +3. **协作成果:** 数据库设计优化工作的完成,提升了项目数据层的稳定性; + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; + + diff --git a/doc/process/weekly/week-8/members/yangzy-weekly-plan-08.md b/doc/process/weekly/week-8/members/yangzy-weekly-plan-08.md new file mode 100644 index 0000000..72c16f1 --- /dev/null +++ b/doc/process/weekly/week-8/members/yangzy-weekly-plan-08.md @@ -0,0 +1,26 @@ +# 个人周计划-第8周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-11-10 继续进行Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 学习前端知识 | 个人 | 本周内持续学习前端开发,主要是Uniapp相关知识 | +| 3 | 系统总用例图编写 | 组员 | 2025-11-13 完成我所负责的顺序图结构,并和组内的同学进行整合 | +| 4 | 技术方案整合 | 组员 | 2025-11-16 整合本周学习的技术栈,指定下一阶段的开发计划 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-8/members/yangzy-weekly-summary-08.md b/doc/process/weekly/week-8/members/yangzy-weekly-summary-08.md new file mode 100644 index 0000000..b018948 --- /dev/null +++ b/doc/process/weekly/week-8/members/yangzy-weekly-summary-08.md @@ -0,0 +1,32 @@ +# 个人周总结-第8周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-10 +**结束时间:** 2025-11-16 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-11-10 继续进行了Uniapp的进阶学习 | +| 2 | 个人技能:前端学习 | 完成 | 2025-11-11 持续学习了前端开发,主要是Uniapp相关知识 | +| 3 | 系统总用例图编写(主要是顺序图的绘制) | 完成 | 2025-11-13 正在进行小组项目的顺序图绘制,目前已经部分完成 | +| 4 | 技术方案整合 |完成 | 2025-11-15 整合本周学习的技术栈,指定下一阶段的开发计划 | +| 5 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-11-16 在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/process/weekly/week-9/group/meeting-minutes-09.md b/doc/process/weekly/week-9/group/meeting-minutes-09.md new file mode 100644 index 0000000..95e4c70 --- /dev/null +++ b/doc/process/weekly/week-9/group/meeting-minutes-09.md @@ -0,0 +1,100 @@ +# 小组会议纪要-第9周 + +## 会议记录概要 + +**团队名称:** 1班-羊了个羊 +**指导老师:** 陆绍飞 +**主 持 人:** 杨默涵 +**记录人员:** 梁晨旭 +**会议主题:** 小程序原型界面改进及迭代开发讨论 +**会议地点:** 腾讯会议 +**会议时间:** 2025-11-15 11:00-12:00 +**纪录时间:** 2025-11-15 19:00 +**参与人员:** 杨默涵,梁晨旭,杨捷,杨振宇,杨帅路,陆绍飞老师 + +--- + +## 会议内容 +本次会议主要围绕后台维护系统的优化方案展开,讨论了用户体验、功能架构及开发计划,并明确了后续需进行的产品规划。 +### 1. 小程序原型界面展示 + + +**(1) 用户评价与工单关联​​** + +- 用户可在订单完成后进行评价,评价结果与对应的订单及上门师傅关联。 +- 提出了将“订购”和“维修/服务”两种单据进行功能分离的建议,使业务逻辑更清晰。 + +**(​2) 维修配送路线优化​​** + +- 系统支持跳转至外部地图APP进行导航。 +- 计划开发基于地图API的道路距离计算及最优路径算法,初始版本仅考虑直线距离,避免过于复杂的交通状况影响。 + +​**(​3) 后台管理与开发模式​​** + +- 由测评系统转向后台管理Web端,以实现对工单的完整闭环管理,后台同时使用MySQL和Redis作为技术栈。 +- 明确了采用双版本迭代的开发与发布策略:首先发布首个“Alpha版”,包含全部核心闭环功能;后续再通过“Beta版”衔接迭代补充新功能。 + + + +### 2. 迭代开发待办讨论 + +**(1)确定阿尔法版本大致内容:** +- 指导老师强调当前版本已完成80%,建议先发布一个可运行的核心功能版本(阿尔法版),后续通过迭代方式逐步叠加功能。 + +**(2)阿尔法版本周期安排:** + +- 阿尔法版本开发周期为5-6周,​​当前进度已超出预期​​,之后可以尝试使用飞书进行进度管理。 + +**(3)指导老师建议:** + +- 老师额外布置了水质监测指标的任务,​​建议以该创新点作为跨领域需求​​。 + + + +--- + +## 问题总结 + +### 已解决问题: +1. 核心功能闭环确认:明确了阿尔法版本的核心范围,即构建一个包含用户下单→工单生成→师傅处理→用户评价的完整业务流程闭环,系统角色从“测评系统”正式转向“后台管理Web端”。 +2. 技术架构与开发模式统一:确定了后台系统采用 MySQL + Redis 的技术栈,并明确了双版本迭代策略(先发布功能完整的Alpha版,再通过Beta版迭代新功能)。 +3. 关键交互设计落地: +明确了用户评价需与订单及上门师傅关联的业务逻辑。 +确定了维修配送将支持跳转外部地图导航,并规划了路径算法从简(直线距离)到繁的演进路线。 +4. 项目进度与管理优化:确认当前进度(80%)已超预期,阿尔法版本周期为5-6周,并计划引入飞书进行项目进度管理。 + +### 待解决问题: +1. 阿尔法版本范围细化:需在“核心功能闭环”的基础上,进一步明确和细化Alpha版本必须包含的具体功能清单,确定功能的优先级与取舍。 +2. 水质监测创新点方案设计:需要将老师提出的“水质监测指标”这一跨领域需求,转化为具体的技术方案和产品功能,并规划其融入现有业务逻辑的路径(例如:何种数据、如何展示、触发何种告警或服务)。 +3. 业务单据分离的设计与实现:需要详细设计“订购”与“维修/服务”两类单据分离后的数据模型、业务流程与前端界面。 +4. 路径规划算法的初步实现:需要完成基于地图API的直线距离计算与路径规划模块的开发,并为后续引入更复杂的交通因素预留架构空间。 + + +--- + +## 小组协作情况总结 + +1. **协作情况:** 小组成员积极参与讨论,对技术选型和需求分析达成一致意见,团队协作顺畅 + +## 一周纪律情况总结 + +1. **纪律情况:** 小组成员按时参加会议,讨论认真,会议氛围良好 + +--- + + +## 备注 + +1. 老师的指导建议对产品方向具有重要指导意义,需要认真落实到具体开发中 +2. 在技术实现过程中,如遇到困难应及时组织技术讨论或寻求老师指导 +3. 注意记录需求变更,及时更新相关文档 + + + +--- + +## 【注】 + +1. 本文档为小组软件过程会议记录,记录人员须在会议后一个工作日内如实填写,并汇报给PM、Lead及相关人员 +2. 文档内容已编号,若需调整编号,请在保证文档格式正确前提下修改 +3. 文档填写完毕后,文件命名按"meeting-minutes-周次"规范;如一周多次会议,命名为"meeting-minutes-05-01" diff --git a/doc/process/weekly/week-9/group/weekly-plan-09.md b/doc/process/weekly/week-9/group/weekly-plan-09.md new file mode 100644 index 0000000..1816917 --- /dev/null +++ b/doc/process/weekly/week-9/group/weekly-plan-09.md @@ -0,0 +1,32 @@ +# 小组周计划-第9周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 执行人 | 情况说明 | +|------|----------|--------|----------| +| 1 | 小程序界面优化和工单订单功能完善 | 前端组 | 按照指导老师意见完成小程序界面进一步优化,完善工单和订单相关功能模块 | +| 2 | 数据库部署到RUOYI管理系统 | 后端组 | 将设计好的数据库部署到后端,在RUOYI管理系统中运行并验证功能 | +| 3 | 数据库共享方案设计 | 全体成员 | 思考并设计数据库的共享方案,调研云服务器部署方案,确定技术选型 | + +## 小结 + +1. **小程序界面优化:** 根据指导老师反馈意见,进一步完善小程序用户界面,提升用户体验和交互流畅度。 +2. **工单订单功能完善:** 完善工单和订单相关功能模块,确保业务流程完整性和数据准确性。 +3. **数据库部署实施:** 将已设计完成的数据库成功部署到后端环境,在RUOYI管理系统中运行并验证各项功能正常。 +4. **数据库共享方案:** 调研云服务器部署方案,设计数据库共享架构,确保多端访问的稳定性和安全性。 +5. **技术支持需求:** 希望老师提供RUOYI框架数据库部署最佳实践指导,以及云服务器选型和配置建议。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 diff --git a/doc/process/weekly/week-9/group/weekly-summary-09.md b/doc/process/weekly/week-9/group/weekly-summary-09.md new file mode 100644 index 0000000..d9c1488 --- /dev/null +++ b/doc/process/weekly/week-9/group/weekly-summary-09.md @@ -0,0 +1,35 @@ +# 小组周总结-第9周 + +## 团队名称和起止时间 + +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +|------|----------|----------|----------| +| 1 | 数据库部署到RUOYI管理系统 | 完成 | 后端组将设计好的数据库成功部署到后端环境,并在RUOYI管理系统中运行,验证了各项功能的正常运行| +| 2 | 数据库设计文档完善 | 完成 | 2025-11-16,形成了可评审的数据库设计文档 | +| 3 | 小程序界面优化和工单订单功能完善 | 完成 | 前端组根据指导老师意见,对小程序界面进行了进一步优化,完善了工单和订单相关功能模块,提升了用户体验和交互流畅度 | +| 4 | 数据库共享方案设计 | 进行中 | 全体成员共同参与了数据库共享方案的初步设计,调研了云服务器部署方案,并初步确定了技术选型 | +| 5 | 主要业务建模图绘制 | 进行中 | 正在编写核心业务场景的活动图、顺序图和类图,保持了与用例图的一致性 + + + +## 小结 + +1. **技术框架掌握深化:** 通过系统梳理RUOYI框架的核心组件和代码生成器,团队对技术栈的理解更加深入,为后续开发工作奠定了坚实基础。 +2. **数据库部署成功:** 后端组顺利将数据库部署到RUOYI管理系统,并完成了功能验证,为后续开发奠定了基础。 +3. **技术支持需求:** 希望老师提供RUOYI框架数据库部署的最佳实践指导,以及云服务器选型和配置建议,帮助团队更好地完成后续任务。 +4. **团队协作高效:** 各小组按分工顺利完成设计任务,分析组、后端组和PM之间的协作顺畅,确保了文档质量的一致性。 +5. **文档编写进展:** 相关技术文档编写工作有序推进,为项目开发提供了规范的文档支持; +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. PM综合本小组成员工作情况提交小组周计划、周总结报告,按时上传至代码托管平台。 \ No newline at end of file diff --git a/doc/process/weekly/week-9/members/liangchenxv-weekly-plan-09.md b/doc/process/weekly/week-9/members/liangchenxv-weekly-plan-09.md new file mode 100644 index 0000000..010d6c4 --- /dev/null +++ b/doc/process/weekly/week-9/members/liangchenxv-weekly-plan-09.md @@ -0,0 +1,36 @@ +# 个人周计划-第9周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | RUOYI框架深入学习 | 后端组成员 | 梳理框架核心模块、权限体系及代码生成器,菜单管理及字典管理等 | +| 2 | 主要业务建模图绘制 | 全体组员 | 本周内继续进行活动图的编制 | +| 3 | web端界面开发 | 个人 | 本周基于上周ruoyi的代码生成功能的尝试完善web端界面 + + + +## 小结 + +1. **技术学习:** 重点掌握RUOYI框架的代码生成器,为后续后端开发工作打好基础; +2. **环境准备:** 确保本地开发环境完整可用,能够独立运行若依后台管理系统; +3. **数据库优化:** 参与数据库设计的优化工作,提升数据模型设计的专业能力; +4. **知识共享:** 希望团队能组织RUOYI框架的技术分享会,交流学习心得和开发经验; +5. **实践应用:** 通过实际搭建和配置环境,加深对前后端分离架构的理解。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +1. 请将个人计划和总结提前发给负责人; +1. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +1. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-9/members/liangchenxv-weekly-summary-09.md b/doc/process/weekly/week-9/members/liangchenxv-weekly-summary-09.md new file mode 100644 index 0000000..eaaa287 --- /dev/null +++ b/doc/process/weekly/week-9/members/liangchenxv-weekly-summary-09.md @@ -0,0 +1,41 @@ + +# 个人周总结-第9周 + +## 姓名和起止时间 + +**姓  名:** 梁晨旭 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +| 1 | 数据库部署到RUOYI管理系统 | 完成 | 2025-11-23,后端组将设计好的数据库成功部署到后端环境,并在RUOYI管理系统中运行,验证了各项功能的正常运行 | +| 2 | 主要业务建模图绘制 | 进行中 | 本周持续进行活动图的绘制编写 | +| 3 | web端界面开发 | 完成 | 2025-11-16,运用RUOYI框架的代码生成功能,实现web端管理界面部署 | + + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度; +3. **设计规范统一:** 建议建立团队统一的设计规范,包括颜色、字体、组件样式等,确保原型整体风格一致 +## 小结 + +1.**技术能力提升:** 通过深入学习RUOYI框架的菜单管理和字典管理功能,进一步提升了后端开发能力; +2.**建模工作推进:** 按计划完成了业务建模图的绘制工作,为后续开发提供了清晰的技术蓝图; +3.**界面开发优化:** 成功运用RUOYI代码生成器优化了web端界面,提升了用户交互体验; +4.**环境配置完善:** 确保本地开发环境完整可用,能够独立运行若依后台管理系统; +5.**知识共享需求:** 希望团队能继续组织技术分享会,交流RUOYI框架的深入学习心得和开发经验。 + + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; \ No newline at end of file diff --git a/doc/process/weekly/week-9/members/yangjie-weekly-plan-09.md b/doc/process/weekly/week-9/members/yangjie-weekly-plan-09.md new file mode 100644 index 0000000..fde82ba --- /dev/null +++ b/doc/process/weekly/week-9/members/yangjie-weekly-plan-09.md @@ -0,0 +1,27 @@ +# 个人周计划-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-22 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------- | ------ | -------- | +| 1 | 数据库部署到RUOYI系统 | 后端组 | 将设计好的数据库表结构导入RUOYI框架,配置数据源和连接参数 | +| 2 | 数据库功能验证测试 | 个人 | 在RUOYI管理系统中测试数据库各项功能,包括数据增删改查和关联查询 | +| 3 | 数据库共享架构设计 | 全体成员 | 参与数据库共享方案讨论,从技术角度评估不同方案的可行性 | +| 4 | 云服务器部署方案调研 | 后端组 | 调研主流云服务器提供商,比较配置、价格和部署复杂度 | +| 5 | 前后端接口对接准备 | 前端组 | 协助前端组明确工单订单功能的接口需求,制定接口规范 | +| 6 | 部署问题排查与解决 | 后端组 | 处理数据库部署过程中遇到的技术问题,确保系统稳定运行 | + +## 小结 + +1. **数据库部署实施:** 重点完成数据库在RUOYI框架中的部署和功能验证,确保数据操作正常; +2. **技术方案设计:** 参与数据库共享架构设计,为后续云服务器部署提供技术支撑; +3. **团队协作支持:** 协助前端组明确接口需求,促进前后端开发协同; +4. **问题解决能力:** 提升在部署过程中遇到问题的排查和解决能力; +5. **学习需求:** 需要了解RUOYI框架数据库部署的最佳实践和常见问题解决方案。 \ No newline at end of file diff --git a/doc/process/weekly/week-9/members/yangjie-weekly-summary-09.md b/doc/process/weekly/week-9/members/yangjie-weekly-summary-09.md new file mode 100644 index 0000000..f31b460 --- /dev/null +++ b/doc/process/weekly/week-9/members/yangjie-weekly-summary-09.md @@ -0,0 +1,33 @@ +# 个人周总结-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨捷 +**团队名称:** 1班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-22 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | -------- | -------- | -------- | +| 1 | 数据库部署到RUOYI系统 | 完成 | 成功将设计好的数据库表结构导入RUOYI框架,完成了数据源配置和连接测试 | +| 2 | 数据库功能验证测试 | 完成 | 在RUOYI管理系统中完成了基础数据操作测试,验证了增删改查和关联查询功能正常 | +| 3 | 数据库共享架构设计 | 部分完成 | 参与了共享方案的技术讨论,提出了数据库读写分离的初步构想 | +| 4 | 云服务器部署方案调研 | 完成 | 调研了阿里云、腾讯云等主流云服务商,对比了不同配置方案的成本和性能 | +| 5 | 前后端接口对接准备 | 完成 | 协助前端组明确了工单、订单模块的接口需求,制定了初步的接口文档规范 | +| 6 | 部署问题排查与解决 | 完成 | 解决了数据库字符集配置和时区设置等问题,确保了系统的稳定运行 | + +## 对团队工作的建议 + +1. **部署文档标准化:** 建议整理数据库部署的标准化流程文档,方便后续维护和新成员上手; +2. **环境统一管理:** 建议建立统一的开发、测试环境配置,减少环境差异导致的问题; +3. **技术方案评审:** 建议对云服务器选型方案进行团队评审,确保技术选型的合理性。 + +## 小结 + +1. **实践能力提升:** 通过实际部署操作,加深了对RUOYI框架数据库配置的理解,掌握了部署流程; +2. **技术视野拓展:** 通过云服务器调研,了解了云端部署的相关知识和技术要点; +3. **协作能力增强:** 在前后端接口对接过程中,提升了跨组沟通和协作能力; +4. **后续重点:** 需要进一步深入研究数据库性能优化和云环境部署的具体实施; +5. **希望获得的帮助:** 希望老师能指导数据库性能监控和优化方案,以及云服务器部署的最佳实践。 \ No newline at end of file diff --git a/doc/process/weekly/week-9/members/yangmohan-weekly-plan-09.md b/doc/process/weekly/week-9/members/yangmohan-weekly-plan-09.md new file mode 100644 index 0000000..ab41bbc --- /dev/null +++ b/doc/process/weekly/week-9/members/yangmohan-weekly-plan-09.md @@ -0,0 +1,24 @@ +# 个人周计划-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-22 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| ---- | -------------------------------------- | ------ | -------- | +| 1 | 开启小程序α版本的编码任务 | 个人 | 优化小程序界面,完善订单工单功能,推进α版本开发进度 | +| 2 | 监督指导后端数据库的部署以及RUOYI界面的优化 | 团队 | 指导后端数据库部署流程,优化RuoYi管理界面,确保系统稳定运行 | +| 3 | 修改迭代计划,完成第二稿 | 个人 | 根据项目进展调整迭代计划,完善功能优先级与里程碑设置 | + +## 小结 + +1. **小程序开发:** 开启α版本编码工作,重点优化小程序界面交互体验,完善订单和工单核心功能; +2. **后端支持:** 监督指导数据库部署工作,优化RuoYi管理界面,保障后端系统稳定运行; +3. **迭代规划:** 完成迭代计划第二稿修订,明确α版本功能优先级与开发里程碑。 + +--- diff --git a/doc/process/weekly/week-9/members/yangmohan-weekly-summary-09.md b/doc/process/weekly/week-9/members/yangmohan-weekly-summary-09.md new file mode 100644 index 0000000..aba9c3e --- /dev/null +++ b/doc/process/weekly/week-9/members/yangmohan-weekly-summary-09.md @@ -0,0 +1,30 @@ + +# 个人周总结-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨默涵 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------ | +|1 | 已将数据库设计并完善提交到RUOYI代码生成| 完成| 已完成数据库设计的完善工作,包括表结构优化、字段设计、索引设置等,并将完整的数据库设计文档提交到RUOYI代码生成平台,为后续代码自动生成做好准备| +|2 | 小程序按照陆绍飞老师意见,在工单和订单的粒度方面做了一些优化| 完成| 根据陆绍飞老师的指导意见,对小程序中工单和订单的业务逻辑进行了粒度优化,调整了数据模型和业务流程,使工单和订单的划分更加合理,提升了系统的业务准确性和可维护性| +|3 | 学习数据库的云端部署方法| 完成| 学习了数据库云端部署的相关知识,包括云数据库的选择、配置方法、数据迁移流程、安全设置等,为后续项目的云端部署工作做好了技术储备| + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **开发效率提升:** 通过完善数据库设计并提交到RUOYI代码生成平台,为项目后续开发提供了标准化的代码生成基础,将有效提升开发效率; +2. **业务逻辑优化:** 根据指导老师的专业建议,对工单和订单模块进行了业务粒度调整,使系统架构更加清晰,为后续功能扩展打下了良好基础; +3. **技术能力拓展:** 通过系统学习数据库云端部署技术,掌握了云环境下的数据库管理方法,为项目的生产环境部署做好了技术准备; + +--- diff --git a/doc/process/weekly/week-9/members/yangshuailu-weekly-plan-09.md b/doc/process/weekly/week-9/members/yangshuailu-weekly-plan-09.md new file mode 100644 index 0000000..0e51414 --- /dev/null +++ b/doc/process/weekly/week-9/members/yangshuailu-weekly-plan-09.md @@ -0,0 +1,31 @@ +# 个人周计划-第九周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 +**团队名称:** 1班-羊了个羊队 +**开始时间:** 2025-11-17 + +**结束时间:** 2025-11-23 + +## 本周任务计划安排 + +| 序号 | 计划内容 | 协作人 | 情况说明 | +| --- | --------------- | --- | ----------------------------------------------- | +| 1 | 数据库部署到RUOYI管理系统 | 组员 | 将设计好的数据库部署到后端,在RUOYI管理系统中运行并验证功能 | +| 2 | 数据库共享方案设计 | 组员 | 思考并设计数据库的共享方案,调研云服务器部署方案,确定技术选型。确保多端访问的稳定性和安全性。 | + +## 小结 + +1. **学习支持:** 希望老师提供RUOYI框架数据库部署最佳实践指导,以及云服务器选型和配置建议; +2. +3. **进度保障:** 每日同步任务进展至后端组群,及时解决学习和设计中遇到的技术卡点。 + +--- + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台; diff --git a/doc/process/weekly/week-9/members/yangshuailu-weekly-summary-09.md b/doc/process/weekly/week-9/members/yangshuailu-weekly-summary-09.md new file mode 100644 index 0000000..51fb49a --- /dev/null +++ b/doc/process/weekly/week-9/members/yangshuailu-weekly-summary-09.md @@ -0,0 +1,36 @@ +# 个人周总结-第九周 + +## 姓名和起止时间 + +**姓  名:** 杨帅路 + + **团队名称:** 1班-羊了个羊队 + +**开始时间:** 2025-11-17 + +**结束时间:** 2025-11-23 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| --- | --------------- | ---- | ------------------------------------------------------------- | +| 1 | 数据库部署到RUOYI管理系统 | 完成 | 成功将设计好的数据库导入到后端环境,但是遇到了一些问题还需要进一步调试 | +| 2 | 数据库共享方案调研与设计 | 完成 | 完成云服务器、局域网共享等方案的对比,但仍在进一步讨论后续部署流程 | + +## 对团队工作的建议 + +1. **统一规范部署流程:** 建议团队建立一份数据库部署与初始化的操作文档,确保每位组员环境一致,减少低级错误。 +2. **方案评审:** 对于核心技术方案,可组织简短的内部评审会,集思广益优化方案细节。 + +## 小结 + +1. **技能提升:** 掌握了 RUOYI 框架与数据库的集成部署方法,对云服务器部署流程及技术选型有了更清晰的认识; +2. **问题解决:** 解决了数据库部署中的兼容性问题,提升了排查系统集成类故障的能力; +3. **协作成果:** 与组员协作完成的数据库共享方案为项目多端访问需求提供了技术支撑,为后续开发奠定基础。 + +## 【注】 + +1. 在小结一栏中写出希望得到如何的帮助,如讲座等; +2. 请将个人计划和总结提前发给负责人; +3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交; +4. 所有组员都需提交个人周计划、周总结文档,上传至代码托管平台; diff --git a/doc/process/weekly/week-9/members/yangzy-weekly-plan-09.md b/doc/process/weekly/week-9/members/yangzy-weekly-plan-09.md new file mode 100644 index 0000000..b54b135 --- /dev/null +++ b/doc/process/weekly/week-9/members/yangzy-weekly-plan-09.md @@ -0,0 +1,27 @@ +# 个人周计划-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-22 + + +## 本周任务计划安排 + +| 序号 | 计划内容| 协作人 | 情况说明 | +| ----| ------ | ------| ------- | +| 1 | Uniapp的进阶学习 | 个人 | 2025-11-18 继续进行Uniapp的进阶学习,争取掌握更多Uniapp的高级用法 | +| 2 | 学习前端知识 | 个人 | 本周内持续学习前端开发,主要是Uniapp相关知识 | +| 3 | 继续系统总用例图编写 | 组员 | 2025-11-20 继续完成我所负责的顺序图结构,并和组内的同学进行整合(上周已经完成部分) | +| 4 | 技术方案整合 | 组员 | 2025-11-21 整合本周学习的技术栈,指定下一阶段的开发计划 | +| 5 | 数据库共享方案设计 | 组员 | 2025-11-22 思考并设计数据库的共享方案,调研云服务器部署方案,确定技术选型 | + +## 小结 + +1. **学习需求:** 希望能有对于原型设计的教学; +2. **知识储备:** 继续学习后续需要使用的知识(比如墨刀的基本使用如界面滚动、图标绘制,以及Uniapp的基本使用方法),为后续的前端开发做准备; +3. **文档撰写:** 结合课内知识学习需求文档的撰写。 + +--- diff --git a/doc/process/weekly/week-9/members/yangzy-weekly-summary-09.md b/doc/process/weekly/week-9/members/yangzy-weekly-summary-09.md new file mode 100644 index 0000000..5281268 --- /dev/null +++ b/doc/process/weekly/week-9/members/yangzy-weekly-summary-09.md @@ -0,0 +1,33 @@ +# 个人周总结-第9周 + +## 姓名和起止时间 + +**姓  名:** 杨振宇 +**团队名称:** 软件2301班-羊了个羊 +**开始时间:** 2025-11-17 +**结束时间:** 2025-11-23 + +## 本周任务完成情况 + +| 序号 | 总结内容 | 是否完成 | 情况说明 | +| ---- | ------------------------------------------------ | -------- | ------------------------------------------------------------- | +| 1 | Uniapp的进阶学习 | 完成 | 2025-11-17 继续进行了Uniapp的进阶学习 | +| 2 | 个人技能:前端学习 | 完成 | 2025-11-18 持续学习了前端开发,主要是Uniapp相关知识 | +| 3 | 继续系统总用例图编写 | 完成 | 2025-11-20 继续进行小组项目的顺序图绘制,目前已经大部分完成 | +| 4 | 技术方案整合 | 完成 | 2025-11-21 整合本周学习的技术栈,指定下一阶段的开发计划 | +| 5 | 数据库共享方案设计 | 完成 | 2025-11-22 讨论、思考并设计数据库的共享方案,调研云服务器部署方案,确定技术选型 | +| 6 | 召开例会,讨论原型的完成情况,并交换报告各自进度 | 完成 | 2025-11-23 在腾讯会议召开每周例会,并确定下周进度计划,需求 | + +## 对团队工作的建议 + +1. **互助学习:** 小组成员应该根据自身的技能长短开展互帮互助的活动,可以各自负责自己擅长的部分,共同努力提高小组成员的专业水平; +2. **进度统一:** 团队成员尽量统一项目进度,以免造成麻烦; + +## 小结 + +1. **原型制作:** 完成了小组初版成果的本地部署; +2. **技能学习:** 小组成员各自开展自己所负责部分的个人技能的学习; +3. **项目管理:** PM及时推进项目进度,确保工作有条不紊; +4. **计划制定:** 根据本周任务完成情况与下一阶段文档提交要求,制定团队任务计划。 + +--- diff --git a/doc/project/01-需求文档/用例文档最终稿.docx b/doc/project/01-需求文档/用例文档最终稿.docx new file mode 100644 index 0000000..8b5b082 Binary files /dev/null and b/doc/project/01-需求文档/用例文档最终稿.docx differ diff --git a/doc/project/01-需求文档/用例文档第一稿.docx b/doc/project/01-需求文档/用例文档第一稿.docx new file mode 100644 index 0000000..1051822 Binary files /dev/null and b/doc/project/01-需求文档/用例文档第一稿.docx differ diff --git a/doc/project/01-需求文档/需求规格说明书最终稿.doc b/doc/project/01-需求文档/需求规格说明书最终稿.doc new file mode 100644 index 0000000..7176343 Binary files /dev/null and b/doc/project/01-需求文档/需求规格说明书最终稿.doc differ diff --git a/doc/project/01-需求文档/需求规格说明书第一稿.doc b/doc/project/01-需求文档/需求规格说明书第一稿.doc new file mode 100644 index 0000000..90141a4 Binary files /dev/null and b/doc/project/01-需求文档/需求规格说明书第一稿.doc differ diff --git a/doc/project/01-需求文档/项目前景与范围文档.docx b/doc/project/01-需求文档/项目前景与范围文档.docx new file mode 100644 index 0000000..02978f3 Binary files /dev/null and b/doc/project/01-需求文档/项目前景与范围文档.docx differ diff --git a/doc/project/02-设计文档/数据库设计说明_v2.0.md b/doc/project/02-设计文档/数据库设计说明_v2.0.md new file mode 100644 index 0000000..647482a --- /dev/null +++ b/doc/project/02-设计文档/数据库设计说明_v2.0.md @@ -0,0 +1,1112 @@ +# 数智水管家数据库设计说明 v2.0 + +> 基于小程序实际功能的精简数据库设计方案 + +## 📊 一、设计概览 + +### 1.1 设计原则 + +- ✅ **功能完整**:覆盖用户端和员工端所有核心功能 +- ✅ **结构精简**:仅 **12 张核心表**,易于维护 +- ✅ **高度复用**:订单、工单、配送统一管理 +- ✅ **易于扩展**:预留扩展字段,支持业务增长 +- ✅ **性能优化**:合理索引设计,支持高并发查询 + +### 1.2 数据库统计 + +| 项目 | 数量 | 说明 | +|------|------|------| +| 核心业务表 | 12 张 | 覆盖全部业务功能 | +| 视图 | 2 个 | 员工绩效、订单统计 | +| 索引 | 30+ 个 | 优化查询性能 | +| 字段总数 | ~180 个 | 平均每表 15 个字段 | + +### 1.3 功能覆盖 + +**用户端功能**: +- 设备管理(绑定、监控、预警) +- 滤芯管理(寿命监控、更换提醒) +- 水质检测(检测记录、报告查看、预警) +- 商品订购(净水器、配件、服务) +- 订单管理(下单、支付、评价) +- 消息通知(系统消息、公告) +- 在线客服 + +**员工端功能**: +- 工单管理(接单、处理、完成) +- 配送任务(任务列表、配送详情) +- 工作统计(绩效查看) +- 个人中心 + +--- + +## 📋 二、核心表清单 + +| 序号 | 表名 | 说明 | 记录数量级 | +|------|------|------|-----------| +| 1 | `water_user` | 普通用户表 | 10万+ | +| 2 | `water_staff` | 员工表 | 100+ | +| 3 | `water_device` | 净水器设备表 | 10万+ | +| 4 | `water_filter` | 滤芯表 | 40万+ | +| 5 | `water_quality` | 水质检测记录表 | 100万+ | +| 6 | `water_product` | 商品表 | 100+ | +| 7 | `water_service_order` | 服务订单表(统一) | 100万+ | +| 8 | `water_order_product` | 订单商品关联表 | 200万+ | +| 9 | `water_evaluation` | 订单评价表 | 50万+ | +| 10 | `water_message` | 系统消息表 | 100万+ | +| 11 | `water_notice` | 通知公告表 | 100+ | +| 12 | `water_config` | 系统配置表 | 50+ | + +--- + +## 🗂️ 三、表结构详细设计 + +### 3.1 water_user(用户表) + +> 存储普通用户的基本信息,支持手机号和微信登录。 + +```sql +CREATE TABLE `water_user` ( + `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `phone` VARCHAR(11) DEFAULT NULL COMMENT '手机号', + `password` VARCHAR(128) DEFAULT NULL COMMENT '密码(BCrypt加密)', + `nick_name` VARCHAR(50) DEFAULT NULL COMMENT '昵称', + `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', + `gender` CHAR(1) DEFAULT '0' COMMENT '性别(0未知 1男 2女)', + `openid` VARCHAR(128) DEFAULT NULL COMMENT '微信openid', + `unionid` VARCHAR(128) DEFAULT NULL COMMENT '微信unionid', + `balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '账户余额', + `total_orders` INT(11) DEFAULT 0 COMMENT '订单总数(冗余)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`user_id`), + UNIQUE KEY `uk_phone` (`phone`), + UNIQUE KEY `uk_openid` (`openid`), + KEY `idx_status` (`status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; +``` + +**字段说明**: +- `phone`:支持手机号登录,唯一索引 +- `openid/unionid`:支持微信登录 +- `balance`:账户余额,支持余额支付 +- `total_orders`:冗余字段,减少订单表统计查询 + +--- + +### 3.2 water_staff(员工表) + +> 存储工作人员信息,与 RuoYi 的 sys_user 关联。 + +```sql +CREATE TABLE `water_staff` ( + `staff_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '员工ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '关联sys_user的user_id', + `employee_no` VARCHAR(20) NOT NULL COMMENT '工号', + `staff_name` VARCHAR(50) NOT NULL COMMENT '姓名', + `phone` VARCHAR(11) NOT NULL COMMENT '手机号', + `dept_id` BIGINT(20) DEFAULT NULL COMMENT '部门ID(关联sys_dept)', + `position` VARCHAR(50) DEFAULT NULL COMMENT '职位', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `total_orders` INT(11) DEFAULT 0 COMMENT '工单总数(冗余)', + `completed_orders` INT(11) DEFAULT 0 COMMENT '完成工单数(冗余)', + `avg_rating` DECIMAL(3,2) DEFAULT 5.00 COMMENT '平均评分(冗余)', + `avg_duration` INT(11) DEFAULT 0 COMMENT '平均服务时长-分钟(冗余)', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`staff_id`), + UNIQUE KEY `uk_employee_no` (`employee_no`), + UNIQUE KEY `uk_phone` (`phone`), + KEY `idx_user_id` (`user_id`), + KEY `idx_dept_id` (`dept_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工表'; +``` + +**字段说明**: +- `user_id`:关联 RuoYi 的 sys_user,实现统一认证 +- `dept_id`:关联 RuoYi 的 sys_dept,实现数据权限 +- `avg_rating/avg_duration`:冗余字段,定时任务更新 + +--- + +### 3.3 water_device(设备表) + +> 存储净水器设备信息,支持状态监控和地理位置。 + +```sql +CREATE TABLE `water_device` ( + `device_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `sn` VARCHAR(50) NOT NULL COMMENT '设备编号(唯一)', + `device_name` VARCHAR(100) DEFAULT NULL COMMENT '设备名称', + `device_type` VARCHAR(50) DEFAULT '智能净水器' COMMENT '设备类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '设备型号', + `status` CHAR(1) DEFAULT '1' COMMENT '状态(0离线 1在线 2故障)', + `install_address` VARCHAR(255) DEFAULT NULL COMMENT '安装地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `bind_time` DATETIME DEFAULT NULL COMMENT '绑定时间', + `last_online_time` DATETIME DEFAULT NULL COMMENT '最后在线时间', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`device_id`), + UNIQUE KEY `uk_sn` (`sn`), + KEY `idx_user_id` (`user_id`), + KEY `idx_status` (`status`), + KEY `idx_bind_time` (`bind_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备表'; +``` + +**字段说明**: +- `sn`:设备序列号,全局唯一 +- `status`:0离线/1在线/2故障,支持实时监控 +- `location_lat/lng`:经纬度,用于配送导航 + +--- + +### 3.4 water_filter(滤芯表) + +> 存储滤芯信息,支持寿命监控和更换提醒。 + +```sql +CREATE TABLE `water_filter` ( + `filter_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '滤芯ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `filter_name` VARCHAR(50) NOT NULL COMMENT '滤芯名称(如:PP棉滤芯)', + `filter_type` VARCHAR(50) DEFAULT NULL COMMENT '滤芯类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '滤芯型号', + `install_time` DATETIME DEFAULT NULL COMMENT '安装时间', + `total_days` INT(11) DEFAULT 180 COMMENT '总使用天数(默认180天)', + `used_days` INT(11) DEFAULT 0 COMMENT '已使用天数', + `life_percentage` INT(11) DEFAULT 100 COMMENT '剩余寿命百分比', + `next_replace_time` DATE DEFAULT NULL COMMENT '预计更换时间', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1需更换)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`filter_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_status` (`status`), + KEY `idx_life_percentage` (`life_percentage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='滤芯表'; +``` + +**字段说明**: +- `life_percentage`:剩余寿命百分比,实时计算 +- `next_replace_time`:预计更换时间,提前预警 +- `status`:0正常/1需更换 + +**寿命计算公式**: +```sql +-- 定时任务每天更新 +UPDATE water_filter +SET used_days = DATEDIFF(NOW(), install_time), + life_percentage = GREATEST(0, ROUND((total_days - used_days) * 100.0 / total_days, 0)), + status = CASE WHEN life_percentage <= 10 THEN '1' ELSE '0' END +WHERE del_flag = '0'; +``` + +--- + +### 3.5 water_quality(水质检测记录表) + +> 存储水质检测记录,支持多指标检测和预警。 + +```sql +CREATE TABLE `water_quality` ( + `quality_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '检测ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `order_id` BIGINT(20) DEFAULT NULL COMMENT '关联订单ID(如果是服务订单)', + `test_time` DATETIME NOT NULL COMMENT '检测时间', + `test_address` VARCHAR(255) DEFAULT NULL COMMENT '检测地址', + `quality_level` VARCHAR(20) DEFAULT NULL COMMENT '水质等级(优质/良好/一般/较差)', + `quality_desc` VARCHAR(500) DEFAULT NULL COMMENT '水质描述', + + -- 检测指标 + `ph_value` DECIMAL(4,2) DEFAULT NULL COMMENT 'pH值(6.5-8.5)', + `turbidity` DECIMAL(6,2) DEFAULT NULL COMMENT '浊度 NTU(≤1)', + `residual_chlorine` DECIMAL(6,2) DEFAULT NULL COMMENT '余氯 mg/L(0.05-4)', + `total_hardness` DECIMAL(8,2) DEFAULT NULL COMMENT '总硬度 mg/L(≤450)', + `tds` DECIMAL(8,2) DEFAULT NULL COMMENT 'TDS溶解性固体 mg/L(≤1000)', + `cod` DECIMAL(8,2) DEFAULT NULL COMMENT 'COD化学需氧量 mg/L', + `ammonia_nitrogen` DECIMAL(6,2) DEFAULT NULL COMMENT '氨氮 mg/L', + + `report_url` VARCHAR(255) DEFAULT NULL COMMENT '检测报告URL', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0检测中 1已完成)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`quality_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_test_time` (`test_time`), + KEY `idx_quality_level` (`quality_level`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水质检测记录表'; +``` + +**字段说明**: +- 支持多种水质指标检测 +- `quality_level`:根据指标自动计算水质等级 +- `report_url`:检测报告文件地址 + +**水质等级计算规则**: +``` +优质:所有指标在标准范围内 +良好:个别指标接近上限/下限 +一般:部分指标超标但影响不大 +较差:关键指标超标,影响饮用安全 +``` + +--- + +### 3.6 water_product(商品表) + +> 存储可订购的商品信息(净水器、配件、服务等)。 + +```sql +CREATE TABLE `water_product` ( + `product_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称', + `product_desc` VARCHAR(500) DEFAULT NULL COMMENT '商品描述', + `category` VARCHAR(50) DEFAULT NULL COMMENT '商品分类(purifier净水器/meter水表/parts配件/service服务)', + `price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '商品价格', + `stock` INT(11) DEFAULT 0 COMMENT '库存数量', + `image_url` VARCHAR(255) DEFAULT NULL COMMENT '商品图片URL', + `icon` VARCHAR(50) DEFAULT NULL COMMENT '图标Emoji', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0上架 1下架)', + `sort_order` INT(11) DEFAULT 0 COMMENT '排序', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`product_id`), + KEY `idx_category` (`category`), + KEY `idx_status` (`status`), + KEY `idx_sort_order` (`sort_order`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; +``` + +**字段说明**: +- `category`:商品分类,支持多种类型 +- `icon`:Emoji 图标,小程序前端显示 +- `sort_order`:排序字段,控制显示顺序 + +--- + +### 3.7 water_service_order(服务订单表)⭐核心 + +> **统一管理**用户订单、工单、配送任务的核心表。 + +```sql +CREATE TABLE `water_service_order` ( + `order_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `order_no` VARCHAR(50) NOT NULL COMMENT '订单号(唯一)', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '负责员工ID', + + -- 订单类型与来源 + `service_type` VARCHAR(50) NOT NULL COMMENT '服务类型(设备安装/滤芯更换/维修/订购/水质检测)', + `order_source` VARCHAR(20) DEFAULT 'user' COMMENT '订单来源(user用户下单/admin后台派单)', + + -- 订单状态 + `order_status` VARCHAR(20) DEFAULT 'pending' COMMENT '订单状态(pending待支付/paid已支付/accepted已接单/processing处理中/completed已完成/cancelled已取消)', + `payment_status` VARCHAR(20) DEFAULT 'unpaid' COMMENT '支付状态(unpaid未支付/paid已支付/refunded已退款)', + + -- 金额信息 + `amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '订单金额', + `actual_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '实付金额', + `discount_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '优惠金额', + `payment_method` VARCHAR(20) DEFAULT NULL COMMENT '支付方式(wechat微信/balance余额/alipay支付宝)', + + -- 服务信息 + `contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人', + `contact_phone` VARCHAR(11) DEFAULT NULL COMMENT '联系电话', + `service_address` VARCHAR(255) DEFAULT NULL COMMENT '服务地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `description` TEXT DEFAULT NULL COMMENT '服务描述/问题描述', + `priority` VARCHAR(20) DEFAULT 'normal' COMMENT '优先级(normal普通/high紧急)', + + -- 配送信息 + `delivery_distance` DECIMAL(10,2) DEFAULT NULL COMMENT '配送距离(公里)', + `estimated_duration` INT(11) DEFAULT NULL COMMENT '预计时长(分钟)', + `actual_duration` INT(11) DEFAULT NULL COMMENT '实际时长(分钟)', + + -- 时间轴 + `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间', + `payment_time` DATETIME DEFAULT NULL COMMENT '支付时间', + `accept_time` DATETIME DEFAULT NULL COMMENT '接单时间', + `start_time` DATETIME DEFAULT NULL COMMENT '开始配送时间', + `complete_time` DATETIME DEFAULT NULL COMMENT '完成时间', + `cancel_time` DATETIME DEFAULT NULL COMMENT '取消时间', + + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`order_id`), + UNIQUE KEY `uk_order_no` (`order_no`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_order_status` (`order_status`), + KEY `idx_service_type` (`service_type`), + KEY `idx_submit_time` (`submit_time`), + KEY `idx_staff_status` (`staff_id`, `order_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务订单表'; +``` + +**设计亮点**: +1. **统一管理**:用户订单、员工工单、配送任务合并为一张表 +2. **灵活状态**:通过 `order_source` 区分来源,通过 `order_status` 管理流程 +3. **完整时间轴**:记录订单全生命周期的时间节点 + +**状态流转**: +``` +用户下单流程: +pending(待支付) → paid(已支付) → accepted(已接单) → processing(处理中) → completed(已完成) + ↓ + cancelled(已取消) + +后台派单流程: +paid(已派单) → accepted(已接单) → processing(处理中) → completed(已完成) +``` + +--- + +### 3.8 water_order_product(订单商品关联表) + +> 存储订单与商品的关联关系,支持一订单多商品。 + +```sql +CREATE TABLE `water_order_product` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `product_id` BIGINT(20) NOT NULL COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称(冗余)', + `product_price` DECIMAL(10,2) NOT NULL COMMENT '商品单价(冗余)', + `quantity` INT(11) DEFAULT 1 COMMENT '购买数量', + `total_price` DECIMAL(10,2) NOT NULL COMMENT '小计金额', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_product_id` (`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品关联表'; +``` + +**字段说明**: +- 冗余 `product_name` 和 `product_price`,防止商品信息修改后订单数据不一致 +- `total_price` = `product_price` × `quantity` + +--- + +### 3.9 water_evaluation(订单评价表) + +> 存储用户对订单的评价,支持多维度评分。 + +```sql +CREATE TABLE `water_evaluation` ( + `evaluation_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '评价ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID', + `rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '综合评分(1-5星)', + `service_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务态度评分', + `quality_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务质量评分', + `speed_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务速度评分', + `content` TEXT DEFAULT NULL COMMENT '评价内容', + `images` VARCHAR(1000) DEFAULT NULL COMMENT '评价图片(JSON数组)', + `is_anonymous` CHAR(1) DEFAULT '0' COMMENT '是否匿名(0否 1是)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`evaluation_id`), + UNIQUE KEY `uk_order_id` (`order_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_rating` (`rating`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单评价表'; +``` + +**字段说明**: +- 支持多维度评分(服务态度、质量、速度) +- `rating` = (service_rating + quality_rating + speed_rating) / 3 +- 支持匿名评价 + +--- + +### 3.10 water_message(系统消息表) + +> 存储系统消息,支持用户端和员工端消息推送。 + +```sql +CREATE TABLE `water_message` ( + `message_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '消息ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '用户ID(用户消息)', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID(员工消息)', + `message_type` VARCHAR(50) DEFAULT NULL COMMENT '消息类型(order订单/device设备/system系统/service服务)', + `title` VARCHAR(100) NOT NULL COMMENT '消息标题', + `content` TEXT NOT NULL COMMENT '消息内容', + `related_id` BIGINT(20) DEFAULT NULL COMMENT '关联ID(如订单ID、设备ID)', + `is_read` CHAR(1) DEFAULT '0' COMMENT '是否已读(0未读 1已读)', + `send_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '发送时间', + `read_time` DATETIME DEFAULT NULL COMMENT '阅读时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`message_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_message_type` (`message_type`), + KEY `idx_is_read` (`is_read`), + KEY `idx_send_time` (`send_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统消息表'; +``` + +**字段说明**: +- `user_id` 和 `staff_id` 二选一,区分用户消息和员工消息 +- `message_type`:消息分类,便于筛选 +- `related_id`:关联业务数据,支持消息跳转 + +--- + +### 3.11 water_notice(通知公告表) + +> 存储系统通知公告,面向所有用户广播。 + +```sql +CREATE TABLE `water_notice` ( + `notice_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `notice_title` VARCHAR(100) NOT NULL COMMENT '公告标题', + `notice_content` TEXT NOT NULL COMMENT '公告内容', + `notice_type` VARCHAR(20) DEFAULT 'info' COMMENT '公告类型(info通知/warning警告/urgent紧急)', + `target_type` VARCHAR(20) DEFAULT 'all' COMMENT '目标对象(all全部/user用户/staff员工)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0发布 1草稿 2下架)', + `publish_time` DATETIME DEFAULT NULL COMMENT '发布时间', + `expire_time` DATETIME DEFAULT NULL COMMENT '过期时间', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`notice_id`), + KEY `idx_status` (`status`), + KEY `idx_target_type` (`target_type`), + KEY `idx_publish_time` (`publish_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通知公告表'; +``` + +**字段说明**: +- `target_type`:支持定向推送(全部/用户/员工) +- `expire_time`:过期自动下架 + +--- + +### 3.12 water_config(系统配置表) + +> 存储系统配置参数,支持动态配置。 + +```sql +CREATE TABLE `water_config` ( + `config_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '配置ID', + `config_key` VARCHAR(100) NOT NULL COMMENT '配置键', + `config_value` VARCHAR(500) NOT NULL COMMENT '配置值', + `config_type` VARCHAR(50) DEFAULT 'string' COMMENT '配置类型(string/number/boolean/json)', + `config_desc` VARCHAR(500) DEFAULT NULL COMMENT '配置描述', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`), + UNIQUE KEY `uk_config_key` (`config_key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表'; +``` + +**常用配置项**: +```sql +-- 订单自动完成时间(小时) +INSERT INTO water_config VALUES (1, 'order.auto_complete_hours', '24', 'number', '订单自动完成时间'); + +-- 滤芯预警阈值(%) +INSERT INTO water_config VALUES (2, 'filter.warning_threshold', '30', 'number', '滤芯寿命预警阈值'); + +-- 水质检测价格 +INSERT INTO water_config VALUES (3, 'service.quality_test_price', '99.00', 'number', '水质检测服务价格'); + +-- 配送费起步价 +INSERT INTO water_config VALUES (4, 'delivery.base_fee', '5.00', 'number', '配送费起步价'); +``` + +--- + +## 📊 四、视图设计 + +### 4.1 v_staff_performance(员工绩效视图) + +> 实时统计员工绩效数据,替代统计表。 + +```sql +CREATE OR REPLACE VIEW `v_staff_performance` AS +SELECT + s.staff_id, + s.employee_no, + s.staff_name, + s.phone, + s.dept_id, + s.position, + + -- 订单统计 + COUNT(o.order_id) AS total_orders, + SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) AS completed_orders, + SUM(CASE WHEN o.order_status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_orders, + ROUND(SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(o.order_id), 0), 2) AS completion_rate, + + -- 评价统计 + IFNULL(AVG(e.rating), 5.00) AS avg_rating, + COUNT(e.evaluation_id) AS evaluation_count, + + -- 时效统计 + IFNULL(AVG(o.actual_duration), 0) AS avg_duration, + + -- 服务类型统计 + SUM(CASE WHEN o.service_type = '设备安装' THEN 1 ELSE 0 END) AS install_count, + SUM(CASE WHEN o.service_type = '滤芯更换' THEN 1 ELSE 0 END) AS filter_count, + SUM(CASE WHEN o.service_type = '维修' THEN 1 ELSE 0 END) AS repair_count, + SUM(CASE WHEN o.service_type = '水质检测' THEN 1 ELSE 0 END) AS quality_count, + + -- 等级评定 + CASE + WHEN AVG(e.rating) >= 4.8 AND COUNT(o.order_id) >= 50 THEN '金牌员工' + WHEN AVG(e.rating) >= 4.5 AND COUNT(o.order_id) >= 30 THEN '优秀员工' + WHEN AVG(e.rating) >= 4.0 THEN '普通员工' + ELSE '待提升' + END AS staff_level + +FROM water_staff s +LEFT JOIN water_service_order o ON s.staff_id = o.staff_id AND o.del_flag = '0' +LEFT JOIN water_evaluation e ON o.order_id = e.order_id AND e.del_flag = '0' +WHERE s.del_flag = '0' +GROUP BY s.staff_id; +``` + +**使用示例**: +```sql +-- 查询金牌员工 +SELECT * FROM v_staff_performance +WHERE staff_level = '金牌员工' +ORDER BY avg_rating DESC, completed_orders DESC; + +-- 查询本月完成订单最多的前10名 +SELECT * FROM v_staff_performance +ORDER BY completed_orders DESC +LIMIT 10; +``` + +--- + +### 4.2 v_order_statistics(订单统计视图) + +> 按日期、服务类型统计订单数据。 + +```sql +CREATE OR REPLACE VIEW `v_order_statistics` AS +SELECT + DATE(submit_time) AS order_date, + service_type, + order_status, + order_source, + + COUNT(*) AS order_count, + SUM(amount) AS total_amount, + SUM(actual_amount) AS total_actual_amount, + SUM(discount_amount) AS total_discount, + + AVG(actual_duration) AS avg_duration, + AVG(delivery_distance) AS avg_distance, + + COUNT(DISTINCT user_id) AS user_count, + COUNT(DISTINCT staff_id) AS staff_count + +FROM water_service_order +WHERE del_flag = '0' +GROUP BY DATE(submit_time), service_type, order_status, order_source; +``` + +**使用示例**: +```sql +-- 查询最近7天订单统计 +SELECT * FROM v_order_statistics +WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) +ORDER BY order_date DESC; + +-- 查询各服务类型完成情况 +SELECT + service_type, + SUM(order_count) AS total, + SUM(total_actual_amount) AS revenue +FROM v_order_statistics +WHERE order_status = 'completed' + AND order_date >= '2025-11-01' +GROUP BY service_type; +``` + +--- + +## 🔍 五、索引优化策略 + +### 5.1 唯一索引(保证数据唯一性) + +| 表名 | 索引名 | 字段 | 说明 | +|------|--------|------|------| +| water_user | uk_phone | phone | 手机号唯一 | +| water_user | uk_openid | openid | 微信openid唯一 | +| water_staff | uk_employee_no | employee_no | 工号唯一 | +| water_staff | uk_phone | phone | 员工手机号唯一 | +| water_device | uk_sn | sn | 设备序列号唯一 | +| water_service_order | uk_order_no | order_no | 订单号唯一 | +| water_evaluation | uk_order_id | order_id | 一订单一评价 | +| water_config | uk_config_key | config_key | 配置键唯一 | + +### 5.2 普通索引(提升查询性能) + +| 表名 | 索引类型 | 字段 | 使用场景 | +|------|----------|------|----------| +| water_user | 单列索引 | status | 查询正常用户 | +| water_device | 单列索引 | user_id | 查询用户的设备 | +| water_device | 单列索引 | status | 查询离线/故障设备 | +| water_filter | 单列索引 | device_id | 查询设备的滤芯 | +| water_filter | 单列索引 | life_percentage | 查询低寿命滤芯 | +| water_quality | 单列索引 | device_id | 查询设备检测记录 | +| water_quality | 单列索引 | test_time | 时间范围查询 | +| water_service_order | 单列索引 | user_id | 查询用户订单 | +| water_service_order | 单列索引 | order_status | 按状态查询 | +| water_service_order | 单列索引 | submit_time | 时间范围查询 | +| water_message | 单列索引 | user_id | 查询用户消息 | +| water_message | 单列索引 | is_read | 查询未读消息 | + +### 5.3 联合索引(复杂查询优化) + +```sql +-- 员工查询某状态的订单 +CREATE INDEX idx_staff_status ON water_service_order(staff_id, order_status); + +-- 用户查询某时间段的订单 +CREATE INDEX idx_user_time ON water_service_order(user_id, submit_time); + +-- 设备查询某时间段的水质记录 +CREATE INDEX idx_device_time ON water_quality(device_id, test_time); + +-- 查询未读消息 +CREATE INDEX idx_user_read ON water_message(user_id, is_read); +``` + +--- + +## ⚡ 六、性能优化建议 + +### 6.1 Redis 缓存策略 + +```java +// 1. 设备状态缓存(5分钟) +@Cacheable(value = "water:device:status", key = "#deviceId", expire = 300) +public String getDeviceStatus(Long deviceId); + +// 2. 用户信息缓存(30分钟) +@Cacheable(value = "water:user:info", key = "#userId", expire = 1800) +public WaterUser getUserInfo(Long userId); + +// 3. 员工绩效缓存(1小时) +@Cacheable(value = "water:staff:performance", key = "#staffId", expire = 3600) +public StaffPerformance getStaffPerformance(Long staffId); + +// 4. 商品列表缓存(10分钟) +@Cacheable(value = "water:product:list", key = "#category", expire = 600) +public List getProductList(String category); + +// 5. 系统配置缓存(永久,手动清除) +@Cacheable(value = "water:config", key = "#configKey") +public String getConfigValue(String configKey); +``` + +### 6.2 定时任务 + +```java +// 1. 每日凌晨1点更新滤芯寿命 +@Scheduled(cron = "0 0 1 * * ?") +public void updateFilterLife() { + // 批量更新滤芯寿命百分比 + filterMapper.batchUpdateLifePercentage(); +} + +// 2. 每日凌晨2点更新员工统计 +@Scheduled(cron = "0 0 2 * * ?") +public void updateStaffStatistics() { + List list = staffMapper.selectPerformanceFromView(); + for (StaffPerformance perf : list) { + staffMapper.updateStatistics(perf); + } +} + +// 3. 每小时检查订单自动完成 +@Scheduled(cron = "0 0 * * * ?") +public void autoCompleteOrder() { + Integer hours = configService.getConfigValueAsInt("order.auto_complete_hours", 24); + orderMapper.autoCompleteByHours(hours); +} + +// 4. 每10分钟检查设备离线状态 +@Scheduled(cron = "0 */10 * * * ?") +public void checkDeviceOffline() { + deviceMapper.updateOfflineStatus(); +} +``` + +### 6.3 分页查询优化 + +```java +// 使用 PageHelper 进行分页 +PageHelper.startPage(pageNum, pageSize); +List list = orderMapper.selectOrderList(order); +return getDataTable(list); +``` + +### 6.4 批量操作 + +```sql +-- 批量插入水质检测数据 +INSERT INTO water_quality (device_id, user_id, test_time, ph_value, turbidity) +VALUES + (1, 1, NOW(), 7.2, 0.5), + (2, 2, NOW(), 7.0, 0.6), + (3, 3, NOW(), 7.1, 0.4); + +-- 批量更新滤芯寿命 +UPDATE water_filter +SET used_days = DATEDIFF(NOW(), install_time), + life_percentage = GREATEST(0, ROUND((total_days - used_days) * 100.0 / total_days, 0)), + status = CASE WHEN life_percentage <= 10 THEN '1' ELSE '0' END +WHERE del_flag = '0'; +``` + +--- + +## 🔐 七、数据安全 + +### 7.1 敏感字段处理 + +```java +// 手机号脱敏 +public String maskPhone(String phone) { + if (StringUtils.isEmpty(phone) || phone.length() != 11) { + return phone; + } + return phone.substring(0, 3) + "****" + phone.substring(7); +} + +// 查询时自动脱敏 +SELECT + user_id, + CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) AS phone, + nick_name +FROM water_user; +``` + +### 7.2 密码加密 + +```java +// 使用 BCrypt 加密 +@Service +public class PasswordService { + @Autowired + private PasswordEncoder passwordEncoder; + + public String encryptPassword(String password) { + return passwordEncoder.encode(password); + } + + public boolean matches(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } +} +``` + +--- + +## 📡 八、与 RuoYi 框架对接 + +### 8.1 字段规范对接 + +所有表均包含 RuoYi 标准字段: + +```sql +create_by VARCHAR(64) -- 创建者 +create_time DATETIME -- 创建时间 +update_by VARCHAR(64) -- 更新者 +update_time DATETIME -- 更新时间 +remark VARCHAR(500) -- 备注 +del_flag CHAR(1) -- 删除标志(0存在 2删除) +``` + +### 8.2 数据权限对接 + +```java +// 员工只能查看本部门数据 +@DataScope(deptAlias = "d", userAlias = "s") +public List selectStaffList(WaterStaff staff); + +// 用户只能查看自己的订单 +@DataScope(userAlias = "o", userCol = "user_id") +public List selectOrderList(WaterServiceOrder order); +``` + +### 8.3 字典管理对接 + +在 RuoYi 的 `sys_dict_type` 中新增字典类型: + +| 字典类型 | 字典名称 | 字典键值 | +|---------|---------|---------| +| water_order_status | 订单状态 | pending/paid/accepted/processing/completed/cancelled | +| water_service_type | 服务类型 | 设备安装/滤芯更换/维修/订购/水质检测 | +| water_device_status | 设备状态 | 0离线/1在线/2故障 | +| water_payment_method | 支付方式 | wechat/balance/alipay | +| water_quality_level | 水质等级 | 优质/良好/一般/较差 | +| water_product_category | 商品分类 | purifier/meter/parts/service | + +### 8.4 菜单权限配置 + +``` +数智水管家 +├─ 用户管理 +│ ├─ 用户列表(water:user:list) +│ └─ 员工管理(water:staff:list) +├─ 设备管理 +│ ├─ 设备列表(water:device:list) +│ ├─ 滤芯管理(water:filter:list) +│ └─ 水质检测(water:quality:list) +├─ 商品管理 +│ ├─ 商品列表(water:product:list) +│ └─ 商品分类(water:product:category) +├─ 订单管理 +│ ├─ 订单列表(water:order:list) +│ ├─ 订单详情(water:order:query) +│ ├─ 派单(water:order:dispatch) +│ └─ 取消订单(water:order:cancel) +├─ 评价管理 +│ └─ 评价列表(water:evaluation:list) +├─ 消息管理 +│ ├─ 系统消息(water:message:list) +│ └─ 通知公告(water:notice:list) +└─ 统计分析 + ├─ 数据看板(water:statistics:dashboard) + ├─ 员工绩效(water:statistics:staff) + └─ 订单报表(water:statistics:order) +``` + +--- + +## 📱 九、API 接口清单 + +### 9.1 用户端(/water/app) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /auth/login | POST | 用户登录 | water_user | +| /auth/wechat | POST | 微信登录 | water_user | +| /device/list | GET | 设备列表 | water_device | +| /device/detail/{sn} | GET | 设备详情 | water_device, water_filter, water_quality | +| /device/bind | POST | 绑定设备 | water_device | +| /filter/list | GET | 滤芯列表 | water_filter | +| /quality/list | GET | 水质检测列表 | water_quality | +| /quality/apply | POST | 申请水质检测 | water_service_order | +| /product/list | GET | 商品列表 | water_product | +| /order/create | POST | 创建订单 | water_service_order, water_order_product | +| /order/list | GET | 订单列表 | water_service_order | +| /order/detail/{id} | GET | 订单详情 | water_service_order | +| /order/pay | POST | 订单支付 | water_service_order | +| /order/cancel | POST | 取消订单 | water_service_order | +| /order/evaluate | POST | 订单评价 | water_evaluation | +| /message/list | GET | 消息列表 | water_message | +| /notice/list | GET | 公告列表 | water_notice | + +### 9.2 员工端(/water/staff) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /auth/login | POST | 员工登录 | water_staff | +| /workorder/list | GET | 工单列表 | water_service_order | +| /workorder/accept | POST | 接单 | water_service_order | +| /workorder/start | POST | 开始处理 | water_service_order | +| /workorder/complete | POST | 完成工单 | water_service_order | +| /delivery/list | GET | 配送任务列表 | water_service_order | +| /statistics | GET | 我的统计 | v_staff_performance | +| /evaluation/list | GET | 我的评价 | water_evaluation | + +### 9.3 管理后台(/water/admin) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /user/list | GET | 用户列表 | water_user | +| /staff/list | GET | 员工列表 | water_staff | +| /device/list | GET | 设备列表 | water_device | +| /product/list | GET | 商品列表 | water_product | +| /product/save | POST | 保存商品 | water_product | +| /order/list | GET | 订单列表 | water_service_order | +| /order/dispatch | POST | 派单 | water_service_order | +| /notice/list | GET | 公告列表 | water_notice | +| /notice/publish | POST | 发布公告 | water_notice | +| /statistics/dashboard | GET | 数据看板 | v_order_statistics | +| /statistics/staff | GET | 员工绩效 | v_staff_performance | + +--- + +## 📈 十、数据库部署 + +### 10.1 创建数据库 + +```sql +CREATE DATABASE `water_manager` + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_general_ci; + +USE `water_manager`; +``` + +### 10.2 执行建表脚本 + +执行配套的 `数智水管家数据库设计_v2.0.sql` 脚本文件。 + +### 10.3 初始化数据 + +```sql +-- 1. 初始化系统配置 +INSERT INTO water_config (config_key, config_value, config_type, config_desc) VALUES +('order.auto_complete_hours', '24', 'number', '订单自动完成时间(小时)'), +('filter.warning_threshold', '30', 'number', '滤芯寿命预警阈值(%)'), +('service.quality_test_price', '99.00', 'number', '水质检测服务价格'), +('delivery.base_fee', '5.00', 'number', '配送费起步价'); + +-- 2. 初始化商品数据 +INSERT INTO water_product (product_name, product_desc, category, price, icon, status, sort_order) VALUES +('智能净水器', 'RO反渗透,5级过滤', 'purifier', 1299.00, '💧', '0', 1), +('智能水表', '远程抄表,实时监测', 'meter', 299.00, '📊', '0', 2), +('净水器滤芯', 'PP棉+活性炭+RO膜', 'parts', 199.00, '🔧', '0', 3), +('水质检测服务', '上门检测,专业报告', 'service', 99.00, '🔬', '0', 4); + +-- 3. 初始化通知公告 +INSERT INTO water_notice (notice_title, notice_content, notice_type, target_type, status, publish_time) VALUES +('欢迎使用数智水管家', '感谢您使用数智水管家系统,我们将为您提供优质的服务。', 'info', 'all', '0', NOW()), +('关于临时停水通知', '因设备维护,部分区域将在本周末临时停水,请提前做好准备。', 'warning', 'user', '0', NOW()); +``` + +--- + +## ✅ 十一、总结 + +### 11.1 设计优势 + +✅ **功能完整**:12张表覆盖用户端和员工端全部功能 +✅ **结构精简**:相比原设计减少9张表(43%),维护成本大幅降低 +✅ **高度复用**:订单、工单、配送统一管理,避免数据冗余 +✅ **性能优化**:合理的索引设计和缓存策略,支持高并发 +✅ **易于扩展**:预留扩展字段,支持业务快速迭代 +✅ **深度集成**:完美对接 RuoYi 框架,复用权限、字典等功能 + +### 11.2 适用场景 + +- ✅ 中小型水管家业务(日订单量 < 10万) +- ✅ 快速开发 MVP 产品 +- ✅ 与 RuoYi 框架深度集成 +- ✅ 注重数据一致性和维护性 + +### 11.3 后续扩展建议 + +当业务量增长时,可考虑: + +1. **订单分表**:按年/月对 `water_service_order` 分表 +2. **读写分离**:配置 MySQL 主从架构 +3. **缓存集群**:升级为 Redis 集群 +4. **消息队列**:引入 RabbitMQ/Kafka 异步处理 +5. **对象存储**:接入 OSS 存储检测报告、评价图片 + +--- + +**文档版本**:v2.0 +**更新日期**:2025-11-13 +**适配框架**:RuoYi v4.x+ +**数据库版本**:MySQL 5.7+ + +--- + +## 📎 附录 + +### A. ER 图说明 + +``` +用户 (water_user) 1----* 设备 (water_device) +用户 (water_user) 1----* 订单 (water_service_order) +用户 (water_user) 1----* 消息 (water_message) + +设备 (water_device) 1----* 滤芯 (water_filter) +设备 (water_device) 1----* 水质检测 (water_quality) + +员工 (water_staff) 1----* 订单 (water_service_order) +员工 (water_staff) 1----* 消息 (water_message) + +订单 (water_service_order) 1----* 订单商品 (water_order_product) +订单 (water_service_order) 1----1 评价 (water_evaluation) + +商品 (water_product) 1----* 订单商品 (water_order_product) +``` + +### B. 表大小预估 + +| 表名 | 预计记录数 | 单条记录大小 | 预计表大小 | +|------|-----------|-------------|-----------| +| water_user | 100,000 | 1KB | ~100MB | +| water_staff | 100 | 0.5KB | ~50KB | +| water_device | 100,000 | 0.5KB | ~50MB | +| water_filter | 400,000 | 0.3KB | ~120MB | +| water_quality | 1,000,000 | 1KB | ~1GB | +| water_product | 100 | 0.5KB | ~50KB | +| water_service_order | 1,000,000 | 1.5KB | ~1.5GB | +| water_order_product | 2,000,000 | 0.3KB | ~600MB | +| water_evaluation | 500,000 | 1KB | ~500MB | +| water_message | 1,000,000 | 0.5KB | ~500MB | +| water_notice | 100 | 0.5KB | ~50KB | +| water_config | 50 | 0.3KB | ~15KB | +| **总计** | **5,000,350** | - | **~4.37GB** | + +### C. 数据备份策略 + +```bash +# 每日全量备份 +0 2 * * * /usr/bin/mysqldump -u root -p water_manager > /backup/water_manager_$(date +\%Y\%m\%d).sql + +# 每周备份保留 +0 3 * * 0 cp /backup/water_manager_$(date +\%Y\%m\%d).sql /backup/weekly/ + +# 自动清理30天前的备份 +0 4 * * * find /backup -name "*.sql" -mtime +30 -delete +``` + +--- + +**文档结束** + diff --git a/doc/project/02-设计文档/数智水管家uml图/活动图/工作人员工作流程.png b/doc/project/02-设计文档/数智水管家uml图/活动图/工作人员工作流程.png new file mode 100644 index 0000000..9c8b094 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/活动图/工作人员工作流程.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/活动图/普通用户主流程.png b/doc/project/02-设计文档/数智水管家uml图/活动图/普通用户主流程.png new file mode 100644 index 0000000..97f1e6c Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/活动图/普通用户主流程.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/活动图/登录与角色切换.png b/doc/project/02-设计文档/数智水管家uml图/活动图/登录与角色切换.png new file mode 100644 index 0000000..81bb4cb Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/活动图/登录与角色切换.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/活动图/订购订单支付客服.png b/doc/project/02-设计文档/数智水管家uml图/活动图/订购订单支付客服.png new file mode 100644 index 0000000..88e3078 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/活动图/订购订单支付客服.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/活动图/设备管理与水质监测.png b/doc/project/02-设计文档/数智水管家uml图/活动图/设备管理与水质监测.png new file mode 100644 index 0000000..6571184 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/活动图/设备管理与水质监测.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/类图/类图.png b/doc/project/02-设计文档/数智水管家uml图/类图/类图.png new file mode 100644 index 0000000..2f73b46 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/类图/类图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/在线客服界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/在线客服界面.png new file mode 100644 index 0000000..59f4198 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/在线客服界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/我的界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/我的界面.png new file mode 100644 index 0000000..7e0fb2b Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/我的界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/支付界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/支付界面.png new file mode 100644 index 0000000..909eda3 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/支付界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/检测报告界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/检测报告界面.png new file mode 100644 index 0000000..2baff3a Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/检测报告界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面.png new file mode 100644 index 0000000..aba3fde Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面(快捷服务跳转).png b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面(快捷服务跳转).png new file mode 100644 index 0000000..3cb8e81 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质检测界面(快捷服务跳转).png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/水质预警界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质预警界面.png new file mode 100644 index 0000000..aa71915 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/水质预警界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/消息界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/消息界面.png new file mode 100644 index 0000000..7e4d18e Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/消息界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/登录界面顺序图.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/登录界面顺序图.png new file mode 100644 index 0000000..1ad4a5d Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/登录界面顺序图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/订单界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/订单界面.png new file mode 100644 index 0000000..976f7d1 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/订单界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/订单详情.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/订单详情.png new file mode 100644 index 0000000..483fb75 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/订单详情.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/订购界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/订购界面.png new file mode 100644 index 0000000..fa58fa7 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/订购界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/设备管理界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/设备管理界面.png new file mode 100644 index 0000000..d4ffe7a Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/设备管理界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/设备详情界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/设备详情界面.png new file mode 100644 index 0000000..a34578a Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/设备详情界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/问题设备详细界面.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/问题设备详细界面.png new file mode 100644 index 0000000..ec020ea Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/问题设备详细界面.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/首页1-问题设备顺序图.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页1-问题设备顺序图.png new file mode 100644 index 0000000..2f712e5 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页1-问题设备顺序图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/首页2-水质预警顺序图.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页2-水质预警顺序图.png new file mode 100644 index 0000000..810e3ac Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页2-水质预警顺序图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/首页3-轮播图顺序图.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页3-轮播图顺序图.png new file mode 100644 index 0000000..c39ad02 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页3-轮播图顺序图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/首页4-快捷服务顺序图.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页4-快捷服务顺序图.png new file mode 100644 index 0000000..34afccd Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页4-快捷服务顺序图.png differ diff --git a/doc/project/02-设计文档/数智水管家uml图/顺序图/首页5-公告通知.png b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页5-公告通知.png new file mode 100644 index 0000000..d5d2664 Binary files /dev/null and b/doc/project/02-设计文档/数智水管家uml图/顺序图/首页5-公告通知.png differ diff --git a/doc/project/03-计划文档/迭代开发计划第一稿.md b/doc/project/03-计划文档/迭代开发计划第一稿.md new file mode 100644 index 0000000..f0cdfc7 --- /dev/null +++ b/doc/project/03-计划文档/迭代开发计划第一稿.md @@ -0,0 +1,137 @@ +## 1. 简介 + +本迭代开发计划基于现有的「数智水管家」小程序,围绕用户端与工作人员端(工单、配送、统计)的既有功能,规划后续两个阶段(α版、β版)的持续演进与优化工作。计划重点在于:将当前前端演示数据逐步替换为真实后端服务、完善业务闭环、提升性能与用户体验,并为正式上线与后期运维打好基础。 + +## 2. 目的 + +- **明确目标**:明确数智水管家后续版本迭代目标与优先级。 +- **路径清晰**:规划从演示原型到可上线版本的演进路径。 +- **可控过程**:明确各阶段可交付成果和责任角色,便于过程管理与验收。 +- **降低风险**:减少需求变更和技术债带来的风险,提升系统稳定性。 + +## 3. 范围 + +本迭代开发计划覆盖以下内容: + +- **用户端小程序**: + - 登录与角色识别(普通用户 / 工作人员)。 + - 首页信息展示(问题设备、水质预警、公告通知、快捷服务)。 + - 设备管理与设备详情(设备状态、滤芯寿命、水质信息跳转)。 + - 水质检测与检测报告(记录列表、详情与预警联动)。 + - 商品订购与订单管理(商品列表、下单、支付、订单状态流转)。 + - 消息通知与公告展示。 + - 在线客服入口与基础交互。 + +- **工作人员端**: + - 工单列表与工单详情(状态流转:待接单、已接单、处理中、已完成)。 + - 配送任务与配送详情。 + - 工作台与工作统计(数据统计面板)。 + - 员工个人中心(基本信息展示)。 + +- **后端与基础设施**: + - 与新设计数据库(v2.0)的对应接口服务。 + - 基础权限与角色控制(用户 / 员工 / 管理员)。 + - 日志、监控及必要的运维支撑。 + +## 4. 定义、首字母缩写词和缩略语 + +- **小程序**:本文指微信小程序 / uni-app 打包的微信平台前端应用。 +- **用户端**:普通用户使用的小程序界面与功能。 +- **工作人员端 / 员工端**:面向运维、客服、工程师的工作台及相关功能。 +- **设备**:接入系统的净水器 / 水表等智能设备。 +- **工单**:与维修、安装、水质检测等服务相关的工作任务记录。 +- **订单**:用户发起的商业订单,包括商品订购、服务订购、水质检测等。 +- **α版**:内部可用版,功能完整但允许有一定瑕疵,主要用于内部联调与业务验证。 +- **β版**:对外体验版,功能稳定,性能与体验基本达标,可小范围推广。 + +## 5. 参考文档 + +- `database/数据库设计说明_v2.0.md` +- `database/数智水管家数据库设计_v2.0.sql` +- 现有小程序代码(示例): + - 用户端页面:`pages/index/index.vue`、`pages/order/order.vue`、`pages/purchase/purchase.vue`、`pages/device/device.vue`、`pages/device-detail/device-detail.vue`、`pages/water-quality/water-quality.vue`、`pages/water-quality-detail/water-quality-detail.vue`、`pages/water-quality-alert/water-quality-alert.vue`、`pages/message/message.vue`、`pages/customer-service/customer-service.vue`、`pages/profile/profile.vue` 等。 + - 工作人员端页面:`pages/staff/index.vue`、`pages/staff/workorder.vue`、`pages/staff/workorder-detail.vue`、`pages/staff/delivery.vue`、`pages/staff/delivery-detail.vue`、`pages/staff/delivery-task.vue`、`pages/staff/stats.vue`、`pages/staff/profile.vue` 等。 +- 前端路由与导航配置:`pages.json`。 +- 历史设计文档:`database/数据库设计说明_精简版.md`。 + +## 6. 计划 + +整体采用两轮迭代: + +- **α版**: + - **目标**:实现端到端业务闭环(设备–水质–订单–工单),前后端全链路打通,替换前端 Mock 数据为真实接口,完成基础权限与员工端工作流。 + - **特征**:功能完整,允许界面与交互存在一定瑕疵,主要用于内部测试与业务验证。 + +- **β版**: + - **目标**:在 α 版基础上进行体验优化、性能优化、安全与监控补强,完善统计与报表,做好上线前准备。 + - **特征**:功能稳定,用户体验较好,可用于试点或小规模对外发布。 + +## 7. 迭代任务 + +### 7.1 迭代阶段 + +> 说明:不精确到具体日期,仅给出相对阶段。 + +| 迭代时间段 | 任务 | 产品 | +|------------|------|------| +| 第 1 阶段(α版迭代) | 1)搭建后端服务与数据库;2)登录与角色识别打通;3)设备管理、工单、订单等核心场景与接口联调;4)基础水质检测记录与报告查询;5)工作人员端工单和配送流程跑通。 | 内部可用 α 版:可完整演示用户下单、工作人员处理、设备状态和水质查看的业务闭环。 | +| 第 2 阶段(β版迭代) | 1)前端 UI/UX 优化;2)消息与预警推送完善;3)统计报表与工作台数据完善;4)性能与安全加固;5)上线前联调与灰度发布支持。 | 对外体验 β 版:功能稳定、体验良好,可小范围试运行或对接业务方验收。 | + +### 7.2 迭代细分 + +#### 7.2.1 α版 + +| 任务 | 可交付工件 | 责任人 | +|------|------------|--------| +| 用户与工作人员登录打通(含角色识别) | 登录接口、角色字段设计;小程序登录流程(含 token 存储);根据 `userRole` 控制首页与 tabBar 展示。 | 后端开发、前端开发 | +| 接入新数据库结构并完成基础表 CRUD | 基于 `water_user`、`water_staff`、`water_device`、`water_service_order` 等表的实体与 DAO;基础管理接口(用户、设备、订单)。 | 后端开发 | +| 设备管理前后端打通 | `pages/device/device.vue`、`pages/device-detail/device-detail.vue` 改造:设备列表、详情、状态、滤芯信息从后端接口获取;设备解绑与新增接口联调。 | 前端开发、后端开发 | +| 首页数据来源改造 | 首页问题设备、水质预警、公告通知由接口提供;与设备、水质、通知表联动。 | 前端开发、后端开发 | +| 水质检测记录与报告 | 基于 `water_quality` 实现水质检测记录查询接口;改造 `pages/water-quality/water-quality.vue` 与 `pages/water-quality-detail/water-quality-detail.vue`,读取真实数据;水质等级映射与描述逻辑后端实现。 | 后端开发、前端开发 | +| 商品订购与订单创建 | 基于 `water_product`、`water_service_order`、`water_order_product` 完成商品列表、订单创建接口;改造 `pages/purchase/purchase.vue`、`pages/order/order.vue` 的数据来源和状态流转。 | 后端开发、前端开发 | +| 支付流程打通(可对接测试支付或模拟支付) | 支付请求接口、支付状态回调模拟;`pages/payment/payment.vue` 与订单状态联动(pending → paid)。 | 后端开发、前端开发 | +| 工单/服务单统一建模与工作人员端工单流程 | 使用 `water_service_order` 统一支持工单;改造 `pages/staff/workorder.vue`、`pages/staff/workorder-detail.vue`:工单列表、接单/开始处理/完成接口打通。 | 后端开发、前端开发 | +| 配送任务数据与界面联通 | 基于 `water_service_order` 的服务类型或标记,提供配送任务列表接口;改造 `pages/staff/delivery.vue`、`pages/staff/delivery-detail.vue`、`pages/staff/delivery-task.vue`。 | 后端开发、前端开发 | +| 基本系统消息与公告接口 | 基于 `water_message`、`water_notice` 表实现查询接口;改造 `pages/message/message.vue` 与首页公告模块。 | 后端开发、前端开发 | +| 基础接口鉴权与日志 | 接口鉴权中间件(token 验证);关键接口日志记录(登录、下单、状态变更等)。 | 后端开发 | +| α版联调与冒烟测试 | α版功能列表与用例;手工测试报告(核心流程:登录–下单–工单–完结–评价–水质查看)。 | 测试、产品 | + +#### 7.2.2 β版 + +| 任务 | 可交付工件 | 责任人 | +|------|------------|--------| +| UI/UX 优化与交互细节完善 | 首页、订单、设备、水质、工单、配送等页面的视觉与交互优化稿;统一样式(颜色、间距、图标);加载状态与空状态处理。 | 产品、前端开发 | +| 消息通知与预警机制完善 | 水质异常、设备离线、滤芯寿命预警的规则实现;通过 `water_message` 推送到用户端/工作人员端;前端消息红点和列表展示优化。 | 后端开发、前端开发 | +| 统计报表与工作台完善 | 基于 `v_staff_performance`、`v_order_statistics` 完善工作人员工作台与管理后台数据展示;`pages/staff/stats.vue` 展示员工个人绩效。 | 后端开发、前端开发 | +| 性能优化与缓存策略落地 | 针对高频接口(设备列表、水质记录、订单列表等)增加 Redis 缓存;数据库索引检查与优化;分页查询优化。 | 后端开发 | +| 安全加固 | 敏感数据脱敏(手机号等);权限控制完善(区分普通用户、工作人员、管理员);防止越权访问与注入攻击。 | 后端开发 | +| 异常处理与日志监控 | 接口错误码规范;前端友好错误提示;关键流程监控指标定义(下单成功率、接口失败率等)。 | 后端开发、测试 | +| 测试用例扩展与回归测试 | 功能测试、接口测试、兼容性测试用例编写与执行;发现并修复 β 版问题。 | 测试、前端开发、后端开发 | +| 上线预案与回滚策略 | 上线步骤文档(数据库脚本执行顺序、服务发布顺序);回滚方案(数据库备份、版本回退流程)。 | 后端开发、运维、产品 | + +## 8. 人员配备 + +> 以下为按角色划分的建议配置,可根据实际团队情况合并或拆分角色。 + +- **产品经理** + - 杨默涵 + +- **前端开发(小程序 / uni-app)** + - 杨默涵 + - 杨振宇 + +- **后端开发** + - 杨默涵 + - 梁晨旭 + - 杨捷 + - 杨帅路 + +- **测试工程师** + - 梁晨旭 + - 杨振宇 + +- **平台管理员** + - 杨捷 + - 杨帅路 + + diff --git a/doc/project/03-计划文档/迭代开发计划第三稿.md b/doc/project/03-计划文档/迭代开发计划第三稿.md new file mode 100644 index 0000000..7ebd62f --- /dev/null +++ b/doc/project/03-计划文档/迭代开发计划第三稿.md @@ -0,0 +1,243 @@ +## 1. 简介 + +本迭代开发计划基于现有的「数智水管家」小程序,聚焦于贝塔版本(β版)的迭代开发工作。计划重点在于:在阿尔法版本核心功能完成的基础上,进行体验优化、性能提升、安全加固,为正式上线与生产环境部署做好准备。 + +贝塔版本作为对外体验版,将在α版功能稳定的基础上,完善UI/UX设计、消息通知机制、统计报表功能、性能优化和安全防护,达到可小范围试运行的标准。相较于第二稿,第三稿进一步细化了β版规划、增加了验收标准和质量保证措施,体现了从内部可用向对外体验的转变。 + +## 2. 目的 + +- **体验提升**:完善UI/UX设计,提升用户操作体验和视觉效果。 +- **功能完善**:补全消息通知、统计报表、监控告警等辅助功能。 +- **性能优化**:提升系统响应速度、稳定性,并进行必要的性能调优。 +- **安全加固**:完善权限控制、数据脱敏、安全防护等安全措施。 +- **质量保证**:建立完整的测试体系,确保系统达到上线标准。 +- **部署准备**:制定上线预案、回滚策略,为生产环境部署做好准备。 + +## 3. 范围 + +本迭代开发计划聚焦于贝塔版本的开发工作,覆盖以下内容: + +**纳入范围:** +- **用户端小程序体验优化**: + - UI/UX设计完善和视觉统一。 + - 消息通知与预警推送机制。 + - 订单评价与反馈系统。 + - 个人中心功能完善。 + +- **工作人员端功能完善**: + - 工作统计面板与数据可视化。 + - 工单状态流转优化。 + - 配送任务管理完善。 + - 员工个人中心功能扩展。 + +- **后端系统优化**: + - 性能优化与缓存策略。 + - 安全加固与权限控制。 + - 监控告警系统建设。 + - 日志系统完善。 + +- **测试与质量保证**: + - 功能测试、性能测试、兼容性测试。 + - 用户验收测试。 + - 安全测试与渗透测试。 + +**排除范围:** +- 新功能模块开发。 +- 第三方服务深度集成(除支付外)。 +- 大规模数据迁移。 +- 生产环境运维部署。 + +## 4. 定义、首字母缩写词和缩略语 + +- **小程序**:本文指微信小程序 / uni-app 打包的微信平台前端应用。 +- **用户端**:普通用户使用的小程序界面与功能。 +- **工作人员端 / 员工端**:面向运维、客服、工程师的工作台及相关功能。 +- **设备**:接入系统的净水器 / 水表等智能设备。 +- **工单**:与维修、安装、水质检测等服务相关的工作任务记录。 +- **订单**:用户发起的商业订单,包括商品订购、服务订购、水质检测等。 +- **β版**:对外体验版,功能稳定,性能与体验基本达标,可小范围推广。 +- **UI/UX**:用户界面(User Interface)和用户体验(User Experience)。 +- **缓存策略**:通过Redis等技术提升系统响应速度的数据存储策略。 +- **监控告警**:系统运行状态监控和异常情况自动告警机制。 +- **P0/P1/P2/P3**:任务优先级,P0最高优先级,P3最低优先级。 +- **灰度发布**:分阶段逐步发布新版本的部署策略。 + +## 5. 参考文档 + +- `database/数据库设计说明_v2.0.md` +- `database/数智水管家数据库设计_v2.0.sql` +- 现有小程序代码: + - 用户端页面:`pages/index/index.vue`、`pages/order/order.vue`、`pages/purchase/purchase.vue`、`pages/device/device.vue`、`pages/device-detail/device-detail.vue`、`pages/water-quality/water-quality.vue`、`pages/water-quality-detail/water-quality-detail.vue`、`pages/water-quality-alert/water-quality-alert.vue`、`pages/message/message.vue`、`pages/customer-service/customer-service.vue`、`pages/profile/profile.vue` 等。 + - 工作人员端页面:`pages/staff/index.vue`、`pages/staff/workorder.vue`、`pages/staff/workorder-detail.vue`、`pages/staff/delivery.vue`、`pages/staff/delivery-detail.vue`、`pages/staff/delivery-task.vue`、`pages/staff/stats.vue`、`pages/staff/profile.vue` 等。 +- 前端路由与导航配置:`pages.json`。 +- 历史设计文档:`database/数据库设计说明_精简版.md`。 +- 迭代开发计划第一稿.md(总体规划参考)。 +- 迭代开发计划第二稿_阿尔法版本.md(α版执行基础)。 +- 功能完成说明文档: + - 登录功能完成说明.md + - 首页功能完成说明.md + - 设备管理功能完成说明.md + - 订单管理功能完成说明.md + +## 6. 计划 + +贝塔版本采用两轮迭代模式,聚焦于体验优化和系统完善。 + +- **β版**: + - **目标**:在α版基础上进行体验优化、性能提升、安全加固,完善消息通知、统计报表和监控机制,达到可小范围试运行的标准。 + - **特征**:功能稳定,用户体验良好,系统性能达标,安全可靠,可用于试点推广。 + - **时间规划**:2025年12月15日-2025年12月28日,共计2周(10个工作日)。 + - **成功标准**:用户体验满意度≥85%,系统性能满足生产要求,安全测试通过率≥95%,核心业务流程测试通过率≥98%。 + +## 7. 迭代任务 + +### 7.1 迭代阶段 + +> 说明:基于第二稿的成功经验,贝塔版本采用4个具体阶段,确保质量优先和风险可控。 + +| 迭代时间段 | 任务 | 产品 | 验收标准 | +|------------|------|------|----------| +| 第 1 阶段(体验优化) | UI/UX设计完善、消息通知机制、订单评价系统 | 体验优化完成 | UI一致性≥95%,消息送达率≥98%,评价功能可用 | +| 第 2 阶段(功能完善) | 统计报表完善、员工端功能优化、个人中心扩展 | 功能完善完成 | 统计数据准确率≥99%,员工端功能完整性≥95% | +| 第 3 阶段(性能安全) | 性能优化、安全加固、监控告警建设 | 系统优化完成 | 接口响应时间≤1s,安全漏洞修复率≥95%,监控覆盖率≥90% | +| 第 4 阶段(测试发布) | 全面测试、上线准备、灰度发布 | β版发布就绪 | 测试通过率≥95%,部署成功率≥99%,用户反馈积极 | + +### 7.2 迭代细分 + +#### 7.2.1 β版 + +| 任务 | 可交付工件 | 责任人 | 优先级 | 预计工时 | 前置任务 | +|------|------------|--------|--------|----------|----------| +| UI设计规范制定 | 设计规范文档、组件库 | 杨默涵 | P0 | 8h | - | +| 全局样式统一 | 主题色、字体、间距规范应用 | 杨默涵 | P0 | 12h | 设计规范制定 | +| 首页UI优化 | 卡片设计、图标优化、布局调整 | 杨默涵 | P0 | 8h | 全局样式统一 | +| 订单评价功能 | 评价界面、评分系统、反馈提交 | 杨默涵 | P0 | 10h | 全局样式统一 | +| 消息推送机制 | 极光推送集成、消息模板、推送策略 | 杨捷 | P0 | 12h | - | +| 预警通知完善 | 水质异常、设备故障、滤芯更换提醒 | 杨帅路 | P0 | 8h | 消息推送机制 | +| 公告通知优化 | 公告分类、阅读状态、推送设置 | 杨振宇 | P1 | 6h | 消息推送机制 | +| 工作人员端UI优化 | 工作台布局、统计图表、操作流程 | 杨振宇 | P0 | 10h | 全局样式统一 | +| 统计面板开发 | 数据可视化、图表组件、实时更新 | 杨振宇 | P0 | 12h | - | +| 工单流程优化 | 状态流转图、操作引导、异常处理 | 杨振宇 | P1 | 8h | 工作人员端UI优化 | +| 配送任务完善 | 路线规划、时间安排、状态跟踪 | 杨振宇 | P1 | 6h | 工作人员端UI优化 | +| 个人中心扩展 | 用户信息完善、地址管理、偏好设置 | 杨默涵 | P1 | 8h | 全局样式统一 | +| 缓存策略实现 | Redis集成、高频接口缓存、缓存更新机制 | 梁晨旭 | P0 | 12h | - | +| 数据库性能优化 | 索引优化、查询优化、分页策略 | 杨捷 | P0 | 10h | - | +| 接口性能调优 | 响应时间优化、并发处理、错误处理 | 梁晨旭 | P0 | 8h | 缓存策略实现 | +| 安全加固实施 | 数据脱敏、权限控制、防止注入攻击 | 梁晨旭 | P0 | 10h | - | +| 监控系统建设 | 接口监控、错误日志、性能指标收集 | 杨帅路 | P0 | 8h | - | +| 告警机制实现 | 异常检测、自动告警、告警策略 | 杨帅路 | P1 | 6h | 监控系统建设 | +| 功能测试执行 | 测试用例编写、回归测试、缺陷修复 | 全员 | P0 | 16h | 体验优化完成 | +| 性能测试执行 | 压力测试、负载测试、性能分析 | 梁晨旭 | P0 | 8h | 性能安全完成 | +| 兼容性测试 | 多机型测试、版本兼容、异常处理 | 杨振宇 | P1 | 6h | 功能完善完成 | +| 安全测试 | 渗透测试、安全扫描、漏洞修复 | 杨捷 | P0 | 8h | 安全加固实施 | +| 用户验收测试 | 用户体验评估、反馈收集、问题修复 | 杨默涵 | P0 | 8h | 功能测试执行 | +| 部署文档编写 | 部署手册、回滚方案、监控配置 | 杨捷 | P1 | 6h | 全阶段 | +| 灰度发布准备 | 分批发布策略、回滚预案、监控方案 | 杨帅路 | P0 | 4h | 部署文档编写 | +| β版发布部署 | 系统上线、监控启动、日志收集 | 全员 | P0 | 4h | 灰度发布准备 | +| 发布总结报告 | 项目总结、用户反馈分析、后续优化计划 | 梁晨旭 | P1 | 4h | β版发布部署 | + +## 8. 风险评估与应对策略 + +### 8.1 技术风险 + +| 风险项 | 概率 | 影响 | 应对策略 | +|--------|------|------|----------| +| UI设计规范落地困难 | 中 | 高 | 提前制定规范,组织设计评审,确保团队理解一致 | +| 消息推送集成复杂 | 中 | 中 | 预留充足时间进行技术调研,准备备用方案 | +| 性能优化效果不佳 | 中 | 高 | 制定明确的性能指标,预先进行性能基线测试 | +| 安全漏洞遗漏 | 低 | 高 | 引入专业安全测试,建立安全检查清单 | + +### 8.2 进度风险 + +| 风险项 | 概率 | 影响 | 应对策略 | +|--------|------|------|----------| +| 需求变更频繁 | 高 | 中 | 设立需求冻结期,建立变更控制流程 | +| 人员资源不足 | 中 | 高 | 提前进行人员安排,准备后备人选 | +| 第三方服务不稳定 | 中 | 中 | 设计降级策略,准备本地备用方案 | + +### 8.3 质量风险 + +| 风险项 | 概率 | 影响 | 应对策略 | +|--------|------|------|----------| +| 测试不充分 | 中 | 高 | 制定详细测试计划,引入自动化测试 | +| 用户体验不佳 | 中 | 高 | 进行用户访谈,收集早期反馈 | +| 兼容性问题 | 高 | 中 | 扩大测试机型范围,建立兼容性测试环境 | + +## 9. 质量保证体系 + +### 9.1 测试策略 + +- **单元测试**:核心业务逻辑测试覆盖率≥80% +- **接口测试**:API功能完整性测试,覆盖所有业务接口 +- **UI测试**:界面一致性检查,操作流程验证 +- **性能测试**:并发用户≥100,平均响应时间≤1秒 +- **兼容性测试**:覆盖主流微信版本和机型 +- **安全测试**:通过专业安全扫描,无高危漏洞 + +### 9.2 验收标准 + +- **功能完整性**:所有规划功能100%实现,核心流程100%打通 +- **性能指标**:接口响应时间≤1秒,页面加载时间≤2秒 +- **用户体验**:操作流程顺畅,无明显交互缺陷 +- **安全合规**:通过安全测试,无安全漏洞 +- **兼容性**:支持98%的目标用户设备 + +### 9.3 监控机制 + +- **线上监控**:接口调用量、响应时间、错误率 +- **用户反馈**:收集用户使用反馈,建立反馈渠道 +- **异常告警**:系统异常自动告警,24小时响应 +- **性能监控**:实时监控系统性能指标 + +## 10. 人员配备 + +> 以下为贝塔版本迭代的建议配置,可根据实际团队情况合并或拆分角色。 + +- **产品经理** + - 杨默涵(负责需求管理、用户体验优化、验收测试) + +- **前端开发(小程序 / uni-app)** + - 杨默涵(负责UI/UX优化、用户端功能完善) + - 杨振宇(负责工作人员端优化、统计面板开发) + +- **后端开发** + - 梁晨旭(负责性能优化、安全加固、缓存策略) + - 杨捷(负责数据库优化、监控系统、部署准备) + - 杨帅路(负责消息推送、告警机制、API优化) + +- **测试工程师** + - 梁晨旭(负责性能测试、安全测试) + - 杨振宇(负责功能测试、兼容性测试) + +- **UI设计师** + - 杨默涵(负责设计规范制定、视觉优化) + +- **运维工程师** + - 杨捷(负责部署准备、监控配置) + - 杨帅路(负责灰度发布、系统监控) + +## 11. 沟通与协作 + +- **每日站会**:15分钟,汇报进展、识别障碍、调整计划 +- **周例会**:1小时,评审完成工作、规划下周任务、风险评估 +- **设计评审**:UI/UX变更时进行,确保设计一致性 +- **代码评审**:所有代码提交前进行,确保代码质量 +- **测试评审**:测试阶段进行,确保质量标准 +- **发布评审**:上线前进行,确保发布就绪 + +## 12. 里程碑与交付物 + +| 里程碑 | 完成时间 | 交付物 | 验收标准 | +|--------|----------|--------|----------| +| 体验优化完成 | 第1阶段结束 | UI设计规范、优化后的界面、消息推送功能 | UI一致性≥95%,消息送达率≥98% | +| 功能完善完成 | 第2阶段结束 | 统计面板、完善的工作人员端、扩展的个人中心 | 统计准确率≥99%,功能完整性≥95% | +| 系统优化完成 | 第3阶段结束 | 优化后的系统、安全加固的代码、监控告警系统 | 性能达标,安全测试通过 | +| β版发布就绪 | 第4阶段结束 | 测试通过的系统、部署文档、发布总结 | 测试通过率≥95%,部署成功 | + +--- + +**最后更新**:2025年12月30日 + +**版本号**:v3.0 + +**作者**:梁晨旭、杨默涵、杨振宇、杨捷、杨帅路 diff --git a/doc/project/03-计划文档/迭代开发计划第二稿.md b/doc/project/03-计划文档/迭代开发计划第二稿.md new file mode 100644 index 0000000..9451eb3 --- /dev/null +++ b/doc/project/03-计划文档/迭代开发计划第二稿.md @@ -0,0 +1,153 @@ +## 1. 简介 + +本迭代开发计划基于现有的「数智水管家」小程序,聚焦于阿尔法版本(α版)的迭代开发工作。计划重点在于:将前端演示数据逐步替换为真实后端服务、完善业务闭环、提升系统稳定性和用户体验,为后续β版迭代奠定坚实基础。 + +阿尔法版本作为内部可用版,将实现端到端业务闭环(设备–水质–订单–工单),前后端全链路打通,完成基础权限与员工端工作流。相较于第一稿,第二稿进一步细化了时间规划、风险评估、任务分解和验收标准,提升了计划的可操作性和执行效率。 + +## 2. 目的 + +- **明确目标**:详细定义阿尔法版本的具体目标、成功标准和验收准则,确保团队对版本定位有清晰认识。 +- **时间可控**:基于第一稿内容,进一步细化时间规划,设立明确的里程碑和交付时间点。 +- **风险管控**:识别潜在风险,制定应对策略,降低项目执行过程中的不确定性。 +- **质量保证**:建立完整的质量保证体系,包括测试策略、验收标准和监控机制。 +- **提升效率**:通过精细化的任务分解和依赖关系管理,提高团队协作效率和执行效能。 + +## 3. 范围 + +本迭代开发计划聚焦于阿尔法版本的开发工作,覆盖以下内容: + +**纳入范围:** +- **用户端小程序核心功能**: + - 登录与角色识别(普通用户 / 工作人员)。 + - 首页信息展示(问题设备、水质预警、公告通知、快捷服务)。 + - 设备管理与设备详情(设备状态、滤芯寿命、水质信息跳转)。 + - 水质检测与检测报告(记录列表、详情与预警联动)。 + - 商品订购与订单管理(商品列表、下单、支付、订单状态流转)。 + - 消息通知与公告展示。 + - 在线客服入口与基础交互。 + +- **工作人员端基础功能**: + - 工单列表与工单详情(状态流转:待接单、已接单、处理中、已完成)。 + - 配送任务与配送详情。 + - 工作台与工作统计(数据统计面板)。 + - 员工个人中心(基本信息展示)。 + +- **后端与基础设施**: + - 与新设计数据库(v2.0)的对应接口服务。 + - 基础权限与角色控制(用户 / 员工 / 管理员)。 + - 日志、监控及必要的运维支撑。 + +**排除范围:** +- 高级UI/UX优化和视觉设计完善。 +- 复杂的数据分析和高级报表功能。 +- 第三方服务深度集成(如微信支付正式环境)。 +- 性能优化和监控告警系统。 +- β版相关功能开发。 + +## 4. 定义、首字母缩写词和缩略语 + +- **小程序**:本文指微信小程序 / uni-app 打包的微信平台前端应用。 +- **用户端**:普通用户使用的小程序界面与功能。 +- **工作人员端 / 员工端**:面向运维、客服、工程师的工作台及相关功能。 +- **设备**:接入系统的净水器 / 水表等智能设备。 +- **工单**:与维修、安装、水质检测等服务相关的工作任务记录。 +- **订单**:用户发起的商业订单,包括商品订购、服务订购、水质检测等。 +- **α版**:内部可用版,功能完整但允许有一定瑕疵,主要用于内部联调与业务验证。 +- **业务闭环**:从用户发起请求到服务完成的完整流程。 +- **端到端**:覆盖前端、后端、数据库的完整技术栈。 +- **P0/P1/P2/P3**:任务优先级,P0最高优先级,P3最低优先级。 +- **里程碑**:项目执行过程中的关键时间点和交付物。 + +## 5. 参考文档 + +- `database/数据库设计说明_v2.0.md` +- `database/数智水管家数据库设计_v2.0.sql` +- 现有小程序代码(示例): + - 用户端页面:`pages/index/index.vue`、`pages/order/order.vue`、`pages/purchase/purchase.vue`、`pages/device/device.vue`、`pages/device-detail/device-detail.vue`、`pages/water-quality/water-quality.vue`、`pages/water-quality-detail/water-quality-detail.vue`、`pages/water-quality-alert/water-quality-alert.vue`、`pages/message/message.vue`、`pages/customer-service/customer-service.vue`、`pages/profile/profile.vue` 等。 + - 工作人员端页面:`pages/staff/index.vue`、`pages/staff/workorder.vue`、`pages/staff/workorder-detail.vue`、`pages/staff/delivery.vue`、`pages/staff/delivery-detail.vue`、`pages/staff/delivery-task.vue`、`pages/staff/stats.vue`、`pages/staff/profile.vue` 等。 +- 前端路由与导航配置:`pages.json`。 +- 历史设计文档:`database/数据库设计说明_精简版.md`。 +- 迭代开发计划第一稿.md(本计划的参考基础)。 + +## 6. 计划 + +阿尔法版本采用单轮迭代模式,聚焦于核心功能的完整实现和业务闭环的打通。 + +- **α版**: + - **目标**:实现端到端业务闭环(设备–水质–订单–工单),前后端全链路打通,替换前端 Mock 数据为真实接口,完成基础权限与员工端工作流。 + - **特征**:功能完整,允许界面与交互存在一定瑕疵,主要用于内部测试与业务验证。 + - **时间规划**:2025年11月10日-2025年12月14日,共计5周(25个工作日)。 + - **成功标准**:核心业务流程100%打通,系统可用性≥99.5%,业务闭环完整可演示。 + +## 7. 迭代任务 + +### 7.1 迭代阶段 + +> 说明:基于第二稿的优化,阿尔法版本采用5个具体阶段,确保时间可控和质量保证。 + +| 迭代时间段 | 任务 | 产品 | 验收标准 | +|------------|------|------|----------| +| 第 1 阶段(准备阶段) | 开发环境搭建、需求确认、数据库部署、分支管理 | 开发环境就绪 | 环境一致性100%,需求范围明确 | +| 第 2 阶段(核心开发1) | 后端基础框架、用户认证、数据库集成、基础CRUD、前端登录改造 | 基础框架完成 | 登录认证接口可用,数据库连接正常 | +| 第 3 阶段(核心开发2) | 业务接口开发(设备、水质、订单、工单、消息)、前端联调、工作人员端基础功能 | 核心业务完成 | 主要业务模块接口联调通过 | +| 第 4 阶段(集成测试) | 单元测试、接口测试、业务流程测试、兼容性测试、Bug修复 | 系统集成完成 | 核心流程测试通过,bug修复率≥90% | +| 第 5 阶段(验收发布) | 系统集成验证、文档归档、α版发布、总结报告 | α版发布就绪 | 系统可正常运行,文档完整齐全 | + +### 7.2 迭代细分 + +#### 7.2.1 α版 + +| 任务 | 可交付工件 | 责任人 | 优先级 | 预计工时 | 前置任务 | +|------|------------|--------|--------|----------|----------| +| 开发环境统一搭建 | 环境配置文档、开发规范 | 梁晨旭 | P0 | 4h | - | +| 需求规格确认 | α版需求确认文档 | 杨默涵 | P0 | 4h | - | +| 数据库v2.0部署 | 数据库部署脚本、基础数据 | 杨捷 | P0 | 4h | - | +| 项目分支管理 | Git分支策略文档 | 杨帅路 | P1 | 2h | 环境搭建 | +| 后端基础框架搭建 | Spring Boot项目结构、基础配置 | 梁晨旭 | P0 | 8h | 数据库部署 | +| 用户认证接口开发 | 登录接口、Token机制、角色识别 | 梁晨旭 | P0 | 6h | 框架搭建 | +| 数据库实体映射 | 主要实体类(User, Device, Order等) | 杨捷 | P0 | 12h | 数据库部署 | +| 基础CRUD接口开发 | 用户、设备、订单基础管理接口 | 杨帅路 | P0 | 16h | 实体映射 | +| 前端登录模块改造 | 支持真实登录、角色切换 | 杨默涵 | P1 | 6h | 用户认证接口 | +| API文档编写 | 主要接口文档完善 | 梁晨旭 | P2 | 4h | 基础CRUD接口 | +| 设备管理接口开发 | 设备列表、详情、状态更新接口 | 杨捷 | P0 | 8h | 基础CRUD接口 | +| 水质检测接口开发 | 水质记录查询、报告生成接口 | 杨帅路 | P0 | 8h | 基础CRUD接口 | +| 订单管理接口开发 | 商品列表、下单、订单状态流转接口 | 梁晨旭 | P0 | 10h | 基础CRUD接口 | +| 工单管理接口开发 | 工单创建、状态更新、分配接口 | 杨捷 | P0 | 8h | 基础CRUD接口 | +| 消息通知接口开发 | 系统消息、公告查询接口 | 杨帅路 | P1 | 6h | 基础CRUD接口 | +| 前端业务模块联调 | 各业务模块与后端接口对接完成 | 杨默涵、杨振宇 | P0 | 16h | 业务接口开发 | +| 工作人员端基础功能 | 工单列表、配送任务基本展示 | 杨振宇 | P1 | 8h | 工单管理接口 | +| 单元测试编写 | 核心业务逻辑测试覆盖率≥70% | 梁晨旭 | P1 | 8h | 前端业务模块联调 | +| 接口测试执行 | 主要接口功能测试通过 | 杨振宇 | P0 | 12h | 前端业务模块联调 | +| 业务流程测试 | 核心业务流程完整执行 | 梁晨旭、杨振宇 | P0 | 16h | 前端业务模块联调 | +| 兼容性测试 | 支持主流微信版本 | 杨振宇 | P1 | 6h | 前端业务模块联调 | +| Bug修复与回归 | P0级bug100%修复,P1级bug≥90%修复 | 全员 | P0 | 12h | 测试执行 | +| 性能基础测试 | 接口响应时间≤2s,主要页面加载≤3s | 梁晨旭 | P2 | 4h | Bug修复 | +| 系统集成验证 | 完整业务流程演示成功 | 全员 | P0 | 4h | Bug修复 | +| 文档归档整理 | 技术文档、用户手册、部署文档完整 | 杨默涵 | P1 | 4h | 全阶段 | +| α版发布部署 | 系统部署成功,可正常访问 | 杨捷 | P0 | 2h | 系统集成验证 | +| 发布总结报告 | 项目总结、经验教训、后续计划明确 | 梁晨旭 | P1 | 2h | α版发布部署 | + +## 8. 人员配备 + +> 以下为阿尔法版本迭代的建议配置,可根据实际团队情况合并或拆分角色。 + +- **产品经理** + - 杨默涵 + +- **前端开发(小程序 / uni-app)** + - 杨默涵 + - 杨振宇 + +- **后端开发** + - 梁晨旭 + - 杨捷 + - 杨帅路 + +- **测试工程师** + - 梁晨旭 + - 杨振宇 + +- **平台管理员** + - 杨捷 + - 杨帅路 + diff --git a/doc/project/04-用户手册/数智水管家用户手册.doc b/doc/project/04-用户手册/数智水管家用户手册.doc new file mode 100644 index 0000000..68a9d1f Binary files /dev/null and b/doc/project/04-用户手册/数智水管家用户手册.doc differ diff --git a/doc/project/05-测试报告/数智水管家测试报告.docx b/doc/project/05-测试报告/数智水管家测试报告.docx new file mode 100644 index 0000000..7e564e0 Binary files /dev/null and b/doc/project/05-测试报告/数智水管家测试报告.docx differ diff --git a/src/数智水管家/数智水管家/App.vue b/src/数智水管家/数智水管家/App.vue new file mode 100644 index 0000000..74cc0e4 --- /dev/null +++ b/src/数智水管家/数智水管家/App.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/数智水管家/数智水管家/api/auth.js b/src/数智水管家/数智水管家/api/auth.js new file mode 100644 index 0000000..3524011 --- /dev/null +++ b/src/数智水管家/数智水管家/api/auth.js @@ -0,0 +1,16 @@ +/** + * 认证相关接口 + */ +import { post } from '../utils/request.js' + +export const login = (data) => post('/water/app/auth/login', data, { preventDuplicate: true }) +export const staffLogin = (data) => post('/water/staff/auth/login', data, { preventDuplicate: true }) +export const wechatLogin = (data) => post('/water/app/auth/wechat', data, { preventDuplicate: true }) +export const logout = () => post('/water/app/auth/logout') +export const refreshToken = () => post('/water/app/auth/refresh') +export const register = (data) => post('/water/app/auth/register', data, { preventDuplicate: true }) +export const sendCode = (phone) => post('/water/app/auth/sendCode', { phone }, { preventDuplicate: true }) + + + + diff --git a/src/数智水管家/数智水管家/api/device.js b/src/数智水管家/数智水管家/api/device.js new file mode 100644 index 0000000..a128348 --- /dev/null +++ b/src/数智水管家/数智水管家/api/device.js @@ -0,0 +1,23 @@ +/** + * 设备与滤芯接口 + */ +import { get, post, put, del } from '../utils/request.js' + +export const getDeviceList = (params = {}) => get('/water/app/device/list', params) +export const getDeviceDetail = (sn) => get(`/water/app/device/detail/${sn}`) +export const bindDevice = (data) => post('/water/app/device/bind', data, { preventDuplicate: true }) +export const unbindDevice = (deviceId) => del(`/water/app/device/unbind/${deviceId}`) +export const updateDevice = (data) => put('/water/app/device/update', data) +export const getDeviceStatus = (deviceId) => get(`/water/app/device/status/${deviceId}`) + +// 滤芯 +export const getFilterList = (deviceId) => get('/water/app/filter/list', { deviceId }) +export const getFilterDetail = (filterId) => get(`/water/app/filter/detail/${filterId}`) + +// 故障上报 +export const reportDeviceProblem = (data) => + post('/water/app/device/problem', data, { preventDuplicate: true }) + + + + diff --git a/src/数智水管家/数智水管家/api/index.js b/src/数智水管家/数智水管家/api/index.js new file mode 100644 index 0000000..b681b88 --- /dev/null +++ b/src/数智水管家/数智水管家/api/index.js @@ -0,0 +1,12 @@ +// API 统一出口 +export * from './auth.js' +export * from './user.js' +export * from './device.js' +export * from './order.js' +export * from './product.js' +export * from './quality.js' +export * from './message.js' +export * from './staff.js' + + + diff --git a/src/数智水管家/数智水管家/api/message.js b/src/数智水管家/数智水管家/api/message.js new file mode 100644 index 0000000..a968d04 --- /dev/null +++ b/src/数智水管家/数智水管家/api/message.js @@ -0,0 +1,24 @@ +/** + * 消息与公告接口 + */ +import { get, post, put } from '../utils/request.js' + +export const getMessageList = (params = {}) => get('/water/app/message/list', params) +export const getUnreadCount = () => get('/water/app/message/unreadCount') +export const markAsRead = (messageIds) => { + const ids = Array.isArray(messageIds) ? messageIds : [messageIds] + return put('/water/app/message/read', { messageIds: ids }) +} +export const markAllAsRead = () => put('/water/app/message/readAll') +export const deleteMessage = (messageIds) => { + const ids = Array.isArray(messageIds) ? messageIds : [messageIds] + return post('/water/app/message/delete', { messageIds: ids }) +} +export const getMessageDetail = (messageId) => get(`/water/app/message/detail/${messageId}`) + +export const getNoticeList = (params = {}) => get('/water/app/notice/list', params) +export const getNoticeDetail = (noticeId) => get(`/water/app/notice/detail/${noticeId}`) + + + + diff --git a/src/数智水管家/数智水管家/api/order.js b/src/数智水管家/数智水管家/api/order.js new file mode 100644 index 0000000..55a1010 --- /dev/null +++ b/src/数智水管家/数智水管家/api/order.js @@ -0,0 +1,31 @@ +/** + * 订单相关接口 + */ +import { get, post, put } from '../utils/request.js' + +export const getOrderList = (params = {}) => get('/water/app/order/list', params) +export const getOrderDetail = (orderId) => get(`/water/app/order/detail/${orderId}`) + +export const createOrder = (data) => + post('/water/app/order/create', data, { preventDuplicate: true }) + +export const payOrder = (data) => + post('/water/app/order/pay', data, { preventDuplicate: true }) + +export const cancelOrder = (orderId, reason) => + post('/water/app/order/cancel', { orderId, reason }, { preventDuplicate: true }) + +export const confirmOrder = (orderId) => + post('/water/app/order/confirm', { orderId }, { preventDuplicate: true }) + +export const getOrderProgress = (orderId) => get(`/water/app/order/progress/${orderId}`) + +export const evaluateOrder = (data) => + post('/water/app/order/evaluate', data, { preventDuplicate: true }) + +export const refundOrder = (data) => + post('/water/app/order/refund', data, { preventDuplicate: true }) + + + + diff --git a/src/数智水管家/数智水管家/api/product.js b/src/数智水管家/数智水管家/api/product.js new file mode 100644 index 0000000..de9e9d2 --- /dev/null +++ b/src/数智水管家/数智水管家/api/product.js @@ -0,0 +1,14 @@ +/** + * 商品相关接口 + */ +import { get } from '../utils/request.js' + +export const getProductList = (params = {}) => get('/water/app/product/list', params) +export const getProductDetail = (productId) => get(`/water/app/product/detail/${productId}`) +export const getProductCategories = () => get('/water/app/product/categories') +export const searchProducts = (params) => get('/water/app/product/search', params) +export const getHotProducts = (limit = 10) => get('/water/app/product/hot', { limit }) + + + + diff --git a/src/数智水管家/数智水管家/api/quality.js b/src/数智水管家/数智水管家/api/quality.js new file mode 100644 index 0000000..1e4c327 --- /dev/null +++ b/src/数智水管家/数智水管家/api/quality.js @@ -0,0 +1,16 @@ +/** + * 水质检测相关接口 + */ +import { get, post } from '../utils/request.js' + +export const getQualityList = (params = {}) => get('/water/app/quality/list', params) +export const getQualityDetail = (qualityId) => get(`/water/app/quality/detail/${qualityId}`) +export const applyQualityTest = (data) => + post('/water/app/quality/apply', data, { preventDuplicate: true }) +export const getLatestQuality = (deviceId) => get(`/water/app/quality/latest/${deviceId}`) +export const getQualityReport = (qualityId) => get(`/water/app/quality/report/${qualityId}`) +export const getQualityAlerts = (params = {}) => get('/water/app/quality/alerts', params) + + + + diff --git a/src/数智水管家/数智水管家/api/staff.js b/src/数智水管家/数智水管家/api/staff.js new file mode 100644 index 0000000..b8f6280 --- /dev/null +++ b/src/数智水管家/数智水管家/api/staff.js @@ -0,0 +1,35 @@ +/** + * 员工端接口 + */ +import { get, post } from '../utils/request.js' + +export const login = (data) => post('/water/staff/auth/login', data, { preventDuplicate: true }) +export const getStaffInfo = (staffId) => + get(staffId ? `/water/员工/${staffId}` : '/water/staff/info') +export const updateStaffInfo = (data) => post('/water/staff/info', data) + +// 工单 +export const getWorkorderList = (params = {}) => get('/water/staff/workorder/list', params) +export const getWorkorderDetail = (orderId) => get(`/water/staff/workorder/detail/${orderId}`) +export const acceptWorkorder = (orderId) => + post('/water/staff/workorder/accept', { orderId }, { preventDuplicate: true }) +export const startWorkorder = (data) => + post('/water/staff/workorder/start', data, { preventDuplicate: true }) +export const completeWorkorder = (data) => + post('/water/staff/workorder/complete', data, { preventDuplicate: true }) + +// 配送 +export const getDeliveryList = (params = {}) => get('/water/staff/delivery/list', params) +export const getDeliveryDetail = (orderId) => get(`/water/staff/delivery/detail/${orderId}`) +export const startDelivery = (data) => + post('/water/staff/delivery/start', data, { preventDuplicate: true }) +export const completeDelivery = (data) => + post('/water/staff/delivery/complete', data, { preventDuplicate: true }) + +// 统计与评价 +export const getStatistics = () => get('/water/staff/statistics') +export const getEvaluationList = (params = {}) => get('/water/staff/evaluation/list', params) + + + + diff --git a/src/数智水管家/数智水管家/api/user.js b/src/数智水管家/数智水管家/api/user.js new file mode 100644 index 0000000..04e524f --- /dev/null +++ b/src/数智水管家/数智水管家/api/user.js @@ -0,0 +1,26 @@ +/** + * 用户相关接口 + */ +import { get, post, put } from '../utils/request.js' + +export const getUserInfo = (userId) => + get(userId ? `/water/用户/${userId}` : '/water/app/user/info') + +export const updateUserInfo = (data) => put('/water/app/user/info', data) + +export const changePassword = (data) => + post('/water/app/user/changePassword', data, { preventDuplicate: true }) + +export const bindPhone = (data) => + post('/water/app/user/bindPhone', data, { preventDuplicate: true }) + +export const getBalance = () => get('/water/app/user/balance') + +export const recharge = (data) => + post('/water/app/user/recharge', data, { preventDuplicate: true }) + +export const getUserStats = () => get('/water/app/user/stats') + + + + diff --git a/src/数智水管家/数智水管家/database/ER关系图.md b/src/数智水管家/数智水管家/database/ER关系图.md new file mode 100644 index 0000000..57b7d6b --- /dev/null +++ b/src/数智水管家/数智水管家/database/ER关系图.md @@ -0,0 +1,448 @@ +# 数智水管家数据库 ER 关系图 + +## 📊 完整 ER 图 + +```mermaid +erDiagram + %% 用户相关 + water_user ||--o{ water_device : "拥有" + water_user ||--o{ water_service_order : "创建" + water_user ||--o{ water_evaluation : "评价" + water_user ||--o{ water_message : "接收" + water_user ||--o{ water_quality : "关联" + + %% 员工相关 + water_staff ||--o{ water_service_order : "处理" + water_staff ||--o{ water_evaluation : "被评价" + water_staff ||--o{ water_message : "接收" + + %% 设备相关 + water_device ||--o{ water_filter : "包含" + water_device ||--o{ water_quality : "检测" + + %% 订单相关 + water_service_order ||--o{ water_order_product : "包含" + water_service_order ||--o| water_evaluation : "评价" + water_service_order ||--o| water_quality : "关联" + + %% 商品相关 + water_product ||--o{ water_order_product : "被订购" + + %% 用户表 + water_user { + bigint user_id PK "用户ID" + varchar phone UK "手机号" + varchar password "密码" + varchar nick_name "昵称" + varchar avatar "头像" + char gender "性别" + varchar openid UK "微信openid" + decimal balance "余额" + int total_orders "订单总数" + char status "状态" + } + + %% 员工表 + water_staff { + bigint staff_id PK "员工ID" + bigint user_id FK "关联sys_user" + varchar employee_no UK "工号" + varchar staff_name "姓名" + varchar phone UK "手机号" + bigint dept_id FK "部门ID" + varchar position "职位" + int total_orders "工单总数" + int completed_orders "完成数" + decimal avg_rating "平均评分" + char status "状态" + } + + %% 设备表 + water_device { + bigint device_id PK "设备ID" + bigint user_id FK "用户ID" + varchar sn UK "设备编号" + varchar device_name "设备名称" + varchar device_type "设备类型" + char status "状态" + varchar install_address "安装地址" + decimal location_lat "纬度" + decimal location_lng "经度" + datetime bind_time "绑定时间" + } + + %% 滤芯表 + water_filter { + bigint filter_id PK "滤芯ID" + bigint device_id FK "设备ID" + varchar filter_name "滤芯名称" + varchar model "型号" + datetime install_time "安装时间" + int total_days "总天数" + int used_days "已用天数" + int life_percentage "剩余百分比" + date next_replace_time "预计更换时间" + char status "状态" + } + + %% 水质检测表 + water_quality { + bigint quality_id PK "检测ID" + bigint device_id FK "设备ID" + bigint user_id FK "用户ID" + bigint order_id FK "订单ID" + datetime test_time "检测时间" + varchar quality_level "水质等级" + decimal ph_value "pH值" + decimal turbidity "浊度" + decimal residual_chlorine "余氯" + decimal total_hardness "总硬度" + decimal tds "TDS" + char status "状态" + } + + %% 商品表 + water_product { + bigint product_id PK "商品ID" + varchar product_name "商品名称" + varchar product_desc "商品描述" + varchar category "商品分类" + decimal price "价格" + int stock "库存" + varchar icon "图标" + char status "状态" + } + + %% 服务订单表(核心) + water_service_order { + bigint order_id PK "订单ID" + varchar order_no UK "订单号" + bigint user_id FK "用户ID" + bigint staff_id FK "员工ID" + varchar service_type "服务类型" + varchar order_source "订单来源" + varchar order_status "订单状态" + varchar payment_status "支付状态" + decimal amount "订单金额" + decimal actual_amount "实付金额" + varchar payment_method "支付方式" + varchar contact_name "联系人" + varchar contact_phone "联系电话" + varchar service_address "服务地址" + varchar priority "优先级" + datetime submit_time "提交时间" + datetime accept_time "接单时间" + datetime complete_time "完成时间" + } + + %% 订单商品关联表 + water_order_product { + bigint id PK "主键ID" + bigint order_id FK "订单ID" + bigint product_id FK "商品ID" + varchar product_name "商品名称" + decimal product_price "商品单价" + int quantity "数量" + decimal total_price "小计" + } + + %% 订单评价表 + water_evaluation { + bigint evaluation_id PK "评价ID" + bigint order_id FK UK "订单ID" + bigint user_id FK "用户ID" + bigint staff_id FK "员工ID" + decimal rating "综合评分" + decimal service_rating "服务态度" + decimal quality_rating "服务质量" + decimal speed_rating "服务速度" + text content "评价内容" + char is_anonymous "是否匿名" + } + + %% 系统消息表 + water_message { + bigint message_id PK "消息ID" + bigint user_id FK "用户ID" + bigint staff_id FK "员工ID" + varchar message_type "消息类型" + varchar title "标题" + text content "内容" + bigint related_id "关联ID" + char is_read "是否已读" + datetime send_time "发送时间" + } + + %% 通知公告表 + water_notice { + bigint notice_id PK "公告ID" + varchar notice_title "标题" + text notice_content "内容" + varchar notice_type "类型" + varchar target_type "目标对象" + char status "状态" + datetime publish_time "发布时间" + } + + %% 系统配置表 + water_config { + bigint config_id PK "配置ID" + varchar config_key UK "配置键" + varchar config_value "配置值" + varchar config_type "配置类型" + varchar config_desc "配置描述" + } +``` + +## 🔗 核心关联关系 + +### 1. 用户中心 + +``` +用户 (water_user) +├── 1:N → 设备 (water_device) +│ └── 1:N → 滤芯 (water_filter) +│ └── 1:N → 水质检测 (water_quality) +├── 1:N → 订单 (water_service_order) +│ └── 1:N → 订单商品 (water_order_product) +│ └── 1:1 → 评价 (water_evaluation) +└── 1:N → 消息 (water_message) +``` + +### 2. 员工中心 + +``` +员工 (water_staff) +├── 1:N → 工单 (water_service_order) +│ └── 1:1 → 评价 (water_evaluation) +└── 1:N → 消息 (water_message) +``` + +### 3. 订单中心 + +``` +订单 (water_service_order) +├── N:1 → 用户 (water_user) +├── N:1 → 员工 (water_staff) +├── 1:N → 订单商品 (water_order_product) +│ └── N:1 → 商品 (water_product) +├── 1:1 → 评价 (water_evaluation) +└── 1:1 → 水质检测 (water_quality) [可选] +``` + +## 📋 业务流程图 + +### 订单流程 + +```mermaid +graph LR + A[用户下单] --> B[创建订单] + B --> C{需要支付?} + C -->|是| D[待支付] + C -->|否| E[已支付] + D --> F[用户支付] + F --> E + E --> G[员工接单] + G --> H[处理中] + H --> I[完成] + I --> J[用户评价] + + style A fill:#e1f5ff + style B fill:#fff4e1 + style E fill:#d4edda + style I fill:#d1ecf1 +``` + +### 设备绑定流程 + +```mermaid +graph TD + A[用户扫描设备二维码] --> B[获取设备SN] + B --> C{设备是否存在?} + C -->|否| D[提示设备不存在] + C -->|是| E{设备是否已绑定?} + E -->|是| F[提示已被绑定] + E -->|否| G[绑定设备] + G --> H[创建滤芯记录] + H --> I[绑定成功] + + style A fill:#e1f5ff + style G fill:#d4edda + style I fill:#d1ecf1 +``` + +### 水质检测流程 + +```mermaid +graph LR + A[用户申请检测] --> B[创建检测订单] + B --> C[员工接单] + C --> D[上门检测] + D --> E[录入检测数据] + E --> F[生成检测报告] + F --> G[推送消息通知] + G --> H[用户查看报告] + + style A fill:#e1f5ff + style F fill:#d4edda + style H fill:#d1ecf1 +``` + +## 🎯 索引关系图 + +### 主要索引 + +``` +water_user +├── PRIMARY KEY (user_id) +├── UNIQUE KEY (phone) +└── UNIQUE KEY (openid) + +water_device +├── PRIMARY KEY (device_id) +├── UNIQUE KEY (sn) +├── INDEX (user_id) +└── INDEX (status) + +water_service_order +├── PRIMARY KEY (order_id) +├── UNIQUE KEY (order_no) +├── INDEX (user_id) +├── INDEX (staff_id) +├── INDEX (order_status) +└── COMPOSITE INDEX (staff_id, order_status) + +water_filter +├── PRIMARY KEY (filter_id) +├── INDEX (device_id) +└── INDEX (life_percentage) +``` + +## 🔄 数据流向图 + +```mermaid +graph TD + subgraph "用户端" + U1[用户注册/登录] + U2[绑定设备] + U3[查看设备状态] + U4[下单购买] + U5[评价服务] + end + + subgraph "核心数据层" + D1[(water_user)] + D2[(water_device)] + D3[(water_filter)] + D4[(water_service_order)] + D5[(water_evaluation)] + D6[(water_quality)] + end + + subgraph "员工端" + S1[员工登录] + S2[查看工单] + S3[接单处理] + S4[完成服务] + S5[查看绩效] + end + + U1 --> D1 + U2 --> D2 + U3 --> D3 + U4 --> D4 + U5 --> D5 + + D1 --> S2 + D4 --> S2 + S3 --> D4 + S4 --> D6 + D5 --> S5 + + style D1 fill:#ffd4d4 + style D2 fill:#ffe4d4 + style D3 fill:#fff4d4 + style D4 fill:#d4f4ff + style D5 fill:#e4d4ff + style D6 fill:#d4ffe4 +``` + +## 📊 数据统计关系 + +### 视图:员工绩效 + +```sql +v_staff_performance +├── 数据来源 +│ ├── water_staff (基础信息) +│ ├── water_service_order (订单统计) +│ └── water_evaluation (评价统计) +└── 统计指标 + ├── 总订单数 (total_orders) + ├── 完成订单数 (completed_orders) + ├── 完成率 (completion_rate) + ├── 平均评分 (avg_rating) + └── 平均时长 (avg_duration) +``` + +### 视图:订单统计 + +```sql +v_order_statistics +├── 数据来源 +│ └── water_service_order +└── 统计维度 + ├── 按日期 (order_date) + ├── 按服务类型 (service_type) + ├── 按订单状态 (order_status) + └── 按订单来源 (order_source) +``` + +## 💡 设计说明 + +### 1. 为什么使用统一订单表? + +**优点**: +- ✅ 减少数据冗余 +- ✅ 统一状态管理 +- ✅ 简化业务逻辑 +- ✅ 便于统计分析 + +**实现方式**: +- 通过 `order_source` 区分来源(用户/后台) +- 通过 `service_type` 区分服务类型 +- 通过 `order_status` 管理流程状态 + +### 2. 如何保证数据一致性? + +**策略**: +- ✅ 使用外键约束(可选) +- ✅ 使用唯一索引防止重复 +- ✅ 使用事务保证原子性 +- ✅ 使用触发器自动更新冗余字段(可选) + +### 3. 如何优化查询性能? + +**措施**: +- ✅ 合理设计索引(单列索引 + 联合索引) +- ✅ 使用 Redis 缓存热点数据 +- ✅ 使用视图简化复杂查询 +- ✅ 使用分页查询减少数据量 +- ✅ 使用批量操作减少IO + +--- + +**文档版本**:v2.0 +**更新日期**:2025-11-13 +**工具推荐**:dbdiagram.io, draw.io, Navicat + +## 🛠️ 在线查看 ER 图 + +推荐使用以下工具在线查看和编辑 ER 图: + +1. **Mermaid Live Editor**: https://mermaid.live +2. **dbdiagram.io**: https://dbdiagram.io +3. **draw.io**: https://app.diagrams.net + +将上述 Mermaid 代码复制到 Mermaid Live Editor 即可查看交互式 ER 图。 + diff --git a/src/数智水管家/数智水管家/database/数据库设计说明_v2.0.md b/src/数智水管家/数智水管家/database/数据库设计说明_v2.0.md new file mode 100644 index 0000000..647482a --- /dev/null +++ b/src/数智水管家/数智水管家/database/数据库设计说明_v2.0.md @@ -0,0 +1,1112 @@ +# 数智水管家数据库设计说明 v2.0 + +> 基于小程序实际功能的精简数据库设计方案 + +## 📊 一、设计概览 + +### 1.1 设计原则 + +- ✅ **功能完整**:覆盖用户端和员工端所有核心功能 +- ✅ **结构精简**:仅 **12 张核心表**,易于维护 +- ✅ **高度复用**:订单、工单、配送统一管理 +- ✅ **易于扩展**:预留扩展字段,支持业务增长 +- ✅ **性能优化**:合理索引设计,支持高并发查询 + +### 1.2 数据库统计 + +| 项目 | 数量 | 说明 | +|------|------|------| +| 核心业务表 | 12 张 | 覆盖全部业务功能 | +| 视图 | 2 个 | 员工绩效、订单统计 | +| 索引 | 30+ 个 | 优化查询性能 | +| 字段总数 | ~180 个 | 平均每表 15 个字段 | + +### 1.3 功能覆盖 + +**用户端功能**: +- 设备管理(绑定、监控、预警) +- 滤芯管理(寿命监控、更换提醒) +- 水质检测(检测记录、报告查看、预警) +- 商品订购(净水器、配件、服务) +- 订单管理(下单、支付、评价) +- 消息通知(系统消息、公告) +- 在线客服 + +**员工端功能**: +- 工单管理(接单、处理、完成) +- 配送任务(任务列表、配送详情) +- 工作统计(绩效查看) +- 个人中心 + +--- + +## 📋 二、核心表清单 + +| 序号 | 表名 | 说明 | 记录数量级 | +|------|------|------|-----------| +| 1 | `water_user` | 普通用户表 | 10万+ | +| 2 | `water_staff` | 员工表 | 100+ | +| 3 | `water_device` | 净水器设备表 | 10万+ | +| 4 | `water_filter` | 滤芯表 | 40万+ | +| 5 | `water_quality` | 水质检测记录表 | 100万+ | +| 6 | `water_product` | 商品表 | 100+ | +| 7 | `water_service_order` | 服务订单表(统一) | 100万+ | +| 8 | `water_order_product` | 订单商品关联表 | 200万+ | +| 9 | `water_evaluation` | 订单评价表 | 50万+ | +| 10 | `water_message` | 系统消息表 | 100万+ | +| 11 | `water_notice` | 通知公告表 | 100+ | +| 12 | `water_config` | 系统配置表 | 50+ | + +--- + +## 🗂️ 三、表结构详细设计 + +### 3.1 water_user(用户表) + +> 存储普通用户的基本信息,支持手机号和微信登录。 + +```sql +CREATE TABLE `water_user` ( + `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `phone` VARCHAR(11) DEFAULT NULL COMMENT '手机号', + `password` VARCHAR(128) DEFAULT NULL COMMENT '密码(BCrypt加密)', + `nick_name` VARCHAR(50) DEFAULT NULL COMMENT '昵称', + `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', + `gender` CHAR(1) DEFAULT '0' COMMENT '性别(0未知 1男 2女)', + `openid` VARCHAR(128) DEFAULT NULL COMMENT '微信openid', + `unionid` VARCHAR(128) DEFAULT NULL COMMENT '微信unionid', + `balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '账户余额', + `total_orders` INT(11) DEFAULT 0 COMMENT '订单总数(冗余)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`user_id`), + UNIQUE KEY `uk_phone` (`phone`), + UNIQUE KEY `uk_openid` (`openid`), + KEY `idx_status` (`status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; +``` + +**字段说明**: +- `phone`:支持手机号登录,唯一索引 +- `openid/unionid`:支持微信登录 +- `balance`:账户余额,支持余额支付 +- `total_orders`:冗余字段,减少订单表统计查询 + +--- + +### 3.2 water_staff(员工表) + +> 存储工作人员信息,与 RuoYi 的 sys_user 关联。 + +```sql +CREATE TABLE `water_staff` ( + `staff_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '员工ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '关联sys_user的user_id', + `employee_no` VARCHAR(20) NOT NULL COMMENT '工号', + `staff_name` VARCHAR(50) NOT NULL COMMENT '姓名', + `phone` VARCHAR(11) NOT NULL COMMENT '手机号', + `dept_id` BIGINT(20) DEFAULT NULL COMMENT '部门ID(关联sys_dept)', + `position` VARCHAR(50) DEFAULT NULL COMMENT '职位', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `total_orders` INT(11) DEFAULT 0 COMMENT '工单总数(冗余)', + `completed_orders` INT(11) DEFAULT 0 COMMENT '完成工单数(冗余)', + `avg_rating` DECIMAL(3,2) DEFAULT 5.00 COMMENT '平均评分(冗余)', + `avg_duration` INT(11) DEFAULT 0 COMMENT '平均服务时长-分钟(冗余)', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`staff_id`), + UNIQUE KEY `uk_employee_no` (`employee_no`), + UNIQUE KEY `uk_phone` (`phone`), + KEY `idx_user_id` (`user_id`), + KEY `idx_dept_id` (`dept_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工表'; +``` + +**字段说明**: +- `user_id`:关联 RuoYi 的 sys_user,实现统一认证 +- `dept_id`:关联 RuoYi 的 sys_dept,实现数据权限 +- `avg_rating/avg_duration`:冗余字段,定时任务更新 + +--- + +### 3.3 water_device(设备表) + +> 存储净水器设备信息,支持状态监控和地理位置。 + +```sql +CREATE TABLE `water_device` ( + `device_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `sn` VARCHAR(50) NOT NULL COMMENT '设备编号(唯一)', + `device_name` VARCHAR(100) DEFAULT NULL COMMENT '设备名称', + `device_type` VARCHAR(50) DEFAULT '智能净水器' COMMENT '设备类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '设备型号', + `status` CHAR(1) DEFAULT '1' COMMENT '状态(0离线 1在线 2故障)', + `install_address` VARCHAR(255) DEFAULT NULL COMMENT '安装地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `bind_time` DATETIME DEFAULT NULL COMMENT '绑定时间', + `last_online_time` DATETIME DEFAULT NULL COMMENT '最后在线时间', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`device_id`), + UNIQUE KEY `uk_sn` (`sn`), + KEY `idx_user_id` (`user_id`), + KEY `idx_status` (`status`), + KEY `idx_bind_time` (`bind_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备表'; +``` + +**字段说明**: +- `sn`:设备序列号,全局唯一 +- `status`:0离线/1在线/2故障,支持实时监控 +- `location_lat/lng`:经纬度,用于配送导航 + +--- + +### 3.4 water_filter(滤芯表) + +> 存储滤芯信息,支持寿命监控和更换提醒。 + +```sql +CREATE TABLE `water_filter` ( + `filter_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '滤芯ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `filter_name` VARCHAR(50) NOT NULL COMMENT '滤芯名称(如:PP棉滤芯)', + `filter_type` VARCHAR(50) DEFAULT NULL COMMENT '滤芯类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '滤芯型号', + `install_time` DATETIME DEFAULT NULL COMMENT '安装时间', + `total_days` INT(11) DEFAULT 180 COMMENT '总使用天数(默认180天)', + `used_days` INT(11) DEFAULT 0 COMMENT '已使用天数', + `life_percentage` INT(11) DEFAULT 100 COMMENT '剩余寿命百分比', + `next_replace_time` DATE DEFAULT NULL COMMENT '预计更换时间', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1需更换)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`filter_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_status` (`status`), + KEY `idx_life_percentage` (`life_percentage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='滤芯表'; +``` + +**字段说明**: +- `life_percentage`:剩余寿命百分比,实时计算 +- `next_replace_time`:预计更换时间,提前预警 +- `status`:0正常/1需更换 + +**寿命计算公式**: +```sql +-- 定时任务每天更新 +UPDATE water_filter +SET used_days = DATEDIFF(NOW(), install_time), + life_percentage = GREATEST(0, ROUND((total_days - used_days) * 100.0 / total_days, 0)), + status = CASE WHEN life_percentage <= 10 THEN '1' ELSE '0' END +WHERE del_flag = '0'; +``` + +--- + +### 3.5 water_quality(水质检测记录表) + +> 存储水质检测记录,支持多指标检测和预警。 + +```sql +CREATE TABLE `water_quality` ( + `quality_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '检测ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `order_id` BIGINT(20) DEFAULT NULL COMMENT '关联订单ID(如果是服务订单)', + `test_time` DATETIME NOT NULL COMMENT '检测时间', + `test_address` VARCHAR(255) DEFAULT NULL COMMENT '检测地址', + `quality_level` VARCHAR(20) DEFAULT NULL COMMENT '水质等级(优质/良好/一般/较差)', + `quality_desc` VARCHAR(500) DEFAULT NULL COMMENT '水质描述', + + -- 检测指标 + `ph_value` DECIMAL(4,2) DEFAULT NULL COMMENT 'pH值(6.5-8.5)', + `turbidity` DECIMAL(6,2) DEFAULT NULL COMMENT '浊度 NTU(≤1)', + `residual_chlorine` DECIMAL(6,2) DEFAULT NULL COMMENT '余氯 mg/L(0.05-4)', + `total_hardness` DECIMAL(8,2) DEFAULT NULL COMMENT '总硬度 mg/L(≤450)', + `tds` DECIMAL(8,2) DEFAULT NULL COMMENT 'TDS溶解性固体 mg/L(≤1000)', + `cod` DECIMAL(8,2) DEFAULT NULL COMMENT 'COD化学需氧量 mg/L', + `ammonia_nitrogen` DECIMAL(6,2) DEFAULT NULL COMMENT '氨氮 mg/L', + + `report_url` VARCHAR(255) DEFAULT NULL COMMENT '检测报告URL', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0检测中 1已完成)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`quality_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_test_time` (`test_time`), + KEY `idx_quality_level` (`quality_level`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水质检测记录表'; +``` + +**字段说明**: +- 支持多种水质指标检测 +- `quality_level`:根据指标自动计算水质等级 +- `report_url`:检测报告文件地址 + +**水质等级计算规则**: +``` +优质:所有指标在标准范围内 +良好:个别指标接近上限/下限 +一般:部分指标超标但影响不大 +较差:关键指标超标,影响饮用安全 +``` + +--- + +### 3.6 water_product(商品表) + +> 存储可订购的商品信息(净水器、配件、服务等)。 + +```sql +CREATE TABLE `water_product` ( + `product_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称', + `product_desc` VARCHAR(500) DEFAULT NULL COMMENT '商品描述', + `category` VARCHAR(50) DEFAULT NULL COMMENT '商品分类(purifier净水器/meter水表/parts配件/service服务)', + `price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '商品价格', + `stock` INT(11) DEFAULT 0 COMMENT '库存数量', + `image_url` VARCHAR(255) DEFAULT NULL COMMENT '商品图片URL', + `icon` VARCHAR(50) DEFAULT NULL COMMENT '图标Emoji', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0上架 1下架)', + `sort_order` INT(11) DEFAULT 0 COMMENT '排序', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`product_id`), + KEY `idx_category` (`category`), + KEY `idx_status` (`status`), + KEY `idx_sort_order` (`sort_order`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; +``` + +**字段说明**: +- `category`:商品分类,支持多种类型 +- `icon`:Emoji 图标,小程序前端显示 +- `sort_order`:排序字段,控制显示顺序 + +--- + +### 3.7 water_service_order(服务订单表)⭐核心 + +> **统一管理**用户订单、工单、配送任务的核心表。 + +```sql +CREATE TABLE `water_service_order` ( + `order_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `order_no` VARCHAR(50) NOT NULL COMMENT '订单号(唯一)', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '负责员工ID', + + -- 订单类型与来源 + `service_type` VARCHAR(50) NOT NULL COMMENT '服务类型(设备安装/滤芯更换/维修/订购/水质检测)', + `order_source` VARCHAR(20) DEFAULT 'user' COMMENT '订单来源(user用户下单/admin后台派单)', + + -- 订单状态 + `order_status` VARCHAR(20) DEFAULT 'pending' COMMENT '订单状态(pending待支付/paid已支付/accepted已接单/processing处理中/completed已完成/cancelled已取消)', + `payment_status` VARCHAR(20) DEFAULT 'unpaid' COMMENT '支付状态(unpaid未支付/paid已支付/refunded已退款)', + + -- 金额信息 + `amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '订单金额', + `actual_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '实付金额', + `discount_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '优惠金额', + `payment_method` VARCHAR(20) DEFAULT NULL COMMENT '支付方式(wechat微信/balance余额/alipay支付宝)', + + -- 服务信息 + `contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人', + `contact_phone` VARCHAR(11) DEFAULT NULL COMMENT '联系电话', + `service_address` VARCHAR(255) DEFAULT NULL COMMENT '服务地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `description` TEXT DEFAULT NULL COMMENT '服务描述/问题描述', + `priority` VARCHAR(20) DEFAULT 'normal' COMMENT '优先级(normal普通/high紧急)', + + -- 配送信息 + `delivery_distance` DECIMAL(10,2) DEFAULT NULL COMMENT '配送距离(公里)', + `estimated_duration` INT(11) DEFAULT NULL COMMENT '预计时长(分钟)', + `actual_duration` INT(11) DEFAULT NULL COMMENT '实际时长(分钟)', + + -- 时间轴 + `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间', + `payment_time` DATETIME DEFAULT NULL COMMENT '支付时间', + `accept_time` DATETIME DEFAULT NULL COMMENT '接单时间', + `start_time` DATETIME DEFAULT NULL COMMENT '开始配送时间', + `complete_time` DATETIME DEFAULT NULL COMMENT '完成时间', + `cancel_time` DATETIME DEFAULT NULL COMMENT '取消时间', + + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`order_id`), + UNIQUE KEY `uk_order_no` (`order_no`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_order_status` (`order_status`), + KEY `idx_service_type` (`service_type`), + KEY `idx_submit_time` (`submit_time`), + KEY `idx_staff_status` (`staff_id`, `order_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务订单表'; +``` + +**设计亮点**: +1. **统一管理**:用户订单、员工工单、配送任务合并为一张表 +2. **灵活状态**:通过 `order_source` 区分来源,通过 `order_status` 管理流程 +3. **完整时间轴**:记录订单全生命周期的时间节点 + +**状态流转**: +``` +用户下单流程: +pending(待支付) → paid(已支付) → accepted(已接单) → processing(处理中) → completed(已完成) + ↓ + cancelled(已取消) + +后台派单流程: +paid(已派单) → accepted(已接单) → processing(处理中) → completed(已完成) +``` + +--- + +### 3.8 water_order_product(订单商品关联表) + +> 存储订单与商品的关联关系,支持一订单多商品。 + +```sql +CREATE TABLE `water_order_product` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `product_id` BIGINT(20) NOT NULL COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称(冗余)', + `product_price` DECIMAL(10,2) NOT NULL COMMENT '商品单价(冗余)', + `quantity` INT(11) DEFAULT 1 COMMENT '购买数量', + `total_price` DECIMAL(10,2) NOT NULL COMMENT '小计金额', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_product_id` (`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品关联表'; +``` + +**字段说明**: +- 冗余 `product_name` 和 `product_price`,防止商品信息修改后订单数据不一致 +- `total_price` = `product_price` × `quantity` + +--- + +### 3.9 water_evaluation(订单评价表) + +> 存储用户对订单的评价,支持多维度评分。 + +```sql +CREATE TABLE `water_evaluation` ( + `evaluation_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '评价ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID', + `rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '综合评分(1-5星)', + `service_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务态度评分', + `quality_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务质量评分', + `speed_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务速度评分', + `content` TEXT DEFAULT NULL COMMENT '评价内容', + `images` VARCHAR(1000) DEFAULT NULL COMMENT '评价图片(JSON数组)', + `is_anonymous` CHAR(1) DEFAULT '0' COMMENT '是否匿名(0否 1是)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`evaluation_id`), + UNIQUE KEY `uk_order_id` (`order_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_rating` (`rating`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单评价表'; +``` + +**字段说明**: +- 支持多维度评分(服务态度、质量、速度) +- `rating` = (service_rating + quality_rating + speed_rating) / 3 +- 支持匿名评价 + +--- + +### 3.10 water_message(系统消息表) + +> 存储系统消息,支持用户端和员工端消息推送。 + +```sql +CREATE TABLE `water_message` ( + `message_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '消息ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '用户ID(用户消息)', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID(员工消息)', + `message_type` VARCHAR(50) DEFAULT NULL COMMENT '消息类型(order订单/device设备/system系统/service服务)', + `title` VARCHAR(100) NOT NULL COMMENT '消息标题', + `content` TEXT NOT NULL COMMENT '消息内容', + `related_id` BIGINT(20) DEFAULT NULL COMMENT '关联ID(如订单ID、设备ID)', + `is_read` CHAR(1) DEFAULT '0' COMMENT '是否已读(0未读 1已读)', + `send_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '发送时间', + `read_time` DATETIME DEFAULT NULL COMMENT '阅读时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`message_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_message_type` (`message_type`), + KEY `idx_is_read` (`is_read`), + KEY `idx_send_time` (`send_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统消息表'; +``` + +**字段说明**: +- `user_id` 和 `staff_id` 二选一,区分用户消息和员工消息 +- `message_type`:消息分类,便于筛选 +- `related_id`:关联业务数据,支持消息跳转 + +--- + +### 3.11 water_notice(通知公告表) + +> 存储系统通知公告,面向所有用户广播。 + +```sql +CREATE TABLE `water_notice` ( + `notice_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `notice_title` VARCHAR(100) NOT NULL COMMENT '公告标题', + `notice_content` TEXT NOT NULL COMMENT '公告内容', + `notice_type` VARCHAR(20) DEFAULT 'info' COMMENT '公告类型(info通知/warning警告/urgent紧急)', + `target_type` VARCHAR(20) DEFAULT 'all' COMMENT '目标对象(all全部/user用户/staff员工)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0发布 1草稿 2下架)', + `publish_time` DATETIME DEFAULT NULL COMMENT '发布时间', + `expire_time` DATETIME DEFAULT NULL COMMENT '过期时间', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`notice_id`), + KEY `idx_status` (`status`), + KEY `idx_target_type` (`target_type`), + KEY `idx_publish_time` (`publish_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通知公告表'; +``` + +**字段说明**: +- `target_type`:支持定向推送(全部/用户/员工) +- `expire_time`:过期自动下架 + +--- + +### 3.12 water_config(系统配置表) + +> 存储系统配置参数,支持动态配置。 + +```sql +CREATE TABLE `water_config` ( + `config_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '配置ID', + `config_key` VARCHAR(100) NOT NULL COMMENT '配置键', + `config_value` VARCHAR(500) NOT NULL COMMENT '配置值', + `config_type` VARCHAR(50) DEFAULT 'string' COMMENT '配置类型(string/number/boolean/json)', + `config_desc` VARCHAR(500) DEFAULT NULL COMMENT '配置描述', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`), + UNIQUE KEY `uk_config_key` (`config_key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表'; +``` + +**常用配置项**: +```sql +-- 订单自动完成时间(小时) +INSERT INTO water_config VALUES (1, 'order.auto_complete_hours', '24', 'number', '订单自动完成时间'); + +-- 滤芯预警阈值(%) +INSERT INTO water_config VALUES (2, 'filter.warning_threshold', '30', 'number', '滤芯寿命预警阈值'); + +-- 水质检测价格 +INSERT INTO water_config VALUES (3, 'service.quality_test_price', '99.00', 'number', '水质检测服务价格'); + +-- 配送费起步价 +INSERT INTO water_config VALUES (4, 'delivery.base_fee', '5.00', 'number', '配送费起步价'); +``` + +--- + +## 📊 四、视图设计 + +### 4.1 v_staff_performance(员工绩效视图) + +> 实时统计员工绩效数据,替代统计表。 + +```sql +CREATE OR REPLACE VIEW `v_staff_performance` AS +SELECT + s.staff_id, + s.employee_no, + s.staff_name, + s.phone, + s.dept_id, + s.position, + + -- 订单统计 + COUNT(o.order_id) AS total_orders, + SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) AS completed_orders, + SUM(CASE WHEN o.order_status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_orders, + ROUND(SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(o.order_id), 0), 2) AS completion_rate, + + -- 评价统计 + IFNULL(AVG(e.rating), 5.00) AS avg_rating, + COUNT(e.evaluation_id) AS evaluation_count, + + -- 时效统计 + IFNULL(AVG(o.actual_duration), 0) AS avg_duration, + + -- 服务类型统计 + SUM(CASE WHEN o.service_type = '设备安装' THEN 1 ELSE 0 END) AS install_count, + SUM(CASE WHEN o.service_type = '滤芯更换' THEN 1 ELSE 0 END) AS filter_count, + SUM(CASE WHEN o.service_type = '维修' THEN 1 ELSE 0 END) AS repair_count, + SUM(CASE WHEN o.service_type = '水质检测' THEN 1 ELSE 0 END) AS quality_count, + + -- 等级评定 + CASE + WHEN AVG(e.rating) >= 4.8 AND COUNT(o.order_id) >= 50 THEN '金牌员工' + WHEN AVG(e.rating) >= 4.5 AND COUNT(o.order_id) >= 30 THEN '优秀员工' + WHEN AVG(e.rating) >= 4.0 THEN '普通员工' + ELSE '待提升' + END AS staff_level + +FROM water_staff s +LEFT JOIN water_service_order o ON s.staff_id = o.staff_id AND o.del_flag = '0' +LEFT JOIN water_evaluation e ON o.order_id = e.order_id AND e.del_flag = '0' +WHERE s.del_flag = '0' +GROUP BY s.staff_id; +``` + +**使用示例**: +```sql +-- 查询金牌员工 +SELECT * FROM v_staff_performance +WHERE staff_level = '金牌员工' +ORDER BY avg_rating DESC, completed_orders DESC; + +-- 查询本月完成订单最多的前10名 +SELECT * FROM v_staff_performance +ORDER BY completed_orders DESC +LIMIT 10; +``` + +--- + +### 4.2 v_order_statistics(订单统计视图) + +> 按日期、服务类型统计订单数据。 + +```sql +CREATE OR REPLACE VIEW `v_order_statistics` AS +SELECT + DATE(submit_time) AS order_date, + service_type, + order_status, + order_source, + + COUNT(*) AS order_count, + SUM(amount) AS total_amount, + SUM(actual_amount) AS total_actual_amount, + SUM(discount_amount) AS total_discount, + + AVG(actual_duration) AS avg_duration, + AVG(delivery_distance) AS avg_distance, + + COUNT(DISTINCT user_id) AS user_count, + COUNT(DISTINCT staff_id) AS staff_count + +FROM water_service_order +WHERE del_flag = '0' +GROUP BY DATE(submit_time), service_type, order_status, order_source; +``` + +**使用示例**: +```sql +-- 查询最近7天订单统计 +SELECT * FROM v_order_statistics +WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) +ORDER BY order_date DESC; + +-- 查询各服务类型完成情况 +SELECT + service_type, + SUM(order_count) AS total, + SUM(total_actual_amount) AS revenue +FROM v_order_statistics +WHERE order_status = 'completed' + AND order_date >= '2025-11-01' +GROUP BY service_type; +``` + +--- + +## 🔍 五、索引优化策略 + +### 5.1 唯一索引(保证数据唯一性) + +| 表名 | 索引名 | 字段 | 说明 | +|------|--------|------|------| +| water_user | uk_phone | phone | 手机号唯一 | +| water_user | uk_openid | openid | 微信openid唯一 | +| water_staff | uk_employee_no | employee_no | 工号唯一 | +| water_staff | uk_phone | phone | 员工手机号唯一 | +| water_device | uk_sn | sn | 设备序列号唯一 | +| water_service_order | uk_order_no | order_no | 订单号唯一 | +| water_evaluation | uk_order_id | order_id | 一订单一评价 | +| water_config | uk_config_key | config_key | 配置键唯一 | + +### 5.2 普通索引(提升查询性能) + +| 表名 | 索引类型 | 字段 | 使用场景 | +|------|----------|------|----------| +| water_user | 单列索引 | status | 查询正常用户 | +| water_device | 单列索引 | user_id | 查询用户的设备 | +| water_device | 单列索引 | status | 查询离线/故障设备 | +| water_filter | 单列索引 | device_id | 查询设备的滤芯 | +| water_filter | 单列索引 | life_percentage | 查询低寿命滤芯 | +| water_quality | 单列索引 | device_id | 查询设备检测记录 | +| water_quality | 单列索引 | test_time | 时间范围查询 | +| water_service_order | 单列索引 | user_id | 查询用户订单 | +| water_service_order | 单列索引 | order_status | 按状态查询 | +| water_service_order | 单列索引 | submit_time | 时间范围查询 | +| water_message | 单列索引 | user_id | 查询用户消息 | +| water_message | 单列索引 | is_read | 查询未读消息 | + +### 5.3 联合索引(复杂查询优化) + +```sql +-- 员工查询某状态的订单 +CREATE INDEX idx_staff_status ON water_service_order(staff_id, order_status); + +-- 用户查询某时间段的订单 +CREATE INDEX idx_user_time ON water_service_order(user_id, submit_time); + +-- 设备查询某时间段的水质记录 +CREATE INDEX idx_device_time ON water_quality(device_id, test_time); + +-- 查询未读消息 +CREATE INDEX idx_user_read ON water_message(user_id, is_read); +``` + +--- + +## ⚡ 六、性能优化建议 + +### 6.1 Redis 缓存策略 + +```java +// 1. 设备状态缓存(5分钟) +@Cacheable(value = "water:device:status", key = "#deviceId", expire = 300) +public String getDeviceStatus(Long deviceId); + +// 2. 用户信息缓存(30分钟) +@Cacheable(value = "water:user:info", key = "#userId", expire = 1800) +public WaterUser getUserInfo(Long userId); + +// 3. 员工绩效缓存(1小时) +@Cacheable(value = "water:staff:performance", key = "#staffId", expire = 3600) +public StaffPerformance getStaffPerformance(Long staffId); + +// 4. 商品列表缓存(10分钟) +@Cacheable(value = "water:product:list", key = "#category", expire = 600) +public List getProductList(String category); + +// 5. 系统配置缓存(永久,手动清除) +@Cacheable(value = "water:config", key = "#configKey") +public String getConfigValue(String configKey); +``` + +### 6.2 定时任务 + +```java +// 1. 每日凌晨1点更新滤芯寿命 +@Scheduled(cron = "0 0 1 * * ?") +public void updateFilterLife() { + // 批量更新滤芯寿命百分比 + filterMapper.batchUpdateLifePercentage(); +} + +// 2. 每日凌晨2点更新员工统计 +@Scheduled(cron = "0 0 2 * * ?") +public void updateStaffStatistics() { + List list = staffMapper.selectPerformanceFromView(); + for (StaffPerformance perf : list) { + staffMapper.updateStatistics(perf); + } +} + +// 3. 每小时检查订单自动完成 +@Scheduled(cron = "0 0 * * * ?") +public void autoCompleteOrder() { + Integer hours = configService.getConfigValueAsInt("order.auto_complete_hours", 24); + orderMapper.autoCompleteByHours(hours); +} + +// 4. 每10分钟检查设备离线状态 +@Scheduled(cron = "0 */10 * * * ?") +public void checkDeviceOffline() { + deviceMapper.updateOfflineStatus(); +} +``` + +### 6.3 分页查询优化 + +```java +// 使用 PageHelper 进行分页 +PageHelper.startPage(pageNum, pageSize); +List list = orderMapper.selectOrderList(order); +return getDataTable(list); +``` + +### 6.4 批量操作 + +```sql +-- 批量插入水质检测数据 +INSERT INTO water_quality (device_id, user_id, test_time, ph_value, turbidity) +VALUES + (1, 1, NOW(), 7.2, 0.5), + (2, 2, NOW(), 7.0, 0.6), + (3, 3, NOW(), 7.1, 0.4); + +-- 批量更新滤芯寿命 +UPDATE water_filter +SET used_days = DATEDIFF(NOW(), install_time), + life_percentage = GREATEST(0, ROUND((total_days - used_days) * 100.0 / total_days, 0)), + status = CASE WHEN life_percentage <= 10 THEN '1' ELSE '0' END +WHERE del_flag = '0'; +``` + +--- + +## 🔐 七、数据安全 + +### 7.1 敏感字段处理 + +```java +// 手机号脱敏 +public String maskPhone(String phone) { + if (StringUtils.isEmpty(phone) || phone.length() != 11) { + return phone; + } + return phone.substring(0, 3) + "****" + phone.substring(7); +} + +// 查询时自动脱敏 +SELECT + user_id, + CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) AS phone, + nick_name +FROM water_user; +``` + +### 7.2 密码加密 + +```java +// 使用 BCrypt 加密 +@Service +public class PasswordService { + @Autowired + private PasswordEncoder passwordEncoder; + + public String encryptPassword(String password) { + return passwordEncoder.encode(password); + } + + public boolean matches(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } +} +``` + +--- + +## 📡 八、与 RuoYi 框架对接 + +### 8.1 字段规范对接 + +所有表均包含 RuoYi 标准字段: + +```sql +create_by VARCHAR(64) -- 创建者 +create_time DATETIME -- 创建时间 +update_by VARCHAR(64) -- 更新者 +update_time DATETIME -- 更新时间 +remark VARCHAR(500) -- 备注 +del_flag CHAR(1) -- 删除标志(0存在 2删除) +``` + +### 8.2 数据权限对接 + +```java +// 员工只能查看本部门数据 +@DataScope(deptAlias = "d", userAlias = "s") +public List selectStaffList(WaterStaff staff); + +// 用户只能查看自己的订单 +@DataScope(userAlias = "o", userCol = "user_id") +public List selectOrderList(WaterServiceOrder order); +``` + +### 8.3 字典管理对接 + +在 RuoYi 的 `sys_dict_type` 中新增字典类型: + +| 字典类型 | 字典名称 | 字典键值 | +|---------|---------|---------| +| water_order_status | 订单状态 | pending/paid/accepted/processing/completed/cancelled | +| water_service_type | 服务类型 | 设备安装/滤芯更换/维修/订购/水质检测 | +| water_device_status | 设备状态 | 0离线/1在线/2故障 | +| water_payment_method | 支付方式 | wechat/balance/alipay | +| water_quality_level | 水质等级 | 优质/良好/一般/较差 | +| water_product_category | 商品分类 | purifier/meter/parts/service | + +### 8.4 菜单权限配置 + +``` +数智水管家 +├─ 用户管理 +│ ├─ 用户列表(water:user:list) +│ └─ 员工管理(water:staff:list) +├─ 设备管理 +│ ├─ 设备列表(water:device:list) +│ ├─ 滤芯管理(water:filter:list) +│ └─ 水质检测(water:quality:list) +├─ 商品管理 +│ ├─ 商品列表(water:product:list) +│ └─ 商品分类(water:product:category) +├─ 订单管理 +│ ├─ 订单列表(water:order:list) +│ ├─ 订单详情(water:order:query) +│ ├─ 派单(water:order:dispatch) +│ └─ 取消订单(water:order:cancel) +├─ 评价管理 +│ └─ 评价列表(water:evaluation:list) +├─ 消息管理 +│ ├─ 系统消息(water:message:list) +│ └─ 通知公告(water:notice:list) +└─ 统计分析 + ├─ 数据看板(water:statistics:dashboard) + ├─ 员工绩效(water:statistics:staff) + └─ 订单报表(water:statistics:order) +``` + +--- + +## 📱 九、API 接口清单 + +### 9.1 用户端(/water/app) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /auth/login | POST | 用户登录 | water_user | +| /auth/wechat | POST | 微信登录 | water_user | +| /device/list | GET | 设备列表 | water_device | +| /device/detail/{sn} | GET | 设备详情 | water_device, water_filter, water_quality | +| /device/bind | POST | 绑定设备 | water_device | +| /filter/list | GET | 滤芯列表 | water_filter | +| /quality/list | GET | 水质检测列表 | water_quality | +| /quality/apply | POST | 申请水质检测 | water_service_order | +| /product/list | GET | 商品列表 | water_product | +| /order/create | POST | 创建订单 | water_service_order, water_order_product | +| /order/list | GET | 订单列表 | water_service_order | +| /order/detail/{id} | GET | 订单详情 | water_service_order | +| /order/pay | POST | 订单支付 | water_service_order | +| /order/cancel | POST | 取消订单 | water_service_order | +| /order/evaluate | POST | 订单评价 | water_evaluation | +| /message/list | GET | 消息列表 | water_message | +| /notice/list | GET | 公告列表 | water_notice | + +### 9.2 员工端(/water/staff) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /auth/login | POST | 员工登录 | water_staff | +| /workorder/list | GET | 工单列表 | water_service_order | +| /workorder/accept | POST | 接单 | water_service_order | +| /workorder/start | POST | 开始处理 | water_service_order | +| /workorder/complete | POST | 完成工单 | water_service_order | +| /delivery/list | GET | 配送任务列表 | water_service_order | +| /statistics | GET | 我的统计 | v_staff_performance | +| /evaluation/list | GET | 我的评价 | water_evaluation | + +### 9.3 管理后台(/water/admin) + +| 接口路径 | 方法 | 说明 | 对应表 | +|---------|------|------|--------| +| /user/list | GET | 用户列表 | water_user | +| /staff/list | GET | 员工列表 | water_staff | +| /device/list | GET | 设备列表 | water_device | +| /product/list | GET | 商品列表 | water_product | +| /product/save | POST | 保存商品 | water_product | +| /order/list | GET | 订单列表 | water_service_order | +| /order/dispatch | POST | 派单 | water_service_order | +| /notice/list | GET | 公告列表 | water_notice | +| /notice/publish | POST | 发布公告 | water_notice | +| /statistics/dashboard | GET | 数据看板 | v_order_statistics | +| /statistics/staff | GET | 员工绩效 | v_staff_performance | + +--- + +## 📈 十、数据库部署 + +### 10.1 创建数据库 + +```sql +CREATE DATABASE `water_manager` + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_general_ci; + +USE `water_manager`; +``` + +### 10.2 执行建表脚本 + +执行配套的 `数智水管家数据库设计_v2.0.sql` 脚本文件。 + +### 10.3 初始化数据 + +```sql +-- 1. 初始化系统配置 +INSERT INTO water_config (config_key, config_value, config_type, config_desc) VALUES +('order.auto_complete_hours', '24', 'number', '订单自动完成时间(小时)'), +('filter.warning_threshold', '30', 'number', '滤芯寿命预警阈值(%)'), +('service.quality_test_price', '99.00', 'number', '水质检测服务价格'), +('delivery.base_fee', '5.00', 'number', '配送费起步价'); + +-- 2. 初始化商品数据 +INSERT INTO water_product (product_name, product_desc, category, price, icon, status, sort_order) VALUES +('智能净水器', 'RO反渗透,5级过滤', 'purifier', 1299.00, '💧', '0', 1), +('智能水表', '远程抄表,实时监测', 'meter', 299.00, '📊', '0', 2), +('净水器滤芯', 'PP棉+活性炭+RO膜', 'parts', 199.00, '🔧', '0', 3), +('水质检测服务', '上门检测,专业报告', 'service', 99.00, '🔬', '0', 4); + +-- 3. 初始化通知公告 +INSERT INTO water_notice (notice_title, notice_content, notice_type, target_type, status, publish_time) VALUES +('欢迎使用数智水管家', '感谢您使用数智水管家系统,我们将为您提供优质的服务。', 'info', 'all', '0', NOW()), +('关于临时停水通知', '因设备维护,部分区域将在本周末临时停水,请提前做好准备。', 'warning', 'user', '0', NOW()); +``` + +--- + +## ✅ 十一、总结 + +### 11.1 设计优势 + +✅ **功能完整**:12张表覆盖用户端和员工端全部功能 +✅ **结构精简**:相比原设计减少9张表(43%),维护成本大幅降低 +✅ **高度复用**:订单、工单、配送统一管理,避免数据冗余 +✅ **性能优化**:合理的索引设计和缓存策略,支持高并发 +✅ **易于扩展**:预留扩展字段,支持业务快速迭代 +✅ **深度集成**:完美对接 RuoYi 框架,复用权限、字典等功能 + +### 11.2 适用场景 + +- ✅ 中小型水管家业务(日订单量 < 10万) +- ✅ 快速开发 MVP 产品 +- ✅ 与 RuoYi 框架深度集成 +- ✅ 注重数据一致性和维护性 + +### 11.3 后续扩展建议 + +当业务量增长时,可考虑: + +1. **订单分表**:按年/月对 `water_service_order` 分表 +2. **读写分离**:配置 MySQL 主从架构 +3. **缓存集群**:升级为 Redis 集群 +4. **消息队列**:引入 RabbitMQ/Kafka 异步处理 +5. **对象存储**:接入 OSS 存储检测报告、评价图片 + +--- + +**文档版本**:v2.0 +**更新日期**:2025-11-13 +**适配框架**:RuoYi v4.x+ +**数据库版本**:MySQL 5.7+ + +--- + +## 📎 附录 + +### A. ER 图说明 + +``` +用户 (water_user) 1----* 设备 (water_device) +用户 (water_user) 1----* 订单 (water_service_order) +用户 (water_user) 1----* 消息 (water_message) + +设备 (water_device) 1----* 滤芯 (water_filter) +设备 (water_device) 1----* 水质检测 (water_quality) + +员工 (water_staff) 1----* 订单 (water_service_order) +员工 (water_staff) 1----* 消息 (water_message) + +订单 (water_service_order) 1----* 订单商品 (water_order_product) +订单 (water_service_order) 1----1 评价 (water_evaluation) + +商品 (water_product) 1----* 订单商品 (water_order_product) +``` + +### B. 表大小预估 + +| 表名 | 预计记录数 | 单条记录大小 | 预计表大小 | +|------|-----------|-------------|-----------| +| water_user | 100,000 | 1KB | ~100MB | +| water_staff | 100 | 0.5KB | ~50KB | +| water_device | 100,000 | 0.5KB | ~50MB | +| water_filter | 400,000 | 0.3KB | ~120MB | +| water_quality | 1,000,000 | 1KB | ~1GB | +| water_product | 100 | 0.5KB | ~50KB | +| water_service_order | 1,000,000 | 1.5KB | ~1.5GB | +| water_order_product | 2,000,000 | 0.3KB | ~600MB | +| water_evaluation | 500,000 | 1KB | ~500MB | +| water_message | 1,000,000 | 0.5KB | ~500MB | +| water_notice | 100 | 0.5KB | ~50KB | +| water_config | 50 | 0.3KB | ~15KB | +| **总计** | **5,000,350** | - | **~4.37GB** | + +### C. 数据备份策略 + +```bash +# 每日全量备份 +0 2 * * * /usr/bin/mysqldump -u root -p water_manager > /backup/water_manager_$(date +\%Y\%m\%d).sql + +# 每周备份保留 +0 3 * * 0 cp /backup/water_manager_$(date +\%Y\%m\%d).sql /backup/weekly/ + +# 自动清理30天前的备份 +0 4 * * * find /backup -name "*.sql" -mtime +30 -delete +``` + +--- + +**文档结束** + diff --git a/src/数智水管家/数智水管家/database/数智水管家数据库设计_v2.0.sql b/src/数智水管家/数智水管家/database/数智水管家数据库设计_v2.0.sql new file mode 100644 index 0000000..bda31e9 --- /dev/null +++ b/src/数智水管家/数智水管家/database/数智水管家数据库设计_v2.0.sql @@ -0,0 +1,523 @@ +-- ============================================= +-- 数智水管家数据库设计 v2.0 +-- 创建日期:2025-11-13 +-- 适配框架:RuoYi v4.x+ +-- 数据库版本:MySQL 5.7+ +-- 表数量:12张核心表 + 2个视图 +-- ============================================= + +-- 创建数据库 +CREATE DATABASE IF NOT EXISTS `water_manager` + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_general_ci; + +USE `water_manager`; + +-- ============================================= +-- 1. 用户表 +-- ============================================= +DROP TABLE IF EXISTS `water_user`; +CREATE TABLE `water_user` ( + `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `phone` VARCHAR(11) DEFAULT NULL COMMENT '手机号', + `password` VARCHAR(128) DEFAULT NULL COMMENT '密码(BCrypt加密)', + `nick_name` VARCHAR(50) DEFAULT NULL COMMENT '昵称', + `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', + `gender` CHAR(1) DEFAULT '0' COMMENT '性别(0未知 1男 2女)', + `openid` VARCHAR(128) DEFAULT NULL COMMENT '微信openid', + `unionid` VARCHAR(128) DEFAULT NULL COMMENT '微信unionid', + `balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '账户余额', + `total_orders` INT(11) DEFAULT 0 COMMENT '订单总数(冗余)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`user_id`), + UNIQUE KEY `uk_phone` (`phone`), + UNIQUE KEY `uk_openid` (`openid`), + KEY `idx_status` (`status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; + +-- ============================================= +-- 2. 员工表 +-- ============================================= +DROP TABLE IF EXISTS `water_staff`; +CREATE TABLE `water_staff` ( + `staff_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '员工ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '关联sys_user的user_id', + `employee_no` VARCHAR(20) NOT NULL COMMENT '工号', + `staff_name` VARCHAR(50) NOT NULL COMMENT '姓名', + `phone` VARCHAR(11) NOT NULL COMMENT '手机号', + `dept_id` BIGINT(20) DEFAULT NULL COMMENT '部门ID(关联sys_dept)', + `position` VARCHAR(50) DEFAULT NULL COMMENT '职位', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `total_orders` INT(11) DEFAULT 0 COMMENT '工单总数(冗余)', + `completed_orders` INT(11) DEFAULT 0 COMMENT '完成工单数(冗余)', + `avg_rating` DECIMAL(3,2) DEFAULT 5.00 COMMENT '平均评分(冗余)', + `avg_duration` INT(11) DEFAULT 0 COMMENT '平均服务时长-分钟(冗余)', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`staff_id`), + UNIQUE KEY `uk_employee_no` (`employee_no`), + UNIQUE KEY `uk_phone` (`phone`), + KEY `idx_user_id` (`user_id`), + KEY `idx_dept_id` (`dept_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工表'; + +-- ============================================= +-- 3. 设备表 +-- ============================================= +DROP TABLE IF EXISTS `water_device`; +CREATE TABLE `water_device` ( + `device_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `sn` VARCHAR(50) NOT NULL COMMENT '设备编号(唯一)', + `device_name` VARCHAR(100) DEFAULT NULL COMMENT '设备名称', + `device_type` VARCHAR(50) DEFAULT '智能净水器' COMMENT '设备类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '设备型号', + `status` CHAR(1) DEFAULT '1' COMMENT '状态(0离线 1在线 2故障)', + `install_address` VARCHAR(255) DEFAULT NULL COMMENT '安装地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `bind_time` DATETIME DEFAULT NULL COMMENT '绑定时间', + `last_online_time` DATETIME DEFAULT NULL COMMENT '最后在线时间', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`device_id`), + UNIQUE KEY `uk_sn` (`sn`), + KEY `idx_user_id` (`user_id`), + KEY `idx_status` (`status`), + KEY `idx_bind_time` (`bind_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备表'; + +-- ============================================= +-- 4. 滤芯表 +-- ============================================= +DROP TABLE IF EXISTS `water_filter`; +CREATE TABLE `water_filter` ( + `filter_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '滤芯ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `filter_name` VARCHAR(50) NOT NULL COMMENT '滤芯名称(如:PP棉滤芯)', + `filter_type` VARCHAR(50) DEFAULT NULL COMMENT '滤芯类型', + `model` VARCHAR(50) DEFAULT NULL COMMENT '滤芯型号', + `install_time` DATETIME DEFAULT NULL COMMENT '安装时间', + `total_days` INT(11) DEFAULT 180 COMMENT '总使用天数(默认180天)', + `used_days` INT(11) DEFAULT 0 COMMENT '已使用天数', + `life_percentage` INT(11) DEFAULT 100 COMMENT '剩余寿命百分比', + `next_replace_time` DATE DEFAULT NULL COMMENT '预计更换时间', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1需更换)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`filter_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_status` (`status`), + KEY `idx_life_percentage` (`life_percentage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='滤芯表'; + +-- ============================================= +-- 5. 水质检测记录表 +-- ============================================= +DROP TABLE IF EXISTS `water_quality`; +CREATE TABLE `water_quality` ( + `quality_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '检测ID', + `device_id` BIGINT(20) NOT NULL COMMENT '设备ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `order_id` BIGINT(20) DEFAULT NULL COMMENT '关联订单ID(如果是服务订单)', + `test_time` DATETIME NOT NULL COMMENT '检测时间', + `test_address` VARCHAR(255) DEFAULT NULL COMMENT '检测地址', + `quality_level` VARCHAR(20) DEFAULT NULL COMMENT '水质等级(优质/良好/一般/较差)', + `quality_desc` VARCHAR(500) DEFAULT NULL COMMENT '水质描述', + + -- 检测指标 + `ph_value` DECIMAL(4,2) DEFAULT NULL COMMENT 'pH值(6.5-8.5)', + `turbidity` DECIMAL(6,2) DEFAULT NULL COMMENT '浊度 NTU(≤1)', + `residual_chlorine` DECIMAL(6,2) DEFAULT NULL COMMENT '余氯 mg/L(0.05-4)', + `total_hardness` DECIMAL(8,2) DEFAULT NULL COMMENT '总硬度 mg/L(≤450)', + `tds` DECIMAL(8,2) DEFAULT NULL COMMENT 'TDS溶解性固体 mg/L(≤1000)', + `cod` DECIMAL(8,2) DEFAULT NULL COMMENT 'COD化学需氧量 mg/L', + `ammonia_nitrogen` DECIMAL(6,2) DEFAULT NULL COMMENT '氨氮 mg/L', + + `report_url` VARCHAR(255) DEFAULT NULL COMMENT '检测报告URL', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0检测中 1已完成)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`quality_id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_test_time` (`test_time`), + KEY `idx_quality_level` (`quality_level`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水质检测记录表'; + +-- ============================================= +-- 6. 商品表 +-- ============================================= +DROP TABLE IF EXISTS `water_product`; +CREATE TABLE `water_product` ( + `product_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称', + `product_desc` VARCHAR(500) DEFAULT NULL COMMENT '商品描述', + `category` VARCHAR(50) DEFAULT NULL COMMENT '商品分类(purifier净水器/meter水表/parts配件/service服务)', + `price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '商品价格', + `stock` INT(11) DEFAULT 0 COMMENT '库存数量', + `image_url` VARCHAR(255) DEFAULT NULL COMMENT '商品图片URL', + `icon` VARCHAR(50) DEFAULT NULL COMMENT '图标Emoji', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0上架 1下架)', + `sort_order` INT(11) DEFAULT 0 COMMENT '排序', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`product_id`), + KEY `idx_category` (`category`), + KEY `idx_status` (`status`), + KEY `idx_sort_order` (`sort_order`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; + +-- ============================================= +-- 7. 服务订单表(核心表) +-- ============================================= +DROP TABLE IF EXISTS `water_service_order`; +CREATE TABLE `water_service_order` ( + `order_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `order_no` VARCHAR(50) NOT NULL COMMENT '订单号(唯一)', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '负责员工ID', + + -- 订单类型与来源 + `service_type` VARCHAR(50) NOT NULL COMMENT '服务类型(设备安装/滤芯更换/维修/订购/水质检测)', + `order_source` VARCHAR(20) DEFAULT 'user' COMMENT '订单来源(user用户下单/admin后台派单)', + + -- 订单状态 + `order_status` VARCHAR(20) DEFAULT 'pending' COMMENT '订单状态(pending待支付/paid已支付/accepted已接单/processing处理中/completed已完成/cancelled已取消)', + `payment_status` VARCHAR(20) DEFAULT 'unpaid' COMMENT '支付状态(unpaid未支付/paid已支付/refunded已退款)', + + -- 金额信息 + `amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '订单金额', + `actual_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '实付金额', + `discount_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '优惠金额', + `payment_method` VARCHAR(20) DEFAULT NULL COMMENT '支付方式(wechat微信/balance余额/alipay支付宝)', + + -- 服务信息 + `contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人', + `contact_phone` VARCHAR(11) DEFAULT NULL COMMENT '联系电话', + `service_address` VARCHAR(255) DEFAULT NULL COMMENT '服务地址', + `location_lat` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', + `location_lng` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', + `description` TEXT DEFAULT NULL COMMENT '服务描述/问题描述', + `priority` VARCHAR(20) DEFAULT 'normal' COMMENT '优先级(normal普通/high紧急)', + + -- 配送信息 + `delivery_distance` DECIMAL(10,2) DEFAULT NULL COMMENT '配送距离(公里)', + `estimated_duration` INT(11) DEFAULT NULL COMMENT '预计时长(分钟)', + `actual_duration` INT(11) DEFAULT NULL COMMENT '实际时长(分钟)', + + -- 时间轴 + `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间', + `payment_time` DATETIME DEFAULT NULL COMMENT '支付时间', + `accept_time` DATETIME DEFAULT NULL COMMENT '接单时间', + `start_time` DATETIME DEFAULT NULL COMMENT '开始配送时间', + `complete_time` DATETIME DEFAULT NULL COMMENT '完成时间', + `cancel_time` DATETIME DEFAULT NULL COMMENT '取消时间', + + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`order_id`), + UNIQUE KEY `uk_order_no` (`order_no`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_order_status` (`order_status`), + KEY `idx_service_type` (`service_type`), + KEY `idx_submit_time` (`submit_time`), + KEY `idx_staff_status` (`staff_id`, `order_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务订单表'; + +-- ============================================= +-- 8. 订单商品关联表 +-- ============================================= +DROP TABLE IF EXISTS `water_order_product`; +CREATE TABLE `water_order_product` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `product_id` BIGINT(20) NOT NULL COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称(冗余)', + `product_price` DECIMAL(10,2) NOT NULL COMMENT '商品单价(冗余)', + `quantity` INT(11) DEFAULT 1 COMMENT '购买数量', + `total_price` DECIMAL(10,2) NOT NULL COMMENT '小计金额', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_order_id` (`order_id`), + KEY `idx_product_id` (`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品关联表'; + +-- ============================================= +-- 9. 订单评价表 +-- ============================================= +DROP TABLE IF EXISTS `water_evaluation`; +CREATE TABLE `water_evaluation` ( + `evaluation_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '评价ID', + `order_id` BIGINT(20) NOT NULL COMMENT '订单ID', + `user_id` BIGINT(20) NOT NULL COMMENT '用户ID', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID', + `rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '综合评分(1-5星)', + `service_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务态度评分', + `quality_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务质量评分', + `speed_rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '服务速度评分', + `content` TEXT DEFAULT NULL COMMENT '评价内容', + `images` VARCHAR(1000) DEFAULT NULL COMMENT '评价图片(JSON数组)', + `is_anonymous` CHAR(1) DEFAULT '0' COMMENT '是否匿名(0否 1是)', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`evaluation_id`), + UNIQUE KEY `uk_order_id` (`order_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_rating` (`rating`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单评价表'; + +-- ============================================= +-- 10. 系统消息表 +-- ============================================= +DROP TABLE IF EXISTS `water_message`; +CREATE TABLE `water_message` ( + `message_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '消息ID', + `user_id` BIGINT(20) DEFAULT NULL COMMENT '用户ID(用户消息)', + `staff_id` BIGINT(20) DEFAULT NULL COMMENT '员工ID(员工消息)', + `message_type` VARCHAR(50) DEFAULT NULL COMMENT '消息类型(order订单/device设备/system系统/service服务)', + `title` VARCHAR(100) NOT NULL COMMENT '消息标题', + `content` TEXT NOT NULL COMMENT '消息内容', + `related_id` BIGINT(20) DEFAULT NULL COMMENT '关联ID(如订单ID、设备ID)', + `is_read` CHAR(1) DEFAULT '0' COMMENT '是否已读(0未读 1已读)', + `send_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '发送时间', + `read_time` DATETIME DEFAULT NULL COMMENT '阅读时间', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`message_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_staff_id` (`staff_id`), + KEY `idx_message_type` (`message_type`), + KEY `idx_is_read` (`is_read`), + KEY `idx_send_time` (`send_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统消息表'; + +-- ============================================= +-- 11. 通知公告表 +-- ============================================= +DROP TABLE IF EXISTS `water_notice`; +CREATE TABLE `water_notice` ( + `notice_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `notice_title` VARCHAR(100) NOT NULL COMMENT '公告标题', + `notice_content` TEXT NOT NULL COMMENT '公告内容', + `notice_type` VARCHAR(20) DEFAULT 'info' COMMENT '公告类型(info通知/warning警告/urgent紧急)', + `target_type` VARCHAR(20) DEFAULT 'all' COMMENT '目标对象(all全部/user用户/staff员工)', + `status` CHAR(1) DEFAULT '0' COMMENT '状态(0发布 1草稿 2下架)', + `publish_time` DATETIME DEFAULT NULL COMMENT '发布时间', + `expire_time` DATETIME DEFAULT NULL COMMENT '过期时间', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 2删除)', + PRIMARY KEY (`notice_id`), + KEY `idx_status` (`status`), + KEY `idx_target_type` (`target_type`), + KEY `idx_publish_time` (`publish_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通知公告表'; + +-- ============================================= +-- 12. 系统配置表 +-- ============================================= +DROP TABLE IF EXISTS `water_config`; +CREATE TABLE `water_config` ( + `config_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '配置ID', + `config_key` VARCHAR(100) NOT NULL COMMENT '配置键', + `config_value` VARCHAR(500) NOT NULL COMMENT '配置值', + `config_type` VARCHAR(50) DEFAULT 'string' COMMENT '配置类型(string/number/boolean/json)', + `config_desc` VARCHAR(500) DEFAULT NULL COMMENT '配置描述', + `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`), + UNIQUE KEY `uk_config_key` (`config_key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表'; + +-- ============================================= +-- 视图1:员工绩效视图 +-- ============================================= +DROP VIEW IF EXISTS `v_staff_performance`; +CREATE OR REPLACE VIEW `v_staff_performance` AS +SELECT + s.staff_id, + s.employee_no, + s.staff_name, + s.phone, + s.dept_id, + s.position, + + -- 订单统计 + COUNT(o.order_id) AS total_orders, + SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) AS completed_orders, + SUM(CASE WHEN o.order_status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_orders, + ROUND(SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(o.order_id), 0), 2) AS completion_rate, + + -- 评价统计 + IFNULL(AVG(e.rating), 5.00) AS avg_rating, + COUNT(e.evaluation_id) AS evaluation_count, + + -- 时效统计 + IFNULL(AVG(o.actual_duration), 0) AS avg_duration, + + -- 服务类型统计 + SUM(CASE WHEN o.service_type = '设备安装' THEN 1 ELSE 0 END) AS install_count, + SUM(CASE WHEN o.service_type = '滤芯更换' THEN 1 ELSE 0 END) AS filter_count, + SUM(CASE WHEN o.service_type = '维修' THEN 1 ELSE 0 END) AS repair_count, + SUM(CASE WHEN o.service_type = '水质检测' THEN 1 ELSE 0 END) AS quality_count, + + -- 等级评定 + CASE + WHEN AVG(e.rating) >= 4.8 AND COUNT(o.order_id) >= 50 THEN '金牌员工' + WHEN AVG(e.rating) >= 4.5 AND COUNT(o.order_id) >= 30 THEN '优秀员工' + WHEN AVG(e.rating) >= 4.0 THEN '普通员工' + ELSE '待提升' + END AS staff_level + +FROM water_staff s +LEFT JOIN water_service_order o ON s.staff_id = o.staff_id AND o.del_flag = '0' +LEFT JOIN water_evaluation e ON o.order_id = e.order_id AND e.del_flag = '0' +WHERE s.del_flag = '0' +GROUP BY s.staff_id; + +-- ============================================= +-- 视图2:订单统计视图 +-- ============================================= +DROP VIEW IF EXISTS `v_order_statistics`; +CREATE OR REPLACE VIEW `v_order_statistics` AS +SELECT + DATE(submit_time) AS order_date, + service_type, + order_status, + order_source, + + COUNT(*) AS order_count, + SUM(amount) AS total_amount, + SUM(actual_amount) AS total_actual_amount, + SUM(discount_amount) AS total_discount, + + AVG(actual_duration) AS avg_duration, + AVG(delivery_distance) AS avg_distance, + + COUNT(DISTINCT user_id) AS user_count, + COUNT(DISTINCT staff_id) AS staff_count + +FROM water_service_order +WHERE del_flag = '0' +GROUP BY DATE(submit_time), service_type, order_status, order_source; + +-- ============================================= +-- 初始化系统配置数据 +-- ============================================= +INSERT INTO `water_config` (`config_key`, `config_value`, `config_type`, `config_desc`, `create_by`, `remark`) VALUES +('order.auto_complete_hours', '24', 'number', '订单自动完成时间(小时)', 'admin', '订单在处理中状态超过指定小时后自动完成'), +('filter.warning_threshold', '30', 'number', '滤芯寿命预警阈值(%)', 'admin', '滤芯寿命低于此百分比时发送预警'), +('service.quality_test_price', '99.00', 'number', '水质检测服务价格', 'admin', '水质检测服务的默认价格'), +('delivery.base_fee', '5.00', 'number', '配送费起步价', 'admin', '配送服务的起步价格'), +('filter.pp_days', '180', 'number', 'PP棉滤芯使用天数', 'admin', 'PP棉滤芯的默认使用天数'), +('filter.cto_days', '180', 'number', '活性炭滤芯使用天数', 'admin', '活性炭滤芯的默认使用天数'), +('filter.ro_days', '720', 'number', 'RO膜使用天数', 'admin', 'RO反渗透膜的默认使用天数'), +('device.offline_minutes', '60', 'number', '设备离线判定时间(分钟)', 'admin', '设备超过指定分钟未上线判定为离线'); + +-- ============================================= +-- 初始化商品数据 +-- ============================================= +INSERT INTO `water_product` (`product_name`, `product_desc`, `category`, `price`, `stock`, `icon`, `status`, `sort_order`, `create_by`) VALUES +('智能净水器', 'RO反渗透,5级过滤', 'purifier', 1299.00, 100, '💧', '0', 1, 'admin'), +('智能水表', '远程抄表,实时监测', 'meter', 299.00, 200, '📊', '0', 2, 'admin'), +('净水器滤芯-PP棉', 'PP棉滤芯,5微米过滤', 'parts', 59.00, 500, '🔧', '0', 3, 'admin'), +('净水器滤芯-活性炭', '前置活性炭滤芯,吸附异味', 'parts', 89.00, 500, '🔧', '0', 4, 'admin'), +('净水器滤芯-RO膜', 'RO反渗透膜,0.0001微米过滤', 'parts', 199.00, 300, '🔧', '0', 5, 'admin'), +('水质检测服务', '上门检测,专业报告', 'service', 99.00, 9999, '🔬', '0', 6, 'admin'), +('前置过滤器', '保护全屋用水安全', 'purifier', 399.00, 80, '🛡️', '0', 7, 'admin'), +('软水机', '去除水垢,软化水质', 'purifier', 2599.00, 50, '✨', '0', 8, 'admin'); + +-- ============================================= +-- 初始化通知公告数据 +-- ============================================= +INSERT INTO `water_notice` (`notice_title`, `notice_content`, `notice_type`, `target_type`, `status`, `publish_time`, `create_by`) VALUES +('欢迎使用数智水管家', '感谢您使用数智水管家系统,我们将为您提供优质的水质管理服务。如有任何问题,请随时联系我们的客服团队。', 'info', 'all', '0', NOW(), 'admin'), +('关于临时停水通知', '因设备维护需要,部分区域将在本周末(11月16-17日)临时停水,请提前做好储水准备。', 'warning', 'user', '0', NOW(), 'admin'), +('春节供水保障公告', '春节期间我们将安排员工值班,确保供水服务正常进行。紧急情况请拨打24小时客服热线。', 'info', 'all', '0', NOW(), 'admin'); + +-- ============================================= +-- 示例数据:用户 +-- ============================================= +INSERT INTO `water_user` (`phone`, `password`, `nick_name`, `gender`, `balance`, `total_orders`, `status`) VALUES +('13800138000', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE/sXHZWzUzn', '张三', '1', 100.00, 5, '0'), +('13800138001', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE/sXHZWzUzn', '李四', '2', 50.00, 3, '0'), +('13800138002', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE/sXHZWzUzn', '王五', '1', 200.00, 8, '0'); + +-- ============================================= +-- 示例数据:员工 +-- ============================================= +INSERT INTO `water_staff` (`employee_no`, `staff_name`, `phone`, `position`, `status`, `total_orders`, `completed_orders`, `avg_rating`, `create_by`) VALUES +('EMP001', '工程师张', '13900139000', '高级工程师', '0', 50, 48, 4.8, 'admin'), +('EMP002', '工程师李', '13900139001', '工程师', '0', 30, 28, 4.5, 'admin'), +('EMP003', '工程师王', '13900139002', '初级工程师', '0', 20, 18, 4.2, 'admin'); + +-- ============================================= +-- 示例数据:设备 +-- ============================================= +INSERT INTO `water_device` (`user_id`, `sn`, `device_name`, `device_type`, `model`, `status`, `install_address`, `bind_time`, `last_online_time`) VALUES +(1, 'JSQ20240115001', '净水器-001', '智能净水器', 'RO-5级复合滤芯', '1', 'XX小区3栋2单元501', '2024-01-10 14:30:00', NOW()), +(1, 'JSQ20240112002', '净水器-002', '智能净水器', 'RO-5级复合滤芯', '1', 'XX小区3栋2单元501', '2024-01-08 10:15:00', NOW()), +(2, 'JSQ20240105003', '净水器-003', '智能净水器', 'RO-5级复合滤芯', '0', 'XX路88号', '2024-01-05 09:00:00', '2024-01-14 18:00:00'); + +-- ============================================= +-- 示例数据:滤芯 +-- ============================================= +INSERT INTO `water_filter` (`device_id`, `filter_name`, `filter_type`, `model`, `install_time`, `total_days`, `used_days`, `life_percentage`, `next_replace_time`, `status`) VALUES +(1, 'PP棉滤芯', 'PP棉', 'PP-001', '2024-01-10', 180, 35, 65, '2024-06-08', '0'), +(1, '前置活性炭', '活性炭', 'CTO-001', '2024-01-10', 180, 35, 58, '2024-06-08', '0'), +(1, 'RO反渗透膜', 'RO膜', 'RO-001', '2024-01-10', 720, 35, 72, '2026-01-05', '0'), +(1, '后置活性炭', '活性炭', 'GAC-001', '2024-01-10', 180, 35, 61, '2024-06-08', '0'), +(2, 'PP棉滤芯', 'PP棉', 'PP-001', '2024-01-08', 180, 45, 45, '2024-06-06', '0'), +(2, '前置活性炭', '活性炭', 'CTO-001', '2024-01-08', 180, 45, 38, '2024-06-06', '0'), +(2, 'RO反渗透膜', 'RO膜', 'RO-001', '2024-01-08', 720, 45, 52, '2026-01-03', '0'), +(2, '后置活性炭', '活性炭', 'GAC-001', '2024-01-08', 180, 45, 42, '2024-06-06', '0'); + +-- ============================================= +-- 示例数据:水质检测 +-- ============================================= +INSERT INTO `water_quality` (`device_id`, `user_id`, `test_time`, `test_address`, `quality_level`, `quality_desc`, `ph_value`, `turbidity`, `residual_chlorine`, `total_hardness`, `tds`, `status`) VALUES +(1, 1, '2024-01-15 10:00:00', 'XX小区3栋2单元501', '优质', '水质指标稳定,符合饮用标准', 7.2, 0.5, 0.3, 150, 220, '1'), +(2, 1, '2024-01-10 14:00:00', 'XX小区3栋2单元501', '良好', '上次检测显示浊度接近上限,建议再次检测确认', 7.0, 1.2, 0.25, 180, 250, '1'), +(3, 2, '2024-01-08 09:00:00', 'XX路88号', '较差', '余氯低于安全值,建议暂停饮用并联系工作人员', 6.8, 0.8, 0.04, 200, 300, '1'); + +-- ============================================= +-- 创建完成提示 +-- ============================================= +SELECT '数据库创建完成!' AS message; +SELECT '核心表数量:12张' AS summary; +SELECT '视图数量:2个' AS summary; +SELECT '已初始化示例数据' AS summary; + diff --git a/src/数智水管家/数智水管家/index.html b/src/数智水管家/数智水管家/index.html new file mode 100644 index 0000000..b5d330d --- /dev/null +++ b/src/数智水管家/数智水管家/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/src/数智水管家/数智水管家/main.js b/src/数智水管家/数智水管家/main.js new file mode 100644 index 0000000..c1caf36 --- /dev/null +++ b/src/数智水管家/数智水管家/main.js @@ -0,0 +1,22 @@ +import App from './App' + +// #ifndef VUE3 +import Vue from 'vue' +import './uni.promisify.adaptor' +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/src/数智水管家/数智水管家/manifest.json b/src/数智水管家/数智水管家/manifest.json new file mode 100644 index 0000000..cebf8f0 --- /dev/null +++ b/src/数智水管家/数智水管家/manifest.json @@ -0,0 +1,72 @@ +{ + "name" : "数智水管家", + "appid" : "", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3" +} diff --git a/src/数智水管家/数智水管家/pages.json b/src/数智水管家/数智水管家/pages.json new file mode 100644 index 0000000..e445235 --- /dev/null +++ b/src/数智水管家/数智水管家/pages.json @@ -0,0 +1,193 @@ +{ + "pages": [ + { + "path": "pages/login/login", + "style": { + "navigationBarTitleText": "登录", + "navigationStyle": "custom", + "navigationBarTextStyle": "white" + } + }, + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "首页" + } + }, + { + "path": "pages/order/order", + "style": { + "navigationBarTitleText": "订单" + } + }, + { + "path": "pages/message/message", + "style": { + "navigationBarTitleText": "消息" + } + }, + { + "path": "pages/profile/profile", + "style": { + "navigationBarTitleText": "我的" + } + }, + { + "path": "pages/staff/index", + "style": { + "navigationBarTitleText": "工作台" + } + }, + { + "path": "pages/staff/delivery", + "style": { + "navigationBarTitleText": "配送" + } + }, + { + "path": "pages/staff/delivery-detail", + "style": { + "navigationBarTitleText": "配送详情" + } + }, + { + "path": "pages/staff/delivery-task", + "style": { + "navigationBarTitleText": "配送任务", + "navigationBarBackgroundColor": "#409eff", + "navigationBarTextStyle": "white" + } + }, + { + "path": "pages/staff/workorder", + "style": { + "navigationBarTitleText": "工单" + } + }, + { + "path": "pages/staff/workorder-detail", + "style": { + "navigationBarTitleText": "工单详情" + } + }, + { + "path": "pages/staff/profile", + "style": { + "navigationBarTitleText": "我的" + } + }, + { + "path": "pages/purchase/purchase", + "style": { + "navigationBarTitleText": "订购" + } + }, + { + "path": "pages/device/device", + "style": { + "navigationBarTitleText": "设备管理" + } + }, + { + "path": "pages/water-quality/water-quality", + "style": { + "navigationBarTitleText": "水质检测" + } + }, + { + "path": "pages/water-quality-detail/water-quality-detail", + "style": { + "navigationBarTitleText": "检测报告" + } + }, + { + "path": "pages/water-quality-alert/water-quality-alert", + "style": { + "navigationBarTitleText": "水质预警" + } + }, + { + "path": "pages/customer-service/customer-service", + "style": { + "navigationBarTitleText": "在线客服" + } + }, + { + "path": "pages/order-detail/order-detail", + "style": { + "navigationBarTitleText": "订单详情" + } + }, + { + "path": "pages/device-detail/device-detail", + "style": { + "navigationBarTitleText": "设备详情" + } + }, + { + "path": "pages/device-problem/device-problem", + "style": { + "navigationBarTitleText": "问题设备", + "navigationBarBackgroundColor": "#F56C6C", + "navigationBarTextStyle": "white" + } + }, + { + "path": "pages/order-progress/order-progress", + "style": { + "navigationBarTitleText": "订单详情" + } + }, + { + "path": "pages/payment/payment", + "style": { + "navigationBarTitleText": "支付" + } + }, + { + "path": "pages/staff/stats", + "style": { + "navigationBarTitleText": "工作统计" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "数智水管家", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "color": "#909399", + "selectedColor": "#409eff", + "backgroundColor": "#ffffff", + "borderStyle": "black", + "list": [ + { + "pagePath": "pages/index/index", + "text": "首页", + "iconPath": "static/首页.png", + "selectedIconPath": "static/首页.png" + }, + { + "pagePath": "pages/order/order", + "text": "订单", + "iconPath": "static/订单.png", + "selectedIconPath": "static/订单.png" + }, + { + "pagePath": "pages/message/message", + "text": "消息", + "iconPath": "static/消息.png", + "selectedIconPath": "static/消息.png" + }, + { + "pagePath": "pages/profile/profile", + "text": "我的", + "iconPath": "static/我的.png", + "selectedIconPath": "static/我的.png" + } + ] + }, + "uniIdRouter": {} +} diff --git a/src/数智水管家/数智水管家/pages/customer-service/customer-service.vue b/src/数智水管家/数智水管家/pages/customer-service/customer-service.vue new file mode 100644 index 0000000..5bafe5f --- /dev/null +++ b/src/数智水管家/数智水管家/pages/customer-service/customer-service.vue @@ -0,0 +1,297 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/device-detail/device-detail.vue b/src/数智水管家/数智水管家/pages/device-detail/device-detail.vue new file mode 100644 index 0000000..64534ba --- /dev/null +++ b/src/数智水管家/数智水管家/pages/device-detail/device-detail.vue @@ -0,0 +1,773 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/device-problem/device-problem.vue b/src/数智水管家/数智水管家/pages/device-problem/device-problem.vue new file mode 100644 index 0000000..e711ade --- /dev/null +++ b/src/数智水管家/数智水管家/pages/device-problem/device-problem.vue @@ -0,0 +1,119 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/device/device.vue b/src/数智水管家/数智水管家/pages/device/device.vue new file mode 100644 index 0000000..f748be0 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/device/device.vue @@ -0,0 +1,406 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/index/index.vue b/src/数智水管家/数智水管家/pages/index/index.vue new file mode 100644 index 0000000..673186d --- /dev/null +++ b/src/数智水管家/数智水管家/pages/index/index.vue @@ -0,0 +1,590 @@ + + + + + diff --git a/src/数智水管家/数智水管家/pages/login/login.vue b/src/数智水管家/数智水管家/pages/login/login.vue new file mode 100644 index 0000000..95fcd5a --- /dev/null +++ b/src/数智水管家/数智水管家/pages/login/login.vue @@ -0,0 +1,722 @@ + + + + + diff --git a/src/数智水管家/数智水管家/pages/message/message.vue b/src/数智水管家/数智水管家/pages/message/message.vue new file mode 100644 index 0000000..93147b6 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/message/message.vue @@ -0,0 +1,299 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/order-detail/order-detail.vue b/src/数智水管家/数智水管家/pages/order-detail/order-detail.vue new file mode 100644 index 0000000..aade6ac --- /dev/null +++ b/src/数智水管家/数智水管家/pages/order-detail/order-detail.vue @@ -0,0 +1,611 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/order-progress/order-progress.vue b/src/数智水管家/数智水管家/pages/order-progress/order-progress.vue new file mode 100644 index 0000000..6756351 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/order-progress/order-progress.vue @@ -0,0 +1,641 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/order/order.vue b/src/数智水管家/数智水管家/pages/order/order.vue new file mode 100644 index 0000000..5a2e1ae --- /dev/null +++ b/src/数智水管家/数智水管家/pages/order/order.vue @@ -0,0 +1,388 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/payment/payment.vue b/src/数智水管家/数智水管家/pages/payment/payment.vue new file mode 100644 index 0000000..a3ff5d9 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/payment/payment.vue @@ -0,0 +1,533 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/profile/profile.vue b/src/数智水管家/数智水管家/pages/profile/profile.vue new file mode 100644 index 0000000..23d1521 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/profile/profile.vue @@ -0,0 +1,273 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/purchase/purchase.vue b/src/数智水管家/数智水管家/pages/purchase/purchase.vue new file mode 100644 index 0000000..7fca97e --- /dev/null +++ b/src/数智水管家/数智水管家/pages/purchase/purchase.vue @@ -0,0 +1,278 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/delivery-detail.vue b/src/数智水管家/数智水管家/pages/staff/delivery-detail.vue new file mode 100644 index 0000000..6be790f --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/delivery-detail.vue @@ -0,0 +1,724 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/delivery-task.vue b/src/数智水管家/数智水管家/pages/staff/delivery-task.vue new file mode 100644 index 0000000..ae07a47 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/delivery-task.vue @@ -0,0 +1,498 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/delivery.vue b/src/数智水管家/数智水管家/pages/staff/delivery.vue new file mode 100644 index 0000000..17d5cb8 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/delivery.vue @@ -0,0 +1,458 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/index.vue b/src/数智水管家/数智水管家/pages/staff/index.vue new file mode 100644 index 0000000..785e5b0 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/index.vue @@ -0,0 +1,533 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/profile.vue b/src/数智水管家/数智水管家/pages/staff/profile.vue new file mode 100644 index 0000000..a2878c9 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/profile.vue @@ -0,0 +1,315 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/stats.vue b/src/数智水管家/数智水管家/pages/staff/stats.vue new file mode 100644 index 0000000..64602fd --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/stats.vue @@ -0,0 +1,454 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/workorder-detail.vue b/src/数智水管家/数智水管家/pages/staff/workorder-detail.vue new file mode 100644 index 0000000..64db6e3 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/workorder-detail.vue @@ -0,0 +1,653 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/staff/workorder.vue b/src/数智水管家/数智水管家/pages/staff/workorder.vue new file mode 100644 index 0000000..64c7fe1 --- /dev/null +++ b/src/数智水管家/数智水管家/pages/staff/workorder.vue @@ -0,0 +1,513 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/water-quality-alert/water-quality-alert.vue b/src/数智水管家/数智水管家/pages/water-quality-alert/water-quality-alert.vue new file mode 100644 index 0000000..61b04bf --- /dev/null +++ b/src/数智水管家/数智水管家/pages/water-quality-alert/water-quality-alert.vue @@ -0,0 +1,281 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/water-quality-detail/water-quality-detail.vue b/src/数智水管家/数智水管家/pages/water-quality-detail/water-quality-detail.vue new file mode 100644 index 0000000..536caeb --- /dev/null +++ b/src/数智水管家/数智水管家/pages/water-quality-detail/water-quality-detail.vue @@ -0,0 +1,462 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/pages/water-quality/water-quality.vue b/src/数智水管家/数智水管家/pages/water-quality/water-quality.vue new file mode 100644 index 0000000..254589b --- /dev/null +++ b/src/数智水管家/数智水管家/pages/water-quality/water-quality.vue @@ -0,0 +1,366 @@ + + + + + + diff --git a/src/数智水管家/数智水管家/static/logo.png b/src/数智水管家/数智水管家/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/src/数智水管家/数智水管家/static/logo.png differ diff --git a/src/数智水管家/数智水管家/static/我的.png b/src/数智水管家/数智水管家/static/我的.png new file mode 100644 index 0000000..ea9346c Binary files /dev/null and b/src/数智水管家/数智水管家/static/我的.png differ diff --git a/src/数智水管家/数智水管家/static/消息.png b/src/数智水管家/数智水管家/static/消息.png new file mode 100644 index 0000000..51787ad Binary files /dev/null and b/src/数智水管家/数智水管家/static/消息.png differ diff --git a/src/数智水管家/数智水管家/static/订单.png b/src/数智水管家/数智水管家/static/订单.png new file mode 100644 index 0000000..a08a1dd Binary files /dev/null and b/src/数智水管家/数智水管家/static/订单.png differ diff --git a/src/数智水管家/数智水管家/static/首页.png b/src/数智水管家/数智水管家/static/首页.png new file mode 100644 index 0000000..89a1cdc Binary files /dev/null and b/src/数智水管家/数智水管家/static/首页.png differ diff --git a/src/数智水管家/数智水管家/uni.promisify.adaptor.js b/src/数智水管家/数智水管家/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/src/数智水管家/数智水管家/uni.promisify.adaptor.js @@ -0,0 +1,13 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => { + if (!res) return resolve(res) + return res[0] ? reject(res[0]) : resolve(res[1]) + }); + }); + }, +}); \ No newline at end of file diff --git a/src/数智水管家/数智水管家/uni.scss b/src/数智水管家/数智水管家/uni.scss new file mode 100644 index 0000000..b9249e9 --- /dev/null +++ b/src/数智水管家/数智水管家/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/api/auth.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/api/auth.js.map new file mode 100644 index 0000000..5570745 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/api/auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.js","sources":["api/auth.js"],"sourcesContent":["/**\r\n * 认证相关API\r\n */\r\nimport { post, get } from '../utils/request.js'\r\n\r\n/**\r\n * 用户登录(手机号/密码)\r\n * @param {Object} data - 登录数据\r\n * @param {string} data.phone - 手机号\r\n * @param {string} data.password - 密码\r\n */\r\nexport function login(data) {\r\n\treturn post('/water/app/auth/login', data, {\r\n\t\tshowError: false, // 登录失败不自动提示,由页面处理\r\n\t\tpreventDuplicate: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 员工登录(工号/密码)\r\n * @param {Object} data - 登录数据\r\n * @param {string} data.employeeNo - 工号\r\n * @param {string} data.password - 密码\r\n */\r\nexport function staffLogin(data) {\r\n\treturn post('/water/staff/auth/login', data, {\r\n\t\tshowError: false,\r\n\t\tpreventDuplicate: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 微信登录\r\n * @param {Object} data - 微信登录数据\r\n * @param {string} data.code - 微信code\r\n * @param {string} data.encryptedData - 加密数据\r\n * @param {string} data.iv - 初始向量\r\n */\r\nexport function wechatLogin(data) {\r\n\treturn post('/water/app/auth/wechat', data, {\r\n\t\tshowError: false,\r\n\t\tpreventDuplicate: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 用户注册\r\n * @param {Object} data - 注册数据\r\n * @param {string} data.phone - 手机号\r\n * @param {string} data.password - 密码\r\n * @param {string} data.code - 验证码\r\n */\r\nexport function register(data) {\r\n\treturn post('/water/app/auth/register', data, {\r\n\t\tpreventDuplicate: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 发送验证码\r\n * @param {string} phone - 手机号\r\n */\r\nexport function sendCode(phone) {\r\n\treturn post('/water/app/auth/sendCode', { phone }, {\r\n\t\tpreventDuplicate: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 退出登录\r\n */\r\nexport function logout() {\r\n\treturn post('/water/app/auth/logout')\r\n}\r\n\r\n/**\r\n * 刷新Token\r\n */\r\nexport function refreshToken() {\r\n\treturn post('/water/app/auth/refresh')\r\n}\r\n\r\n"],"names":["post"],"mappings":";;AAWO,SAAS,MAAM,MAAM;AAC3B,SAAOA,cAAI,KAAC,yBAAyB,MAAM;AAAA,IAC1C,WAAW;AAAA;AAAA,IACX,kBAAkB;AAAA,EACpB,CAAE;AACF;AAQO,SAAS,WAAW,MAAM;AAChC,SAAOA,cAAI,KAAC,2BAA2B,MAAM;AAAA,IAC5C,WAAW;AAAA,IACX,kBAAkB;AAAA,EACpB,CAAE;AACF;AASO,SAAS,YAAY,MAAM;AACjC,SAAOA,cAAI,KAAC,0BAA0B,MAAM;AAAA,IAC3C,WAAW;AAAA,IACX,kBAAkB;AAAA,EACpB,CAAE;AACF;;;;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map new file mode 100644 index 0000000..bc54aec --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.js","sources":["App.vue","main.js"],"sourcesContent":["\r\n\r\n\r\n","import App from './App'\r\n\r\n// #ifndef VUE3\r\nimport Vue from 'vue'\r\nimport './uni.promisify.adaptor'\r\nVue.config.productionTip = false\r\nApp.mpType = 'app'\r\nconst app = new Vue({\r\n ...App\r\n})\r\napp.$mount()\r\n// #endif\r\n\r\n// #ifdef VUE3\r\nimport { createSSRApp } from 'vue'\r\nexport function createApp() {\r\n const app = createSSRApp(App)\r\n return {\r\n app\r\n }\r\n}\r\n// #endif"],"names":["onLaunch","uni","setTabBar","onShow","onHide","createSSRApp","App"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIAA,kBAAAA,SAAS,MAAM;AACdC,oBAAAA,MAAA,MAAA,OAAA,gBAAY,oBAAoB;AAEhC,YAAM,WAAWA,cAAG,MAAC,eAAe,UAAU,KAAK;AACnDC,mBAAAA,UAAU,QAAQ;AAAA,IACnB,CAAC;AAEDC,kBAAAA,OAAO,MAAM;AACZF,oBAAAA,MAAY,MAAA,OAAA,iBAAA,UAAU;AAAA,IACvB,CAAC;AAEDG,kBAAAA,OAAO,MAAM;AACZH,oBAAAA,MAAY,MAAA,OAAA,iBAAA,UAAU;AAAA,IACvB,CAAC;;;;;ACFM,SAAS,YAAY;AAC1B,QAAM,MAAMI,cAAY,aAACC,SAAG;AAC5B,SAAO;AAAA,IACL;AAAA,EACD;AACH;;;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map new file mode 100644 index 0000000..81c5d3f --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map @@ -0,0 +1 @@ +{"version":3,"file":"assets.js","sources":["static/logo.png"],"sourcesContent":["export default \"__VITE_ASSET__46719607__\""],"names":[],"mappings":";AAAA,MAAe,aAAA;;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map new file mode 100644 index 0000000..e420b39 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"vendor.js","sources":["../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@vue/shared/dist/shared.esm-bundler.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-i18n/dist/uni-i18n.es.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-shared/dist/uni-shared.es.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-mp-vue/dist/vue.runtime.esm.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-mp-weixin/dist/uni.api.esm.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-console/dist/mp.esm.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-mp-weixin/dist/uni.mp.esm.js","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-app/dist/uni-app.es.js"],"sourcesContent":["/**\n* @vue/shared v3.4.21\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\nfunction makeMap(str, expectsLowerCase) {\n const set = new Set(str.split(\",\"));\n return expectsLowerCase ? (val) => set.has(val.toLowerCase()) : (val) => set.has(val);\n}\n\nconst EMPTY_OBJ = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze({}) : {};\nconst EMPTY_ARR = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze([]) : [];\nconst NOOP = () => {\n};\nconst NO = () => false;\nconst isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter\n(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);\nconst isModelListener = (key) => key.startsWith(\"onUpdate:\");\nconst extend = Object.assign;\nconst remove = (arr, el) => {\n const i = arr.indexOf(el);\n if (i > -1) {\n arr.splice(i, 1);\n }\n};\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst hasOwn = (val, key) => hasOwnProperty.call(val, key);\nconst isArray = Array.isArray;\nconst isMap = (val) => toTypeString(val) === \"[object Map]\";\nconst isSet = (val) => toTypeString(val) === \"[object Set]\";\nconst isDate = (val) => toTypeString(val) === \"[object Date]\";\nconst isRegExp = (val) => toTypeString(val) === \"[object RegExp]\";\nconst isFunction = (val) => typeof val === \"function\";\nconst isString = (val) => typeof val === \"string\";\nconst isSymbol = (val) => typeof val === \"symbol\";\nconst isObject = (val) => val !== null && typeof val === \"object\";\nconst isPromise = (val) => {\n return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);\n};\nconst objectToString = Object.prototype.toString;\nconst toTypeString = (value) => objectToString.call(value);\nconst toRawType = (value) => {\n return toTypeString(value).slice(8, -1);\n};\nconst isPlainObject = (val) => toTypeString(val) === \"[object Object]\";\nconst isIntegerKey = (key) => isString(key) && key !== \"NaN\" && key[0] !== \"-\" && \"\" + parseInt(key, 10) === key;\nconst isReservedProp = /* @__PURE__ */ makeMap(\n // the leading comma is intentional so empty string \"\" is also included\n \",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"\n);\nconst isBuiltInDirective = /* @__PURE__ */ makeMap(\n \"bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo\"\n);\nconst cacheStringFunction = (fn) => {\n const cache = /* @__PURE__ */ Object.create(null);\n return (str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n };\n};\nconst camelizeRE = /-(\\w)/g;\nconst camelize = cacheStringFunction((str) => {\n return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n});\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction(\n (str) => str.replace(hyphenateRE, \"-$1\").toLowerCase()\n);\nconst capitalize = cacheStringFunction((str) => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n});\nconst toHandlerKey = cacheStringFunction((str) => {\n const s = str ? `on${capitalize(str)}` : ``;\n return s;\n});\nconst hasChanged = (value, oldValue) => !Object.is(value, oldValue);\nconst invokeArrayFns = (fns, arg) => {\n for (let i = 0; i < fns.length; i++) {\n fns[i](arg);\n }\n};\nconst def = (obj, key, value) => {\n Object.defineProperty(obj, key, {\n configurable: true,\n enumerable: false,\n value\n });\n};\nconst looseToNumber = (val) => {\n const n = parseFloat(val);\n return isNaN(n) ? val : n;\n};\nconst toNumber = (val) => {\n const n = isString(val) ? Number(val) : NaN;\n return isNaN(n) ? val : n;\n};\nlet _globalThis;\nconst getGlobalThis = () => {\n return _globalThis || (_globalThis = typeof globalThis !== \"undefined\" ? globalThis : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : {});\n};\nconst identRE = /^[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*$/;\nfunction genPropsAccessExp(name) {\n return identRE.test(name) ? `__props.${name}` : `__props[${JSON.stringify(name)}]`;\n}\n\nconst PatchFlags = {\n \"TEXT\": 1,\n \"1\": \"TEXT\",\n \"CLASS\": 2,\n \"2\": \"CLASS\",\n \"STYLE\": 4,\n \"4\": \"STYLE\",\n \"PROPS\": 8,\n \"8\": \"PROPS\",\n \"FULL_PROPS\": 16,\n \"16\": \"FULL_PROPS\",\n \"NEED_HYDRATION\": 32,\n \"32\": \"NEED_HYDRATION\",\n \"STABLE_FRAGMENT\": 64,\n \"64\": \"STABLE_FRAGMENT\",\n \"KEYED_FRAGMENT\": 128,\n \"128\": \"KEYED_FRAGMENT\",\n \"UNKEYED_FRAGMENT\": 256,\n \"256\": \"UNKEYED_FRAGMENT\",\n \"NEED_PATCH\": 512,\n \"512\": \"NEED_PATCH\",\n \"DYNAMIC_SLOTS\": 1024,\n \"1024\": \"DYNAMIC_SLOTS\",\n \"DEV_ROOT_FRAGMENT\": 2048,\n \"2048\": \"DEV_ROOT_FRAGMENT\",\n \"HOISTED\": -1,\n \"-1\": \"HOISTED\",\n \"BAIL\": -2,\n \"-2\": \"BAIL\"\n};\nconst PatchFlagNames = {\n [1]: `TEXT`,\n [2]: `CLASS`,\n [4]: `STYLE`,\n [8]: `PROPS`,\n [16]: `FULL_PROPS`,\n [32]: `NEED_HYDRATION`,\n [64]: `STABLE_FRAGMENT`,\n [128]: `KEYED_FRAGMENT`,\n [256]: `UNKEYED_FRAGMENT`,\n [512]: `NEED_PATCH`,\n [1024]: `DYNAMIC_SLOTS`,\n [2048]: `DEV_ROOT_FRAGMENT`,\n [-1]: `HOISTED`,\n [-2]: `BAIL`\n};\n\nconst ShapeFlags = {\n \"ELEMENT\": 1,\n \"1\": \"ELEMENT\",\n \"FUNCTIONAL_COMPONENT\": 2,\n \"2\": \"FUNCTIONAL_COMPONENT\",\n \"STATEFUL_COMPONENT\": 4,\n \"4\": \"STATEFUL_COMPONENT\",\n \"TEXT_CHILDREN\": 8,\n \"8\": \"TEXT_CHILDREN\",\n \"ARRAY_CHILDREN\": 16,\n \"16\": \"ARRAY_CHILDREN\",\n \"SLOTS_CHILDREN\": 32,\n \"32\": \"SLOTS_CHILDREN\",\n \"TELEPORT\": 64,\n \"64\": \"TELEPORT\",\n \"SUSPENSE\": 128,\n \"128\": \"SUSPENSE\",\n \"COMPONENT_SHOULD_KEEP_ALIVE\": 256,\n \"256\": \"COMPONENT_SHOULD_KEEP_ALIVE\",\n \"COMPONENT_KEPT_ALIVE\": 512,\n \"512\": \"COMPONENT_KEPT_ALIVE\",\n \"COMPONENT\": 6,\n \"6\": \"COMPONENT\"\n};\n\nconst SlotFlags = {\n \"STABLE\": 1,\n \"1\": \"STABLE\",\n \"DYNAMIC\": 2,\n \"2\": \"DYNAMIC\",\n \"FORWARDED\": 3,\n \"3\": \"FORWARDED\"\n};\nconst slotFlagsText = {\n [1]: \"STABLE\",\n [2]: \"DYNAMIC\",\n [3]: \"FORWARDED\"\n};\n\nconst GLOBALS_ALLOWED = \"Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error\";\nconst isGloballyAllowed = /* @__PURE__ */ makeMap(GLOBALS_ALLOWED);\nconst isGloballyWhitelisted = isGloballyAllowed;\n\nconst range = 2;\nfunction generateCodeFrame(source, start = 0, end = source.length) {\n let lines = source.split(/(\\r?\\n)/);\n const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);\n lines = lines.filter((_, idx) => idx % 2 === 0);\n let count = 0;\n const res = [];\n for (let i = 0; i < lines.length; i++) {\n count += lines[i].length + (newlineSequences[i] && newlineSequences[i].length || 0);\n if (count >= start) {\n for (let j = i - range; j <= i + range || end > count; j++) {\n if (j < 0 || j >= lines.length)\n continue;\n const line = j + 1;\n res.push(\n `${line}${\" \".repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`\n );\n const lineLength = lines[j].length;\n const newLineSeqLength = newlineSequences[j] && newlineSequences[j].length || 0;\n if (j === i) {\n const pad = start - (count - (lineLength + newLineSeqLength));\n const length = Math.max(\n 1,\n end > count ? lineLength - pad : end - start\n );\n res.push(` | ` + \" \".repeat(pad) + \"^\".repeat(length));\n } else if (j > i) {\n if (end > count) {\n const length = Math.max(Math.min(end - count, lineLength), 1);\n res.push(` | ` + \"^\".repeat(length));\n }\n count += lineLength + newLineSeqLength;\n }\n }\n break;\n }\n }\n return res.join(\"\\n\");\n}\n\nfunction normalizeStyle(value) {\n if (isArray(value)) {\n const res = {};\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item);\n if (normalized) {\n for (const key in normalized) {\n res[key] = normalized[key];\n }\n }\n }\n return res;\n } else if (isString(value) || isObject(value)) {\n return value;\n }\n}\nconst listDelimiterRE = /;(?![^(]*\\))/g;\nconst propertyDelimiterRE = /:([^]+)/;\nconst styleCommentRE = /\\/\\*[^]*?\\*\\//g;\nfunction parseStringStyle(cssText) {\n const ret = {};\n cssText.replace(styleCommentRE, \"\").split(listDelimiterRE).forEach((item) => {\n if (item) {\n const tmp = item.split(propertyDelimiterRE);\n tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());\n }\n });\n return ret;\n}\nfunction stringifyStyle(styles) {\n let ret = \"\";\n if (!styles || isString(styles)) {\n return ret;\n }\n for (const key in styles) {\n const value = styles[key];\n const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key);\n if (isString(value) || typeof value === \"number\") {\n ret += `${normalizedKey}:${value};`;\n }\n }\n return ret;\n}\nfunction normalizeClass(value) {\n let res = \"\";\n if (isString(value)) {\n res = value;\n } else if (isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const normalized = normalizeClass(value[i]);\n if (normalized) {\n res += normalized + \" \";\n }\n }\n } else if (isObject(value)) {\n for (const name in value) {\n if (value[name]) {\n res += name + \" \";\n }\n }\n }\n return res.trim();\n}\nfunction normalizeProps(props) {\n if (!props)\n return null;\n let { class: klass, style } = props;\n if (klass && !isString(klass)) {\n props.class = normalizeClass(klass);\n }\n if (style) {\n props.style = normalizeStyle(style);\n }\n return props;\n}\n\nconst HTML_TAGS = \"html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot\";\nconst SVG_TAGS = \"svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view\";\nconst MATH_TAGS = \"annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics\";\nconst VOID_TAGS = \"area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr\";\nconst isHTMLTag = /* @__PURE__ */ makeMap(HTML_TAGS);\nconst isSVGTag = /* @__PURE__ */ makeMap(SVG_TAGS);\nconst isMathMLTag = /* @__PURE__ */ makeMap(MATH_TAGS);\nconst isVoidTag = /* @__PURE__ */ makeMap(VOID_TAGS);\n\nconst specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;\nconst isSpecialBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs);\nconst isBooleanAttr = /* @__PURE__ */ makeMap(\n specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`\n);\nfunction includeBooleanAttr(value) {\n return !!value || value === \"\";\n}\nconst unsafeAttrCharRE = /[>/=\"'\\u0009\\u000a\\u000c\\u0020]/;\nconst attrValidationCache = {};\nfunction isSSRSafeAttrName(name) {\n if (attrValidationCache.hasOwnProperty(name)) {\n return attrValidationCache[name];\n }\n const isUnsafe = unsafeAttrCharRE.test(name);\n if (isUnsafe) {\n console.error(`unsafe attribute name: ${name}`);\n }\n return attrValidationCache[name] = !isUnsafe;\n}\nconst propsToAttrMap = {\n acceptCharset: \"accept-charset\",\n className: \"class\",\n htmlFor: \"for\",\n httpEquiv: \"http-equiv\"\n};\nconst isKnownHtmlAttr = /* @__PURE__ */ makeMap(\n `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap`\n);\nconst isKnownSvgAttr = /* @__PURE__ */ makeMap(\n `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan`\n);\nfunction isRenderableAttrValue(value) {\n if (value == null) {\n return false;\n }\n const type = typeof value;\n return type === \"string\" || type === \"number\" || type === \"boolean\";\n}\n\nconst escapeRE = /[\"'&<>]/;\nfunction escapeHtml(string) {\n const str = \"\" + string;\n const match = escapeRE.exec(str);\n if (!match) {\n return str;\n }\n let html = \"\";\n let escaped;\n let index;\n let lastIndex = 0;\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34:\n escaped = \""\";\n break;\n case 38:\n escaped = \"&\";\n break;\n case 39:\n escaped = \"'\";\n break;\n case 60:\n escaped = \"<\";\n break;\n case 62:\n escaped = \">\";\n break;\n default:\n continue;\n }\n if (lastIndex !== index) {\n html += str.slice(lastIndex, index);\n }\n lastIndex = index + 1;\n html += escaped;\n }\n return lastIndex !== index ? html + str.slice(lastIndex, index) : html;\n}\nconst commentStripRE = /^-?>||--!>| looseEqual(item, val));\n}\n\nconst toDisplayString = (val) => {\n return isString(val) ? val : val == null ? \"\" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);\n};\nconst replacer = (_key, val) => {\n if (val && val.__v_isRef) {\n return replacer(_key, val.value);\n } else if (isMap(val)) {\n return {\n [`Map(${val.size})`]: [...val.entries()].reduce(\n (entries, [key, val2], i) => {\n entries[stringifySymbol(key, i) + \" =>\"] = val2;\n return entries;\n },\n {}\n )\n };\n } else if (isSet(val)) {\n return {\n [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v))\n };\n } else if (isSymbol(val)) {\n return stringifySymbol(val);\n } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {\n return String(val);\n }\n return val;\n};\nconst stringifySymbol = (v, i = \"\") => {\n var _a;\n return isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v;\n};\n\nexport { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, PatchFlags, ShapeFlags, SlotFlags, camelize, capitalize, def, escapeHtml, escapeHtmlComment, extend, genPropsAccessExp, generateCodeFrame, getGlobalThis, hasChanged, hasOwn, hyphenate, includeBooleanAttr, invokeArrayFns, isArray, isBooleanAttr, isBuiltInDirective, isDate, isFunction, isGloballyAllowed, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownHtmlAttr, isKnownSvgAttr, isMap, isMathMLTag, isModelListener, isObject, isOn, isPlainObject, isPromise, isRegExp, isRenderableAttrValue, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet, isSpecialBooleanAttr, isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, looseToNumber, makeMap, normalizeClass, normalizeProps, normalizeStyle, objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString };\n","const isObject = (val) => val !== null && typeof val === 'object';\nconst defaultDelimiters = ['{', '}'];\nclass BaseFormatter {\n constructor() {\n this._caches = Object.create(null);\n }\n interpolate(message, values, delimiters = defaultDelimiters) {\n if (!values) {\n return [message];\n }\n let tokens = this._caches[message];\n if (!tokens) {\n tokens = parse(message, delimiters);\n this._caches[message] = tokens;\n }\n return compile(tokens, values);\n }\n}\nconst RE_TOKEN_LIST_VALUE = /^(?:\\d)+/;\nconst RE_TOKEN_NAMED_VALUE = /^(?:\\w)+/;\nfunction parse(format, [startDelimiter, endDelimiter]) {\n const tokens = [];\n let position = 0;\n let text = '';\n while (position < format.length) {\n let char = format[position++];\n if (char === startDelimiter) {\n if (text) {\n tokens.push({ type: 'text', value: text });\n }\n text = '';\n let sub = '';\n char = format[position++];\n while (char !== undefined && char !== endDelimiter) {\n sub += char;\n char = format[position++];\n }\n const isClosed = char === endDelimiter;\n const type = RE_TOKEN_LIST_VALUE.test(sub)\n ? 'list'\n : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)\n ? 'named'\n : 'unknown';\n tokens.push({ value: sub, type });\n }\n // else if (char === '%') {\n // // when found rails i18n syntax, skip text capture\n // if (format[position] !== '{') {\n // text += char\n // }\n // }\n else {\n text += char;\n }\n }\n text && tokens.push({ type: 'text', value: text });\n return tokens;\n}\nfunction compile(tokens, values) {\n const compiled = [];\n let index = 0;\n const mode = Array.isArray(values)\n ? 'list'\n : isObject(values)\n ? 'named'\n : 'unknown';\n if (mode === 'unknown') {\n return compiled;\n }\n while (index < tokens.length) {\n const token = tokens[index];\n switch (token.type) {\n case 'text':\n compiled.push(token.value);\n break;\n case 'list':\n compiled.push(values[parseInt(token.value, 10)]);\n break;\n case 'named':\n if (mode === 'named') {\n compiled.push(values[token.value]);\n }\n else {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);\n }\n }\n break;\n case 'unknown':\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Detect 'unknown' type of token!`);\n }\n break;\n }\n index++;\n }\n return compiled;\n}\n\nconst LOCALE_ZH_HANS = 'zh-Hans';\nconst LOCALE_ZH_HANT = 'zh-Hant';\nconst LOCALE_EN = 'en';\nconst LOCALE_FR = 'fr';\nconst LOCALE_ES = 'es';\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst hasOwn = (val, key) => hasOwnProperty.call(val, key);\nconst defaultFormatter = new BaseFormatter();\nfunction include(str, parts) {\n return !!parts.find((part) => str.indexOf(part) !== -1);\n}\nfunction startsWith(str, parts) {\n return parts.find((part) => str.indexOf(part) === 0);\n}\nfunction normalizeLocale(locale, messages) {\n if (!locale) {\n return;\n }\n locale = locale.trim().replace(/_/g, '-');\n if (messages && messages[locale]) {\n return locale;\n }\n locale = locale.toLowerCase();\n if (locale === 'chinese') {\n // 支付宝\n return LOCALE_ZH_HANS;\n }\n if (locale.indexOf('zh') === 0) {\n if (locale.indexOf('-hans') > -1) {\n return LOCALE_ZH_HANS;\n }\n if (locale.indexOf('-hant') > -1) {\n return LOCALE_ZH_HANT;\n }\n if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {\n return LOCALE_ZH_HANT;\n }\n return LOCALE_ZH_HANS;\n }\n let locales = [LOCALE_EN, LOCALE_FR, LOCALE_ES];\n if (messages && Object.keys(messages).length > 0) {\n locales = Object.keys(messages);\n }\n const lang = startsWith(locale, locales);\n if (lang) {\n return lang;\n }\n}\nclass I18n {\n constructor({ locale, fallbackLocale, messages, watcher, formater, }) {\n this.locale = LOCALE_EN;\n this.fallbackLocale = LOCALE_EN;\n this.message = {};\n this.messages = {};\n this.watchers = [];\n if (fallbackLocale) {\n this.fallbackLocale = fallbackLocale;\n }\n this.formater = formater || defaultFormatter;\n this.messages = messages || {};\n this.setLocale(locale || LOCALE_EN);\n if (watcher) {\n this.watchLocale(watcher);\n }\n }\n setLocale(locale) {\n const oldLocale = this.locale;\n this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;\n if (!this.messages[this.locale]) {\n // 可能初始化时不存在\n this.messages[this.locale] = {};\n }\n this.message = this.messages[this.locale];\n // 仅发生变化时,通知\n if (oldLocale !== this.locale) {\n this.watchers.forEach((watcher) => {\n watcher(this.locale, oldLocale);\n });\n }\n }\n getLocale() {\n return this.locale;\n }\n watchLocale(fn) {\n const index = this.watchers.push(fn) - 1;\n return () => {\n this.watchers.splice(index, 1);\n };\n }\n add(locale, message, override = true) {\n const curMessages = this.messages[locale];\n if (curMessages) {\n if (override) {\n Object.assign(curMessages, message);\n }\n else {\n Object.keys(message).forEach((key) => {\n if (!hasOwn(curMessages, key)) {\n curMessages[key] = message[key];\n }\n });\n }\n }\n else {\n this.messages[locale] = message;\n }\n }\n f(message, values, delimiters) {\n return this.formater.interpolate(message, values, delimiters).join('');\n }\n t(key, locale, values) {\n let message = this.message;\n if (typeof locale === 'string') {\n locale = normalizeLocale(locale, this.messages);\n locale && (message = this.messages[locale]);\n }\n else {\n values = locale;\n }\n if (!hasOwn(message, key)) {\n console.warn(`Cannot translate the value of keypath ${key}. Use the value of keypath as default.`);\n return key;\n }\n return this.formater.interpolate(message[key], values).join('');\n }\n}\n\nfunction watchAppLocale(appVm, i18n) {\n // 需要保证 watch 的触发在组件渲染之前\n if (appVm.$watchLocale) {\n // vue2\n appVm.$watchLocale((newLocale) => {\n i18n.setLocale(newLocale);\n });\n }\n else {\n appVm.$watch(() => appVm.$locale, (newLocale) => {\n i18n.setLocale(newLocale);\n });\n }\n}\nfunction getDefaultLocale() {\n if (typeof uni !== 'undefined' && uni.getLocale) {\n return uni.getLocale();\n }\n // 小程序平台,uni 和 uni-i18n 互相引用,导致访问不到 uni,故在 global 上挂了 getLocale\n if (typeof global !== 'undefined' && global.getLocale) {\n return global.getLocale();\n }\n return LOCALE_EN;\n}\nfunction initVueI18n(locale, messages = {}, fallbackLocale, watcher) {\n // 兼容旧版本入参\n if (typeof locale !== 'string') {\n // ;[locale, messages] = [\n // messages as unknown as string,\n // locale as unknown as LocaleMessages,\n // ]\n // 暂不使用数组解构,uts编译器暂未支持。\n const options = [\n messages,\n locale,\n ];\n locale = options[0];\n messages = options[1];\n }\n if (typeof locale !== 'string') {\n // 因为小程序平台,uni-i18n 和 uni 互相引用,导致此时访问 uni 时,为 undefined\n locale = getDefaultLocale();\n }\n if (typeof fallbackLocale !== 'string') {\n fallbackLocale =\n (typeof __uniConfig !== 'undefined' && __uniConfig.fallbackLocale) ||\n LOCALE_EN;\n }\n const i18n = new I18n({\n locale,\n fallbackLocale,\n messages,\n watcher,\n });\n let t = (key, values) => {\n if (typeof getApp !== 'function') {\n // app view\n /* eslint-disable no-func-assign */\n t = function (key, values) {\n return i18n.t(key, values);\n };\n }\n else {\n let isWatchedAppLocale = false;\n t = function (key, values) {\n const appVm = getApp().$vm;\n // 可能$vm还不存在,比如在支付宝小程序中,组件定义较早,在props的default里使用了t()函数(如uni-goods-nav),此时app还未初始化\n // options: {\n // \ttype: Array,\n // \tdefault () {\n // \t\treturn [{\n // \t\t\ticon: 'shop',\n // \t\t\ttext: t(\"uni-goods-nav.options.shop\"),\n // \t\t}, {\n // \t\t\ticon: 'cart',\n // \t\t\ttext: t(\"uni-goods-nav.options.cart\")\n // \t\t}]\n // \t}\n // },\n if (appVm) {\n // 触发响应式\n appVm.$locale;\n if (!isWatchedAppLocale) {\n isWatchedAppLocale = true;\n watchAppLocale(appVm, i18n);\n }\n }\n return i18n.t(key, values);\n };\n }\n return t(key, values);\n };\n return {\n i18n,\n f(message, values, delimiters) {\n return i18n.f(message, values, delimiters);\n },\n t(key, values) {\n return t(key, values);\n },\n add(locale, message, override = true) {\n return i18n.add(locale, message, override);\n },\n watch(fn) {\n return i18n.watchLocale(fn);\n },\n getLocale() {\n return i18n.getLocale();\n },\n setLocale(newLocale) {\n return i18n.setLocale(newLocale);\n },\n };\n}\n\nconst isString = (val) => typeof val === 'string';\nlet formater;\nfunction hasI18nJson(jsonObj, delimiters) {\n if (!formater) {\n formater = new BaseFormatter();\n }\n return walkJsonObj(jsonObj, (jsonObj, key) => {\n const value = jsonObj[key];\n if (isString(value)) {\n if (isI18nStr(value, delimiters)) {\n return true;\n }\n }\n else {\n return hasI18nJson(value, delimiters);\n }\n });\n}\nfunction parseI18nJson(jsonObj, values, delimiters) {\n if (!formater) {\n formater = new BaseFormatter();\n }\n walkJsonObj(jsonObj, (jsonObj, key) => {\n const value = jsonObj[key];\n if (isString(value)) {\n if (isI18nStr(value, delimiters)) {\n jsonObj[key] = compileStr(value, values, delimiters);\n }\n }\n else {\n parseI18nJson(value, values, delimiters);\n }\n });\n return jsonObj;\n}\nfunction compileI18nJsonStr(jsonStr, { locale, locales, delimiters, }) {\n if (!isI18nStr(jsonStr, delimiters)) {\n return jsonStr;\n }\n if (!formater) {\n formater = new BaseFormatter();\n }\n const localeValues = [];\n Object.keys(locales).forEach((name) => {\n if (name !== locale) {\n localeValues.push({\n locale: name,\n values: locales[name],\n });\n }\n });\n localeValues.unshift({ locale, values: locales[locale] });\n try {\n return JSON.stringify(compileJsonObj(JSON.parse(jsonStr), localeValues, delimiters), null, 2);\n }\n catch (e) { }\n return jsonStr;\n}\nfunction isI18nStr(value, delimiters) {\n return value.indexOf(delimiters[0]) > -1;\n}\nfunction compileStr(value, values, delimiters) {\n return formater.interpolate(value, values, delimiters).join('');\n}\nfunction compileValue(jsonObj, key, localeValues, delimiters) {\n const value = jsonObj[key];\n if (isString(value)) {\n // 存在国际化\n if (isI18nStr(value, delimiters)) {\n jsonObj[key] = compileStr(value, localeValues[0].values, delimiters);\n if (localeValues.length > 1) {\n // 格式化国际化语言\n const valueLocales = (jsonObj[key + 'Locales'] = {});\n localeValues.forEach((localValue) => {\n valueLocales[localValue.locale] = compileStr(value, localValue.values, delimiters);\n });\n }\n }\n }\n else {\n compileJsonObj(value, localeValues, delimiters);\n }\n}\nfunction compileJsonObj(jsonObj, localeValues, delimiters) {\n walkJsonObj(jsonObj, (jsonObj, key) => {\n compileValue(jsonObj, key, localeValues, delimiters);\n });\n return jsonObj;\n}\nfunction walkJsonObj(jsonObj, walk) {\n if (Array.isArray(jsonObj)) {\n for (let i = 0; i < jsonObj.length; i++) {\n if (walk(jsonObj, i)) {\n return true;\n }\n }\n }\n else if (isObject(jsonObj)) {\n for (const key in jsonObj) {\n if (walk(jsonObj, key)) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction resolveLocale(locales) {\n return (locale) => {\n if (!locale) {\n return locale;\n }\n locale = normalizeLocale(locale) || locale;\n return resolveLocaleChain(locale).find((locale) => locales.indexOf(locale) > -1);\n };\n}\nfunction resolveLocaleChain(locale) {\n const chain = [];\n const tokens = locale.split('-');\n while (tokens.length) {\n chain.push(tokens.join('-'));\n tokens.pop();\n }\n return chain;\n}\n\nexport { BaseFormatter as Formatter, I18n, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT, compileI18nJsonStr, hasI18nJson, initVueI18n, isI18nStr, isString, normalizeLocale, parseI18nJson, resolveLocale };\n","import { isHTMLTag, isSVGTag, isVoidTag, isString, isFunction, isPlainObject, hyphenate, camelize, normalizeStyle as normalizeStyle$1, parseStringStyle, isArray, normalizeClass as normalizeClass$1, extend, capitalize, makeMap } from '@vue/shared';\n\nconst BUILT_IN_TAG_NAMES = [\n 'ad',\n 'ad-content-page',\n 'ad-draw',\n 'audio',\n 'button',\n 'camera',\n 'canvas',\n 'checkbox',\n 'checkbox-group',\n 'cover-image',\n 'cover-view',\n 'editor',\n 'form',\n 'functional-page-navigator',\n 'icon',\n 'image',\n 'input',\n 'label',\n 'live-player',\n 'live-pusher',\n 'map',\n 'movable-area',\n 'movable-view',\n 'navigator',\n 'official-account',\n 'open-data',\n 'picker',\n 'picker-view',\n 'picker-view-column',\n 'progress',\n 'radio',\n 'radio-group',\n 'rich-text',\n 'scroll-view',\n 'slider',\n 'swiper',\n 'swiper-item',\n 'switch',\n 'text',\n 'textarea',\n 'video',\n 'view',\n 'web-view',\n 'location-picker',\n 'location-view',\n];\nconst BUILT_IN_TAGS = BUILT_IN_TAG_NAMES.map((tag) => 'uni-' + tag);\nconst TAGS = [\n 'app',\n 'layout',\n 'content',\n 'main',\n 'top-window',\n 'left-window',\n 'right-window',\n 'tabbar',\n 'page',\n 'page-head',\n 'page-wrapper',\n 'page-body',\n 'page-refresh',\n 'actionsheet',\n 'modal',\n 'toast',\n 'resize-sensor',\n 'shadow-root',\n].map((tag) => 'uni-' + tag);\nconst NVUE_BUILT_IN_TAGS = [\n 'svg',\n 'view',\n 'a',\n 'div',\n 'img',\n 'image',\n 'text',\n 'span',\n 'input',\n 'textarea',\n 'spinner',\n 'select',\n // slider 被自定义 u-slider 替代\n // 'slider',\n 'slider-neighbor',\n 'indicator',\n 'canvas',\n 'list',\n 'cell',\n 'header',\n 'loading',\n 'loading-indicator',\n 'refresh',\n 'scrollable',\n 'scroller',\n 'video',\n 'web',\n 'embed',\n 'tabbar',\n 'tabheader',\n 'datepicker',\n 'timepicker',\n 'marquee',\n 'countdown',\n 'dc-switch',\n 'waterfall',\n 'richtext',\n 'recycle-list',\n 'u-scalable',\n 'barcode',\n 'gcanvas',\n];\nconst UVUE_BUILT_IN_TAGS = [\n 'ad',\n 'ad-content-page',\n 'ad-draw',\n 'native-view',\n 'loading-indicator',\n 'list-view',\n 'list-item',\n 'swiper',\n 'swiper-item',\n 'rich-text',\n 'sticky-view',\n 'sticky-header',\n 'sticky-section',\n // 自定义\n 'uni-slider',\n // 原生实现\n 'button',\n 'nested-scroll-header',\n 'nested-scroll-body',\n 'waterflow',\n 'flow-item',\n 'share-element',\n 'cover-view',\n 'cover-image',\n // custom element\n 'match-media',\n];\nconst UVUE_WEB_BUILT_IN_TAGS = [\n 'list-view',\n 'list-item',\n 'sticky-section',\n 'sticky-header',\n 'cloud-db-element',\n].map((tag) => 'uni-' + tag);\nconst UVUE_IOS_BUILT_IN_TAGS = [\n 'scroll-view',\n 'web-view',\n 'slider',\n 'form',\n 'switch',\n];\nconst UVUE_HARMONY_BUILT_IN_TAGS = [\n // TODO 列出完整列表\n ...BUILT_IN_TAG_NAMES,\n 'volume-panel',\n];\nconst NVUE_U_BUILT_IN_TAGS = [\n 'u-text',\n 'u-image',\n 'u-input',\n 'u-textarea',\n 'u-video',\n 'u-web-view',\n 'u-slider',\n 'u-ad',\n 'u-ad-draw',\n 'u-rich-text',\n];\nconst UVUE_WEB_BUILT_IN_CUSTOM_ELEMENTS = ['match-media'];\nconst UNI_UI_CONFLICT_TAGS = ['list-item'].map((tag) => 'uni-' + tag);\nfunction isBuiltInComponent(tag) {\n if (UNI_UI_CONFLICT_TAGS.indexOf(tag) !== -1) {\n return false;\n }\n // h5 平台会被转换为 v-uni-\n const realTag = 'uni-' + tag.replace('v-uni-', '');\n // TODO 区分x和非x\n return (BUILT_IN_TAGS.indexOf(realTag) !== -1 ||\n UVUE_WEB_BUILT_IN_TAGS.indexOf(realTag) !== -1);\n}\nfunction isH5CustomElement(tag, isX = false) {\n if (isX && UVUE_WEB_BUILT_IN_TAGS.indexOf(tag) !== -1) {\n return true;\n }\n return TAGS.indexOf(tag) !== -1 || BUILT_IN_TAGS.indexOf(tag) !== -1;\n}\nfunction isUniXElement(name) {\n return /^I?Uni.*Element(?:Impl)?$/.test(name);\n}\nfunction isH5NativeTag(tag) {\n return (tag !== 'head' &&\n (isHTMLTag(tag) || isSVGTag(tag)) &&\n !isBuiltInComponent(tag));\n}\nfunction isAppNativeTag(tag) {\n return isHTMLTag(tag) || isSVGTag(tag) || isBuiltInComponent(tag);\n}\nconst NVUE_CUSTOM_COMPONENTS = [\n 'ad',\n 'ad-draw',\n 'button',\n 'checkbox-group',\n 'checkbox',\n 'form',\n 'icon',\n 'label',\n 'movable-area',\n 'movable-view',\n 'navigator',\n 'picker',\n 'progress',\n 'radio-group',\n 'radio',\n 'rich-text',\n 'swiper-item',\n 'swiper',\n 'switch',\n 'slider',\n 'picker-view',\n 'picker-view-column',\n];\n// 内置的easycom组件\nconst UVUE_BUILT_IN_EASY_COMPONENTS = [\n 'map',\n 'camera',\n 'live-player',\n 'live-pusher',\n];\nfunction isAppUVueBuiltInEasyComponent(tag) {\n return UVUE_BUILT_IN_EASY_COMPONENTS.includes(tag);\n}\n// 主要是指前端实现的组件列表\nconst UVUE_CUSTOM_COMPONENTS = [\n ...NVUE_CUSTOM_COMPONENTS,\n ...UVUE_BUILT_IN_EASY_COMPONENTS,\n];\nfunction isAppUVueNativeTag(tag) {\n // 前端实现的内置组件都会注册一个根组件\n if (tag.startsWith('uni-') && tag.endsWith('-element')) {\n return true;\n }\n if (UVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (UVUE_CUSTOM_COMPONENTS.includes(tag)) {\n return false;\n }\n if (isBuiltInComponent(tag)) {\n return true;\n }\n // u-text,u-video...\n if (NVUE_U_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n return false;\n}\nfunction isAppIOSUVueNativeTag(tag) {\n // 前端实现的内置组件都会注册一个根组件\n if (tag.startsWith('uni-') && tag.endsWith('-element')) {\n return true;\n }\n if (NVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (UVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (UVUE_IOS_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n return false;\n}\nfunction isAppHarmonyUVueNativeTag(tag) {\n // video 目前是easycom实现的\n if (tag === 'video' || tag === 'map') {\n return false;\n }\n // 前端实现的内置组件都会注册一个根组件\n if (tag.startsWith('uni-') && tag.endsWith('-element')) {\n return true;\n }\n if (NVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (UVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (UVUE_HARMONY_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n return false;\n}\nfunction isAppNVueNativeTag(tag) {\n if (NVUE_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n if (NVUE_CUSTOM_COMPONENTS.includes(tag)) {\n return false;\n }\n if (isBuiltInComponent(tag)) {\n return true;\n }\n // u-text,u-video...\n if (NVUE_U_BUILT_IN_TAGS.includes(tag)) {\n return true;\n }\n return false;\n}\nfunction isMiniProgramNativeTag(tag) {\n return isBuiltInComponent(tag);\n}\nfunction isMiniProgramUVueNativeTag(tag) {\n // 小程序平台内置的自定义元素,会被转换为 view\n if (tag.startsWith('uni-') && tag.endsWith('-element')) {\n return true;\n }\n return isBuiltInComponent(tag);\n}\nfunction createIsCustomElement(tags = []) {\n return function isCustomElement(tag) {\n return tags.includes(tag);\n };\n}\nfunction isComponentTag(tag) {\n return tag[0].toLowerCase() + tag.slice(1) === 'component';\n}\nconst COMPONENT_SELECTOR_PREFIX = 'uni-';\nconst COMPONENT_PREFIX = 'v-' + COMPONENT_SELECTOR_PREFIX;\n// TODO 是否还存在其他需要特殊处理的 void 标签?\nconst APP_VOID_TAGS = ['textarea'];\nfunction isAppVoidTag(tag) {\n return APP_VOID_TAGS.includes(tag) || isVoidTag(tag);\n}\n\nconst LINEFEED = '\\n';\nconst NAVBAR_HEIGHT = 44;\nconst TABBAR_HEIGHT = 50;\nconst ON_REACH_BOTTOM_DISTANCE = 50;\nconst RESPONSIVE_MIN_WIDTH = 768;\nconst UNI_STORAGE_LOCALE = 'UNI_LOCALE';\n// quickapp-webview 不能使用 default 作为插槽名称\nconst SLOT_DEFAULT_NAME = 'd';\nconst COMPONENT_NAME_PREFIX = 'VUni';\nconst I18N_JSON_DELIMITERS = ['%', '%'];\nconst PRIMARY_COLOR = '#007aff';\nconst SELECTED_COLOR = '#0062cc'; // 选中的颜色,如选项卡默认的选中颜色\nconst BACKGROUND_COLOR = '#f7f7f7'; // 背景色,如标题栏默认背景色\nconst UNI_SSR = '__uniSSR';\nconst UNI_SSR_TITLE = 'title';\nconst UNI_SSR_STORE = 'store';\nconst UNI_SSR_DATA = 'data';\nconst UNI_SSR_GLOBAL_DATA = 'globalData';\nconst SCHEME_RE = /^([a-z-]+:)?\\/\\//i;\nconst DATA_RE = /^data:.*,.*/;\nconst WEB_INVOKE_APPSERVICE = 'WEB_INVOKE_APPSERVICE';\nconst WXS_PROTOCOL = 'wxs://';\nconst JSON_PROTOCOL = 'json://';\nconst WXS_MODULES = 'wxsModules';\nconst RENDERJS_MODULES = 'renderjsModules';\n// lifecycle\n// App and Page\nconst ON_SHOW = 'onShow';\nconst ON_HIDE = 'onHide';\n//App\nconst ON_LAUNCH = 'onLaunch';\nconst ON_ERROR = 'onError';\nconst ON_THEME_CHANGE = 'onThemeChange';\nconst OFF_THEME_CHANGE = 'offThemeChange';\nconst ON_HOST_THEME_CHANGE = 'onHostThemeChange';\nconst OFF_HOST_THEME_CHANGE = 'offHostThemeChange';\nconst ON_KEYBOARD_HEIGHT_CHANGE = 'onKeyboardHeightChange';\nconst ON_PAGE_NOT_FOUND = 'onPageNotFound';\nconst ON_UNHANDLE_REJECTION = 'onUnhandledRejection';\nconst ON_LAST_PAGE_BACK_PRESS = 'onLastPageBackPress';\nconst ON_EXIT = 'onExit';\n//Page\nconst ON_LOAD = 'onLoad';\nconst ON_READY = 'onReady';\nconst ON_UNLOAD = 'onUnload';\n// 百度特有\nconst ON_INIT = 'onInit';\n// 微信特有\nconst ON_SAVE_EXIT_STATE = 'onSaveExitState';\nconst ON_RESIZE = 'onResize';\nconst ON_BACK_PRESS = 'onBackPress';\nconst ON_PAGE_SCROLL = 'onPageScroll';\nconst ON_TAB_ITEM_TAP = 'onTabItemTap';\nconst ON_REACH_BOTTOM = 'onReachBottom';\nconst ON_PULL_DOWN_REFRESH = 'onPullDownRefresh';\nconst ON_SHARE_TIMELINE = 'onShareTimeline';\nconst ON_SHARE_CHAT = 'onShareChat'; // xhs-share\nconst ON_ADD_TO_FAVORITES = 'onAddToFavorites';\nconst ON_SHARE_APP_MESSAGE = 'onShareAppMessage';\n// navigationBar\nconst ON_NAVIGATION_BAR_BUTTON_TAP = 'onNavigationBarButtonTap';\nconst ON_NAVIGATION_BAR_CHANGE = 'onNavigationBarChange';\nconst ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED = 'onNavigationBarSearchInputClicked';\nconst ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED = 'onNavigationBarSearchInputChanged';\nconst ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED = 'onNavigationBarSearchInputConfirmed';\nconst ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED = 'onNavigationBarSearchInputFocusChanged';\n// framework\nconst ON_APP_ENTER_FOREGROUND = 'onAppEnterForeground';\nconst ON_APP_ENTER_BACKGROUND = 'onAppEnterBackground';\nconst ON_WEB_INVOKE_APP_SERVICE = 'onWebInvokeAppService';\nconst ON_WXS_INVOKE_CALL_METHOD = 'onWxsInvokeCallMethod';\n// mergeVirtualHostAttributes\nconst VIRTUAL_HOST_STYLE = 'virtualHostStyle';\nconst VIRTUAL_HOST_CLASS = 'virtualHostClass';\nconst VIRTUAL_HOST_HIDDEN = 'virtualHostHidden';\nconst VIRTUAL_HOST_ID = 'virtualHostId';\n\nfunction cache(fn) {\n const cache = Object.create(null);\n return (str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n };\n}\nfunction cacheStringFunction(fn) {\n return cache(fn);\n}\nfunction getLen(str = '') {\n return ('' + str).replace(/[^\\x00-\\xff]/g, '**').length;\n}\nfunction hasLeadingSlash(str) {\n return str.indexOf('/') === 0;\n}\nfunction addLeadingSlash(str) {\n return hasLeadingSlash(str) ? str : '/' + str;\n}\nfunction removeLeadingSlash(str) {\n return hasLeadingSlash(str) ? str.slice(1) : str;\n}\nconst invokeArrayFns = (fns, arg) => {\n let ret;\n for (let i = 0; i < fns.length; i++) {\n ret = fns[i](arg);\n }\n return ret;\n};\nfunction updateElementStyle(element, styles) {\n for (const attrName in styles) {\n element.style[attrName] = styles[attrName];\n }\n}\nfunction once(fn, ctx = null) {\n let res;\n return ((...args) => {\n if (fn) {\n res = fn.apply(ctx, args);\n fn = null;\n }\n return res;\n });\n}\nconst sanitise = (val) => (val && JSON.parse(JSON.stringify(val))) || val;\nconst _completeValue = (value) => (value > 9 ? value : '0' + value);\nfunction formatDateTime({ date = new Date(), mode = 'date' }) {\n if (mode === 'time') {\n return (_completeValue(date.getHours()) + ':' + _completeValue(date.getMinutes()));\n }\n else {\n return (date.getFullYear() +\n '-' +\n _completeValue(date.getMonth() + 1) +\n '-' +\n _completeValue(date.getDate()));\n }\n}\nfunction callOptions(options, data) {\n options = options || {};\n if (isString(data)) {\n data = {\n errMsg: data,\n };\n }\n if (/:ok$/.test(data.errMsg)) {\n if (isFunction(options.success)) {\n options.success(data);\n }\n }\n else {\n if (isFunction(options.fail)) {\n options.fail(data);\n }\n }\n if (isFunction(options.complete)) {\n options.complete(data);\n }\n}\nfunction getValueByDataPath(obj, path) {\n if (!isString(path)) {\n return;\n }\n path = path.replace(/\\[(\\d+)\\]/g, '.$1');\n const parts = path.split('.');\n let key = parts[0];\n if (!obj) {\n obj = {};\n }\n if (parts.length === 1) {\n return obj[key];\n }\n return getValueByDataPath(obj[key], parts.slice(1).join('.'));\n}\nfunction sortObject(obj) {\n let sortObj = {};\n if (isPlainObject(obj)) {\n Object.keys(obj)\n .sort()\n .forEach((key) => {\n const _key = key;\n sortObj[_key] = obj[_key];\n });\n }\n return !Object.keys(sortObj) ? obj : sortObj;\n}\nfunction getGlobalOnce() {\n if (typeof globalThis !== 'undefined') {\n return globalThis;\n }\n // worker\n if (typeof self !== 'undefined') {\n return self;\n }\n // browser\n if (typeof window !== 'undefined') {\n return window;\n }\n // nodejs\n // if (typeof global !== 'undefined') {\n // return global\n // }\n function g() {\n return this;\n }\n if (typeof g() !== 'undefined') {\n return g();\n }\n return (function () {\n return new Function('return this')();\n })();\n}\nlet g = undefined;\nfunction getGlobal() {\n if (g) {\n return g;\n }\n g = getGlobalOnce();\n return g;\n}\n\nfunction isComponentInternalInstance(vm) {\n return !!vm.appContext;\n}\nfunction resolveComponentInstance(instance) {\n return (instance &&\n (isComponentInternalInstance(instance) ? instance.proxy : instance));\n}\nfunction resolveOwnerVm(vm) {\n if (!vm) {\n return;\n }\n let componentName = vm.type.name;\n while (componentName && isBuiltInComponent(hyphenate(componentName))) {\n // ownerInstance 内置组件需要使用父 vm\n vm = vm.parent;\n componentName = vm.type.name;\n }\n return vm.proxy;\n}\nfunction isElement(el) {\n // Element\n return el.nodeType === 1;\n}\nfunction resolveOwnerEl(instance, multi = false) {\n const { vnode } = instance;\n if (isElement(vnode.el)) {\n return multi ? (vnode.el ? [vnode.el] : []) : vnode.el;\n }\n const { subTree } = instance;\n // ShapeFlags.ARRAY_CHILDREN = 1<<4\n if (subTree.shapeFlag & 16) {\n const elemVNodes = subTree.children.filter((vnode) => vnode.el && isElement(vnode.el));\n if (elemVNodes.length > 0) {\n if (multi) {\n return elemVNodes.map((node) => node.el);\n }\n return elemVNodes[0].el;\n }\n }\n return multi ? (vnode.el ? [vnode.el] : []) : vnode.el;\n}\nfunction dynamicSlotName(name) {\n return name === 'default' ? SLOT_DEFAULT_NAME : name;\n}\nconst customizeRE = /:/g;\nfunction customizeEvent(str) {\n return camelize(str.replace(customizeRE, '-'));\n}\nfunction normalizeStyle(value) {\n const g = getGlobal();\n if (g && g.UTSJSONObject && value instanceof g.UTSJSONObject) {\n const styleObject = {};\n g.UTSJSONObject.keys(value).forEach((key) => {\n styleObject[key] = value[key];\n });\n return normalizeStyle$1(styleObject);\n }\n else if (value instanceof Map) {\n const styleObject = {};\n value.forEach((value, key) => {\n styleObject[key] = value;\n });\n return normalizeStyle$1(styleObject);\n }\n else if (isString(value)) {\n return parseStringStyle(value);\n }\n else if (isArray(value)) {\n const res = {};\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n const normalized = isString(item)\n ? parseStringStyle(item)\n : normalizeStyle(item);\n if (normalized) {\n for (const key in normalized) {\n res[key] = normalized[key];\n }\n }\n }\n return res;\n }\n else {\n return normalizeStyle$1(value);\n }\n}\nfunction normalizeClass(value) {\n let res = '';\n const g = getGlobal();\n if (g && g.UTSJSONObject && value instanceof g.UTSJSONObject) {\n g.UTSJSONObject.keys(value).forEach((key) => {\n if (value[key]) {\n res += key + ' ';\n }\n });\n }\n else if (value instanceof Map) {\n value.forEach((value, key) => {\n if (value) {\n res += key + ' ';\n }\n });\n }\n else if (isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const normalized = normalizeClass(value[i]);\n if (normalized) {\n res += normalized + ' ';\n }\n }\n }\n else {\n res = normalizeClass$1(value);\n }\n return res.trim();\n}\nfunction normalizeProps(props) {\n if (!props)\n return null;\n let { class: klass, style } = props;\n if (klass && !isString(klass)) {\n props.class = normalizeClass(klass);\n }\n if (style) {\n props.style = normalizeStyle(style);\n }\n return props;\n}\n\nlet lastLogTime = 0;\nfunction formatLog(module, ...args) {\n const now = Date.now();\n const diff = lastLogTime ? now - lastLogTime : 0;\n lastLogTime = now;\n return `[${now}][${diff}ms][${module}]:${args\n .map((arg) => JSON.stringify(arg))\n .join(' ')}`;\n}\n\nfunction formatKey(key) {\n return camelize(key.substring(5));\n}\n// question/139181,增加副作用,避免 initCustomDataset 在 build 下被 tree-shaking\nconst initCustomDatasetOnce = /*#__PURE__*/ once((isBuiltInElement) => {\n isBuiltInElement =\n isBuiltInElement || ((el) => el.tagName.startsWith('UNI-'));\n const prototype = HTMLElement.prototype;\n const setAttribute = prototype.setAttribute;\n prototype.setAttribute = function (key, value) {\n if (key.startsWith('data-') && isBuiltInElement(this)) {\n const dataset = this.__uniDataset ||\n (this.__uniDataset = {});\n dataset[formatKey(key)] = value;\n }\n setAttribute.call(this, key, value);\n };\n const removeAttribute = prototype.removeAttribute;\n prototype.removeAttribute = function (key) {\n if (this.__uniDataset &&\n key.startsWith('data-') &&\n isBuiltInElement(this)) {\n delete this.__uniDataset[formatKey(key)];\n }\n removeAttribute.call(this, key);\n };\n});\nfunction getCustomDataset(el) {\n return extend({}, el.dataset, el.__uniDataset);\n}\n\nconst unitRE = new RegExp(`\"[^\"]+\"|'[^']+'|url\\\\([^)]+\\\\)|(\\\\d*\\\\.?\\\\d+)[r|u]px`, 'g');\nfunction toFixed(number, precision) {\n const multiplier = Math.pow(10, precision + 1);\n const wholeNumber = Math.floor(number * multiplier);\n return (Math.round(wholeNumber / 10) * 10) / multiplier;\n}\nconst defaultRpx2Unit = {\n unit: 'rem',\n unitRatio: 10 / 320,\n unitPrecision: 5,\n};\nconst defaultMiniProgramRpx2Unit = {\n unit: 'rpx',\n unitRatio: 1,\n unitPrecision: 1,\n};\nconst defaultNVueRpx2Unit = defaultMiniProgramRpx2Unit;\nfunction createRpx2Unit(unit, unitRatio, unitPrecision) {\n // ignore: rpxCalcIncludeWidth\n return (val) => val.replace(unitRE, (m, $1) => {\n if (!$1) {\n return m;\n }\n if (unitRatio === 1) {\n return `${$1}${unit}`;\n }\n const value = toFixed(parseFloat($1) * unitRatio, unitPrecision);\n return value === 0 ? '0' : `${value}${unit}`;\n });\n}\n\nfunction passive(passive) {\n return { passive };\n}\nfunction normalizeDataset(el) {\n // TODO\n return JSON.parse(JSON.stringify(el.dataset || {}));\n}\nfunction normalizeTarget(el) {\n const { id, offsetTop, offsetLeft } = el;\n return {\n id,\n dataset: getCustomDataset(el),\n offsetTop,\n offsetLeft,\n };\n}\nfunction addFont(family, source, desc) {\n const fonts = document.fonts;\n if (fonts) {\n const fontFace = new FontFace(family, source, desc);\n return fontFace.load().then(() => {\n fonts.add && fonts.add(fontFace);\n });\n }\n return new Promise((resolve) => {\n const style = document.createElement('style');\n const values = [];\n if (desc) {\n const { style, weight, stretch, unicodeRange, variant, featureSettings } = desc;\n style && values.push(`font-style:${style}`);\n weight && values.push(`font-weight:${weight}`);\n stretch && values.push(`font-stretch:${stretch}`);\n unicodeRange && values.push(`unicode-range:${unicodeRange}`);\n variant && values.push(`font-variant:${variant}`);\n featureSettings && values.push(`font-feature-settings:${featureSettings}`);\n }\n style.innerText = `@font-face{font-family:\"${family}\";src:${source};${values.join(';')}}`;\n document.head.appendChild(style);\n resolve();\n });\n}\nfunction scrollTo(scrollTop, duration, isH5) {\n if (isString(scrollTop)) {\n const el = document.querySelector(scrollTop);\n if (el) {\n const { top } = el.getBoundingClientRect();\n scrollTop = top + window.pageYOffset;\n // 如果存在,减去 高度\n const pageHeader = document.querySelector('uni-page-head');\n if (pageHeader) {\n scrollTop -= pageHeader.offsetHeight;\n }\n }\n }\n if (scrollTop < 0) {\n scrollTop = 0;\n }\n const documentElement = document.documentElement;\n const { clientHeight, scrollHeight } = documentElement;\n scrollTop = Math.min(scrollTop, scrollHeight - clientHeight);\n if (duration === 0) {\n // 部分浏览器(比如微信)中 scrollTop 的值需要通过 document.body 来控制\n documentElement.scrollTop = document.body.scrollTop = scrollTop;\n return;\n }\n if (window.scrollY === scrollTop) {\n return;\n }\n const scrollTo = (duration) => {\n if (duration <= 0) {\n window.scrollTo(0, scrollTop);\n return;\n }\n const distaince = scrollTop - window.scrollY;\n requestAnimationFrame(function () {\n window.scrollTo(0, window.scrollY + (distaince / duration) * 10);\n scrollTo(duration - 10);\n });\n };\n scrollTo(duration);\n}\n\nconst encode = encodeURIComponent;\nfunction stringifyQuery(obj, encodeStr = encode) {\n const res = obj\n ? Object.keys(obj)\n .map((key) => {\n let val = obj[key];\n if (typeof val === undefined || val === null) {\n val = '';\n }\n else if (isPlainObject(val)) {\n val = JSON.stringify(val);\n }\n return encodeStr(key) + '=' + encodeStr(val);\n })\n .filter((x) => x.length > 0)\n .join('&')\n : null;\n return res ? `?${res}` : '';\n}\n/**\n * Decode text using `decodeURIComponent`. Returns the original text if it\n * fails.\n *\n * @param text - string to decode\n * @returns decoded string\n */\nfunction decode(text) {\n try {\n return decodeURIComponent('' + text);\n }\n catch (err) { }\n return '' + text;\n}\nfunction decodedQuery(query = {}) {\n const decodedQuery = {};\n Object.keys(query).forEach((name) => {\n try {\n decodedQuery[name] = decode(query[name]);\n }\n catch (e) {\n decodedQuery[name] = query[name];\n }\n });\n return decodedQuery;\n}\nconst PLUS_RE = /\\+/g; // %2B\n/**\n * https://github.com/vuejs/vue-router-next/blob/master/src/query.ts\n * @internal\n *\n * @param search - search string to parse\n * @returns a query object\n */\nfunction parseQuery(search) {\n const query = {};\n // avoid creating an object with an empty key and empty value\n // because of split('&')\n if (search === '' || search === '?')\n return query;\n const hasLeadingIM = search[0] === '?';\n const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&');\n for (let i = 0; i < searchParams.length; ++i) {\n // pre decode the + into space\n const searchParam = searchParams[i].replace(PLUS_RE, ' ');\n // allow the = character\n let eqPos = searchParam.indexOf('=');\n let key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));\n let value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));\n if (key in query) {\n // an extra variable for ts types\n let currentValue = query[key];\n if (!isArray(currentValue)) {\n currentValue = query[key] = [currentValue];\n }\n currentValue.push(value);\n }\n else {\n query[key] = value;\n }\n }\n return query;\n}\n\nfunction parseUrl(url) {\n const [path, querystring] = url.split('?', 2);\n return {\n path,\n query: parseQuery(querystring || ''),\n };\n}\n\nfunction parseNVueDataset(attr) {\n const dataset = {};\n if (attr) {\n Object.keys(attr).forEach((key) => {\n if (key.indexOf('data-') === 0) {\n dataset[key.replace('data-', '')] = attr[key];\n }\n });\n }\n return dataset;\n}\n\nfunction plusReady(callback) {\n if (!isFunction(callback)) {\n return;\n }\n if (window.plus) {\n return callback();\n }\n document.addEventListener('plusready', callback);\n}\n\nclass DOMException extends Error {\n constructor(message) {\n super(message);\n this.name = 'DOMException';\n }\n}\n\nfunction normalizeEventType(type, options) {\n if (options) {\n if (options.capture) {\n type += 'Capture';\n }\n if (options.once) {\n type += 'Once';\n }\n if (options.passive) {\n type += 'Passive';\n }\n }\n return `on${capitalize(camelize(type))}`;\n}\nclass UniEvent {\n constructor(type, opts) {\n this.defaultPrevented = false;\n this.timeStamp = Date.now();\n this._stop = false;\n this._end = false;\n this.type = type;\n this.bubbles = !!opts.bubbles;\n this.cancelable = !!opts.cancelable;\n }\n preventDefault() {\n this.defaultPrevented = true;\n }\n stopImmediatePropagation() {\n this._end = this._stop = true;\n }\n stopPropagation() {\n this._stop = true;\n }\n}\nfunction createUniEvent(evt) {\n if (evt instanceof UniEvent) {\n return evt;\n }\n const [type] = parseEventName(evt.type);\n const uniEvent = new UniEvent(type, {\n bubbles: false,\n cancelable: false,\n });\n extend(uniEvent, evt);\n return uniEvent;\n}\nclass UniEventTarget {\n constructor() {\n this.listeners = Object.create(null);\n }\n dispatchEvent(evt) {\n const listeners = this.listeners[evt.type];\n if (!listeners) {\n if ((process.env.NODE_ENV !== 'production')) {\n console.error(formatLog('dispatchEvent', this.nodeId), evt.type, 'not found');\n }\n return false;\n }\n // 格式化事件类型\n const event = createUniEvent(evt);\n const len = listeners.length;\n for (let i = 0; i < len; i++) {\n listeners[i].call(this, event);\n if (event._end) {\n break;\n }\n }\n return event.cancelable && event.defaultPrevented;\n }\n addEventListener(type, listener, options) {\n type = normalizeEventType(type, options);\n (this.listeners[type] || (this.listeners[type] = [])).push(listener);\n }\n removeEventListener(type, callback, options) {\n type = normalizeEventType(type, options);\n const listeners = this.listeners[type];\n if (!listeners) {\n return;\n }\n const index = listeners.indexOf(callback);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n}\nconst optionsModifierRE = /(?:Once|Passive|Capture)$/;\nfunction parseEventName(name) {\n let options;\n if (optionsModifierRE.test(name)) {\n options = {};\n let m;\n while ((m = name.match(optionsModifierRE))) {\n name = name.slice(0, name.length - m[0].length);\n options[m[0].toLowerCase()] = true;\n }\n }\n return [hyphenate(name.slice(2)), options];\n}\n\nconst EventModifierFlags = /*#__PURE__*/ (() => {\n return {\n stop: 1,\n prevent: 1 << 1,\n self: 1 << 2,\n };\n})();\nfunction encodeModifier(modifiers) {\n let flag = 0;\n if (modifiers.includes('stop')) {\n flag |= EventModifierFlags.stop;\n }\n if (modifiers.includes('prevent')) {\n flag |= EventModifierFlags.prevent;\n }\n if (modifiers.includes('self')) {\n flag |= EventModifierFlags.self;\n }\n return flag;\n}\n\nconst NODE_TYPE_PAGE = 0;\nconst NODE_TYPE_ELEMENT = 1;\nconst NODE_TYPE_TEXT = 3;\nconst NODE_TYPE_COMMENT = 8;\nfunction sibling(node, type) {\n const { parentNode } = node;\n if (!parentNode) {\n return null;\n }\n const { childNodes } = parentNode;\n return childNodes[childNodes.indexOf(node) + (type === 'n' ? 1 : -1)] || null;\n}\nfunction removeNode(node) {\n const { parentNode } = node;\n if (parentNode) {\n const { childNodes } = parentNode;\n const index = childNodes.indexOf(node);\n if (index > -1) {\n node.parentNode = null;\n childNodes.splice(index, 1);\n }\n }\n}\nfunction checkNodeId(node) {\n if (!node.nodeId && node.pageNode) {\n node.nodeId = node.pageNode.genId();\n }\n}\n// 为优化性能,各平台不使用proxy来实现node的操作拦截,而是直接通过pageNode定制\nclass UniNode extends UniEventTarget {\n constructor(nodeType, nodeName, container) {\n super();\n this.pageNode = null;\n this.parentNode = null;\n this._text = null;\n if (container) {\n const { pageNode } = container;\n if (pageNode) {\n this.pageNode = pageNode;\n this.nodeId = pageNode.genId();\n !pageNode.isUnmounted && pageNode.onCreate(this, nodeName);\n }\n }\n this.nodeType = nodeType;\n this.nodeName = nodeName;\n this.childNodes = [];\n }\n get firstChild() {\n return this.childNodes[0] || null;\n }\n get lastChild() {\n const { childNodes } = this;\n const length = childNodes.length;\n return length ? childNodes[length - 1] : null;\n }\n get nextSibling() {\n return sibling(this, 'n');\n }\n get nodeValue() {\n return null;\n }\n set nodeValue(_val) { }\n get textContent() {\n return this._text || '';\n }\n set textContent(text) {\n this._text = text;\n if (this.pageNode && !this.pageNode.isUnmounted) {\n this.pageNode.onTextContent(this, text);\n }\n }\n get parentElement() {\n const { parentNode } = this;\n if (parentNode && parentNode.nodeType === NODE_TYPE_ELEMENT) {\n return parentNode;\n }\n return null;\n }\n get previousSibling() {\n return sibling(this, 'p');\n }\n appendChild(newChild) {\n return this.insertBefore(newChild, null);\n }\n cloneNode(deep) {\n const cloned = extend(Object.create(Object.getPrototypeOf(this)), this);\n const { attributes } = cloned;\n if (attributes) {\n cloned.attributes = extend({}, attributes);\n }\n if (deep) {\n cloned.childNodes = cloned.childNodes.map((childNode) => childNode.cloneNode(true));\n }\n return cloned;\n }\n insertBefore(newChild, refChild) {\n // 先从现在的父节点移除(注意:不能触发onRemoveChild,否则会生成先remove该 id,再 insert)\n removeNode(newChild);\n newChild.pageNode = this.pageNode;\n newChild.parentNode = this;\n checkNodeId(newChild);\n const { childNodes } = this;\n if (refChild) {\n const index = childNodes.indexOf(refChild);\n if (index === -1) {\n throw new DOMException(`Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.`);\n }\n childNodes.splice(index, 0, newChild);\n }\n else {\n childNodes.push(newChild);\n }\n return this.pageNode && !this.pageNode.isUnmounted\n ? this.pageNode.onInsertBefore(this, newChild, refChild)\n : newChild;\n }\n removeChild(oldChild) {\n const { childNodes } = this;\n const index = childNodes.indexOf(oldChild);\n if (index === -1) {\n throw new DOMException(`Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.`);\n }\n oldChild.parentNode = null;\n childNodes.splice(index, 1);\n return this.pageNode && !this.pageNode.isUnmounted\n ? this.pageNode.onRemoveChild(oldChild)\n : oldChild;\n }\n}\nconst ATTR_CLASS = 'class';\nconst ATTR_STYLE = 'style';\nconst ATTR_INNER_HTML = 'innerHTML';\nconst ATTR_TEXT_CONTENT = 'textContent';\nconst ATTR_V_SHOW = '.vShow';\nconst ATTR_V_OWNER_ID = '.vOwnerId';\nconst ATTR_V_RENDERJS = '.vRenderjs';\nconst ATTR_CHANGE_PREFIX = 'change:';\nclass UniBaseNode extends UniNode {\n constructor(nodeType, nodeName, container) {\n super(nodeType, nodeName, container);\n this.attributes = Object.create(null);\n this.style = null;\n this.vShow = null;\n this._html = null;\n }\n get className() {\n return (this.attributes[ATTR_CLASS] || '');\n }\n set className(val) {\n this.setAttribute(ATTR_CLASS, val);\n }\n get innerHTML() {\n return '';\n }\n set innerHTML(html) {\n this._html = html;\n }\n addEventListener(type, listener, options) {\n super.addEventListener(type, listener, options);\n if (this.pageNode && !this.pageNode.isUnmounted) {\n if (listener.wxsEvent) {\n this.pageNode.onAddWxsEvent(this, normalizeEventType(type, options), listener.wxsEvent, encodeModifier(listener.modifiers || []));\n }\n else {\n this.pageNode.onAddEvent(this, normalizeEventType(type, options), encodeModifier(listener.modifiers || []));\n }\n }\n }\n removeEventListener(type, callback, options) {\n super.removeEventListener(type, callback, options);\n if (this.pageNode && !this.pageNode.isUnmounted) {\n this.pageNode.onRemoveEvent(this, normalizeEventType(type, options));\n }\n }\n getAttribute(qualifiedName) {\n if (qualifiedName === ATTR_STYLE) {\n return this.style;\n }\n return this.attributes[qualifiedName];\n }\n removeAttribute(qualifiedName) {\n if (qualifiedName == ATTR_STYLE) {\n this.style = null;\n }\n else {\n delete this.attributes[qualifiedName];\n }\n if (this.pageNode && !this.pageNode.isUnmounted) {\n this.pageNode.onRemoveAttribute(this, qualifiedName);\n }\n }\n setAttribute(qualifiedName, value) {\n if (qualifiedName === ATTR_STYLE) {\n this.style = value;\n }\n else {\n this.attributes[qualifiedName] = value;\n }\n if (this.pageNode && !this.pageNode.isUnmounted) {\n this.pageNode.onSetAttribute(this, qualifiedName, value);\n }\n }\n toJSON({ attr, normalize, } = {}) {\n const { attributes, style, listeners, _text } = this;\n const res = {};\n if (Object.keys(attributes).length) {\n res.a = normalize ? normalize(attributes) : attributes;\n }\n const events = Object.keys(listeners);\n if (events.length) {\n let w = undefined;\n const e = {};\n events.forEach((name) => {\n const handlers = listeners[name];\n if (handlers.length) {\n // 可能存在多个 handler 且不同 modifiers 吗?\n const { wxsEvent, modifiers } = handlers[0];\n const modifier = encodeModifier(modifiers || []);\n if (!wxsEvent) {\n e[name] = modifier;\n }\n else {\n if (!w) {\n w = {};\n }\n w[name] = [normalize ? normalize(wxsEvent) : wxsEvent, modifier];\n }\n }\n });\n res.e = normalize ? normalize(e, false) : e;\n if (w) {\n res.w = normalize ? normalize(w, false) : w;\n }\n }\n if (style !== null) {\n res.s = normalize ? normalize(style) : style;\n }\n if (!attr) {\n res.i = this.nodeId;\n res.n = this.nodeName;\n }\n if (_text !== null) {\n res.t = normalize ? normalize(_text) : _text;\n }\n return res;\n }\n}\n\nclass UniCommentNode extends UniNode {\n constructor(text, container) {\n super(NODE_TYPE_COMMENT, '#comment', container);\n this._text = (process.env.NODE_ENV !== 'production') ? text : '';\n }\n toJSON(opts = {}) {\n // 暂时不传递 text 到 view 层,没啥意义,节省点数据量\n return opts.attr\n ? {}\n : {\n i: this.nodeId,\n };\n // return opts.attr\n // ? { t: this._text as string }\n // : {\n // i: this.nodeId!,\n // t: this._text as string,\n // }\n }\n}\n\nclass UniElement extends UniBaseNode {\n constructor(nodeName, container) {\n super(NODE_TYPE_ELEMENT, nodeName.toUpperCase(), container);\n this.tagName = this.nodeName;\n }\n}\nclass UniInputElement extends UniElement {\n get value() {\n return this.getAttribute('value');\n }\n set value(val) {\n this.setAttribute('value', val);\n }\n}\nclass UniTextAreaElement extends UniInputElement {\n}\n\nclass UniTextNode extends UniBaseNode {\n constructor(text, container) {\n super(NODE_TYPE_TEXT, '#text', container);\n this._text = text;\n }\n get nodeValue() {\n return this._text || '';\n }\n set nodeValue(text) {\n this._text = text;\n if (this.pageNode && !this.pageNode.isUnmounted) {\n this.pageNode.onNodeValue(this, text);\n }\n }\n}\n\nconst forcePatchProps = {\n AD: ['data'],\n 'AD-DRAW': ['data'],\n 'LIVE-PLAYER': ['picture-in-picture-mode'],\n MAP: [\n 'markers',\n 'polyline',\n 'circles',\n 'controls',\n 'include-points',\n 'polygons',\n ],\n PICKER: ['range', 'value'],\n 'PICKER-VIEW': ['value'],\n 'RICH-TEXT': ['nodes'],\n VIDEO: ['danmu-list', 'header'],\n 'WEB-VIEW': ['webview-styles'],\n};\nconst forcePatchPropKeys = ['animation'];\n\nconst forcePatchProp = (el, key) => {\n if (forcePatchPropKeys.indexOf(key) > -1) {\n return true;\n }\n const keys = forcePatchProps[el.nodeName];\n if (keys && keys.indexOf(key) > -1) {\n return true;\n }\n return false;\n};\n\nconst ACTION_TYPE_PAGE_CREATE = 1;\nconst ACTION_TYPE_PAGE_CREATED = 2;\nconst ACTION_TYPE_CREATE = 3;\nconst ACTION_TYPE_INSERT = 4;\nconst ACTION_TYPE_REMOVE = 5;\nconst ACTION_TYPE_SET_ATTRIBUTE = 6;\nconst ACTION_TYPE_REMOVE_ATTRIBUTE = 7;\nconst ACTION_TYPE_ADD_EVENT = 8;\nconst ACTION_TYPE_REMOVE_EVENT = 9;\nconst ACTION_TYPE_SET_TEXT = 10;\nconst ACTION_TYPE_ADD_WXS_EVENT = 12;\nconst ACTION_TYPE_PAGE_SCROLL = 15;\nconst ACTION_TYPE_EVENT = 20;\n\n/**\n * 需要手动传入 timer,主要是解决 App 平台的定制 timer\n */\nfunction debounce(fn, delay, { clearTimeout, setTimeout }) {\n let timeout;\n const newFn = function () {\n clearTimeout(timeout);\n const timerFn = () => fn.apply(this, arguments);\n timeout = setTimeout(timerFn, delay);\n };\n newFn.cancel = function () {\n clearTimeout(timeout);\n };\n return newFn;\n}\n\nclass EventChannel {\n constructor(id, events) {\n this.id = id;\n this.listener = {};\n this.emitCache = [];\n if (events) {\n Object.keys(events).forEach((name) => {\n this.on(name, events[name]);\n });\n }\n }\n emit(eventName, ...args) {\n const fns = this.listener[eventName];\n if (!fns) {\n return this.emitCache.push({\n eventName,\n args,\n });\n }\n fns.forEach((opt) => {\n opt.fn.apply(opt.fn, args);\n });\n this.listener[eventName] = fns.filter((opt) => opt.type !== 'once');\n }\n on(eventName, fn) {\n this._addListener(eventName, 'on', fn);\n this._clearCache(eventName);\n }\n once(eventName, fn) {\n this._addListener(eventName, 'once', fn);\n this._clearCache(eventName);\n }\n off(eventName, fn) {\n const fns = this.listener[eventName];\n if (!fns) {\n return;\n }\n if (fn) {\n for (let i = 0; i < fns.length;) {\n if (fns[i].fn === fn) {\n fns.splice(i, 1);\n i--;\n }\n i++;\n }\n }\n else {\n delete this.listener[eventName];\n }\n }\n _clearCache(eventName) {\n for (let index = 0; index < this.emitCache.length; index++) {\n const cache = this.emitCache[index];\n const _name = eventName\n ? cache.eventName === eventName\n ? eventName\n : null\n : cache.eventName;\n if (!_name)\n continue;\n const location = this.emit.apply(this, [_name, ...cache.args]);\n if (typeof location === 'number') {\n this.emitCache.pop();\n continue;\n }\n this.emitCache.splice(index, 1);\n index--;\n }\n }\n _addListener(eventName, type, fn) {\n (this.listener[eventName] || (this.listener[eventName] = [])).push({\n fn,\n type,\n });\n }\n}\n\nconst PAGE_HOOKS = [\n ON_INIT,\n ON_LOAD,\n ON_SHOW,\n ON_HIDE,\n ON_UNLOAD,\n ON_BACK_PRESS,\n ON_PAGE_SCROLL,\n ON_TAB_ITEM_TAP,\n ON_REACH_BOTTOM,\n ON_PULL_DOWN_REFRESH,\n ON_SHARE_TIMELINE,\n ON_SHARE_APP_MESSAGE,\n ON_SHARE_CHAT,\n ON_ADD_TO_FAVORITES,\n ON_SAVE_EXIT_STATE,\n ON_NAVIGATION_BAR_BUTTON_TAP,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED,\n];\nfunction isRootImmediateHook(name) {\n const PAGE_SYNC_HOOKS = [ON_LOAD, ON_SHOW];\n return PAGE_SYNC_HOOKS.indexOf(name) > -1;\n}\n// isRootImmediateHookX deprecated\nfunction isRootHook(name) {\n return PAGE_HOOKS.indexOf(name) > -1;\n}\nconst UniLifecycleHooks = [\n ON_SHOW,\n ON_HIDE,\n ON_LAUNCH,\n ON_ERROR,\n ON_THEME_CHANGE,\n ON_PAGE_NOT_FOUND,\n ON_UNHANDLE_REJECTION,\n ON_EXIT,\n ON_INIT,\n ON_LOAD,\n ON_READY,\n ON_UNLOAD,\n ON_RESIZE,\n ON_BACK_PRESS,\n ON_PAGE_SCROLL,\n ON_TAB_ITEM_TAP,\n ON_REACH_BOTTOM,\n ON_PULL_DOWN_REFRESH,\n ON_SHARE_TIMELINE,\n ON_ADD_TO_FAVORITES,\n ON_SHARE_APP_MESSAGE,\n ON_SHARE_CHAT,\n ON_SAVE_EXIT_STATE,\n ON_NAVIGATION_BAR_BUTTON_TAP,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED,\n ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED,\n];\nconst MINI_PROGRAM_PAGE_RUNTIME_HOOKS = /*#__PURE__*/ (() => {\n return {\n onPageScroll: 1,\n onShareAppMessage: 1 << 1,\n onShareTimeline: 1 << 2,\n };\n})();\nfunction isUniLifecycleHook(name, value, checkType = true) {\n // 检查类型\n if (checkType && !isFunction(value)) {\n return false;\n }\n if (UniLifecycleHooks.indexOf(name) > -1) {\n // 已预定义\n return true;\n }\n else if (name.indexOf('on') === 0) {\n // 以 on 开头\n return true;\n }\n return false;\n}\n\nlet vueApp;\nconst createVueAppHooks = [];\n/**\n * 提供 createApp 的回调事件,方便三方插件接收 App 对象,处理挂靠全局 mixin 之类的逻辑\n */\nfunction onCreateVueApp(hook) {\n // TODO 每个 nvue 页面都会触发\n if (vueApp) {\n return hook(vueApp);\n }\n createVueAppHooks.push(hook);\n}\nfunction invokeCreateVueAppHook(app) {\n vueApp = app;\n createVueAppHooks.forEach((hook) => hook(app));\n}\nconst invokeCreateErrorHandler = once((app, createErrorHandler) => {\n // 不再判断开发者是否监听了onError,直接返回 createErrorHandler,内部 errorHandler 会调用开发者自定义的 errorHandler,以及判断开发者是否监听了onError\n return createErrorHandler(app);\n});\n\nconst E = function () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n};\nE.prototype = {\n _id: 1,\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx,\n _id: this._id,\n });\n return this._id++;\n },\n once: function (name, callback, ctx) {\n var self = this;\n function listener() {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n }\n listener._ = callback;\n return this.on(name, listener, ctx);\n },\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n return this;\n },\n off: function (name, event) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n if (evts && event) {\n for (var i = evts.length - 1; i >= 0; i--) {\n if (evts[i].fn === event ||\n evts[i].fn._ === event ||\n evts[i]._id === event) {\n evts.splice(i, 1);\n break;\n }\n }\n liveEvents = evts;\n }\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n liveEvents.length ? (e[name] = liveEvents) : delete e[name];\n return this;\n },\n};\nvar E$1 = E;\n\nconst borderStyles = {\n black: 'rgba(0,0,0,0.4)',\n white: 'rgba(255,255,255,0.4)',\n};\nfunction normalizeTabBarStyles(borderStyle) {\n if (borderStyle && borderStyle in borderStyles) {\n return borderStyles[borderStyle];\n }\n return borderStyle;\n}\nfunction normalizeTitleColor(titleColor) {\n return titleColor === 'black' ? '#000000' : '#ffffff';\n}\nfunction resolveStringStyleItem(modeStyle, styleItem, key) {\n if (isString(styleItem) && styleItem.startsWith('@')) {\n const _key = styleItem.replace('@', '');\n let _styleItem = modeStyle[_key] || styleItem;\n switch (key) {\n case 'titleColor':\n _styleItem = normalizeTitleColor(_styleItem);\n break;\n case 'borderStyle':\n _styleItem = normalizeTabBarStyles(_styleItem);\n break;\n }\n return _styleItem;\n }\n return styleItem;\n}\nfunction normalizeStyles(pageStyle, themeConfig = {}, mode = 'light') {\n const modeStyle = themeConfig[mode];\n const styles = {};\n if (typeof modeStyle === 'undefined' || !pageStyle)\n return pageStyle;\n Object.keys(pageStyle).forEach((key) => {\n const styleItem = pageStyle[key]; // Object Array String\n const parseStyleItem = () => {\n if (isPlainObject(styleItem))\n return normalizeStyles(styleItem, themeConfig, mode);\n if (isArray(styleItem))\n return styleItem.map((item) => {\n if (isPlainObject(item))\n return normalizeStyles(item, themeConfig, mode);\n return resolveStringStyleItem(modeStyle, item);\n });\n return resolveStringStyleItem(modeStyle, styleItem, key);\n };\n styles[key] = parseStyleItem();\n });\n return styles;\n}\n\nfunction getEnvLocale() {\n const { env } = process;\n const lang = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE;\n return (lang && lang.replace(/[.:].*/, '')) || 'en';\n}\n\nconst isStringIntegerKey = (key) => typeof key === 'string' &&\n key !== 'NaN' &&\n key[0] !== '-' &&\n '' + parseInt(key, 10) === key;\nconst isNumberIntegerKey = (key) => typeof key === 'number' &&\n !isNaN(key) &&\n key >= 0 &&\n parseInt(key + '', 10) === key;\n/**\n * 用于替代@vue/shared的isIntegerKey,原始方法在鸿蒙arkts中会引发bug。根本原因是arkts的数组的key是数字而不是字符串。\n * 目前这个方法使用的地方都和数组有关,切记不能挪作他用。\n * @param key\n * @returns\n */\nconst isIntegerKey = (key) => isNumberIntegerKey(key) || isStringIntegerKey(key);\n\nconst GLOBALS_ALLOWED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +\n 'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +\n 'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,' +\n 'uni';\nconst isGloballyAllowed = /*#__PURE__*/ makeMap(GLOBALS_ALLOWED);\n\nexport { ACTION_TYPE_ADD_EVENT, ACTION_TYPE_ADD_WXS_EVENT, ACTION_TYPE_CREATE, ACTION_TYPE_EVENT, ACTION_TYPE_INSERT, ACTION_TYPE_PAGE_CREATE, ACTION_TYPE_PAGE_CREATED, ACTION_TYPE_PAGE_SCROLL, ACTION_TYPE_REMOVE, ACTION_TYPE_REMOVE_ATTRIBUTE, ACTION_TYPE_REMOVE_EVENT, ACTION_TYPE_SET_ATTRIBUTE, ACTION_TYPE_SET_TEXT, ATTR_CHANGE_PREFIX, ATTR_CLASS, ATTR_INNER_HTML, ATTR_STYLE, ATTR_TEXT_CONTENT, ATTR_V_OWNER_ID, ATTR_V_RENDERJS, ATTR_V_SHOW, BACKGROUND_COLOR, BUILT_IN_TAGS, BUILT_IN_TAG_NAMES, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, E$1 as Emitter, EventChannel, EventModifierFlags, I18N_JSON_DELIMITERS, JSON_PROTOCOL, LINEFEED, MINI_PROGRAM_PAGE_RUNTIME_HOOKS, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, NVUE_BUILT_IN_TAGS, NVUE_U_BUILT_IN_TAGS, OFF_HOST_THEME_CHANGE, OFF_THEME_CHANGE, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_EXIT, ON_HIDE, ON_HOST_THEME_CHANGE, ON_INIT, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAST_PAGE_BACK_PRESS, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_CHANGE, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_PAGE_NOT_FOUND, ON_PAGE_SCROLL, ON_PULL_DOWN_REFRESH, ON_REACH_BOTTOM, ON_REACH_BOTTOM_DISTANCE, ON_READY, ON_RESIZE, ON_SAVE_EXIT_STATE, ON_SHARE_APP_MESSAGE, ON_SHARE_CHAT, ON_SHARE_TIMELINE, ON_SHOW, ON_TAB_ITEM_TAP, ON_THEME_CHANGE, ON_UNHANDLE_REJECTION, ON_UNLOAD, ON_WEB_INVOKE_APP_SERVICE, ON_WXS_INVOKE_CALL_METHOD, PLUS_RE, PRIMARY_COLOR, RENDERJS_MODULES, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, SLOT_DEFAULT_NAME, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UNI_STORAGE_LOCALE, UNI_UI_CONFLICT_TAGS, UVUE_BUILT_IN_TAGS, UVUE_HARMONY_BUILT_IN_TAGS, UVUE_IOS_BUILT_IN_TAGS, UVUE_WEB_BUILT_IN_CUSTOM_ELEMENTS, UVUE_WEB_BUILT_IN_TAGS, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, VIRTUAL_HOST_CLASS, VIRTUAL_HOST_HIDDEN, VIRTUAL_HOST_ID, VIRTUAL_HOST_STYLE, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, borderStyles, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, customizeEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultNVueRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatDateTime, formatLog, getCustomDataset, getEnvLocale, getGlobal, getLen, getValueByDataPath, initCustomDatasetOnce, invokeArrayFns, invokeCreateErrorHandler, invokeCreateVueAppHook, isAppHarmonyUVueNativeTag, isAppIOSUVueNativeTag, isAppNVueNativeTag, isAppNativeTag, isAppUVueBuiltInEasyComponent, isAppUVueNativeTag, isAppVoidTag, isBuiltInComponent, isComponentInternalInstance, isComponentTag, isGloballyAllowed, isH5CustomElement, isH5NativeTag, isIntegerKey, isMiniProgramNativeTag, isMiniProgramUVueNativeTag, isRootHook, isRootImmediateHook, isUniLifecycleHook, isUniXElement, normalizeClass, normalizeDataset, normalizeEventType, normalizeProps, normalizeStyle, normalizeStyles, normalizeTabBarStyles, normalizeTarget, normalizeTitleColor, onCreateVueApp, once, parseEventName, parseNVueDataset, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveComponentInstance, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, sortObject, stringifyQuery, updateElementStyle };\n","import { isRootHook, getValueByDataPath, isUniLifecycleHook, ON_ERROR, UniLifecycleHooks, invokeCreateErrorHandler, dynamicSlotName } from '@dcloudio/uni-shared';\nimport { NOOP, extend, isSymbol, isObject, def, hasChanged, isFunction, isArray, isPromise, camelize, capitalize, EMPTY_OBJ, remove, toHandlerKey, hasOwn, hyphenate, isReservedProp, toRawType, isString, normalizeClass, normalizeStyle, isOn, toTypeString, isMap, isIntegerKey, isSet, isPlainObject, makeMap, invokeArrayFns, isBuiltInDirective, looseToNumber, NO, EMPTY_ARR, isModelListener, toNumber, toDisplayString } from '@vue/shared';\nexport { EMPTY_OBJ, camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared';\n\n/**\n* @dcloudio/uni-mp-vue v3.4.21\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\n\nfunction warn$2(msg, ...args) {\n console.warn(`[Vue warn] ${msg}`, ...args);\n}\n\nlet activeEffectScope;\nclass EffectScope {\n constructor(detached = false) {\n this.detached = detached;\n /**\n * @internal\n */\n this._active = true;\n /**\n * @internal\n */\n this.effects = [];\n /**\n * @internal\n */\n this.cleanups = [];\n this.parent = activeEffectScope;\n if (!detached && activeEffectScope) {\n this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(\n this\n ) - 1;\n }\n }\n get active() {\n return this._active;\n }\n run(fn) {\n if (this._active) {\n const currentEffectScope = activeEffectScope;\n try {\n activeEffectScope = this;\n return fn();\n } finally {\n activeEffectScope = currentEffectScope;\n }\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$2(`cannot run an inactive effect scope.`);\n }\n }\n /**\n * This should only be called on non-detached scopes\n * @internal\n */\n on() {\n activeEffectScope = this;\n }\n /**\n * This should only be called on non-detached scopes\n * @internal\n */\n off() {\n activeEffectScope = this.parent;\n }\n stop(fromParent) {\n if (this._active) {\n let i, l;\n for (i = 0, l = this.effects.length; i < l; i++) {\n this.effects[i].stop();\n }\n for (i = 0, l = this.cleanups.length; i < l; i++) {\n this.cleanups[i]();\n }\n if (this.scopes) {\n for (i = 0, l = this.scopes.length; i < l; i++) {\n this.scopes[i].stop(true);\n }\n }\n if (!this.detached && this.parent && !fromParent) {\n const last = this.parent.scopes.pop();\n if (last && last !== this) {\n this.parent.scopes[this.index] = last;\n last.index = this.index;\n }\n }\n this.parent = void 0;\n this._active = false;\n }\n }\n}\nfunction effectScope(detached) {\n return new EffectScope(detached);\n}\nfunction recordEffectScope(effect, scope = activeEffectScope) {\n if (scope && scope.active) {\n scope.effects.push(effect);\n }\n}\nfunction getCurrentScope() {\n return activeEffectScope;\n}\nfunction onScopeDispose(fn) {\n if (activeEffectScope) {\n activeEffectScope.cleanups.push(fn);\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$2(\n `onScopeDispose() is called when there is no active effect scope to be associated with.`\n );\n }\n}\n\nlet activeEffect;\nclass ReactiveEffect {\n constructor(fn, trigger, scheduler, scope) {\n this.fn = fn;\n this.trigger = trigger;\n this.scheduler = scheduler;\n this.active = true;\n this.deps = [];\n /**\n * @internal\n */\n this._dirtyLevel = 4;\n /**\n * @internal\n */\n this._trackId = 0;\n /**\n * @internal\n */\n this._runnings = 0;\n /**\n * @internal\n */\n this._shouldSchedule = false;\n /**\n * @internal\n */\n this._depsLength = 0;\n recordEffectScope(this, scope);\n }\n get dirty() {\n if (this._dirtyLevel === 2 || this._dirtyLevel === 3) {\n this._dirtyLevel = 1;\n pauseTracking();\n for (let i = 0; i < this._depsLength; i++) {\n const dep = this.deps[i];\n if (dep.computed) {\n triggerComputed(dep.computed);\n if (this._dirtyLevel >= 4) {\n break;\n }\n }\n }\n if (this._dirtyLevel === 1) {\n this._dirtyLevel = 0;\n }\n resetTracking();\n }\n return this._dirtyLevel >= 4;\n }\n set dirty(v) {\n this._dirtyLevel = v ? 4 : 0;\n }\n run() {\n this._dirtyLevel = 0;\n if (!this.active) {\n return this.fn();\n }\n let lastShouldTrack = shouldTrack;\n let lastEffect = activeEffect;\n try {\n shouldTrack = true;\n activeEffect = this;\n this._runnings++;\n preCleanupEffect(this);\n return this.fn();\n } finally {\n postCleanupEffect(this);\n this._runnings--;\n activeEffect = lastEffect;\n shouldTrack = lastShouldTrack;\n }\n }\n stop() {\n var _a;\n if (this.active) {\n preCleanupEffect(this);\n postCleanupEffect(this);\n (_a = this.onStop) == null ? void 0 : _a.call(this);\n this.active = false;\n }\n }\n}\nfunction triggerComputed(computed) {\n return computed.value;\n}\nfunction preCleanupEffect(effect2) {\n effect2._trackId++;\n effect2._depsLength = 0;\n}\nfunction postCleanupEffect(effect2) {\n if (effect2.deps.length > effect2._depsLength) {\n for (let i = effect2._depsLength; i < effect2.deps.length; i++) {\n cleanupDepEffect(effect2.deps[i], effect2);\n }\n effect2.deps.length = effect2._depsLength;\n }\n}\nfunction cleanupDepEffect(dep, effect2) {\n const trackId = dep.get(effect2);\n if (trackId !== void 0 && effect2._trackId !== trackId) {\n dep.delete(effect2);\n if (dep.size === 0) {\n dep.cleanup();\n }\n }\n}\nfunction effect(fn, options) {\n if (fn.effect instanceof ReactiveEffect) {\n fn = fn.effect.fn;\n }\n const _effect = new ReactiveEffect(fn, NOOP, () => {\n if (_effect.dirty) {\n _effect.run();\n }\n });\n if (options) {\n extend(_effect, options);\n if (options.scope)\n recordEffectScope(_effect, options.scope);\n }\n if (!options || !options.lazy) {\n _effect.run();\n }\n const runner = _effect.run.bind(_effect);\n runner.effect = _effect;\n return runner;\n}\nfunction stop(runner) {\n runner.effect.stop();\n}\nlet shouldTrack = true;\nlet pauseScheduleStack = 0;\nconst trackStack = [];\nfunction pauseTracking() {\n trackStack.push(shouldTrack);\n shouldTrack = false;\n}\nfunction resetTracking() {\n const last = trackStack.pop();\n shouldTrack = last === void 0 ? true : last;\n}\nfunction pauseScheduling() {\n pauseScheduleStack++;\n}\nfunction resetScheduling() {\n pauseScheduleStack--;\n while (!pauseScheduleStack && queueEffectSchedulers.length) {\n queueEffectSchedulers.shift()();\n }\n}\nfunction trackEffect(effect2, dep, debuggerEventExtraInfo) {\n var _a;\n if (dep.get(effect2) !== effect2._trackId) {\n dep.set(effect2, effect2._trackId);\n const oldDep = effect2.deps[effect2._depsLength];\n if (oldDep !== dep) {\n if (oldDep) {\n cleanupDepEffect(oldDep, effect2);\n }\n effect2.deps[effect2._depsLength++] = dep;\n } else {\n effect2._depsLength++;\n }\n if (!!(process.env.NODE_ENV !== \"production\")) {\n (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));\n }\n }\n}\nconst queueEffectSchedulers = [];\nfunction triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) {\n var _a;\n pauseScheduling();\n for (const effect2 of dep.keys()) {\n let tracking;\n if (effect2._dirtyLevel < dirtyLevel && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {\n effect2._shouldSchedule || (effect2._shouldSchedule = effect2._dirtyLevel === 0);\n effect2._dirtyLevel = dirtyLevel;\n }\n if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));\n }\n effect2.trigger();\n if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) {\n effect2._shouldSchedule = false;\n if (effect2.scheduler) {\n queueEffectSchedulers.push(effect2.scheduler);\n }\n }\n }\n }\n resetScheduling();\n}\n\nconst createDep = (cleanup, computed) => {\n const dep = /* @__PURE__ */ new Map();\n dep.cleanup = cleanup;\n dep.computed = computed;\n return dep;\n};\n\nconst targetMap = /* @__PURE__ */ new WeakMap();\nconst ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== \"production\") ? \"iterate\" : \"\");\nconst MAP_KEY_ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== \"production\") ? \"Map key iterate\" : \"\");\nfunction track(target, type, key) {\n if (shouldTrack && activeEffect) {\n let depsMap = targetMap.get(target);\n if (!depsMap) {\n targetMap.set(target, depsMap = /* @__PURE__ */ new Map());\n }\n let dep = depsMap.get(key);\n if (!dep) {\n depsMap.set(key, dep = createDep(() => depsMap.delete(key)));\n }\n trackEffect(\n activeEffect,\n dep,\n !!(process.env.NODE_ENV !== \"production\") ? {\n target,\n type,\n key\n } : void 0\n );\n }\n}\nfunction trigger(target, type, key, newValue, oldValue, oldTarget) {\n const depsMap = targetMap.get(target);\n if (!depsMap) {\n return;\n }\n let deps = [];\n if (type === \"clear\") {\n deps = [...depsMap.values()];\n } else if (key === \"length\" && isArray(target)) {\n const newLength = Number(newValue);\n depsMap.forEach((dep, key2) => {\n if (key2 === \"length\" || !isSymbol(key2) && key2 >= newLength) {\n deps.push(dep);\n }\n });\n } else {\n if (key !== void 0) {\n deps.push(depsMap.get(key));\n }\n switch (type) {\n case \"add\":\n if (!isArray(target)) {\n deps.push(depsMap.get(ITERATE_KEY));\n if (isMap(target)) {\n deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));\n }\n } else if (isIntegerKey(key)) {\n deps.push(depsMap.get(\"length\"));\n }\n break;\n case \"delete\":\n if (!isArray(target)) {\n deps.push(depsMap.get(ITERATE_KEY));\n if (isMap(target)) {\n deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));\n }\n }\n break;\n case \"set\":\n if (isMap(target)) {\n deps.push(depsMap.get(ITERATE_KEY));\n }\n break;\n }\n }\n pauseScheduling();\n for (const dep of deps) {\n if (dep) {\n triggerEffects(\n dep,\n 4,\n !!(process.env.NODE_ENV !== \"production\") ? {\n target,\n type,\n key,\n newValue,\n oldValue,\n oldTarget\n } : void 0\n );\n }\n }\n resetScheduling();\n}\nfunction getDepFromReactive(object, key) {\n var _a;\n return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key);\n}\n\nconst isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);\nconst builtInSymbols = new Set(\n /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== \"arguments\" && key !== \"caller\").map((key) => Symbol[key]).filter(isSymbol)\n);\nconst arrayInstrumentations = /* @__PURE__ */ createArrayInstrumentations();\nfunction createArrayInstrumentations() {\n const instrumentations = {};\n [\"includes\", \"indexOf\", \"lastIndexOf\"].forEach((key) => {\n instrumentations[key] = function(...args) {\n const arr = toRaw(this);\n for (let i = 0, l = this.length; i < l; i++) {\n track(arr, \"get\", i + \"\");\n }\n const res = arr[key](...args);\n if (res === -1 || res === false) {\n return arr[key](...args.map(toRaw));\n } else {\n return res;\n }\n };\n });\n [\"push\", \"pop\", \"shift\", \"unshift\", \"splice\"].forEach((key) => {\n instrumentations[key] = function(...args) {\n pauseTracking();\n pauseScheduling();\n const res = toRaw(this)[key].apply(this, args);\n resetScheduling();\n resetTracking();\n return res;\n };\n });\n return instrumentations;\n}\nfunction hasOwnProperty(key) {\n const obj = toRaw(this);\n track(obj, \"has\", key);\n return obj.hasOwnProperty(key);\n}\nclass BaseReactiveHandler {\n constructor(_isReadonly = false, _isShallow = false) {\n this._isReadonly = _isReadonly;\n this._isShallow = _isShallow;\n }\n get(target, key, receiver) {\n const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow;\n if (key === \"__v_isReactive\") {\n return !isReadonly2;\n } else if (key === \"__v_isReadonly\") {\n return isReadonly2;\n } else if (key === \"__v_isShallow\") {\n return isShallow2;\n } else if (key === \"__v_raw\") {\n if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype\n // this means the reciever is a user proxy of the reactive proxy\n Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) {\n return target;\n }\n return;\n }\n const targetIsArray = isArray(target);\n if (!isReadonly2) {\n if (targetIsArray && hasOwn(arrayInstrumentations, key)) {\n return Reflect.get(arrayInstrumentations, key, receiver);\n }\n if (key === \"hasOwnProperty\") {\n return hasOwnProperty;\n }\n }\n const res = Reflect.get(target, key, receiver);\n if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {\n return res;\n }\n if (!isReadonly2) {\n track(target, \"get\", key);\n }\n if (isShallow2) {\n return res;\n }\n if (isRef(res)) {\n return targetIsArray && isIntegerKey(key) ? res : res.value;\n }\n if (isObject(res)) {\n return isReadonly2 ? readonly(res) : reactive(res);\n }\n return res;\n }\n}\nclass MutableReactiveHandler extends BaseReactiveHandler {\n constructor(isShallow2 = false) {\n super(false, isShallow2);\n }\n set(target, key, value, receiver) {\n let oldValue = target[key];\n if (!this._isShallow) {\n const isOldValueReadonly = isReadonly(oldValue);\n if (!isShallow(value) && !isReadonly(value)) {\n oldValue = toRaw(oldValue);\n value = toRaw(value);\n }\n if (!isArray(target) && isRef(oldValue) && !isRef(value)) {\n if (isOldValueReadonly) {\n return false;\n } else {\n oldValue.value = value;\n return true;\n }\n }\n }\n const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key);\n const result = Reflect.set(target, key, value, receiver);\n if (target === toRaw(receiver)) {\n if (!hadKey) {\n trigger(target, \"add\", key, value);\n } else if (hasChanged(value, oldValue)) {\n trigger(target, \"set\", key, value, oldValue);\n }\n }\n return result;\n }\n deleteProperty(target, key) {\n const hadKey = hasOwn(target, key);\n const oldValue = target[key];\n const result = Reflect.deleteProperty(target, key);\n if (result && hadKey) {\n trigger(target, \"delete\", key, void 0, oldValue);\n }\n return result;\n }\n has(target, key) {\n const result = Reflect.has(target, key);\n if (!isSymbol(key) || !builtInSymbols.has(key)) {\n track(target, \"has\", key);\n }\n return result;\n }\n ownKeys(target) {\n track(\n target,\n \"iterate\",\n isArray(target) ? \"length\" : ITERATE_KEY\n );\n return Reflect.ownKeys(target);\n }\n}\nclass ReadonlyReactiveHandler extends BaseReactiveHandler {\n constructor(isShallow2 = false) {\n super(true, isShallow2);\n }\n set(target, key) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$2(\n `Set operation on key \"${String(key)}\" failed: target is readonly.`,\n target\n );\n }\n return true;\n }\n deleteProperty(target, key) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$2(\n `Delete operation on key \"${String(key)}\" failed: target is readonly.`,\n target\n );\n }\n return true;\n }\n}\nconst mutableHandlers = /* @__PURE__ */ new MutableReactiveHandler();\nconst readonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler();\nconst shallowReactiveHandlers = /* @__PURE__ */ new MutableReactiveHandler(\n true\n);\nconst shallowReadonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler(true);\n\nconst toShallow = (value) => value;\nconst getProto = (v) => Reflect.getPrototypeOf(v);\nfunction get(target, key, isReadonly = false, isShallow = false) {\n target = target[\"__v_raw\"];\n const rawTarget = toRaw(target);\n const rawKey = toRaw(key);\n if (!isReadonly) {\n if (hasChanged(key, rawKey)) {\n track(rawTarget, \"get\", key);\n }\n track(rawTarget, \"get\", rawKey);\n }\n const { has: has2 } = getProto(rawTarget);\n const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n if (has2.call(rawTarget, key)) {\n return wrap(target.get(key));\n } else if (has2.call(rawTarget, rawKey)) {\n return wrap(target.get(rawKey));\n } else if (target !== rawTarget) {\n target.get(key);\n }\n}\nfunction has(key, isReadonly = false) {\n const target = this[\"__v_raw\"];\n const rawTarget = toRaw(target);\n const rawKey = toRaw(key);\n if (!isReadonly) {\n if (hasChanged(key, rawKey)) {\n track(rawTarget, \"has\", key);\n }\n track(rawTarget, \"has\", rawKey);\n }\n return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey);\n}\nfunction size(target, isReadonly = false) {\n target = target[\"__v_raw\"];\n !isReadonly && track(toRaw(target), \"iterate\", ITERATE_KEY);\n return Reflect.get(target, \"size\", target);\n}\nfunction add(value) {\n value = toRaw(value);\n const target = toRaw(this);\n const proto = getProto(target);\n const hadKey = proto.has.call(target, value);\n if (!hadKey) {\n target.add(value);\n trigger(target, \"add\", value, value);\n }\n return this;\n}\nfunction set$1(key, value) {\n value = toRaw(value);\n const target = toRaw(this);\n const { has: has2, get: get2 } = getProto(target);\n let hadKey = has2.call(target, key);\n if (!hadKey) {\n key = toRaw(key);\n hadKey = has2.call(target, key);\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n checkIdentityKeys(target, has2, key);\n }\n const oldValue = get2.call(target, key);\n target.set(key, value);\n if (!hadKey) {\n trigger(target, \"add\", key, value);\n } else if (hasChanged(value, oldValue)) {\n trigger(target, \"set\", key, value, oldValue);\n }\n return this;\n}\nfunction deleteEntry(key) {\n const target = toRaw(this);\n const { has: has2, get: get2 } = getProto(target);\n let hadKey = has2.call(target, key);\n if (!hadKey) {\n key = toRaw(key);\n hadKey = has2.call(target, key);\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n checkIdentityKeys(target, has2, key);\n }\n const oldValue = get2 ? get2.call(target, key) : void 0;\n const result = target.delete(key);\n if (hadKey) {\n trigger(target, \"delete\", key, void 0, oldValue);\n }\n return result;\n}\nfunction clear() {\n const target = toRaw(this);\n const hadItems = target.size !== 0;\n const oldTarget = !!(process.env.NODE_ENV !== \"production\") ? isMap(target) ? new Map(target) : new Set(target) : void 0;\n const result = target.clear();\n if (hadItems) {\n trigger(target, \"clear\", void 0, void 0, oldTarget);\n }\n return result;\n}\nfunction createForEach(isReadonly, isShallow) {\n return function forEach(callback, thisArg) {\n const observed = this;\n const target = observed[\"__v_raw\"];\n const rawTarget = toRaw(target);\n const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n !isReadonly && track(rawTarget, \"iterate\", ITERATE_KEY);\n return target.forEach((value, key) => {\n return callback.call(thisArg, wrap(value), wrap(key), observed);\n });\n };\n}\nfunction createIterableMethod(method, isReadonly, isShallow) {\n return function(...args) {\n const target = this[\"__v_raw\"];\n const rawTarget = toRaw(target);\n const targetIsMap = isMap(rawTarget);\n const isPair = method === \"entries\" || method === Symbol.iterator && targetIsMap;\n const isKeyOnly = method === \"keys\" && targetIsMap;\n const innerIterator = target[method](...args);\n const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n !isReadonly && track(\n rawTarget,\n \"iterate\",\n isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY\n );\n return {\n // iterator protocol\n next() {\n const { value, done } = innerIterator.next();\n return done ? { value, done } : {\n value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),\n done\n };\n },\n // iterable protocol\n [Symbol.iterator]() {\n return this;\n }\n };\n };\n}\nfunction createReadonlyMethod(type) {\n return function(...args) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n const key = args[0] ? `on key \"${args[0]}\" ` : ``;\n warn$2(\n `${capitalize(type)} operation ${key}failed: target is readonly.`,\n toRaw(this)\n );\n }\n return type === \"delete\" ? false : type === \"clear\" ? void 0 : this;\n };\n}\nfunction createInstrumentations() {\n const mutableInstrumentations2 = {\n get(key) {\n return get(this, key);\n },\n get size() {\n return size(this);\n },\n has,\n add,\n set: set$1,\n delete: deleteEntry,\n clear,\n forEach: createForEach(false, false)\n };\n const shallowInstrumentations2 = {\n get(key) {\n return get(this, key, false, true);\n },\n get size() {\n return size(this);\n },\n has,\n add,\n set: set$1,\n delete: deleteEntry,\n clear,\n forEach: createForEach(false, true)\n };\n const readonlyInstrumentations2 = {\n get(key) {\n return get(this, key, true);\n },\n get size() {\n return size(this, true);\n },\n has(key) {\n return has.call(this, key, true);\n },\n add: createReadonlyMethod(\"add\"),\n set: createReadonlyMethod(\"set\"),\n delete: createReadonlyMethod(\"delete\"),\n clear: createReadonlyMethod(\"clear\"),\n forEach: createForEach(true, false)\n };\n const shallowReadonlyInstrumentations2 = {\n get(key) {\n return get(this, key, true, true);\n },\n get size() {\n return size(this, true);\n },\n has(key) {\n return has.call(this, key, true);\n },\n add: createReadonlyMethod(\"add\"),\n set: createReadonlyMethod(\"set\"),\n delete: createReadonlyMethod(\"delete\"),\n clear: createReadonlyMethod(\"clear\"),\n forEach: createForEach(true, true)\n };\n const iteratorMethods = [\n \"keys\",\n \"values\",\n \"entries\",\n Symbol.iterator\n ];\n iteratorMethods.forEach((method) => {\n mutableInstrumentations2[method] = createIterableMethod(method, false, false);\n readonlyInstrumentations2[method] = createIterableMethod(method, true, false);\n shallowInstrumentations2[method] = createIterableMethod(method, false, true);\n shallowReadonlyInstrumentations2[method] = createIterableMethod(\n method,\n true,\n true\n );\n });\n return [\n mutableInstrumentations2,\n readonlyInstrumentations2,\n shallowInstrumentations2,\n shallowReadonlyInstrumentations2\n ];\n}\nconst [\n mutableInstrumentations,\n readonlyInstrumentations,\n shallowInstrumentations,\n shallowReadonlyInstrumentations\n] = /* @__PURE__ */ createInstrumentations();\nfunction createInstrumentationGetter(isReadonly, shallow) {\n const instrumentations = shallow ? isReadonly ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly ? readonlyInstrumentations : mutableInstrumentations;\n return (target, key, receiver) => {\n if (key === \"__v_isReactive\") {\n return !isReadonly;\n } else if (key === \"__v_isReadonly\") {\n return isReadonly;\n } else if (key === \"__v_raw\") {\n return target;\n }\n return Reflect.get(\n hasOwn(instrumentations, key) && key in target ? instrumentations : target,\n key,\n receiver\n );\n };\n}\nconst mutableCollectionHandlers = {\n get: /* @__PURE__ */ createInstrumentationGetter(false, false)\n};\nconst shallowCollectionHandlers = {\n get: /* @__PURE__ */ createInstrumentationGetter(false, true)\n};\nconst readonlyCollectionHandlers = {\n get: /* @__PURE__ */ createInstrumentationGetter(true, false)\n};\nconst shallowReadonlyCollectionHandlers = {\n get: /* @__PURE__ */ createInstrumentationGetter(true, true)\n};\nfunction checkIdentityKeys(target, has2, key) {\n const rawKey = toRaw(key);\n if (rawKey !== key && has2.call(target, rawKey)) {\n const type = toRawType(target);\n warn$2(\n `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`\n );\n }\n}\n\nconst reactiveMap = /* @__PURE__ */ new WeakMap();\nconst shallowReactiveMap = /* @__PURE__ */ new WeakMap();\nconst readonlyMap = /* @__PURE__ */ new WeakMap();\nconst shallowReadonlyMap = /* @__PURE__ */ new WeakMap();\nfunction targetTypeMap(rawType) {\n switch (rawType) {\n case \"Object\":\n case \"Array\":\n return 1 /* COMMON */;\n case \"Map\":\n case \"Set\":\n case \"WeakMap\":\n case \"WeakSet\":\n return 2 /* COLLECTION */;\n default:\n return 0 /* INVALID */;\n }\n}\nfunction getTargetType(value) {\n return value[\"__v_skip\"] || !Object.isExtensible(value) ? 0 /* INVALID */ : targetTypeMap(toRawType(value));\n}\nfunction reactive(target) {\n if (isReadonly(target)) {\n return target;\n }\n return createReactiveObject(\n target,\n false,\n mutableHandlers,\n mutableCollectionHandlers,\n reactiveMap\n );\n}\nfunction shallowReactive(target) {\n return createReactiveObject(\n target,\n false,\n shallowReactiveHandlers,\n shallowCollectionHandlers,\n shallowReactiveMap\n );\n}\nfunction readonly(target) {\n return createReactiveObject(\n target,\n true,\n readonlyHandlers,\n readonlyCollectionHandlers,\n readonlyMap\n );\n}\nfunction shallowReadonly(target) {\n return createReactiveObject(\n target,\n true,\n shallowReadonlyHandlers,\n shallowReadonlyCollectionHandlers,\n shallowReadonlyMap\n );\n}\nfunction createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) {\n if (!isObject(target)) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$2(`value cannot be made reactive: ${String(target)}`);\n }\n return target;\n }\n if (target[\"__v_raw\"] && !(isReadonly2 && target[\"__v_isReactive\"])) {\n return target;\n }\n const existingProxy = proxyMap.get(target);\n if (existingProxy) {\n return existingProxy;\n }\n const targetType = getTargetType(target);\n if (targetType === 0 /* INVALID */) {\n return target;\n }\n const proxy = new Proxy(\n target,\n targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers\n );\n proxyMap.set(target, proxy);\n return proxy;\n}\nfunction isReactive(value) {\n if (isReadonly(value)) {\n return isReactive(value[\"__v_raw\"]);\n }\n return !!(value && value[\"__v_isReactive\"]);\n}\nfunction isReadonly(value) {\n return !!(value && value[\"__v_isReadonly\"]);\n}\nfunction isShallow(value) {\n return !!(value && value[\"__v_isShallow\"]);\n}\nfunction isProxy(value) {\n return isReactive(value) || isReadonly(value);\n}\nfunction toRaw(observed) {\n const raw = observed && observed[\"__v_raw\"];\n return raw ? toRaw(raw) : observed;\n}\nfunction markRaw(value) {\n if (Object.isExtensible(value)) {\n def(value, \"__v_skip\", true);\n }\n return value;\n}\nconst toReactive = (value) => isObject(value) ? reactive(value) : value;\nconst toReadonly = (value) => isObject(value) ? readonly(value) : value;\n\nconst COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided. Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`;\nclass ComputedRefImpl {\n constructor(getter, _setter, isReadonly, isSSR) {\n this.getter = getter;\n this._setter = _setter;\n this.dep = void 0;\n this.__v_isRef = true;\n this[\"__v_isReadonly\"] = false;\n this.effect = new ReactiveEffect(\n () => getter(this._value),\n () => triggerRefValue(\n this,\n this.effect._dirtyLevel === 2 ? 2 : 3\n )\n );\n this.effect.computed = this;\n this.effect.active = this._cacheable = !isSSR;\n this[\"__v_isReadonly\"] = isReadonly;\n }\n get value() {\n const self = toRaw(this);\n if ((!self._cacheable || self.effect.dirty) && hasChanged(self._value, self._value = self.effect.run())) {\n triggerRefValue(self, 4);\n }\n trackRefValue(self);\n if (self.effect._dirtyLevel >= 2) {\n if (!!(process.env.NODE_ENV !== \"production\") && this._warnRecursive) {\n warn$2(COMPUTED_SIDE_EFFECT_WARN, `\n\ngetter: `, this.getter);\n }\n triggerRefValue(self, 2);\n }\n return self._value;\n }\n set value(newValue) {\n this._setter(newValue);\n }\n // #region polyfill _dirty for backward compatibility third party code for Vue <= 3.3.x\n get _dirty() {\n return this.effect.dirty;\n }\n set _dirty(v) {\n this.effect.dirty = v;\n }\n // #endregion\n}\nfunction computed$1(getterOrOptions, debugOptions, isSSR = false) {\n let getter;\n let setter;\n const onlyGetter = isFunction(getterOrOptions);\n if (onlyGetter) {\n getter = getterOrOptions;\n setter = !!(process.env.NODE_ENV !== \"production\") ? () => {\n warn$2(\"Write operation failed: computed value is readonly\");\n } : NOOP;\n } else {\n getter = getterOrOptions.get;\n setter = getterOrOptions.set;\n }\n const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR);\n if (!!(process.env.NODE_ENV !== \"production\") && debugOptions && !isSSR) {\n cRef.effect.onTrack = debugOptions.onTrack;\n cRef.effect.onTrigger = debugOptions.onTrigger;\n }\n return cRef;\n}\n\nfunction trackRefValue(ref2) {\n var _a;\n if (shouldTrack && activeEffect) {\n ref2 = toRaw(ref2);\n trackEffect(\n activeEffect,\n (_a = ref2.dep) != null ? _a : ref2.dep = createDep(\n () => ref2.dep = void 0,\n ref2 instanceof ComputedRefImpl ? ref2 : void 0\n ),\n !!(process.env.NODE_ENV !== \"production\") ? {\n target: ref2,\n type: \"get\",\n key: \"value\"\n } : void 0\n );\n }\n}\nfunction triggerRefValue(ref2, dirtyLevel = 4, newVal) {\n ref2 = toRaw(ref2);\n const dep = ref2.dep;\n if (dep) {\n triggerEffects(\n dep,\n dirtyLevel,\n !!(process.env.NODE_ENV !== \"production\") ? {\n target: ref2,\n type: \"set\",\n key: \"value\",\n newValue: newVal\n } : void 0\n );\n }\n}\nfunction isRef(r) {\n return !!(r && r.__v_isRef === true);\n}\nfunction ref(value) {\n return createRef(value, false);\n}\nfunction shallowRef(value) {\n return createRef(value, true);\n}\nfunction createRef(rawValue, shallow) {\n if (isRef(rawValue)) {\n return rawValue;\n }\n return new RefImpl(rawValue, shallow);\n}\nclass RefImpl {\n constructor(value, __v_isShallow) {\n this.__v_isShallow = __v_isShallow;\n this.dep = void 0;\n this.__v_isRef = true;\n this._rawValue = __v_isShallow ? value : toRaw(value);\n this._value = __v_isShallow ? value : toReactive(value);\n }\n get value() {\n trackRefValue(this);\n return this._value;\n }\n set value(newVal) {\n const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);\n newVal = useDirectValue ? newVal : toRaw(newVal);\n if (hasChanged(newVal, this._rawValue)) {\n this._rawValue = newVal;\n this._value = useDirectValue ? newVal : toReactive(newVal);\n triggerRefValue(this, 4, newVal);\n }\n }\n}\nfunction triggerRef(ref2) {\n triggerRefValue(ref2, 4, !!(process.env.NODE_ENV !== \"production\") ? ref2.value : void 0);\n}\nfunction unref(ref2) {\n return isRef(ref2) ? ref2.value : ref2;\n}\nfunction toValue(source) {\n return isFunction(source) ? source() : unref(source);\n}\nconst shallowUnwrapHandlers = {\n get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),\n set: (target, key, value, receiver) => {\n const oldValue = target[key];\n if (isRef(oldValue) && !isRef(value)) {\n oldValue.value = value;\n return true;\n } else {\n return Reflect.set(target, key, value, receiver);\n }\n }\n};\nfunction proxyRefs(objectWithRefs) {\n return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers);\n}\nclass CustomRefImpl {\n constructor(factory) {\n this.dep = void 0;\n this.__v_isRef = true;\n const { get, set } = factory(\n () => trackRefValue(this),\n () => triggerRefValue(this)\n );\n this._get = get;\n this._set = set;\n }\n get value() {\n return this._get();\n }\n set value(newVal) {\n this._set(newVal);\n }\n}\nfunction customRef(factory) {\n return new CustomRefImpl(factory);\n}\nfunction toRefs(object) {\n if (!!(process.env.NODE_ENV !== \"production\") && !isProxy(object)) {\n warn$2(`toRefs() expects a reactive object but received a plain one.`);\n }\n const ret = isArray(object) ? new Array(object.length) : {};\n for (const key in object) {\n ret[key] = propertyToRef(object, key);\n }\n return ret;\n}\nclass ObjectRefImpl {\n constructor(_object, _key, _defaultValue) {\n this._object = _object;\n this._key = _key;\n this._defaultValue = _defaultValue;\n this.__v_isRef = true;\n }\n get value() {\n const val = this._object[this._key];\n return val === void 0 ? this._defaultValue : val;\n }\n set value(newVal) {\n this._object[this._key] = newVal;\n }\n get dep() {\n return getDepFromReactive(toRaw(this._object), this._key);\n }\n}\nclass GetterRefImpl {\n constructor(_getter) {\n this._getter = _getter;\n this.__v_isRef = true;\n this.__v_isReadonly = true;\n }\n get value() {\n return this._getter();\n }\n}\nfunction toRef(source, key, defaultValue) {\n if (isRef(source)) {\n return source;\n } else if (isFunction(source)) {\n return new GetterRefImpl(source);\n } else if (isObject(source) && arguments.length > 1) {\n return propertyToRef(source, key, defaultValue);\n } else {\n return ref(source);\n }\n}\nfunction propertyToRef(source, key, defaultValue) {\n const val = source[key];\n return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue);\n}\n\nconst stack = [];\nfunction pushWarningContext(vnode) {\n stack.push(vnode);\n}\nfunction popWarningContext() {\n stack.pop();\n}\nfunction warn$1(msg, ...args) {\n pauseTracking();\n const instance = stack.length ? stack[stack.length - 1].component : null;\n const appWarnHandler = instance && instance.appContext.config.warnHandler;\n const trace = getComponentTrace();\n if (appWarnHandler) {\n callWithErrorHandling(\n appWarnHandler,\n instance,\n 11,\n [\n msg + args.map((a) => {\n var _a, _b;\n return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a);\n }).join(\"\"),\n instance && instance.proxy,\n trace.map(\n ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`\n ).join(\"\\n\"),\n trace\n ]\n );\n } else {\n const warnArgs = [`[Vue warn]: ${msg}`, ...args];\n if (trace.length && // avoid spamming console during tests\n true) {\n warnArgs.push(`\n`, ...formatTrace(trace));\n }\n console.warn(...warnArgs);\n }\n resetTracking();\n}\nfunction getComponentTrace() {\n let currentVNode = stack[stack.length - 1];\n if (!currentVNode) {\n return [];\n }\n const normalizedStack = [];\n while (currentVNode) {\n const last = normalizedStack[0];\n if (last && last.vnode === currentVNode) {\n last.recurseCount++;\n } else {\n normalizedStack.push({\n vnode: currentVNode,\n recurseCount: 0\n });\n }\n const parentInstance = currentVNode.component && currentVNode.component.parent;\n currentVNode = parentInstance && parentInstance.vnode;\n }\n return normalizedStack;\n}\nfunction formatTrace(trace) {\n const logs = [];\n trace.forEach((entry, i) => {\n logs.push(...i === 0 ? [] : [`\n`], ...formatTraceEntry(entry));\n });\n return logs;\n}\nfunction formatTraceEntry({ vnode, recurseCount }) {\n const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``;\n const isRoot = vnode.component ? vnode.component.parent == null : false;\n const open = ` at <${formatComponentName(\n vnode.component,\n vnode.type,\n isRoot\n )}`;\n const close = `>` + postfix;\n return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close];\n}\nfunction formatProps(props) {\n const res = [];\n const keys = Object.keys(props);\n keys.slice(0, 3).forEach((key) => {\n res.push(...formatProp(key, props[key]));\n });\n if (keys.length > 3) {\n res.push(` ...`);\n }\n return res;\n}\nfunction formatProp(key, value, raw) {\n if (isString(value)) {\n value = JSON.stringify(value);\n return raw ? value : [`${key}=${value}`];\n } else if (typeof value === \"number\" || typeof value === \"boolean\" || value == null) {\n return raw ? value : [`${key}=${value}`];\n } else if (isRef(value)) {\n value = formatProp(key, toRaw(value.value), true);\n return raw ? value : [`${key}=Ref<`, value, `>`];\n } else if (isFunction(value)) {\n return [`${key}=fn${value.name ? `<${value.name}>` : ``}`];\n } else {\n value = toRaw(value);\n return raw ? value : [`${key}=`, value];\n }\n}\n\nconst ErrorTypeStrings = {\n [\"sp\"]: \"serverPrefetch hook\",\n [\"bc\"]: \"beforeCreate hook\",\n [\"c\"]: \"created hook\",\n [\"bm\"]: \"beforeMount hook\",\n [\"m\"]: \"mounted hook\",\n [\"bu\"]: \"beforeUpdate hook\",\n [\"u\"]: \"updated\",\n [\"bum\"]: \"beforeUnmount hook\",\n [\"um\"]: \"unmounted hook\",\n [\"a\"]: \"activated hook\",\n [\"da\"]: \"deactivated hook\",\n [\"ec\"]: \"errorCaptured hook\",\n [\"rtc\"]: \"renderTracked hook\",\n [\"rtg\"]: \"renderTriggered hook\",\n [0]: \"setup function\",\n [1]: \"render function\",\n [2]: \"watcher getter\",\n [3]: \"watcher callback\",\n [4]: \"watcher cleanup function\",\n [5]: \"native event handler\",\n [6]: \"component event handler\",\n [7]: \"vnode hook\",\n [8]: \"directive hook\",\n [9]: \"transition hook\",\n [10]: \"app errorHandler\",\n [11]: \"app warnHandler\",\n [12]: \"ref function\",\n [13]: \"async component loader\",\n [14]: \"scheduler flush. This is likely a Vue internals bug. Please open an issue at https://github.com/vuejs/core .\"\n};\nfunction callWithErrorHandling(fn, instance, type, args) {\n try {\n return args ? fn(...args) : fn();\n } catch (err) {\n handleError(err, instance, type);\n }\n}\nfunction callWithAsyncErrorHandling(fn, instance, type, args) {\n if (isFunction(fn)) {\n const res = callWithErrorHandling(fn, instance, type, args);\n if (res && isPromise(res)) {\n res.catch((err) => {\n handleError(err, instance, type);\n });\n }\n return res;\n }\n const values = [];\n for (let i = 0; i < fn.length; i++) {\n values.push(callWithAsyncErrorHandling(fn[i], instance, type, args));\n }\n return values;\n}\nfunction handleError(err, instance, type, throwInDev = true) {\n const contextVNode = instance ? instance.vnode : null;\n if (instance) {\n let cur = instance.parent;\n const exposedInstance = instance.proxy;\n const errorInfo = !!(process.env.NODE_ENV !== \"production\") ? ErrorTypeStrings[type] || type : `https://vuejs.org/error-reference/#runtime-${type}`;\n while (cur) {\n const errorCapturedHooks = cur.ec;\n if (errorCapturedHooks) {\n for (let i = 0; i < errorCapturedHooks.length; i++) {\n if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) {\n return;\n }\n }\n }\n cur = cur.parent;\n }\n const appErrorHandler = instance.appContext.config.errorHandler;\n if (appErrorHandler) {\n callWithErrorHandling(\n appErrorHandler,\n null,\n 10,\n [err, exposedInstance, errorInfo]\n );\n return;\n }\n }\n logError(err, type, contextVNode, throwInDev);\n}\nfunction logError(err, type, contextVNode, throwInDev = true) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n const info = ErrorTypeStrings[type] || type;\n if (contextVNode) {\n pushWarningContext(contextVNode);\n }\n warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`);\n if (contextVNode) {\n popWarningContext();\n }\n if (throwInDev) {\n console.error(err);\n } else {\n console.error(err);\n }\n } else {\n console.error(err);\n }\n}\n\nlet isFlushing = false;\nlet isFlushPending = false;\nconst queue = [];\nlet flushIndex = 0;\nconst pendingPostFlushCbs = [];\nlet activePostFlushCbs = null;\nlet postFlushIndex = 0;\nconst resolvedPromise = /* @__PURE__ */ Promise.resolve();\nlet currentFlushPromise = null;\nconst RECURSION_LIMIT = 100;\nfunction nextTick$1(fn) {\n const p = currentFlushPromise || resolvedPromise;\n return fn ? p.then(this ? fn.bind(this) : fn) : p;\n}\nfunction findInsertionIndex(id) {\n let start = flushIndex + 1;\n let end = queue.length;\n while (start < end) {\n const middle = start + end >>> 1;\n const middleJob = queue[middle];\n const middleJobId = getId(middleJob);\n if (middleJobId < id || middleJobId === id && middleJob.pre) {\n start = middle + 1;\n } else {\n end = middle;\n }\n }\n return start;\n}\nfunction queueJob(job) {\n if (!queue.length || !queue.includes(\n job,\n isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex\n )) {\n if (job.id == null) {\n queue.push(job);\n } else {\n queue.splice(findInsertionIndex(job.id), 0, job);\n }\n queueFlush();\n }\n}\nfunction queueFlush() {\n if (!isFlushing && !isFlushPending) {\n isFlushPending = true;\n currentFlushPromise = resolvedPromise.then(flushJobs);\n }\n}\nfunction hasQueueJob(job) {\n return queue.indexOf(job) > -1;\n}\nfunction invalidateJob(job) {\n const i = queue.indexOf(job);\n if (i > flushIndex) {\n queue.splice(i, 1);\n }\n}\nfunction queuePostFlushCb(cb) {\n if (!isArray(cb)) {\n if (!activePostFlushCbs || !activePostFlushCbs.includes(\n cb,\n cb.allowRecurse ? postFlushIndex + 1 : postFlushIndex\n )) {\n pendingPostFlushCbs.push(cb);\n }\n } else {\n pendingPostFlushCbs.push(...cb);\n }\n queueFlush();\n}\nfunction flushPreFlushCbs(instance, seen, i = isFlushing ? flushIndex + 1 : 0) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n seen = seen || /* @__PURE__ */ new Map();\n }\n for (; i < queue.length; i++) {\n const cb = queue[i];\n if (cb && cb.pre) {\n if (!!(process.env.NODE_ENV !== \"production\") && checkRecursiveUpdates(seen, cb)) {\n continue;\n }\n queue.splice(i, 1);\n i--;\n cb();\n }\n }\n}\nfunction flushPostFlushCbs(seen) {\n if (pendingPostFlushCbs.length) {\n const deduped = [...new Set(pendingPostFlushCbs)].sort(\n (a, b) => getId(a) - getId(b)\n );\n pendingPostFlushCbs.length = 0;\n if (activePostFlushCbs) {\n activePostFlushCbs.push(...deduped);\n return;\n }\n activePostFlushCbs = deduped;\n if (!!(process.env.NODE_ENV !== \"production\")) {\n seen = seen || /* @__PURE__ */ new Map();\n }\n for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) {\n if (!!(process.env.NODE_ENV !== \"production\") && checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) {\n continue;\n }\n activePostFlushCbs[postFlushIndex]();\n }\n activePostFlushCbs = null;\n postFlushIndex = 0;\n }\n}\nconst getId = (job) => job.id == null ? Infinity : job.id;\nconst comparator = (a, b) => {\n const diff = getId(a) - getId(b);\n if (diff === 0) {\n if (a.pre && !b.pre)\n return -1;\n if (b.pre && !a.pre)\n return 1;\n }\n return diff;\n};\nfunction flushJobs(seen) {\n isFlushPending = false;\n isFlushing = true;\n if (!!(process.env.NODE_ENV !== \"production\")) {\n seen = seen || /* @__PURE__ */ new Map();\n }\n queue.sort(comparator);\n const check = !!(process.env.NODE_ENV !== \"production\") ? (job) => checkRecursiveUpdates(seen, job) : NOOP;\n try {\n for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {\n const job = queue[flushIndex];\n if (job && job.active !== false) {\n if (!!(process.env.NODE_ENV !== \"production\") && check(job)) {\n continue;\n }\n callWithErrorHandling(job, null, 14);\n }\n }\n } finally {\n flushIndex = 0;\n queue.length = 0;\n flushPostFlushCbs(seen);\n isFlushing = false;\n currentFlushPromise = null;\n if (queue.length || pendingPostFlushCbs.length) {\n flushJobs(seen);\n }\n }\n}\nfunction checkRecursiveUpdates(seen, fn) {\n if (!seen.has(fn)) {\n seen.set(fn, 1);\n } else {\n const count = seen.get(fn);\n if (count > RECURSION_LIMIT) {\n const instance = fn.ownerInstance;\n const componentName = instance && getComponentName(instance.type);\n handleError(\n `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`,\n null,\n 10\n );\n return true;\n } else {\n seen.set(fn, count + 1);\n }\n }\n}\n\nlet devtools;\nlet buffer = [];\nlet devtoolsNotInstalled = false;\nfunction emit$1(event, ...args) {\n if (devtools) {\n devtools.emit(event, ...args);\n } else if (!devtoolsNotInstalled) {\n buffer.push({ event, args });\n }\n}\nfunction setDevtoolsHook(hook, target) {\n var _a, _b;\n devtools = hook;\n if (devtools) {\n devtools.enabled = true;\n buffer.forEach(({ event, args }) => devtools.emit(event, ...args));\n buffer = [];\n } else if (\n // handle late devtools injection - only do this if we are in an actual\n // browser environment to avoid the timer handle stalling test runner exit\n // (#4815)\n typeof window !== \"undefined\" && // some envs mock window but not fully\n window.HTMLElement && // also exclude jsdom\n !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes(\"jsdom\"))\n ) {\n const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || [];\n replay.push((newHook) => {\n setDevtoolsHook(newHook, target);\n });\n setTimeout(() => {\n if (!devtools) {\n target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null;\n devtoolsNotInstalled = true;\n buffer = [];\n }\n }, 3e3);\n } else {\n devtoolsNotInstalled = true;\n buffer = [];\n }\n}\nfunction devtoolsInitApp(app, version) {\n emit$1(\"app:init\" /* APP_INIT */, app, version, {\n Fragment,\n Text,\n Comment,\n Static\n });\n}\nconst devtoolsComponentAdded = /* @__PURE__ */ createDevtoolsComponentHook(\n \"component:added\" /* COMPONENT_ADDED */\n);\nconst devtoolsComponentUpdated = /* @__PURE__ */ createDevtoolsComponentHook(\"component:updated\" /* COMPONENT_UPDATED */);\nconst _devtoolsComponentRemoved = /* @__PURE__ */ createDevtoolsComponentHook(\n \"component:removed\" /* COMPONENT_REMOVED */\n);\nconst devtoolsComponentRemoved = (component) => {\n if (devtools && typeof devtools.cleanupBuffer === \"function\" && // remove the component if it wasn't buffered\n !devtools.cleanupBuffer(component)) {\n _devtoolsComponentRemoved(component);\n }\n};\n/*! #__NO_SIDE_EFFECTS__ */\n// @__NO_SIDE_EFFECTS__\nfunction createDevtoolsComponentHook(hook) {\n return (component) => {\n emit$1(\n hook,\n component.appContext.app,\n component.uid,\n // fixed by xxxxxx\n // 为 0 是 App,无 parent 是 Page 指向 App\n component.uid === 0 ? void 0 : component.parent ? component.parent.uid : 0,\n component\n );\n };\n}\nconst devtoolsPerfStart = /* @__PURE__ */ createDevtoolsPerformanceHook(\n \"perf:start\" /* PERFORMANCE_START */\n);\nconst devtoolsPerfEnd = /* @__PURE__ */ createDevtoolsPerformanceHook(\n \"perf:end\" /* PERFORMANCE_END */\n);\nfunction createDevtoolsPerformanceHook(hook) {\n return (component, type, time) => {\n emit$1(hook, component.appContext.app, component.uid, component, type, time);\n };\n}\nfunction devtoolsComponentEmit(component, event, params) {\n emit$1(\n \"component:emit\" /* COMPONENT_EMIT */,\n component.appContext.app,\n component,\n event,\n params\n );\n}\n\nfunction emit(instance, event, ...rawArgs) {\n if (instance.isUnmounted)\n return;\n const props = instance.vnode.props || EMPTY_OBJ;\n if (!!(process.env.NODE_ENV !== \"production\")) {\n const {\n emitsOptions,\n propsOptions: [propsOptions]\n } = instance;\n if (emitsOptions) {\n if (!(event in emitsOptions) && true) {\n if (!propsOptions || !(toHandlerKey(event) in propsOptions)) {\n warn$1(\n `Component emitted event \"${event}\" but it is neither declared in the emits option nor as an \"${toHandlerKey(event)}\" prop.`\n );\n }\n } else {\n const validator = emitsOptions[event];\n if (isFunction(validator)) {\n const isValid = validator(...rawArgs);\n if (!isValid) {\n warn$1(\n `Invalid event arguments: event validation failed for event \"${event}\".`\n );\n }\n }\n }\n }\n }\n let args = rawArgs;\n const isModelListener = event.startsWith(\"update:\");\n const modelArg = isModelListener && event.slice(7);\n if (modelArg && modelArg in props) {\n const modifiersKey = `${modelArg === \"modelValue\" ? \"model\" : modelArg}Modifiers`;\n const { number, trim } = props[modifiersKey] || EMPTY_OBJ;\n if (trim) {\n args = rawArgs.map((a) => isString(a) ? a.trim() : a);\n }\n if (number) {\n args = rawArgs.map(looseToNumber);\n }\n }\n if (!!(process.env.NODE_ENV !== \"production\") || __VUE_PROD_DEVTOOLS__) {\n devtoolsComponentEmit(instance, event, args);\n }\n if (!!(process.env.NODE_ENV !== \"production\")) {\n const lowerCaseEvent = event.toLowerCase();\n if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) {\n warn$1(\n `Event \"${lowerCaseEvent}\" is emitted in component ${formatComponentName(\n instance,\n instance.type\n )} but the handler is registered for \"${event}\". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use \"${hyphenate(\n event\n )}\" instead of \"${event}\".`\n );\n }\n }\n let handlerName;\n let handler = props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249)\n props[handlerName = toHandlerKey(camelize(event))];\n if (!handler && isModelListener) {\n handler = props[handlerName = toHandlerKey(hyphenate(event))];\n }\n if (handler) {\n callWithAsyncErrorHandling(\n handler,\n instance,\n 6,\n args\n );\n }\n const onceHandler = props[handlerName + `Once`];\n if (onceHandler) {\n if (!instance.emitted) {\n instance.emitted = {};\n } else if (instance.emitted[handlerName]) {\n return;\n }\n instance.emitted[handlerName] = true;\n callWithAsyncErrorHandling(\n onceHandler,\n instance,\n 6,\n args\n );\n }\n}\nfunction normalizeEmitsOptions(comp, appContext, asMixin = false) {\n const cache = appContext.emitsCache;\n const cached = cache.get(comp);\n if (cached !== void 0) {\n return cached;\n }\n const raw = comp.emits;\n let normalized = {};\n let hasExtends = false;\n if (__VUE_OPTIONS_API__ && !isFunction(comp)) {\n const extendEmits = (raw2) => {\n const normalizedFromExtend = normalizeEmitsOptions(raw2, appContext, true);\n if (normalizedFromExtend) {\n hasExtends = true;\n extend(normalized, normalizedFromExtend);\n }\n };\n if (!asMixin && appContext.mixins.length) {\n appContext.mixins.forEach(extendEmits);\n }\n if (comp.extends) {\n extendEmits(comp.extends);\n }\n if (comp.mixins) {\n comp.mixins.forEach(extendEmits);\n }\n }\n if (!raw && !hasExtends) {\n if (isObject(comp)) {\n cache.set(comp, null);\n }\n return null;\n }\n if (isArray(raw)) {\n raw.forEach((key) => normalized[key] = null);\n } else {\n extend(normalized, raw);\n }\n if (isObject(comp)) {\n cache.set(comp, normalized);\n }\n return normalized;\n}\nfunction isEmitListener(options, key) {\n if (!options || !isOn(key)) {\n return false;\n }\n key = key.slice(2).replace(/Once$/, \"\");\n return hasOwn(options, key[0].toLowerCase() + key.slice(1)) || hasOwn(options, hyphenate(key)) || hasOwn(options, key);\n}\n\nlet currentRenderingInstance = null;\nlet currentScopeId = null;\nfunction setCurrentRenderingInstance(instance) {\n const prev = currentRenderingInstance;\n currentRenderingInstance = instance;\n currentScopeId = instance && instance.type.__scopeId || null;\n return prev;\n}\nconst withScopeId = (_id) => withCtx;\nfunction withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) {\n if (!ctx)\n return fn;\n if (fn._n) {\n return fn;\n }\n const renderFnWithContext = (...args) => {\n if (renderFnWithContext._d) {\n setBlockTracking(-1);\n }\n const prevInstance = setCurrentRenderingInstance(ctx);\n let res;\n try {\n res = fn(...args);\n } finally {\n setCurrentRenderingInstance(prevInstance);\n if (renderFnWithContext._d) {\n setBlockTracking(1);\n }\n }\n if (!!(process.env.NODE_ENV !== \"production\") || __VUE_PROD_DEVTOOLS__) {\n devtoolsComponentUpdated(ctx);\n }\n return res;\n };\n renderFnWithContext._n = true;\n renderFnWithContext._c = true;\n renderFnWithContext._d = true;\n return renderFnWithContext;\n}\n\nfunction markAttrsAccessed() {\n}\n\nconst COMPONENTS = \"components\";\nconst DIRECTIVES = \"directives\";\nfunction resolveComponent(name, maybeSelfReference) {\n return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name;\n}\nconst NULL_DYNAMIC_COMPONENT = Symbol.for(\"v-ndc\");\nfunction resolveDirective(name) {\n return resolveAsset(DIRECTIVES, name);\n}\nfunction resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) {\n const instance = currentRenderingInstance || currentInstance;\n if (instance) {\n const Component = instance.type;\n if (type === COMPONENTS) {\n const selfName = getComponentName(\n Component,\n false\n );\n if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) {\n return Component;\n }\n }\n const res = (\n // local registration\n // check instance[type] first which is resolved for options API\n resolve(instance[type] || Component[type], name) || // global registration\n resolve(instance.appContext[type], name)\n );\n if (!res && maybeSelfReference) {\n return Component;\n }\n if (!!(process.env.NODE_ENV !== \"production\") && warnMissing && !res) {\n const extra = type === COMPONENTS ? `\nIf this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``;\n warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`);\n }\n return res;\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(\n `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().`\n );\n }\n}\nfunction resolve(registry, name) {\n return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]);\n}\n\nconst ssrContextKey = Symbol.for(\"v-scx\");\nconst useSSRContext = () => {\n {\n const ctx = inject(ssrContextKey);\n if (!ctx) {\n !!(process.env.NODE_ENV !== \"production\") && warn$1(\n `Server rendering context not provided. Make sure to only call useSSRContext() conditionally in the server build.`\n );\n }\n return ctx;\n }\n};\n\nfunction watchEffect(effect, options) {\n return doWatch(effect, null, options);\n}\nfunction watchPostEffect(effect, options) {\n return doWatch(\n effect,\n null,\n !!(process.env.NODE_ENV !== \"production\") ? extend({}, options, { flush: \"post\" }) : { flush: \"post\" }\n );\n}\nfunction watchSyncEffect(effect, options) {\n return doWatch(\n effect,\n null,\n !!(process.env.NODE_ENV !== \"production\") ? extend({}, options, { flush: \"sync\" }) : { flush: \"sync\" }\n );\n}\nconst INITIAL_WATCHER_VALUE = {};\nfunction watch(source, cb, options) {\n if (!!(process.env.NODE_ENV !== \"production\") && !isFunction(cb)) {\n warn$1(\n `\\`watch(fn, options?)\\` signature has been moved to a separate API. Use \\`watchEffect(fn, options?)\\` instead. \\`watch\\` now only supports \\`watch(source, cb, options?) signature.`\n );\n }\n return doWatch(source, cb, options);\n}\nfunction doWatch(source, cb, {\n immediate,\n deep,\n flush,\n once,\n onTrack,\n onTrigger\n} = EMPTY_OBJ) {\n if (cb && once) {\n const _cb = cb;\n cb = (...args) => {\n _cb(...args);\n unwatch();\n };\n }\n if (!!(process.env.NODE_ENV !== \"production\") && deep !== void 0 && typeof deep === \"number\") {\n warn$1(\n `watch() \"deep\" option with number value will be used as watch depth in future versions. Please use a boolean instead to avoid potential breakage.`\n );\n }\n if (!!(process.env.NODE_ENV !== \"production\") && !cb) {\n if (immediate !== void 0) {\n warn$1(\n `watch() \"immediate\" option is only respected when using the watch(source, callback, options?) signature.`\n );\n }\n if (deep !== void 0) {\n warn$1(\n `watch() \"deep\" option is only respected when using the watch(source, callback, options?) signature.`\n );\n }\n if (once !== void 0) {\n warn$1(\n `watch() \"once\" option is only respected when using the watch(source, callback, options?) signature.`\n );\n }\n }\n const warnInvalidSource = (s) => {\n warn$1(\n `Invalid watch source: `,\n s,\n `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.`\n );\n };\n const instance = currentInstance;\n const reactiveGetter = (source2) => deep === true ? source2 : (\n // for deep: false, only traverse root-level properties\n traverse(source2, deep === false ? 1 : void 0)\n );\n let getter;\n let forceTrigger = false;\n let isMultiSource = false;\n if (isRef(source)) {\n getter = () => source.value;\n forceTrigger = isShallow(source);\n } else if (isReactive(source)) {\n getter = () => reactiveGetter(source);\n forceTrigger = true;\n } else if (isArray(source)) {\n isMultiSource = true;\n forceTrigger = source.some((s) => isReactive(s) || isShallow(s));\n getter = () => source.map((s) => {\n if (isRef(s)) {\n return s.value;\n } else if (isReactive(s)) {\n return reactiveGetter(s);\n } else if (isFunction(s)) {\n return callWithErrorHandling(s, instance, 2);\n } else {\n !!(process.env.NODE_ENV !== \"production\") && warnInvalidSource(s);\n }\n });\n } else if (isFunction(source)) {\n if (cb) {\n getter = () => callWithErrorHandling(source, instance, 2);\n } else {\n getter = () => {\n if (cleanup) {\n cleanup();\n }\n return callWithAsyncErrorHandling(\n source,\n instance,\n 3,\n [onCleanup]\n );\n };\n }\n } else {\n getter = NOOP;\n !!(process.env.NODE_ENV !== \"production\") && warnInvalidSource(source);\n }\n if (cb && deep) {\n const baseGetter = getter;\n getter = () => traverse(baseGetter());\n }\n let cleanup;\n let onCleanup = (fn) => {\n cleanup = effect.onStop = () => {\n callWithErrorHandling(fn, instance, 4);\n cleanup = effect.onStop = void 0;\n };\n };\n let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE;\n const job = () => {\n if (!effect.active || !effect.dirty) {\n return;\n }\n if (cb) {\n const newValue = effect.run();\n if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue)) || false) {\n if (cleanup) {\n cleanup();\n }\n callWithAsyncErrorHandling(cb, instance, 3, [\n newValue,\n // pass undefined as the old value when it's changed for the first time\n oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue,\n onCleanup\n ]);\n oldValue = newValue;\n }\n } else {\n effect.run();\n }\n };\n job.allowRecurse = !!cb;\n let scheduler;\n if (flush === \"sync\") {\n scheduler = job;\n } else if (flush === \"post\") {\n scheduler = () => queuePostRenderEffect$1(job, instance && instance.suspense);\n } else {\n job.pre = true;\n if (instance)\n job.id = instance.uid;\n scheduler = () => queueJob(job);\n }\n const effect = new ReactiveEffect(getter, NOOP, scheduler);\n const scope = getCurrentScope();\n const unwatch = () => {\n effect.stop();\n if (scope) {\n remove(scope.effects, effect);\n }\n };\n if (!!(process.env.NODE_ENV !== \"production\")) {\n effect.onTrack = onTrack;\n effect.onTrigger = onTrigger;\n }\n if (cb) {\n if (immediate) {\n job();\n } else {\n oldValue = effect.run();\n }\n } else if (flush === \"post\") {\n queuePostRenderEffect$1(\n effect.run.bind(effect),\n instance && instance.suspense\n );\n } else {\n effect.run();\n }\n return unwatch;\n}\nfunction instanceWatch(source, value, options) {\n const publicThis = this.proxy;\n const getter = isString(source) ? source.includes(\".\") ? createPathGetter(publicThis, source) : () => publicThis[source] : source.bind(publicThis, publicThis);\n let cb;\n if (isFunction(value)) {\n cb = value;\n } else {\n cb = value.handler;\n options = value;\n }\n const reset = setCurrentInstance(this);\n const res = doWatch(getter, cb.bind(publicThis), options);\n reset();\n return res;\n}\nfunction createPathGetter(ctx, path) {\n const segments = path.split(\".\");\n return () => {\n let cur = ctx;\n for (let i = 0; i < segments.length && cur; i++) {\n cur = cur[segments[i]];\n }\n return cur;\n };\n}\nfunction traverse(value, depth, currentDepth = 0, seen) {\n if (!isObject(value) || value[\"__v_skip\"]) {\n return value;\n }\n if (depth && depth > 0) {\n if (currentDepth >= depth) {\n return value;\n }\n currentDepth++;\n }\n seen = seen || /* @__PURE__ */ new Set();\n if (seen.has(value)) {\n return value;\n }\n seen.add(value);\n if (isRef(value)) {\n traverse(value.value, depth, currentDepth, seen);\n } else if (isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n traverse(value[i], depth, currentDepth, seen);\n }\n } else if (isSet(value) || isMap(value)) {\n value.forEach((v) => {\n traverse(v, depth, currentDepth, seen);\n });\n } else if (isPlainObject(value)) {\n for (const key in value) {\n traverse(value[key], depth, currentDepth, seen);\n }\n }\n return value;\n}\n\nfunction validateDirectiveName(name) {\n if (isBuiltInDirective(name)) {\n warn$1(\"Do not use built-in directive ids as custom directive id: \" + name);\n }\n}\nfunction withDirectives(vnode, directives) {\n if (currentRenderingInstance === null) {\n !!(process.env.NODE_ENV !== \"production\") && warn$1(`withDirectives can only be used inside render functions.`);\n return vnode;\n }\n const instance = getExposeProxy(currentRenderingInstance) || currentRenderingInstance.proxy;\n const bindings = vnode.dirs || (vnode.dirs = []);\n for (let i = 0; i < directives.length; i++) {\n let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i];\n if (dir) {\n if (isFunction(dir)) {\n dir = {\n mounted: dir,\n updated: dir\n };\n }\n if (dir.deep) {\n traverse(value);\n }\n bindings.push({\n dir,\n instance,\n value,\n oldValue: void 0,\n arg,\n modifiers\n });\n }\n }\n return vnode;\n}\n\nfunction createAppContext() {\n return {\n app: null,\n config: {\n isNativeTag: NO,\n performance: false,\n globalProperties: {},\n optionMergeStrategies: {},\n errorHandler: void 0,\n warnHandler: void 0,\n compilerOptions: {}\n },\n mixins: [],\n components: {},\n directives: {},\n provides: /* @__PURE__ */ Object.create(null),\n optionsCache: /* @__PURE__ */ new WeakMap(),\n propsCache: /* @__PURE__ */ new WeakMap(),\n emitsCache: /* @__PURE__ */ new WeakMap()\n };\n}\nlet uid$1 = 0;\nfunction createAppAPI(render, hydrate) {\n return function createApp(rootComponent, rootProps = null) {\n if (!isFunction(rootComponent)) {\n rootComponent = extend({}, rootComponent);\n }\n if (rootProps != null && !isObject(rootProps)) {\n !!(process.env.NODE_ENV !== \"production\") && warn$1(`root props passed to app.mount() must be an object.`);\n rootProps = null;\n }\n const context = createAppContext();\n const installedPlugins = /* @__PURE__ */ new WeakSet();\n const app = context.app = {\n _uid: uid$1++,\n _component: rootComponent,\n _props: rootProps,\n _container: null,\n _context: context,\n _instance: null,\n version,\n get config() {\n return context.config;\n },\n set config(v) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(\n `app.config cannot be replaced. Modify individual options instead.`\n );\n }\n },\n use(plugin, ...options) {\n if (installedPlugins.has(plugin)) {\n !!(process.env.NODE_ENV !== \"production\") && warn$1(`Plugin has already been applied to target app.`);\n } else if (plugin && isFunction(plugin.install)) {\n installedPlugins.add(plugin);\n plugin.install(app, ...options);\n } else if (isFunction(plugin)) {\n installedPlugins.add(plugin);\n plugin(app, ...options);\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(\n `A plugin must either be a function or an object with an \"install\" function.`\n );\n }\n return app;\n },\n mixin(mixin) {\n if (__VUE_OPTIONS_API__) {\n if (!context.mixins.includes(mixin)) {\n context.mixins.push(mixin);\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(\n \"Mixin has already been applied to target app\" + (mixin.name ? `: ${mixin.name}` : \"\")\n );\n }\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(\"Mixins are only available in builds supporting Options API\");\n }\n return app;\n },\n component(name, component) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n validateComponentName(name, context.config);\n }\n if (!component) {\n return context.components[name];\n }\n if (!!(process.env.NODE_ENV !== \"production\") && context.components[name]) {\n warn$1(`Component \"${name}\" has already been registered in target app.`);\n }\n context.components[name] = component;\n return app;\n },\n directive(name, directive) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n validateDirectiveName(name);\n }\n if (!directive) {\n return context.directives[name];\n }\n if (!!(process.env.NODE_ENV !== \"production\") && context.directives[name]) {\n warn$1(`Directive \"${name}\" has already been registered in target app.`);\n }\n context.directives[name] = directive;\n return app;\n },\n // fixed by xxxxxx\n mount() {\n },\n // fixed by xxxxxx\n unmount() {\n },\n provide(key, value) {\n if (!!(process.env.NODE_ENV !== \"production\") && key in context.provides) {\n warn$1(\n `App already provides property with key \"${String(key)}\". It will be overwritten with the new value.`\n );\n }\n context.provides[key] = value;\n return app;\n },\n runWithContext(fn) {\n const lastApp = currentApp;\n currentApp = app;\n try {\n return fn();\n } finally {\n currentApp = lastApp;\n }\n }\n };\n return app;\n };\n}\nlet currentApp = null;\n\nfunction provide(key, value) {\n if (!currentInstance) {\n if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(`provide() can only be used inside setup().`);\n }\n } else {\n let provides = currentInstance.provides;\n const parentProvides = currentInstance.parent && currentInstance.parent.provides;\n if (parentProvides === provides) {\n provides = currentInstance.provides = Object.create(parentProvides);\n }\n provides[key] = value;\n if (currentInstance.type.mpType === \"app\") {\n currentInstance.appContext.app.provide(key, value);\n }\n }\n}\nfunction inject(key, defaultValue, treatDefaultAsFactory = false) {\n const instance = currentInstance || currentRenderingInstance;\n if (instance || currentApp) {\n const provides = instance ? instance.parent == null ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : currentApp._context.provides;\n if (provides && key in provides) {\n return provides[key];\n } else if (arguments.length > 1) {\n return treatDefaultAsFactory && isFunction(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue;\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(`injection \"${String(key)}\" not found.`);\n }\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n warn$1(`inject() can only be used inside setup() or functional components.`);\n }\n}\nfunction hasInjectionContext() {\n return !!(currentInstance || currentRenderingInstance || currentApp);\n}\n\n/*! #__NO_SIDE_EFFECTS__ */\n// @__NO_SIDE_EFFECTS__\nfunction defineComponent(options, extraOptions) {\n return isFunction(options) ? (\n // #8326: extend call and options.name access are considered side-effects\n // by Rollup, so we have to wrap it in a pure-annotated IIFE.\n /* @__PURE__ */ (() => extend({ name: options.name }, extraOptions, { setup: options }))()\n ) : options;\n}\n\nconst isKeepAlive = (vnode) => vnode.type.__isKeepAlive;\nfunction onActivated(hook, target) {\n registerKeepAliveHook(hook, \"a\", target);\n}\nfunction onDeactivated(hook, target) {\n registerKeepAliveHook(hook, \"da\", target);\n}\nfunction registerKeepAliveHook(hook, type, target = currentInstance) {\n const wrappedHook = hook.__wdc || (hook.__wdc = () => {\n let current = target;\n while (current) {\n if (current.isDeactivated) {\n return;\n }\n current = current.parent;\n }\n return hook();\n });\n injectHook(type, wrappedHook, target);\n if (target) {\n let current = target.parent;\n while (current && current.parent) {\n if (isKeepAlive(current.parent.vnode)) {\n injectToKeepAliveRoot(wrappedHook, type, target, current);\n }\n current = current.parent;\n }\n }\n}\nfunction injectToKeepAliveRoot(hook, type, target, keepAliveRoot) {\n const injected = injectHook(\n type,\n hook,\n keepAliveRoot,\n true\n /* prepend */\n );\n onUnmounted(() => {\n remove(keepAliveRoot[type], injected);\n }, target);\n}\n\nfunction injectHook(type, hook, target = currentInstance, prepend = false) {\n if (target) {\n if (isRootHook(type)) {\n target = target.root;\n }\n const hooks = target[type] || (target[type] = []);\n const wrappedHook = hook.__weh || (hook.__weh = (...args) => {\n if (target.isUnmounted) {\n return;\n }\n pauseTracking();\n const reset = setCurrentInstance(target);\n const res = callWithAsyncErrorHandling(hook, target, type, args);\n reset();\n resetTracking();\n return res;\n });\n if (prepend) {\n hooks.unshift(wrappedHook);\n } else {\n hooks.push(wrappedHook);\n }\n return wrappedHook;\n } else if (!!(process.env.NODE_ENV !== \"production\")) {\n const apiName = toHandlerKey(\n (ErrorTypeStrings[type] || type.replace(/^on/, \"\")).replace(/ hook$/, \"\")\n );\n warn$1(\n `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().` + (``)\n );\n }\n}\nconst createHook = (lifecycle) => (hook, target = currentInstance) => (\n // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)\n (!isInSSRComponentSetup || lifecycle === \"sp\") && injectHook(lifecycle, (...args) => hook(...args), target)\n);\nconst onBeforeMount = createHook(\"bm\");\nconst onMounted = createHook(\"m\");\nconst onBeforeUpdate = createHook(\"bu\");\nconst onUpdated = createHook(\"u\");\nconst onBeforeUnmount = createHook(\"bum\");\nconst onUnmounted = createHook(\"um\");\nconst onServerPrefetch = createHook(\"sp\");\nconst onRenderTriggered = createHook(\n \"rtg\"\n);\nconst onRenderTracked = createHook(\n \"rtc\"\n);\nfunction onErrorCaptured(hook, target = currentInstance) {\n injectHook(\"ec\", hook, target);\n}\n\nfunction toHandlers(obj, preserveCaseIfNecessary) {\n const ret = {};\n if (!!(process.env.NODE_ENV !== \"production\") && !isObject(obj)) {\n warn$1(`v-on with no argument expects an object value.`);\n return ret;\n }\n for (const key in obj) {\n ret[preserveCaseIfNecessary && /[A-Z]/.test(key) ? `on:${key}` : toHandlerKey(key)] = obj[key];\n }\n return ret;\n}\n\nconst getPublicInstance = (i) => {\n if (!i)\n return null;\n if (isStatefulComponent(i))\n return getExposeProxy(i) || i.proxy;\n return getPublicInstance(i.parent);\n};\nfunction getComponentInternalInstance(i) {\n return i;\n}\nconst publicPropertiesMap = (\n // Move PURE marker to new line to workaround compiler discarding it\n // due to type annotation\n /* @__PURE__ */ extend(/* @__PURE__ */ Object.create(null), {\n // fixed by xxxxxx\n $: getComponentInternalInstance,\n // fixed by xxxxxx vue-i18n 在 dev 模式,访问了 $el,故模拟一个假的\n // $el: i => i.vnode.el,\n $el: (i) => i.__$el || (i.__$el = {}),\n $data: (i) => i.data,\n $props: (i) => !!(process.env.NODE_ENV !== \"production\") ? shallowReadonly(i.props) : i.props,\n $attrs: (i) => !!(process.env.NODE_ENV !== \"production\") ? shallowReadonly(i.attrs) : i.attrs,\n $slots: (i) => !!(process.env.NODE_ENV !== \"production\") ? shallowReadonly(i.slots) : i.slots,\n $refs: (i) => !!(process.env.NODE_ENV !== \"production\") ? shallowReadonly(i.refs) : i.refs,\n $parent: (i) => getPublicInstance(i.parent),\n $root: (i) => getPublicInstance(i.root),\n $emit: (i) => i.emit,\n $options: (i) => __VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type,\n $forceUpdate: (i) => i.f || (i.f = () => {\n i.effect.dirty = true;\n queueJob(i.update);\n }),\n // $nextTick: i => i.n || (i.n = nextTick.bind(i.proxy!)),// fixed by xxxxxx\n $watch: (i) => __VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP\n })\n);\nconst isReservedPrefix = (key) => key === \"_\" || key === \"$\";\nconst hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key);\nconst PublicInstanceProxyHandlers = {\n get({ _: instance }, key) {\n const { ctx, setupState, data, props, accessCache, type, appContext } = instance;\n if (!!(process.env.NODE_ENV !== \"production\") && key === \"__isVue\") {\n return true;\n }\n let normalizedProps;\n if (key[0] !== \"$\") {\n const n = accessCache[key];\n if (n !== void 0) {\n switch (n) {\n case 1 /* SETUP */:\n return setupState[key];\n case 2 /* DATA */:\n return data[key];\n case 4 /* CONTEXT */:\n return ctx[key];\n case 3 /* PROPS */:\n return props[key];\n }\n } else if (hasSetupBinding(setupState, key)) {\n accessCache[key] = 1 /* SETUP */;\n return setupState[key];\n } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {\n accessCache[key] = 2 /* DATA */;\n return data[key];\n } else if (\n // only cache other properties when instance has declared (thus stable)\n // props\n (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key)\n ) {\n accessCache[key] = 3 /* PROPS */;\n return props[key];\n } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {\n accessCache[key] = 4 /* CONTEXT */;\n return ctx[key];\n } else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) {\n accessCache[key] = 0 /* OTHER */;\n }\n }\n const publicGetter = publicPropertiesMap[key];\n let cssModule, globalProperties;\n if (publicGetter) {\n if (key === \"$attrs\") {\n track(instance, \"get\", key);\n !!(process.env.NODE_ENV !== \"production\") && markAttrsAccessed();\n } else if (!!(process.env.NODE_ENV !== \"production\") && key === \"$slots\") {\n track(instance, \"get\", key);\n }\n return publicGetter(instance);\n } else if (\n // css module (injected by vue-loader)\n (cssModule = type.__cssModules) && (cssModule = cssModule[key])\n ) {\n return cssModule;\n } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {\n accessCache[key] = 4 /* CONTEXT */;\n return ctx[key];\n } else if (\n // global properties\n globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key)\n ) {\n {\n return globalProperties[key];\n }\n } else if (!!(process.env.NODE_ENV !== \"production\") && currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading\n // to infinite warning loop\n key.indexOf(\"__v\") !== 0)) {\n if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) {\n warn$1(\n `Property ${JSON.stringify(\n key\n )} must be accessed via $data because it starts with a reserved character (\"$\" or \"_\") and is not proxied on the render context.`\n );\n } else if (instance === currentRenderingInstance) {\n warn$1(\n `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.`\n );\n }\n }\n },\n set({ _: instance }, key, value) {\n const { data, setupState, ctx } = instance;\n if (hasSetupBinding(setupState, key)) {\n setupState[key] = value;\n return true;\n } else if (!!(process.env.NODE_ENV !== \"production\") && setupState.__isScriptSetup && hasOwn(setupState, key)) {\n warn$1(`Cannot mutate \r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/customer-service/customer-service.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref"],"mappings":";;;;;AA0DA,UAAM,OAAOA,cAAAA,IAAI;AAAA,MAChB,EAAE,UAAU,YAAa;AAAA,MACzB,EAAE,UAAU,UAAW;AAAA,MACvB,EAAE,UAAU,YAAa;AAAA,MACzB,EAAE,UAAU,aAAc;AAAA,MAC1B,EAAE,UAAU,UAAW;AAAA,IACxB,CAAC;AAGD,UAAM,WAAWA,cAAAA,IAAI;AAAA,MACpB;AAAA,QACC,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACN;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAGD,UAAM,YAAYA,cAAG,IAAC,EAAE;AACxB,UAAM,YAAYA,cAAG,IAAC,CAAC;AAGvB,UAAM,iBAAiB,CAAC,QAAQ;AAC/B,gBAAU,QAAQ,IAAI;AACtB,iBAAY;AAAA,IACb;AAGA,UAAM,aAAa,MAAM;AACxB,UAAI,CAAC,UAAU,MAAM,KAAM;AAAE;AAG7B,eAAS,MAAM,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,SAAS,UAAU;AAAA,QACnB,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,MACrF,CAAE;AAED,YAAM,cAAc,UAAU;AAC9B,gBAAU,QAAQ;AAGlB,iBAAW,MAAM;AAChB,kBAAU,QAAQ;AAAA,MAClB,GAAE,GAAG;AAGN,iBAAW,MAAM;AAChB,iBAAS,MAAM,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,SAAS,WAAW;AAAA,UAC7B,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,QACtF,CAAG;AAED,mBAAW,MAAM;AAChB,oBAAU,QAAQ;AAAA,QAClB,GAAE,GAAG;AAAA,MACN,GAAE,GAAI;AAAA,IACR;AAGA,UAAM,WAAW,CAAC,YAAY;AAC7B,UAAI,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAAS,IAAI,GAAG;AACrD,eAAO;AAAA,MACP,WAAU,QAAQ,SAAS,IAAI,GAAG;AAClC,eAAO;AAAA,MACT,WAAY,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAAS,IAAI,GAAG;AAC5D,eAAO;AAAA,MACP,WAAU,QAAQ,SAAS,IAAI,GAAG;AAClC,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvIA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-detail/device-detail.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-detail/device-detail.js.map new file mode 100644 index 0000000..d73df63 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-detail/device-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"device-detail.js","sources":["pages/device-detail/device-detail.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvZGV2aWNlLWRldGFpbC9kZXZpY2UtZGV0YWlsLnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/device-detail/device-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni","onMounted"],"mappings":";;;;;AA2GA,UAAM,eAAeA,cAAAA,IAAI;AAAA,MACxB,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,SAAS;AAAA,QACR;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACb;AAAA,QACD;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACb;AAAA,QACD;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACb;AAAA,QACD;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACb;AAAA,MACD;AAAA,IACF,CAAC;AAED,UAAM,qBAAqBA,cAAG,IAAC,IAAI;AAEnC,UAAM,wBAAwB;AAAA,MAC7B,OAAO,EAAE,KAAK,KAAK,KAAK,KAAK,MAAM,GAAI;AAAA,MACvC,MAAM,EAAE,KAAK,GAAG,MAAM,MAAO;AAAA,MAC7B,MAAM,EAAE,KAAK,MAAM,KAAK,GAAG,MAAM,OAAQ;AAAA,MACzC,OAAO,EAAE,KAAK,KAAK,MAAM,OAAQ;AAAA,MACjC,OAAO,EAAE,KAAK,KAAM,MAAM,OAAQ;AAAA,IACnC;AAGA,UAAM,iBAAiB,CAAC,WAAW;AAClC,aAAO,WAAW,WAAW,kBAAkB;AAAA,IAChD;AAGA,UAAM,mBAAmB,CAAC,WAAW;AACpC,UAAI,SAAS,IAAI;AAChB,eAAO;AAAA,MACT,WAAY,SAAS,IAAI;AACvB,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF;AAGA,UAAM,sBAAsB,MAAM;AACjCC,oBAAAA,MAAI,gBAAgB;AAAA,QACnB,UAAU,aAAa,MAAM,QAAQ,IAAI,OAAK,GAAG,EAAE,IAAI,OAAO,EAAE,MAAM,IAAI;AAAA,QAC1E,SAAS,CAAC,QAAQ;AACjB,gBAAM,iBAAiB,aAAa,MAAM,QAAQ,IAAI,QAAQ;AAC9DA,wBAAAA,MAAI,UAAU;AAAA,YACb,OAAO;AAAA,YACP,SAAS,SAAS,eAAe,IAAI;AAAA,YACrC,SAAS,CAAC,aAAa;AACtB,kBAAI,SAAS,SAAS;AAErB,+BAAe,SAAS;AACxB,sBAAM,MAAM,oBAAI,KAAM;AACtB,sBAAM,YAAY,IAAI,KAAK,IAAI,YAAa,GAAE,IAAI,aAAa,GAAG,IAAI,QAAO,CAAE;AAC/E,+BAAe,cAAc,UAAU,mBAAmB,SAAS;AAAA,kBAClE,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,KAAK;AAAA,gBACZ,CAAO;AACDA,8BAAAA,MAAI,UAAU;AAAA,kBACb,OAAO;AAAA,kBACP,MAAM;AAAA,gBACb,CAAO;AAAA,cACD;AAAA,YACD;AAAA,UACL,CAAI;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,qBAAqB,MAAM;AAChCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,yBAAyB,MAAM;AACpC,YAAM,KAAK,aAAa,MAAM;AAC9B,YAAM,MAAM,KAAK,yCAAyC,EAAE,KAAK;AACjEA,0BAAI,WAAW,EAAE,KAAK;AAAA,IACvB;AAEA,UAAM,2BAA2B,MAAM;AACtC,UAAI,CAAC,mBAAmB,OAAO;AAC9BA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AACD,YAAM,WAAW,mBAAmB,MAAM,MAAM,UAAU,aAAa,MAAM,EAAE;AAC/E,UAAI;AACHA,sBAAAA,MAAI,eAAe,sBAAsB,QAAQ,IAAI;AAAA,UACpD,GAAG,mBAAmB;AAAA,UACtB,IAAI;AAAA,QACP,CAAG;AACDA,sBAAAA,MAAI,WAAW;AAAA,UACd,KAAK,6DAA6D,QAAQ;AAAA,QAC7E,CAAG;AAAA,MACD,SAAQ,GAAG;AACXA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AAAA,MACD;AAAA,IACF;AAGAC,kBAAAA,UAAU,MAAM;AAEf,YAAM,QAAQ,gBAAiB;AAC/B,YAAM,cAAc,MAAM,MAAM,SAAS,CAAC;AAC1C,YAAM,UAAU,YAAY,WAAW,CAAE;AACzC,YAAM,KAAK,QAAQ;AAEnB,UAAI,IAAI;AACP,yBAAiB,EAAE;AACnB,+BAAuB,EAAE;AAAA,MAC3B,OAAQ;AACN,+BAAuB,aAAa,MAAM,EAAE;AAAA,MAC5C;AAGD,YAAM,QAAQ,YAAY,MAAM;AAC/B,yBAAkB;AAAA,MAClB,GAAE,GAAK;AAGR,aAAO,MAAM;AACZ,sBAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AAGD,UAAM,mBAAmB,CAAC,OAAO;AAEhC,YAAM,YAAY;AAAA,QACjB,kBAAkB;AAAA,UACjB,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,SAAS;AAAA,YACR,EAAE,MAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YACzE,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,UAAU,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,UAC1E;AAAA,QACD;AAAA,QACD,kBAAkB;AAAA,UACjB,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,SAAS;AAAA,YACR,EAAE,MAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YACzE,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,UAAU,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,UAC1E;AAAA,QACD;AAAA,QACD,kBAAkB;AAAA,UACjB,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,SAAS;AAAA,YACR,EAAE,MAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YACzE,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,UAAU,OAAO,UAAU,QAAQ,IAAI,aAAa,aAAc;AAAA,YAC1E,EAAE,MAAM,SAAS,OAAO,WAAW,QAAQ,IAAI,aAAa,aAAc;AAAA,UAC1E;AAAA,QACD;AAAA,MACD;AAED,UAAI,UAAU,EAAE,GAAG;AAClB,qBAAa,QAAQ,UAAU,EAAE;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,yBAAyB,CAAC,OAAO;AACtC,UAAI,SAAS;AACb,UAAI;AACH,cAAM,aAAaD,cAAAA,MAAI,eAAe,qBAAqB;AAC3D,YAAI,MAAM,QAAQ,UAAU,KAAK,WAAW,QAAQ;AACnD,gBAAM,mBAAmB,WACvB,OAAO,UAAQ,KAAK,OAAO,MAAM,KAAK,WAAW,YAAY,EAC7D,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,IAAI,EAAE,QAAS,IAAG,IAAI,KAAK,EAAE,IAAI,EAAE,QAAO,CAAE;AACxE,cAAI,iBAAiB,QAAQ;AAC5B,qBAAS,iBAAiB,CAAC;AAAA,UAC3B;AAAA,QACD;AACD,cAAM,SAASA,cAAAA,MAAI,eAAe,oBAAoB;AACtD,YAAI,CAAC,UAAU,MAAM,QAAQ,MAAM,GAAG;AACrC,mBAAS,OAAO,KAAK,UAAQ,KAAK,OAAO,EAAE,KAAK;AAAA,QAChD;AACD,YAAI,CAAC,QAAQ;AACZ,gBAAM,SAASA,cAAAA,MAAI,eAAe,sBAAsB,EAAE,EAAE;AAC5D,cAAI,UAAU,OAAO,WAAW,UAAU;AACzC,qBAAS;AAAA,UACT;AAAA,QACD;AAAA,MACD,SAAQ,GAAG;AACX,iBAAS;AAAA,MACT;AACD,UAAI,CAAC,QAAQ;AACZ,iBAAS;AAAA,UACR,IAAI,UAAU,EAAE;AAAA,UAChB,MAAM,aAAa,MAAM;AAAA,UACzB;AAAA,UACA,OAAO;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,UACb,QAAQ;AAAA,YACP,EAAE,MAAM,OAAO,OAAO,OAAO,MAAM,GAAI;AAAA,YACvC,EAAE,MAAM,MAAM,OAAO,OAAO,MAAM,MAAO;AAAA,YACzC,EAAE,MAAM,MAAM,OAAO,OAAO,MAAM,OAAQ;AAAA,YAC1C,EAAE,MAAM,OAAO,OAAO,OAAO,MAAM,OAAQ;AAAA,UAC3C;AAAA,QACD;AAAA,MACD;AACD,UAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,GAAG;AAClC,eAAO,SAAS,CAAE;AAAA,MAClB;AACD,UAAI,CAAC,OAAO,aAAa;AACxB,eAAO,cAAc,OAAO,QAAQ,UAAU,OAAO,KAAK,aAAa;AAAA,MACvE;AACD,UAAI,CAAC,OAAO,MAAM;AACjB,eAAO,OAAO;AAAA,MACd;AACD,YAAM,eAAe;AAAA,QACpB,IAAI,OAAO,MAAM,UAAU,EAAE;AAAA,QAC7B,MAAM,OAAO,QAAQ,aAAa,MAAM;AAAA,QACxC;AAAA,QACA,OAAO,OAAO,SAAS;AAAA,QACvB,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,QAAQ,OAAO;AAAA,MACf;AACD,yBAAmB,QAAQ;AAC3B,UAAI;AACHA,sBAAG,MAAC,eAAe,sBAAsB,EAAE,IAAI,YAAY;AAAA,MAC7D,SAAU,GAAG;AAAA,MAAE;AAAA,IACf;AAGA,UAAM,mBAAmB,MAAM;AAC9B,mBAAa,MAAM,QAAQ,QAAQ,YAAU;AAE5C,YAAI,OAAO,SAAS,GAAG;AACtB,iBAAO,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC;AAAA,QAC5D;AAAA,MACH,CAAE;AAAA,IACF;AAEA,UAAM,qBAAqB,CAAC,UAAU;AACrC,UAAI,UAAU;AAAM,eAAO;AAC3B,UAAI,UAAU;AAAM,eAAO;AAC3B,UAAI,UAAU;AAAM,eAAO;AAC3B,aAAO;AAAA,IACR;AAEA,UAAM,0BAA0B,CAAC,cAAc;AAC9C,YAAM,WAAW,sBAAsB,UAAU,IAAI;AACrD,UAAI,CAAC;AAAU,eAAO;AACtB,YAAM,QAAQ,WAAW,UAAU,KAAK;AACxC,UAAI,MAAM,KAAK;AAAG,eAAO;AACzB,UAAI,SAAS,QAAQ,UAAa,QAAQ,SAAS,KAAK;AACvD,eAAO;AAAA,MACP;AACD,UAAI,SAAS,QAAQ,UAAa,QAAQ,SAAS,KAAK;AACvD,eAAO;AAAA,MACP;AACD,aAAO;AAAA,IACR;AAEA,UAAM,yBAAyB,CAAC,cAAc;AAC7C,YAAM,WAAW,sBAAsB,UAAU,IAAI;AACrD,UAAI,CAAC;AAAU,eAAO;AACtB,YAAM,QAAQ,WAAW,UAAU,KAAK;AACxC,UAAI,MAAM,KAAK;AAAG,eAAO;AACzB,UAAI,SAAS,QAAQ,UAAa,QAAQ,SAAS,KAAK;AACvD,eAAO;AAAA,MACP;AACD,UAAI,SAAS,QAAQ,UAAa,QAAQ,SAAS,KAAK;AACvD,eAAO;AAAA,MACP;AACD,aAAO;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjbA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-problem/device-problem.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-problem/device-problem.js.map new file mode 100644 index 0000000..80c56b5 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device-problem/device-problem.js.map @@ -0,0 +1 @@ +{"version":3,"file":"device-problem.js","sources":["pages/device-problem/device-problem.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvZGV2aWNlLXByb2JsZW0vZGV2aWNlLXByb2JsZW0udnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/device-problem/device-problem.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","onMounted","uni"],"mappings":";;;;;AA4CA,UAAM,iBAAiBA,cAAG,IAAC,EAAE;AAE7BC,kBAAAA,UAAU,MAAM;AACf,UAAI;AACH,cAAM,OAAOC,cAAG,MAAC,eAAe,gBAAgB,KAAK,CAAE;AACvD,uBAAe,QAAQ,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAE;AAAA,MACtD,SAAQ,GAAG;AACX,uBAAe,QAAQ,CAAE;AAAA,MACzB;AAAA,IACF,CAAC;AAED,UAAM,WAAW,CAAC,WAAW;AAC5BA,oBAAAA,MAAI,WAAW;AAAA,QACd,KAAK,yCAAyC,OAAO,EAAE;AAAA,MACzD,CAAE;AAAA,IACF;AAEA,UAAM,YAAY,CAAC,WAAW;AAC7BA,oBAAAA,MAAI,YAAY,EAAE,OAAO,SAAQ,CAAE;AACnC,iBAAW,MAAM;AAChBA,sBAAAA,MAAI,YAAa;AACjBA,sBAAG,MAAC,UAAU,EAAE,OAAO,eAAe,MAAM,QAAQ;AAAA,MACpD,GAAE,GAAI;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;AClEA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device/device.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device/device.js.map new file mode 100644 index 0000000..325caf2 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/device/device.js.map @@ -0,0 +1 @@ +{"version":3,"file":"device.js","sources":["pages/device/device.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvZGV2aWNlL2RldmljZS52dWU"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/device/device.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni","res"],"mappings":";;;;;AAgFA,UAAM,cAAcA,cAAAA,IAAI;AAAA,MACvB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,SAAS;AAAA;AAAA,IACV,CAAC;AAGD,UAAM,UAAUA,cAAAA,IAAI;AAAA,MACnB;AAAA,QACC,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAGD,UAAM,iBAAiB,CAAC,WAAW;AAClC,aAAO,WAAW,WAAW,kBAAkB;AAAA,IAChD;AAGA,UAAM,oBAAoB,CAAC,WAAW;AACrC,yBAAmB,MAAM;AAAA,IAC1B;AAGA,UAAM,qBAAqB,CAAC,WAAW;AACtCC,oBAAAA,MAAI,WAAW;AAAA,QACd,KAAK,yCAAyC,OAAO,EAAE;AAAA,MACzD,CAAE;AAAA,IACF;AAGA,UAAM,eAAe,CAAC,WAAW;AAChCA,oBAAAA,MAAI,gBAAgB;AAAA,QACnB,UAAU,CAAC,QAAQ,QAAQ,MAAM;AAAA,QACjC,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,aAAa,GAAG;AACvB,+BAAmB,MAAM;AAAA,UAC7B,WAAc,IAAI,aAAa,GAAG;AAC9BA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAAA,UACL,OAAU;AACNA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,SAAS;AAAA,cACT,SAAS,CAACC,SAAQ;AACjB,oBAAIA,KAAI,SAAS;AAEhB,wBAAM,QAAQ,QAAQ,MAAM,UAAU,OAAK,EAAE,OAAO,OAAO,EAAE;AAC7D,sBAAI,QAAQ,IAAI;AACf,4BAAQ,MAAM,OAAO,OAAO,CAAC;AAC7B,gCAAY,MAAM;AAClB,wBAAI,OAAO,WAAW,UAAU;AAC/B,kCAAY,MAAM;AAAA,oBAC3B,OAAe;AACN,kCAAY,MAAM;AAAA,oBAClB;AAAA,kBACD;AACDD,gCAAAA,MAAI,UAAU;AAAA,oBACb,OAAO;AAAA,oBACP,MAAM;AAAA,kBACd,CAAQ;AAAA,gBACD;AAAA,cACD;AAAA,YACN,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,kBAAkB,MAAM;AAC7BA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,uBAAuB,MAAM;AAClC,UAAI;AACH,cAAM,cAAc,QAAQ,MAAM,OAAO,OAAK,EAAE,WAAW,SAAS;AACpEA,4BAAI,eAAe,kBAAkB,WAAW;AAAA,MAClD,SAAU,GAAG;AAAA,MAAE;AACdA,oBAAAA,MAAI,WAAW;AAAA,QACd,KAAK;AAAA,MACP,CAAE;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChMA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map new file mode 100644 index 0000000..d765346 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["pages/index/index.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvaW5kZXgvaW5kZXgudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/index/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","watch","uni","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/login/login.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/login/login.js.map new file mode 100644 index 0000000..df776be --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/login/login.js.map @@ -0,0 +1 @@ +{"version":3,"file":"login.js","sources":["pages/login/login.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbG9naW4vbG9naW4udnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/login/login.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","login","staffLogin","setToken","config","setTabBar","wechatLogin","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/message/message.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/message/message.js.map new file mode 100644 index 0000000..fea6ade --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/message/message.js.map @@ -0,0 +1 @@ +{"version":3,"file":"message.js","sources":["pages/message/message.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbWVzc2FnZS9tZXNzYWdlLnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/message/message.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni"],"mappings":";;;;;AAoDA,UAAM,aAAaA,cAAG,IAAC,CAAC;AAGxB,UAAM,OAAOA,cAAAA,IAAI;AAAA,MAChB,EAAE,OAAO,MAAM,MAAM,OAAO,QAAQ,EAAG;AAAA,MACvC,EAAE,OAAO,QAAQ,MAAM,UAAU,QAAQ,EAAG;AAAA,MAC5C,EAAE,OAAO,QAAQ,MAAM,WAAW,QAAQ,EAAG;AAAA,MAC7C,EAAE,OAAO,QAAQ,MAAM,YAAY,QAAQ,EAAG;AAAA,IAC/C,CAAC;AAGD,UAAM,WAAWA,cAAAA,IAAI;AAAA,MACpB;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACN;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACN;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACN;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAGD,UAAM,mBAAmBC,cAAQ,SAAC,MAAM;AACvC,UAAI,KAAK,MAAM,WAAW,KAAK,EAAE,SAAS,OAAO;AAChD,eAAO,SAAS;AAAA,MAChB;AACD,aAAO,SAAS,MAAM,OAAO,SAAO,IAAI,SAAS,KAAK,MAAM,WAAW,KAAK,EAAE,IAAI;AAAA,IACnF,CAAC;AAGD,UAAM,YAAY,CAAC,UAAU;AAC5B,iBAAW,QAAQ;AAAA,IACpB;AAGA,UAAM,qBAAqB,CAAC,YAAY;AAEvC,UAAI,CAAC,QAAQ,MAAM;AAClB,gBAAQ,OAAO;AACf,wBAAiB;AAAA,MACjB;AAEDC,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,kBAAkB,MAAM;AAC7B,WAAK,MAAM,QAAQ,SAAO;AACzB,YAAI,IAAI,SAAS,OAAO;AACvB,cAAI,SAAS,SAAS,MAAM,OAAO,SAAO,CAAC,IAAI,IAAI,EAAE;AAAA,QACxD,OAAS;AACN,cAAI,SAAS,SAAS,MAAM,OAAO,SAAO,IAAI,SAAS,IAAI,QAAQ,CAAC,IAAI,IAAI,EAAE;AAAA,QAC9E;AAAA,MACH,CAAE;AAAA,IACF;AAGA,oBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxIjB,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-detail/order-detail.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-detail/order-detail.js.map new file mode 100644 index 0000000..c4046cc --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-detail/order-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"order-detail.js","sources":["pages/order-detail/order-detail.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvb3JkZXItZGV0YWlsL29yZGVyLWRldGFpbC52dWU"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/order-detail/order-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-progress/order-progress.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-progress/order-progress.js.map new file mode 100644 index 0000000..1d3b516 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order-progress/order-progress.js.map @@ -0,0 +1 @@ +{"version":3,"file":"order-progress.js","sources":["pages/order-progress/order-progress.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvb3JkZXItcHJvZ3Jlc3Mvb3JkZXItcHJvZ3Jlc3MudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/order-progress/order-progress.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order/order.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order/order.js.map new file mode 100644 index 0000000..fb63092 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/order/order.js.map @@ -0,0 +1 @@ +{"version":3,"file":"order.js","sources":["pages/order/order.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvb3JkZXIvb3JkZXIudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/order/order.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/payment/payment.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/payment/payment.js.map new file mode 100644 index 0000000..9f7ae14 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/payment/payment.js.map @@ -0,0 +1 @@ +{"version":3,"file":"payment.js","sources":["pages/payment/payment.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvcGF5bWVudC9wYXltZW50LnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/payment/payment.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/profile/profile.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/profile/profile.js.map new file mode 100644 index 0000000..f37f7fb --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/profile/profile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"profile.js","sources":["pages/profile/profile.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvcHJvZmlsZS9wcm9maWxlLnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/profile/profile.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","onMounted"],"mappings":";;;;;AA4DA,UAAM,WAAWA,cAAG,IAAC,MAAM;AAC3B,UAAM,WAAWA,cAAG,IAAC,IAAI;AACzB,UAAM,eAAeC,cAAQ,SAAC,MAAM,SAAS,UAAU,SAAS,SAAS,MAAM;AAC/E,UAAM,UAAUA,cAAAA,SAAS,MAAM,SAAS,UAAU,OAAO;AAGzD,UAAM,YAAYD,cAAAA,IAAI;AAAA,MACrB,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,KAAK,MAAM,IAAI,OAAO,GAAI;AAAA,MACjD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,IACnD,CAAC;AAGD,UAAM,iBAAiBA,cAAAA,IAAI;AAAA,MAC1B,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,KAAM;AAAA,MACpD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,IACnD,CAAC;AAGD,UAAM,iBAAiB,MAAM;AAC5BE,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,iBAAiB,CAAC,SAAS;AAChCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO,KAAK;AAAA,QACZ,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,eAAe,MAAM;AAC1BA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAEhBA,0BAAG,MAAC,kBAAkB,UAAU;AAChCA,0BAAG,MAAC,kBAAkB,cAAc;AACpCA,0BAAG,MAAC,kBAAkB,mBAAmB;AAGzCA,0BAAAA,MAAI,SAAS;AAAA,cACZ,KAAK;AAAA,YACV,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGAC,kBAAAA,UAAU,MAAM;AACf,YAAM,OAAOD,cAAAA,MAAI,eAAe,UAAU;AAC1C,YAAM,UAAUA,cAAAA,MAAI,eAAe,cAAc;AAEjD,UAAI,MAAM;AACT,iBAAS,QAAQ;AAAA,MACjB;AAED,UAAI,SAAS;AACZ,YAAI,SAAS,QAAQ;AACpB,mBAAS,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,SAAS,CAAC;AAAA,QAChE,OAAS;AACN,mBAAS,QAAQ,UAAU;AAAA,QAC3B;AAAA,MACD;AAAA,IACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtID,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/purchase/purchase.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/purchase/purchase.js.map new file mode 100644 index 0000000..d2b636b --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/purchase/purchase.js.map @@ -0,0 +1 @@ +{"version":3,"file":"purchase.js","sources":["pages/purchase/purchase.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvcHVyY2hhc2UvcHVyY2hhc2UudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/purchase/purchase.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni"],"mappings":";;;;;AAmDA,UAAM,kBAAkBA,cAAG,IAAC,CAAC;AAG7B,UAAM,aAAaA,cAAAA,IAAI;AAAA,MACtB,EAAE,MAAM,MAAM,MAAM,MAAO;AAAA,MAC3B,EAAE,MAAM,OAAO,MAAM,WAAY;AAAA,MACjC,EAAE,MAAM,MAAM,MAAM,QAAS;AAAA,MAC7B,EAAE,MAAM,MAAM,MAAM,QAAS;AAAA,MAC7B,EAAE,MAAM,MAAM,MAAM,UAAW;AAAA,IAChC,CAAC;AAGD,UAAM,WAAWA,cAAAA,IAAI;AAAA,MACpB;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,MACD;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAGD,UAAM,mBAAmBC,cAAQ,SAAC,MAAM;AACvC,UAAI,WAAW,MAAM,gBAAgB,KAAK,EAAE,SAAS,OAAO;AAC3D,eAAO,SAAS;AAAA,MAChB;AACD,aAAO,SAAS,MAAM,OAAO,aAAW,QAAQ,aAAa,WAAW,MAAM,gBAAgB,KAAK,EAAE,IAAI;AAAA,IAC1G,CAAC;AAGD,UAAM,iBAAiB,CAAC,UAAU;AACjC,sBAAgB,QAAQ;AAAA,IACzB;AAGA,UAAM,qBAAqB,CAAC,YAAY;AACvCC,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,kBAAkB,CAAC,YAAY;AACpCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS,SAAS,QAAQ,IAAI;AAAA,QAC9B,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAChBA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9IA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-detail.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-detail.js.map new file mode 100644 index 0000000..775d4ff --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"delivery-detail.js","sources":["pages/staff/delivery-detail.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvZGVsaXZlcnktZGV0YWlsLnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/delivery-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","onLoad","setTabBar","uni"],"mappings":";;;;;;AA8HA,UAAM,iBAAiBA,cAAAA,IAAI;AAAA,MAC1B,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,cAAc;AAAA,IACf,CAAC;AAGD,UAAM,WAAWA,cAAAA,IAAI;AAAA,MACpB;AAAA,QACC,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAGD,UAAM,YAAYA,cAAG,IAAC,EAAE;AACxB,UAAM,YAAYA,cAAG,IAAC,CAAC;AAGvB,UAAM,oBAAoBA,cAAG,IAAC,KAAK;AACnC,UAAM,kBAAkBA,cAAG,IAAC,EAAE;AAG9BC,kBAAM,OAAC,CAAC,YAAY;AAEnBC,mBAAAA,UAAU,OAAO;AAGjB,YAAM,iBAAiB,QAAQ,kBAAkBC,cAAAA,MAAI,eAAe,uBAAuB;AAE3F,UAAI,gBAAgB;AACnB,YAAI;AACH,gBAAM,aAAaA,cAAAA,MAAI,eAAe,YAAY,cAAc,EAAE;AAClE,cAAI,YAAY;AACf,2BAAe,QAAQ;AACvB;AAAA,UACA;AAAA,QACD,SAAQ,GAAG;AAAA,QAEX;AAAA,MACD;AAGD,0BAAqB;AAAA,IACtB,CAAC;AAGD,UAAM,sBAAsB,MAAM;AACjC,qBAAe,QAAQ;AAAA,QACtB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,cAAc;AAAA,MACd;AAAA,IACF;AAGA,UAAM,oBAAoB,MAAM;AAC/B,YAAM,WAAW;AAAA,QAChB,SAAS;AAAA,QACT,aAAa;AAAA,QACb,WAAW;AAAA,MACX;AACD,aAAO,SAAS,eAAe,MAAM,MAAM,KAAK,SAAS;AAAA,IAC1D;AAGA,UAAM,gBAAgB,MAAM;AAC3B,YAAM,UAAU;AAAA,QACf,SAAS;AAAA,QACT,aAAa;AAAA,QACb,WAAW;AAAA,MACX;AACD,aAAO,QAAQ,eAAe,MAAM,MAAM,KAAK,QAAQ;AAAA,IACxD;AAGA,UAAM,aAAa,MAAM;AACxBA,oBAAAA,MAAI,cAAc;AAAA,QACjB,aAAa,eAAe,MAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,EAAE;AAAA,QAC5E,MAAM,MAAM;AACXA,wBAAAA,MAAI,UAAU;AAAA,YACb,OAAO;AAAA,YACP,MAAM;AAAA,UACV,CAAI;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,aAAa,MAAM;AACxB,UAAI,CAAC,UAAU,MAAM,KAAM;AAAE;AAG7B,UAAI,eAAe,MAAM,WAAW,WAAW;AAC9CA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AAGD,eAAS,MAAM,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,SAAS,UAAU;AAAA,QACnB,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,MACrF,CAAE;AAED,YAAM,cAAc,UAAU;AAC9B,gBAAU,QAAQ;AAGlB,iBAAW,MAAM;AAChB,kBAAU,QAAQ;AAAA,MAClB,GAAE,GAAG;AAGN,iBAAW,MAAM;AAChB,iBAAS,MAAM,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,aAAa,WAAW;AAAA,UACjC,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,QACtF,CAAG;AAED,mBAAW,MAAM;AAChB,oBAAU,QAAQ;AAAA,QAClB,GAAE,GAAG;AAAA,MACN,GAAE,GAAI;AAAA,IACR;AAGA,UAAM,eAAe,CAAC,YAAY;AACjC,UAAI,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAAS,IAAI,GAAG;AACjF,eAAO;AAAA,MACT,WAAY,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAAS,IAAI,GAAG;AAC5D,eAAO;AAAA,MACT,WAAY,QAAQ,SAAS,IAAI,KAAK,QAAQ,SAAS,IAAI,GAAG;AAC5D,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF;AAGA,UAAM,sBAAsB,MAAM;AACjCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS,YAAY,eAAe,MAAM,MAAM;AAAA,QAChD,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAEhB,2BAAe,MAAM,SAAS;AAC9B,2BAAe,MAAM,aAAa;AAGlC,gBAAI;AACHA,kCAAI,eAAe,YAAY,eAAe,MAAM,MAAM,IAAI,eAAe,KAAK;AAAA,YACvF,SAAa,GAAG;AAAA,YAAE;AAGd,qBAAS,MAAM,KAAK;AAAA,cACnB,MAAM;AAAA,cACN,SAAS;AAAA,cACT,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,YACxF,CAAK;AAEDA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,yBAAyB,MAAM;AACpCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS,SAAS,eAAe,MAAM,MAAM;AAAA,QAC7C,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAChB,2BAAe,MAAM,SAAS;AAC9B,2BAAe,MAAM,aAAa;AAGlC,gBAAI;AACHA,kCAAI,eAAe,YAAY,eAAe,MAAM,MAAM,IAAI,eAAe,KAAK;AAAA,YACvF,SAAa,GAAG;AAAA,YAAE;AAGd,qBAAS,MAAM,KAAK;AAAA,cACnB,MAAM;AAAA,cACN,SAAS;AAAA,cACT,OAAM,oBAAI,KAAM,GAAC,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,YACxF,CAAK;AAEDA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAGD,uBAAW,MAAM;AAChBA,4BAAAA,MAAI,aAAc;AAAA,YAClB,GAAE,IAAI;AAAA,UACP;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,iBAAiB,MAAM;AAC5B,wBAAkB,QAAQ;AAC1B,sBAAgB,QAAQ;AAAA,IACzB;AAGA,UAAM,qBAAqB,MAAM;AAChC,wBAAkB,QAAQ;AAC1B,sBAAgB,QAAQ;AAAA,IACzB;AAGA,UAAM,iBAAiB,MAAM;AAC5B,UAAI,CAAC,gBAAgB,MAAM,QAAQ;AAClCA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AAGDA,oBAAAA,MAAI,YAAY;AAAA,QACf,OAAO;AAAA,MACT,CAAE;AAED,iBAAW,MAAM;AAChBA,sBAAAA,MAAI,YAAa;AACjBA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD,2BAAoB;AAAA,MACpB,GAAE,GAAI;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9XA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-task.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-task.js.map new file mode 100644 index 0000000..77c3aea --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"delivery-task.js","sources":["pages/staff/delivery-task.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvZGVsaXZlcnktdGFzay52dWU"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/delivery-task.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","onLoad","setTabBar","uni","onMounted"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery.js.map new file mode 100644 index 0000000..8f528c1 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/delivery.js.map @@ -0,0 +1 @@ +{"version":3,"file":"delivery.js","sources":["pages/staff/delivery.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvZGVsaXZlcnkudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/delivery.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","onMounted","setTabBar"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/index.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/index.js.map new file mode 100644 index 0000000..8e88a6e --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["pages/staff/index.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvaW5kZXgudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/profile.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/profile.js.map new file mode 100644 index 0000000..3c80b99 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/profile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"profile.js","sources":["pages/staff/profile.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvcHJvZmlsZS52dWU"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/profile.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni","onMounted","setTabBar"],"mappings":";;;;;;AAiEA,UAAM,YAAYA,cAAG,IAAC,MAAM;AAC5B,UAAM,UAAUA,cAAG,IAAC,cAAc;AAClC,UAAM,YAAYA,cAAG,IAAC,MAAM;AAG5B,UAAM,QAAQA,cAAAA,IAAI;AAAA,MACjB,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACT,CAAC;AAGD,UAAM,YAAYA,cAAAA,IAAI;AAAA,MACrB,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,0BAA0B,OAAO,GAAI;AAAA,MACxE,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,yBAAyB,OAAO,GAAI;AAAA,MACvE,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,sBAAsB,OAAO,GAAI;AAAA,MACpE,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,OAAO,GAAI;AAAA,MAClD,EAAE,OAAO,QAAQ,MAAM,KAAK,MAAM,IAAI,OAAO,GAAI;AAAA,IAClD,CAAC;AAGD,UAAM,kBAAkB,MAAM;AAC7BC,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAGA,UAAM,iBAAiB,CAAC,SAAS;AAChC,UAAI,KAAK,MAAM;AACdA,sBAAAA,MAAI,WAAW;AAAA,UACd,KAAK,KAAK;AAAA,UACV,MAAM,MAAM;AACXA,0BAAAA,MAAI,WAAW;AAAA,cACd,KAAK,KAAK;AAAA,YACf,CAAK;AAAA,UACD;AAAA,QACJ,CAAG;AAAA,MACH,OAAQ;AACNA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO,KAAK,QAAQ;AAAA,UACpB,MAAM;AAAA,QACT,CAAG;AAAA,MACD;AAAA,IACF;AAGA,UAAM,eAAe,MAAM;AAC1BA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAEhBA,0BAAG,MAAC,kBAAkB,UAAU;AAChCA,0BAAG,MAAC,kBAAkB,cAAc;AACpCA,0BAAG,MAAC,kBAAkB,mBAAmB;AAGzCA,0BAAAA,MAAI,SAAS;AAAA,cACZ,KAAK;AAAA,YACV,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGAC,kBAAAA,UAAU,MAAM;AAEfC,mBAAAA,UAAU,OAAO;AAEjB,YAAM,UAAUF,cAAAA,MAAI,eAAe,cAAc;AACjD,UAAI,SAAS;AACZ,gBAAQ,QAAQ;AAChB,kBAAU,QAAQ,UAAU;AAAA,MAC5B;AAAA,IACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/ID,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/stats.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/stats.js.map new file mode 100644 index 0000000..db21562 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/stats.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stats.js","sources":["pages/staff/stats.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvc3RhdHMudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/stats.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","onMounted","setTabBar"],"mappings":";;;;;;AA0GA,UAAM,YAAYA,cAAAA,IAAI;AAAA,MACrB,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,YAAY;AAAA,IACb,CAAC;AAGD,UAAM,UAAUA,cAAAA,IAAI;AAAA,MACnB;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACT;AAAA,MACD;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACT;AAAA,MACD;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACT;AAAA,MACD;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACT;AAAA,MACD;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAGD,UAAM,kBAAkBC,cAAQ,SAAC,MAAM;AACtC,YAAM,SAAS,UAAU,MAAM;AAC/B,UAAI,UAAU,KAAK;AAClB,eAAO;AAAA,MACT,WAAY,UAAU,GAAK;AACzB,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF,CAAC;AAGD,UAAM,iBAAiBA,cAAQ,SAAC,MAAM;AACrC,YAAM,SAAS,UAAU,MAAM;AAC/B,UAAI,UAAU,KAAK;AAClB,eAAO;AAAA,MACT,WAAY,UAAU,GAAK;AACzB,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF,CAAC;AAGD,UAAM,qBAAqB,MAAM;AAChC,YAAM,SAAS,UAAU,MAAM;AAC/B,UAAI,UAAU,KAAK;AAClB,eAAO;AAAA,MACT,WAAY,UAAU,GAAK;AACzB,eAAO;AAAA,MACT,OAAQ;AACN,eAAO;AAAA,MACP;AAAA,IACF;AAGAC,kBAAAA,UAAU,MAAM;AAEfC,mBAAAA,UAAU,OAAO;AAAA,IAClB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnMD,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder-detail.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder-detail.js.map new file mode 100644 index 0000000..f567d1b --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"workorder-detail.js","sources":["pages/staff/workorder-detail.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvd29ya29yZGVyLWRldGFpbC52dWU"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/workorder-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","onLoad","setTabBar","uni"],"mappings":";;;;;;AAgIA,UAAM,kBAAkBA,cAAAA,IAAI;AAAA,MAC3B,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS,CAAE;AAAA,IACZ,CAAC;AAGD,UAAM,oBAAoBA,cAAG,IAAC,KAAK;AACnC,UAAM,kBAAkBA,cAAG,IAAC,EAAE;AAG9BC,kBAAM,OAAC,CAAC,YAAY;AAEnBC,mBAAAA,UAAU,OAAO;AAGjB,YAAM,cAAc,QAAQ,eAAeC,cAAAA,MAAI,eAAe,oBAAoB;AAElF,UAAI,aAAa;AAChB,YAAI;AACH,gBAAM,aAAaA,cAAAA,MAAI,eAAe,aAAa,WAAW,EAAE;AAChE,cAAI,YAAY;AACf,4BAAgB,QAAQ;AAAA,cACvB,GAAG;AAAA;AAAA,cAEH,SAAS,WAAW,WAAW;AAAA,gBAC9B;AAAA,kBACC,MAAM;AAAA,kBACN,IAAI;AAAA,kBACJ,SAAS,WAAW,WAAW;AAAA,kBAC/B,QAAQ;AAAA,kBACR,YAAY;AAAA,gBACZ;AAAA,cACD;AAAA,YACD;AACD;AAAA,UACA;AAAA,QACD,SAAQ,GAAG;AAAA,QAEX;AAAA,MACD;AAGD,2BAAsB;AAAA,IACvB,CAAC;AAGD,UAAM,uBAAuB,MAAM;AAClC,sBAAgB,QAAQ;AAAA,QACvB,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,OAAO;AAAA,QACP,aAAa;AAAA,QACb,UAAU;AAAA,QACV,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,SAAS;AAAA,UACR;AAAA,YACC,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,YAAY;AAAA,UACZ;AAAA,QACD;AAAA,MACD;AAAA,IACF;AAGA,UAAM,iBAAiB,CAAC,WAAW;AAClC,YAAM,WAAW;AAAA,QAChB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,WAAW;AAAA,MACX;AACD,aAAO,SAAS,MAAM,KAAK;AAAA,IAC5B;AAGA,UAAM,mBAAmB,CAAC,aAAa;AACtC,aAAO,aAAa,SAAS,kBAAkB;AAAA,IAChD;AAGA,UAAM,uBAAuB,CAAC,WAAW;AACxC,aAAO,WAAW,WAAW,kBAAkB;AAAA,IAChD;AAGA,UAAM,aAAa,MAAM;AACxBA,oBAAAA,MAAI,cAAc;AAAA,QACjB,aAAa,gBAAgB,MAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,EAAE;AAAA,QAC7E,MAAM,MAAM;AACXA,wBAAAA,MAAI,UAAU;AAAA,YACb,OAAO;AAAA,YACP,MAAM;AAAA,UACV,CAAI;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,sBAAsB,MAAM;AACjCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS,aAAa,gBAAgB,MAAM,EAAE;AAAA,QAC9C,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAChB,4BAAgB,MAAM,SAAS;AAC/B,4BAAgB,MAAM,aAAa;AACnCA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAAA,UACD;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,yBAAyB,MAAM;AACpCA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,SAAS,QAAQ,gBAAgB,MAAM,EAAE;AAAA,QACzC,SAAS,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS;AAChB,4BAAgB,MAAM,SAAS;AAC/B,4BAAgB,MAAM,aAAa;AACnCA,0BAAAA,MAAI,UAAU;AAAA,cACb,OAAO;AAAA,cACP,MAAM;AAAA,YACX,CAAK;AAED,uBAAW,MAAM;AAChBA,4BAAAA,MAAI,aAAc;AAAA,YAClB,GAAE,IAAI;AAAA,UACP;AAAA,QACD;AAAA,MACH,CAAE;AAAA,IACF;AAGA,UAAM,iBAAiB,MAAM;AAC5B,wBAAkB,QAAQ;AAC1B,sBAAgB,QAAQ;AAAA,IACzB;AAGA,UAAM,qBAAqB,MAAM;AAChC,wBAAkB,QAAQ;AAC1B,sBAAgB,QAAQ;AAAA,IACzB;AAGA,UAAM,iBAAiB,MAAM;AAC5B,UAAI,CAAC,gBAAgB,MAAM,QAAQ;AAClCA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AAGDA,oBAAAA,MAAI,YAAY;AAAA,QACf,OAAO;AAAA,MACT,CAAE;AAED,iBAAW,MAAM;AAChBA,sBAAAA,MAAI,YAAa;AACjBA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD,2BAAoB;AAAA,MACpB,GAAE,GAAI;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/TA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder.js.map new file mode 100644 index 0000000..b831830 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/staff/workorder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"workorder.js","sources":["pages/staff/workorder.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvc3RhZmYvd29ya29yZGVyLnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/staff/workorder.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","computed","uni","onMounted","setTabBar"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-alert/water-quality-alert.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-alert/water-quality-alert.js.map new file mode 100644 index 0000000..c99c776 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-alert/water-quality-alert.js.map @@ -0,0 +1 @@ +{"version":3,"file":"water-quality-alert.js","sources":["pages/water-quality-alert/water-quality-alert.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvd2F0ZXItcXVhbGl0eS1hbGVydC93YXRlci1xdWFsaXR5LWFsZXJ0LnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/water-quality-alert/water-quality-alert.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","onMounted","uni"],"mappings":";;;;;AAyCA,UAAM,SAASA,cAAG,IAAC,EAAE;AAErBC,kBAAAA,UAAU,MAAM;AACf,UAAI;AACH,cAAM,SAASC,cAAAA,MAAI,eAAe,oBAAoB;AACtD,eAAO,QAAQ,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAE;AAClD,YAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,4BAAmB;AAAA,QACnB;AAAA,MACD,SAAQ,GAAG;AACX,0BAAmB;AAAA,MACnB;AAAA,IACF,CAAC;AAED,UAAM,oBAAoB,MAAM;AAC/B,aAAO,QAAQ;AAAA,QACd;AAAA,UACC,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,aAAa;AAAA,UACb,aAAa;AAAA,QACb;AAAA,QACD;AAAA,UACC,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,aAAa;AAAA,UACb,aAAa;AAAA,QACb;AAAA,MACD;AACD,UAAI;AACHA,sBAAAA,MAAI,eAAe,sBAAsB,OAAO,KAAK;AAAA,MACvD,SAAU,GAAG;AAAA,MAAE;AAAA,IACf;AAEA,UAAM,iBAAiB,CAAC,OAAO;AAC9B,UAAI,CAAC,IAAI;AACRA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AACD,YAAM,MAAM,yCAAyC,EAAE;AACvDA,oBAAAA,MAAI,WAAW;AAAA,QACd;AAAA,QACA,MAAM,MAAM;AACXA,8BAAI,WAAW,EAAE,KAAK;AAAA,QACtB;AAAA,MACH,CAAE;AAAA,IACF;AAEA,UAAM,uBAAuB,CAAC,SAAS;AACtC,UAAI,CAAC,QAAQ,CAAC,KAAK,IAAI;AACtBA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AACD;AAAA,MACA;AACD,UAAI;AACH,cAAM,WAAW,SAAS,KAAK,EAAE;AACjC,cAAM,SAAS;AAAA,UACd,IAAI;AAAA,UACJ,MAAM,KAAK,eAAe;AAAA,UAC1B,SAAS,KAAK,WAAW;AAAA,UACzB,OAAO,KAAK,SAAS;AAAA,UACrB,eAAe,KAAK,eAAe;AAAA,UACnC,SAAS;AAAA,UACT,QAAQ,KAAK,UAAU;AAAA,YACtB,EAAE,MAAM,MAAM,OAAO,QAAQ,MAAM,MAAO;AAAA,YAC1C,EAAE,MAAM,MAAM,OAAO,QAAQ,MAAM,OAAQ;AAAA,YAC3C,EAAE,MAAM,OAAO,OAAO,OAAO,MAAM,OAAQ;AAAA,UAC3C;AAAA,QACD;AACDA,sBAAG,MAAC,eAAe,sBAAsB,QAAQ,IAAI,MAAM;AAC3DA,sBAAAA,MAAI,WAAW;AAAA,UACd,KAAK,6DAA6D,QAAQ;AAAA,QAC7E,CAAG;AAAA,MACD,SAAQ,GAAG;AACXA,sBAAAA,MAAI,UAAU;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACT,CAAG;AAAA,MACD;AAAA,IACF;AAEA,UAAM,eAAe,CAAC,SAAS;AAC9BA,oBAAAA,MAAI,UAAU;AAAA,QACb,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAE;AAAA,IACF;AAEA,UAAM,gBAAgB,CAAC,SAAS;AAC/B,UAAI,SAAS;AAAU,eAAO;AAC9B,UAAI,SAAS;AAAW,eAAO;AAC/B,aAAO;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;;AC7IA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-detail/water-quality-detail.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-detail/water-quality-detail.js.map new file mode 100644 index 0000000..b07b3c7 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality-detail/water-quality-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"water-quality-detail.js","sources":["pages/water-quality-detail/water-quality-detail.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvd2F0ZXItcXVhbGl0eS1kZXRhaWwvd2F0ZXItcXVhbGl0eS1kZXRhaWwudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/water-quality-detail/water-quality-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","onLoad","uni","onUnload","computed"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality/water-quality.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality/water-quality.js.map new file mode 100644 index 0000000..3d79e9f --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/pages/water-quality/water-quality.js.map @@ -0,0 +1 @@ +{"version":3,"file":"water-quality.js","sources":["pages/water-quality/water-quality.vue","../../../../../HBuilderX/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvd2F0ZXItcXVhbGl0eS93YXRlci1xdWFsaXR5LnZ1ZQ"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'D:/软件工程导论/团队项目/WaterManager/src/数智水管家/pages/water-quality/water-quality.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","uni","onLoad"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/config.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/config.js.map new file mode 100644 index 0000000..5c145e6 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sources":["utils/config.js"],"sourcesContent":["/**\r\n * 应用配置文件\r\n */\r\n\r\n// API基础地址配置\r\n// 注意:微信小程序不能直接访问 localhost,需要使用局域网IP或内网穿透\r\n\r\n// 开发环境 - 本地后端\r\n// 方式1:使用 localhost(仅H5、App可用)\r\nconst DEV_BASE_URL_LOCALHOST = 'http://localhost:8080'\r\n\r\n// 方式2:使用局域网IP(推荐,微信小程序可用)\r\n// 获取本机IP:Windows运行 ipconfig,Mac/Linux运行 ifconfig\r\n// 当前配置:无线局域网适配器 WLAN 的IP地址\r\nconst DEV_BASE_URL_LAN = 'http://10.68.189.14:8080' // 你的本机IP(WLAN)\r\n\r\n// 方式3:使用内网穿透工具(如ngrok、natapp等)\r\n// const DEV_BASE_URL_TUNNEL = 'https://your-tunnel-domain.com'\r\n\r\n// 生产环境\r\nconst PROD_BASE_URL = 'https://your-domain.com'\r\n\r\n// 根据环境变量选择API地址\r\n// #ifdef MP-WEIXIN\r\n// 微信小程序环境 - 必须使用局域网IP或内网穿透,不能使用localhost\r\nconst BASE_URL = process.env.NODE_ENV === 'development' \r\n\t? DEV_BASE_URL_LAN // 微信小程序开发时使用局域网IP\r\n\t: PROD_BASE_URL\r\n// #endif\r\n\r\n// #ifndef MP-WEIXIN\r\n// 其他环境(H5、App等)- 可以使用localhost\r\nconst BASE_URL = process.env.NODE_ENV === 'development' \r\n\t? DEV_BASE_URL_LOCALHOST // H5、App可以使用localhost\r\n\t: PROD_BASE_URL\r\n// #endif\r\n\r\n// 请求超时时间(毫秒)\r\nconst TIMEOUT = 10000\r\n\r\n// Token存储键名\r\nconst TOKEN_KEY = 'water_token'\r\nconst USER_INFO_KEY = 'water_user_info'\r\nconst USER_ROLE_KEY = 'userRole'\r\n\r\nexport default {\r\n\tBASE_URL,\r\n\tTIMEOUT,\r\n\tTOKEN_KEY,\r\n\tUSER_INFO_KEY,\r\n\tUSER_ROLE_KEY\r\n}\r\n\r\n"],"names":[],"mappings":";AAcA,MAAM,mBAAmB;AAWzB,MAAM,WACH;AAYH,MAAM,UAAU;AAGhB,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AAEtB,MAAe,SAAA;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/request.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/request.js.map new file mode 100644 index 0000000..e3c9375 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/request.js.map @@ -0,0 +1 @@ +{"version":3,"file":"request.js","sources":["utils/request.js"],"sourcesContent":["/**\r\n * 请求工具 - 基于uni.request封装\r\n */\r\nimport config from './config.js'\r\n\r\n// 请求队列,用于防止重复请求\r\nconst pendingRequests = new Map()\r\n\r\n/**\r\n * 生成请求唯一标识\r\n */\r\nfunction getRequestKey(url, method, data) {\r\n\treturn `${method}_${url}_${JSON.stringify(data)}`\r\n}\r\n\r\n/**\r\n * 获取Token\r\n */\r\nfunction getToken() {\r\n\treturn uni.getStorageSync(config.TOKEN_KEY) || ''\r\n}\r\n\r\n/**\r\n * 设置Token\r\n */\r\nfunction setToken(token) {\r\n\tuni.setStorageSync(config.TOKEN_KEY, token)\r\n}\r\n\r\n/**\r\n * 移除Token\r\n */\r\nfunction removeToken() {\r\n\tuni.removeStorageSync(config.TOKEN_KEY)\r\n}\r\n\r\n/**\r\n * 显示加载提示\r\n */\r\nfunction showLoading(title = '加载中...') {\r\n\tuni.showLoading({\r\n\t\ttitle,\r\n\t\tmask: true\r\n\t})\r\n}\r\n\r\n/**\r\n * 隐藏加载提示\r\n */\r\nfunction hideLoading() {\r\n\tuni.hideLoading()\r\n}\r\n\r\n/**\r\n * 显示错误提示\r\n */\r\nfunction showError(message) {\r\n\tuni.showToast({\r\n\t\ttitle: message || '请求失败',\r\n\t\ticon: 'none',\r\n\t\tduration: 2000\r\n\t})\r\n}\r\n\r\n/**\r\n * 处理响应错误\r\n */\r\nfunction handleError(error, showToast = true) {\r\n\tlet message = '请求失败'\r\n\t\r\n\tif (error.statusCode) {\r\n\t\tswitch (error.statusCode) {\r\n\t\t\tcase 401:\r\n\t\t\t\tmessage = '未授权,请重新登录'\r\n\t\t\t\t// 清除token,跳转到登录页\r\n\t\t\t\tremoveToken()\r\n\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\tuni.reLaunch({\r\n\t\t\t\t\t\turl: '/pages/login/login'\r\n\t\t\t\t\t})\r\n\t\t\t\t}, 1500)\r\n\t\t\t\tbreak\r\n\t\t\tcase 403:\r\n\t\t\t\tmessage = '拒绝访问'\r\n\t\t\t\tbreak\r\n\t\t\tcase 404:\r\n\t\t\t\tmessage = '请求地址不存在'\r\n\t\t\t\tbreak\r\n\t\t\tcase 500:\r\n\t\t\t\tmessage = '服务器内部错误'\r\n\t\t\t\tbreak\r\n\t\t\tcase 502:\r\n\t\t\t\tmessage = '网关错误'\r\n\t\t\t\tbreak\r\n\t\t\tcase 503:\r\n\t\t\t\tmessage = '服务不可用'\r\n\t\t\t\tbreak\r\n\t\t\tcase 504:\r\n\t\t\t\tmessage = '网关超时'\r\n\t\t\t\tbreak\r\n\t\t\tdefault:\r\n\t\t\t\tmessage = `请求失败(${error.statusCode})`\r\n\t\t}\r\n\t} else if (error.errMsg) {\r\n\t\tif (error.errMsg.includes('timeout')) {\r\n\t\t\tmessage = '请求超时,请稍后重试'\r\n\t\t} else if (error.errMsg.includes('fail')) {\r\n\t\t\tmessage = '网络连接失败,请检查网络'\r\n\t\t} else {\r\n\t\t\tmessage = error.errMsg\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (showToast) {\r\n\t\tshowError(message)\r\n\t}\r\n\t\r\n\treturn Promise.reject({\r\n\t\tmessage,\r\n\t\tstatusCode: error.statusCode,\r\n\t\t...error\r\n\t})\r\n}\r\n\r\n/**\r\n * 请求拦截器\r\n */\r\nfunction requestInterceptor(options) {\r\n\t// 添加Token\r\n\tconst token = getToken()\r\n\tif (token && !options.header) {\r\n\t\toptions.header = {}\r\n\t}\r\n\tif (token && !options.header['Authorization']) {\r\n\t\toptions.header['Authorization'] = `Bearer ${token}`\r\n\t}\r\n\t\r\n\t// 设置Content-Type\r\n\tif (!options.header['Content-Type']) {\r\n\t\toptions.header['Content-Type'] = 'application/json;charset=UTF-8'\r\n\t}\r\n\t\r\n\t// 设置请求地址\r\n\tif (!options.url.startsWith('http')) {\r\n\t\toptions.url = config.BASE_URL + options.url\r\n\t}\r\n\t\r\n\t// 设置超时时间\r\n\tif (!options.timeout) {\r\n\t\toptions.timeout = config.TIMEOUT\r\n\t}\r\n\t\r\n\treturn options\r\n}\r\n\r\n/**\r\n * 响应拦截器\r\n */\r\nfunction responseInterceptor(response, options) {\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tconst { data } = response\r\n\t\t\r\n\t\t// HTTP状态码处理\r\n\t\tif (response.statusCode !== 200) {\r\n\t\t\thandleError({\r\n\t\t\t\tstatusCode: response.statusCode,\r\n\t\t\t\terrMsg: '请求失败'\r\n\t\t\t}, options.showError !== false).then(() => {\r\n\t\t\t\treject({\r\n\t\t\t\t\tstatusCode: response.statusCode,\r\n\t\t\t\t\tmessage: '请求失败'\r\n\t\t\t\t})\r\n\t\t\t}).catch((err) => {\r\n\t\t\t\treject(err)\r\n\t\t\t})\r\n\t\t\treturn\r\n\t\t}\r\n\t\t\r\n\t\t// 业务状态码处理(RuoYi框架返回格式)\r\n\t\tconst code = data.code || response.statusCode\r\n\t\t\r\n\t\tif (code === 200) {\r\n\t\t\t// 请求成功\r\n\t\t\tresolve(data)\r\n\t\t} else if (code === 401) {\r\n\t\t\t// 未授权\r\n\t\t\tremoveToken()\r\n\t\t\tshowError('登录已过期,请重新登录')\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tuni.reLaunch({\r\n\t\t\t\t\turl: '/pages/login/login'\r\n\t\t\t\t})\r\n\t\t\t}, 1500)\r\n\t\t\treject(data)\r\n\t\t} else {\r\n\t\t\t// 其他错误\r\n\t\t\tconst message = data.msg || data.message || '请求失败'\r\n\t\t\tif (options.showError !== false) {\r\n\t\t\t\tshowError(message)\r\n\t\t\t}\r\n\t\t\treject(data)\r\n\t\t}\r\n\t})\r\n}\r\n\r\n/**\r\n * 主请求方法\r\n */\r\nfunction request(options = {}) {\r\n\t// 默认配置\r\n\tconst defaultOptions = {\r\n\t\turl: '',\r\n\t\tmethod: 'GET',\r\n\t\tdata: {},\r\n\t\theader: {},\r\n\t\tshowLoading: true,\r\n\t\tloadingText: '加载中...',\r\n\t\tshowError: true,\r\n\t\tpreventDuplicate: false // 是否防止重复请求\r\n\t}\r\n\t\r\n\t// 合并配置\r\n\toptions = { ...defaultOptions, ...options }\r\n\t\r\n\t// 防止重复请求\r\n\tif (options.preventDuplicate) {\r\n\t\tconst requestKey = getRequestKey(options.url, options.method, options.data)\r\n\t\tif (pendingRequests.has(requestKey)) {\r\n\t\t\treturn Promise.reject({\r\n\t\t\t\tmessage: '请求正在进行中,请勿重复提交'\r\n\t\t\t})\r\n\t\t}\r\n\t\tpendingRequests.set(requestKey, true)\r\n\t}\r\n\t\r\n\t// 显示加载提示\r\n\tif (options.showLoading) {\r\n\t\tshowLoading(options.loadingText)\r\n\t}\r\n\t\r\n\t// 请求拦截\r\n\tconst finalOptions = requestInterceptor(options)\r\n\t\r\n\t// 发送请求\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tuni.request({\r\n\t\t\t...finalOptions,\r\n\t\t\tsuccess: async (response) => {\r\n\t\t\t\ttry {\r\n\t\t\t\t\t// 响应拦截\r\n\t\t\t\t\tconst result = await responseInterceptor(response, options)\r\n\t\t\t\t\tresolve(result)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\treject(error)\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tfail: (error) => {\r\n\t\t\t\t// 请求失败\r\n\t\t\t\thandleError(error, options.showError !== false)\r\n\t\t\t\t\t.catch((err) => {\r\n\t\t\t\t\t\treject(err)\r\n\t\t\t\t\t})\r\n\t\t\t},\r\n\t\t\tcomplete: () => {\r\n\t\t\t\t// 隐藏加载提示\r\n\t\t\t\tif (options.showLoading) {\r\n\t\t\t\t\thideLoading()\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// 清除请求标记\r\n\t\t\t\tif (options.preventDuplicate) {\r\n\t\t\t\t\tconst requestKey = getRequestKey(options.url, options.method, options.data)\r\n\t\t\t\t\tpendingRequests.delete(requestKey)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\t})\r\n}\r\n\r\n/**\r\n * GET请求\r\n */\r\nexport function get(url, params = {}, options = {}) {\r\n\treturn request({\r\n\t\turl,\r\n\t\tmethod: 'GET',\r\n\t\tdata: params,\r\n\t\t...options\r\n\t})\r\n}\r\n\r\n/**\r\n * POST请求\r\n */\r\nexport function post(url, data = {}, options = {}) {\r\n\treturn request({\r\n\t\turl,\r\n\t\tmethod: 'POST',\r\n\t\tdata,\r\n\t\t...options\r\n\t})\r\n}\r\n\r\n/**\r\n * PUT请求\r\n */\r\nexport function put(url, data = {}, options = {}) {\r\n\treturn request({\r\n\t\turl,\r\n\t\tmethod: 'PUT',\r\n\t\tdata,\r\n\t\t...options\r\n\t})\r\n}\r\n\r\n/**\r\n * DELETE请求\r\n */\r\nexport function del(url, params = {}, options = {}) {\r\n\treturn request({\r\n\t\turl,\r\n\t\tmethod: 'DELETE',\r\n\t\tdata: params,\r\n\t\t...options\r\n\t})\r\n}\r\n\r\n/**\r\n * 文件上传\r\n */\r\nexport function upload(url, filePath, name = 'file', formData = {}, options = {}) {\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tconst token = getToken()\r\n\t\tconst header = {\r\n\t\t\t'Authorization': token ? `Bearer ${token}` : ''\r\n\t\t}\r\n\t\t\r\n\t\t// 显示上传进度\r\n\t\tif (options.showLoading !== false) {\r\n\t\t\tshowLoading(options.loadingText || '上传中...')\r\n\t\t}\r\n\t\t\r\n\t\tuni.uploadFile({\r\n\t\t\turl: url.startsWith('http') ? url : config.BASE_URL + url,\r\n\t\t\tfilePath,\r\n\t\t\tname,\r\n\t\t\tformData,\r\n\t\t\theader,\r\n\t\t\tsuccess: (response) => {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst data = JSON.parse(response.data)\r\n\t\t\t\t\tif (data.code === 200) {\r\n\t\t\t\t\t\tresolve(data)\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tconst message = data.msg || '上传失败'\r\n\t\t\t\t\t\tif (options.showError !== false) {\r\n\t\t\t\t\t\t\tshowError(message)\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\treject(data)\r\n\t\t\t\t\t}\r\n\t\t\t\t} catch (e) {\r\n\t\t\t\t\tshowError('上传响应解析失败')\r\n\t\t\t\t\treject(e)\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tfail: (error) => {\r\n\t\t\t\thandleError(error, options.showError !== false)\r\n\t\t\t\treject(error)\r\n\t\t\t},\r\n\t\t\tcomplete: () => {\r\n\t\t\t\tif (options.showLoading !== false) {\r\n\t\t\t\t\thideLoading()\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\t})\r\n}\r\n\r\n// 导出工具方法\r\nexport { getToken, setToken, removeToken }\r\nexport default request\r\n\r\n"],"names":["uni","config"],"mappings":"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"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/tabBar.js.map b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/tabBar.js.map new file mode 100644 index 0000000..f5c2725 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/.sourcemap/mp-weixin/utils/tabBar.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tabBar.js","sources":["utils/tabBar.js"],"sourcesContent":["// 动态设置 tabBar\r\nexport function setTabBar(userRole) {\r\n\t// #ifdef MP-WEIXIN\r\n\ttry {\r\n\t\tif (userRole === 'staff') {\r\n\t\t\t// 工作人员:隐藏底边栏\r\n\t\t\tuni.hideTabBar({\r\n\t\t\t\tanimation: false\r\n\t\t\t})\r\n\t\t} else {\r\n\t\t\t// 普通用户:显示并恢复默认 tabBar\r\n\t\t\tuni.setTabBarItems({\r\n\t\t\t\tlist: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpagePath: 'pages/index/index',\r\n\t\t\t\t\t\ttext: '首页',\r\n\t\t\t\t\t\ticonPath: 'static/logo.png',\r\n\t\t\t\t\t\tselectedIconPath: 'static/logo.png'\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpagePath: 'pages/order/order',\r\n\t\t\t\t\t\ttext: '订单',\r\n\t\t\t\t\t\ticonPath: 'static/logo.png',\r\n\t\t\t\t\t\tselectedIconPath: 'static/logo.png'\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpagePath: 'pages/message/message',\r\n\t\t\t\t\t\ttext: '消息',\r\n\t\t\t\t\t\ticonPath: 'static/logo.png',\r\n\t\t\t\t\t\tselectedIconPath: 'static/logo.png'\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpagePath: 'pages/profile/profile',\r\n\t\t\t\t\t\ttext: '我的',\r\n\t\t\t\t\t\ticonPath: 'static/logo.png',\r\n\t\t\t\t\t\tselectedIconPath: 'static/logo.png'\r\n\t\t\t\t\t}\r\n\t\t\t\t]\r\n\t\t\t})\r\n\t\t\tuni.showTabBar({\r\n\t\t\t\tanimation: false\r\n\t\t\t})\r\n\t\t}\r\n\t} catch (e) {\r\n\t\tconsole.log('设置 tabBar 失败:', e)\r\n\t}\r\n\t// #endif\r\n}\r\n\r\n"],"names":["uni"],"mappings":";;AACO,SAAS,UAAU,UAAU;AAEnC,MAAI;AACH,QAAI,aAAa,SAAS;AAEzBA,oBAAAA,MAAI,WAAW;AAAA,QACd,WAAW;AAAA,MACf,CAAI;AAAA,IACJ,OAAS;AAENA,oBAAAA,MAAI,eAAe;AAAA,QAClB,MAAM;AAAA,UACL;AAAA,YACC,UAAU;AAAA,YACV,MAAM;AAAA,YACN,UAAU;AAAA,YACV,kBAAkB;AAAA,UAClB;AAAA,UACD;AAAA,YACC,UAAU;AAAA,YACV,MAAM;AAAA,YACN,UAAU;AAAA,YACV,kBAAkB;AAAA,UAClB;AAAA,UACD;AAAA,YACC,UAAU;AAAA,YACV,MAAM;AAAA,YACN,UAAU;AAAA,YACV,kBAAkB;AAAA,UAClB;AAAA,UACD;AAAA,YACC,UAAU;AAAA,YACV,MAAM;AAAA,YACN,UAAU;AAAA,YACV,kBAAkB;AAAA,UAClB;AAAA,QACD;AAAA,MACL,CAAI;AACDA,oBAAAA,MAAI,WAAW;AAAA,QACd,WAAW;AAAA,MACf,CAAI;AAAA,IACD;AAAA,EACD,SAAQ,GAAG;AACXA,kBAAAA,4CAAY,iBAAiB,CAAC;AAAA,EAC9B;AAEF;;"} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/api/auth.js b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/api/auth.js new file mode 100644 index 0000000..e914662 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/api/auth.js @@ -0,0 +1,25 @@ +"use strict"; +const utils_request = require("../utils/request.js"); +function login(data) { + return utils_request.post("/water/app/auth/login", data, { + showError: false, + // 登录失败不自动提示,由页面处理 + preventDuplicate: true + }); +} +function staffLogin(data) { + return utils_request.post("/water/staff/auth/login", data, { + showError: false, + preventDuplicate: true + }); +} +function wechatLogin(data) { + return utils_request.post("/water/app/auth/wechat", data, { + showError: false, + preventDuplicate: true + }); +} +exports.login = login; +exports.staffLogin = staffLogin; +exports.wechatLogin = wechatLogin; +//# sourceMappingURL=../../.sourcemap/mp-weixin/api/auth.js.map diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.js b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.js new file mode 100644 index 0000000..18459c9 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); +const common_vendor = require("./common/vendor.js"); +const utils_tabBar = require("./utils/tabBar.js"); +if (!Math) { + "./pages/login/login.js"; + "./pages/index/index.js"; + "./pages/order/order.js"; + "./pages/message/message.js"; + "./pages/profile/profile.js"; + "./pages/staff/index.js"; + "./pages/staff/delivery.js"; + "./pages/staff/delivery-detail.js"; + "./pages/staff/delivery-task.js"; + "./pages/staff/workorder.js"; + "./pages/staff/workorder-detail.js"; + "./pages/staff/profile.js"; + "./pages/purchase/purchase.js"; + "./pages/device/device.js"; + "./pages/water-quality/water-quality.js"; + "./pages/water-quality-detail/water-quality-detail.js"; + "./pages/water-quality-alert/water-quality-alert.js"; + "./pages/customer-service/customer-service.js"; + "./pages/order-detail/order-detail.js"; + "./pages/device-detail/device-detail.js"; + "./pages/device-problem/device-problem.js"; + "./pages/order-progress/order-progress.js"; + "./pages/payment/payment.js"; + "./pages/staff/stats.js"; +} +const _sfc_main = { + __name: "App", + setup(__props) { + common_vendor.onLaunch(() => { + common_vendor.index.__f__("log", "at App.vue:6", "App Launch - 数智水管家"); + const userRole = common_vendor.index.getStorageSync("userRole") || "user"; + utils_tabBar.setTabBar(userRole); + }); + common_vendor.onShow(() => { + common_vendor.index.__f__("log", "at App.vue:13", "App Show"); + }); + common_vendor.onHide(() => { + common_vendor.index.__f__("log", "at App.vue:17", "App Hide"); + }); + return () => { + }; + } +}; +function createApp() { + const app = common_vendor.createSSRApp(_sfc_main); + return { + app + }; +} +createApp().app.mount("#app"); +exports.createApp = createApp; +//# sourceMappingURL=../.sourcemap/mp-weixin/app.js.map diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.json b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.json new file mode 100644 index 0000000..1d12fab --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.json @@ -0,0 +1,67 @@ +{ + "pages": [ + "pages/login/login", + "pages/index/index", + "pages/order/order", + "pages/message/message", + "pages/profile/profile", + "pages/staff/index", + "pages/staff/delivery", + "pages/staff/delivery-detail", + "pages/staff/delivery-task", + "pages/staff/workorder", + "pages/staff/workorder-detail", + "pages/staff/profile", + "pages/purchase/purchase", + "pages/device/device", + "pages/water-quality/water-quality", + "pages/water-quality-detail/water-quality-detail", + "pages/water-quality-alert/water-quality-alert", + "pages/customer-service/customer-service", + "pages/order-detail/order-detail", + "pages/device-detail/device-detail", + "pages/device-problem/device-problem", + "pages/order-progress/order-progress", + "pages/payment/payment", + "pages/staff/stats" + ], + "window": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "数智水管家", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "color": "#909399", + "selectedColor": "#409eff", + "backgroundColor": "#ffffff", + "borderStyle": "black", + "list": [ + { + "pagePath": "pages/index/index", + "text": "首页", + "iconPath": "static/首页.png", + "selectedIconPath": "static/首页.png" + }, + { + "pagePath": "pages/order/order", + "text": "订单", + "iconPath": "static/订单.png", + "selectedIconPath": "static/订单.png" + }, + { + "pagePath": "pages/message/message", + "text": "消息", + "iconPath": "static/消息.png", + "selectedIconPath": "static/消息.png" + }, + { + "pagePath": "pages/profile/profile", + "text": "我的", + "iconPath": "static/我的.png", + "selectedIconPath": "static/我的.png" + } + ] + }, + "usingComponents": {} +} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.wxss b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.wxss new file mode 100644 index 0000000..9a0ae85 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/app.wxss @@ -0,0 +1,7 @@ + +/* 全局样式 */ +page { + background-color: #f5f5f5; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; +} +page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display: none !important;} \ No newline at end of file diff --git a/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/common/vendor.js b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/common/vendor.js new file mode 100644 index 0000000..d084bb0 --- /dev/null +++ b/src/数智水管家/数智水管家/unpackage/dist/dev/mp-weixin/common/vendor.js @@ -0,0 +1,7934 @@ +"use strict"; +/** +* @vue/shared v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/ +function makeMap(str, expectsLowerCase) { + const set2 = new Set(str.split(",")); + return expectsLowerCase ? (val) => set2.has(val.toLowerCase()) : (val) => set2.has(val); +} +const EMPTY_OBJ = Object.freeze({}); +const EMPTY_ARR = Object.freeze([]); +const NOOP = () => { +}; +const NO = () => false; +const isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter +(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); +const isModelListener = (key) => key.startsWith("onUpdate:"); +const extend = Object.assign; +const remove = (arr, el) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } +}; +const hasOwnProperty$1 = Object.prototype.hasOwnProperty; +const hasOwn = (val, key) => hasOwnProperty$1.call(val, key); +const isArray = Array.isArray; +const isMap = (val) => toTypeString(val) === "[object Map]"; +const isSet = (val) => toTypeString(val) === "[object Set]"; +const isFunction = (val) => typeof val === "function"; +const isString = (val) => typeof val === "string"; +const isSymbol = (val) => typeof val === "symbol"; +const isObject = (val) => val !== null && typeof val === "object"; +const isPromise = (val) => { + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); +}; +const objectToString = Object.prototype.toString; +const toTypeString = (value) => objectToString.call(value); +const toRawType = (value) => { + return toTypeString(value).slice(8, -1); +}; +const isPlainObject = (val) => toTypeString(val) === "[object Object]"; +const isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; +const isReservedProp = /* @__PURE__ */ makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" +); +const isBuiltInDirective = /* @__PURE__ */ makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); +const cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +}; +const camelizeRE = /-(\w)/g; +const camelize = cacheStringFunction((str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); +}); +const hyphenateRE = /\B([A-Z])/g; +const hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() +); +const capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}); +const toHandlerKey = cacheStringFunction((str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; +}); +const hasChanged = (value, oldValue) => !Object.is(value, oldValue); +const invokeArrayFns$1 = (fns, arg) => { + for (let i = 0; i < fns.length; i++) { + fns[i](arg); + } +}; +const def = (obj, key, value) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + value + }); +}; +const looseToNumber = (val) => { + const n2 = parseFloat(val); + return isNaN(n2) ? val : n2; +}; +function normalizeClass(value) { + let res = ""; + if (isString(value)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); +} +const toDisplayString = (val) => { + return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val); +}; +const replacer = (_key, val) => { + if (val && val.__v_isRef) { + return replacer(_key, val.value); + } else if (isMap(val)) { + return { + [`Map(${val.size})`]: [...val.entries()].reduce( + (entries, [key, val2], i) => { + entries[stringifySymbol(key, i) + " =>"] = val2; + return entries; + }, + {} + ) + }; + } else if (isSet(val)) { + return { + [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v)) + }; + } else if (isSymbol(val)) { + return stringifySymbol(val); + } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { + return String(val); + } + return val; +}; +const stringifySymbol = (v, i = "") => { + var _a; + return isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v; +}; +const LOCALE_ZH_HANS = "zh-Hans"; +const LOCALE_ZH_HANT = "zh-Hant"; +const LOCALE_EN = "en"; +const LOCALE_FR = "fr"; +const LOCALE_ES = "es"; +function include(str, parts) { + return !!parts.find((part) => str.indexOf(part) !== -1); +} +function startsWith(str, parts) { + return parts.find((part) => str.indexOf(part) === 0); +} +function normalizeLocale(locale, messages) { + if (!locale) { + return; + } + locale = locale.trim().replace(/_/g, "-"); + if (messages && messages[locale]) { + return locale; + } + locale = locale.toLowerCase(); + if (locale === "chinese") { + return LOCALE_ZH_HANS; + } + if (locale.indexOf("zh") === 0) { + if (locale.indexOf("-hans") > -1) { + return LOCALE_ZH_HANS; + } + if (locale.indexOf("-hant") > -1) { + return LOCALE_ZH_HANT; + } + if (include(locale, ["-tw", "-hk", "-mo", "-cht"])) { + return LOCALE_ZH_HANT; + } + return LOCALE_ZH_HANS; + } + let locales = [LOCALE_EN, LOCALE_FR, LOCALE_ES]; + if (messages && Object.keys(messages).length > 0) { + locales = Object.keys(messages); + } + const lang = startsWith(locale, locales); + if (lang) { + return lang; + } +} +const SLOT_DEFAULT_NAME = "d"; +const ON_SHOW = "onShow"; +const ON_HIDE = "onHide"; +const ON_LAUNCH = "onLaunch"; +const ON_ERROR = "onError"; +const ON_THEME_CHANGE = "onThemeChange"; +const ON_PAGE_NOT_FOUND = "onPageNotFound"; +const ON_UNHANDLE_REJECTION = "onUnhandledRejection"; +const ON_EXIT = "onExit"; +const ON_LOAD = "onLoad"; +const ON_READY = "onReady"; +const ON_UNLOAD = "onUnload"; +const ON_INIT = "onInit"; +const ON_SAVE_EXIT_STATE = "onSaveExitState"; +const ON_RESIZE = "onResize"; +const ON_BACK_PRESS = "onBackPress"; +const ON_PAGE_SCROLL = "onPageScroll"; +const ON_TAB_ITEM_TAP = "onTabItemTap"; +const ON_REACH_BOTTOM = "onReachBottom"; +const ON_PULL_DOWN_REFRESH = "onPullDownRefresh"; +const ON_SHARE_TIMELINE = "onShareTimeline"; +const ON_SHARE_CHAT = "onShareChat"; +const ON_ADD_TO_FAVORITES = "onAddToFavorites"; +const ON_SHARE_APP_MESSAGE = "onShareAppMessage"; +const ON_NAVIGATION_BAR_BUTTON_TAP = "onNavigationBarButtonTap"; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED = "onNavigationBarSearchInputClicked"; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED = "onNavigationBarSearchInputChanged"; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED = "onNavigationBarSearchInputConfirmed"; +const ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED = "onNavigationBarSearchInputFocusChanged"; +const VIRTUAL_HOST_STYLE = "virtualHostStyle"; +const VIRTUAL_HOST_CLASS = "virtualHostClass"; +const VIRTUAL_HOST_HIDDEN = "virtualHostHidden"; +const VIRTUAL_HOST_ID = "virtualHostId"; +function hasLeadingSlash(str) { + return str.indexOf("/") === 0; +} +function addLeadingSlash(str) { + return hasLeadingSlash(str) ? str : "/" + str; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +function once(fn, ctx = null) { + let res; + return (...args) => { + if (fn) { + res = fn.apply(ctx, args); + fn = null; + } + return res; + }; +} +function getValueByDataPath(obj, path) { + if (!isString(path)) { + return; + } + path = path.replace(/\[(\d+)\]/g, ".$1"); + const parts = path.split("."); + let key = parts[0]; + if (!obj) { + obj = {}; + } + if (parts.length === 1) { + return obj[key]; + } + return getValueByDataPath(obj[key], parts.slice(1).join(".")); +} +function sortObject(obj) { + let sortObj = {}; + if (isPlainObject(obj)) { + Object.keys(obj).sort().forEach((key) => { + const _key = key; + sortObj[_key] = obj[_key]; + }); + } + return !Object.keys(sortObj) ? obj : sortObj; +} +const customizeRE = /:/g; +function customizeEvent(str) { + return camelize(str.replace(customizeRE, "-")); +} +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj ? Object.keys(obj).map((key) => { + let val = obj[key]; + if (typeof val === void 0 || val === null) { + val = ""; + } else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + "=" + encodeStr(val); + }).filter((x) => x.length > 0).join("&") : null; + return res ? `?${res}` : ""; +} +const PAGE_HOOKS = [ + ON_INIT, + ON_LOAD, + ON_SHOW, + ON_HIDE, + ON_UNLOAD, + ON_BACK_PRESS, + ON_PAGE_SCROLL, + ON_TAB_ITEM_TAP, + ON_REACH_BOTTOM, + ON_PULL_DOWN_REFRESH, + ON_SHARE_TIMELINE, + ON_SHARE_APP_MESSAGE, + ON_SHARE_CHAT, + ON_ADD_TO_FAVORITES, + ON_SAVE_EXIT_STATE, + ON_NAVIGATION_BAR_BUTTON_TAP, + ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, + ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED +]; +function isRootHook(name) { + return PAGE_HOOKS.indexOf(name) > -1; +} +const UniLifecycleHooks = [ + ON_SHOW, + ON_HIDE, + ON_LAUNCH, + ON_ERROR, + ON_THEME_CHANGE, + ON_PAGE_NOT_FOUND, + ON_UNHANDLE_REJECTION, + ON_EXIT, + ON_INIT, + ON_LOAD, + ON_READY, + ON_UNLOAD, + ON_RESIZE, + ON_BACK_PRESS, + ON_PAGE_SCROLL, + ON_TAB_ITEM_TAP, + ON_REACH_BOTTOM, + ON_PULL_DOWN_REFRESH, + ON_SHARE_TIMELINE, + ON_ADD_TO_FAVORITES, + ON_SHARE_APP_MESSAGE, + ON_SHARE_CHAT, + ON_SAVE_EXIT_STATE, + ON_NAVIGATION_BAR_BUTTON_TAP, + ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, + ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED +]; +const MINI_PROGRAM_PAGE_RUNTIME_HOOKS = /* @__PURE__ */ (() => { + return { + onPageScroll: 1, + onShareAppMessage: 1 << 1, + onShareTimeline: 1 << 2 + }; +})(); +function isUniLifecycleHook(name, value, checkType = true) { + if (checkType && !isFunction(value)) { + return false; + } + if (UniLifecycleHooks.indexOf(name) > -1) { + return true; + } else if (name.indexOf("on") === 0) { + return true; + } + return false; +} +let vueApp; +const createVueAppHooks = []; +function onCreateVueApp(hook) { + if (vueApp) { + return hook(vueApp); + } + createVueAppHooks.push(hook); +} +function invokeCreateVueAppHook(app) { + vueApp = app; + createVueAppHooks.forEach((hook) => hook(app)); +} +const invokeCreateErrorHandler = once((app, createErrorHandler2) => { + return createErrorHandler2(app); +}); +const E = function() { +}; +E.prototype = { + _id: 1, + on: function(name, callback, ctx) { + var e2 = this.e || (this.e = {}); + (e2[name] || (e2[name] = [])).push({ + fn: callback, + ctx, + _id: this._id + }); + return this._id++; + }, + once: function(name, callback, ctx) { + var self2 = this; + function listener() { + self2.off(name, listener); + callback.apply(ctx, arguments); + } + listener._ = callback; + return this.on(name, listener, ctx); + }, + emit: function(name) { + var data = [].slice.call(arguments, 1); + var evtArr = ((this.e || (this.e = {}))[name] || []).slice(); + var i = 0; + var len = evtArr.length; + for (i; i < len; i++) { + evtArr[i].fn.apply(evtArr[i].ctx, data); + } + return this; + }, + off: function(name, event) { + var e2 = this.e || (this.e = {}); + var evts = e2[name]; + var liveEvents = []; + if (evts && event) { + for (var i = evts.length - 1; i >= 0; i--) { + if (evts[i].fn === event || evts[i].fn._ === event || evts[i]._id === event) { + evts.splice(i, 1); + break; + } + } + liveEvents = evts; + } + liveEvents.length ? e2[name] = liveEvents : delete e2[name]; + return this; + } +}; +var E$1 = E; +/** +* @dcloudio/uni-mp-vue v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/ +function warn$2(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} +let activeEffectScope; +class EffectScope { + constructor(detached = false) { + this.detached = detached; + this._active = true; + this.effects = []; + this.cleanups = []; + this.parent = activeEffectScope; + if (!detached && activeEffectScope) { + this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( + this + ) - 1; + } + } + get active() { + return this._active; + } + run(fn) { + if (this._active) { + const currentEffectScope = activeEffectScope; + try { + activeEffectScope = this; + return fn(); + } finally { + activeEffectScope = currentEffectScope; + } + } else { + warn$2(`cannot run an inactive effect scope.`); + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + on() { + activeEffectScope = this; + } + /** + * This should only be called on non-detached scopes + * @internal + */ + off() { + activeEffectScope = this.parent; + } + stop(fromParent) { + if (this._active) { + let i, l; + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].stop(); + } + for (i = 0, l = this.cleanups.length; i < l; i++) { + this.cleanups[i](); + } + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].stop(true); + } + } + if (!this.detached && this.parent && !fromParent) { + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.parent = void 0; + this._active = false; + } + } +} +function recordEffectScope(effect2, scope = activeEffectScope) { + if (scope && scope.active) { + scope.effects.push(effect2); + } +} +function getCurrentScope() { + return activeEffectScope; +} +let activeEffect; +class ReactiveEffect { + constructor(fn, trigger2, scheduler, scope) { + this.fn = fn; + this.trigger = trigger2; + this.scheduler = scheduler; + this.active = true; + this.deps = []; + this._dirtyLevel = 4; + this._trackId = 0; + this._runnings = 0; + this._shouldSchedule = false; + this._depsLength = 0; + recordEffectScope(this, scope); + } + get dirty() { + if (this._dirtyLevel === 2 || this._dirtyLevel === 3) { + this._dirtyLevel = 1; + pauseTracking(); + for (let i = 0; i < this._depsLength; i++) { + const dep = this.deps[i]; + if (dep.computed) { + triggerComputed(dep.computed); + if (this._dirtyLevel >= 4) { + break; + } + } + } + if (this._dirtyLevel === 1) { + this._dirtyLevel = 0; + } + resetTracking(); + } + return this._dirtyLevel >= 4; + } + set dirty(v) { + this._dirtyLevel = v ? 4 : 0; + } + run() { + this._dirtyLevel = 0; + if (!this.active) { + return this.fn(); + } + let lastShouldTrack = shouldTrack; + let lastEffect = activeEffect; + try { + shouldTrack = true; + activeEffect = this; + this._runnings++; + preCleanupEffect(this); + return this.fn(); + } finally { + postCleanupEffect(this); + this._runnings--; + activeEffect = lastEffect; + shouldTrack = lastShouldTrack; + } + } + stop() { + var _a; + if (this.active) { + preCleanupEffect(this); + postCleanupEffect(this); + (_a = this.onStop) == null ? void 0 : _a.call(this); + this.active = false; + } + } +} +function triggerComputed(computed2) { + return computed2.value; +} +function preCleanupEffect(effect2) { + effect2._trackId++; + effect2._depsLength = 0; +} +function postCleanupEffect(effect2) { + if (effect2.deps.length > effect2._depsLength) { + for (let i = effect2._depsLength; i < effect2.deps.length; i++) { + cleanupDepEffect(effect2.deps[i], effect2); + } + effect2.deps.length = effect2._depsLength; + } +} +function cleanupDepEffect(dep, effect2) { + const trackId = dep.get(effect2); + if (trackId !== void 0 && effect2._trackId !== trackId) { + dep.delete(effect2); + if (dep.size === 0) { + dep.cleanup(); + } + } +} +let shouldTrack = true; +let pauseScheduleStack = 0; +const trackStack = []; +function pauseTracking() { + trackStack.push(shouldTrack); + shouldTrack = false; +} +function resetTracking() { + const last = trackStack.pop(); + shouldTrack = last === void 0 ? true : last; +} +function pauseScheduling() { + pauseScheduleStack++; +} +function resetScheduling() { + pauseScheduleStack--; + while (!pauseScheduleStack && queueEffectSchedulers.length) { + queueEffectSchedulers.shift()(); + } +} +function trackEffect(effect2, dep, debuggerEventExtraInfo) { + var _a; + if (dep.get(effect2) !== effect2._trackId) { + dep.set(effect2, effect2._trackId); + const oldDep = effect2.deps[effect2._depsLength]; + if (oldDep !== dep) { + if (oldDep) { + cleanupDepEffect(oldDep, effect2); + } + effect2.deps[effect2._depsLength++] = dep; + } else { + effect2._depsLength++; + } + { + (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo)); + } + } +} +const queueEffectSchedulers = []; +function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) { + var _a; + pauseScheduling(); + for (const effect2 of dep.keys()) { + let tracking; + if (effect2._dirtyLevel < dirtyLevel && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) { + effect2._shouldSchedule || (effect2._shouldSchedule = effect2._dirtyLevel === 0); + effect2._dirtyLevel = dirtyLevel; + } + if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) { + { + (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo)); + } + effect2.trigger(); + if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) { + effect2._shouldSchedule = false; + if (effect2.scheduler) { + queueEffectSchedulers.push(effect2.scheduler); + } + } + } + } + resetScheduling(); +} +const createDep = (cleanup, computed2) => { + const dep = /* @__PURE__ */ new Map(); + dep.cleanup = cleanup; + dep.computed = computed2; + return dep; +}; +const targetMap = /* @__PURE__ */ new WeakMap(); +const ITERATE_KEY = Symbol("iterate"); +const MAP_KEY_ITERATE_KEY = Symbol("Map key iterate"); +function track(target, type, key) { + if (shouldTrack && activeEffect) { + let depsMap = targetMap.get(target); + if (!depsMap) { + targetMap.set(target, depsMap = /* @__PURE__ */ new Map()); + } + let dep = depsMap.get(key); + if (!dep) { + depsMap.set(key, dep = createDep(() => depsMap.delete(key))); + } + trackEffect( + activeEffect, + dep, + { + target, + type, + key + } + ); + } +} +function trigger(target, type, key, newValue, oldValue, oldTarget) { + const depsMap = targetMap.get(target); + if (!depsMap) { + return; + } + let deps = []; + if (type === "clear") { + deps = [...depsMap.values()]; + } else if (key === "length" && isArray(target)) { + const newLength = Number(newValue); + depsMap.forEach((dep, key2) => { + if (key2 === "length" || !isSymbol(key2) && key2 >= newLength) { + deps.push(dep); + } + }); + } else { + if (key !== void 0) { + deps.push(depsMap.get(key)); + } + switch (type) { + case "add": + if (!isArray(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } else if (isIntegerKey(key)) { + deps.push(depsMap.get("length")); + } + break; + case "delete": + if (!isArray(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } + break; + case "set": + if (isMap(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + } + break; + } + } + pauseScheduling(); + for (const dep of deps) { + if (dep) { + triggerEffects( + dep, + 4, + { + target, + type, + key, + newValue, + oldValue, + oldTarget + } + ); + } + } + resetScheduling(); +} +const isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`); +const builtInSymbols = new Set( + /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol) +); +const arrayInstrumentations = /* @__PURE__ */ createArrayInstrumentations(); +function createArrayInstrumentations() { + const instrumentations = {}; + ["includes", "indexOf", "lastIndexOf"].forEach((key) => { + instrumentations[key] = function(...args) { + const arr = toRaw(this); + for (let i = 0, l = this.length; i < l; i++) { + track(arr, "get", i + ""); + } + const res = arr[key](...args); + if (res === -1 || res === false) { + return arr[key](...args.map(toRaw)); + } else { + return res; + } + }; + }); + ["push", "pop", "shift", "unshift", "splice"].forEach((key) => { + instrumentations[key] = function(...args) { + pauseTracking(); + pauseScheduling(); + const res = toRaw(this)[key].apply(this, args); + resetScheduling(); + resetTracking(); + return res; + }; + }); + return instrumentations; +} +function hasOwnProperty(key) { + const obj = toRaw(this); + track(obj, "has", key); + return obj.hasOwnProperty(key); +} +class BaseReactiveHandler { + constructor(_isReadonly = false, _isShallow = false) { + this._isReadonly = _isReadonly; + this._isShallow = _isShallow; + } + get(target, key, receiver) { + const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow; + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_isShallow") { + return isShallow2; + } else if (key === "__v_raw") { + if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype + // this means the reciever is a user proxy of the reactive proxy + Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) { + return target; + } + return; + } + const targetIsArray = isArray(target); + if (!isReadonly2) { + if (targetIsArray && hasOwn(arrayInstrumentations, key)) { + return Reflect.get(arrayInstrumentations, key, receiver); + } + if (key === "hasOwnProperty") { + return hasOwnProperty; + } + } + const res = Reflect.get(target, key, receiver); + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { + return res; + } + if (!isReadonly2) { + track(target, "get", key); + } + if (isShallow2) { + return res; + } + if (isRef(res)) { + return targetIsArray && isIntegerKey(key) ? res : res.value; + } + if (isObject(res)) { + return isReadonly2 ? readonly(res) : reactive(res); + } + return res; + } +} +class MutableReactiveHandler extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { + let oldValue = target[key]; + if (!this._isShallow) { + const isOldValueReadonly = isReadonly(oldValue); + if (!isShallow(value) && !isReadonly(value)) { + oldValue = toRaw(oldValue); + value = toRaw(value); + } + if (!isArray(target) && isRef(oldValue) && !isRef(value)) { + if (isOldValueReadonly) { + return false; + } else { + oldValue.value = value; + return true; + } + } + } + const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key); + const result = Reflect.set(target, key, value, receiver); + if (target === toRaw(receiver)) { + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + } + return result; + } + deleteProperty(target, key) { + const hadKey = hasOwn(target, key); + const oldValue = target[key]; + const result = Reflect.deleteProperty(target, key); + if (result && hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + } + has(target, key) { + const result = Reflect.has(target, key); + if (!isSymbol(key) || !builtInSymbols.has(key)) { + track(target, "has", key); + } + return result; + } + ownKeys(target) { + track( + target, + "iterate", + isArray(target) ? "length" : ITERATE_KEY + ); + return Reflect.ownKeys(target); + } +} +class ReadonlyReactiveHandler extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } + set(target, key) { + { + warn$2( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } + deleteProperty(target, key) { + { + warn$2( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } +} +const mutableHandlers = /* @__PURE__ */ new MutableReactiveHandler(); +const readonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler(); +const shallowReactiveHandlers = /* @__PURE__ */ new MutableReactiveHandler( + true +); +const shallowReadonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler(true); +const toShallow = (value) => value; +const getProto = (v) => Reflect.getPrototypeOf(v); +function get(target, key, isReadonly2 = false, isShallow2 = false) { + target = target["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "get", key); + } + track(rawTarget, "get", rawKey); + } + const { has: has2 } = getProto(rawTarget); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + if (has2.call(rawTarget, key)) { + return wrap(target.get(key)); + } else if (has2.call(rawTarget, rawKey)) { + return wrap(target.get(rawKey)); + } else if (target !== rawTarget) { + target.get(key); + } +} +function has$1(key, isReadonly2 = false) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "has", key); + } + track(rawTarget, "has", rawKey); + } + return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey); +} +function size(target, isReadonly2 = false) { + target = target["__v_raw"]; + !isReadonly2 && track(toRaw(target), "iterate", ITERATE_KEY); + return Reflect.get(target, "size", target); +} +function add(value) { + value = toRaw(value); + const target = toRaw(this); + const proto = getProto(target); + const hadKey = proto.has.call(target, value); + if (!hadKey) { + target.add(value); + trigger(target, "add", value, value); + } + return this; +} +function set$1(key, value) { + value = toRaw(value); + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2.call(target, key); + target.set(key, value); + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + return this; +} +function deleteEntry(key) { + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2 ? get2.call(target, key) : void 0; + const result = target.delete(key); + if (hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; +} +function clear() { + const target = toRaw(this); + const hadItems = target.size !== 0; + const oldTarget = isMap(target) ? new Map(target) : new Set(target); + const result = target.clear(); + if (hadItems) { + trigger(target, "clear", void 0, void 0, oldTarget); + } + return result; +} +function createForEach(isReadonly2, isShallow2) { + return function forEach(callback, thisArg) { + const observed = this; + const target = observed["__v_raw"]; + const rawTarget = toRaw(target); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track(rawTarget, "iterate", ITERATE_KEY); + return target.forEach((value, key) => { + return callback.call(thisArg, wrap(value), wrap(key), observed); + }); + }; +} +function createIterableMethod(method, isReadonly2, isShallow2) { + return function(...args) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const targetIsMap = isMap(rawTarget); + const isPair = method === "entries" || method === Symbol.iterator && targetIsMap; + const isKeyOnly = method === "keys" && targetIsMap; + const innerIterator = target[method](...args); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track( + rawTarget, + "iterate", + isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY + ); + return { + // iterator protocol + next() { + const { value, done } = innerIterator.next(); + return done ? { value, done } : { + value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), + done + }; + }, + // iterable protocol + [Symbol.iterator]() { + return this; + } + }; + }; +} +function createReadonlyMethod(type) { + return function(...args) { + { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn$2( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } + return type === "delete" ? false : type === "clear" ? void 0 : this; + }; +} +function createInstrumentations() { + const mutableInstrumentations2 = { + get(key) { + return get(this, key); + }, + get size() { + return size(this); + }, + has: has$1, + add, + set: set$1, + delete: deleteEntry, + clear, + forEach: createForEach(false, false) + }; + const shallowInstrumentations2 = { + get(key) { + return get(this, key, false, true); + }, + get size() { + return size(this); + }, + has: has$1, + add, + set: set$1, + delete: deleteEntry, + clear, + forEach: createForEach(false, true) + }; + const readonlyInstrumentations2 = { + get(key) { + return get(this, key, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has$1.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, false) + }; + const shallowReadonlyInstrumentations2 = { + get(key) { + return get(this, key, true, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has$1.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, true) + }; + const iteratorMethods = [ + "keys", + "values", + "entries", + Symbol.iterator + ]; + iteratorMethods.forEach((method) => { + mutableInstrumentations2[method] = createIterableMethod(method, false, false); + readonlyInstrumentations2[method] = createIterableMethod(method, true, false); + shallowInstrumentations2[method] = createIterableMethod(method, false, true); + shallowReadonlyInstrumentations2[method] = createIterableMethod( + method, + true, + true + ); + }); + return [ + mutableInstrumentations2, + readonlyInstrumentations2, + shallowInstrumentations2, + shallowReadonlyInstrumentations2 + ]; +} +const [ + mutableInstrumentations, + readonlyInstrumentations, + shallowInstrumentations, + shallowReadonlyInstrumentations +] = /* @__PURE__ */ createInstrumentations(); +function createInstrumentationGetter(isReadonly2, shallow) { + const instrumentations = shallow ? isReadonly2 ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly2 ? readonlyInstrumentations : mutableInstrumentations; + return (target, key, receiver) => { + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_raw") { + return target; + } + return Reflect.get( + hasOwn(instrumentations, key) && key in target ? instrumentations : target, + key, + receiver + ); + }; +} +const mutableCollectionHandlers = { + get: /* @__PURE__ */ createInstrumentationGetter(false, false) +}; +const shallowCollectionHandlers = { + get: /* @__PURE__ */ createInstrumentationGetter(false, true) +}; +const readonlyCollectionHandlers = { + get: /* @__PURE__ */ createInstrumentationGetter(true, false) +}; +const shallowReadonlyCollectionHandlers = { + get: /* @__PURE__ */ createInstrumentationGetter(true, true) +}; +function checkIdentityKeys(target, has2, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has2.call(target, rawKey)) { + const type = toRawType(target); + warn$2( + `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` + ); + } +} +const reactiveMap = /* @__PURE__ */ new WeakMap(); +const shallowReactiveMap = /* @__PURE__ */ new WeakMap(); +const readonlyMap = /* @__PURE__ */ new WeakMap(); +const shallowReadonlyMap = /* @__PURE__ */ new WeakMap(); +function targetTypeMap(rawType) { + switch (rawType) { + case "Object": + case "Array": + return 1; + case "Map": + case "Set": + case "WeakMap": + case "WeakSet": + return 2; + default: + return 0; + } +} +function getTargetType(value) { + return value["__v_skip"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value)); +} +function reactive(target) { + if (isReadonly(target)) { + return target; + } + return createReactiveObject( + target, + false, + mutableHandlers, + mutableCollectionHandlers, + reactiveMap + ); +} +function shallowReactive(target) { + return createReactiveObject( + target, + false, + shallowReactiveHandlers, + shallowCollectionHandlers, + shallowReactiveMap + ); +} +function readonly(target) { + return createReactiveObject( + target, + true, + readonlyHandlers, + readonlyCollectionHandlers, + readonlyMap + ); +} +function shallowReadonly(target) { + return createReactiveObject( + target, + true, + shallowReadonlyHandlers, + shallowReadonlyCollectionHandlers, + shallowReadonlyMap + ); +} +function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { + if (!isObject(target)) { + { + warn$2(`value cannot be made reactive: ${String(target)}`); + } + return target; + } + if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { + return target; + } + const existingProxy = proxyMap.get(target); + if (existingProxy) { + return existingProxy; + } + const targetType = getTargetType(target); + if (targetType === 0) { + return target; + } + const proxy = new Proxy( + target, + targetType === 2 ? collectionHandlers : baseHandlers + ); + proxyMap.set(target, proxy); + return proxy; +} +function isReactive(value) { + if (isReadonly(value)) { + return isReactive(value["__v_raw"]); + } + return !!(value && value["__v_isReactive"]); +} +function isReadonly(value) { + return !!(value && value["__v_isReadonly"]); +} +function isShallow(value) { + return !!(value && value["__v_isShallow"]); +} +function toRaw(observed) { + const raw = observed && observed["__v_raw"]; + return raw ? toRaw(raw) : observed; +} +function markRaw(value) { + if (Object.isExtensible(value)) { + def(value, "__v_skip", true); + } + return value; +} +const toReactive = (value) => isObject(value) ? reactive(value) : value; +const toReadonly = (value) => isObject(value) ? readonly(value) : value; +const COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided. Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`; +class ComputedRefImpl { + constructor(getter, _setter, isReadonly2, isSSR) { + this.getter = getter; + this._setter = _setter; + this.dep = void 0; + this.__v_isRef = true; + this["__v_isReadonly"] = false; + this.effect = new ReactiveEffect( + () => getter(this._value), + () => triggerRefValue( + this, + this.effect._dirtyLevel === 2 ? 2 : 3 + ) + ); + this.effect.computed = this; + this.effect.active = this._cacheable = !isSSR; + this["__v_isReadonly"] = isReadonly2; + } + get value() { + const self = toRaw(this); + if ((!self._cacheable || self.effect.dirty) && hasChanged(self._value, self._value = self.effect.run())) { + triggerRefValue(self, 4); + } + trackRefValue(self); + if (self.effect._dirtyLevel >= 2) { + if (this._warnRecursive) { + warn$2(COMPUTED_SIDE_EFFECT_WARN, ` + +getter: `, this.getter); + } + triggerRefValue(self, 2); + } + return self._value; + } + set value(newValue) { + this._setter(newValue); + } + // #region polyfill _dirty for backward compatibility third party code for Vue <= 3.3.x + get _dirty() { + return this.effect.dirty; + } + set _dirty(v) { + this.effect.dirty = v; + } + // #endregion +} +function computed$1(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + const onlyGetter = isFunction(getterOrOptions); + if (onlyGetter) { + getter = getterOrOptions; + setter = () => { + warn$2("Write operation failed: computed value is readonly"); + }; + } else { + getter = getterOrOptions.get; + setter = getterOrOptions.set; + } + const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR); + if (debugOptions && !isSSR) { + cRef.effect.onTrack = debugOptions.onTrack; + cRef.effect.onTrigger = debugOptions.onTrigger; + } + return cRef; +} +function trackRefValue(ref2) { + var _a; + if (shouldTrack && activeEffect) { + ref2 = toRaw(ref2); + trackEffect( + activeEffect, + (_a = ref2.dep) != null ? _a : ref2.dep = createDep( + () => ref2.dep = void 0, + ref2 instanceof ComputedRefImpl ? ref2 : void 0 + ), + { + target: ref2, + type: "get", + key: "value" + } + ); + } +} +function triggerRefValue(ref2, dirtyLevel = 4, newVal) { + ref2 = toRaw(ref2); + const dep = ref2.dep; + if (dep) { + triggerEffects( + dep, + dirtyLevel, + { + target: ref2, + type: "set", + key: "value", + newValue: newVal + } + ); + } +} +function isRef(r2) { + return !!(r2 && r2.__v_isRef === true); +} +function ref(value) { + return createRef(value, false); +} +function createRef(rawValue, shallow) { + if (isRef(rawValue)) { + return rawValue; + } + return new RefImpl(rawValue, shallow); +} +class RefImpl { + constructor(value, __v_isShallow) { + this.__v_isShallow = __v_isShallow; + this.dep = void 0; + this.__v_isRef = true; + this._rawValue = __v_isShallow ? value : toRaw(value); + this._value = __v_isShallow ? value : toReactive(value); + } + get value() { + trackRefValue(this); + return this._value; + } + set value(newVal) { + const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal); + newVal = useDirectValue ? newVal : toRaw(newVal); + if (hasChanged(newVal, this._rawValue)) { + this._rawValue = newVal; + this._value = useDirectValue ? newVal : toReactive(newVal); + triggerRefValue(this, 4, newVal); + } + } +} +function unref(ref2) { + return isRef(ref2) ? ref2.value : ref2; +} +const shallowUnwrapHandlers = { + get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)), + set: (target, key, value, receiver) => { + const oldValue = target[key]; + if (isRef(oldValue) && !isRef(value)) { + oldValue.value = value; + return true; + } else { + return Reflect.set(target, key, value, receiver); + } + } +}; +function proxyRefs(objectWithRefs) { + return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers); +} +const stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} +function warn$1(msg, ...args) { + pauseTracking(); + const instance = stack.length ? stack[stack.length - 1].component : null; + const appWarnHandler = instance && instance.appContext.config.warnHandler; + const trace = getComponentTrace(); + if (appWarnHandler) { + callWithErrorHandling( + appWarnHandler, + instance, + 11, + [ + msg + args.map((a) => { + var _a, _b; + return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a); + }).join(""), + instance && instance.proxy, + trace.map( + ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>` + ).join("\n"), + trace + ] + ); + } else { + const warnArgs = [`[Vue warn]: ${msg}`, ...args]; + if (trace.length && // avoid spamming console during tests + true) { + warnArgs.push(` +`, ...formatTrace(trace)); + } + console.warn(...warnArgs); + } + resetTracking(); +} +function getComponentTrace() { + let currentVNode = stack[stack.length - 1]; + if (!currentVNode) { + return []; + } + const normalizedStack = []; + while (currentVNode) { + const last = normalizedStack[0]; + if (last && last.vnode === currentVNode) { + last.recurseCount++; + } else { + normalizedStack.push({ + vnode: currentVNode, + recurseCount: 0 + }); + } + const parentInstance = currentVNode.component && currentVNode.component.parent; + currentVNode = parentInstance && parentInstance.vnode; + } + return normalizedStack; +} +function formatTrace(trace) { + const logs = []; + trace.forEach((entry, i) => { + logs.push(...i === 0 ? [] : [` +`], ...formatTraceEntry(entry)); + }); + return logs; +} +function formatTraceEntry({ vnode, recurseCount }) { + const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; + const isRoot = vnode.component ? vnode.component.parent == null : false; + const open = ` at <${formatComponentName( + vnode.component, + vnode.type, + isRoot + )}`; + const close = `>` + postfix; + return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close]; +} +function formatProps(props) { + const res = []; + const keys = Object.keys(props); + keys.slice(0, 3).forEach((key) => { + res.push(...formatProp(key, props[key])); + }); + if (keys.length > 3) { + res.push(` ...`); + } + return res; +} +function formatProp(key, value, raw) { + if (isString(value)) { + value = JSON.stringify(value); + return raw ? value : [`${key}=${value}`]; + } else if (typeof value === "number" || typeof value === "boolean" || value == null) { + return raw ? value : [`${key}=${value}`]; + } else if (isRef(value)) { + value = formatProp(key, toRaw(value.value), true); + return raw ? value : [`${key}=Ref<`, value, `>`]; + } else if (isFunction(value)) { + return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + } else { + value = toRaw(value); + return raw ? value : [`${key}=`, value]; + } +} +const ErrorTypeStrings = { + ["sp"]: "serverPrefetch hook", + ["bc"]: "beforeCreate hook", + ["c"]: "created hook", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [11]: "app warnHandler", + [12]: "ref function", + [13]: "async component loader", + [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://github.com/vuejs/core ." +}; +function callWithErrorHandling(fn, instance, type, args) { + try { + return args ? fn(...args) : fn(); + } catch (err) { + handleError(err, instance, type); + } +} +function callWithAsyncErrorHandling(fn, instance, type, args) { + if (isFunction(fn)) { + const res = callWithErrorHandling(fn, instance, type, args); + if (res && isPromise(res)) { + res.catch((err) => { + handleError(err, instance, type); + }); + } + return res; + } + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + return values; +} +function handleError(err, instance, type, throwInDev = true) { + const contextVNode = instance ? instance.vnode : null; + if (instance) { + let cur = instance.parent; + const exposedInstance = instance.proxy; + const errorInfo = ErrorTypeStrings[type] || type; + while (cur) { + const errorCapturedHooks = cur.ec; + if (errorCapturedHooks) { + for (let i = 0; i < errorCapturedHooks.length; i++) { + if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { + return; + } + } + } + cur = cur.parent; + } + const appErrorHandler = instance.appContext.config.errorHandler; + if (appErrorHandler) { + callWithErrorHandling( + appErrorHandler, + null, + 10, + [err, exposedInstance, errorInfo] + ); + return; + } + } + logError(err, type, contextVNode, throwInDev); +} +function logError(err, type, contextVNode, throwInDev = true) { + { + const info = ErrorTypeStrings[type] || type; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + console.error(err); + } else { + console.error(err); + } + } +} +let isFlushing = false; +let isFlushPending = false; +const queue$1 = []; +let flushIndex = 0; +const pendingPostFlushCbs = []; +let activePostFlushCbs = null; +let postFlushIndex = 0; +const resolvedPromise = /* @__PURE__ */ Promise.resolve(); +let currentFlushPromise = null; +const RECURSION_LIMIT = 100; +function nextTick$1(fn) { + const p2 = currentFlushPromise || resolvedPromise; + return fn ? p2.then(this ? fn.bind(this) : fn) : p2; +} +function findInsertionIndex(id) { + let start = flushIndex + 1; + let end = queue$1.length; + while (start < end) { + const middle = start + end >>> 1; + const middleJob = queue$1[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.pre) { + start = middle + 1; + } else { + end = middle; + } + } + return start; +} +function queueJob(job) { + if (!queue$1.length || !queue$1.includes( + job, + isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex + )) { + if (job.id == null) { + queue$1.push(job); + } else { + queue$1.splice(findInsertionIndex(job.id), 0, job); + } + queueFlush(); + } +} +function queueFlush() { + if (!isFlushing && !isFlushPending) { + isFlushPending = true; + currentFlushPromise = resolvedPromise.then(flushJobs); + } +} +function hasQueueJob(job) { + return queue$1.indexOf(job) > -1; +} +function invalidateJob(job) { + const i = queue$1.indexOf(job); + if (i > flushIndex) { + queue$1.splice(i, 1); + } +} +function queuePostFlushCb(cb) { + if (!isArray(cb)) { + if (!activePostFlushCbs || !activePostFlushCbs.includes( + cb, + cb.allowRecurse ? postFlushIndex + 1 : postFlushIndex + )) { + pendingPostFlushCbs.push(cb); + } + } else { + pendingPostFlushCbs.push(...cb); + } + queueFlush(); +} +function flushPreFlushCbs(instance, seen, i = isFlushing ? flushIndex + 1 : 0) { + { + seen = seen || /* @__PURE__ */ new Map(); + } + for (; i < queue$1.length; i++) { + const cb = queue$1[i]; + if (cb && cb.pre) { + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + queue$1.splice(i, 1); + i--; + cb(); + } + } +} +function flushPostFlushCbs(seen) { + if (pendingPostFlushCbs.length) { + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); + pendingPostFlushCbs.length = 0; + if (activePostFlushCbs) { + activePostFlushCbs.push(...deduped); + return; + } + activePostFlushCbs = deduped; + { + seen = seen || /* @__PURE__ */ new Map(); + } + for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + if (checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) { + continue; + } + activePostFlushCbs[postFlushIndex](); + } + activePostFlushCbs = null; + postFlushIndex = 0; + } +} +const getId = (job) => job.id == null ? Infinity : job.id; +const comparator = (a, b) => { + const diff2 = getId(a) - getId(b); + if (diff2 === 0) { + if (a.pre && !b.pre) + return -1; + if (b.pre && !a.pre) + return 1; + } + return diff2; +}; +function flushJobs(seen) { + isFlushPending = false; + isFlushing = true; + { + seen = seen || /* @__PURE__ */ new Map(); + } + queue$1.sort(comparator); + const check = (job) => checkRecursiveUpdates(seen, job); + try { + for (flushIndex = 0; flushIndex < queue$1.length; flushIndex++) { + const job = queue$1[flushIndex]; + if (job && job.active !== false) { + if (check(job)) { + continue; + } + callWithErrorHandling(job, null, 14); + } + } + } finally { + flushIndex = 0; + queue$1.length = 0; + flushPostFlushCbs(seen); + isFlushing = false; + currentFlushPromise = null; + if (queue$1.length || pendingPostFlushCbs.length) { + flushJobs(seen); + } + } +} +function checkRecursiveUpdates(seen, fn) { + if (!seen.has(fn)) { + seen.set(fn, 1); + } else { + const count = seen.get(fn); + if (count > RECURSION_LIMIT) { + const instance = fn.ownerInstance; + const componentName = instance && getComponentName(instance.type); + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 + ); + return true; + } else { + seen.set(fn, count + 1); + } + } +} +let devtools; +let buffer = []; +let devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools) { + devtools.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook(hook, target) { + var _a, _b; + devtools = hook; + if (devtools) { + devtools.enabled = true; + buffer.forEach(({ event, args }) => devtools.emit(event, ...args)); + buffer = []; + } else if ( + // handle late devtools injection - only do this if we are in an actual + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook(newHook, target); + }); + setTimeout(() => { + if (!devtools) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +const devtoolsComponentAdded = /* @__PURE__ */ createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +const devtoolsComponentUpdated = /* @__PURE__ */ createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +const _devtoolsComponentRemoved = /* @__PURE__ */ createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +const devtoolsComponentRemoved = (component) => { + if (devtools && typeof devtools.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +/*! #__NO_SIDE_EFFECTS__ */ +// @__NO_SIDE_EFFECTS__ +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + // fixed by xxxxxx + // 为 0 是 App,无 parent 是 Page 指向 App + component.uid === 0 ? void 0 : component.parent ? component.parent.uid : 0, + component + ); + }; +} +const devtoolsPerfStart = /* @__PURE__ */ createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +const devtoolsPerfEnd = /* @__PURE__ */ createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} +function emit(instance, event, ...rawArgs) { + if (instance.isUnmounted) + return; + const props = instance.vnode.props || EMPTY_OBJ; + { + const { + emitsOptions, + propsOptions: [propsOptions] + } = instance; + if (emitsOptions) { + if (!(event in emitsOptions) && true) { + if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { + warn$1( + `Component emitted event "${event}" but it is neither declared in the emits option nor as an "${toHandlerKey(event)}" prop.` + ); + } + } else { + const validator = emitsOptions[event]; + if (isFunction(validator)) { + const isValid = validator(...rawArgs); + if (!isValid) { + warn$1( + `Invalid event arguments: event validation failed for event "${event}".` + ); + } + } + } + } + } + let args = rawArgs; + const isModelListener2 = event.startsWith("update:"); + const modelArg = isModelListener2 && event.slice(7); + if (modelArg && modelArg in props) { + const modifiersKey = `${modelArg === "modelValue" ? "model" : modelArg}Modifiers`; + const { number, trim } = props[modifiersKey] || EMPTY_OBJ; + if (trim) { + args = rawArgs.map((a) => isString(a) ? a.trim() : a); + } + if (number) { + args = rawArgs.map(looseToNumber); + } + } + { + devtoolsComponentEmit(instance, event, args); + } + { + const lowerCaseEvent = event.toLowerCase(); + if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { + warn$1( + `Event "${lowerCaseEvent}" is emitted in component ${formatComponentName( + instance, + instance.type + )} but the handler is registered for "${event}". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "${hyphenate( + event + )}" instead of "${event}".` + ); + } + } + let handlerName; + let handler = props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249) + props[handlerName = toHandlerKey(camelize(event))]; + if (!handler && isModelListener2) { + handler = props[handlerName = toHandlerKey(hyphenate(event))]; + } + if (handler) { + callWithAsyncErrorHandling( + handler, + instance, + 6, + args + ); + } + const onceHandler = props[handlerName + `Once`]; + if (onceHandler) { + if (!instance.emitted) { + instance.emitted = {}; + } else if (instance.emitted[handlerName]) { + return; + } + instance.emitted[handlerName] = true; + callWithAsyncErrorHandling( + onceHandler, + instance, + 6, + args + ); + } +} +function normalizeEmitsOptions(comp, appContext, asMixin = false) { + const cache = appContext.emitsCache; + const cached = cache.get(comp); + if (cached !== void 0) { + return cached; + } + const raw = comp.emits; + let normalized = {}; + let hasExtends = false; + if (!isFunction(comp)) { + const extendEmits = (raw2) => { + const normalizedFromExtend = normalizeEmitsOptions(raw2, appContext, true); + if (normalizedFromExtend) { + hasExtends = true; + extend(normalized, normalizedFromExtend); + } + }; + if (!asMixin && appContext.mixins.length) { + appContext.mixins.forEach(extendEmits); + } + if (comp.extends) { + extendEmits(comp.extends); + } + if (comp.mixins) { + comp.mixins.forEach(extendEmits); + } + } + if (!raw && !hasExtends) { + if (isObject(comp)) { + cache.set(comp, null); + } + return null; + } + if (isArray(raw)) { + raw.forEach((key) => normalized[key] = null); + } else { + extend(normalized, raw); + } + if (isObject(comp)) { + cache.set(comp, normalized); + } + return normalized; +} +function isEmitListener(options, key) { + if (!options || !isOn(key)) { + return false; + } + key = key.slice(2).replace(/Once$/, ""); + return hasOwn(options, key[0].toLowerCase() + key.slice(1)) || hasOwn(options, hyphenate(key)) || hasOwn(options, key); +} +let currentRenderingInstance = null; +function setCurrentRenderingInstance(instance) { + const prev = currentRenderingInstance; + currentRenderingInstance = instance; + instance && instance.type.__scopeId || null; + return prev; +} +const INITIAL_WATCHER_VALUE = {}; +function watch(source, cb, options) { + if (!isFunction(cb)) { + warn$1( + `\`watch(fn, options?)\` signature has been moved to a separate API. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.` + ); + } + return doWatch(source, cb, options); +} +function doWatch(source, cb, { + immediate, + deep, + flush, + once: once2, + onTrack, + onTrigger +} = EMPTY_OBJ) { + if (cb && once2) { + const _cb = cb; + cb = (...args) => { + _cb(...args); + unwatch(); + }; + } + if (deep !== void 0 && typeof deep === "number") { + warn$1( + `watch() "deep" option with number value will be used as watch depth in future versions. Please use a boolean instead to avoid potential breakage.` + ); + } + if (!cb) { + if (immediate !== void 0) { + warn$1( + `watch() "immediate" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (deep !== void 0) { + warn$1( + `watch() "deep" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (once2 !== void 0) { + warn$1( + `watch() "once" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + } + const warnInvalidSource = (s2) => { + warn$1( + `Invalid watch source: `, + s2, + `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` + ); + }; + const instance = currentInstance; + const reactiveGetter = (source2) => deep === true ? source2 : ( + // for deep: false, only traverse root-level properties + traverse(source2, deep === false ? 1 : void 0) + ); + let getter; + let forceTrigger = false; + let isMultiSource = false; + if (isRef(source)) { + getter = () => source.value; + forceTrigger = isShallow(source); + } else if (isReactive(source)) { + getter = () => reactiveGetter(source); + forceTrigger = true; + } else if (isArray(source)) { + isMultiSource = true; + forceTrigger = source.some((s2) => isReactive(s2) || isShallow(s2)); + getter = () => source.map((s2) => { + if (isRef(s2)) { + return s2.value; + } else if (isReactive(s2)) { + return reactiveGetter(s2); + } else if (isFunction(s2)) { + return callWithErrorHandling(s2, instance, 2); + } else { + warnInvalidSource(s2); + } + }); + } else if (isFunction(source)) { + if (cb) { + getter = () => callWithErrorHandling(source, instance, 2); + } else { + getter = () => { + if (cleanup) { + cleanup(); + } + return callWithAsyncErrorHandling( + source, + instance, + 3, + [onCleanup] + ); + }; + } + } else { + getter = NOOP; + warnInvalidSource(source); + } + if (cb && deep) { + const baseGetter = getter; + getter = () => traverse(baseGetter()); + } + let cleanup; + let onCleanup = (fn) => { + cleanup = effect2.onStop = () => { + callWithErrorHandling(fn, instance, 4); + cleanup = effect2.onStop = void 0; + }; + }; + let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; + const job = () => { + if (!effect2.active || !effect2.dirty) { + return; + } + if (cb) { + const newValue = effect2.run(); + if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue)) || false) { + if (cleanup) { + cleanup(); + } + callWithAsyncErrorHandling(cb, instance, 3, [ + newValue, + // pass undefined as the old value when it's changed for the first time + oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue, + onCleanup + ]); + oldValue = newValue; + } + } else { + effect2.run(); + } + }; + job.allowRecurse = !!cb; + let scheduler; + if (flush === "sync") { + scheduler = job; + } else if (flush === "post") { + scheduler = () => queuePostRenderEffect$1(job, instance && instance.suspense); + } else { + job.pre = true; + if (instance) + job.id = instance.uid; + scheduler = () => queueJob(job); + } + const effect2 = new ReactiveEffect(getter, NOOP, scheduler); + const scope = getCurrentScope(); + const unwatch = () => { + effect2.stop(); + if (scope) { + remove(scope.effects, effect2); + } + }; + { + effect2.onTrack = onTrack; + effect2.onTrigger = onTrigger; + } + if (cb) { + if (immediate) { + job(); + } else { + oldValue = effect2.run(); + } + } else if (flush === "post") { + queuePostRenderEffect$1( + effect2.run.bind(effect2), + instance && instance.suspense + ); + } else { + effect2.run(); + } + return unwatch; +} +function instanceWatch(source, value, options) { + const publicThis = this.proxy; + const getter = isString(source) ? source.includes(".") ? createPathGetter(publicThis, source) : () => publicThis[source] : source.bind(publicThis, publicThis); + let cb; + if (isFunction(value)) { + cb = value; + } else { + cb = value.handler; + options = value; + } + const reset = setCurrentInstance(this); + const res = doWatch(getter, cb.bind(publicThis), options); + reset(); + return res; +} +function createPathGetter(ctx, path) { + const segments = path.split("."); + return () => { + let cur = ctx; + for (let i = 0; i < segments.length && cur; i++) { + cur = cur[segments[i]]; + } + return cur; + }; +} +function traverse(value, depth, currentDepth = 0, seen) { + if (!isObject(value) || value["__v_skip"]) { + return value; + } + if (depth && depth > 0) { + if (currentDepth >= depth) { + return value; + } + currentDepth++; + } + seen = seen || /* @__PURE__ */ new Set(); + if (seen.has(value)) { + return value; + } + seen.add(value); + if (isRef(value)) { + traverse(value.value, depth, currentDepth, seen); + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + traverse(value[i], depth, currentDepth, seen); + } + } else if (isSet(value) || isMap(value)) { + value.forEach((v) => { + traverse(v, depth, currentDepth, seen); + }); + } else if (isPlainObject(value)) { + for (const key in value) { + traverse(value[key], depth, currentDepth, seen); + } + } + return value; +} +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} +function createAppContext() { + return { + app: null, + config: { + isNativeTag: NO, + performance: false, + globalProperties: {}, + optionMergeStrategies: {}, + errorHandler: void 0, + warnHandler: void 0, + compilerOptions: {} + }, + mixins: [], + components: {}, + directives: {}, + provides: /* @__PURE__ */ Object.create(null), + optionsCache: /* @__PURE__ */ new WeakMap(), + propsCache: /* @__PURE__ */ new WeakMap(), + emitsCache: /* @__PURE__ */ new WeakMap() + }; +} +let uid$1 = 0; +function createAppAPI(render, hydrate) { + return function createApp2(rootComponent, rootProps = null) { + if (!isFunction(rootComponent)) { + rootComponent = extend({}, rootComponent); + } + if (rootProps != null && !isObject(rootProps)) { + warn$1(`root props passed to app.mount() must be an object.`); + rootProps = null; + } + const context = createAppContext(); + const installedPlugins = /* @__PURE__ */ new WeakSet(); + const app = context.app = { + _uid: uid$1++, + _component: rootComponent, + _props: rootProps, + _container: null, + _context: context, + _instance: null, + version, + get config() { + return context.config; + }, + set config(v) { + { + warn$1( + `app.config cannot be replaced. Modify individual options instead.` + ); + } + }, + use(plugin2, ...options) { + if (installedPlugins.has(plugin2)) { + warn$1(`Plugin has already been applied to target app.`); + } else if (plugin2 && isFunction(plugin2.install)) { + installedPlugins.add(plugin2); + plugin2.install(app, ...options); + } else if (isFunction(plugin2)) { + installedPlugins.add(plugin2); + plugin2(app, ...options); + } else { + warn$1( + `A plugin must either be a function or an object with an "install" function.` + ); + } + return app; + }, + mixin(mixin) { + { + if (!context.mixins.includes(mixin)) { + context.mixins.push(mixin); + } else { + warn$1( + "Mixin has already been applied to target app" + (mixin.name ? `: ${mixin.name}` : "") + ); + } + } + return app; + }, + component(name, component) { + { + validateComponentName(name, context.config); + } + if (!component) { + return context.components[name]; + } + if (context.components[name]) { + warn$1(`Component "${name}" has already been registered in target app.`); + } + context.components[name] = component; + return app; + }, + directive(name, directive) { + { + validateDirectiveName(name); + } + if (!directive) { + return context.directives[name]; + } + if (context.directives[name]) { + warn$1(`Directive "${name}" has already been registered in target app.`); + } + context.directives[name] = directive; + return app; + }, + // fixed by xxxxxx + mount() { + }, + // fixed by xxxxxx + unmount() { + }, + provide(key, value) { + if (key in context.provides) { + warn$1( + `App already provides property with key "${String(key)}". It will be overwritten with the new value.` + ); + } + context.provides[key] = value; + return app; + }, + runWithContext(fn) { + const lastApp = currentApp; + currentApp = app; + try { + return fn(); + } finally { + currentApp = lastApp; + } + } + }; + return app; + }; +} +let currentApp = null; +function provide(key, value) { + if (!currentInstance) { + { + warn$1(`provide() can only be used inside setup().`); + } + } else { + let provides = currentInstance.provides; + const parentProvides = currentInstance.parent && currentInstance.parent.provides; + if (parentProvides === provides) { + provides = currentInstance.provides = Object.create(parentProvides); + } + provides[key] = value; + if (currentInstance.type.mpType === "app") { + currentInstance.appContext.app.provide(key, value); + } + } +} +function inject(key, defaultValue, treatDefaultAsFactory = false) { + const instance = currentInstance || currentRenderingInstance; + if (instance || currentApp) { + const provides = instance ? instance.parent == null ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : currentApp._context.provides; + if (provides && key in provides) { + return provides[key]; + } else if (arguments.length > 1) { + return treatDefaultAsFactory && isFunction(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue; + } else { + warn$1(`injection "${String(key)}" not found.`); + } + } else { + warn$1(`inject() can only be used inside setup() or functional components.`); + } +} +const isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a", target); +} +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da", target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + const wrappedHook = hook.__wdc || (hook.__wdc = () => { + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + return hook(); + }); + injectHook(type, wrappedHook, target); + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } + } +} +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + const injected = injectHook( + type, + hook, + keepAliveRoot, + true + /* prepend */ + ); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + if (isRootHook(type)) { + target = target.root; + } + const hooks = target[type] || (target[type] = []); + const wrappedHook = hook.__weh || (hook.__weh = (...args) => { + if (target.isUnmounted) { + return; + } + pauseTracking(); + const reset = setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + reset(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); + } else { + hooks.push(wrappedHook); + } + return wrappedHook; + } else { + const apiName = toHandlerKey( + (ErrorTypeStrings[type] || type.replace(/^on/, "")).replace(/ hook$/, "") + ); + warn$1( + `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().` + ); + } +} +const createHook = (lifecycle) => (hook, target = currentInstance) => ( + // post-create lifecycle registrations are noops during SSR (except for serverPrefetch) + (!isInSSRComponentSetup || lifecycle === "sp") && injectHook(lifecycle, (...args) => hook(...args), target) +); +const onBeforeMount = createHook("bm"); +const onMounted = createHook("m"); +const onBeforeUpdate = createHook("bu"); +const onUpdated = createHook("u"); +const onBeforeUnmount = createHook("bum"); +const onUnmounted = createHook("um"); +const onServerPrefetch = createHook("sp"); +const onRenderTriggered = createHook( + "rtg" +); +const onRenderTracked = createHook( + "rtc" +); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec", hook, target); +} +const getPublicInstance = (i) => { + if (!i) + return null; + if (isStatefulComponent(i)) + return getExposeProxy(i) || i.proxy; + return getPublicInstance(i.parent); +}; +function getComponentInternalInstance(i) { + return i; +} +const publicPropertiesMap = ( + // Move PURE marker to new line to workaround compiler discarding it + // due to type annotation + /* @__PURE__ */ extend(/* @__PURE__ */ Object.create(null), { + // fixed by xxxxxx + $: getComponentInternalInstance, + // fixed by xxxxxx vue-i18n 在 dev 模式,访问了 $el,故模拟一个假的 + // $el: i => i.vnode.el, + $el: (i) => i.__$el || (i.__$el = {}), + $data: (i) => i.data, + $props: (i) => shallowReadonly(i.props), + $attrs: (i) => shallowReadonly(i.attrs), + $slots: (i) => shallowReadonly(i.slots), + $refs: (i) => shallowReadonly(i.refs), + $parent: (i) => getPublicInstance(i.parent), + $root: (i) => getPublicInstance(i.root), + $emit: (i) => i.emit, + $options: (i) => resolveMergedOptions(i), + $forceUpdate: (i) => i.f || (i.f = () => { + i.effect.dirty = true; + queueJob(i.update); + }), + // $nextTick: i => i.n || (i.n = nextTick.bind(i.proxy!)),// fixed by xxxxxx + $watch: (i) => instanceWatch.bind(i) + }) +); +const isReservedPrefix = (key) => key === "_" || key === "$"; +const hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); +const PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } + let normalizedProps; + if (key[0] !== "$") { + const n2 = accessCache[key]; + if (n2 !== void 0) { + switch (n2) { + case 1: + return setupState[key]; + case 2: + return data[key]; + case 4: + return ctx[key]; + case 3: + return props[key]; + } + } else if (hasSetupBinding(setupState, key)) { + accessCache[key] = 1; + return setupState[key]; + } else if (data !== EMPTY_OBJ && hasOwn(data, key)) { + accessCache[key] = 2; + return data[key]; + } else if ( + // only cache other properties when instance has declared (thus stable) + // props + (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key) + ) { + accessCache[key] = 3; + return props[key]; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if (shouldCacheAccess) { + accessCache[key] = 0; + } + } + const publicGetter = publicPropertiesMap[key]; + let cssModule, globalProperties; + if (publicGetter) { + if (key === "$attrs") { + track(instance, "get", key); + } else if (key === "$slots") { + track(instance, "get", key); + } + return publicGetter(instance); + } else if ( + // css module (injected by vue-loader) + (cssModule = type.__cssModules) && (cssModule = cssModule[key]) + ) { + return cssModule; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if ( + // global properties + globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key) + ) { + { + return globalProperties[key]; + } + } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + warn$1( + `Property ${JSON.stringify( + key + )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` + ); + } else if (instance === currentRenderingInstance) { + warn$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } + }, + set({ _: instance }, key, value) { + const { data, setupState, ctx } = instance; + if (hasSetupBinding(setupState, key)) { + setupState[key] = value; + return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate