feat(contract-select): 为合同选择组件添加分页功能并优化搜索逻辑

1.  移除了vis-network依赖包
2.  重构两个合同选择页面的搜索与列表逻辑,移除本地合并合同数据的操作,改为直接使用接口返回数据
3.  为所有合同tab添加分页组件,支持分页查询、搜索重置页码
4.  调整表格高度优化布局,更新搜索触发事件为失焦、回车和清空按钮
5.  新增搜索查询按钮,优化搜索交互体验
This commit is contained in:
2026-06-18 15:39:42 +08:00
parent 6120e87966
commit 041e5aef0e
3 changed files with 87 additions and 59 deletions

View File

@@ -77,7 +77,6 @@
"three": "^0.160.1", "three": "^0.160.1",
"vditor": "^3.11.1", "vditor": "^3.11.1",
"video.js": "^8.23.3", "video.js": "^8.23.3",
"vis-network": "^8.5.2",
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",

View File

@@ -55,13 +55,14 @@
<!-- 所有合同tab --> <!-- 所有合同tab -->
<el-tab-pane label="所有合同" name="all"> <el-tab-pane label="所有合同" name="all">
<div style="margin-bottom: 16px;"> <div style="margin-bottom: 16px;">
<el-input v-model="searchKeyword" placeholder="搜索合同" @input="handleSearch" clearable <el-input v-model="searchKeyword" placeholder="搜索合同" @blur="handleSearch"
@keyup.enter.native="handleSearch" @clear="handleSearch" clearable
size="small"> size="small">
<el-button slot="append" icon="el-icon-search" size="small"></el-button> <el-button slot="append" icon="el-icon-search" @click="handleSearch" size="small"></el-button>
</el-input> </el-input>
</div> </div>
<el-table :data="allContracts" style="width: 100%" size="mini" height="600"> <el-table :data="allContracts" style="width: 100%" size="mini" height="520">
<el-table-column prop="contractCode" label="合同编号" width="160" /> <el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="contractName" label="合同名称" width="180" /> <el-table-column prop="contractName" label="合同名称" width="180" />
<el-table-column prop="customer" label="客户" width="140" /> <el-table-column prop="customer" label="客户" width="140" />
@@ -93,6 +94,10 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-pagination v-if="allTotal > 0" background layout="total, prev, pager, next, jumper"
:total="allTotal" :page-size="allPageSize" :current-page.sync="allPageNum"
@current-change="handleAllPageChange" style="margin-top: 12px; text-align: right;" />
<div v-if="allContracts.length === 0" style="text-align: center; padding: 20px;"> <div v-if="allContracts.length === 0" style="text-align: center; padding: 20px;">
暂无合同数据 暂无合同数据
</div> </div>
@@ -125,6 +130,9 @@ export default {
searchKeyword: '', searchKeyword: '',
allContracts: [], allContracts: [],
activeTab: 'configured', // 默认显示已配置合同tab activeTab: 'configured', // 默认显示已配置合同tab
allPageNum: 1,
allPageSize: 20,
allTotal: 0,
} }
}, },
computed: { computed: {
@@ -227,15 +235,12 @@ export default {
async loadAllContracts() { async loadAllContracts() {
try { try {
const res = await listOrder({ const res = await listOrder({
pageNum: 1, pageNum: this.allPageNum,
pageSize: 1000, pageSize: this.allPageSize,
keyword: this.searchKeyword || undefined, keyword: this.searchKeyword || undefined,
}); });
// 合并现有合同(包括手动添加的) this.allTotal = res.total || 0;
const existingContracts = this.contractList; this.allContracts = res.rows || [];
this.allContracts = [...res.rows || [], ...existingContracts].filter((item, index, self) =>
index === self.findIndex(t => t.orderId === item.orderId)
);
} catch (error) { } catch (error) {
console.error('Failed to load all contracts:', error); console.error('Failed to load all contracts:', error);
this.allContracts = []; this.allContracts = [];
@@ -244,6 +249,12 @@ export default {
// 搜索合同 // 搜索合同
handleSearch() { handleSearch() {
this.allPageNum = 1;
this.loadAllContracts();
},
handleAllPageChange(page) {
this.allPageNum = page;
this.loadAllContracts(); this.loadAllContracts();
}, },

View File

@@ -64,58 +64,63 @@
<el-tab-pane label="所有合同" v-loading="allLoading" name="all"> <el-tab-pane label="所有合同" v-loading="allLoading" name="all">
<div class="search-bar"> <div class="search-bar">
<el-input v-model="searchKeyword" placeholder="搜索合同编号 / 名称 / 客户" @input="handleSearch" clearable <el-input v-model="searchKeyword" placeholder="搜索合同编号 / 名称 / 客户" @blur="handleSearch"
@keyup.enter.native="handleSearch" @clear="handleSearch" clearable
size="small" class="search-input"> size="small" class="search-input">
<i slot="prefix" class="el-input__icon el-icon-search"></i> <i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input> </el-input>
<el-button type="primary" size="small" @click="handleSearch" style="margin-left: 8px;">查询</el-button>
</div> </div>
<div v-if="allContracts.length === 0" class="empty-state"> <div v-if="allContracts.length === 0" class="empty-state">
<i class="el-icon-folder-opened"></i> <i class="el-icon-folder-opened"></i>
<p>暂无合同数据</p> <p>暂无合同数据</p>
</div> </div>
<el-table v-else :data="allContracts" size="small" stripe height="calc(100vh - 320px)"> <template v-else>
<el-table-column prop="contractCode" label="合同编号" width="160" /> <el-table :data="allContracts" size="small" stripe height="calc(100vh - 400px)">
<el-table-column prop="contractName" label="合同名称" min-width="180" show-overflow-tooltip /> <el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="customer" label="客户" width="140" /> <el-table-column prop="contractName" label="合同名称" min-width="180" show-overflow-tooltip />
<el-table-column prop="salesman" label="销售人员" width="100" /> <el-table-column prop="customer" label="客户" width="140" />
<el-table-column prop="deliveryDate" label="交付日期" width="110"> <el-table-column prop="salesman" label="销售人员" width="100" />
<template slot-scope="scope"> <el-table-column prop="deliveryDate" label="交付日期" width="110">
<span :class="{ 'text-muted': !scope.row.deliveryDate }"> <template slot-scope="scope">
{{ scope.row.deliveryDate || '-' }} <span :class="{ 'text-muted': !scope.row.deliveryDate }">
</span> {{ scope.row.deliveryDate || '-' }}
</template> </span>
</el-table-column> </template>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip> </el-table-column>
<template slot-scope="scope"> <el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip>
<span :class="{ 'text-muted': !scope.row.remark }"> <template slot-scope="scope">
{{ scope.row.remark || '-' }} <span :class="{ 'text-muted': !scope.row.remark }">
</span> {{ scope.row.remark || '-' }}
</template> </span>
</el-table-column> </template>
<el-table-column label="状态" width="80" align="center"> </el-table-column>
<template slot-scope="scope"> <el-table-column label="状态" width="80" align="center">
<el-tag v-if="isContractInList(scope.row.orderId)" type="success" size="small">已添加</el-tag> <template slot-scope="scope">
<el-tag v-else type="info" size="small">添加</el-tag> <el-tag v-if="isContractInList(scope.row.orderId)" type="success" size="small">添加</el-tag>
</template> <el-tag v-else type="info" size="small">未添加</el-tag>
</el-table-column> </template>
<el-table-column label="操作" width="80" align="center"> </el-table-column>
<template slot-scope="scope"> <el-table-column label="操作" width="80" align="center">
<el-button v-if="!isContractInList(scope.row.orderId)" type="primary" size="mini" <template slot-scope="scope">
@click="addContract(scope.row)" plain> <el-button v-if="!isContractInList(scope.row.orderId)" type="primary" size="mini"
添加 @click="addContract(scope.row)" plain>
</el-button> 添加
<el-button v-else type="text" size="small" @click="removeContract(scope.row.orderId)" </el-button>
style="color: #f56c6c;"> <el-button v-else type="text" size="small" @click="removeContract(scope.row.orderId)"
移除 style="color: #f56c6c;">
</el-button> 移除
</template> </el-button>
</el-table-column> </template>
</el-table> </el-table-column>
</el-table>
<div v-if="allContracts.length > 0" class="table-footer"> <div class="pagination-wrapper">
{{ allContracts.length }} 条记录 <el-pagination background layout="total, prev, pager, next, jumper" :total="total"
</div> :page-size="pageSize" :current-page.sync="pageNum" @current-change="handlePageChange" />
</div>
</template>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@@ -135,6 +140,9 @@ export default {
allContracts: [], allContracts: [],
allLoading: false, allLoading: false,
activeTab: 'configured', activeTab: 'configured',
pageNum: 1,
pageSize: 20,
total: 0,
} }
}, },
mounted() { mounted() {
@@ -190,14 +198,12 @@ export default {
this.allLoading = true; this.allLoading = true;
try { try {
const res = await listOrder({ const res = await listOrder({
pageNum: 1, pageNum: this.pageNum,
pageSize: 10000, pageSize: this.pageSize,
keyword: this.searchKeyword || undefined, keyword: this.searchKeyword || undefined,
}); });
const existingContracts = this.contractList; this.total = res.total || 0;
this.allContracts = [...(res.rows || []), ...existingContracts].filter((item, index, self) => this.allContracts = res.rows || [];
index === self.findIndex(t => t.orderId === item.orderId)
);
} catch (error) { } catch (error) {
console.error('Failed to load all contracts:', error); console.error('Failed to load all contracts:', error);
this.allContracts = []; this.allContracts = [];
@@ -207,6 +213,12 @@ export default {
}, },
handleSearch() { handleSearch() {
this.pageNum = 1;
this.loadAllContracts();
},
handlePageChange(page) {
this.pageNum = page;
this.loadAllContracts(); this.loadAllContracts();
}, },
@@ -338,4 +350,10 @@ export default {
font-size: 13px; font-size: 13px;
color: #909399; color: #909399;
} }
.pagination-wrapper {
display: flex;
justify-content: flex-end;
padding: 12px 0;
}
</style> </style>