This commit is contained in:
zlwu committed 2026-07-22 10:43:55 +08:00
1 parent f9c9577843
commit b8b0446542
22 files changed
+5225 -4282

No files matched your search

@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "label": "QcWorkOrderProtocolPaymentPanel.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_datetime_display", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L226", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L227", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_work_order", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L228", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_money_format", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L229", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L230", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L235", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_presets", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L236", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "label": "QcWorkOrderProtocolPaymentPanel.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_datetime_display", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L236", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L237", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_work_order", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L238", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_money_format", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L239", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L240", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L245", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkorderprotocolpaymentpanel_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_presets", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderProtocolPaymentPanel.vue", "source_location": "L246", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkordertasksublist_vue", "label": "QcWorkOrderTaskSubList.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L1"}, {"id": "qc_work_order_qcworkordertasksublist_iscurrentuserassignee", "label": "isCurrentUserAssignee()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L636"}, {"id": "qc_work_order_qcworkordertasksublist_nextmaterialrowkey", "label": "nextMaterialRowKey()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L666"}, {"id": "qc_work_order_qcworkordertasksublist_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L928"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkordertasksublist_vue", "target": "qc_work_order_qcworkordertasksublist_iscurrentuserassignee", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L636", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkordertasksublist_vue", "target": "qc_work_order_qcworkordertasksublist_nextmaterialrowkey", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L666", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkordertasksublist_vue", "target": "qc_work_order_qcworkordertasksublist_if", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L928", "weight": 1.0}], "raw_calls": [{"caller_nid": "qc_work_order_qcworkordertasksublist_iscurrentuserassignee", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L637"}, {"caller_nid": "qc_work_order_qcworkordertasksublist_iscurrentuserassignee", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L637"}, {"caller_nid": "qc_work_order_qcworkordertasksublist_iscurrentuserassignee", "callee": "some", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L639"}, {"caller_nid": "qc_work_order_qcworkordertasksublist_nextmaterialrowkey", "callee": "now", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderTaskSubList.vue", "source_location": "L668"}]}
@@ -8,86 +8,145 @@
}"
>
<template v-if="summary">
<!-- 列表卡片:单行摘要 + 横向排列的多条明细 -->
<!-- 列表卡片:默认折叠为各期状态(单行),展开后为完整摘要 + 明细 -->
<template v-if="compact">
<div class="qc-protocol-payment__compact-summary">
<!-- 折叠:标题 + 各期状态 + 箭头,同一行 -->
<button
v-if="!feeExpanded"
type="button"
class="qc-protocol-payment__toggle qc-protocol-payment__toggle--collapsed"
:aria-expanded="false"
@click="feeExpanded = true"
>
<span v-if="!embedded" class="qc-protocol-payment__title">协议费用</span>
<el-tag v-if="summary.payModeLabel" :type="payModeTagType" size="small">
{{ summary.payModeLabel }}
</el-tag>
<span class="qc-protocol-payment__compact-item">
合同 {{ formatAmount(summary.contractAmount) }}
</span>
<span class="qc-protocol-payment__compact-item">
已收 {{ formatAmount(summary.receivedAmount) }}
</span>
<span class="qc-protocol-payment__compact-item">
待收 {{ formatAmount(summary.pendingAmount) }}
</span>
<template v-if="isLumpSum && primaryDetail">
<span
v-if="primaryDetail.installmentDueDate"
class="qc-protocol-payment__compact-item"
>
应缴 {{ primaryDetail.installmentDueDate }}
</span>
<div class="qc-protocol-payment__collapsed-status">
<template v-if="collapsedStatusRows.length">
<div
v-for="(row, index) in collapsedStatusRows"
:key="row.installmentNo ?? index"
class="qc-protocol-payment__status-chip"
>
<span
v-if="isInstallment && row.installmentLabel"
class="qc-protocol-payment__status-chip-label"
>
{{ row.installmentLabel }}
</span>
<el-tag :type="payStatusTagType(row.payStatus)" size="small">
{{ row.payStatusLabel || payStatusLabel(row.payStatus || '') }}
</el-tag>
</div>
</template>
<el-tag
v-if="hideOverallPayStatus && primaryDetail.payStatus"
:type="payStatusTagType(primaryDetail.payStatus)"
v-else-if="summary.overallPayStatusLabel"
:type="overallStatusTagType"
size="small"
>
{{ primaryDetail.payStatusLabel || payStatusLabel(primaryDetail.payStatus || '') }}
{{ summary.overallPayStatusLabel }}
</el-tag>
</template>
<span v-if="summary.statusHint" class="qc-protocol-payment__compact-hint">
{{ summary.statusHint }}
</span>
<el-tag
v-if="!hideOverallPayStatus && summary.overallPayStatusLabel"
:type="overallStatusTagType"
size="small"
class="qc-protocol-payment__compact-status"
<span v-else class="qc-protocol-payment__empty">暂无缴费状态</span>
</div>
<el-icon class="qc-protocol-payment__toggle-icon" :size="14">
<ArrowDown />
</el-icon>
</button>
<!-- 展开:标题行 + 完整摘要 + 明细 -->
<template v-else>
<button
type="button"
class="qc-protocol-payment__toggle"
:aria-expanded="true"
@click="feeExpanded = false"
>
{{ summary.overallPayStatusLabel }}
</el-tag>
</div>
<div v-if="showCompactDetailChips" class="qc-protocol-payment__compact-details">
<div
v-for="(row, index) in detailRows"
:key="row.installmentNo ?? index"
class="qc-protocol-payment__detail-chip"
:class="{
'qc-protocol-payment__detail-chip--head-only': hideInstallmentDetailAmounts && isInstallment,
'qc-protocol-payment__detail-chip--inline': isLumpSum
}"
>
<div class="qc-protocol-payment__detail-chip-head">
<span v-if="isInstallment && row.installmentLabel" class="qc-protocol-payment__detail-chip-label">
{{ row.installmentLabel }}
</span>
<span v-if="!embedded" class="qc-protocol-payment__title">协议费用</span>
<span v-else class="qc-protocol-payment__toggle-spacer" />
<el-icon class="qc-protocol-payment__toggle-icon" :size="14">
<ArrowUp />
</el-icon>
</button>
<div class="qc-protocol-payment__compact-summary">
<el-tag v-if="summary.payModeLabel" :type="payModeTagType" size="small">
{{ summary.payModeLabel }}
</el-tag>
<span class="qc-protocol-payment__compact-item">
合同 {{ formatAmount(summary.contractAmount) }}
</span>
<span class="qc-protocol-payment__compact-item">
已收 {{ formatAmount(summary.receivedAmount) }}
</span>
<span class="qc-protocol-payment__compact-item">
待收 {{ formatAmount(summary.pendingAmount) }}
</span>
<template v-if="isLumpSum && primaryDetail">
<span
v-if="isInstallment && row.installmentDueDate"
class="qc-protocol-payment__detail-chip-date"
v-if="primaryDetail.installmentDueDate"
class="qc-protocol-payment__compact-item"
>
{{ row.installmentDueDate }}
应缴 {{ primaryDetail.installmentDueDate }}
</span>
<el-tag
:type="payStatusTagType(row.payStatus)"
v-if="hideOverallPayStatus && primaryDetail.payStatus"
:type="payStatusTagType(primaryDetail.payStatus)"
size="small"
class="qc-protocol-payment__detail-chip-tag"
>
{{ row.payStatusLabel || payStatusLabel(row.payStatus || '') }}
{{ primaryDetail.payStatusLabel || payStatusLabel(primaryDetail.payStatus || '') }}
</el-tag>
</div>
<div
v-if="!(hideInstallmentDetailAmounts && isInstallment)"
class="qc-protocol-payment__detail-chip-body"
</template>
<span v-if="summary.statusHint" class="qc-protocol-payment__compact-hint">
{{ summary.statusHint }}
</span>
<el-tag
v-if="!hideOverallPayStatus && summary.overallPayStatusLabel"
:type="overallStatusTagType"
size="small"
class="qc-protocol-payment__compact-status"
>
<span>应缴 {{ formatAmount(row.dueAmount) }}</span>
<span>实收 {{ formatAmount(row.transferAmount) }}</span>
{{ summary.overallPayStatusLabel }}
</el-tag>
</div>
<div v-if="showCompactDetailChips" class="qc-protocol-payment__compact-details">
<div
v-for="(row, index) in detailRows"
:key="row.installmentNo ?? index"
class="qc-protocol-payment__detail-chip"
:class="{
'qc-protocol-payment__detail-chip--head-only':
hideInstallmentDetailAmounts && isInstallment,
'qc-protocol-payment__detail-chip--inline': isLumpSum
}"
>
<div class="qc-protocol-payment__detail-chip-head">
<span
v-if="isInstallment && row.installmentLabel"
class="qc-protocol-payment__detail-chip-label"
>
{{ row.installmentLabel }}
</span>
<span
v-if="isInstallment && row.installmentDueDate"
class="qc-protocol-payment__detail-chip-date"
>
{{ row.installmentDueDate }}
</span>
<el-tag
:type="payStatusTagType(row.payStatus)"
size="small"
class="qc-protocol-payment__detail-chip-tag"
>
{{ row.payStatusLabel || payStatusLabel(row.payStatus || '') }}
</el-tag>
</div>
<div
v-if="!(hideInstallmentDetailAmounts && isInstallment)"
class="qc-protocol-payment__detail-chip-body"
>
<span>应缴 {{ formatAmount(row.dueAmount) }}</span>
<span>实收 {{ formatAmount(row.transferAmount) }}</span>
</div>
</div>
</div>
</div>
</template>
</template>
<!-- 查看弹窗:汇总指标 + 明细表 -->
@@ -173,8 +232,9 @@
</template>
<script setup lang="ts">
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
import { formatDisplayOrDash } from '@/utils/datetime-display'
import { computed } from 'vue'
import { computed, ref } from 'vue'
import type { QcProtocolPaymentSummary } from '@/api/qc-work-order'
import { formatMoneyDisplay } from '@/utils/money-format'
import {
@@ -199,6 +259,9 @@
hideInstallmentDetailAmounts?: boolean
}>()
/** 列表卡片协议费用默认折叠 */
const feeExpanded = ref(false)
const isInstallment = computed(() => isInstallmentPayMode(props.summary?.payMode || ''))
const isLumpSum = computed(() => props.summary?.payMode === 'dj')
@@ -207,6 +270,9 @@
const primaryDetail = computed(() => detailRows.value[0] ?? null)
/** 折叠态:有明细则按期展示状态;无明细则回退整体状态 */
const collapsedStatusRows = computed(() => detailRows.value)
/** 趸交仅 1 条明细时信息已并入摘要行,不再占满整行的明细区 */
const showCompactDetailChips = computed(() => {
if (!detailRows.value.length) return false
@@ -246,6 +312,7 @@
}
.qc-protocol-payment__title {
flex-shrink: 0;
font-size: 13px;
font-weight: 600;
color: #065f46;
@@ -299,12 +366,74 @@
box-sizing: border-box;
}
.qc-protocol-payment__toggle {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
margin: 0;
padding: 0;
border: none;
background: transparent;
cursor: pointer;
text-align: left;
font: inherit;
color: inherit;
&:hover .qc-protocol-payment__title,
&:hover .qc-protocol-payment__toggle-icon {
color: var(--el-color-primary, #10b981);
}
&--collapsed {
flex-wrap: nowrap;
gap: 8px 12px;
min-width: 0;
}
}
.qc-protocol-payment__toggle-spacer {
flex: 1;
}
.qc-protocol-payment__toggle-icon {
margin-left: auto;
flex-shrink: 0;
color: #065f46;
transition: color 0.15s ease;
}
.qc-protocol-payment__collapsed-status {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 8px 14px;
min-width: 0;
flex: 1;
overflow-x: auto;
}
.qc-protocol-payment__status-chip {
display: inline-flex;
flex-shrink: 0;
align-items: center;
gap: 6px;
}
.qc-protocol-payment__status-chip-label {
font-size: 12px;
font-weight: 600;
color: #334155;
white-space: nowrap;
}
.qc-protocol-payment__compact-summary {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px 14px;
width: 100%;
margin-top: 8px;
font-size: 12px;
line-height: 1.4;
}
@@ -317,8 +317,9 @@
<el-radio value="ywc">已完成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="结论" required>
<el-form-item label="结论" :required="resultSaveStatus === 'ywc'">
<el-radio-group v-model="resultConclusion">
<el-radio value="" :disabled="resultSaveStatus === 'ywc'">待结论</el-radio>
<el-radio value="tg">通过</el-radio>
<el-radio value="btg">不通过</el-radio>
</el-radio-group>
@@ -1274,7 +1275,7 @@
resultTaskId.value = row.id
resultTaskType.value = row.taskType
resultRemark.value = row.remark || ''
resultConclusion.value = 'tg'
resultConclusion.value = ''
resultAttachments.value = apiFilesToFinanceItems(row.attachmentFiles)
materialUsages.value = []
requisitionOptions.value = []
@@ -1284,7 +1285,8 @@
resultTaskStatus.value = detail.taskStatus || row.taskStatus
resultSaveStatus.value = normalizeResultSaveStatus(detail.taskStatus || row.taskStatus)
resultRemark.value = detail.remark || row.remark || ''
resultConclusion.value = detail.conclusion || 'tg'
const c = (detail.conclusion || '').trim()
resultConclusion.value = c === 'tg' || c === 'btg' ? c : ''
resultAttachments.value = apiFilesToFinanceItems(detail.attachmentFiles)
const results = await fetchQcTaskResults(row.id)
resultParams.value = normalizeResultParams(results || [])
@@ -1318,7 +1320,11 @@
ElMessage.warning('请上传检测材料')
return
}
if (!resultConclusion.value) {
if (
resultSaveStatus.value === 'ywc' &&
resultConclusion.value !== 'tg' &&
resultConclusion.value !== 'btg'
) {
ElMessage.warning('请选择检测结论')
return
}