|
@@ -0,0 +1,442 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ id="pdfDom"
|
|
|
+ ref="pdfDom"
|
|
|
+ style="padding: 30px 60px"
|
|
|
+ v-loading="loading"
|
|
|
+ >
|
|
|
+ <table border="1" style="width: 100%" class="table">
|
|
|
+ <tr>
|
|
|
+ <td>
|
|
|
+ <img
|
|
|
+ :src="pdfData.companyPic"
|
|
|
+ alt=""
|
|
|
+ fit="scale-down"
|
|
|
+ style="height: 60px; width: 60px"
|
|
|
+ v-if="pdfData.companyPic && isShowImg"
|
|
|
+ />
|
|
|
+ </td>
|
|
|
+ <td style="padding: 10px" colspan="6">
|
|
|
+ <div style="font-size: 18px; color: #7f197f">
|
|
|
+ {{ pdfData.sellCorporationNameEn }}
|
|
|
+ </div>
|
|
|
+ <div style="font-size: 18px; color: #7f197f">
|
|
|
+ {{ pdfData.sellCorporationName }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style="font-size: 14px; color: #000">
|
|
|
+ Address: {{ pdfData.sellDetailedAddressEn }}
|
|
|
+ </div>
|
|
|
+ <div style="font-size: 14px; color: #000; margin-top: 5px">
|
|
|
+ {{ pdfData.sellCityNameEn }} , {{ pdfData.sellProvinceNameEn }} ,
|
|
|
+ {{ pdfData.sellCountryNameEn }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style="font-size: 14px; color: #000; margin-top: 10px">
|
|
|
+ 地址: {{ pdfData.sellCountryName }} ,
|
|
|
+ {{ pdfData.sellProvinceName }} , {{ pdfData.sellCityName }}
|
|
|
+ </div>
|
|
|
+ <div style="font-size: 14px; color: #000; margin-top: 5px">
|
|
|
+ {{ pdfData.sellDetailedAddress }}
|
|
|
+ </div>
|
|
|
+ <div style="margin: 8px 0; color: black">
|
|
|
+ Tel: <span>{{ pdfData.sellContactNumber }}</span>
|
|
|
+ <!-- Fax:
|
|
|
+ <span>{{ pdfData.fax }}</span>
|
|
|
+ Website:
|
|
|
+ <span>{{ pdfData.Website }}</span> -->
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="7">
|
|
|
+ <div style="text-align: center; font-size: 18px; color: #7f197f">
|
|
|
+ Proforma Invoice
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="7" style="padding: 0; background: #7f197f">
|
|
|
+ <div style="height: 15px"></div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="3" style="text-align: left">
|
|
|
+ Buyer: {{ pdfData.buyCorporationName }}
|
|
|
+ </td>
|
|
|
+ <td colspan="4" style="text-align: left">
|
|
|
+ Seller: {{ pdfData.sellCorporationNameEn }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td>PI No.</td>
|
|
|
+ <td colspan="2">{{ pdfData.contractCode }}</td>
|
|
|
+ <td>Date:</td>
|
|
|
+ <td colspan="3">{{ pdfData.createTimeEn }}</td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <!-- 客户合同号 -->
|
|
|
+ <td>PO No.</td>
|
|
|
+ <td colspan="2"></td>
|
|
|
+ <td>Loading Port:</td>
|
|
|
+ <td colspan="3">{{ pdfData.transportRemark }}</td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="7" style="padding: 0; background: #7f197f">
|
|
|
+ <div style="height: 15px"></div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <!-- 产品内容 -->
|
|
|
+ <tr>
|
|
|
+ <td style="width: 17%">Image</td>
|
|
|
+ <td style="width: 18%">Description</td>
|
|
|
+ <td style="width: 15%">Size</td>
|
|
|
+ <td style="width: 12%">Packaging</td>
|
|
|
+ <td style="width: 13%">
|
|
|
+ Order <br />
|
|
|
+ Quantity
|
|
|
+ </td>
|
|
|
+ <td style="width: 12%">Unit <br />Price</td>
|
|
|
+ <td style="width: 13%">Total <br />Amount</td>
|
|
|
+ </tr>
|
|
|
+
|
|
|
+ <tr
|
|
|
+ v-if="pdfData.productInfoList && pdfData.productInfoList.length > 0"
|
|
|
+ v-for="(item, index) in pdfData.productInfoList"
|
|
|
+ :key="item.productId"
|
|
|
+ >
|
|
|
+ <td>
|
|
|
+ <img
|
|
|
+ :src="item.fileList[0].fileUrl"
|
|
|
+ alt=""
|
|
|
+ fit="scale-down"
|
|
|
+ style="height: 60px; width: 60px"
|
|
|
+ v-if="item.fileList && item.fileList.length > 0 && isShowImg"
|
|
|
+ />
|
|
|
+ </td>
|
|
|
+ <td>{{ item.productName }}</td>
|
|
|
+ <td>
|
|
|
+ <span v-if="item.productModel">{{ item.productModel }} cm</span>
|
|
|
+ </td>
|
|
|
+ <td>{{ item.packMethod }}</td>
|
|
|
+ <td>
|
|
|
+ {{ item.productQuantity }}
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ {{ pdfData.currency }} {{ moneyFormat(item.productPrice, 2) }}
|
|
|
+ </td>
|
|
|
+ <td>{{ pdfData.currency }} {{ moneyFormat(item.amount, 2) }}</td>
|
|
|
+ </tr>
|
|
|
+ <template
|
|
|
+ v-if="
|
|
|
+ pdfData.contractProjectList &&
|
|
|
+ pdfData.contractProjectList.length > 0
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <tr>
|
|
|
+ <td colspan="6" style="text-align: right">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in pdfData.contractProjectList"
|
|
|
+ :key="item.id"
|
|
|
+ >
|
|
|
+ {{ item.payName }}:
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in pdfData.contractProjectList"
|
|
|
+ :key="item.id"
|
|
|
+ >
|
|
|
+ {{ pdfData.currency }}
|
|
|
+ {{ moneyFormat(item.amount, 2) }}
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </template>
|
|
|
+ <tr>
|
|
|
+ <td colspan="6" style="text-align: right">Total Amount:</td>
|
|
|
+ <td>
|
|
|
+ {{ pdfData.currency }}
|
|
|
+ {{ moneyFormat(pdfData.totalAmount, 2) }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="6" style="text-align: right">
|
|
|
+ Deposit( {{ pdfData.advanceRatio }} %):
|
|
|
+ </td>
|
|
|
+ <td>{{ pdfData.currency }} {{ getBalance(pdfData.advanceRatio) }}</td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="6" style="text-align: right">
|
|
|
+ Balance( {{ pdfData.advanceRatioOne }} %):
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ {{ pdfData.currency }} {{ getBalance(pdfData.advanceRatioOne) }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td colspan="7" style="padding: 0; background: #7f197f">
|
|
|
+ <div style="height: 15px"></div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <!-- 其他内容 -->
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">1.Lead Time:</td>
|
|
|
+ <td colspan="6" style="text-align: left">
|
|
|
+ {{ pdfData.deliveryTime }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">2.Payment Term:</td>
|
|
|
+ <td colspan="6" style="text-align: left">
|
|
|
+ <div v-html="pdfData.remark"></div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">3.Shipping Mode</td>
|
|
|
+ <td colspan="6" style="text-align: left">
|
|
|
+ {{ dictValueLabel(pdfData.transportMethod, shippingMethod) }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">4.Insurance</td>
|
|
|
+ <td colspan="6" style="text-align: left">By Buyer</td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">5.Banking Info</td>
|
|
|
+ <td colspan="6" style="text-align: left">
|
|
|
+ <div>Beneficiary Name: {{ pdfData.beneficiaryName }}</div>
|
|
|
+ <div>Beneficiary Bank: {{ pdfData.beneficiaryBank }}</div>
|
|
|
+ <div>
|
|
|
+ Beneficiary Bank Address:
|
|
|
+ {{ pdfData.beneficiaryBankAddress }}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ Beneficiary Account Number:
|
|
|
+ {{ pdfData.beneficiaryAccountNumber }}
|
|
|
+ </div>
|
|
|
+ <div>Swift Code: {{ pdfData.swiftCode }}</div>
|
|
|
+ <div>Beneficiary Address: {{ pdfData.beneficiaryAddress }}</div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align: left">6.Important Clauses:</td>
|
|
|
+ <td colspan="6" style="text-align: left">
|
|
|
+ A:Making payment will be considered as confirmation and
|
|
|
+ countersignature of this order. Order can not be canceled after
|
|
|
+ confirmation and countersignature except acceptance by the seller.
|
|
|
+ The Buyer has obligation to make full payment of order including
|
|
|
+ canceled orders.
|
|
|
+ <br />
|
|
|
+ B:The seller should not be responsible for the delay cause by the
|
|
|
+ buyer and force majeure.
|
|
|
+ <br />
|
|
|
+ C:Modification of products will not be allowed after the deposit has
|
|
|
+ been arranged unless acceptance by the seller. All costs and
|
|
|
+ <br />consequences arising from modifying the product or other
|
|
|
+ things will be borne by the buyer.
|
|
|
+ <br />
|
|
|
+ D:Packging details including shipping marks, barcodes, artworks,etc
|
|
|
+ .should be provided 30 days before cargo readty agreed by both
|
|
|
+ <br />parties.The delay caused by the buyer's failure to submit the
|
|
|
+ packaging materials on time will be borne the buyer.
|
|
|
+ <br />
|
|
|
+ E: Shipping information including consignee and notify party,
|
|
|
+ discharge port, loading port ects should be provided 20 before
|
|
|
+ cargo<br />
|
|
|
+ ready date. The delay caused by the buyer's failure to provide
|
|
|
+ shipping information on time will be borne by the buyer.
|
|
|
+ <br />
|
|
|
+ F:Please notify the seller of the special requirements of shipping
|
|
|
+ documents and certificates when placing an order.
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <!-- 盖章 -->
|
|
|
+ <tr>
|
|
|
+ <td colspan="3" style="text-align: left">
|
|
|
+ The Buyer's Signature
|
|
|
+ <div style="width: 200px; height: 200px"></div>
|
|
|
+ </td>
|
|
|
+ <td colspan="4" style="text-align: left">
|
|
|
+ The Seller's Signature
|
|
|
+ <div style="width: 200px; height: 200px">
|
|
|
+ <img
|
|
|
+ v-if="pdfData.companySeal && isShowImg"
|
|
|
+ :src="pdfData.companySeal"
|
|
|
+ alt=""
|
|
|
+ fit="scale-down"
|
|
|
+ style="height: 200px; width: 200px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { NumberToChinese } from "@/utils/util.js";
|
|
|
+import { watch } from "vue";
|
|
|
+import $ from "jquery";
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+const pdfData = ref({});
|
|
|
+const props = defineProps({
|
|
|
+ rowData: Object,
|
|
|
+});
|
|
|
+const loading = ref(false);
|
|
|
+const getPdfData = (query) => {
|
|
|
+ loading.value = true;
|
|
|
+ proxy.post("/contract/getContractPdfInfo", query).then((res) => {
|
|
|
+ pdfData.value = res;
|
|
|
+ if (pdfData.value.advanceRatio) {
|
|
|
+ pdfData.value.advanceRatio = parseFloat(
|
|
|
+ pdfData.value.advanceRatio
|
|
|
+ ).toFixed(2);
|
|
|
+ pdfData.value.advanceRatioOne = (
|
|
|
+ 100 - Number(pdfData.value.advanceRatio)
|
|
|
+ ).toFixed(2);
|
|
|
+ }
|
|
|
+ if (pdfData.value.sellCorporationId) {
|
|
|
+ proxy
|
|
|
+ .post("/fileInfo/getList", {
|
|
|
+ businessIdList: [pdfData.value.sellCorporationId],
|
|
|
+ fileType: 1,
|
|
|
+ })
|
|
|
+ .then((fileObj) => {
|
|
|
+ proxy
|
|
|
+ .getImgBase64(fileObj[pdfData.value.sellCorporationId][0].fileUrl)
|
|
|
+ .then((res) => {
|
|
|
+ pdfData.value.companyPic = res;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ proxy
|
|
|
+ .post("/fileInfo/getList", {
|
|
|
+ businessIdList: [pdfData.value.sellCorporationId],
|
|
|
+ fileType: 4,
|
|
|
+ })
|
|
|
+ .then((fileObj) => {
|
|
|
+ proxy
|
|
|
+ .getImgBase64(fileObj[pdfData.value.sellCorporationId][0].fileUrl)
|
|
|
+ .then((res) => {
|
|
|
+ pdfData.value.companySeal = res;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ loading.value = false;
|
|
|
+ // 拿取产品图
|
|
|
+ if (
|
|
|
+ pdfData.value.productInfoList &&
|
|
|
+ pdfData.value.productInfoList.length > 0
|
|
|
+ ) {
|
|
|
+ let arr = pdfData.value.productInfoList.map((x) => x.productId);
|
|
|
+ proxy
|
|
|
+ .post("/fileInfo/getList", {
|
|
|
+ businessIdList: arr,
|
|
|
+ })
|
|
|
+ .then(async (fileObj) => {
|
|
|
+ for (let i = 0; i < pdfData.value.productInfoList.length; i++) {
|
|
|
+ const e = pdfData.value.productInfoList[i];
|
|
|
+ for (const key in fileObj) {
|
|
|
+ if (e.productId === key) {
|
|
|
+ if (fileObj[key] && fileObj[key].length > 0) {
|
|
|
+ const res = await proxy.getImgBase64(fileObj[key][0].fileUrl);
|
|
|
+ fileObj[key][0].fileUrl = res;
|
|
|
+ e.fileList = fileObj[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const productUnit = ref([]);
|
|
|
+const tradeMethods = ref([]);
|
|
|
+const shippingMethod = ref([]);
|
|
|
+const getDict = () => {
|
|
|
+ proxy.getDictOne(["trade_mode", "shipping_method", "unit"]).then((res) => {
|
|
|
+ tradeMethods.value = res["trade_mode"].map((x) => ({
|
|
|
+ label: x.dictValue,
|
|
|
+ value: x.dictKey,
|
|
|
+ }));
|
|
|
+ shippingMethod.value = res["shipping_method"].map((x) => ({
|
|
|
+ label: x.dictValue,
|
|
|
+ value: x.dictKey,
|
|
|
+ }));
|
|
|
+ productUnit.value = res["unit"].map((x) => ({
|
|
|
+ label: x.dictValue,
|
|
|
+ value: x.dictKey,
|
|
|
+ }));
|
|
|
+ });
|
|
|
+};
|
|
|
+getDict();
|
|
|
+const getBalance = (val) => {
|
|
|
+ if (val) {
|
|
|
+ return proxy.moneyFormat(
|
|
|
+ parseFloat(pdfData.value.totalAmount * (val / 100)).toFixed(2),
|
|
|
+ 2
|
|
|
+ );
|
|
|
+ }
|
|
|
+};
|
|
|
+const isShowImg = ref(true);
|
|
|
+const exportExcel = () => {
|
|
|
+ isShowImg.value = false;
|
|
|
+ loading.value = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ $("#pdfDom").table2excel({
|
|
|
+ exclude: ".noExl",
|
|
|
+ sheetName: `外销合同${pdfData.value.contractCode}`,
|
|
|
+ filename: `外销合同${pdfData.value.contractCode}`,
|
|
|
+ exclude_img: false,
|
|
|
+ exclude_links: false,
|
|
|
+ exclude_inputs: true,
|
|
|
+ });
|
|
|
+ isShowImg.value = true;
|
|
|
+ loading.value = false;
|
|
|
+ }, 500);
|
|
|
+};
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ exportExcel,
|
|
|
+});
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.rowData,
|
|
|
+ (val) => {
|
|
|
+ if (props.rowData.id) {
|
|
|
+ getPdfData({ id: props.rowData.id });
|
|
|
+ } else if (props.rowData.code) {
|
|
|
+ getPdfData({ code: props.rowData.code });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ immediate: true,
|
|
|
+ deep: true,
|
|
|
+ }
|
|
|
+);
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.color-class {
|
|
|
+ color: #7f197f;
|
|
|
+}
|
|
|
+.bck {
|
|
|
+ background: #7f197f;
|
|
|
+}
|
|
|
+.width-one {
|
|
|
+ width: 140px;
|
|
|
+}
|
|
|
+.table {
|
|
|
+ border-collapse: collapse;
|
|
|
+ border-spacing: 0;
|
|
|
+
|
|
|
+ td {
|
|
|
+ text-align: center;
|
|
|
+ padding: 2px 4px;
|
|
|
+ // padding: 5px 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|