<template>
|
<view class="sales-account">
|
<PageHeader title="销售报价" @back="goBack" />
|
|
<view class="search-section">
|
<view class="search-bar">
|
<view class="search-input">
|
<up-input
|
class="search-text"
|
v-model="searchForm.product"
|
placeholder="请输入产品名称搜索"
|
clearable
|
@change="getList(true)"
|
/>
|
</view>
|
<view class="filter-button" @click="getList(true)">
|
<up-icon name="search" size="24" color="#999"></up-icon>
|
</view>
|
</view>
|
</view>
|
|
<view v-if="quotationList.length > 0" class="ledger-list">
|
<view v-for="item in quotationList" :key="item.id" class="ledger-item">
|
<view class="item-header">
|
<view class="item-left">
|
<view class="document-icon">
|
<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
|
</view>
|
<text class="item-id">{{ item.product || "-" }}</text>
|
</view>
|
</view>
|
|
<up-divider></up-divider>
|
|
<view class="item-details">
|
<view class="detail-row">
|
<text class="detail-label">规格</text>
|
<text class="detail-value">{{ item.specification || "-" }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">纸张</text>
|
<text class="detail-value">{{ item.paper || "-" }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">定量</text>
|
<text class="detail-value">{{ item.paperWeight || "-" }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">单价</text>
|
<text class="detail-value">{{ formatAmount(item.unitPrice) }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">印版费</text>
|
<text class="detail-value">{{ formatAmount(item.printingFee) }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">刀版费</text>
|
<text class="detail-value">{{ formatAmount(item.dieCuttingFee) }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">磨具费</text>
|
<text class="detail-value">{{ formatAmount(item.grindingFee) }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">数量</text>
|
<text class="detail-value">{{ Number(item.quantity || 0) }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">备注</text>
|
<text class="detail-value">{{ item.remark || "-" }}</text>
|
</view>
|
</view>
|
|
<view class="action-buttons">
|
<up-button class="action-btn" size="small" type="primary" @click="goEdit(item)">编辑</up-button>
|
<up-button class="action-btn" size="small" @click="goDetail(item)">详情</up-button>
|
<up-button class="action-btn" size="small" type="error" plain @click="handleDelete(item)">删除</up-button>
|
</view>
|
</view>
|
</view>
|
|
<view v-else class="no-data">
|
<text>暂无数据</text>
|
</view>
|
|
<view class="fab-button" @click="goAdd">
|
<up-icon name="plus" size="28" color="#ffffff"></up-icon>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { reactive, ref } from "vue";
|
import { onShow } from "@dcloudio/uni-app";
|
import PageHeader from "@/components/PageHeader.vue";
|
import { deleteQuotation } from "@/api/salesManagement/salesQuotation";
|
import { quotationProductListPage } from "@/api/salesManagement/salesQuotationProduct";
|
|
const searchForm = reactive({ product: "" });
|
const quotationList = ref([]);
|
const goBack = () => uni.navigateBack();
|
const goAdd = () => uni.navigateTo({ url: "/pages/sales/salesQuotation/edit" });
|
const goEdit = item => {
|
const source = item?.__raw || item || {};
|
uni.setStorageSync("salesQuotationEdit", source);
|
uni.navigateTo({ url: `/pages/sales/salesQuotation/edit?id=${item.id}` });
|
};
|
const goDetail = item => {
|
uni.setStorageSync("salesQuotationDetail", item || {});
|
uni.navigateTo({ url: `/pages/sales/salesQuotation/detail?id=${item.id}` });
|
};
|
|
const formatAmount = amount => `¥${Number(amount || 0).toFixed(2)}`;
|
|
const calcTotalAmountFromProducts = products =>
|
Number(
|
(products || [])
|
.reduce((sum, product) => {
|
const unitPrice = Number(product?.unitPrice || 0);
|
const printingFee = Number(product?.printingFee || 0);
|
const dieCuttingFee = Number(product?.dieCuttingFee || 0);
|
const grindingFee = Number(product?.grindingFee || 0);
|
return sum + unitPrice + printingFee + dieCuttingFee + grindingFee;
|
}, 0)
|
.toFixed(2)
|
);
|
|
const normalizeQuotation = row => {
|
const sourceProducts = Array.isArray(row?.products) && row.products.length ? row.products : [row];
|
const first = sourceProducts[0] || {};
|
return {
|
...row,
|
__raw: row,
|
customer: row?.customer || row?.customerName || first?.customer || first?.customerName || "",
|
salesperson: row?.salesperson || row?.salesman || row?.salesPerson || first?.salesperson || "",
|
quotationDate: row?.quotationDate || row?.quoteDate || first?.quotationDate || "",
|
validDate: row?.validDate || row?.expireDate || first?.validDate || "",
|
paymentMethod: row?.paymentMethod || row?.paymentType || first?.paymentMethod || "",
|
product: first.product || first.productName || row?.product || "",
|
specification: first.specification || row?.specification || "",
|
paper: first.paper || row?.paper || "",
|
paperWeight: first.paperWeight || row?.paperWeight || "",
|
unitPrice: Number(first.unitPrice || row?.unitPrice || 0),
|
printingFee: Number(first.printingFee || row?.printingFee || 0),
|
dieCuttingFee: Number(first.dieCuttingFee || row?.dieCuttingFee || 0),
|
grindingFee: Number(first.grindingFee || row?.grindingFee || 0),
|
quantity: Number(first.quantity || row?.quantity || 0),
|
quotationNo: row?.quotationNo || first?.quotationNo || "",
|
totalAmount: Number(row?.totalAmount || calcTotalAmountFromProducts(sourceProducts)),
|
};
|
};
|
|
const getList = () => {
|
uni.showLoading({ title: "加载中...", mask: true });
|
quotationProductListPage({
|
current: -1,
|
size: -1,
|
product: String(searchForm.product || "").trim(),
|
})
|
.then(res => {
|
const records = res?.data?.records || res?.records || [];
|
quotationList.value = Array.isArray(records) ? records.map(normalizeQuotation) : [];
|
})
|
.catch(() => {
|
uni.showToast({ title: "查询失败", icon: "error" });
|
})
|
.finally(() => {
|
uni.hideLoading();
|
});
|
};
|
|
const handleDelete = item => {
|
if (!item?.id) return;
|
uni.showModal({
|
title: "删除确认",
|
content: "确认删除该报价吗?",
|
success: res => {
|
if (!res.confirm) return;
|
uni.showLoading({ title: "处理中...", mask: true });
|
deleteQuotation([item.id])
|
.then(() => {
|
uni.showToast({ title: "删除成功", icon: "success" });
|
getList();
|
})
|
.catch(() => {
|
uni.showToast({ title: "删除失败", icon: "error" });
|
})
|
.finally(() => {
|
uni.hideLoading();
|
});
|
},
|
});
|
};
|
|
onShow(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
@import "@/styles/sales-common.scss";
|
|
.item-index {
|
max-width: 180rpx;
|
text-align: center;
|
}
|
|
.detail-value {
|
max-width: 70%;
|
word-break: break-all;
|
}
|
</style>
|