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.

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