Merge remote-tracking branch 'websoft/master'
# Conflicts: # src/views/business/contract-manage-change.vue
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
## 合同管理独立表单页下拉框定位修复
|
||||||
|
- `src/views/business/contract-manage.vue` 全部 12 处 `el-select` 加 `:teleported="false"` + `:fit-input-width="true"`:下拉保持在输入框正下方、宽度与输入框一致(原 teleport 到 body 导致下拉漂移且按内容撑宽)。
|
||||||
|
- 若后续新增独立表单页出现同样问题,照加这两个属性即可。
|
||||||
|
- 追加:teleported=false 后 popper 因下方空间不足自动上翻,再给 12 处 el-select 加 `placement="bottom-start"` + `:popper-options="{ modifiers: [{ name: 'flip', enabled: false }] }"` 强制始终在下方展示。
|
||||||
|
|
||||||
|
## 调度弹窗司机输入框宽度不一致修复
|
||||||
|
- 现象:「编辑调度信息(精简录入)」弹窗中,司机(el-autocomplete)输入框比同行 250px 的其他输入框宽。
|
||||||
|
- 根因:`business-crud-page.vue` 约 13434 行的「表单控件统一 250px」规则漏了 `.el-autocomplete`(autocomplete 根节点是包装层,内部才是 .el-input)。
|
||||||
|
- 修复:在该规则选择器列表追加 `> .el-autocomplete` 和 `> .el-autocomplete > .el-input`,与运单独立表单页(13658 行 business-crud-page--form-page 先例)一致。
|
||||||
|
- 经验:凡「控件统一 250px」类规则,选择器必须包含 `.el-autocomplete` 包装层。
|
||||||
|
|
||||||
|
## 调度弹窗收发货地址行溢出修复
|
||||||
|
- 现象:「编辑调度信息」弹窗收发货信息行,地址输入框过宽,右侧「联系方式」列被挤出弹窗。
|
||||||
|
- 根因:`__dispatch-shipping-form __route-address-row` 网格地址列为 `minmax(280px, 1fr)`,各列最小宽度合计 1030px,弹窗不够宽时 grid 不换行直接溢出。
|
||||||
|
- 修复:地址列改 `minmax(0, 1fr)`(宽屏仍 1fr 拉伸,窄窗自动收窄,总最小宽降到 750px)。
|
||||||
|
- 备注:基础规则 `__route-address-row`(13750 行,运单独立表单页等在用,7 列含 40px 按钮列)仍是 minmax(280px,1fr),同样窄窗有溢出风险,暂未动(用户未反馈该页问题)。
|
||||||
|
|
||||||
|
## el-select 选中值 / 占位符颜色区分(全局)
|
||||||
|
- 需求:已选值 #606266,未选值保持 placeholder 灰 #909399。
|
||||||
|
- 根因:Element Plus 的选中值文本与占位符**共用同一节点** `<div class="el-select__selected-item el-select__placeholder [is-transparent]">`,仅靠 `.el-select__selected-item` 无法区分,导致未选态也被染成选中色。
|
||||||
|
- 区分标志:只有「未选值」或「已展开但无搜索输入」时才带 `.is-transparent`。
|
||||||
|
- 修复(`src/styles/element-ui.scss`):选中规则改为 `.el-select__wrapper:not(.is-disabled) .el-select__selected-item:not(.is-transparent)`;多选 tag 文字另加 `.el-select__tags-text` 规则(tag 自身 color 优先级更高,父级规则盖不到)。
|
||||||
|
- 经验:以后写任何「区分 el-select 有值/无值」的 CSS,一律用 `:not(.is-transparent)`。
|
||||||
@@ -55,13 +55,13 @@
|
|||||||
<el-button type="primary" @click.prevent="handleLogin" class="login-submit"
|
<el-button type="primary" @click.prevent="handleLogin" class="login-submit"
|
||||||
>{{ $t('login.submit') }}
|
>{{ $t('login.submit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<!-- <el-button-->
|
||||||
v-if="this.registerMode"
|
<!-- v-if="this.registerMode"-->
|
||||||
type="danger"
|
<!-- type="danger"-->
|
||||||
@click.prevent="handleRegister"
|
<!-- @click.prevent="handleRegister"-->
|
||||||
class="register-submit"
|
<!-- class="register-submit"-->
|
||||||
>{{ $t('login.register') }}
|
<!-- >{{ $t('login.register') }}-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<behavior-captcha ref="behaviorCaptcha" @success="handleBehaviorSuccess"></behavior-captcha>
|
<behavior-captcha ref="behaviorCaptcha" @success="handleBehaviorSuccess"></behavior-captcha>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|||||||
@@ -1117,11 +1117,18 @@
|
|||||||
color: #909399 !important;
|
color: #909399 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已选中:选中文本用主文字色 #333333,与占位符明显区分。
|
// 已选中:选中文本用主文字色 #606266,与占位符明显区分。
|
||||||
// 注意:Element Plus 选中值节点同时带 el-select__selected-item 与 el-select__placeholder 两个类,
|
// 关键:Element Plus 的「选中值文本」与「占位符」共用同一个节点,
|
||||||
// 而上面占位符规则用了 !important,故此处必须同样 !important 才能胜出(本规则 specificity 更高)。
|
// <div class="el-select__selected-item el-select__placeholder [is-transparent]">
|
||||||
|
// 只有未选值(或已展开但无搜索输入)时才会带 .is-transparent。
|
||||||
|
// 因此这里必须排除 .is-transparent,否则未选值的占位符也会被染成选中色,与占位符灰无法区分。
|
||||||
// 仅作用于非禁用态,禁用态保留 Element Plus 的禁用灰(--el-select-disabled-color),避免被覆盖。
|
// 仅作用于非禁用态,禁用态保留 Element Plus 的禁用灰(--el-select-disabled-color),避免被覆盖。
|
||||||
.el-select__wrapper:not(.is-disabled) .el-select__selected-item {
|
.el-select__wrapper:not(.is-disabled) .el-select__selected-item:not(.is-transparent) {
|
||||||
|
color: #606266 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多选:选中项渲染为 el-tag,文字色由 tag 自身控制,上面规则覆盖不到,单独处理。
|
||||||
|
.el-select__wrapper:not(.is-disabled) .el-select__tags-text {
|
||||||
color: #606266 !important;
|
color: #606266 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -770,6 +770,6 @@ export default {
|
|||||||
margin-bottom: 12px !important;
|
margin-bottom: 12px !important;
|
||||||
}
|
}
|
||||||
.el-form-item{
|
.el-form-item{
|
||||||
margin-bottom: 8px !important;
|
margin-bottom: 9px !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13573,7 +13573,9 @@ export default {
|
|||||||
:deep(.el-form-item__content > .el-select),
|
:deep(.el-form-item__content > .el-select),
|
||||||
:deep(.el-form-item__content > .el-cascader),
|
:deep(.el-form-item__content > .el-cascader),
|
||||||
:deep(.el-form-item__content > .el-input-number),
|
:deep(.el-form-item__content > .el-input-number),
|
||||||
:deep(.el-form-item__content > .el-date-editor) {
|
:deep(.el-form-item__content > .el-date-editor),
|
||||||
|
:deep(.el-form-item__content > .el-autocomplete),
|
||||||
|
:deep(.el-form-item__content > .el-autocomplete > .el-input) {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@@ -13644,7 +13646,7 @@ export default {
|
|||||||
&__shipping-title,
|
&__shipping-title,
|
||||||
&__goods-title,
|
&__goods-title,
|
||||||
&__task-title {
|
&__task-title {
|
||||||
min-width: 100%;
|
//min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__shipping-route-action {
|
&__shipping-route-action {
|
||||||
@@ -13891,7 +13893,7 @@ export default {
|
|||||||
);
|
);
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width:98%;
|
||||||
|
|
||||||
:deep(.el-input),
|
:deep(.el-input),
|
||||||
:deep(.el-select),
|
:deep(.el-select),
|
||||||
@@ -13945,7 +13947,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__dispatch-shipping-form &__route-address-row {
|
&__dispatch-shipping-form &__route-address-row {
|
||||||
grid-template-columns: 260px minmax(280px, 1fr) 58px minmax(160px, 220px) 72px minmax(
|
// 地址列用 minmax(0, 1fr):窗口较窄时地址输入框自动收窄,
|
||||||
|
// 避免各列最小宽度合计超出弹窗宽度,把右侧联系方式挤出弹窗。
|
||||||
|
grid-template-columns: 260px minmax(0, 1fr) 58px minmax(160px, 220px) 72px minmax(
|
||||||
160px,
|
160px,
|
||||||
220px
|
220px
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -528,7 +528,6 @@
|
|||||||
@size-change="size => handleDetailSizeChange('contact', size)"
|
@size-change="size => handleDetailSizeChange('contact', size)"
|
||||||
@current-change="page => handleDetailCurrentChange('contact', page)"
|
@current-change="page => handleDetailCurrentChange('contact', page)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="收款信息" name="receiptAccounts">
|
<el-tab-pane label="收款信息" name="receiptAccounts">
|
||||||
<div class="tab-table-toolbar" v-if="!readonly">
|
<div class="tab-table-toolbar" v-if="!readonly">
|
||||||
@@ -607,7 +606,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<div class="section-actions">
|
<div class="section-actions">
|
||||||
<el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button>
|
<el-button type="primary" plain icon="el-icon-download" @click="downloadAttachments"
|
||||||
|
>批量下载</el-button
|
||||||
|
>
|
||||||
<vehicle-attachment-upload
|
<vehicle-attachment-upload
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
v-model="ocrQualificationUploadFiles"
|
v-model="ocrQualificationUploadFiles"
|
||||||
@@ -817,9 +818,7 @@
|
|||||||
|
|
||||||
<div class="archive-form__footer">
|
<div class="archive-form__footer">
|
||||||
<!-- 次要:独立页返回 / 只读关闭 / 弹窗取消 -->
|
<!-- 次要:独立页返回 / 只读关闭 / 弹窗取消 -->
|
||||||
<el-button @click="closeArchive">{{
|
<el-button @click="closeArchive">{{ readonly ? '关闭' : '取消' }}</el-button>
|
||||||
readonly ? '关闭' : '取消'
|
|
||||||
}}</el-button>
|
|
||||||
<el-button type="primary" plain v-if="!readonly" @click="saveArchive">保存</el-button>
|
<el-button type="primary" plain v-if="!readonly" @click="saveArchive">保存</el-button>
|
||||||
<el-button type="primary" v-if="!readonly" @click="saveAndSubmitArchive">提交</el-button>
|
<el-button type="primary" v-if="!readonly" @click="saveAndSubmitArchive">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1145,7 +1144,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="最大资金使用额度">
|
<el-form-item label="最大资金使用额度">
|
||||||
<el-input :model-value="formatScoreValue(currentScore.maxCreditLimit)" disabled >
|
<el-input :model-value="formatScoreValue(currentScore.maxCreditLimit)" disabled>
|
||||||
<template #suffix>万元</template>
|
<template #suffix>万元</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -1245,7 +1244,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- <div class="score-standard-cell__label">请选择:</div>-->
|
<!-- <div class="score-standard-cell__label">请选择:</div>-->
|
||||||
<el-select
|
<el-select
|
||||||
v-model="detail.selectedOption"
|
v-model="detail.selectedOption"
|
||||||
filterable
|
filterable
|
||||||
@@ -1419,12 +1418,7 @@ import { normalizeSearchRangeParams } from '@/utils/search-range';
|
|||||||
import { ArrowRight, Location } from '@element-plus/icons-vue';
|
import { ArrowRight, Location } from '@element-plus/icons-vue';
|
||||||
import { ElImageViewer, ElLoading } from 'element-plus';
|
import { ElImageViewer, ElLoading } from 'element-plus';
|
||||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||||
import {
|
import { fallbackPlugin, imagePlugin, officePlugin, textPlugin } from '@open-file-viewer/core';
|
||||||
fallbackPlugin,
|
|
||||||
imagePlugin,
|
|
||||||
officePlugin,
|
|
||||||
textPlugin,
|
|
||||||
} from '@open-file-viewer/core';
|
|
||||||
import '@open-file-viewer/core/style.css';
|
import '@open-file-viewer/core/style.css';
|
||||||
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
@@ -1482,7 +1476,9 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const validateUnifiedCreditCode = (rule, value, callback) => {
|
const validateUnifiedCreditCode = (rule, value, callback) => {
|
||||||
const code = String(value || '').trim().toUpperCase();
|
const code = String(value || '')
|
||||||
|
.trim()
|
||||||
|
.toUpperCase();
|
||||||
const charset = '0123456789ABCDEFGHJKLMNPQRTUWXY';
|
const charset = '0123456789ABCDEFGHJKLMNPQRTUWXY';
|
||||||
const weights = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
|
const weights = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
|
||||||
if (!code) {
|
if (!code) {
|
||||||
@@ -1865,10 +1861,7 @@ export default {
|
|||||||
this.initScoreQuantificationOptions();
|
this.initScoreQuantificationOptions();
|
||||||
if (this.isArchivePage) {
|
if (this.isArchivePage) {
|
||||||
const readonly = this.$route.query.view === '1' || this.$route.query.view === 'true';
|
const readonly = this.$route.query.view === '1' || this.$route.query.view === 'true';
|
||||||
this.openArchive(
|
this.openArchive(this.$route.query.id ? { id: this.$route.query.id } : null, readonly);
|
||||||
this.$route.query.id ? { id: this.$route.query.id } : null,
|
|
||||||
readonly
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -2596,15 +2589,10 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
initBusinessDictionaries() {
|
initBusinessDictionaries() {
|
||||||
this.loadDictOptions(
|
this.loadDictOptions('nature_of_client', 'customerNatureOptions', [], options => {
|
||||||
'nature_of_client',
|
|
||||||
'customerNatureOptions',
|
|
||||||
[],
|
|
||||||
options => {
|
|
||||||
const customerNatureColumn = this.findColumn(this.option.column, 'customerNature');
|
const customerNatureColumn = this.findColumn(this.option.column, 'customerNature');
|
||||||
customerNatureColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
customerNatureColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
||||||
}
|
});
|
||||||
);
|
|
||||||
this.loadDictOptions('customer_type', 'customerTypeOptions', ['客户', '承运商'], options => {
|
this.loadDictOptions('customer_type', 'customerTypeOptions', ['客户', '承运商'], options => {
|
||||||
const customerTypeColumn = this.findColumn(this.option.column, 'customerType');
|
const customerTypeColumn = this.findColumn(this.option.column, 'customerType');
|
||||||
customerTypeColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
customerTypeColumn.dicData = [{ label: '全部', value: '' }, ...options];
|
||||||
@@ -3605,7 +3593,11 @@ export default {
|
|||||||
: this.splitValue(customerType);
|
: this.splitValue(customerType);
|
||||||
const requiredTypes = ['营业执照', '法人身份证'];
|
const requiredTypes = ['营业执照', '法人身份证'];
|
||||||
const includesCarrier = customerTypes.some(item =>
|
const includesCarrier = customerTypes.some(item =>
|
||||||
['承运商', 'carrier'].includes(String(item || '').trim().toLowerCase())
|
['承运商', 'carrier'].includes(
|
||||||
|
String(item || '')
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
if (includesCarrier) requiredTypes.push('运输许可证');
|
if (includesCarrier) requiredTypes.push('运输许可证');
|
||||||
return requiredTypes;
|
return requiredTypes;
|
||||||
@@ -3656,10 +3648,7 @@ export default {
|
|||||||
}
|
}
|
||||||
files.forEach((item, index) => {
|
files.forEach((item, index) => {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
downloadFileByUrl(
|
downloadFileByUrl(item.url, item.originalName || item.name || `客商材料${index + 1}`);
|
||||||
item.url,
|
|
||||||
item.originalName || item.name || `客商材料${index + 1}`
|
|
||||||
);
|
|
||||||
}, index * 300);
|
}, index * 300);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -4155,7 +4144,9 @@ export default {
|
|||||||
const changeLabel = item.changeType === 'decrease' ? '每减少' : '每增加';
|
const changeLabel = item.changeType === 'decrease' ? '每减少' : '每增加';
|
||||||
const scoreLabel = item.scoreType === 'subtract' ? '减' : '加';
|
const scoreLabel = item.scoreType === 'subtract' ? '减' : '加';
|
||||||
const generatedLabel = isScoreOption
|
const generatedLabel = isScoreOption
|
||||||
? `${changeLabel}${item.changeValue || ''}${item.changeUnit || ''}${scoreLabel}${item.score || ''}分`
|
? `${changeLabel}${item.changeValue || ''}${item.changeUnit || ''}${scoreLabel}${
|
||||||
|
item.score || ''
|
||||||
|
}分`
|
||||||
: '';
|
: '';
|
||||||
const label = item.label || item.optionName || item.value || generatedLabel;
|
const label = item.label || item.optionName || item.value || generatedLabel;
|
||||||
return {
|
return {
|
||||||
@@ -4359,7 +4350,8 @@ export default {
|
|||||||
calculateScore(score) {
|
calculateScore(score) {
|
||||||
const details = score.details || [];
|
const details = score.details || [];
|
||||||
details.forEach(detail => {
|
details.forEach(detail => {
|
||||||
if (!this.isScoreTypeDetail(detail) || String(detail.scoreInput ?? '').trim() === '') return;
|
if (!this.isScoreTypeDetail(detail) || String(detail.scoreInput ?? '').trim() === '')
|
||||||
|
return;
|
||||||
const calculatedScore = this.getScoreTypeCalculatedScore(detail);
|
const calculatedScore = this.getScoreTypeCalculatedScore(detail);
|
||||||
if (calculatedScore !== null) detail.selfScore = calculatedScore;
|
if (calculatedScore !== null) detail.selfScore = calculatedScore;
|
||||||
});
|
});
|
||||||
@@ -5316,7 +5308,7 @@ export default {
|
|||||||
max-height: 72vh;
|
max-height: 72vh;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.el-col{
|
.el-col {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
|
|||||||
Reference in New Issue
Block a user