Files
klp-oa/klp-ui/src/components/KLPService/ContractSelect/index.vue
砂糖 274671f309 feat(wms): 新增钢卷合同号自动填充功能
1. 在钢卷合并、分卷、打钢印、计划拆分、退火计划页面添加合同号自动拉取逻辑
2. 优化合同选择组件,补全不存在于列表的已选合同
3. 移除split.vue中冗余的注释代码
2026-06-21 11:32:02 +08:00

356 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div style="display: flex; align-items: center; margin-bottom: 0px;">
<!-- all模式远程搜索 -->
<el-select v-if="mode == 'all'" v-model="selectedValue" placeholder="请选择合同" style="width: 100%" clearable
filterable remote :remote-method="handleRemoteSearch" :loading="selectLoading">
<el-option v-for="item in contractList" :key="item.orderId" :value="item.orderId"
:label="item.contractCode" />
</el-select>
<!-- today模式本地 -->
<el-select v-else v-model="selectedValue" placeholder="请选择合同" style="width: 100%" clearable filterable>
<el-option v-for="item in contractList" :key="item.orderId" :value="item.orderId"
:label="item.contractCode" />
</el-select>
<!-- 编辑按钮点击打开弹窗 -->
<el-button v-if="mode == 'today'" @click="openSelectDialog" type="primary" size="small"
style="margin-left: 8px; padding: 0 12px;">
<i class="el-icon-setting"></i>
</el-button>
<!-- 刷新时不会移除手动添加的合同 -->
<el-button @click="handleRefresh" type="info" size="small" style="margin-left: 8px; padding: 0 12px;">
<i class="el-icon-refresh"></i>
</el-button>
</div>
<!-- 查询所有的合同和当前localstorage中的合同可以对localstorage中的合同进行新增和删除手动新增的合同带有手动添加的标记 -->
<el-dialog title="可选合同配置" :visible.sync="dialogVisible" width="80%" append-to-body>
<el-tabs v-model="activeTab">
<!-- 已配置合同tab -->
<el-tab-pane label="可选合同" name="configured">
<div v-if="contractList.length === 0" style="text-align: center; padding: 20px;">
暂无已配置合同
</div>
<el-table v-else :data="contractList" style="width: 100%" size="mini" height="600">
<el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="contractName" label="合同名称" width="180" />
<el-table-column prop="customer" label="客户" width="140" />
<el-table-column prop="salesman" label="销售人员" width="100" />
<el-table-column prop="deliveryDate" label="交付日期" width="110">
<template slot-scope="scope">
{{ scope.row.deliveryDate || '-' }}
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
<el-table-column label="添加方式" width="90">
<template slot-scope="scope">
<el-tag v-if="scope.row.isManual" type="success" size="small">手动</el-tag>
<el-tag v-else type="info" size="small">接口</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="70">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="removeContract(scope.row.orderId)" plain>
移除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!-- 所有合同tab -->
<el-tab-pane label="所有合同" name="all">
<div style="margin-bottom: 16px;">
<el-input v-model="searchKeyword" placeholder="搜索合同" @blur="handleSearch"
@keyup.enter.native="handleSearch" @clear="handleSearch" clearable
size="small">
<el-button slot="append" icon="el-icon-search" @click="handleSearch" size="small"></el-button>
</el-input>
</div>
<el-table :data="allContracts" style="width: 100%" size="mini" height="520">
<el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="contractName" label="合同名称" width="180" />
<el-table-column prop="customer" label="客户" width="140" />
<el-table-column prop="salesman" label="销售人员" width="100" />
<el-table-column prop="deliveryDate" label="交付日期" width="110">
<template slot-scope="scope">
{{ scope.row.deliveryDate || '-' }}
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
<el-table-column label="状态" width="80">
<template slot-scope="scope">
<el-tag v-if="isContractInList(scope.row.orderId)" type="success"
size="small">已添加</el-tag>
<el-tag v-else type="info" size="small">未添加</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button v-if="!isContractInList(scope.row.orderId)" type="primary" size="mini"
@click="addContract(scope.row)" plain>
添加
</el-button>
<el-button v-else type="danger" size="mini" @click="removeContract(scope.row.orderId)"
plain>
移除
</el-button>
</template>
</el-table-column>
</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>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</template>
<script>
import { listOrder, listTodayOrder, getOrder } from '@/api/crm/order';
export default {
name: "ContractSelect",
props: {
value: {
type: String,
default: ""
},
mode: {
type: String,
default: "today" // today 或 all
}
},
data() {
return {
contractList: [],
dialogVisible: false,
searchKeyword: '',
allContracts: [],
activeTab: 'configured', // 默认显示已配置合同tab
allPageNum: 1,
allPageSize: 20,
allTotal: 0,
selectLoading: false,
selectTimer: null,
}
},
computed: {
selectedValue: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
if (val) {
localStorage.setItem('lastSelectedContractId', val);
}
}
}
},
watch: {
value(val) {
if (val && !this.contractList.some(item => String(item.orderId) === String(val))) {
getOrder(val).then(res => {
if (res.data) {
this.contractList.unshift(res.data)
}
}).catch(() => {})
}
}
},
mounted() {
if (this.mode == "today") {
this.loadFromLocalStorage();
} else {
this.handleRemoteSearch('');
}
},
methods: {
// 从localStorage中加载合同列表
loadFromLocalStorage() {
try {
const storedContracts = localStorage.getItem('todayContracts');
if (storedContracts) {
this.contractList = JSON.parse(storedContracts);
}
// else {
// 如果localStorage中没有从接口获取
this.loadContractList();
// }
} catch (error) {
console.error('Failed to load contracts from localStorage:', error);
this.loadContractList();
}
},
// 保存合同列表到localStorage
saveToLocalStorage() {
try {
localStorage.setItem('todayContracts', JSON.stringify(this.contractList));
} catch (error) {
console.error('Failed to save contracts to localStorage:', error);
}
},
// 加载合同列表today模式
async loadContractList() {
const res = await listTodayOrder();
// 获取现有手动添加的合同
const existingManualContracts = this.contractList.filter(item => item.isManual);
// 将接口返回的合同标记为非手动添加
const apiContracts = (res.data || []).map(item => ({
...item,
isManual: false
}));
// 合并合同列表,保留手动添加的合同
this.contractList = [...apiContracts, ...existingManualContracts];
// 去重,避免重复合同
this.contractList = this.contractList.filter((item, index, self) =>
index === self.findIndex(t => t.orderId === item.orderId)
);
// 上一次选择的合同放在列表第一位
this.sortLastSelectedToFirst();
// 保存到localStorage
this.saveToLocalStorage();
// 确保已选中的合同在列表中
if (this.value && !this.contractList.some(item => String(item.orderId) === String(this.value))) {
try {
const contract = await getOrder(this.value);
if (contract.data) {
this.contractList.unshift(contract.data);
}
} catch (e) {
console.error('Failed to fetch selected contract:', e);
}
}
},
// 将上一次选择的合同排到列表第一位
sortLastSelectedToFirst() {
const lastId = localStorage.getItem('lastSelectedContractId');
if (!lastId) return;
const index = this.contractList.findIndex(item => String(item.orderId) === String(lastId));
if (index > 0) {
const [item] = this.contractList.splice(index, 1);
this.contractList.unshift(item);
}
},
// 打开选择弹窗
async openSelectDialog() {
this.dialogVisible = true;
// 加载所有合同供选择
await this.loadAllContracts();
},
// 加载所有合同
async loadAllContracts() {
try {
const res = await listOrder({
pageNum: this.allPageNum,
pageSize: this.allPageSize,
keyword: this.searchKeyword || undefined,
});
this.allTotal = res.total || 0;
this.allContracts = res.rows || [];
} catch (error) {
console.error('Failed to load all contracts:', error);
this.allContracts = [];
}
},
// 搜索合同
handleSearch() {
this.allPageNum = 1;
this.loadAllContracts();
},
handleAllPageChange(page) {
this.allPageNum = page;
this.loadAllContracts();
},
// 检查合同是否在列表中
isContractInList(orderId) {
return this.contractList.some(item => item.orderId === orderId);
},
// 添加合同
addContract(contract) {
if (!this.isContractInList(contract.orderId)) {
this.contractList.push({
...contract,
isManual: true // 标记为手动添加
});
this.saveToLocalStorage();
}
},
// 移除合同
removeContract(orderId) {
this.contractList = this.contractList.filter(item => item.orderId !== orderId);
this.saveToLocalStorage();
},
// 刷新合同列表
handleRefresh() {
if (this.mode == 'all') {
this.handleRemoteSearch('');
} else {
this.loadContractList();
}
},
// all模式远程搜索
handleRemoteSearch(query) {
if (this.selectTimer) {
clearTimeout(this.selectTimer);
}
if (!query) {
this.selectTimer = null;
this.doRemoteSearch('');
return;
}
this.selectLoading = true;
this.selectTimer = setTimeout(() => {
this.doRemoteSearch(query);
}, 300);
},
async doRemoteSearch(query) {
try {
const res = await listOrder({
pageNum: 1,
pageSize: 100,
keyword: query || undefined,
});
this.contractList = res.rows || [];
// 初始加载时,确保已选中的合同在列表中
if (!query && this.value && !this.contractList.some(item => String(item.orderId) === String(this.value))) {
try {
const contract = await getOrder(this.value);
if (contract.data) {
this.contractList.unshift(contract.data);
}
} catch (e) {
console.error('Failed to fetch selected contract:', e);
}
}
} catch (error) {
console.error('Failed to search contracts:', error);
} finally {
this.selectLoading = false;
}
},
}
}
</script>