Sfoglia il codice sorgente

更新引航计划需求文档和最佳实践文档

需求文档更新:
- 修改船公司查询条件描述为"可搜索的下拉选择(支持远程搜索和滚动加载)"
- 添加船公司数据查询逻辑详细说明
- 添加数据库查询示例SQL

最佳实践文档更新:
- 更新搜索下拉框实现,移除remote属性,改为使用本地filterable
- 添加滚动加载实现,包括样式、方法和生命周期钩子
- 更新后端API规范,添加完整的Service和Repository实现
- 添加数据库表结构和查询逻辑说明
heyiwen 2 settimane fa
parent
commit
021b54f4bd

+ 67 - 26
.trae/rules/web-dev-best-practices.md

@@ -683,11 +683,9 @@ request.interceptors.request.use(config => {
     style="width: 180px"
     clearable
     filterable
-    remote
-    :remote-method="searchShipCompany"
     :loading="shipCompanyLoading"
     @visible-change="handleShipCompanyVisibleChange"
-    @scroll="handleShipCompanyScroll"
+    popper-class="ship-company-select-dropdown"
   >
     <el-option
       v-for="company in shipCompanyList"
@@ -699,7 +697,22 @@ request.interceptors.request.use(config => {
 </el-form-item>
 ```
 
-#### 11.2.2 数据属性
+#### 11.2.2 样式部分
+
+```css
+/* 船公司下拉框样式 */
+.ship-company-select-dropdown {
+  max-height: 300px;
+  overflow-y: auto;
+}
+
+.ship-company-select-dropdown .el-select-dropdown__wrap {
+  max-height: 300px;
+  overflow-y: auto;
+}
+```
+
+#### 11.2.3 数据属性
 
 ```javascript
 data() {
@@ -708,38 +721,36 @@ data() {
       shipownerId: ''
     },
     shipCompanyList: [],
-    shipCompanyQuery: '',
     shipCompanyPage: 1,
     shipCompanyPageSize: 10,
+    shipCompanyTotal: 0,
     shipCompanyLoading: false,
     shipCompanyHasMore: true
   }
 }
 ```
 
-#### 11.2.3 方法实现
+#### 11.2.4 方法实现
 
 ```javascript
 methods: {
-  getShipCompanyList() {
-    this.getShipCompanyListByPage('', 1);
-  },
-  getShipCompanyListByPage(query, page) {
+  getShipCompanyList(isLoadMore = false) {
     this.shipCompanyLoading = true;
     this.$axios.get('/api/ship-company/list', {
       params: {
-        companyName: query,
-        page: page,
+        page: this.shipCompanyPage,
         pageSize: this.shipCompanyPageSize
       }
     })
       .then(response => {
-        if (page === 1) {
-          this.shipCompanyList = response.data.content || [];
+        const newCompanies = response.data.content || [];
+        if (isLoadMore) {
+          this.shipCompanyList = [...this.shipCompanyList, ...newCompanies];
         } else {
-          this.shipCompanyList = [...this.shipCompanyList, ...(response.data.content || [])];
+          this.shipCompanyList = newCompanies;
         }
-        this.shipCompanyHasMore = response.data.content && response.data.content.length >= this.shipCompanyPageSize;
+        this.shipCompanyTotal = response.data.totalElements || 0;
+        this.shipCompanyHasMore = this.shipCompanyList.length < this.shipCompanyTotal;
       })
       .catch(error => {
         console.error('获取船公司列表失败:', error);
@@ -749,26 +760,56 @@ methods: {
         this.shipCompanyLoading = false;
       });
   },
-  searchShipCompany(query) {
-    this.shipCompanyQuery = query || '';
-    this.shipCompanyPage = 1;
-    this.getShipCompanyListByPage(this.shipCompanyQuery, this.shipCompanyPage);
-  },
   handleShipCompanyVisibleChange(visible) {
-    if (visible && !this.shipCompanyQuery) {
+    if (visible) {
       this.shipCompanyPage = 1;
-      this.getShipCompanyListByPage('', this.shipCompanyPage);
+      this.getShipCompanyList();
+      this.addShipCompanyScrollListener();
+    } else {
+      this.removeShipCompanyScrollListener();
     }
   },
-  handleShipCompanyScroll() {
-    if (this.shipCompanyHasMore && !this.shipCompanyLoading) {
+  handleShipCompanyScroll(event) {
+    const { target } = event;
+    const scrollBottom = target.scrollHeight - target.scrollTop - target.clientHeight;
+    
+    if (scrollBottom < 10 && this.shipCompanyHasMore && !this.shipCompanyLoading) {
       this.shipCompanyPage++;
-      this.getShipCompanyListByPage(this.shipCompanyQuery, this.shipCompanyPage);
+      this.getShipCompanyList(true);
+    }
+  },
+  addShipCompanyScrollListener() {
+    this.$nextTick(() => {
+      const dropdown = document.querySelector('.ship-company-select-dropdown');
+      if (dropdown) {
+        const dropdownWrap = dropdown.querySelector('.el-select-dropdown__wrap');
+        if (dropdownWrap) {
+          dropdownWrap.addEventListener('scroll', this.handleShipCompanyScroll);
+        }
+      }
+    });
+  },
+  removeShipCompanyScrollListener() {
+    const dropdown = document.querySelector('.ship-company-select-dropdown');
+    if (dropdown) {
+      const dropdownWrap = dropdown.querySelector('.el-select-dropdown__wrap');
+      if (dropdownWrap) {
+        dropdownWrap.removeEventListener('scroll', this.handleShipCompanyScroll);
+      }
     }
   }
 }
 ```
 
+#### 11.2.5 生命周期钩子
+
+```javascript
+beforeUnmount() {
+  this.removeShipCompanyScrollListener();
+}
+```
+```
+
 ### 11.3 后端API规范
 
 #### 11.3.1 Controller实现

+ 30 - 2
引航计划和用户管理功能需求文档.md

@@ -27,7 +27,7 @@
 | 港口 | 港口名称 | 下拉选择 | 否 |
 | 英文船名 | 船舶英文名称 | 文本输入 | 否 |
 | 状态 | 未调度/已调度 | 下拉选择 | 否 |
-| 船公司 | 船舶所属公司 | 可搜索的下拉选择(支持远程搜索和分页加载) | 否 |
+| 船公司 | 船舶所属公司 | 可搜索的下拉选择(支持远程搜索和滚动加载) | 否 |
 | 吃水 | 船舶吃水范围(最小值-最大值) | 数值范围 | 否 |
 | 交通船 | 交通船名称 | 文本输入 | 否 |
 
@@ -445,10 +445,38 @@
 
 - 支持按船公司名称进行模糊搜索
 - 支持分页查询,避免一次性加载过多数据
-- 前端实现可搜索的下拉框,支持远程搜索和瀑布式加载
+- 前端实现可搜索的下拉框,支持远程搜索和滚动加载
 - 当用户输入搜索关键词时,触发远程搜索
 - 当下拉列表滚动到底部时,自动加载下一页数据
 
+**数据查询逻辑**:
+
+船公司查询需要关联以下两个表:
+1. **Bus_CustomerCompany**:客户公司表,存储公司基本信息
+2. **Bus_Customer_CustomerType**:客户类型关联表,存储客户与类型的关联关系
+
+查询步骤:
+1. 首先从Bus_Customer_CustomerType表中查询CustomerType=2(船公司)的所有客户ID
+2. 然后从Bus_CustomerCompany表中查询对应的客户公司信息
+3. 支持按公司名称进行模糊搜索
+4. 支持分页查询,按公司名称排序
+5. 只返回RecordStatus=1(启用)的客户公司
+
+**数据库查询示例**:
+
+```sql
+-- 第一步:查询CustomerType=2的所有客户ID
+SELECT CustomerID FROM Bus_Customer_CustomerType WHERE CustomerType = 2
+
+-- 第二步:查询对应的客户公司信息(支持模糊搜索和分页)
+SELECT * FROM Bus_CustomerCompany 
+WHERE CustomerCompanyID IN (上一步的客户ID)
+AND RecordStatus = 1
+AND Name LIKE '%搜索关键词%'
+ORDER BY Name
+OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
+```
+
 ## 权限控制
 
 ### 功能权限代码