<template>
|
<view class="customer-detail-page">
|
<PageHeader title="报价详情" @back="goBack" />
|
|
<view class="detail-content">
|
<view class="section">
|
<view class="section-title">基础信息</view>
|
<view class="info-list">
|
<view class="info-item">
|
<text class="info-label">报价单号</text>
|
<text class="info-value">{{ detailData.quotationNo || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">客户名称</text>
|
<text class="info-value">{{ detailData.customer || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">业务员</text>
|
<text class="info-value">{{ detailData.salesperson || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">报价日期</text>
|
<text class="info-value">{{ detailData.quotationDate || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">有效期至</text>
|
<text class="info-value">{{ detailData.validDate || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">付款方式</text>
|
<text class="info-value">{{ detailData.paymentMethod || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">审批状态</text>
|
<text class="info-value">{{ detailData.status || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">报价总额</text>
|
<text class="info-value highlight">{{ formatAmount(detailData.totalAmount) }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">备注</text>
|
<text class="info-value">{{ detailData.remark || "-" }}</text>
|
</view>
|
</view>
|
</view>
|
|
<view class="section">
|
<view class="section-title">审批节点</view>
|
<view v-if="approverNames.length" class="info-list">
|
<view v-for="(name, index) in approverNames" :key="index" class="info-item">
|
<text class="info-label">审批节点 {{ index + 1 }}</text>
|
<text class="info-value">{{ name }}</text>
|
</view>
|
</view>
|
<view v-else class="empty-box">
|
<text>暂无审批节点</text>
|
</view>
|
</view>
|
|
<view class="section">
|
<view class="section-title">产品明细</view>
|
<view v-if="detailData.products && detailData.products.length > 0" class="product-list">
|
<view v-for="(item, index) in detailData.products" :key="index" class="product-card">
|
<view class="product-head">产品 {{ index + 1 }}</view>
|
<view class="info-item">
|
<text class="info-label">产品名称</text>
|
<text class="info-value">{{ item.product || item.productName || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">规格型号</text>
|
<text class="info-value">{{ item.specification || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">单位</text>
|
<text class="info-value">{{ item.unit || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">数量</text>
|
<text class="info-value">{{ item.quantity || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">单价</text>
|
<text class="info-value">{{ formatAmount(item.unitPrice) }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">金额</text>
|
<text class="info-value highlight">{{ formatAmount(item.amount) }}</text>
|
</view>
|
</view>
|
</view>
|
<view v-else class="empty-box">
|
<text>暂无产品明细</text>
|
</view>
|
</view>
|
</view>
|
|
<FooterButtons cancelText="返回" confirmText="编辑" @cancel="goBack" @confirm="goEdit" />
|
</view>
|
</template>
|
|
<script setup>
|
import { computed, ref } from "vue";
|
import { onLoad, onShow } from "@dcloudio/uni-app";
|
import FooterButtons from "@/components/FooterButtons.vue";
|
import PageHeader from "@/components/PageHeader.vue";
|
|
const quotationId = ref("");
|
const detailData = ref({});
|
|
const approverNames = computed(() => {
|
const approverText = detailData.value.approveUserNames || detailData.value.approverNames || detailData.value.approveUserIds || "";
|
if (Array.isArray(approverText)) return approverText.filter(Boolean);
|
return String(approverText)
|
.split(",")
|
.map(item => item.trim())
|
.filter(Boolean);
|
});
|
|
const goBack = () => {
|
uni.navigateBack();
|
};
|
|
const goEdit = () => {
|
if (!quotationId.value) return;
|
uni.navigateTo({ url: `/pages/sales/salesQuotation/edit?id=${quotationId.value}` });
|
};
|
|
const formatAmount = amount => `¥${Number(amount || 0).toFixed(2)}`;
|
|
const loadDetailFromStorage = () => {
|
const cachedData = uni.getStorageSync("salesQuotationDetail");
|
detailData.value = cachedData || {};
|
};
|
|
onLoad(options => {
|
if (options?.id) {
|
quotationId.value = options.id;
|
}
|
loadDetailFromStorage();
|
});
|
|
onShow(() => {
|
loadDetailFromStorage();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.customer-detail-page {
|
min-height: 100vh;
|
background-color: #f5f5f5;
|
padding-bottom: 90px;
|
}
|
|
.detail-content {
|
padding: 16px;
|
}
|
|
.section {
|
background: #ffffff;
|
border-radius: 12px;
|
margin-bottom: 16px;
|
overflow: hidden;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
}
|
|
.section-title {
|
padding: 16px;
|
font-size: 16px;
|
font-weight: 600;
|
color: #303133;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.info-list {
|
padding: 8px 0;
|
}
|
|
.info-item {
|
display: flex;
|
padding: 12px 16px;
|
border-bottom: 1px solid #f8f8f8;
|
}
|
|
.info-item:last-child {
|
border-bottom: none;
|
}
|
|
.info-label {
|
width: 120px;
|
font-size: 14px;
|
color: #606266;
|
}
|
|
.info-value {
|
flex: 1;
|
font-size: 14px;
|
color: #303133;
|
text-align: right;
|
word-break: break-all;
|
}
|
|
.highlight {
|
color: #2979ff;
|
font-weight: 600;
|
}
|
|
.empty-box {
|
padding: 20px 16px;
|
font-size: 14px;
|
color: #999;
|
text-align: center;
|
}
|
|
.product-list {
|
padding: 12px;
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
}
|
|
.product-card {
|
background: #f9fafc;
|
border-radius: 10px;
|
overflow: hidden;
|
}
|
|
.product-head {
|
padding: 12px 16px;
|
font-size: 14px;
|
font-weight: 600;
|
color: #22324d;
|
border-bottom: 1px solid #eef2f7;
|
}
|
</style>
|