ProductDetail.vue 12 KB
<template>
  <v-container>
    <div>
      <v-breadcrumbs divider="/" style="padding-top: 0">
        <template v-for="(item, index) in items" :key="index">
          <v-breadcrumbs-item
            :disabled="item.disabled"
            :href="item.href"
            :class="{
              'breadcrumb-disabled': item.disabled,
              'breadcrumb-active': !item.disabled,
            }"
          >
            {{ item.title }}
          </v-breadcrumbs-item>

          <!-- 添加分隔符,排除最后一个 item -->
          <span v-if="index < items.length - 1" class="breadcrumb-divider"
            >/</span
          >
        </template>
        <span class="breadcrumb-divider">/</span>
        <span style="margin-left: 5px">{{ info.name }}</span>
      </v-breadcrumbs>
    </div>
    <v-row class="mb-16 ma-0">
      <v-col cols="12" sm="5" class="carousel-container">
        <v-carousel
          class="tw-float-left tw-sticky tw-top-[16px]"
          height="450"
          v-model="slide"
          hide-delimiter-background
          style="top: 16px"
        >
          <v-carousel-item
            cover
            v-for="(slide, i) in info.productimageliststore"
            :src="slide.url"
            :key="i"
            :alt="info.name"
          >
          </v-carousel-item>
        </v-carousel>
      </v-col>
      <v-col cols="12" sm="7" class="table-container">
        <!-- <v-row class="bg-white mb-sm-10 text-h4 font-weight-medium">
          <v-col>{{ info.name }}</v-col>
        </v-row> -->
        <h1>{{ info.name }}</h1>
        <div class="tw-flex tw-flex-wrap">
          <div class="tw-w-1/2">
            <span class="tw-leading-[10px] tw-m-[16px]">
              Brand:{{ info.brandName }}
            </span>
          </div>
          <div class="tw-w-1/2 tw-mb-[12px]">
            <span class="tw-leading-[10px] tw-m-[16px]"
              >Product Model:{{ info.model }}</span
            >
          </div>
          <div class="tw-w-1/2 tw-mb-[12px]" v-if="info.basename1">
            <span class="tw-leading-[10px] tw-m-[16px]"
              >{{ info.basename1 }}:{{ info.basecore1 }}</span
            >
          </div>
          <div class="tw-w-1/2 tw-mb-[12px]" v-if="info.basename2">
            <span class="tw-leading-[10px] tw-m-[16px]"
              >{{ info.basename2 }}:{{ info.basecore2 }}</span
            >
          </div>
          <div class="tw-w-1/2 tw-mb-[12px]" v-if="info.basename3">
            <span class="tw-leading-[10px] tw-m-[16px]"
              >{{ info.basename3 }}:{{ info.basecore3 }}</span
            >
          </div>
        </div>
        <div
          class="tw-flex tw-flex-wrap"
          v-if="
            info.productAttributeList && info.productAttributeList.length > 0
          "
        >
          <div
            v-for="(attribute, index) in info.productAttributeList"
            :key="index"
            class="tw-w-1/2 tw-mb-[12px]"
          >
            <span class="tw-leading-[10px] tw-m-[16px]"
              >{{ attribute.name }}:{{ attribute.value }}</span
            >
          </div>
        </div>
        <!-- <v-table
          density="comfortable"
          class="table1 tw-mt-[32px]"
          v-if="info.ticketTypes?.length"
        > -->
        <v-table
          density="comfortable"
          class="table1 tw-mt-[32px] tw-overflow-x-auto"
          v-if="info.ticketTypes?.length"
        >
          <thead>
            <tr class="bg-grey-lighten-3">
              <th class="text-left headerBorder text-grey-darken-1">
                Product Name / Code
              </th>
              <th class="text-left headerBorder text-grey-darken-1">
                Specification and model
              </th>
              <th
                v-if="info.priceShow !== undefined && info.priceShow"
                class="text-left headerBorder text-grey-darken-1"
              >
                Price
              </th>
              <th class="text-left headerBorder text-grey-darken-1">Actions</th>
            </tr>
          </thead>
          <tbody>
            <tr
              class="tr"
              v-for="item in info.ticketTypes || []"
              :key="item.rank"
            >
              <td class="td text-grey-darken-4 font-weight-medium">
                {{ item.rank }}
              </td>
              <td class="td text-grey-darken-4 font-weight-medium">
                {{ item.typeName }}
              </td>
              <td v-if="item.priceShow" class="td">
                {{ item.price + " " + item.priceUnit }}
              </td>
              <td class="td">
                <v-btn
                  size="small"
                  color="blue-darken-1"
                  @click="router.push('/contact')"
                >
                  <!-- Quotation Inquiry -->
                  Quote
                </v-btn>
              </td>
            </tr>
          </tbody>
        </v-table>
        <!-- <v-dialog v-model="dialog" activator="parent" width="auto">
          <v-card> Contact us Email: contact@canrd.com QQ: 3003597584 / 2902385824 </v-card>
        </v-dialog> -->
      </v-col>
    </v-row>
    <div class="tw-pb-[64px]">
      <v-tabs
        class="tabs"
        v-model="tab"
        color="white"
        bg-color="#eeeeee"
        slider-color="blue-lighten-1"
        selected-class="active"
      >
        <v-tab :value="1">Product Details</v-tab>
        <v-tab :value="2">Specification</v-tab>
        <!-- <v-tab :value="3">商品百科</v-tab> -->
      </v-tabs>
      <v-window v-model="tab" class="tw-p-[24px]">
        <v-window-item key="1" :value="1">
          <div v-if="info.advantage" class="tw-mb-[24px]">
            <div class="text-h6">Advantage</div>
            <v-divider class="tw-mb-[12px]"></v-divider>
            <div v-html="info.advantage"></div>
          </div>
          <div v-if="info.physicalproperty" class="tw-mb-[24px]">
            <div class="text-h6">Physical Property</div>
            <v-divider class="tw-mb-[12px]"></v-divider>
            <div v-html="info.physicalproperty"></div>
          </div>
          <div v-if="info.storage" class="tw-mb-[24px]">
            <div class="text-h6">Storage</div>
            <v-divider class="tw-mb-[12px]"></v-divider>
            <div v-html="info.storage"></div>
          </div>
          <div v-if="info.introduction" class="tw-mb-[24px]">
            <div class="text-h6">Introduction</div>
            <v-divider class="tw-mb-[12px]"></v-divider>
            <div v-html="info.introduction"></div>
          </div>
          <div v-if="info.description" class="tw-mb-[24px]">
            <div class="text-h6">Description</div>
            <v-divider class="tw-mb-[12px]"></v-divider>
            <div v-html="info.description"></div>
          </div>
        </v-window-item>
        <v-window-item key="2" :value="2">
          <v-table density="compact" class="table2">
            <tbody>
              <tr
                class="tr"
                v-for="item in info.productAttributeList || []"
                :key="item.name"
              >
                <td class="td tw-w-[400px]">{{ item.name }}</td>
                <td class="td">{{ item.value }}</td>
              </tr>
            </tbody>
          </v-table>
        </v-window-item>
        <!-- <v-window-item key="3" :value="3"> 2 </v-window-item> -->
      </v-window>
    </div>
  </v-container>
</template>

<script setup lang="ts">
import type { Product, ProductImage } from "~/type";
import { onMounted, ref } from "vue";
import { useDialogStore } from "~/stores/dialog";
import { useRouter, useRoute } from "vue-router";
import { useRouteQuery } from "@/stores/route_query";

const route = useRoute();
const router = useRouter();
const routeQuery = useRouteQuery();
const dialogStore = useDialogStore();
const href1 = ref("/products");
const href2 = ref("/products");
// 定义单个 item 的接口
interface BreadcrumbItem {
  title: string; // 标题
  disabled: boolean; // 是否禁用
  href: string; // 链接地址
}

// 示例数据
const items = ref<BreadcrumbItem[]>([
  {
    title: "Products",
    disabled: false,
    href: "/products",
  },
  {
    title: "CATEGORY",
    disabled: false,
    href: href1.value,
  },
  {
    title: "DEVICE TYPE",
    disabled: false,
    href: href2.value,
  },
  {
    title: "FUNCTION",
    disabled: false,
    href: "/products",
  },
  // {
  //   title: "TITLE",
  //   disabled: false,
  //   href: "",
  // },
]);

const props = defineProps<{
  info: Product;
}>();
const info = props.info;
watchEffect(() => {
  if (routeQuery.categories) {
    if (!routeQuery.categories.includes("Energy materials")) {
      routeQuery.updateFunction("Not specified");
    }
    const categories = routeQuery.categories.split(",");
    const mainCategory = categories[0].trim(); // 取第一个值
    const subCategoryName = ref(
      categories[1] ? categories[1].trim() : "Not specified"
    ); // 取第二个值(如果存在)
    if (subCategoryName.value == "Accessories & fixtures") {
      subCategoryName.value = encodeURIComponent("Accessories & fixtures");
      items.value[2].title = "Accessories & fixtures";
    } else {
      items.value[2].title = subCategoryName.value;
    }
    items.value[1].title = mainCategory;
    items.value[1].href = href1.value + "?categories=" + mainCategory;
    href1.value = href1.value + "?categories=" + mainCategory;
    // items.value[1].title = subCategoryName.value;
    href2.value = href1.value + "," + subCategoryName.value;
    items.value[2].href = href1.value + "," + subCategoryName.value;
    if (routeQuery?.selectedFunction) {
      // items.value.push({
      //   title: routeQuery.selectedFunction,
      //   disabled: false,
      //   href: href2.value + "&function=" + routeQuery.selectedFunction,
      // });
      items.value[3].title = routeQuery.selectedFunction;
      items.value[3].href =
        href2.value + "&function=" + routeQuery.selectedFunction;
      // routeQuery.updateFunction(null);
    }
  } else if (info?.productCrumbsVO?.category1) {
    items.value[1].title = info.productCrumbsVO.category1;
    items.value[1].href =
      href1.value + "?categories=" + info.productCrumbsVO.category1;
    href1.value = href1.value + "?categories=" + info.productCrumbsVO.category1;
    if (info?.productCrumbsVO?.category2) {
      items.value[2].title = info.productCrumbsVO.category2;
      href2.value = href1.value + "," + info.productCrumbsVO.category2;
      items.value[2].href = href1.value + "," + info.productCrumbsVO.category2;
    }
    if (info?.productCrumbsVO?.function) {
      // items.value.push({
      //   title: info.productCrumbsVO.function,
      //   disabled: false,
      //   href: href2.value + "&function=" + info.productCrumbsVO.function,
      // });
      items.value[3].title = info.productCrumbsVO.function;
      items.value[3].href =
        href2.value + "&function=" + info.productCrumbsVO.function;
    }
  }
});
// onMounted(() => {
//   dialogStore.updateDialog(true)
// })

const tab = ref(0);
const slide = ref(0);
</script>

<style lang="scss" scoped>
.headerBorder {
  border-top: 3px solid #1f88e5 !important;
}

.tabs {
  border-bottom: 2px solid #1f88e5;
}

.active {
  background-color: #1086e8;
}

.td,
th {
  border: 1px solid #dcdcdc;
  border-right: 0px;
  border-bottom: 0px !important;
  height: 50px !important;

  &:last-child {
    border: 1px solid #dcdcdc;
  }
}

.tr:last-child {
  .td {
    border-bottom: 1px solid #dcdcdc !important;
  }
}

.tw-sticky {
  position: sticky;
}

.carousel-container {
  position: relative;
}

.table-container {
  overflow-x: auto; /* 防止表格超出页面宽度 */
}

.table1 {
  width: 100%;
  min-width: 600px; /* 设置表格最小宽度 */
}

.tr {
  border-bottom: 1px solid #e0e0e0; /* 表格行样式 */
}

.headerBorder {
  border-bottom: 2px solid #ccc; /* 表头边框 */
}

.text-grey-darken-4 {
  color: #333; /* 表格文字颜色 */
}
.breadcrumb-disabled {
  color: black;
  pointer-events: none; /* 禁用点击 */
  text-decoration: none; /* 移除链接样式 */
}

.breadcrumb-active {
  color: gray;
}
</style>