wupengfei
2 天以前 34b86673ec8fd29680a7679d3d8a597351a63f60
apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue
@@ -1,15 +1,114 @@
<template>
  <PageLayoutWithBg class="mineHire-page-wrapper" :title="'服务名'" :need-auth="false">
  <PageLayout class="serciceDetail-page-wrapper" :title="detail?.name ?? ''" :need-auth="false">
    <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
      <ContentScrollView style="background-color: transparent"> serciceDetail </ContentScrollView>
      <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>
  </PageLayoutWithBg>
  </PageLayout>
</template>
<script setup lang="ts">
import { useTaskInfo } from '@12333/hooks';
import InnerPage from './InnerPage.vue';
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',
@@ -18,11 +117,177 @@
const router = Taro.useRouter();
const id = router.params?.id ?? '';
const { isLoading, isError, detail, refetch } = useTaskInfo({
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>