Merge remote-tracking branch 'websoft/master'

# Conflicts:
#	src/views/business/components/business-crud-page.vue
#	src/views/business/contract-manage.vue
#	src/views/settlement/components/pre-settlement-editor.vue
#	src/views/settlement/formal-settlement.vue
This commit is contained in:
2026-08-22 21:12:26 +08:00
31 changed files with 1098 additions and 616 deletions
+1 -1
View File
@@ -1012,7 +1012,7 @@ export default {
}
.el-input:first-child {
flex: 0 0 34%;
flex: 0 0 42.5%;
}
.el-button {
@@ -20,16 +20,28 @@
<template v-for="(route, index) in routes" :key="route.segmentNo">
<div class="route-overview__node">
<span :class="['route-badge', index === 0 ? 'start' : 'middle']">{{ index === 0 ? '起' : '经' }}</span>
<strong>{{ route.departureName || '-' }}</strong>
<small>{{ route.departureAddress || '-' }}</small>
<small>{{ contactText(route.departureContact, route.departurePhone) }}</small>
<el-tooltip :content="route.departureName || '-'" placement="top" :show-after="120">
<strong>{{ route.departureName || '-' }}</strong>
</el-tooltip>
<el-tooltip :content="route.departureAddress || '-'" placement="top" :show-after="120">
<small>{{ route.departureAddress || '-' }}</small>
</el-tooltip>
<el-tooltip :content="contactText(route.departureContact, route.departurePhone)" placement="top" :show-after="120">
<small>{{ contactText(route.departureContact, route.departurePhone) }}</small>
</el-tooltip>
</div>
<div class="route-overview__line"></div>
<div v-if="index === routes.length - 1" class="route-overview__node">
<span class="route-badge end"></span>
<strong>{{ route.arrivalName || '-' }}</strong>
<small>{{ route.arrivalAddress || '-' }}</small>
<small>{{ contactText(route.arrivalContact, route.arrivalPhone) }}</small>
<el-tooltip :content="route.arrivalName || '-'" placement="top" :show-after="120">
<strong>{{ route.arrivalName || '-' }}</strong>
</el-tooltip>
<el-tooltip :content="route.arrivalAddress || '-'" placement="top" :show-after="120">
<small>{{ route.arrivalAddress || '-' }}</small>
</el-tooltip>
<el-tooltip :content="contactText(route.arrivalContact, route.arrivalPhone)" placement="top" :show-after="120">
<small>{{ contactText(route.arrivalContact, route.arrivalPhone) }}</small>
</el-tooltip>
</div>
</template>
</div>
@@ -677,10 +689,10 @@ export default {
.overview-content { display: grid; grid-template-columns: minmax(400px, .9fr) minmax(620px, 1.6fr); gap: 28px; padding: 8px 24px 20px; }
.overview-meta { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 24px; margin: 0; dt { margin-bottom: 6px; color: #909399; font-size: 13px; } dd { margin: 0; color: #409eff; font-size: 14px; word-break: break-all; } }
.overview-meta dd.overview-meta__plain-value { color: #303133; }
.route-overview { display: flex; align-items: flex-start; justify-content: flex-end; padding-top: 8px; overflow-x: auto; }
.route-overview__node { display: grid; flex: 0 0 130px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
.route-overview { display: flex; align-items: flex-start; justify-content: flex-start; padding: 8px 24px 0; overflow-x: auto; }
.route-overview__node { display: grid; flex: 0 0 auto; min-width: 130px; max-width: 200px; justify-items: center; gap: 6px; text-align: center; padding: 0 4px; strong { font-size: 16px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } small { color: #606266; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } }
.route-badge { display: inline-flex; width: 32px; height: 32px; align-items: center; justify-content: center; border-radius: 4px; background: #67c23a; color: #fff; font-weight: 600; &.start { background: #409eff; } &.end { background: #e6a23c; } }
.route-overview__line { flex: 1 0 56px; min-width: 56px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; }
.route-overview__line { flex: 0 1 56px; min-width: 24px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; }
.segment-header { min-height: 46px; padding: 0 20px; border-bottom: 1px solid #eff1f7; font-weight: 600; em { color: #409eff; font-style: normal; } }
.segment-content { padding: 16px 24px; }
.dispatch-form { :deep(.el-form-item) { margin-bottom: 16px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } }
@@ -705,4 +717,7 @@ export default {
.table-actions { display: flex; flex-wrap: wrap; gap: 8px; }
@media screen and (max-width: 1200px) { .overview-content { grid-template-columns: 1fr; } .route-overview { justify-content: flex-start; } }
@media screen and (max-width: 992px) { .dispatch-bottom { left: 0; width: 100%; } }
.route-overview {
margin-top: -30px !important;
}
</style>
@@ -1752,7 +1752,7 @@ export default {
font-size: 16px;
}
.el-form-item {
margin-bottom: 16px;
margin-bottom: 14px;
}
}
.goods-heading {
+14 -14
View File
@@ -5,20 +5,20 @@
<div class="dialog-section-title">基本信息</div>
<el-row :gutter="28">
<el-col :span="24"><el-form-item label="变更类型"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="一式"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /><span></span></div></el-form-item></el-col>
<el-col :span="8"><el-form-item label="回款账期"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /><span class="unit"></span></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="一式"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /><span></span></div></el-form-item></el-col>
<el-col :span="6"><el-form-item label="回款账期"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /><span class="unit"></span></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" maxlength="2000" show-word-limit /></el-form-item></el-col>
</el-row>
</section>
+358 -373
View File
@@ -8,9 +8,6 @@
v-model="form"
ref="crud"
:permission="permissionList"
:before-open="beforeOpen"
@row-save="rowSave"
@row-update="rowUpdate"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@@ -25,7 +22,7 @@
type="primary"
icon="el-icon-plus"
v-if="hasPermission('process_config_add')"
@click="$refs.crud.rowAdd()"
@click="openConfig()"
>新建过程配置
</el-button>
<el-button
@@ -46,27 +43,6 @@
</el-button>
</template>
<template #menu-form-before="{ disabled }">
<template v-if="!dialogReadonly">
<el-button
plain
:loading="disabled"
:disabled="disabled"
@click="handleProcessConfigSave('draft')"
>
保存草稿
</el-button>
<el-button
type="primary"
:loading="disabled"
:disabled="disabled"
@click="handleProcessConfigSave('enabled')"
>
保存并启用
</el-button>
</template>
</template>
<template #status="{ row }">
<el-tag :type="statusTagType(row.status)">
{{ row.statusName || displayStatus(row.status) }}
@@ -79,300 +55,18 @@
</span>
</template>
<template #basicInfo-form>
<section-card title="基本信息">
<el-form
:model="form"
label-position="right"
label-width="calc(6em + 24px)"
>
<el-row :gutter="18">
<el-col :span="6">
<el-form-item label="配置名称" required>
<el-input
v-model="form.configName"
:disabled="dialogReadonly"
maxlength="100"
placeholder="请输入"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="项目" required>
<el-select
v-model="selectedProjectId"
clearable
filterable
remote
:remote-method="loadProjectOptions"
:loading="projectLoading"
:disabled="dialogReadonly"
placeholder="请选择"
style="width: 100%"
@change="handleProjectChange"
>
<el-option
v-for="item in projectOptions"
:key="item.id"
:label="formatProjectLabel(item)"
:value="String(item.id)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运输完成时限">
<div class="process-config-page__finish-days">
<span>默认</span>
<el-input
v-model="form.defaultFinishDays"
:disabled="dialogReadonly"
maxlength="3"
placeholder="请输入"
@input="handleFinishDaysInput"
/>
<span>天后完成运输</span>
</div>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
:rows="4"
:disabled="dialogReadonly"
maxlength="500"
show-word-limit
placeholder="请输入"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
</template>
<template #nodeConfigJson-form>
<div class="process-config-page__custom-form">
<section-card title="现行过程节点">
<div class="process-config-page__timeline" v-if="enabledNodes.length">
<div class="process-config-page__timeline-line"></div>
<div
v-for="node in enabledNodes"
:key="node.key"
class="process-config-page__timeline-item"
>
<span class="process-config-page__timeline-dot"></span>
<div class="process-config-page__timeline-name">{{ node.name }}</div>
<div class="process-config-page__timeline-desc">
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
</div>
</div>
</div>
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
</section-card>
<section-card title="节点设置">
<el-table
class="process-config-page__node-table"
border
:data="nodeRows"
:span-method="nodeSpanMethod"
>
<el-table-column label="节点设置" width="136">
<template #default="{ row, $index }">
<div class="process-config-page__node-cell">
<el-checkbox
v-model="row.enabled"
:disabled="dialogReadonly"
@change="syncNodeFields"
/>
<span class="process-config-page__node-name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作要求" min-width="660">
<template #default="{ row }">
<div class="process-config-page__requirements">
<template v-if="row.key === 'accept'">
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">是否确认</span>
<el-radio-group
v-model="row.confirmMode"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio label="yes"></el-radio>
<el-radio label="no_confirm_accept">无需确认接单</el-radio>
</el-radio-group>
</div>
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">确认接单人</span>
<el-checkbox
v-model="row.confirmDriver"
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
@change="syncNodeFields"
>司机</el-checkbox
>
</div>
</template>
<template v-else-if="row.key === 'return'">
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">是否确认</span>
<el-radio-group
v-model="row.confirmMode"
:disabled="dialogReadonly || !row.enabled"
@change="handleReturnConfirmChange(row)"
>
<el-radio label="yes"></el-radio>
<el-radio label="no_confirm_complete">无需确认完成</el-radio>
</el-radio-group>
</div>
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">确认完成</span>
<el-checkbox
v-model="row.confirmInternal"
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
@change="syncNodeFields"
>内部人员</el-checkbox
>
</div>
</template>
<template v-else>
<div class="process-config-page__require-grid">
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">是否打卡</span>
<el-radio-group
v-model="row.punch"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-page__require-line" v-if="row.supportCargo">
<span class="process-config-page__require-label">上传货量</span>
<el-radio-group
v-model="row.uploadCargo"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div
class="process-config-page__require-line process-config-page__require-line--wide"
v-if="row.key === 'transit'"
>
<span class="process-config-page__require-label">打卡频次</span>
<el-input
v-model="row.frequencyDays"
:disabled="dialogReadonly || !row.enabled || !row.punch"
maxlength="3"
@input="value => handleFrequencyInput(row, value)"
/>
<span>天打卡1次</span>
</div>
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">打卡定位</span>
<el-radio-group
v-model="row.location"
:disabled="dialogReadonly || !row.enabled || !row.punch"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-page__require-line" v-if="row.supportCargo">
<span class="process-config-page__require-label">上传货量类型</span>
<el-checkbox-group
v-model="row.cargoTypes"
:disabled="dialogReadonly || !row.enabled || !row.uploadCargo"
@change="syncNodeFields"
>
<el-checkbox label="重量">重量</el-checkbox>
<el-checkbox label="体积">体积</el-checkbox>
<el-checkbox label="数量">数量</el-checkbox>
</el-checkbox-group>
</div>
<div
class="process-config-page__require-line process-config-page__require-line--wide"
v-if="row.key === 'transit'"
>
<span class="process-config-page__require-label">打卡时段</span>
<el-time-picker
v-model="row.timeStart"
:disabled="dialogReadonly || !row.enabled || !row.punch"
format="HH:mm"
value-format="HH:mm"
placeholder="开始"
/>
<span>-</span>
<el-time-picker
v-model="row.timeEnd"
:disabled="dialogReadonly || !row.enabled || !row.punch"
format="HH:mm"
value-format="HH:mm"
placeholder="结束"
/>
</div>
</div>
</template>
</div>
</template>
</el-table-column>
<el-table-column label="附件要求" min-width="320">
<template #default="{ row }">
<div class="process-config-page__attachments" v-if="row.supportVoucher">
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">上传凭证</span>
<el-radio-group
v-model="row.uploadVoucher"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-page__require-line">
<span class="process-config-page__require-label">凭证类型</span>
<el-checkbox-group
v-model="row.voucherTypes"
:disabled="dialogReadonly || !row.enabled || !row.uploadVoucher"
@change="syncNodeFields"
>
<el-checkbox v-for="item in row.voucherOptions" :key="item" :label="item">
{{ item }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</template>
</el-table-column>
</el-table>
</section-card>
</div>
</template>
<template #menu="{ row, index }">
<el-link
type="primary"
v-if="hasPermission('process_config_view')"
@click="$refs.crud.rowView(row, index)"
@click="openConfig(row, true)"
>
查看
</el-link>
<el-link
type="primary"
v-if="canEdit(row)"
@click="$refs.crud.rowEdit(row, index)"
@click="openConfig(row)"
>
编辑
</el-link>
@@ -407,6 +101,311 @@
</template>
</avue-crud>
<el-dialog
:title="dialogReadonly ? '查看过程配置' : form.id ? '编辑过程配置' : '新建过程配置'"
append-to-body
v-model="configBox"
width="96%"
top="4vh"
class="process-config-dialog"
:close-on-click-modal="false"
@closed="handleDialogClosed"
>
<div class="process-config-form">
<section-card title="基本信息">
<el-form
:model="form"
label-position="right"
label-width="calc(6em + 24px)"
:disabled="dialogReadonly"
>
<el-row :gutter="18">
<el-col :span="6">
<el-form-item label="配置名称" required>
<el-input
v-model="form.configName"
maxlength="100"
placeholder="请输入"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="项目" required>
<el-select
v-model="selectedProjectId"
clearable
filterable
remote
:remote-method="loadProjectOptions"
:loading="projectLoading"
placeholder="请选择"
style="width: 100%"
@change="handleProjectChange"
>
<el-option
v-for="item in projectOptions"
:key="item.id"
:label="formatProjectLabel(item)"
:value="String(item.id)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运输完成时限">
<div class="process-config-form__finish-days">
<span>默认</span>
<el-input
v-model="form.defaultFinishDays"
maxlength="3"
placeholder="请输入"
@input="handleFinishDaysInput"
/>
<span>天后完成运输</span>
</div>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
:rows="4"
maxlength="500"
show-word-limit
placeholder="请输入"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<section-card title="现行过程节点">
<div class="process-config-form__timeline" v-if="enabledNodes.length">
<div class="process-config-form__timeline-line"></div>
<div
v-for="node in enabledNodes"
:key="node.key"
class="process-config-form__timeline-item"
>
<span class="process-config-form__timeline-dot"></span>
<div class="process-config-form__timeline-name">{{ node.name }}</div>
<div class="process-config-form__timeline-desc">
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
</div>
</div>
</div>
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
</section-card>
<section-card title="节点设置">
<el-table
class="process-config-form__node-table"
border
:data="nodeRows"
:span-method="nodeSpanMethod"
>
<el-table-column label="节点设置" width="136">
<template #default="{ row }">
<div class="process-config-form__node-cell">
<el-checkbox
v-model="row.enabled"
:disabled="dialogReadonly"
@change="syncNodeFields"
/>
<span class="process-config-form__node-name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作要求" min-width="660">
<template #default="{ row }">
<div class="process-config-form__requirements">
<template v-if="row.key === 'accept'">
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">是否确认</span>
<el-radio-group
v-model="row.confirmMode"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio label="yes"></el-radio>
<el-radio label="no_confirm_accept">无需确认接单</el-radio>
</el-radio-group>
</div>
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">确认接单人</span>
<el-checkbox
v-model="row.confirmDriver"
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
@change="syncNodeFields"
>司机</el-checkbox
>
</div>
</template>
<template v-else-if="row.key === 'return'">
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">是否确认</span>
<el-radio-group
v-model="row.confirmMode"
:disabled="dialogReadonly || !row.enabled"
@change="handleReturnConfirmChange(row)"
>
<el-radio label="yes"></el-radio>
<el-radio label="no_confirm_complete">无需确认完成</el-radio>
</el-radio-group>
</div>
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">确认完成</span>
<el-checkbox
v-model="row.confirmInternal"
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
@change="syncNodeFields"
>内部人员</el-checkbox
>
</div>
</template>
<template v-else>
<div class="process-config-form__require-grid">
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">是否打卡</span>
<el-radio-group
v-model="row.punch"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-form__require-line" v-if="row.supportCargo">
<span class="process-config-form__require-label">上传货量</span>
<el-radio-group
v-model="row.uploadCargo"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div
class="process-config-form__require-line process-config-form__require-line--wide"
v-if="row.key === 'transit'"
>
<span class="process-config-form__require-label">打卡频次</span>
<el-input
v-model="row.frequencyDays"
:disabled="dialogReadonly || !row.enabled || !row.punch"
maxlength="3"
@input="value => handleFrequencyInput(row, value)"
/>
<span>天打卡1次</span>
</div>
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">打卡定位</span>
<el-radio-group
v-model="row.location"
:disabled="dialogReadonly || !row.enabled || !row.punch"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-form__require-line" v-if="row.supportCargo">
<span class="process-config-form__require-label">上传货量类型</span>
<el-checkbox-group
v-model="row.cargoTypes"
:disabled="dialogReadonly || !row.enabled || !row.uploadCargo"
@change="syncNodeFields"
>
<el-checkbox label="重量">重量</el-checkbox>
<el-checkbox label="体积">体积</el-checkbox>
<el-checkbox label="数量">数量</el-checkbox>
</el-checkbox-group>
</div>
<div
class="process-config-form__require-line process-config-form__require-line--wide"
v-if="row.key === 'transit'"
>
<span class="process-config-form__require-label">打卡时段</span>
<el-time-picker
v-model="row.timeStart"
:disabled="dialogReadonly || !row.enabled || !row.punch"
format="HH:mm"
value-format="HH:mm"
placeholder="开始"
/>
<span>-</span>
<el-time-picker
v-model="row.timeEnd"
:disabled="dialogReadonly || !row.enabled || !row.punch"
format="HH:mm"
value-format="HH:mm"
placeholder="结束"
/>
</div>
</div>
</template>
</div>
</template>
</el-table-column>
<el-table-column label="附件要求" min-width="320">
<template #default="{ row }">
<div class="process-config-form__attachments" v-if="row.supportVoucher">
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">上传凭证</span>
<el-radio-group
v-model="row.uploadVoucher"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">凭证类型</span>
<el-checkbox-group
v-model="row.voucherTypes"
:disabled="dialogReadonly || !row.enabled || !row.uploadVoucher"
@change="syncNodeFields"
>
<el-checkbox v-for="item in row.voucherOptions" :key="item" :label="item">
{{ item }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</template>
</el-table-column>
</el-table>
</section-card>
</div>
<template #footer>
<el-button @click="configBox = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
<el-button
plain
:loading="submitting"
v-if="!dialogReadonly"
@click="submitConfig('draft')"
>
保存草稿
</el-button>
<el-button
type="primary"
:loading="submitting"
v-if="!dialogReadonly"
@click="submitConfig('enabled')"
>
保存并启用
</el-button>
</template>
</el-dialog>
<empty-pagination
:page="page"
@size-change="sizeChange"
@@ -507,6 +506,8 @@ export default {
loading: true,
data: [],
dialogReadonly: false,
configBox: false,
submitting: false,
projectOptions: [],
projectLoading: false,
selectedProjectId: '',
@@ -518,7 +519,6 @@ export default {
total: 0,
},
selectionList: [],
submitStatus: 1,
};
},
computed: {
@@ -880,11 +880,6 @@ export default {
}
return true;
},
stopSubmitLoading(loading) {
if (typeof loading === 'function') {
loading();
}
},
needsDuplicateVoucherConfirm() {
const signNode = this.nodeRows.find(item => item.key === 'sign');
const returnNode = this.nodeRows.find(item => item.key === 'return');
@@ -914,14 +909,45 @@ export default {
}
);
},
submitRow(row, done, loading, status = this.submitStatus) {
this.submitStatus = 1;
this.syncNodeFields();
const submitRow = this.normalizeRow({ ...row, status });
if (!this.validateRow(submitRow)) {
this.stopSubmitLoading(loading);
openConfig(row, readonly = false) {
this.dialogReadonly = readonly;
if (!row || !row.id) {
this.form = {
configName: '',
projectIds: '',
projectNames: '',
defaultFinishDays: '',
remark: '',
status: 0,
};
this.selectedProjectId = '';
this.resetNodeRows();
this.configBox = true;
return;
}
api.getDetail(row.id).then(res => {
this.form = res.data.data || {};
this.selectedProjectId = this.form.projectIds ? String(this.form.projectIds) : '';
this.ensureSelectedProjectOption();
this.parseNodeConfig(this.form);
this.configBox = true;
});
},
handleDialogClosed() {
this.submitting = false;
this.dialogReadonly = false;
},
submitConfig(mode) {
if (this.submitting) return;
this.syncNodeFields();
const submitRow = this.normalizeRow({
...this.form,
status: mode === 'draft' ? 2 : 1,
});
if (!this.validateRow(submitRow)) {
return;
}
this.submitting = true;
this.checkEnabledProjectBeforeSubmit(submitRow)
.then(exists => {
if (exists) {
@@ -932,9 +958,9 @@ export default {
.then(() => this.confirmDuplicateVoucher())
.then(() => api.submit(submitRow))
.then(() => {
this.configBox = false;
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
})
.catch(error => {
if (
@@ -944,21 +970,11 @@ export default {
) {
window.console.log(error);
}
this.stopSubmitLoading(loading);
})
.finally(() => {
this.submitting = false;
});
},
rowSave(row, done, loading) {
this.submitRow(row, done, loading);
},
rowUpdate(row, index, done, loading) {
this.submitRow(row, done, loading);
},
handleProcessConfigSave(mode) {
this.submitStatus = mode === 'draft' ? 2 : 1;
if (this.$refs.crud && typeof this.$refs.crud.rowSave === 'function') {
this.$refs.crud.rowSave();
}
},
rowDel(row) {
this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定',
@@ -1001,35 +1017,6 @@ export default {
}
this.selectionClear();
},
beforeOpen(done, type) {
this.dialogReadonly = type === 'view';
this.submitStatus = 1;
if (type === 'add') {
this.form = {
configName: '',
projectIds: '',
projectNames: '',
defaultFinishDays: '',
remark: '',
status: 0,
};
this.selectedProjectId = '';
this.resetNodeRows();
done();
return;
}
if (['edit', 'view'].includes(type)) {
api.getDetail(this.form.id).then(res => {
this.form = res.data.data || {};
this.selectedProjectId = this.form.projectIds ? String(this.form.projectIds) : '';
this.ensureSelectedProjectOption();
this.parseNodeConfig(this.form);
done();
});
return;
}
done();
},
searchReset() {
this.query = {};
this.applyDefaultDeptSearch();
@@ -1164,6 +1151,13 @@ export default {
word-break: break-all;
}
:deep(.avue-crud__header) {
margin-top: 12px;
background: transparent;
}
}
.process-config-form {
&__finish-days {
display: flex;
align-items: center;
@@ -1174,10 +1168,6 @@ export default {
}
}
&__custom-form {
width: 100%;
}
&__timeline {
position: relative;
display: flex;
@@ -1285,11 +1275,6 @@ export default {
text-align: right;
}
:deep(.avue-crud__header) {
margin-top: 12px;
background: transparent;
}
:deep(.el-table) {
--el-table-border-color: #eff1f7;
}
+9 -2
View File
@@ -106,7 +106,7 @@
:model="form"
:rules="formRules"
label-position="right"
label-width="auto"
label-width="150"
class="project-apply-form"
:disabled="dialogReadonly"
>
@@ -1964,7 +1964,7 @@ export default {
&__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 24px;
row-gap: 0;
margin-bottom: 12px;
@@ -1972,6 +1972,13 @@ export default {
border-radius: 0 0 6px 6px;
padding: 14px 16px 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
// label 固定宽度:可容纳 6 个汉字,超出自动换行(覆盖全局 min-width:160px 与 auto 行内宽度)
:deep(.el-form-item__label) {
width: 108px !important;
min-width: 0 !important;
white-space: normal;
}
}
&__picker-icon {
+2 -2
View File
@@ -364,7 +364,7 @@
:before-close="beforeProgressDialogClose"
@opened="loadProgress"
>
<section class="voucher-manage-page__progress-search">
<section-card class="voucher-manage-page__progress-search">
<el-form :model="progressQuery" label-position="right" label-width="160px"
><div class="voucher-manage-page__search-grid">
<el-form-item label="凭证批次号"
@@ -391,7 +391,7 @@
</div>
</div></el-form
>
</section>
</section-card>
<el-table :data="progressRows" border class="voucher-manage-page__table"
><el-table-column type="selection" width="52" /><el-table-column
type="index"