refactor(crm): 统一搜索字段名并优化搜索功能

- 将多个页面的搜索字段统一命名为"keyword"以提高一致性
- 优化搜索按钮布局和交互,添加明确的搜索按钮
- 调整字段标签和占位文本使其更准确
- 修复合同列表导出功能中的HTML内容处理逻辑
This commit is contained in:
砂糖
2026-04-07 11:47:41 +08:00
parent dc92939262
commit 505f821df0
4 changed files with 48 additions and 38 deletions

View File

@@ -4,8 +4,8 @@
<div class="filter-section" style="padding: 10px; border-bottom: 1px solid #e4e7ed;"> <div class="filter-section" style="padding: 10px; border-bottom: 1px solid #e4e7ed;">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">
<div style="display: flex; align-items: center; gap: 4px;"> <div style="display: flex; align-items: center; gap: 4px;">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable @keyup.enter.native="handleQuery" <el-input v-model="queryParams.keyword" placeholder="请输入关键字" clearable
style="width: 200px;" /> @keyup.enter.native="handleQuery" />
<el-button icon="el-icon-sort" size="mini" @click="toggleMoreFilter" <el-button icon="el-icon-sort" size="mini" @click="toggleMoreFilter"
:type="showMoreFilter ? 'primary' : 'default'"> :type="showMoreFilter ? 'primary' : 'default'">
<!-- {{ showMoreFilter ? '收起' : '更多' }} --> <!-- {{ showMoreFilter ? '收起' : '更多' }} -->
@@ -19,6 +19,10 @@
<div v-show="showMoreFilter" class="more-filter" <div v-show="showMoreFilter" class="more-filter"
style="margin-top: 10px; padding-top: 10px; border-top: 1px dashed #e4e7ed;"> style="margin-top: 10px; padding-top: 10px; border-top: 1px dashed #e4e7ed;">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="80px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="80px">
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="合同编号" prop="contractNo"> <el-form-item label="合同编号" prop="contractNo">
<el-input v-model="queryParams.contractNo" placeholder="请输入合同编号" clearable <el-input v-model="queryParams.contractNo" placeholder="请输入合同编号" clearable
@keyup.enter.native="handleQuery" /> @keyup.enter.native="handleQuery" />
@@ -518,18 +522,18 @@ export default {
if (row.contractContent) { if (row.contractContent) {
// 优化HTML处理保留p标签作为换行符将多个p标签单元格合并 // 优化HTML处理保留p标签作为换行符将多个p标签单元格合并
let htmlContent = row.contractContent; let htmlContent = row.contractContent;
// 提取所有p标签内容 // 提取所有p标签内容
const pTagRegex = /<p[^>]*>([\s\S]*?)<\/p>/g; const pTagRegex = /<p[^>]*>([\s\S]*?)<\/p>/g;
let match; let match;
const pContents = []; const pContents = [];
while ((match = pTagRegex.exec(htmlContent)) !== null) { while ((match = pTagRegex.exec(htmlContent)) !== null) {
let content = match[1]; let content = match[1];
// 移除其他HTML标签 // 移除其他HTML标签
content = content.replace(/<[^>]*>/g, ''); content = content.replace(/<[^>]*>/g, '');
// 处理HTML实体 // 处理HTML实体
content = content.replace(/&nbsp;/g, ' '); content = content.replace(/&nbsp;/g, ' ');
content = content.replace(/&lt;/g, '<'); content = content.replace(/&lt;/g, '<');
@@ -537,10 +541,10 @@ export default {
content = content.replace(/&amp;/g, '&'); content = content.replace(/&amp;/g, '&');
content = content.replace(/&quot;/g, '"'); content = content.replace(/&quot;/g, '"');
content = content.replace(/&#39;/g, "'"); content = content.replace(/&#39;/g, "'");
// 清理空格和换行 // 清理空格和换行
content = content.trim(); content = content.trim();
// 如果不是以大写汉字数字开头,添加一个中文字符的缩进 // 如果不是以大写汉字数字开头,添加一个中文字符的缩进
if (content) { if (content) {
// 检查是否以大写汉字数字开头(一、二、三、四、五、六、七、八、九、十) // 检查是否以大写汉字数字开头(一、二、三、四、五、六、七、八、九、十)
@@ -551,12 +555,12 @@ export default {
pContents.push(content); pContents.push(content);
} }
} }
// 如果没有提取到p标签内容尝试提取所有文本内容 // 如果没有提取到p标签内容尝试提取所有文本内容
if (pContents.length === 0) { if (pContents.length === 0) {
let textContent = htmlContent.replace(/<[^>]*>/g, ''); let textContent = htmlContent.replace(/<[^>]*>/g, '');
textContent = textContent.replace(/&nbsp;/g, ' ').trim(); textContent = textContent.replace(/&nbsp;/g, ' ').trim();
// 如果不是以大写汉字数字开头,添加一个中文字符的缩进 // 如果不是以大写汉字数字开头,添加一个中文字符的缩进
if (textContent) { if (textContent) {
// 检查是否以大写汉字数字开头(一、二、三、四、五、六、七、八、九、十) // 检查是否以大写汉字数字开头(一、二、三、四、五、六、七、八、九、十)
@@ -567,28 +571,28 @@ export default {
pContents.push(textContent); pContents.push(textContent);
} }
} }
// 直接合并单元格并设置内容,避免合并已合并的单元格 // 直接合并单元格并设置内容,避免合并已合并的单元格
if (pContents.length > 0) { if (pContents.length > 0) {
// 计算需要的行数 // 计算需要的行数
const contentLines = pContents.reduce((total, content) => { const contentLines = pContents.reduce((total, content) => {
return total + (content.match(/\n/g) || []).length + 1; return total + (content.match(/\n/g) || []).length + 1;
}, 0); }, 0);
// 合并单元格 // 合并单元格
const endRow = currentRow + Math.ceil(contentLines / 2); // 估算需要的行数 const endRow = currentRow + Math.ceil(contentLines / 2); // 估算需要的行数
worksheet.mergeCells(`A${currentRow}:H${endRow}`); worksheet.mergeCells(`A${currentRow}:H${endRow}`);
// 设置合并后单元格的内容和样式 // 设置合并后单元格的内容和样式
const mergedContent = pContents.join('\n'); const mergedContent = pContents.join('\n');
worksheet.getCell(`A${currentRow}`).value = mergedContent; worksheet.getCell(`A${currentRow}`).value = mergedContent;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'top', wrapText: true }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'top', wrapText: true };
// 调整合并后单元格的行高 // 调整合并后单元格的行高
const lineCount = (mergedContent.match(/\n/g) || []).length + 1; const lineCount = (mergedContent.match(/\n/g) || []).length + 1;
const height = Math.max(60, lineCount * 15); const height = Math.max(60, lineCount * 15);
worksheet.getRow(currentRow).height = height; worksheet.getRow(currentRow).height = height;
// 调整currentRow // 调整currentRow
currentRow = endRow + 1; currentRow = endRow + 1;
} }
@@ -602,62 +606,62 @@ export default {
if (currentRow > 0) { if (currentRow > 0) {
// 空行 // 空行
currentRow++; currentRow++;
// 供方(甲方)信息 // 供方(甲方)信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `供方(甲方):${row.supplier || '嘉祥科伦普重工有限公司'}`; worksheet.getCell(`A${currentRow}`).value = `供方(甲方):${row.supplier || '嘉祥科伦普重工有限公司'}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `需方(乙方):${row.customer || ''}`; worksheet.getCell(`E${currentRow}`).value = `需方(乙方):${row.customer || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
currentRow++; currentRow++;
// 地址信息 // 地址信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `地址:${row.supplierAddress || ''}`; worksheet.getCell(`A${currentRow}`).value = `地址:${row.supplierAddress || ''}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `地址:${row.customerAddress || ''}`; worksheet.getCell(`E${currentRow}`).value = `地址:${row.customerAddress || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
currentRow++; currentRow++;
// 电话信息 // 电话信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `电话:${row.supplierPhone || ''}`; worksheet.getCell(`A${currentRow}`).value = `电话:${row.supplierPhone || ''}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `电话:${row.customerPhone || ''}`; worksheet.getCell(`E${currentRow}`).value = `电话:${row.customerPhone || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
currentRow++; currentRow++;
// 开户行信息 // 开户行信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `开户行:${row.supplierBank || ''}`; worksheet.getCell(`A${currentRow}`).value = `开户行:${row.supplierBank || ''}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `开户行:${row.customerBank || ''}`; worksheet.getCell(`E${currentRow}`).value = `开户行:${row.customerBank || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
currentRow++; currentRow++;
// 账号信息 // 账号信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `账号:${row.supplierAccount || ''}`; worksheet.getCell(`A${currentRow}`).value = `账号:${row.supplierAccount || ''}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `账号:${row.customerAccount || ''}`; worksheet.getCell(`E${currentRow}`).value = `账号:${row.customerAccount || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
currentRow++; currentRow++;
// 税号信息 // 税号信息
worksheet.mergeCells(`A${currentRow}:D${currentRow}`); worksheet.mergeCells(`A${currentRow}:D${currentRow}`);
worksheet.getCell(`A${currentRow}`).value = `税号:${row.supplierTaxNo || ''}`; worksheet.getCell(`A${currentRow}`).value = `税号:${row.supplierTaxNo || ''}`;
worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`A${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };
worksheet.mergeCells(`E${currentRow}:H${currentRow}`); worksheet.mergeCells(`E${currentRow}:H${currentRow}`);
worksheet.getCell(`E${currentRow}`).value = `税号:${row.customerTaxNo || ''}`; worksheet.getCell(`E${currentRow}`).value = `税号:${row.customerTaxNo || ''}`;
worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' }; worksheet.getCell(`E${currentRow}`).alignment = { horizontal: 'left', vertical: 'middle' };

View File

@@ -6,14 +6,17 @@
<div style="font-weight: 900;">客户列表</div> <div style="font-weight: 900;">客户列表</div>
<!-- 搜索区域 --> <!-- 搜索区域 -->
<div style="display: flex; align-items: center; gap: 5px; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px; margin-top: 10px;">
<el-input style="flex: 1;" prefix-icon="el-icon-search" placeholder="输入客户编码搜索" <el-input style="flex: 1;" prefix-icon="el-icon-search" placeholder="输入关键字搜索"
v-model="queryParams.customerCode" @change="getCustomerList" clearable></el-input> v-model="queryParams.keyword" @change="getCustomerList" clearable></el-input>
<el-button icon="el-icon-search" @click="toggleQuery"></el-button> <el-button icon="el-icon-sort" @click="toggleQuery"></el-button>
<el-button type="primary" icon="el-icon-search" style="margin-left: 0;" size="mini" @click="getCustomerList"></el-button>
<el-button type="primary" icon="el-icon-plus" style="margin-left: 0;" @click="handleAdd"></el-button> <el-button type="primary" icon="el-icon-plus" style="margin-left: 0;" @click="handleAdd"></el-button>
</div> </div>
<!-- 高级查询区域 --> <!-- 高级查询区域 -->
<div v-show="showQuery" <div v-show="showQuery"
style="display: flex; align-items: center; gap: 5px; margin-top: 10px; flex-wrap: wrap;"> style="display: flex; align-items: center; gap: 5px; margin-top: 10px; flex-wrap: wrap;">
<el-input style="width: 180px" placeholder="客户编码"
v-model="queryParams.customerCode" @change="getCustomerList" clearable></el-input>
<el-select style="width: 100px;" v-model="queryParams.industry" placeholder="客户行业" clearable <el-select style="width: 100px;" v-model="queryParams.industry" placeholder="客户行业" clearable
@change="getCustomerList"> @change="getCustomerList">
<el-option v-for="item in dict.type.customer_industry" :key="item.value" :label="item.label" <el-option v-for="item in dict.type.customer_industry" :key="item.value" :label="item.label"

View File

@@ -5,9 +5,10 @@
<div style="font-weight: 900;">订单列表</div> <div style="font-weight: 900;">订单列表</div>
<div style="display: flex; align-items: center; gap: 5px; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px; margin-top: 10px;">
<!-- 主搜索和添加 --> <!-- 主搜索和添加 -->
<el-input style="flex: 1;" prefix-icon="el-icon-search" placeholder="输入订单编号搜索" <el-input style="flex: 1;" prefix-icon="el-icon-search" placeholder="输入关键字搜索"
v-model="queryParams.orderCode"></el-input> v-model="queryParams.keyword" @change="getList" clearable></el-input>
<el-button icon="el-icon-search" @click="toggleQuery"></el-button> <el-button icon="el-icon-sort" @click="toggleQuery"></el-button>
<el-button type="primary" icon="el-icon-search" style="margin-left: 0;" size="mini" @click="getList"></el-button>
<el-button type="primary" icon="el-icon-plus" style="margin-left: 0;" @click="handleAdd" <el-button type="primary" icon="el-icon-plus" style="margin-left: 0;" @click="handleAdd"
v-hasPermi="['crm:order:add']"></el-button> v-hasPermi="['crm:order:add']"></el-button>
</div> </div>
@@ -15,11 +16,13 @@
style="display: flex; align-items: center; gap: 5px; margin-top: 10px; flex-wrap: wrap;"> style="display: flex; align-items: center; gap: 5px; margin-top: 10px; flex-wrap: wrap;">
<!-- 查询区通过上方的查询按钮控制显示隐藏 --> <!-- 查询区通过上方的查询按钮控制显示隐藏 -->
<!-- 客户行业和客户等级的下拉选 --> <!-- 客户行业和客户等级的下拉选 -->
<el-select style="width: 100px;" v-model="queryParams.salesman" placeholder="销售员" clearable> <el-input style="width: 180px;" placeholder="订单编号"
v-model="queryParams.orderCode" @change="getList" clearable></el-input>
<el-select style="width: 100px;" v-model="queryParams.salesman" placeholder="销售员" clearable @change="getList">
<el-option v-for="item in dict.type.wip_pack_saleman" :key="item.value" :label="item.label" <el-option v-for="item in dict.type.wip_pack_saleman" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
</el-select> </el-select>
<el-select style="width: 100px;" v-model="queryParams.orderStatus" placeholder="订单状态" clearable> <el-select style="width: 100px;" v-model="queryParams.orderStatus" placeholder="订单状态" clearable @change="getList">
<el-option v-for="(value, key) in ORDER_STATUS" :key="value" :label="key" :value="value" /> <el-option v-for="(value, key) in ORDER_STATUS" :key="value" :label="key" :value="value" />
</el-select> </el-select>
</div> </div>
@@ -35,7 +38,7 @@
</div> </div>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getOrderList" /> :limit.sync="queryParams.pageSize" @pagination="getList" />
</el-col> </el-col>
<el-col :span="19"> <el-col :span="19">

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="销售员标签" prop="dictLabel"> <el-form-item label="销售员名称" prop="dictLabel">
<el-input <el-input
v-model="queryParams.dictLabel" v-model="queryParams.dictLabel"
placeholder="请输入销售员标签" placeholder="请输入销售员名称"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />