10 changed files with 187 additions and 236 deletions
@ -1,34 +0,0 @@ |
|||||
<template> |
|
||||
<el-button |
|
||||
v-loading.fullscreen.lock="fullscreenLoading" |
|
||||
type="primary" |
|
||||
@click="openFullScreen1" |
|
||||
> |
|
||||
As a directive |
|
||||
</el-button> |
|
||||
<el-button type="primary" @click="openFullScreen2"> As a service </el-button> |
|
||||
</template> |
|
||||
|
|
||||
<script lang="ts" setup> |
|
||||
import { ref } from 'vue' |
|
||||
import { ElLoading } from 'element-plus' |
|
||||
|
|
||||
const fullscreenLoading = ref(false) |
|
||||
const openFullScreen1 = () => { |
|
||||
fullscreenLoading.value = true |
|
||||
setTimeout(() => { |
|
||||
fullscreenLoading.value = false |
|
||||
}, 2000) |
|
||||
} |
|
||||
|
|
||||
const openFullScreen2 = () => { |
|
||||
const loading = ElLoading.service({ |
|
||||
lock: true, |
|
||||
text: 'Loading', |
|
||||
background: 'rgba(0, 0, 0, 0.7)', |
|
||||
}) |
|
||||
setTimeout(() => { |
|
||||
loading.close() |
|
||||
}, 2000) |
|
||||
} |
|
||||
</script> |
|
@ -0,0 +1,167 @@ |
|||||
|
<template> |
||||
|
<el-affix :offset="0" @change="onAffix"> |
||||
|
<div class="affix justify-between p-2 opacity-90 border-b-solid border-gray-200 border-b-1" :class="affix ? 'bg-white w-full' : 'hidden'"> |
||||
|
<div class="w-3/4 m-auto flex justify-between"> |
||||
|
<a class="goods-name text-xl font-bold cursor-pointer hover:text-gray-900">{{ goods?.goodsName }}</a> |
||||
|
<div class="affix-bar"> |
||||
|
<el-anchor :offset="100" direction="horizontal" :marker="false"> |
||||
|
<el-anchor-link :href="`#basic`"> |
||||
|
参数信息 |
||||
|
</el-anchor-link> |
||||
|
<el-anchor-link :href="`#photo`"> |
||||
|
图文详情 |
||||
|
</el-anchor-link> |
||||
|
<el-anchor-link :href="`#comment`"> |
||||
|
用户评价 |
||||
|
</el-anchor-link> |
||||
|
<el-anchor-link :href="`#buynow`"> |
||||
|
<el-button type="danger" size="small">立即购买</el-button> |
||||
|
</el-anchor-link> |
||||
|
</el-anchor> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-affix> |
||||
|
|
||||
|
<div id="buynow" class="flex flex-col w-full md:w-3/4 m-auto md:pt-[60px]" v-if="goods"> |
||||
|
|
||||
|
<Breadcrumb :data="goods" /> |
||||
|
|
||||
|
<div class="content bg-white rounded-xl"> |
||||
|
|
||||
|
<!-- <ProductShopInfo :data="goods?.merchant" />--> |
||||
|
|
||||
|
<div id="buynow" class="bg-white p-4 mt-4 flex gap-xl rounded-xl"> |
||||
|
<div class="goods-image flex gap-xl"> |
||||
|
<div class="gap-xs flex flex-col" v-if="goods?.files"> |
||||
|
<el-avatar v-for="item in JSON.parse(goods.files)" :src="item.url" size="large" shape="square" /> |
||||
|
</div> |
||||
|
<el-image :src="goods?.image" fit="contain" class="w-2xl h-2xl bg-gray-100 border-radius:30px"></el-image> |
||||
|
</div> |
||||
|
<div class="goods-info flex flex-col gap-xs"> |
||||
|
<div class="goods-name text-2xl">{{ goods.goodsName }}</div> |
||||
|
<div class="goods-price text-2xl red">¥{{ Number(goods?.salePrice) * Number(goods?.num) }}</div> |
||||
|
<div class="text-green-7">购买得积分</div> |
||||
|
<div class="text-gray-4">配送:无需配送</div> |
||||
|
<div class="text-gray-4">保障:假一赔四 退货包运费 极速退款</div> |
||||
|
<div class="text-gray-4">销量: {{ goods.sales }}</div> |
||||
|
<!-- <template v-for="spec in goods?.goodsSpecValue">--> |
||||
|
<!-- <div class="flex items-center">--> |
||||
|
<!-- <div class="text-gray-4">{{ spec.value }}:</div>--> |
||||
|
<!-- <el-radio-group v-model="goods.radio">--> |
||||
|
<!-- <el-radio v-for="(specValue,specIndex) in spec.detail" :label="specIndex" border>{{ specValue }}</el-radio>--> |
||||
|
<!-- </el-radio-group>--> |
||||
|
<!-- </div>--> |
||||
|
<!-- </template>--> |
||||
|
<div class="text-gray-4"> |
||||
|
已选中:{{ goods.radio }} |
||||
|
</div> |
||||
|
<div class="text-gray-4"> |
||||
|
数量: |
||||
|
<el-input-number v-model="goods.num" :min="1" :max="10" label="描述文字"></el-input-number> |
||||
|
</div> |
||||
|
<div class="py-5"> |
||||
|
<el-button-group size="large"> |
||||
|
<el-button type="danger">立即购买</el-button> |
||||
|
<el-button type="warning">加入购物车</el-button> |
||||
|
</el-button-group> |
||||
|
<el-button size="large" class="ml-3">收藏</el-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div id="basic" class="bg-white p-4 mt-4 flex gap-xl rounded-xl"> |
||||
|
<el-descriptions class="margin-top" title="参数信息" :column="1" border> |
||||
|
<el-descriptions-item label="品牌">websoft</el-descriptions-item> |
||||
|
<el-descriptions-item label="版本">2.0</el-descriptions-item> |
||||
|
<el-descriptions-item label="开发语言">Java、Vue3、Nuxt</el-descriptions-item> |
||||
|
<el-descriptions-item label="版本"> |
||||
|
<el-tag size="small">授权版</el-tag> |
||||
|
</el-descriptions-item> |
||||
|
<el-descriptions-item label="备注">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item> |
||||
|
</el-descriptions> |
||||
|
</div> |
||||
|
|
||||
|
<div id="photo" class="bg-white p-4 mt-4 flex gap-xl rounded-xl flex-col"> |
||||
|
<div class="font-bold">图文详情</div> |
||||
|
<div class="files flex flex-col w-3/4" v-if="goods?.files"> |
||||
|
<el-image v-for="item in JSON.parse(goods.files)" :src="item.url" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div id="comment" class="bg-white p-4 mt-4 flex gap-xl rounded-xl"> |
||||
|
<div class="font-bold">用户评价</div> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="!goods"> |
||||
|
<el-empty description="404 该商品找不到了222"></el-empty> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import type {ApiResult} from "~/api"; |
||||
|
import {useServerRequest} from "~/composables/useServerRequest"; |
||||
|
import type {Goods} from "~/api/shop/goods/model"; |
||||
|
import Breadcrumb from "~/components/Breadcrumb.vue"; |
||||
|
import type {Navigation} from "~/api/cms/navigation/model"; |
||||
|
import {useProductAffix} from "~/composables/configState"; |
||||
|
|
||||
|
const route = useRoute(); |
||||
|
|
||||
|
const affix = useProductAffix(); |
||||
|
|
||||
|
// 商品ID |
||||
|
const goodsId = ref(); |
||||
|
// 页面信息 |
||||
|
const form = ref<Navigation>(); |
||||
|
// 商品信息 |
||||
|
const goods = ref<Goods>(); |
||||
|
|
||||
|
const onAffix = (index: boolean) => { |
||||
|
affix.value = index; |
||||
|
} |
||||
|
|
||||
|
// 加载数据 |
||||
|
const reload = async () => { |
||||
|
// TODO 请求导航页面数据 |
||||
|
// const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath',{ |
||||
|
// query: { |
||||
|
// path: goodsId.value |
||||
|
// } |
||||
|
// }) |
||||
|
// if(nav.value?.data){ |
||||
|
// form.value = nav.value.data; |
||||
|
// } |
||||
|
|
||||
|
// TODO 获取商品详情 |
||||
|
console.log(goodsId.value,'sss') |
||||
|
const { data: info } = await useServerRequest<ApiResult<Goods>>('/shop/goods/' + goodsId.value) |
||||
|
|
||||
|
goods.value = info.value?.data; |
||||
|
console.log(goods.value) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
watch( |
||||
|
() => route.query.spm, |
||||
|
(spm) => { |
||||
|
console.log(spm) |
||||
|
// TODO 方案一:从spm参数提取商品ID |
||||
|
const spmValue = String(spm).split('.') |
||||
|
if(spmValue[5]){ |
||||
|
goodsId.value = spmValue[5]; |
||||
|
} |
||||
|
console.log(goodsId.value) |
||||
|
// TODO 方案二(优先级更高):从params获取商品ID |
||||
|
const { detail } = route.params |
||||
|
const split = String(detail).split('.'); |
||||
|
if(Number(split[0]) > 0){ |
||||
|
goodsId.value = split[0]; |
||||
|
} |
||||
|
|
||||
|
reload(); |
||||
|
}, |
||||
|
{ immediate: true } |
||||
|
); |
||||
|
</script> |
@ -1,117 +0,0 @@ |
|||||
<template> |
|
||||
<div class="flex flex-col w-full md:w-3/4 m-auto md:pt-[70px] pt-[60px]"> |
|
||||
|
|
||||
<Breadcrumb :data="form" /> |
|
||||
|
|
||||
<!-- <ProductShopInfo :data="goods?.merchant" />--> |
|
||||
|
|
||||
<div class="bg-white p-4 mt-4 flex gap-xl rounded-xl" v-if="goods"> |
|
||||
<div class="goods-image flex gap-xl"> |
|
||||
<div class="gap-xs flex flex-col"> |
|
||||
<el-avatar v-for="item in JSON.parse(goods.files)" :src="item.url" size="large" shape="square" /> |
|
||||
</div> |
|
||||
<el-image :src="goods.image" fit="contain" class="w-2xl h-2xl bg-gray-100 border-radius:30px"></el-image> |
|
||||
</div> |
|
||||
<div class="goods-info flex flex-col gap-xs"> |
|
||||
<div class="goods-name text-2xl">{{ goods.goodsName }}</div> |
|
||||
<div class="goods-price text-2xl red">¥{{ goods?.salePrice * goods?.num }}</div> |
|
||||
<div class="text-green-7">购买得积分</div> |
|
||||
<div class="text-gray-4">配送:无需配送</div> |
|
||||
<div class="text-gray-4">保障:假一赔四 退货包运费 极速退款</div> |
|
||||
<div class="text-gray-4">销量: {{ goods.sales }}</div> |
|
||||
<template v-for="spec in goods.goodsSpecValue"> |
|
||||
<div class="flex items-center"> |
|
||||
<div class="text-gray-4">{{ spec.value }}:</div> |
|
||||
<el-radio-group v-model="goods.radio"> |
|
||||
<el-radio v-for="(specValue,specIndex) in spec.detail" :label="specIndex" border>{{ specValue }}</el-radio> |
|
||||
</el-radio-group> |
|
||||
</div> |
|
||||
</template> |
|
||||
<div class="text-gray-4"> |
|
||||
已选中:{{ goods.radio }} |
|
||||
</div> |
|
||||
<div class="text-gray-4"> |
|
||||
数量: |
|
||||
<el-input-number v-model="goods.num" @change="handleChange" :min="1" :max="10" label="描述文字"></el-input-number> |
|
||||
</div> |
|
||||
<div class="py-5"> |
|
||||
<el-button-group size="large"> |
|
||||
<el-button type="danger">立即购买</el-button> |
|
||||
<el-button type="warning">加入购物车</el-button> |
|
||||
</el-button-group> |
|
||||
<el-button size="large" class="ml-3">收藏</el-button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="content p-4 bg-white mt-4 rounded-xl"> |
|
||||
<el-tabs v-model="activeName" :lazy="true" @tab-click="handleClick"> |
|
||||
<el-tab-pane label="参数信息" name="parameter"> |
|
||||
<el-descriptions class="margin-top" title="参数信息" :column="1" border> |
|
||||
<el-descriptions-item label="品牌">websoft</el-descriptions-item> |
|
||||
<el-descriptions-item label="版本">2.0</el-descriptions-item> |
|
||||
<el-descriptions-item label="开发语言">Java、Vue3、Nuxt</el-descriptions-item> |
|
||||
<el-descriptions-item label="版本"> |
|
||||
<el-tag size="small">授权版</el-tag> |
|
||||
</el-descriptions-item> |
|
||||
<el-descriptions-item label="备注">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item> |
|
||||
</el-descriptions> |
|
||||
</el-tab-pane> |
|
||||
<el-tab-pane label="图文详情" name="content"> |
|
||||
<div class="files flex flex-col w-3/4" v-if="goods?.files"> |
|
||||
<el-image v-for="item in JSON.parse(goods.files)" :src="item.url" /> |
|
||||
</div> |
|
||||
</el-tab-pane> |
|
||||
<el-tab-pane label="用户评价" name="reviews">用户评价</el-tab-pane> |
|
||||
</el-tabs> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div v-if="!form"> |
|
||||
<el-empty description="404 页面不存在"></el-empty> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script setup lang="ts"> |
|
||||
import type {ApiResult} from "~/api"; |
|
||||
import {useServerRequest} from "~/composables/useServerRequest"; |
|
||||
import type {Goods} from "~/api/shop/goods/model"; |
|
||||
import Breadcrumb from "~/components/Breadcrumb.vue"; |
|
||||
import type {Navigation} from "~/api/cms/navigation/model"; |
|
||||
|
|
||||
const route = useRoute(); |
|
||||
const { query, params } = route; |
|
||||
const { name: productName } = params; |
|
||||
const activeName = ref('parameter'); |
|
||||
const rate = ref(4); |
|
||||
|
|
||||
|
|
||||
// 页面信息 |
|
||||
const form = ref<Navigation>(); |
|
||||
// 商品信息 |
|
||||
const goods = ref<Goods>(); |
|
||||
|
|
||||
// TODO 请求导航页面数据 |
|
||||
const pathName = window.location.pathname; |
|
||||
console.log(pathName) |
|
||||
const split = pathName.split('/'); |
|
||||
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath',{ |
|
||||
query: { |
|
||||
path: pathName |
|
||||
} |
|
||||
}) |
|
||||
if(nav.value?.data){ |
|
||||
form.value = nav.value.data; |
|
||||
} |
|
||||
|
|
||||
// TODO 获取商品详情 |
|
||||
const { data: info } = await useServerRequest<ApiResult<Goods>>('/shop/goods/' + productName) |
|
||||
goods.value = info.value?.data; |
|
||||
goods.value.num = 1; |
|
||||
|
|
||||
|
|
||||
const handleClick = (tab, event) => { |
|
||||
console.log(tab, event); |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style scoped lang="scss"> |
|
||||
|
|
||||
</style> |
|
@ -1,75 +0,0 @@ |
|||||
<template> |
|
||||
<!-- Banner --> |
|
||||
<Banner :data="form" /> |
|
||||
|
|
||||
<div class="container"> |
|
||||
<div v-if="form" class="flex flex-col w-[1280px] m-auto"> |
|
||||
|
|
||||
<Breadcrumb :data="goods" /> |
|
||||
|
|
||||
<div class="w-7xl m-auto bg-white"> |
|
||||
<div class="title text-3xl text-center py-10">{{ form.name }}</div> |
|
||||
<div class="p-4 leading-7" v-html="form.content"> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div v-if="!form"> |
|
||||
<el-empty description="404 页面不存在"></el-empty> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script setup lang="ts"> |
|
||||
import type {Design} from "~/api/cms/design/model"; |
|
||||
import type {ApiResult} from "~/api"; |
|
||||
import {useServerRequest} from "~/composables/useServerRequest"; |
|
||||
import {useConfigInfo, useToken} from "~/composables/configState"; |
|
||||
import type {GoodsCategory} from "~/api/shop/goodsCategory/model"; |
|
||||
import Breadcrumb from "~/components/Breadcrumb.vue"; |
|
||||
|
|
||||
const route = useRoute(); |
|
||||
const { query, params } = route; |
|
||||
const pageName = window.location.pathname; |
|
||||
|
|
||||
console.log(window.location.pathname,'pageName') |
|
||||
|
|
||||
// 网站配置信息 |
|
||||
const config = useConfigInfo(); |
|
||||
const token = useToken(); |
|
||||
// 页面信息 |
|
||||
const form = ref<Design | any>(); |
|
||||
|
|
||||
// 请求数据 |
|
||||
const { data: design } = await useServerRequest<ApiResult<Design[]>>('/cms/design', {params: { |
|
||||
path: `${pageName}` |
|
||||
}}) |
|
||||
if (design.value) { |
|
||||
design.value?.data?.map((d,i) => { |
|
||||
if(i == 0){ |
|
||||
form.value = d; |
|
||||
console.log(d.name) |
|
||||
useHead({ |
|
||||
title: `${d.name} 网宿软件`, |
|
||||
meta: [{ name: "keywords", content: "Nuxt Vue SSR Typescript" }], |
|
||||
bodyAttrs: { |
|
||||
class: "page-container", |
|
||||
}, |
|
||||
script: [ |
|
||||
{ |
|
||||
children: "console.log('Hello World')", |
|
||||
}, |
|
||||
], |
|
||||
}); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
const { data: category } = useServerRequest<ApiResult<GoodsCategory>>('/shop/goods-category') |
|
||||
|
|
||||
console.log(category.value) |
|
||||
|
|
||||
</script> |
|
||||
|
|
||||
<style scoped lang="scss"> |
|
||||
|
|
||||
</style> |
|
Loading…
Reference in new issue