You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1545 lines
56 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div
  3. class="service-content tw-mb-[60px] tw-grid tw-grid-cols-1 tw-gap-[30px] md:tw-mb-[100px] xl:tw-px-[60px] xl:tw-max-w-screen-xl xl:tw-mx-auto xl:tw-grid-cols-[auto_364px]">
  4. <mobileFixTopBar ref="stickySwiper" :fixBar="fixBar" :currStep="currStep" :list="fixBarList"></mobileFixTopBar>
  5. <section class="step sercion-1 tw-w-full md:tw-px-[30px] xl:tw-px-0 xl:tw-col-span-2">
  6. <div class="tw-mt-[20px] md:tw-mb-[11px] md:tw-mt-[40px]">
  7. <Breadcrumbs></Breadcrumbs>
  8. </div>
  9. <div v-if="content.banners.length" class="tw-w-full">
  10. <slideshow :banners="content.banners"></slideshow>
  11. </div>
  12. </section>
  13. <section class="sercion-2 tw-px-[30px] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-2">
  14. <h1 class="t16 tw-mb-[18px] md:t24">{{ content.name }}</h1>
  15. <div v-if="content.supplier"
  16. class="supplier tw-flex tw-items-center tw-mb-[20px] tw-text-base-primary t14 md:tw-mb-[30px] md:t16 md:tw-font-normal">
  17. <img :src="content.supplier.logo" class="tw-max-w-[40px] md:tw-max-w-[80px]" />
  18. <div class="t14 tw-font-normal tw-ml-[10px] md:t18 md:tw-font-normal">
  19. {{ content.supplier.brand }}
  20. </div>
  21. </div>
  22. <div class="editor-styleguide tw-text-base-primary" v-html="content.highlights"></div>
  23. </section>
  24. <section
  25. class="sercion-3 tw-grid tw-grid-cols-1 tw-gap-[30px] md:tw-gap-[40px] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-3">
  26. <div ref="packageOptions" id="packageOptions" class="step">
  27. <div class="tw-px-[30px] md:tw-px-0">
  28. <h2 class="title-icon-left t16 tw-mb-[20px] md:t24">
  29. {{ $t("Package Options") }}
  30. </h2>
  31. <p class="text-slate-600 t12 md:t16">{{ $t("Select the exhibition you want to attend, and add the storage and delivery service of exhibits or truck pickup service") }}</p>
  32. </div>
  33. <div class="tw-w-full tw-bg-neutrals-100 tw-px-[20px] tw-py-[30px] md:tw-p-[30px] tw-rounded-[20px]">
  34. <div class="">
  35. <!-- 輸入攤位數量 -->
  36. <div v-if="serviceID" class="group tw-mb-[40px] tw-px-[20px] tw-py-[30px] tw-rounded-[20px] tw-bg-white">
  37. <h3 class="t14 tw-font-bold tw-mb-[30px] md:t16 tw-block">
  38. 輸入攤位數量
  39. </h3>
  40. <selectExhibitionBooth @booth-select="getBoothSelect" ref="ref_selectExhibitionBooth"></selectExhibitionBooth>
  41. </div>
  42. <!-- 選擇展覽 -->
  43. <div v-else class="group tw-mb-[40px] tw-px-[20px] tw-py-[30px] tw-rounded-[20px] tw-bg-white">
  44. <h3 class="t14 tw-font-bold tw-mb-[30px] md:t16 tw-block">
  45. {{ $t("Select Exhibition") }}
  46. </h3>
  47. <selectExhibition ref="ref_selectExhibition" :selectYearList="selectYearList" :selectMonthList="selectMonthList" :selectExhibitionList="selectExhibitionList"></selectExhibition>
  48. </div>
  49. <div class="group tw-mb-[20px] tw-p-[20px] tw-rounded-[20px] tw-bg-white">
  50. <h3 class="t14 tw-font-bold tw-mb-[20px] md:t16 tw-block">
  51. {{ $t("Select exhibition hall service") }}
  52. </h3>
  53. <div class="tw-mb-[10px]">
  54. <p class="tw-text-neutrals-500 tw-font-normal md:t16">{{ $t("Storage service of exhibits in the exhibition hall, and assistance in transportation to the designated booth") }}</p>
  55. </div>
  56. <selectExhibitionService v-for="(item,index) in selectExhibitionServiceList"
  57. :key="item.id" :ref="'ref_selectExhibitionitem'+item.id" @ChangeCosts="ChangeCosts($event)"
  58. :selectQuantityList="selectQuantityList"
  59. :selectPackageList="selectPackageList"
  60. :typeGroupList="typeGroupList"
  61. :sort="index+1"
  62. :show = "item.id == showServiceItem"
  63. @delExhibitionService="delExhibitionService(item.id)">
  64. </selectExhibitionService>
  65. <v-btn outlined class="tw-rounded-[16px] remove-upper tw-border-primary-2 tw-text-primary-1 tw-flex tw-items-center"
  66. style="padding: 24px 10px" width="100%" @click="addExhibitionService">
  67. <v-img max-width="20" class="tw-mr-[8px]" :src="require(`@/assets/svg/new.svg`)"></v-img>
  68. <span class="t18 tw-font-normal">{{ $t("New exhibit specifications") }}</span>
  69. </v-btn>
  70. </div>
  71. <div v-show="showCardItem" class="group tw-mb-[20px] tw-p-[20px] tw-rounded-[20px] tw-bg-white">
  72. <div class="tw-flex tw-justify-between tw-items-center">
  73. <h3 class="t14 tw-font-bold tw-mb-[20px] md:t16">
  74. {{ $t("Select truck pickup service") }}
  75. </h3>
  76. <v-img v-show="pickupServiceShow" max-width="18" max-height="19" class="tw-mr-[8px] tw-cursor-pointer" :src="require(`@/assets/svg/delete_default.svg`)" @click="deletePickupSerivce()"></v-img>
  77. </div>
  78. <div class="tw-mb-[20px]">
  79. <p class="tw-text-neutrals-500 tw-font-normal md:t16">{{ $t("Pick up the goods at the designated place and transport them to the exhibition hall") }}</p>
  80. </div>
  81. <div v-show="pickupServiceShow">
  82. <div>
  83. <quantitySelectGroup ref="ref_quantitySelectGroup" :label="'Select quantity'" :quantitySelectList="quantitySelectList" @ChangeCosts="ChangeCosts($event)">
  84. </quantitySelectGroup>
  85. </div>
  86. <h3 class="t14 tw-font-bold tw-mb-[20px] md:t16 tw-block">
  87. {{ $t("Fill in the picking information") }}<span class="required t12 md:t14">*</span>
  88. </h3>
  89. <pickupInformation :selectAddressList="selectAddressList" ref="ref_pickupService" @ChangeCosts="ChangeCosts($event)"></pickupInformation>
  90. </div>
  91. <v-btn v-show="pickupServiceShow==false" outlined class="tw-rounded-[16px] remove-upper tw-border-primary-2 tw-text-primary-1 t18"
  92. style="padding: 24px 10px" width="100%" @click="pickupServiceShow = true">
  93. <v-img max-width="20" class="tw-mr-[8px]" :src="require(`@/assets/svg/new.svg`)"></v-img>
  94. <span class="t18 tw-font-normal">{{ $t("New pickup service") }}</span>
  95. </v-btn>
  96. </div>
  97. <div class="md:tw-flex md:tw-justify-between md:tw-items-center">
  98. <div class="tw-flex tw-justify-between tw-items-start md:tw-w-full md:tw-basis-10/12">
  99. <div class="tw-flex tw-flex-col tw-justify-center">
  100. <div class="tw-flex tw-items-center tw-mb-[8px] md:tw-mb-0">
  101. <div class="tw-body-4 tw-text-neutrals-900 tw-mr-[10px] md:t24">
  102. ${{ finalPrice }} {{ currencyName }}
  103. <span style="font-size: 16px; color: gray;">{{ tax }}</span>
  104. </div>
  105. </div>
  106. <!-- <div class="tw-hidden tw-body-4 tw-text-neutrals-600 md:tw-hidden">
  107. Deposit fee: $5 {{ currency }} (10%)
  108. </div> -->
  109. </div>
  110. <like></like>
  111. </div>
  112. <button
  113. class="tw-transition tw-btn-md tw-text-white tw-border tw-border-solid tw-border-primary-default tw-bg-primary-default tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl md:tw-mt-0 md:tw-ml-[36px] md:tw-w-auto md:tw-basis-2/12 disabled:tw-bg-neutral-100 disabled:tw-text-base-disable disabled:tw-border-neutral-200"
  114. @click="bookNow" :disabled="btnDisabled">
  115. {{ $t("Book Now") }}
  116. </button>
  117. </div>
  118. </div>
  119. </div>
  120. </div>
  121. <div id="serviceDetails" class="serviceDetails step">
  122. <div class="tw-px-[30px] md:tw-px-0">
  123. <h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
  124. {{ $t("Service Details") }}
  125. </h2>
  126. <div v-if="content.details.length < 800">
  127. <div ref="details" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal"
  128. v-html="content.details"></div>
  129. </div>
  130. <div v-else>
  131. <div :class="[
  132. button.details ? 'seeMore-hide' : 'seeMore-show',
  133. 'editor-styleguide tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal',
  134. ]" ref="details" v-html="content.details"></div>
  135. <button v-show="seeMore.details" :class="[
  136. 'seeMore tw-transition tw-btn-md tw-text-primary-1 tw-border tw-border-solid tw-border-primary-1 tw-px-[30px] tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl hover:tw-bg-primary-3 xl:hover:tw-bg-transparent xl:tw-border-none',
  137. button.details ? '' : 'open',
  138. ]" @click="opendetail()">
  139. {{ $t(seeMoreDetailsText) }}
  140. </button>
  141. </div>
  142. </div>
  143. </div>
  144. <div id="serviceDescription" class="serviceDescription step">
  145. <div class="tw-px-[30px] md:tw-px-0">
  146. <h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
  147. {{ $t("Service Description") }}
  148. </h2>
  149. <div v-for="(item,index) in expenseRules" :key="index">
  150. <h3 class="t16 tw-mb-[20px] md:18 xl:t18 xl:tw-font-bold tw-pl-[10px]">
  151. {{ index+1 }}.&nbsp;{{ item.ItemName }}
  152. </h3>
  153. <table class="tablecss" width="100%" v-if="item.ItemType=='01'">
  154. <thead class="tw-bg-[#343434]">
  155. <tr>
  156. <th class="tw-text-[#fefefe]">{{$t('Weight')}}</th>
  157. <th class="tw-text-[#fefefe]">{{$t('Price (NT $, tax included)')}}</th>
  158. </tr>
  159. </thead>
  160. <tbody>
  161. <template v-if="item.StackerCostRules && item.StackerCostRules.length>0">
  162. <tr v-for="item2 in item.StackerCostRules" :key="item2.Guid">
  163. <td width="50%">{{item2.Weight_Min}}{{$t('More than tons to')}}{{item2.Weight_Max}}{{$t('Less than tons')}}</td>
  164. <td width="50%">{{item2.Price}}<span v-if="item2.PricingMode=='N'">{{$t('NTD/piece')}}</span><span v-else>{{$t('NTD/ton')}}</span></td>
  165. </tr>
  166. </template>
  167. </tbody>
  168. </table>
  169. <div ref="details" v-if="item.ItemType!='01' && item.ItemType!='02'" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal tw-mt-[20px]"
  170. v-html="item.CostRuleText"></div>
  171. <div ref="details" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal tw-mt-[20px]"
  172. v-html="item.ExpensesMemo"></div>
  173. </div>
  174. <!-- <div v-if="content.details.length < 800">
  175. <div ref="details" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal"
  176. v-html="content.details"></div>
  177. </div>
  178. <div v-else>
  179. <div :class="[
  180. button.details ? 'seeMore-hide' : 'seeMore-show',
  181. 'editor-styleguide tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal',
  182. ]" ref="details" v-html="content.details"></div>
  183. <button v-show="seeMore.details" :class="[
  184. 'seeMore tw-transition tw-btn-md tw-text-primary-1 tw-border tw-border-solid tw-border-primary-1 tw-px-[30px] tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl hover:tw-bg-primary-3 xl:hover:tw-bg-transparent xl:tw-border-none',
  185. button.details ? '' : 'open',
  186. ]" @click="opendetail()">
  187. {{ $t(seeMoreDetailsText) }}
  188. </button>
  189. </div> -->
  190. </div>
  191. </div>
  192. <div id="cancellationPolicy" class="cancellationPolicy step tw-px-[30px] md:tw-px-0">
  193. <h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
  194. {{ $t("Cancellation Policy") }}
  195. </h2>
  196. <div v-if="content.cancellation_policy.length < 800">
  197. <div ref="cancellation_policy" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal"
  198. v-html="content.cancellation_policy">
  199. </div>
  200. </div>
  201. <div v-else>
  202. <div :class="[
  203. button.cancellation_policy ? 'seeMore-hide' : 'seeMore-show',
  204. 'editor-styleguide tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal',
  205. ]" ref="cancellation_policy" v-html="content.cancellation_policy"></div>
  206. <button v-show="seeMore.cancellation_policy" :class="[
  207. 'seeMore tw-transition tw-btn-md tw-text-primary-1 tw-border tw-border-solid tw-border-primary-1 tw-px-[30px] tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl hover:tw-bg-primary-3 xl:hover:tw-bg-transparent xl:tw-border-none',
  208. button.cancellation_policy ? '' : 'open',
  209. ]" @click="openCancellationPolicy()">
  210. {{ $t(seeMoreCancellationPolicyText) }}
  211. </button>
  212. </div>
  213. </div>
  214. <div v-show="content.faq && content.faq.length>0" id="faq" ref="faq" class="step tw-px-[30px] md:tw-px-0">
  215. <h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
  216. {{ $t("FAQ") }}
  217. </h2>
  218. <faq :faq="content.faq" class="tw-z-[8]"></faq>
  219. </div>
  220. <div id="contactUs" class="step tw-px-[30px] md:tw-px-0">
  221. <h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
  222. {{ $t("Contact Us") }}
  223. </h2>
  224. <div class="tw-body-3 tw-text-base-primary tw-mb-[20px]">
  225. 886-2-2725-5000
  226. </div>
  227. <div class="tw-body-3 tw-text-base-primary">info@showeasy.com</div>
  228. </div>
  229. <div :class="[
  230. 'tw-bg-white tw-flex tw-flex-cols tw-justify-between tw-items-center tw-px-[30px] tw-py-[16px] tw-w-full',
  231. fixBar
  232. ? 'tw-fixed tw-left-[0px] tw-bottom-[0px] tw-z-[8] tw-shadow-[1px_0px_2px_rgba(0,0,0,0.25)]'
  233. : 'tw-hidden',
  234. ]">
  235. <div :class="[
  236. 'tw-flex tw-flex-col tw-justify-between tw-items-start tw-grow md:tw-w-full md:tw-flex-row md:tw-items-center',
  237. ]">
  238. <div class="tw-flex tw-items-center tw-mb-[12px] md:tw-mb-0">
  239. <div class="t16 tw-text-neutrals-900 tw-mr-[10px] md:t20 md:tw-mr-0">
  240. ${{ finalPrice }} {{ currencyName }}
  241. <span style="font-size: 16px; color: gray;">{{ tax }}</span>
  242. </div>
  243. </div>
  244. <div class="tw-flex tw-justify-center tw-items-center tw-w-full md:tw-w-fit">
  245. <like></like>
  246. <button
  247. class="tw-transition tw-whitespace-nowrap tw-body-4 tw-text-white tw-border tw-border-solid tw-border-primary-default tw-bg-primary-default tw-ml-[22px] tw-px-[24px] tw-py-[8.5px] tw-rounded-xl tw-w-full md:tw-body-2 md:tw-min-w-[130px] md:tw-max-w-[130px] md:tw-mt-0 disabled:tw-bg-neutral-100 disabled:tw-text-base-disable disabled:tw-border-neutral-200"
  248. @click="bookNow" :disabled="btnDisabled">
  249. {{ $t("Book Now") }}
  250. </button>
  251. </div>
  252. </div>
  253. </div>
  254. </section>
  255. <section
  256. class="sercion-4 tw-px-[30px] tw-grid tw-grid-cols-1 tw-gap-[40px] tw-z-[8] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-4">
  257. <detailsModal :detail="content.details"></detailsModal>
  258. <cancellationPolicyModal :cancellationPolicy="content.cancellation_policy"></cancellationPolicyModal>
  259. </section>
  260. <section class="sercion-5 tw-hidden md:tw-px-[30px] xl:tw-px-0 xl:tw-block xl:tw-row-start-2 xl:tw-row-end-5">
  261. <div class="tw-mb-[40px]">
  262. <sidebarSelectOption :totalPrice="finalPrice" :currency="currencyName" :confirmationTime="content.confirmationTime">
  263. </sidebarSelectOption>
  264. </div>
  265. <sideBarMenu :fixBarList="fixBarList" :currStep="currStep"></sideBarMenu>
  266. </section>
  267. <v-dialog v-model="dialog" :width="423"
  268. @click:outside="colseDialog()">
  269. <v-card class="tw-p-[30px]">
  270. <v-spacer class="d-flex tw-justify-between align-center tw-mb-[30px]">
  271. <div class="tw-text-[20px] tw-text-black tw-font-bold">
  272. {{ $t("Remind") }}
  273. </div>
  274. <v-btn @click="colseDialog()" icon>
  275. <v-icon> mdi-close </v-icon>
  276. </v-btn>
  277. </v-spacer>
  278. <v-spacer class="tw-mb-[40px]">
  279. <div class="tw-text-[16px] tw-text-neutrals-800">
  280. {{$t("Your goods are of special size. Please contact ShowEasy service personnel (02) 2725-5000")}}
  281. </div>
  282. </v-spacer>
  283. <div class="tw-text-[18px] tw-rounded-[16px] tw-text-center">
  284. <span class="tw-text-primary-1 t18">{{countdown}}</span>s{{ $t("userProfile.unLinkOK") }}
  285. </div>
  286. </v-card>
  287. </v-dialog>
  288. <loading :isLoading="isLoading"></loading>
  289. </div>
  290. </template>
  291. <script>
  292. import Breadcrumbs from "@/components/Breadcrumbs";
  293. import slideshow from "@/components/swiper/serviceContent.vue";
  294. import detailsModal from "@/components/service/contentModal/DetailsModal.vue";
  295. import cancellationPolicyModal from "@/components/service/contentModal/cancellationPolicyModal.vue";
  296. import selectExhibition from "@/components/service/content/selectExhibition.vue";
  297. import selectExhibitionBooth from "@/components/service/content/selectExhibitionBooth.vue";
  298. import selectExhibitionService from "@/components/service/content/selectExhibitionService.vue";
  299. import quantitySelectGroup from "@/components/service/content/quantitySelectGroup.vue";
  300. import pickupInformation from "@/components/service/content/pickupInformation.vue";
  301. import faq from "@/components/service/content/faq.vue";
  302. import sidebarSelectOption from "@/components/service/content/sidebarSelectOption.vue";
  303. import sideBarMenu from "@/components/service/content/sideBarMenu.vue";
  304. import Swiper from "swiper/bundle";
  305. import { scrollama } from "scrollama";
  306. import mobileFixTopBar from "@/components/swiper/mobileFixTopBar.vue";
  307. import like from "@/components/newComponent/like/like.vue";
  308. import { filterData,dateIsInWeekend } from "~/utils/common";
  309. import loading from "@/components/newComponent/loading/loading.vue";
  310. export default {
  311. name: 'ServiceContent',
  312. layout: "login",
  313. auth: false,
  314. components: {
  315. Swiper,
  316. scrollama,
  317. Breadcrumbs,
  318. slideshow,
  319. detailsModal,
  320. cancellationPolicyModal,
  321. selectExhibition,
  322. selectExhibitionBooth,
  323. selectExhibitionService,
  324. quantitySelectGroup,
  325. pickupInformation,
  326. faq,
  327. sidebarSelectOption,
  328. sideBarMenu,
  329. mobileFixTopBar,
  330. like,
  331. loading,
  332. },
  333. data() {
  334. return {
  335. dialog: false,
  336. isLoading: false,
  337. showCardItem: false,
  338. pickupServiceShow: false,
  339. apiUrl: process.env.SERVICE_CONSOLE,
  340. btnDisabled: process.env.ENV == 'production',
  341. currStep: null,
  342. stickySwiper: null,
  343. content: {
  344. banners: [],
  345. country: null,
  346. city: null,
  347. name: "",
  348. highlights: '',
  349. details: '',
  350. cancellation_policy: "",
  351. saved: false,
  352. confirmation_time: 24,
  353. supplier: {
  354. logo: require('/assets/img/Footer.png'),
  355. brand: 'ShowEasy'
  356. },
  357. available_sections: null,
  358. timeStatus: 'active',
  359. dateStatus: 'active',
  360. times: [{
  361. start_time: '2023-02-06',
  362. end_time: '2023-03-06',
  363. },{
  364. start_time: '2023-02-06',
  365. end_time: '2023-03-06',
  366. },{
  367. start_time: '2023-02-06',
  368. end_time: '2023-03-06',
  369. }],
  370. start: '2023-02-06',
  371. end: '2023-06-06',
  372. faq: [],
  373. confirmationTime: '',
  374. additionalServices: [
  375. {
  376. name: '司機英文服務'
  377. },{
  378. name: '兒童安全座椅'
  379. },{
  380. name: '增加一個停靠點'
  381. },{
  382. name: '協助飯店入住(每個人,限接機)'
  383. }
  384. ],
  385. },
  386. list: [],
  387. choicesIndex: 0,
  388. countrycode: [],
  389. regionName: [],
  390. elementHeight: {
  391. details: null,
  392. cancellation_policy: null,
  393. faq: null,
  394. },
  395. seeMore: {
  396. details: true,
  397. cancellation_policy: true,
  398. },
  399. button: {
  400. details: true,
  401. cancellation_policy: true,
  402. },
  403. offset: {
  404. packageOptions: 0,
  405. faq: 0,
  406. },
  407. contentId: "",
  408. packageId: "",
  409. packageName: "",
  410. window: {
  411. width: 0,
  412. },
  413. fixBar: false,
  414. fixBarList: [
  415. { id: "packageOptions", title: "Package Options", show: true },
  416. { id: "serviceDetails", title: "Service Details", show: true },
  417. { id: "serviceDescription", title: "Service Description", show: true },
  418. { id: "cancellationPolicy", title: "Cancellation Policy", show: true },
  419. { id: "faq", title: "FAQ", show: false },
  420. { id: "contactUs", title: "Contact Us", show: true },
  421. ],
  422. activePackage: 0,
  423. totalPrice: 0,
  424. additionTotalPrice: [],
  425. customPlanPrice: [],
  426. selectDates: '',
  427. typeGroupList: [],
  428. selectQuantityList: [],
  429. selectYearList: [],
  430. selectMonthList: [],
  431. selectExhibitionList: [],
  432. selectAddressList: [],
  433. selectExhibitionServiceList: [{id: 0,show: true}],
  434. selectPackageList: [],
  435. quantitySelectList: [],
  436. deliveryType: '',
  437. expenseRules: [],
  438. finalPrice: "0",
  439. showServiceItem: 0,
  440. currencyName: '',
  441. currencyID: '',
  442. previewFile: '',
  443. countdown: 15,
  444. rulesShow: false,
  445. boothSelect: 0,
  446. serviceID: false,
  447. stackerDiscountQuota: 0,
  448. stackerDiscountQuotaUsed: 0,
  449. tax: '(未稅)'
  450. };
  451. },
  452. async created() {
  453. if(this.$route.params.id == "fb48072e-2d82-4ec6-9aeb-759df42a9ab0"){
  454. // if(this.$route.params.id == "1c6e0001-e2dd-46b5-a617-4dac2f34894f"){
  455. this.serviceID = true;
  456. }else{
  457. this.serviceID = false;
  458. }
  459. this.isLoading = true;
  460. let arr = [];
  461. for(let i=1;i<11;i++){
  462. let target = {
  463. id: i+"",
  464. name: i+"",
  465. };
  466. arr.push(target);
  467. }
  468. this.selectQuantityList = arr;
  469. await this.getBanners();
  470. await this.getServiceData();
  471. await this.getExtensionYear();
  472. await this.getExtensionMonth();
  473. await this.getExhibitions();
  474. await this.getQuantitySelects();
  475. await this.getServiceItems();
  476. await this.getReceivingCitys();
  477. // await this.getFaq();
  478. await this.getPackages();
  479. await this.getInfoItem();
  480. // await this.addViewCount();
  481. // await this.getYouMightLikeData();
  482. // await this.getRegionName();
  483. // await this.getCountryCode();
  484. if (process.browser) {
  485. window.addEventListener("resize", this.handleResize);
  486. }
  487. this.handleResize();
  488. this.$nextTick(()=>{
  489. this.isLoading = false;
  490. });
  491. console.log(this.$refs.ref_selectExhibition)
  492. },
  493. mounted() {
  494. let vm = this;
  495. vm.contentId = vm.$route.params.id;
  496. vm.offset.packageOptions = vm.$refs.packageOptions.offsetTop;
  497. vm.offset.faq = vm.$refs.faq.offsetTop;
  498. vm.$nextTick(function () {
  499. // instantiate the scrollama
  500. const scrollama = require("scrollama");
  501. const scroller = scrollama();
  502. // setup the instance, pass callback functions
  503. scroller
  504. .setup({
  505. step: ".service-content .step",
  506. offset: 0.6,
  507. })
  508. .onStepEnter((response) => {
  509. // { element, index, direction }
  510. vm.currStep = response.element.id;
  511. let fb_messenger = document.querySelector(".fb_dialog_content");
  512. if (response.index > 3) {
  513. vm.$refs.stickySwiper.slideTo(4);
  514. } else {
  515. vm.$refs.stickySwiper.slideTo(0);
  516. }
  517. if (response.index >= 1 && response.index < 6) {
  518. vm.fixBar = true;
  519. if (fb_messenger) {
  520. fb_messenger.classList.add("hasBar");
  521. }
  522. } else {
  523. vm.fixBar = false;
  524. if (fb_messenger) {
  525. fb_messenger.classList.remove("hasBar");
  526. }
  527. }
  528. })
  529. .onStepExit((response) => {
  530. // { element, index, direction }
  531. vm.currStep = response.element.id;
  532. let fb_messenger = document.querySelector(".fb_dialog_content");
  533. if (response.index >= 1 && response.index < 6) {
  534. vm.fixBar = true;
  535. if (fb_messenger) {
  536. fb_messenger.classList.add("hasBar");
  537. }
  538. } else {
  539. vm.fixBar = false;
  540. if (fb_messenger) {
  541. fb_messenger.classList.remove("hasBar");
  542. }
  543. }
  544. });
  545. })
  546. },
  547. computed: {
  548. currency() {
  549. return this.$store.getters.getCurrency;
  550. },
  551. seeMoreDetailsText() {
  552. if (this.button.details == false) {
  553. return "See less";
  554. } else {
  555. return "See more";
  556. }
  557. },
  558. seeMoreCancellationPolicyText() {
  559. if (this.button.cancellation_policy == false) {
  560. return "See less";
  561. } else {
  562. return "See more";
  563. }
  564. },
  565. // finalPrice() {
  566. // let option = 0;
  567. // let custom = 0;
  568. // let addition = 0;
  569. // if (this.additionTotalPrice) {
  570. // this.additionTotalPrice.forEach((item) => {
  571. // addition += Number(item.total);
  572. // });
  573. // }
  574. // if (this.customPlanPrice) {
  575. // this.customPlanPrice.forEach((item) => {
  576. // custom += Number(item.total);
  577. // });
  578. // }
  579. // if (this.totalPrice) {
  580. // this.totalPrice.forEach((item) => {
  581. // option += Number(item.total);
  582. // });
  583. // }
  584. // if (this.currency == 'USD') {
  585. // return Number(addition + custom + option).toFixed(2).toLocaleString();
  586. // } else {
  587. // return Number(addition + custom + option).toLocaleString();
  588. // }
  589. // },
  590. },
  591. watch: {
  592. currency: {
  593. handler: function () {
  594. this.getServiceData();
  595. // this.getPackages();
  596. },
  597. },
  598. // activePackage: {
  599. // handler: function (newVal, oldVal) {
  600. // if (newVal !== oldVal) {
  601. // this.customPlanPrice = [];
  602. // this.totalPrice = [];
  603. // }
  604. // },
  605. // },
  606. // choicesIndex: {
  607. // handler: function (newVal, oldVal) {
  608. // if (newVal !== oldVal) {
  609. // this.customPlanPrice = [];
  610. // this.totalPrice = [];
  611. // }
  612. // },
  613. // }
  614. },
  615. destroyed() {
  616. if (process.browser) {
  617. window.removeEventListener("resize", this.handleResize);
  618. }
  619. },
  620. methods: {
  621. async getBanners() {
  622. await this.$axios.get(`/trending/api/Onsite/BannerFiles?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}`)
  623. .then((response) => {
  624. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  625. let data = response.data.DATA.rel
  626. if(data.length>0){
  627. this.content.banners = data.map((item) => {
  628. return {
  629. banner_id: item.FileID,
  630. image: item.FilePath,
  631. };
  632. });
  633. }
  634. }
  635. })
  636. .catch((error) => console.log(error));
  637. },
  638. async getExtensionYear() {
  639. await this.$axios.get(`/trending/api/Onsite/ExtensionYear?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}`)
  640. .then((response) => {
  641. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  642. let data = response.data.DATA.rel
  643. if(data.length>0){
  644. this.selectYearList = data.map((item) => {
  645. return {
  646. id: item.ArgumentID,
  647. name: item.ArgumentValue,
  648. };
  649. });
  650. }
  651. }
  652. })
  653. .catch((error) => console.log(error));
  654. },
  655. async getExtensionMonth() {
  656. await this.$axios.get(`/trending/api/Onsite/ExtensionMonth?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  657. .then((response) => {
  658. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  659. let data = response.data.DATA.rel
  660. if(data.length>0){
  661. this.selectMonthList = data.map((item) => {
  662. return {
  663. id: item.ArgumentID,
  664. name: item.ArgumentValue,
  665. };
  666. });
  667. }
  668. }
  669. })
  670. .catch((error) => console.log(error));
  671. },
  672. async getExhibitions(){
  673. let select_year = "";
  674. let select_month = "";
  675. await this.$axios.get(`/trending/api/Onsite/Exhibitions?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}&Year=${select_year}&Month=${select_month}`)
  676. .then((response) => {
  677. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  678. let data = response.data.DATA.rel
  679. if(data.length>0){
  680. this.selectExhibitionList = data.map((item) => {
  681. return {
  682. id: item.ArgumentID,
  683. name: item.ArgumentValue,
  684. };
  685. });
  686. }
  687. }
  688. })
  689. .catch((error) => console.log(error));
  690. },
  691. async getServiceItems() {
  692. this.showCardItem = false;
  693. await this.$axios
  694. .get(`trending/api/Onsite/ServiceItems?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}`)
  695. .then((response) => {
  696. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  697. let data = response.data.DATA.rel
  698. if(data.length>0){
  699. this.typeGroupList = data.map((item) => {
  700. if(item.ItemType=="02"){
  701. this.showCardItem = true;
  702. }
  703. return {
  704. package_id: item.ArgumentID,
  705. name: item.ArgumentValue,
  706. itemType: item.ItemType
  707. };
  708. });
  709. }
  710. }
  711. })
  712. .catch((error) => console.log(error));
  713. },
  714. // async getFaq() {
  715. // await this.$axios
  716. // .get(
  717. // `${this.apiUrl}/user-services/faqs?service_id=${this.$route.params.id}&lang_code=${this.$i18n.localeProperties["langQuery"]}`
  718. // )
  719. // .then((res) => {
  720. // this.content.faq = res.data;
  721. // })
  722. // .catch((error) => console.log(error));
  723. // },
  724. async getPackages() {
  725. await this.$axios
  726. .get(`trending/api/Onsite/PackingTypes?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  727. .then((response) => {
  728. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  729. let data = response.data.DATA.rel
  730. if(data.length>0){
  731. this.selectPackageList = data.map((item) => {
  732. return {
  733. id: item.ArgumentID,
  734. name: item.ArgumentValue,
  735. };
  736. });
  737. }
  738. }
  739. })
  740. .catch((error) => console.log(error));
  741. },
  742. async getQuantitySelects() {
  743. await this.$axios
  744. .get(`trending/api/Onsite/TruckTypes?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  745. .then((response) => {
  746. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  747. let data = response.data.DATA.rel
  748. if(data.length>0){
  749. this.quantitySelectList = data;
  750. }
  751. }
  752. })
  753. .catch((error) => console.log(error));
  754. },
  755. async getReceivingCitys() {
  756. await this.$axios
  757. .get(`trending/api/Onsite/ReceivingCitys?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  758. .then((response) => {
  759. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  760. let data = response.data.DATA.rel
  761. if(data.length>0){
  762. this.selectAddressList = data.map((item) => {
  763. return {
  764. id: item.ArgumentID,
  765. name: item.ArgumentValue,
  766. };
  767. });
  768. }
  769. }
  770. })
  771. .catch((error) => console.log(error));
  772. },
  773. async getServiceData() {
  774. await this.$axios
  775. .get(`/trending/api/Onsite/Info?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}`)
  776. .then((response) => {
  777. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  778. let data = response.data.DATA.rel
  779. if(data){
  780. this.content.name = data.ServiceName;
  781. this.content.highlights = data.Features;
  782. this.content.details = data.Details;
  783. this.content.cancellation_policy = data.CancelPolicy;
  784. this.content.faq = data.FQAs;
  785. this.currencyName = data.CurrencyName;
  786. this.currencyID = data.CurrencyID;
  787. this.previewFile = data.PreviewFile;
  788. this.finalPrice = data.MinPrice == null ? "0" : data.MinPrice +"";
  789. this.content.supplier.brand = data.SupplierName;
  790. this.content.supplier.logo = data.SupplierLogo;
  791. for(let i=0;i<this.fixBarList.length;i++){
  792. if(this.fixBarList[i].id=="faq"){
  793. if(data.FQAs && data.FQAs.length>0){
  794. this.fixBarList.show = true;
  795. }else{
  796. this.fixBarList.show = false;
  797. }
  798. break;
  799. }
  800. }
  801. this.content.confirmationTime = data.ConfirmDays;
  802. }
  803. }
  804. // this.content.country = res.data.country;
  805. // this.content.city = res.data.city;
  806. // this.content.highlights = res.data.highlights;
  807. // this.content.details = res.data.details;
  808. // this.content.cancellation_policy = res.data.cancellation_policy;
  809. // this.content.supplier = res.data.supplier;
  810. // this.content.available_sections = res.data.available_sections;
  811. // this.content.times = res.data.available_sections.times;
  812. // this.content.timeStatus = res.data.available_sections.time_status;
  813. // this.content.dateStatus = res.data.available_sections.date_status;
  814. // this.content.start = res.data.available_sections.start;
  815. // this.content.end = res.data.available_sections.end;
  816. // this.content.payment_currency = res.data.payment_currency;
  817. // this.content.confirmationTime = res.data.confirmation_time.toString();
  818. })
  819. .catch((error) => console.log(error));
  820. },
  821. //攤位數量
  822. getBoothSelect(value){
  823. this.boothSelect = value;
  824. this.setStackerDiscountQuota();
  825. this.ChangeCosts(null);
  826. },
  827. //抓卡車相關數據
  828. async getInfoItem() {
  829. await this.$axios
  830. .get(`/trending/api/Onsite/InfoItem?Lang=${this.$i18n.localeProperties["langQuery"]}&ServiceID=${this.$route.params.id}`)
  831. .then((response) => {
  832. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  833. let data = response.data.DATA.rel
  834. if(data.length>0){
  835. this.expenseRules = data;
  836. }
  837. }
  838. })
  839. .catch((error) => console.log(error));
  840. },
  841. async addViewCount() {
  842. let Obj = {
  843. service_id: `${this.$route.params.id}`,
  844. lang_code: `${this.$i18n.localeProperties["langQuery"]}`,
  845. add_number: 1,
  846. };
  847. await this.$axios
  848. .put(`${this.apiUrl}/user-services/view-counts`, Obj)
  849. .then((res) => { })
  850. .catch((error) => console.log(error));
  851. },
  852. opendetail() {
  853. if (this.window.width >= 1366) {
  854. this.button.details = !this.button.details;
  855. } else {
  856. this.$modal.show("Details");
  857. }
  858. },
  859. openCancellationPolicy() {
  860. if (this.window.width >= 1366) {
  861. this.button.cancellation_policy = !this.button.cancellation_policy;
  862. } else {
  863. this.$modal.show("cancellationPolicy");
  864. }
  865. },
  866. handleResize() {
  867. if (process.browser) {
  868. this.window.width = window.innerWidth;
  869. }
  870. },
  871. bookNow() {
  872. //正常的service
  873. if(this.serviceID == false){
  874. let validators = this.$refs.ref_selectExhibition.validators();
  875. console.log(validators)
  876. console.log("this.$refs.ref_selectExhibition:", this.$refs.ref_selectExhibition);
  877. if(validators==false){
  878. return false;
  879. }
  880. if(this.selectExhibitionServiceList.length>0){
  881. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  882. let ref = eval("this.$refs.ref_selectExhibitionitem"+this.selectExhibitionServiceList[i].id)[0];
  883. if(ref !=undefined){
  884. validators = ref.validators();
  885. if(validators==false){
  886. ref.show = true;
  887. return false;
  888. }
  889. }
  890. }
  891. }
  892. let selectExhibitionData = this.$refs.ref_selectExhibition.formData;
  893. let selectExhibitionServiceData = [];
  894. if(this.selectExhibitionServiceList.length>0){
  895. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  896. let ref = eval("this.$refs.ref_selectExhibitionitem"+this.selectExhibitionServiceList[i].id)[0];
  897. if(ref !=undefined){
  898. let target = ref.formData;
  899. selectExhibitionServiceData.push(target);
  900. }
  901. }
  902. }
  903. let quantityData = this.$refs.ref_quantitySelectGroup.formData;
  904. console.log(quantityData)
  905. if(quantityData.selectList.length>0){
  906. if(this.showCardItem){
  907. validators = this.$refs.ref_quantitySelectGroup.validators();
  908. if(validators==false){
  909. this.pickupServiceShow = true;
  910. return false;
  911. }
  912. validators = this.$refs.ref_pickupService.validators();
  913. if(validators==false){
  914. this.pickupServiceShow = true;
  915. return false;
  916. }
  917. }
  918. }
  919. // let pickupServiceData = this.$refs. ref_pickupService.formData;
  920. if(this.rulesShow){
  921. this.ChangeCosts(null);
  922. return false;
  923. }
  924. this.$router.push(
  925. {
  926. path: this.localePath("/service/checkout/" + this.$route.params.id),
  927. //携带需要传递的参数
  928. query: {
  929. selectExhibitionData: encodeURIComponent(JSON.stringify(selectExhibitionData)),
  930. selectExhibitionServiceData: encodeURIComponent(JSON.stringify(selectExhibitionServiceData)),
  931. quantityData: encodeURIComponent(JSON.stringify(quantityData)),
  932. // pickupServiceData: encodeURIComponent(JSON.stringify(pickupServiceData)),
  933. totalPrice: this.totalPrice,
  934. currencyName: encodeURIComponent(this.currencyName),
  935. previewFile: encodeURIComponent(this.previewFile),
  936. title: encodeURIComponent(this.content.name)
  937. }
  938. });
  939. this.$auth.$storage.setUniversal('userBeforePath', this.$route.fullPath);
  940. }
  941. //高雄展
  942. else if (this.serviceID == true) {
  943. let validators = this.$refs.ref_selectExhibitionBooth.validators();
  944. if(validators==false){
  945. return false;
  946. }
  947. if(this.selectExhibitionServiceList.length>0){
  948. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  949. let ref = eval("this.$refs.ref_selectExhibitionitem"+this.selectExhibitionServiceList[i].id)[0];
  950. if(ref !=undefined){
  951. validators = ref.validators();
  952. if(validators==false){
  953. ref.show = true;
  954. return false;
  955. }
  956. }
  957. }
  958. }
  959. let selectExhibitionData = this.selectExhibitionList;
  960. let selectExhibitionServiceData = [];
  961. if(this.selectExhibitionServiceList.length>0){
  962. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  963. let ref = eval("this.$refs.ref_selectExhibitionitem"+this.selectExhibitionServiceList[i].id)[0];
  964. if(ref !=undefined){
  965. let target = ref.formData;
  966. selectExhibitionServiceData.push(target);
  967. }
  968. }
  969. }
  970. let quantityData = this.$refs.ref_quantitySelectGroup.formData;
  971. console.log(quantityData)
  972. if(quantityData.selectList.length>0){
  973. if(this.showCardItem){
  974. validators = this.$refs.ref_quantitySelectGroup.validators();
  975. if(validators==false){
  976. this.pickupServiceShow = true;
  977. return false;
  978. }
  979. validators = this.$refs.ref_pickupService.validators();
  980. if(validators==false){
  981. this.pickupServiceShow = true;
  982. return false;
  983. }
  984. }
  985. }
  986. // let pickupServiceData = this.$refs. ref_pickupService.formData;
  987. if(this.rulesShow){
  988. this.ChangeCosts(null);
  989. return false;
  990. }
  991. this.$router.push(
  992. {
  993. path: this.localePath("/service/checkout/" + this.$route.params.id),
  994. //携带需要传递的参数
  995. query: {
  996. // selectExhibitionData: selectExhibitionData,
  997. selectExhibitionData: encodeURIComponent(JSON.stringify(selectExhibitionData)),
  998. selectExhibitionServiceData: encodeURIComponent(JSON.stringify(selectExhibitionServiceData)),
  999. quantityData: encodeURIComponent(JSON.stringify(quantityData)),
  1000. // pickupServiceData: encodeURIComponent(JSON.stringify(pickupServiceData)),
  1001. totalPrice: this.totalPrice,
  1002. currencyName: encodeURIComponent(this.currencyName),
  1003. previewFile: encodeURIComponent(this.previewFile),
  1004. title: encodeURIComponent(this.content.name)
  1005. }
  1006. });
  1007. }
  1008. },
  1009. // choicesIdx(data) {
  1010. // let vm = this;
  1011. // vm.choicesIndex = data;
  1012. // },
  1013. addExhibitionService(){
  1014. const arr = this.selectExhibitionServiceList.map(({id})=> id);
  1015. let max = arr.length>0 ? Math.max.apply(null, arr) : 0;
  1016. this.selectExhibitionServiceList.push({id: max+1,show:true});
  1017. this.showServiceItem = max+1;
  1018. },
  1019. delExhibitionService(value){
  1020. if(this.selectExhibitionServiceList.length>0){
  1021. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  1022. if(value == this.selectExhibitionServiceList[i].id){
  1023. // let index = this.selectExhibitionServiceList.indexOf(this.selectExhibitionServiceList[i]);
  1024. this.selectExhibitionServiceList.splice(i, 1);
  1025. break;
  1026. }
  1027. }
  1028. }
  1029. this.ChangeCosts(null);
  1030. },
  1031. deletePickupSerivce(){
  1032. this.pickupServiceShow = false;
  1033. if(this.$refs.ref_quantitySelectGroup){
  1034. this.$refs.ref_quantitySelectGroup.clearAll();
  1035. }
  1036. },
  1037. //展館服務(包裝、尺寸、數量、服務類型) //加總金額
  1038. ChangeCosts(data){
  1039. let totalPrice = 0;
  1040. this.totalPrice = 0;
  1041. this.rulesShow = false;
  1042. this.stackerDiscountQuotaUsed = 0;
  1043. // let selectExhibitionData = this.$refs.ref_selectExhibition.formData;
  1044. let selectExhibitionServiceData = [];
  1045. if(this.selectExhibitionServiceList.length>0){
  1046. for(let i=0;i<this.selectExhibitionServiceList.length;i++){
  1047. let ref = eval("this.$refs.ref_selectExhibitionitem"+this.selectExhibitionServiceList[i].id)[0];
  1048. if(ref !=undefined){
  1049. let target = ref.formData;
  1050. selectExhibitionServiceData.push(target);
  1051. }
  1052. }
  1053. }
  1054. if(selectExhibitionServiceData.length>0){
  1055. // sort by serviceData weight
  1056. selectExhibitionServiceData = selectExhibitionServiceData.sort(function(serviceDataA, serviceDataB) {
  1057. return serviceDataB.weight - serviceDataA.weight;
  1058. });
  1059. for(let i=0;i<selectExhibitionServiceData.length;i++){
  1060. let serviceTypeArr = selectExhibitionServiceData[i].selectServiceItems;
  1061. // let arr = selectExhibitionServiceData[i].selectServiceItems;
  1062. if(serviceTypeArr.length>0){
  1063. for(let j=0;j<serviceTypeArr.length;j++){
  1064. if(serviceTypeArr[j].itemType == "01"){
  1065. totalPrice += this.stackerCostRules(selectExhibitionServiceData[i],serviceTypeArr[j]);
  1066. // totalPrice += this.discount(selectExhibitionServiceData[i],serviceTypeArr[j]);
  1067. if(totalPrice==-1){
  1068. this.totalPrice = 0;
  1069. this.finalPrice = "0";
  1070. this.rulesShow = true;
  1071. return false;
  1072. }
  1073. }else if(serviceTypeArr[j].itemType == "02"){
  1074. }else if(serviceTypeArr[j].itemType == "03" || serviceTypeArr[j].itemType == "04" || serviceTypeArr[j].itemType == "05" || arr[j].itemType == "06"){
  1075. totalPrice += this.OtherCostRules(selectExhibitionServiceData[i],serviceTypeArr[j]);
  1076. if(totalPrice==-1){
  1077. this.totalPrice = 0;
  1078. this.finalPrice = "0";
  1079. this.rulesShow = true;
  1080. return false;
  1081. }
  1082. }
  1083. }
  1084. }
  1085. }
  1086. }
  1087. let quantityData = this.$refs.ref_quantitySelectGroup.formData;
  1088. if(quantityData.selectList.length>0){
  1089. totalPrice += this.TruckCostRules();
  1090. }
  1091. this.totalPrice = Math.ceil(totalPrice);
  1092. this.finalPrice = Math.ceil(Number(totalPrice)).toLocaleString();
  1093. },
  1094. setStackerDiscountQuota() {
  1095. this.stackerDiscountQuota = 0;
  1096. if (this.expenseRules) {
  1097. this.expenseRules.forEach(rule => {
  1098. if(rule.ItemType === "01" && rule.BoothNo > 0) {
  1099. this.stackerDiscountQuota = this.boothSelect / rule.BoothNo * rule.ItemNo;
  1100. }
  1101. });
  1102. }
  1103. },
  1104. // 7公噸以下優惠折扣
  1105. stackerDiscount(quantity, formData, serviceType) {
  1106. this.expenseRules.forEach( rule => {
  1107. if(rule.PreferentialScheme === "1") {
  1108. // check if serviceType is null
  1109. if (serviceType && serviceType.itemType) {
  1110. if (serviceType.itemType == rule.ItemType) {
  1111. if(formData.weight <= rule.TonNo) {
  1112. // if stacker discount still has quota
  1113. let quotaLeft = this.stackerDiscountQuota - this.stackerDiscountQuotaUsed;
  1114. for (let i = 0; i < quotaLeft; i++) {
  1115. if (quantity > 0) {
  1116. quantity -= 1;
  1117. this.stackerDiscountQuotaUsed += 1;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. })
  1125. return quantity;
  1126. },
  1127. // 堆高機
  1128. stackerCostRules(data1,data2){
  1129. let price = 0;
  1130. let tmpWeight = 0;//Number(data1.weight)/1000;
  1131. // 材積重 長x寬x高/6000 得到噸
  1132. if((data1.length =="" && data1.width=="" && data1.height=="") && data1.weight!=""){
  1133. tmpWeight = Number(data1.weight)/1000; // Number() => 將字串轉為數值!!
  1134. } //長(沒值),寬(沒值),高(沒值) 但重量(有值) => 總噸數 = 重量(公斤)/1000!!
  1135. else if((data1.length !="" && data1.width!="" && data1.height!="") && data1.weight==""){
  1136. tmpWeight = Number(data1.length)*Number(data1.width)*Number(data1.height)/6000/1000;
  1137. } //長(有值),寬(有值),高(有值) 但重量(沒值) => 總噸數 = 長*寬*高/6000/1000!!
  1138. //長(有值),寬(有值),高(有值) 但重量(有值) => 總噸數 = 長*寬*高/6000/1000!!
  1139. else if(data1.length !="" && data1.width!="" && data1.height!="" && data1.weight!=""){
  1140. let volumeWeight = Number(data1.length)*Number(data1.width)*Number(data1.height)/6000/1000;
  1141. // 比較誰大 (材積重與客戶給出的公斤重比較)!!
  1142. if(volumeWeight>Number(data1.weight)/1000){
  1143. tmpWeight = volumeWeight; //若材積重 > 客戶給的公斤重 => 總噸數 = 材積重!!
  1144. }else{
  1145. tmpWeight = Number(data1.weight)/1000; //若材積重 < 客戶給的公斤重 => 總噸數 = 客戶給的公斤重!!
  1146. }
  1147. }
  1148. //判斷 => 若長 > 1000 或 寬 > 1000 或 高 > 330,則顯示提醒dialog!!
  1149. if(Number(data1.length) > 1000 || Number(data1.width) > 1000 || Number(data1.height)>330){
  1150. this.dialog = true;
  1151. this.openTimer();
  1152. return -1;
  1153. }
  1154. //防呆 => 若總噸數為0,則總金額為0 !!
  1155. if(tmpWeight==0){
  1156. return price;
  1157. }
  1158. if(this.expenseRules.length>0){
  1159. for(let i=0;i<this.expenseRules.length;i++){
  1160. let subArr = this.expenseRules[i].StackerCostRules;
  1161. if(this.expenseRules[i].Guid == data2.package_id && subArr.length>0){
  1162. for(let j=0;j<subArr.length;j++){
  1163. // 需要判斷按數量還是重量
  1164. if(subArr[j].Weight_Min!="" && subArr[j].Weight_Max!=""){
  1165. if(Number(subArr[j].Weight_Min)<=tmpWeight && Number(subArr[j].Weight_Max)>=tmpWeight){
  1166. if(subArr[j].PricingMode=="N"){
  1167. price = subArr[j].Price;
  1168. }else{
  1169. price = subArr[j].Price*tmpWeight;
  1170. }
  1171. break;
  1172. }
  1173. }
  1174. }
  1175. break;
  1176. }
  1177. }
  1178. }
  1179. let num = (data1.quantity =="" || data1.quantity =="0") ? 0 : Number(data1.quantity);
  1180. // price = price*num;
  1181. // apply stacker discount
  1182. let quantityLeft = this.stackerDiscount(num, data1, data2);
  1183. price = price * quantityLeft;
  1184. return price;
  1185. },
  1186. TruckCostRules(){
  1187. let price = 0;
  1188. let quantityData = this.$refs.ref_quantitySelectGroup.formData;
  1189. let pickupServiceData = this.$refs.ref_pickupService.formData;
  1190. if(this.expenseRules.length>0){
  1191. let list = filterData({ItemType: '02'},this.expenseRules);
  1192. if(list.length>0){
  1193. if(list[0].TruckCostRules.length>0 && quantityData.selectList.length>0 && pickupServiceData.address1!="" && pickupServiceData.address1!="0"){
  1194. price += this.updateForData(quantityData.selectList,list[0].TruckCostRules,pickupServiceData.address1);
  1195. }
  1196. if(list[0].TruckMarkupByModel.length>0 && quantityData.truckList.length>0){
  1197. price += this.updateForData(quantityData.truckList,list[0].TruckMarkupByModel,null);
  1198. }
  1199. // 壓車費
  1200. if(list[0].TruckEscortCostRules.length>0 && pickupServiceData.delivery_type=="2" && quantityData.selectList.length>0
  1201. && list[0].EscortFreeCityID!="" && pickupServiceData.address1!="0"){
  1202. price += this.updateForData(quantityData.selectList,list[0].TruckEscortCostRules,list[0].EscortFreeCityID);
  1203. }
  1204. if(list[0].TruckHolidayPay.length>0 && pickupServiceData.select_date!=""){
  1205. let inWeekend = dateIsInWeekend(pickupServiceData.select_date);
  1206. if(inWeekend==5 && pickupServiceData.delivery_type=="2"){
  1207. price += this.updateForData(quantityData.selectList,list[0].TruckHolidayPay,null);
  1208. }else if(inWeekend==6 && pickupServiceData.delivery_type=="2"){
  1209. price += this.updateForData(quantityData.selectList,list[0].TruckHolidayPay,null)*2;
  1210. }else if(inWeekend==0 && pickupServiceData.delivery_type=="2"){
  1211. price += this.updateForData(quantityData.selectList,list[0].TruckHolidayPay,null);
  1212. }else if(inWeekend==6 && pickupServiceData.delivery_type=="1"){
  1213. price += this.updateForData(quantityData.selectList,list[0].TruckHolidayPay,null);
  1214. }else if(inWeekend==0 && pickupServiceData.delivery_type=="1"){
  1215. price += this.updateForData(quantityData.selectList,list[0].TruckHolidayPay,null);
  1216. }
  1217. }
  1218. }
  1219. }
  1220. return price;
  1221. },
  1222. updateForData(data1,data2,address1){
  1223. let price = 0;
  1224. if(data1.length>0 && data2.length>0){
  1225. for(let n=0;n<data1.length;n++){
  1226. let truckID = data1[n].id;
  1227. let num = data1[n].number;
  1228. for(let i=0;i<data2.length;i++){
  1229. if(data2[i].CityID!=undefined && data2[i].CityID!="" && data2[i].TruckID!=""){
  1230. if(data2[i].CityID==address1 && data2[i].TruckID == truckID){
  1231. price += data2[i].Price*num;
  1232. break;
  1233. }
  1234. }else if(data2[i].CityID ==undefined && data2[i].TruckID!=""){
  1235. if(data2[i].TruckID == truckID){
  1236. price += data2[i].Price*num;
  1237. break;
  1238. }
  1239. }
  1240. }
  1241. }
  1242. }
  1243. return price;
  1244. },
  1245. OtherCostRules(data1,data2){
  1246. console.log('OtherCostRules data1: ',data1)
  1247. console.log('OtherCostRules data2: ',data2)
  1248. let price = 0;
  1249. let tmpValue = 0;
  1250. if(data1.length =="" && data1.width=="" && data1.height==""){
  1251. return price;
  1252. }else{
  1253. tmpValue = Number(data1.length)*Number(data1.width)*Number(data1.height)/1000000;
  1254. }
  1255. if(Number(data1.length) > 1000 || Number(data1.width) > 1000 || Number(data1.height)>330){
  1256. this.dialog = true;
  1257. this.openTimer();
  1258. return -1;
  1259. }
  1260. if(this.expenseRules.length>0){
  1261. for(let i=0;i<this.expenseRules.length;i++){
  1262. let subArr = this.expenseRules[i].OtherCostRules;
  1263. if(this.expenseRules[i].Guid == data2.package_id && subArr.length>0){
  1264. for(let j=0;j<subArr.length;j++){
  1265. if(subArr[j].Unit_Min!=""){
  1266. if(Number(subArr[j].Unit_Min)<tmpValue){
  1267. price = subArr[j].Price*tmpValue;
  1268. }else{
  1269. price = subArr[j].Price*subArr[j].Unit_Min;
  1270. }
  1271. break;
  1272. }
  1273. }
  1274. break;
  1275. }
  1276. }
  1277. }
  1278. let num = (data1.quantity =="" || data1.quantity =="0") ? 0 : Number(data1.quantity);
  1279. price = price*num;
  1280. return price;
  1281. },
  1282. colseDialog(){
  1283. this.dialog = false;
  1284. },
  1285. openTimer(){
  1286. this.countdown = 15;
  1287. this.timer = setInterval(() => {
  1288. if (this.countdown > 0) {
  1289. this.countdown--;
  1290. } else {
  1291. clearInterval(this.timer);
  1292. this.dialog = false;
  1293. }
  1294. }, 1000);
  1295. },
  1296. },
  1297. };
  1298. </script>
  1299. <style lang="scss" scoped>
  1300. :deep() {
  1301. // .serviceDetails,
  1302. // .cancellationPolicy {
  1303. // p {
  1304. // margin-bottom: 6px;
  1305. // }
  1306. // }
  1307. }
  1308. .service-content {
  1309. .serviceDetails img {
  1310. width: 100%;
  1311. height: auto;
  1312. }
  1313. .fix-right {
  1314. position: fixed;
  1315. top: 120px;
  1316. right: 0 px;
  1317. max-width: 400px;
  1318. height: auto;
  1319. z-index: 100;
  1320. }
  1321. .title-icon-left {
  1322. background-position: left 0px center;
  1323. }
  1324. ul {
  1325. padding-left: 24px;
  1326. }
  1327. img {
  1328. // image-rendering: pixelated;
  1329. }
  1330. }
  1331. .seeMore {
  1332. &-hide {
  1333. position: relative;
  1334. max-height: 295px;
  1335. overflow: hidden;
  1336. &::after {
  1337. content: "";
  1338. display: block;
  1339. position: absolute;
  1340. background: url("~/assets/img/gradient_white.png") repeat-x left bottom;
  1341. width: 100%;
  1342. height: 130px;
  1343. left: 0;
  1344. bottom: 0;
  1345. z-index: 1;
  1346. transition: bottom 0.5s;
  1347. }
  1348. }
  1349. &-show {
  1350. position: relative;
  1351. max-height: 100%;
  1352. overflow: initial;
  1353. &::after {
  1354. display: none;
  1355. }
  1356. }
  1357. @media screen and (min-width: 1366px) {
  1358. position: relative;
  1359. display: flex;
  1360. align-items: center;
  1361. justify-content: center;
  1362. &::after {
  1363. content: "";
  1364. display: inline-block;
  1365. position: relative;
  1366. background-image: url("~/assets/svg/arrow-down-primary.svg");
  1367. background-position: center center;
  1368. background-repeat: no-repeat;
  1369. background-size: 100%;
  1370. width: 9px;
  1371. height: 6px;
  1372. margin-left: 16px;
  1373. }
  1374. &.open {
  1375. &::after {
  1376. transform: rotate(180deg);
  1377. }
  1378. }
  1379. }
  1380. }
  1381. .section-7 {
  1382. >div {
  1383. box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.25), 0px 1px 2px rgba(0, 0, 0, 0.1);
  1384. }
  1385. }
  1386. .tablecss{
  1387. line-height: 36px;
  1388. text-align: center;
  1389. color: #343434;
  1390. // border-radius: 10px;
  1391. }
  1392. table{
  1393. border: 1px solid #cecece;
  1394. border-collapse: separate;
  1395. border-radius: 10px;
  1396. text-align: center;
  1397. border-spacing: 0px;
  1398. // padding: 10px;
  1399. }
  1400. table thead{
  1401. border-radius: 10px;
  1402. }
  1403. th{
  1404. border: 1px solid #343434;
  1405. text-align: center;
  1406. }
  1407. td{
  1408. border-top: 1px solid #cecece;
  1409. text-align: center;
  1410. }
  1411. table thead>tr:first-of-type>th:first-of-type{
  1412. border-top-left-radius: 10px;
  1413. }
  1414. table thead>tr:first-of-type>th:last-of-type{
  1415. border-top-right-radius: 10px;
  1416. }
  1417. table tfoot>tr:last-of-type>td:first-of-type{
  1418. border-bottom-left-radius: 10px;
  1419. }
  1420. table tfoot>tr:last-of-type>td:last-of-type{
  1421. border-bottom-right-radius: 10px;
  1422. }
  1423. table::before{
  1424. border-radius: 10px;
  1425. }
  1426. // table tr:first-child th:first-child {
  1427. // border-top-left-radius: 10px; /* 设置table左下圆角 */
  1428. // }
  1429. // table tr:first-child th:last-child {
  1430. // border-top-right-radius: 10px; /* 设置table右下圆角 */
  1431. // }
  1432. table tr:last-child td:first-child {
  1433. border-bottom-left-radius: 10px; /* 设置table左下圆角 */
  1434. }
  1435. table tr:last-child td:last-child {
  1436. border-bottom-right-radius: 10px; /* 设置table右下圆角 */
  1437. }
  1438. </style>