exportQuota2.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. <template>
  2. <div class="pdf-wrap">
  3. <table
  4. id="pdfTarget"
  5. style="
  6. width: 850px;
  7. line-height: 20px;
  8. font-size: 12px;
  9. font-family:
  10. 'Source Han Sans', 'Open Sans', 'WebFont-Open Sans', Arial, sans-serif;
  11. "
  12. >
  13. <tbody>
  14. <tr>
  15. <td style="vertical-align: bottom">
  16. <img
  17. style="position: relative; left: -10pt"
  18. src="http://zohocrmapi.promocollection.com.au/static/uploads/logo/pdf_logo.png"
  19. height="50px"
  20. />
  21. </td>
  22. <td style="vertical-align: top; text-align: right">
  23. <h1>Quotation</h1>
  24. </td>
  25. </tr>
  26. <tr>
  27. <td style="vertical-align: top">
  28. <template v-if="city2 === 'US'">
  29. <p>Promocollection, LLC</p>
  30. <p>1309 COFFEEN AVE STE 1200</p>
  31. <p>SHERIDAN</p>
  32. <p>WY 82801</p>
  33. </template>
  34. <template v-else>
  35. <p>FAIR OCEAN TRADING AUSTRALIA</p>
  36. <p>PTY LTD</p>
  37. <p>15/10 Chilvers Road,</p>
  38. <p>THORNLEIGH NSW 2120,</p>
  39. <p>AUSTRALIA</p>
  40. </template>
  41. </td>
  42. <td style="vertical-align: top; text-align: right">
  43. <table style="width: 250px; float: right">
  44. <colgroup>
  45. <col width="100px" />
  46. <col width="150px" />
  47. </colgroup>
  48. <tr>
  49. <td><strong>Sales Person:</strong></td>
  50. <td>{{ computedCreator }}</td>
  51. </tr>
  52. <tr>
  53. <td><strong>Order Date:</strong></td>
  54. <td>{{ dayjs().format('DD MMM YYYY') }}</td>
  55. </tr>
  56. </table>
  57. </td>
  58. </tr>
  59. <tr>
  60. <td style="vertical-align: top">
  61. <template v-if="city2 !== 'US'">
  62. <p>
  63. Email:&nbsp;&nbsp;&nbsp;&nbsp;accounts@promocollection.com.au
  64. </p>
  65. <p>Phone Number:&nbsp;&nbsp;&nbsp;&nbsp;02 9008 1152</p>
  66. <p>Fax Number:&nbsp;&nbsp;&nbsp;&nbsp;02 9008 1157</p>
  67. </template>
  68. </td>
  69. <td
  70. rowspan="3"
  71. style="vertical-align: top; text-align: right"
  72. >
  73. <img
  74. v-if="mainPicture2"
  75. :src="mainPicture2"
  76. width="300px"
  77. />
  78. </td>
  79. </tr>
  80. <tr>
  81. <td style="vertical-align: top">
  82. <p><strong>Information</strong></p>
  83. <p>
  84. <strong>{{ productInfo.product_name }}</strong>
  85. </p>
  86. <p v-if="productInfo.product_size">
  87. <strong>Size:</strong>
  88. {{ productInfo.product_size }}
  89. </p>
  90. <p v-if="productInfo.product_hd">
  91. <strong>Thickness:</strong>
  92. {{ productInfo.product_hd }}
  93. </p>
  94. <p v-if="productInfo.product_capacity">
  95. <strong>Capacity:</strong>
  96. {{ productInfo.product_capacity }}
  97. </p>
  98. <p v-if="productInfo.product_material">
  99. <strong>Material:</strong>
  100. {{ productInfo.product_material }}
  101. </p>
  102. <p v-if="productInfo.product_require_print">
  103. <strong>Print:</strong>
  104. {{ productInfo.product_require_print }}
  105. </p>
  106. <p v-if="productInfo.product_require_color">
  107. <strong>Color requirements:</strong>
  108. {{ productInfo.product_require_color }}
  109. </p>
  110. <p v-if="productInfo.product_color">
  111. <strong>Product Colours Available:</strong>
  112. {{ productInfo.product_color }}
  113. </p>
  114. <p v-if="productInfo.product_battery">
  115. <strong>Whether with battery:</strong>
  116. {{ productInfo.product_battery }}
  117. </p>
  118. <p v-if="productInfo.package_info">
  119. <strong>Packaging:</strong>
  120. {{ productInfo.package_info }}
  121. </p>
  122. <p v-if="productInfo.product_other">
  123. <strong>More Details:</strong>
  124. <span
  125. v-html="productInfo.product_other.replace(/\n/g, '<br>')"
  126. ></span>
  127. </p>
  128. </td>
  129. </tr>
  130. <tr style="vertical-align: top">
  131. <td><p></p></td>
  132. </tr>
  133. <tr style="vertical-align: top">
  134. <td colspan="2">
  135. <table style="width: 800px; border-spacing: 0">
  136. <tbody>
  137. <tr
  138. style="
  139. background-color: #eee;
  140. line-height: 45px;
  141. border-top: solid 1px #ccc;
  142. font-weight: bold;
  143. text-align: center;
  144. "
  145. >
  146. <td
  147. style="
  148. border-top: solid 1px #ccc;
  149. border-bottom: solid 1px #ccc;
  150. width: 20px;
  151. height: 45px;
  152. "
  153. >
  154. #
  155. </td>
  156. <td
  157. style="
  158. border-top: solid 1px #ccc;
  159. border-bottom: solid 1px #ccc;
  160. text-align: left;
  161. width: 230px;
  162. height: 45px;
  163. "
  164. >
  165. Items
  166. </td>
  167. <td
  168. style="
  169. border-top: solid 1px #ccc;
  170. border-bottom: solid 1px #ccc;
  171. width: 120px;
  172. height: 45px;
  173. "
  174. >
  175. Qty
  176. </td>
  177. <td
  178. style="
  179. border-top: solid 1px #ccc;
  180. border-bottom: solid 1px #ccc;
  181. width: 120px;
  182. height: 45px;
  183. "
  184. >
  185. Setup cost
  186. </td>
  187. <td
  188. style="
  189. border-top: solid 1px #ccc;
  190. border-bottom: solid 1px #ccc;
  191. width: 120px;
  192. height: 45px;
  193. "
  194. >
  195. Unit cost
  196. </td>
  197. <td
  198. style="
  199. border-top: solid 1px #ccc;
  200. border-bottom: solid 1px #ccc;
  201. width: 120px;
  202. height: 45px;
  203. "
  204. >
  205. Local Freight
  206. </td>
  207. <td
  208. style="
  209. border-top: solid 1px #ccc;
  210. border-bottom: solid 1px #ccc;
  211. width: 120px;
  212. height: 45px;
  213. "
  214. >
  215. {{ exportForm.gst_name ? 'Total(ex-GST)($)' : 'Total($)' }}
  216. </td>
  217. </tr>
  218. <tr
  219. v-for="(row, index) in step3FormList"
  220. :key="index"
  221. style="text-align: center; line-height: 45px"
  222. >
  223. <td style="border-bottom: solid 1px #ccc; height: 45px">
  224. {{ index + 1 }}
  225. </td>
  226. <td
  227. style="
  228. border-bottom: solid 1px #ccc;
  229. text-align: left;
  230. height: 45px;
  231. "
  232. >
  233. {{ productInfo.product_name }}
  234. <br />
  235. By {{ getFreightType(row) }}&nbsp;-&nbsp;{{
  236. exportForm[`zdy_date_${row.typeNumber}_${row.number}`]
  237. }}{{
  238. exportForm[`cycle_name_${row.typeNumber}_${row.number}`]
  239. }}
  240. </td>
  241. <td style="border-bottom: solid 1px #ccc; height: 45px">
  242. {{ formatNumber(row.number, true) }}&nbsp;units
  243. </td>
  244. <td style="border-bottom: solid 1px #ccc; height: 45px">
  245. ${{ formatNumber(row.setup_cost)
  246. }}{{ exportForm.gst_name ? '+GST' : '' }}
  247. </td>
  248. <td style="border-bottom: solid 1px #ccc; height: 45px">
  249. ${{ formatNumber(row.sold_unit)
  250. }}{{ exportForm.gst_name ? '+GST' : '' }}
  251. </td>
  252. <td style="border-bottom: solid 1px #ccc; height: 45px">
  253. ${{ formatNumber(row.add_freight_cost)
  254. }}{{ exportForm.gst_name ? '+GST' : '' }}
  255. </td>
  256. <td style="border-bottom: solid 1px #ccc; height: 45px">
  257. ${{ formatNumber(row.sold_price)
  258. }}{{ exportForm.gst_name ? '+GST' : '' }}
  259. </td>
  260. </tr>
  261. <tr>
  262. <td
  263. colspan="7"
  264. style="text-align: left; line-height: 45px"
  265. >
  266. Freight to {{ city_short[city] || city }} is included.Price
  267. based on exchange rate of {{ exportForm.exchange }}.Price is
  268. only valid for {{ exportForm.days }} days.
  269. </td>
  270. </tr>
  271. </tbody>
  272. </table>
  273. </td>
  274. </tr>
  275. <tr>
  276. <td colspan="2">
  277. <p style="line-height: 45px">
  278. <strong style="border-bottom: dashed 2px #000; padding: 10px">
  279. Notes
  280. </strong>
  281. </p>
  282. </td>
  283. </tr>
  284. <tr>
  285. <td colspan="2">
  286. <p
  287. style="padding-top: 20px"
  288. v-html="exportForm.notes.replace(/\n/g, '<br>')"
  289. ></p>
  290. </td>
  291. </tr>
  292. <tr>
  293. <td colspan="2">
  294. <p style="padding-top: 20px">
  295. <img
  296. v-for="(item, index) in otherPicture2"
  297. :key="index"
  298. :src="item"
  299. width="250px"
  300. style="padding-right: 10px"
  301. />
  302. </p>
  303. </td>
  304. </tr>
  305. <tr>
  306. <td colspan="2">
  307. <p>
  308. <a :href="mainPicture">{{ mainPicture }}</a>
  309. </p>
  310. </td>
  311. </tr>
  312. <tr>
  313. <td colspan="2">
  314. <p
  315. v-for="p in otherPicture"
  316. :key="p"
  317. >
  318. <a
  319. :href="p"
  320. target="_blank"
  321. >
  322. {{ p }}
  323. </a>
  324. </p>
  325. </td>
  326. </tr>
  327. <tr>
  328. <td
  329. colspan="2"
  330. style="text-align: center"
  331. >
  332. <img
  333. style="margin-top: 10px"
  334. src="http://zohocrmapi.promocollection.com.au/static/uploads/logo/pdf_end.png"
  335. />
  336. </td>
  337. </tr>
  338. </tbody>
  339. </table>
  340. </div>
  341. </template>
  342. <script lang="ts" setup>
  343. import { defineComponent, computed } from 'vue'
  344. import dayjs from 'dayjs'
  345. import { downloadPDF } from '@/api/indent'
  346. defineComponent({
  347. name: 'ComponentExportQuota2',
  348. })
  349. const {
  350. city = '',
  351. city2 = '',
  352. productInfo = {} as any,
  353. exportForm = {} as any,
  354. step2FormList = [],
  355. step3FormList = [],
  356. creatorOptions = [],
  357. } = defineProps<{
  358. city: string
  359. city2: string
  360. productInfo: object
  361. exportForm: object
  362. step2FormList: any[]
  363. step3FormList: any[]
  364. creatorOptions: any[]
  365. }>()
  366. const city_short = {
  367. SYD: 'Sydney',
  368. Melb: 'Melbourne',
  369. Brisbane: 'Brisbane',
  370. SA: 'Adelaide',
  371. WA: 'Perth',
  372. US: 'US',
  373. '': '',
  374. } as any
  375. const getFreightType = (row: any) => {
  376. let result = 'Sea'
  377. if (row.typeNumber < 2) {
  378. result = 'Air'
  379. }
  380. if (row.typeNumber === 3) {
  381. const temp: any[] = step2FormList.filter(
  382. (i: any) => i.number === row.number,
  383. )
  384. if (
  385. temp.length &&
  386. temp[0].fclData?.method_fcl &&
  387. ['快递', '空运'].includes(temp[0].fclData.method_fcl)
  388. ) {
  389. result = 'Air'
  390. }
  391. }
  392. return result
  393. }
  394. const generatePDF = () => {
  395. downloadPDF({
  396. content: document.getElementById('pdfTarget')?.outerHTML,
  397. title: productInfo.product_name || '_',
  398. create_time: '_',
  399. }).then((res: any) => {
  400. console.log(res, 'res pdf')
  401. if (res.result?.length) {
  402. window.open(import.meta.env.VITE_API_PREFIX + '/' + res.result)
  403. }
  404. })
  405. }
  406. // 把这个方法暴露给父组件, 否则无法在父组件被调用
  407. defineExpose({ generatePDF })
  408. const sliceImage = (urlString: string, width: number, height = width) => {
  409. if (urlString) {
  410. const extractedString = urlString.replace(/^https?:\/\/[^/]+/, '')
  411. const resizedImageUrl = `https://mediahub.promocollection.com.au/fit-in/${width}x${height}${extractedString}`
  412. return resizedImageUrl
  413. }
  414. }
  415. const mainPicture = computed(() => {
  416. if (
  417. Array.isArray(productInfo.product_image) &&
  418. productInfo.product_image.length
  419. ) {
  420. return productInfo.product_image[0]
  421. }
  422. return ''
  423. })
  424. const mainPicture2 = computed(() => {
  425. if (
  426. Array.isArray(productInfo.product_image) &&
  427. productInfo.product_image.length
  428. ) {
  429. return sliceImage(productInfo.product_image[0], 1000)
  430. }
  431. return ''
  432. })
  433. const otherPicture = computed(() => {
  434. if (
  435. Array.isArray(productInfo.product_image) &&
  436. productInfo.product_image.length > 1
  437. ) {
  438. return productInfo.product_image.slice(1)
  439. }
  440. return []
  441. })
  442. const otherPicture2 = computed(() => {
  443. if (
  444. Array.isArray(productInfo.product_image) &&
  445. productInfo.product_image.length > 1
  446. ) {
  447. return productInfo.product_image
  448. .slice(1)
  449. .map((i: string) => sliceImage(i, 1000))
  450. }
  451. return []
  452. })
  453. const computedCreator = computed(() => {
  454. let result = ''
  455. if (creatorOptions.length) {
  456. const a: any[] = creatorOptions.filter(
  457. (i: any) => i.value === exportForm.saleperson,
  458. )
  459. if (a.length) result = a[0].label
  460. }
  461. return result
  462. })
  463. // 处理数字, 保留两位小数, 即使是整数也显示两位00, 每3位用英文逗号分割
  464. const formatNumber = (number: number, no00 = false) => {
  465. const num = Number(number)
  466. if (Number.isNaN(num)) return '0.00'
  467. return no00
  468. ? `${num}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  469. : num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  470. }
  471. </script>
  472. <style lang="scss" scoped>
  473. $subColor: #777;
  474. .pdf-wrap {
  475. position: fixed;
  476. // top: 0;
  477. // left: 0;
  478. // z-index: 9999;
  479. top: -9999px;
  480. right: -9999px;
  481. box-sizing: border-box;
  482. width: 21cm;
  483. margin: 0 auto 12px;
  484. box-shadow: 1px 1px 2pt 0px $subColor;
  485. }
  486. </style>