<template>
|
<PageLayout class="serciceDetail-page-wrapper" :title="detail?.name ?? ''" :need-auth="false">
|
<LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
|
<InfiniteLoading
|
commonMode
|
:refetch="refetch"
|
:isLoading="isLoading"
|
:isError="isError"
|
:showMoreText="false"
|
scrollViewClassName="common-infinite-scroll-list-no-padding"
|
>
|
<div class="serciceDetail-top-view">
|
<SquareView>
|
<nut-swiper
|
:auto-play="3000"
|
v-if="detail?.files?.length > 0"
|
class="serciceDetail-swiper"
|
>
|
<nut-swiper-item
|
v-for="(item, index) in detail.files"
|
:key="item"
|
class="serciceDetail-swiper-item"
|
>
|
<img
|
:src="setOSSLink(item)"
|
class="serciceDetail-swiper-item-img"
|
draggable="false"
|
/>
|
</nut-swiper-item>
|
</nut-swiper>
|
</SquareView>
|
<div class="serciceDetail-top-view-title-wrapper">
|
<div class="serciceDetail-price-wrapper">
|
<div class="serciceDetail-price">{{ toThousand(minPrice) }}</div>
|
<div class="serciceDetail-price-unit">元起</div>
|
</div>
|
<div class="serciceDetail-top-view-title">{{ detail?.name ?? '' }}</div>
|
</div>
|
</div>
|
|
<List class="serciceDetail-content-list">
|
<ListItem title="规格" @click="openSkuDialog()">
|
<template #extra>
|
<div>共{{ detail.specs?.length }}类</div>
|
</template>
|
</ListItem>
|
</List>
|
<ProTabs
|
v-model="tab"
|
name="serciceDetail-content-tab"
|
class="serciceDetail-content-tabs"
|
flexTitle
|
>
|
<ProTabPane :title="`服务详情`" pane-key="1">
|
<RichEditorContent :content="detail?.description ?? ''"></RichEditorContent>
|
</ProTabPane>
|
<ProTabPane :title="`客户评价`" pane-key="2">
|
<NoData />
|
</ProTabPane>
|
<ProTabPane :title="`相关推荐`" pane-key="3">
|
<NoData />
|
</ProTabPane>
|
</ProTabs>
|
</InfiniteLoading>
|
<Sku
|
v-model:visible="skuState.visible"
|
:sku="skuState.sku"
|
v-model:goods="skuState.goods"
|
@clickBtnOperate="clickBtnOperate"
|
>
|
</Sku>
|
<PageFooter>
|
<PageFooterAction
|
:icon="detail.isCollection ? IconAttentionActive : IconAttention"
|
text="收藏"
|
:isFlex="false"
|
@click="handleAttention"
|
></PageFooterAction>
|
<PageFooterAction
|
:icon="IconShare"
|
text="客服"
|
:isFlex="false"
|
:open-type="'contact'"
|
></PageFooterAction>
|
<PageFooterBtn type="primary" @click="openSkuDialog()">预约下单</PageFooterBtn>
|
</PageFooter>
|
</LoadingLayout>
|
</PageLayout>
|
</template>
|
|
<script setup lang="ts">
|
import { useStandardServiceDetail } from '@12333/hooks';
|
import Taro from '@tarojs/taro';
|
import * as standardOrderServices from '@12333/services/apiV2/standardOrder';
|
import * as standardServiceServices from '@12333/services/apiV2/standardService';
|
import { toThousand, setOSSLink, Message } from '@12333/utils';
|
import {
|
Sku,
|
Goods,
|
SkuItem,
|
SkuUtils,
|
List,
|
ListItem,
|
ProTabs,
|
ProTabPane,
|
SquareView,
|
} from '@12333/components';
|
import { useAccessLogin } from '@/hooks';
|
import IconShare from '@/assets/flexJob/icon-share.png';
|
import IconAttention from '@/assets/flexJob/icon-attention-lg.png';
|
import IconAttentionActive from '@/assets/flexJob/icon-attention-lg-active.png';
|
|
defineOptions({
|
name: 'serciceDetail',
|
});
|
|
const router = Taro.useRouter();
|
const id = router.params?.id ?? '';
|
|
const tab = ref('1');
|
|
const { isLoading, isError, detail, refetch, minPrice } = useStandardServiceDetail({
|
id,
|
onSuccess(res) {
|
skuState.sku = [
|
{
|
id: SkuUtils.DefaultSkuSpecId,
|
name: '规格',
|
list: res.specs.map((item, index) => ({
|
id: item.id,
|
name: item.name,
|
price: item.price,
|
active: index === 0,
|
disable: false,
|
})),
|
},
|
];
|
skuState.goods = {
|
skuId: SkuUtils.DefaultSkuSpecId,
|
price: toThousand(res.specs[0].price),
|
imagePath: setOSSLink(res.files[0]),
|
name: res.name,
|
};
|
},
|
});
|
|
const skuState = reactive({
|
visible: false,
|
sku: [] as SkuItem[],
|
goods: {} as Goods,
|
});
|
|
// 底部操作按钮触发
|
const clickBtnOperate = (op: { type: string; value: number }) => {
|
// addStandardOrder(op.value);
|
Message.warning('支付系统维护中,请稍后预约');
|
};
|
|
const openSkuDialog = () => {
|
skuState.visible = true;
|
};
|
|
const goAddStandardOrder = useAccessLogin((specNumber: number) => {
|
Taro.navigateTo({
|
url: `${RouterPath.addStandardOrder}?specNumber=${specNumber}`,
|
});
|
});
|
|
async function addStandardOrder(specNumber: number) {
|
try {
|
const spec = SkuUtils.getCurrentActiveSpec(skuState.sku);
|
let params: API.AddStandardOrderCommand = {
|
serviceId: detail.value.id,
|
serviceName: detail.value.name,
|
serviceCode: detail.value.code,
|
specId: spec.id,
|
specName: spec.name,
|
specPrice: detail.value.specs.find((x) => x.id === spec.id)?.price ?? 0,
|
specNumber: specNumber,
|
addressId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
|
name: detail.value.name,
|
contactPhoneNumber: 'string',
|
provinceCode: 'string',
|
provinceContent: 'string',
|
cityCode: 'string',
|
cityContent: 'string',
|
areaCode: 'string',
|
areaContent: 'string',
|
addressName: 'string',
|
addressDetail: 'string',
|
longitude: 0,
|
latitude: 0,
|
beginTime: '2025-12-24T08:25:08.372Z',
|
endTime: '2025-12-24T08:25:08.372Z',
|
supplierEnterpriseId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
|
enterpriseEmployeeIds: ['3fa85f64-5717-4562-b3fc-2c963f66afa6'],
|
remark: 'string',
|
payAccess: 1,
|
};
|
let res = await standardOrderServices.addStandardOrder(params);
|
} catch (error) {}
|
}
|
|
async function pay() {
|
try {
|
let params: API.PayStandardOrderCommand = {
|
id: '9e919af2-3d33-4eac-f6dc-08de429676b3',
|
};
|
let res = await standardOrderServices.payStandardOrder(params);
|
if (res) {
|
Taro.requestPayment({
|
timeStamp: res.timestamp,
|
nonceStr: res.nonceStr,
|
package: res.package,
|
signType: res.signType as any,
|
paySign: res.paySign,
|
});
|
}
|
} catch (error) {}
|
}
|
|
async function handleAttention() {
|
try {
|
let params: API.CollectionStandardServiceCommand = {
|
ids: [id],
|
isCollect: !detail.value.isCollection,
|
};
|
let res = await standardServiceServices.collectionStandardService(params);
|
if (res) {
|
refetch({ type: 'inactive' });
|
}
|
} catch (error) {}
|
}
|
</script>
|
|
<style lang="scss">
|
@import '@/styles/common.scss';
|
|
.serciceDetail-page-wrapper {
|
.serciceDetail-swiper {
|
width: 100%;
|
height: 100%;
|
|
.serciceDetail-swiper-item-img {
|
width: 100%;
|
height: 100%;
|
object-fit: cover;
|
/* 可选:调整图片裁剪的对齐方式(默认居中) */
|
object-position: center center;
|
}
|
}
|
|
.serciceDetail-top-view {
|
margin-bottom: 20px;
|
background-color: #fff;
|
|
.serciceDetail-top-view-title-wrapper {
|
padding: 24px boleGetCssVar('size', 'body-padding-h') 32px;
|
|
.serciceDetail-price-wrapper {
|
display: flex;
|
align-items: flex-end;
|
margin-bottom: 24px;
|
|
.serciceDetail-price {
|
font-weight: 600;
|
font-size: 48px;
|
color: #ff6414;
|
line-height: 52px;
|
}
|
|
.serciceDetail-price-unit {
|
font-weight: 400;
|
font-size: 28px;
|
color: #ff6414;
|
line-height: 40px;
|
}
|
}
|
|
.serciceDetail-top-view-title {
|
font-weight: 500;
|
font-size: 32px;
|
color: boleGetCssVar('text-color', 'primary');
|
line-height: 44px;
|
}
|
}
|
}
|
|
.serciceDetail-content-list {
|
margin-bottom: 20px;
|
}
|
}
|
</style>
|