feat(project-apply): 优化表单提示与客户承运商表格交互

- 将“项目资金使用额度”和“项目应收账款额度”提示从placeholder移至label右侧问号tooltip
- 调整提示文案为“实际业务回款周期内付款”和“回款期内最大应收账款额”
- 客户信息和承运商信息表格中“客户”“承运商”列变为可点击链接,点击跳转查看客商档案
- 删除客户和承运商表格中的“联系人”“联系方式”列
- 表单输入框placeholder统一调整为“请选择”或“请输入”
- 新增openCustomerArchive方法支持查看客商档案,缺失ID时提示警告
- 项目申请页面用户查询条件由account改为phone,相关表格列同步调整
- 部门管理权限调整,操作列只显示“添加”按钮,删除查看、编辑、删除按钮相关代码及样式
- Vite配置中更新本地开发端口为2889并修改API代理目标地址为局域网地址http://172.16.203.228:8000
- 修正项目申请页面部分样式,使label问号图标与文字baseline对齐和换行显示
This commit is contained in:
2026-08-28 16:44:06 +08:00
parent b6fed6892a
commit 16af750030
3 changed files with 108 additions and 42 deletions
+22
View File
@@ -58,3 +58,25 @@
- 根因:`<el-form-item label="业务部门">` 误加 `class="project-apply-form__item--full"`(该类对应样式 `:deep(.project-apply-form__item--full) { grid-column: 1 / -1; ... }` 是横跨整行的:本意只用于"项目由来说明"等多行文本字段)。
- 修复:移除该 class,业务部门恢复为半宽(一行两列网格的常规项),仅"项目由来说明"等需要全宽铺开的字段仍保留 full。同时把样式块上方注释由「占满整行的表单项(业务部门 / 项目由来说明)」改为「占满整行的表单项(如项目由来说明等多行文本字段)」,避免再误读。
## project-apply 字段 label 问号悬浮提示
- 文件:`src/views/business/project-apply.vue`
- 需求:把"项目资金使用额度"/"项目应收账款额度"两字段的提示从 placeholder 移到 label 右侧问号 tooltip。
- 实现:
-`el-form-item``class="project-apply-form__tip-label"`,用 `#label` slot 包裹文字 + `<el-tooltip content=... placement="top"><el-icon class="project-apply-form__label-tip"><QuestionFilled /></el-icon></el-tooltip>`
- placeholder 改回"请输入"。
- 提示文案按截图(去掉"额度"二字):资金使用额度→`实际业务回款周期内付款`;应收账款额度→`回款期内最大应收账款额`
- scoped 样式:`__tip-label :deep(.el-form-item__label){vertical-align:top}` 保持默认 inline 布局,让文字按全局 `white-space: normal` 换行显示;`__label-tip{margin-left:4px;color:#a8abb2;cursor:help;vertical-align:-0.125em}` 问号与文字 baseline 对齐。
- 图标 `QuestionFilled` 已在 main.js 全局注册(@element-plus/icons-vue),模板可直接用。
- 可复用模式:其它表单字段如需 label 旁问号提示,套用此 slot 结构即可。
## project-apply 详情页客户/承运商表格改造
- 文件:`src/views/business/project-apply.vue`
- 需求:
1. 客户信息、承运商信息两个表格的「客户」「承运商」列改为可点击链接,跳转打开对应客商档案。
2. 删除两个表格的「联系人」「联系方式」列。
- 实现:
- 模板:两列的 `el-table-column``#default` slot 渲染 `<el-link type="primary" :underline="false" @click="openCustomerArchive(row)">`,显示 `row.customer` / `row.carrier`
- 删除原 `prop="contact"``prop="phone"` 两列。
- methods 新增 `openCustomerArchive(row)`:取 `getCustomerRowId(row)``row.id || row.customerId || row.carrierId`),无 ID 时 `this.$message.warning`;有 ID 则 `this.$router.push({ path: '/vehicle/customer-archive/form', query: { id: String(id), name: '查看客商档案', view: '1' } })`
- 注意:客商档案查看态由 `customer-archive.vue``this.$route.query.view === '1'` 识别,与现有查看逻辑一致。
+75 -21
View File
@@ -220,7 +220,7 @@
<el-form-item label="客户名称" prop="customerNames">
<el-select
v-model="selectedCustomerId"
placeholder="支持多选,选择后下方列表展示"
placeholder="请选择"
multiple
filterable
clearable
@@ -241,7 +241,7 @@
<el-form-item label="下游承运商" prop="carrierNames">
<el-select
v-model="selectedCarrierIds"
placeholder="支持多选选择后下方列表展示"
placeholder="请选择"
multiple
filterable
clearable
@@ -259,18 +259,30 @@
/>
</el-select>
</el-form-item>
<el-form-item label="项目资金使用额度万元" prop="fundLimit">
<el-form-item prop="fundLimit" class="project-apply-form__tip-label">
<template #label>
<span>项目资金使用额度(万元)</span>
<el-tooltip content="实际业务回款周期内付款" placement="top">
<el-icon class="project-apply-form__label-tip"><QuestionFilled /></el-icon>
</el-tooltip>
</template>
<el-input
v-model="form.fundLimit"
placeholder="实际业务回款周期内付款额度"
placeholder="请输入"
@input="value => handleNumberInput('fundLimit', value)"
@blur="formatAmountField('fundLimit')"
/>
</el-form-item>
<el-form-item label="项目应收账款额度万元" prop="receivableLimit">
<el-form-item prop="receivableLimit" class="project-apply-form__tip-label">
<template #label>
<span>项目应收账款额度(万元)</span>
<el-tooltip content="回款期内最大应收账款额" placement="top">
<el-icon class="project-apply-form__label-tip"><QuestionFilled /></el-icon>
</el-tooltip>
</template>
<el-input
v-model="form.receivableLimit"
placeholder="回款期内最大应收账款额度"
placeholder="请输入"
@input="value => handleNumberInput('receivableLimit', value)"
@blur="formatAmountField('receivableLimit')"
/>
@@ -292,7 +304,7 @@
</el-input>
</el-form-item>
<el-form-item label="货物类型" prop="cargoType">
<el-select v-model="form.cargoType" placeholder="请选择货物类型" filterable clearable>
<el-select v-model="form.cargoType" placeholder="请选择" filterable clearable>
<el-option
v-for="item in cargoTypeOptions"
:key="item.value"
@@ -304,7 +316,7 @@
<el-form-item label="预估货物数量" prop="cargoQuantity">
<el-input
v-model="form.cargoQuantity"
placeholder="请输入数字"
placeholder="请输入"
@input="value => handleIntegerInput('cargoQuantity', value)"
/>
</el-form-item>
@@ -399,7 +411,17 @@
<div class="dialog-section-title project-apply-form__table-title">客户信息</div>
<el-table :data="customerRows" border class="project-apply-form__table">
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="customer" label="客户" min-width="160" align="center" />
<el-table-column prop="customer" label="客户" min-width="160" align="center">
<template #default="{ row }">
<el-link
type="primary"
:underline="false"
@click="openCustomerArchive(row)"
>
{{ row.customer }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="credit" label="客户信用额度" min-width="150" align="center">
<template #default="{ row }">
{{ normalizeReadonlyAmount(row.credit) }}
@@ -414,14 +436,22 @@
align="center"
show-overflow-tooltip
/>
<el-table-column prop="contact" label="联系人" min-width="120" align="center" />
<el-table-column prop="phone" label="联系方式" min-width="140" align="center" />
</el-table>
<div class="dialog-section-title">承运商信息</div>
<el-table :data="carrierRows" border class="project-apply-form__table">
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="carrier" label="承运商" min-width="180" align="center" />
<el-table-column prop="carrier" label="承运商" min-width="180" align="center">
<template #default="{ row }">
<el-link
type="primary"
:underline="false"
@click="openCustomerArchive(row)"
>
{{ row.carrier }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="companyNature" label="企业性质" min-width="140" align="center" />
<el-table-column prop="legalPerson" label="法定代表人" min-width="140" align="center" />
<el-table-column
@@ -431,8 +461,6 @@
align="center"
show-overflow-tooltip
/>
<el-table-column prop="contact" label="联系人" min-width="120" align="center" />
<el-table-column prop="phone" label="联系方式" min-width="140" align="center" />
</el-table>
<div class="dialog-section-title">项目情况说明</div>
@@ -718,8 +746,8 @@
@keyup.enter="loadUsers"
/>
<el-input
v-model="userQuery.account"
placeholder="登录账"
v-model="userQuery.phone"
placeholder="手机"
clearable
@keyup.enter="loadUsers"
/>
@@ -728,8 +756,8 @@
</div>
<el-table :data="userData" border v-loading="userLoading" @row-dblclick="selectUser">
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column prop="account" label="登录账号" min-width="140" align="center" />
<el-table-column prop="realName" label="用户姓名" min-width="140" align="center" />
<el-table-column prop="phone" label="手机号" min-width="140" align="center" />
<el-table-column prop="deptName" label="所属部门" min-width="180" align="center" />
<el-table-column label="操作" width="100" align="center">
<template #default="{ row }">
@@ -796,7 +824,7 @@ const emptyForm = () => ({
businessDeptName: '',
undertakeDeptId: '',
undertakeDeptName: '',
projectSource: '商务洽谈',
projectSource: '',
sourceRemark: '',
changeType: '',
changeNo: '',
@@ -1071,7 +1099,7 @@ export default {
userData: [],
userQuery: {
realName: '',
account: '',
phone: '',
},
userPage: {
currentPage: 1,
@@ -1729,6 +1757,17 @@ export default {
getCustomerRowId(row = {}) {
return row.id || row.customerId || row.carrierId || '';
},
openCustomerArchive(row = {}) {
const id = this.getCustomerRowId(row);
if (!id) {
this.$message.warning('客商档案 ID 为空无法打开');
return;
}
this.$router.push({
path: '/vehicle/customer-archive/form',
query: { id: String(id), name: '查看客商档案', view: '1' },
});
},
getCustomerRowLabel(row = {}, type) {
return (
row[type === 'carrier' ? 'carrier' : 'customer'] ||
@@ -2117,7 +2156,7 @@ export default {
});
},
resetUserQuery() {
this.userQuery = { realName: '', account: '' };
this.userQuery = { realName: '', phone: '' };
this.userPage.currentPage = 1;
this.loadUsers();
},
@@ -2205,6 +2244,21 @@ export default {
cursor: pointer;
}
&__tip-label {
// 保持 .el-form-item__label 默认 inline 布局,让文字按全局 white-space: normal 换行显示
:deep(.el-form-item__label) {
vertical-align: top;
}
}
&__label-tip {
margin-left: 4px;
color: #a8abb2;
cursor: help;
font-size: 14px;
vertical-align: -0.125em;
}
&__table-title {
display: flex;
align-items: center;
@@ -2365,7 +2419,7 @@ export default {
}
&--change {
justify-content: flex-start;
justify-content: flex-end;
padding-left: 24px;
}
}
+11 -21
View File
@@ -32,15 +32,6 @@
</el-button>
</template>
<template #menu="scope">
<el-link type="primary" @click.stop="handleView(scope.row, scope.index)" v-if="permissionList.viewBtn"
>查看</el-link
>
<el-link type="primary" @click.stop="handleEdit(scope.row, scope.index)" v-if="permissionList.editBtn"
>编辑</el-link
>
<el-link type="danger" @click.stop="handleDel(scope.row, scope.index)" v-if="permissionList.delBtn"
>删除</el-link
>
<el-link
type="primary"
@click.stop="handleAdd(scope.row, scope.index)"
@@ -186,9 +177,7 @@ export default {
border: true,
index: true,
selection: true,
viewBtn: false,
editBtn: false,
delBtn: false,
viewBtn: true,
menuWidth: 320,
dialogWidth: 800,
dialogClickModal: false,
@@ -530,15 +519,6 @@ export default {
isRootDept(row) {
return row && (row.parentId === 0 || String(row.parentId) === '0');
},
handleView(row, index) {
this.$refs.crud.rowView(row, index);
},
handleEdit(row, index) {
this.$refs.crud.rowEdit(row, index);
},
handleDel(row, index) {
this.$refs.crud.rowDel(row, index);
},
handleAdd(row) {
this.parentId = row.id;
this.loadParentDeptCode(row.id);
@@ -774,4 +754,14 @@ export default {
display: inline-flex;
}
}
/* 操作列删除按钮使用危险色 */
:deep(.avue-crud__menu > .el-button.is-text.avue-crud__delBtn) {
color: var(--el-color-danger);
}
:deep(.avue-crud__menu > .el-button.is-text.avue-crud__delBtn:hover),
:deep(.avue-crud__menu > .el-button.is-text.avue-crud__delBtn:focus) {
color: var(--el-color-danger-light-3);
}
</style>