123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- <route lang="json">
- {
- "style": {
- "navigationStyle": "custom"
- }
- }
- </route>
- <script setup lang="ts">
- import MomentItem from '@/components/moment-item.vue'
- import {
- createBrowseHistory,
- deleteCircle,
- getCircles,
- getDesignerInfo,
- getUserInfoById,
- updateDesignerInfo,
- shareCircle,
- getOwnBadges,
- } from '../../../core/libs/requests'
- import { useUserStore } from '../../../store'
- import { storeToRefs } from 'pinia'
- import { NetImages } from '../../../core/libs/net-images'
- import PageHelper from '@/components/page-helper.vue'
- import BottomAppBar from '@/components/bottom-app-bar.vue'
- import { useRouter } from '../../../core/utils/router'
- import NavbarEvo from '@/components/navbar-evo.vue'
- import { useMessage } from 'wot-design-uni'
- import { requestToast } from '../../../core/utils/common'
- import { ComponentExposed } from 'vue-component-type-helpers'
- import dayjs from 'dayjs'
- import wechatChannels from '@designer-hub/assets/src/libs/assets/wechatChannels'
- import { handleUpvoteClick } from '../../../core/libs/actions'
- import { usePermissions } from '../../../composables/permissions'
- import ImageEvo from '@/components/image-evo.vue'
- import more from '@designer-hub/assets/src/libs/assets/more'
- import qrCode from '@designer-hub/assets/src/libs/assets/qrCode'
- import { useShare } from '@/composables/share'
- const { features, clickByPermission } = usePermissions()
- const { shareAppMessage } = useShare()
- const { alert, confirm } = useMessage()
- const router = useRouter()
- const userStore = useUserStore()
- const { userInfo } = storeToRefs(userStore)
- const pageHelperRef = ref<ComponentExposed<typeof PageHelper>>()
- const id = ref()
- const isShared = ref(false)
- const tab = ref('2')
- const tabs = ref([
- { label: '案例', value: '2' },
- { label: '动态', value: '1' },
- // { label: '视频', value: '0' },
- ])
- const viewDuration = ref(0)
- const viewStartAt = ref<Date>()
- const { data: memberInfo, run: setMemberInfo } = useRequest(() => getUserInfoById(id.value), {
- initialData: {},
- })
- const { data: designerInfo, run: setDesignerInfo } = useRequest(() => getDesignerInfo(id.value), {
- initialData: {},
- })
- const { data: badges, run: setBadges } = useRequest(() => getOwnBadges({ userId: id.value }))
- const isOwn = computed(() => String(userInfo.value?.userId) === id.value)
- const skills = computed(() =>
- [
- {
- label: '从业年限',
- value: designerInfo.value?.serviceYears,
- show: designerInfo.value?.serviceYears,
- },
- {
- label: '客户',
- value: designerInfo.value?.serviceCustomerCount,
- show: designerInfo.value?.serviceCustomerCount,
- },
- {
- label: '设计费',
- value: `${designerInfo.value?.designFee}元/㎡`,
- show: designerInfo.value?.designFee,
- },
- ].filter(({ show }) => show),
- )
- const query = computed(() => ({
- circleType: tab.value,
- stylistId: id.value,
- }))
- const handleMomentDelete = async (id) => {
- confirm({
- title: '警告',
- msg: '确定要删除吗?',
- beforeConfirm: async ({ resolve }) => {
- await requestToast(() => deleteCircle(id))
- await pageHelperRef.value?.refresh()
- resolve(true)
- },
- })
- }
- const handleLike = async (options) => {
- await handleUpvoteClick({
- ...options,
- userId: userInfo.value.userId,
- userName: userInfo.value.nickname,
- })
- await pageHelperRef.value?.refresh()
- }
- const handle2Video = () => {
- try {
- uni.openChannelsUserProfile({ finderUserName: designerInfo.value?.videoNumber })
- } catch (e) {
- uni.showToast({
- title: '打开失败',
- icon: 'none',
- })
- }
- }
- const handleUnbundle = async () => {
- confirm({
- title: '警告',
- msg: '确定要解绑吗?',
- beforeConfirm: async ({ resolve }) => {
- await requestToast(
- () =>
- updateDesignerInfo({
- id: designerInfo.value.id,
- userId: designerInfo.value.userId,
- videoNumber: '',
- }),
- { success: true, successTitle: '解绑成功' },
- )
- await setDesignerInfo()
- resolve(true)
- },
- })
- }
- onLoad(async (query: { id: string; isShared?: string }) => {
- if (query.id) {
- id.value = query.id
- } else {
- id.value = userInfo.value.userId
- // memberInfo.value =
- }
- if (query.isShared) {
- isShared.value = true
- }
- if (!isOwn.value) {
- viewStartAt.value = new Date()
- }
- await Promise.all([setMemberInfo(), setBadges()])
- })
- onShow(async () => {
- await setDesignerInfo()
- })
- onUnload(async () => {
- if (!isOwn.value) {
- viewDuration.value = dayjs().diff(viewStartAt.value, 'seconds')
- const { data, code } = await createBrowseHistory({
- stylistId: id.value,
- bizType: 3,
- // bizId: '1',
- duration: viewDuration.value.toString(),
- })
- }
- })
- onShareAppMessage(shareAppMessage)
- onShareTimeline(() => ({}))
- defineExpose({
- navBarFixed: false,
- })
- </script>
- <template>
- <div class="flex-grow flex flex-col">
- <NavbarEvo transparent dark :isShowBack="!isShared"></NavbarEvo>
- <div class="relative">
- <!-- <wd-img width="100%" custom-class="aspect-[1.14/1]" /> -->
- <div class="aspect-[1.14/1]">
- <ImageEvo
- :src="designerInfo?.homePageUrl || NetImages.DesignerHomepageDefaultBg"
- mode="aspectFill"
- ></ImageEvo>
- </div>
- <div class="absolute bottom-0 left-0 right-0">
- <div class="bg-gradient-to-t from-black to-transparent">
- <div class="flex min-h-27 px-3.5 gap-3.5">
- <div class="w-18 h-18 border-white border border-solid rounded-full overflow-hidden">
- <wd-img
- width="100%"
- height="100%"
- :src="memberInfo?.avatar || NetImages.DefaultAvatar"
- ></wd-img>
- </div>
- <div class="pb-8 flex-1 overflow-hidden">
- <div class="flex items-center justify-between">
- <div class="text-white text-2xl font-normal font-['PingFang_SC'] leading-normal">
- {{ designerInfo.homePageName || memberInfo.nickname }}
- </div>
- <div
- v-if="isOwn && features.personalCode"
- class="flex items-center"
- @click="router.push(`/pages/mine/homepage/qr-code/index`)"
- >
- <wd-img width="22" height="22" :src="qrCode"></wd-img>
- <wd-icon name="chevron-right" color="white" size="16"></wd-icon>
- </div>
- </div>
- <div
- class="mt-2.5 flex gap-4 overflow-x-auto whitespace-nowrap"
- v-if="designerInfo?.personalIdentity != ''"
- >
- <template v-for="(it, i) in designerInfo?.personalIdentity?.split('、')" :key="i">
- <div
- class="inline-block h-6 px-2 bg-black/10 rounded-[30px] border border-solid border-white/60 justify-center items-center box-border inline-flex"
- >
- <div
- class="text-center text-white text-[10px] font-normal font-['PingFang_SC']"
- >
- {{ it }}
- </div>
- </div>
- </template>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="flex-grow flex flex-col bg-white rounded-t-2xl relative bottom-4 gap-5 px-3.5 pt-5">
- <div class="flex gap-4" v-if="skills?.length">
- <template v-for="(it, i) in skills" :key="i">
- <div>
- <span
- class="mr-0.575 text-black/90 text-base font-normal font-['PingFang_SC'] leading-[26.98px]"
- >
- {{ it.value }}
- </span>
- <span
- class="text-center text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[26.98px]"
- >
- {{ it.label }}
- </span>
- </div>
- <div v-if="i < skills?.length - 1" class="leading-[26.98px] text-black/60">|</div>
- </template>
- </div>
- <div class="text-black/80 text-sm font-normal font-['PingFang_SC'] leading-normal">
- {{ designerInfo?.designDesc }}
- </div>
- <div v-if="badges?.length" class="h-[42px] relative mr--3.5">
- <div
- class="h-full left-0 pl-20 pr-6 right-20 top-0 bottom-0 absolute bg-gradient-to-r from-[#ffe9e9] via-[#fff7f7] to-[#fff8f8] rounded-tl-md rounded-bl-md flex flex-col justify-center"
- >
- <div class="">
- <div class="flex items-center gap-4">
- <template v-for="(it, i) in badges?.slice(0, badges?.length > 5 ? 3 : 4)" :key="i">
- <!-- <div class="bg-[#fa9d3b]"> -->
- <wd-img width="26" mode="widthFix" :src="it.badgeYesObtainedImage"></wd-img>
- <!-- </div> -->
- </template>
- <div v-if="badges?.length > 5" class="flex">
- <wd-img custom-class="m-a" width="26" mode="widthFix" :src="more"></wd-img>
- </div>
- </div>
- </div>
- </div>
- <div
- class="w-[61px] h-2 left-[14px] top-[23px] absolute bg-gradient-to-r from-[#ff9e91] via-[#ffe5d7] to-[#ffe4d6] rounded-tl-[20px] rounded-bl-[20px]"
- ></div>
- <div
- class="w-12 h-[19px] left-[14px] top-[9px] absolute text-center text-black text-xs font-normal font-['PingFang_SC'] leading-normal"
- >
- 荣誉徽章
- </div>
- <div
- class="w-[76px] h-[30px] px-3 right-0 top-1.5 absolute bg-black/90 rounded-tl-[30px] rounded-bl-[30px] justify-center items-center gap-2.5 inline-flex"
- @click="
- router.push(`/pages/mine/honors/index?id=${id}${isShared ? '&isShared=true' : ''}`)
- "
- >
- <div class="text-center text-white text-xs font-normal font-['PingFang_SC']">
- 查看荣誉
- </div>
- </div>
- </div>
- <div
- v-if="isOwn || designerInfo?.videoNumber"
- class="bg-gradient-to-t from-[#fdf6ee] to-[#fefdfc] rounded-[10px] border border-[#fff4e6] border-solid flex items-center px-3.5 py-5 gap-3"
- @click="handle2Video"
- >
- <div>
- <div class="w-[37.01px] h-[37.01px] bg-[#fa9d3b] rounded-lg">
- <wd-img width="100%" height="100%" :src="wechatChannels"></wd-img>
- </div>
- <div
- v-if="isOwn && (designerInfo?.videoNumber ?? '') !== ''"
- @click.stop="handleUnbundle"
- >
- <div
- class="text-[#da7e1e] text-[9px] font-normal font-['PingFang_SC'] leading-normal flex items-center"
- >
- 解绑
- <wd-icon name="arrow-right" size="12"></wd-icon>
- </div>
- </div>
- </div>
- <div class="flex-1">
- <div class="text-black/90 text-sm font-normal font-['PingFang_SC'] leading-normal">
- {{ designerInfo?.videoNumber ? '个人视频号' : '视频号' }}
- </div>
- <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
- {{
- designerInfo?.videoNumber
- ? '案例分享,打造专属生活美学空间'
- : '您还没有关联视频号 , 快去关联吧~'
- }}
- </div>
- </div>
- <div>
- <div
- v-if="designerInfo?.videoNumber"
- class="text-[#e08e38] text-xs font-normal font-['PingFang_SC'] leading-normal"
- >
- 去看看
- </div>
- <div
- v-else
- class="h-7 px-4 py-0.5 bg-[#fa9d3b] rounded-[20px] justify-center items-center gap-2.5 inline-flex"
- @click.stop="router.push('/pages/mine/homepage/channels/index')"
- >
- <div
- class="text-center text-white text-xs font-normal font-['PingFang_SC'] leading-normal"
- >
- 去关联
- </div>
- </div>
- </div>
- </div>
- <div>
- <wd-tabs v-model="tab" custom-class="bg-transparent!">
- <template v-for="({ label, value }, index) in tabs" :key="index">
- <wd-tab :title="label" :name="value"></wd-tab>
- </template>
- </wd-tabs>
- <PageHelper
- ref="pageHelperRef"
- class="flex-grow flex flex-col bg-[#f6f6f6] mx--3.5"
- custom-class=""
- :request="getCircles"
- :query="query"
- >
- <template #default="{ source }">
- <div class="p-3.5 flex flex-col bg-[#f6f6f6] gap-3.5">
- <template v-for="it of source.list" :key="it.id">
- <view class="">
- <MomentItem
- :options="it"
- :is-own="userInfo.userId === it.stylistId"
- :is-shared="isShared"
- @delete="handleMomentDelete"
- @like="handleLike"
- ></MomentItem>
- </view>
- </template>
- </div>
- </template>
- </PageHelper>
- </div>
- </div>
- <BottomAppBar fixed placeholder>
- <div class="flex gap-7.5">
- <div class="flex-1" v-if="isOwn && !isShared">
- <wd-button block :round="false" @click="router.push(`/pages/mine/homepage/edit/index`)">
- 编辑
- </wd-button>
- </div>
- <div class="flex-1" v-if="isOwn && !isShared">
- <button
- v-if="features.shareMoment"
- class="p-0 after:b-none"
- block
- :round="false"
- :open-type="features.shareMoment ? 'share' : ''"
- :data-type="'homepage'"
- :data-share-content="{
- title: `${userInfo.nickname}: “${designerInfo.designDesc}”`,
- imageUrl: designerInfo.sharePageUrl,
- path: `/pages/mine/homepage/index?id=${id}&isShared=true`,
- }"
- :data-options="{
- homepageId: id,
- userId: userInfo.userId,
- }"
- >
- <wd-button block :round="false">分享</wd-button>
- </button>
- <template v-else>
- <!-- 1-->
- <wd-button block :round="false" @click="clickByPermission('share', () => {})">
- 分享
- </wd-button>
- </template>
- </div>
- <div class="flex-1" v-if="!isOwn || isShared">
- <wd-button
- block
- :round="false"
- @click="router.push(`/pages/mine/homepage/consult/index?id=${id}`)"
- >
- 预约咨询
- </wd-button>
- </div>
- </div>
- </BottomAppBar>
- </div>
- </template>
|