Browse Source

feat(app): 圈子支持分享,显示视频

EvilDragon 4 months ago
parent
commit
6aaf1f8170

+ 18 - 4
packages/app/src/components/moment-item.vue

@@ -4,6 +4,7 @@ import dayjs from 'dayjs'
 import { beforeNow } from '../utils/date-util'
 import Tag from './tag.vue'
 import { stringify } from 'qs'
+import { isImageOrVideo } from '@/core/utils/common'
 
 const props = defineProps({
   options: {
@@ -50,15 +51,18 @@ const props = defineProps({
   },
 })
 const imgClass = ref('')
+const isVideo = ref(false)
 const toDetail = () => {
   uni.navigateTo({
     url: `/pages/home/moment/index?${stringify({ id: props.options.id })}`,
   })
 }
-
 onMounted(async () => {
   // console.log('加载')
-  if (props.options.bannerUrls?.length === 1) {
+  if (
+    props.options.bannerUrls?.length === 1 &&
+    isImageOrVideo(props.options.bannerUrls[0]) === 'image'
+  ) {
     const { width, height } = await uni.getImageInfo({
       src: props.options.bannerUrls[0],
     })
@@ -69,6 +73,12 @@ onMounted(async () => {
       imgClass.value = 'w-[44vw]'
     }
   }
+  if (
+    props.options.bannerUrls?.length === 1 &&
+    isImageOrVideo(props.options.bannerUrls[0]) === 'video'
+  ) {
+    isVideo.value = true
+  }
 })
 </script>
 <template>
@@ -87,7 +97,11 @@ onMounted(async () => {
       <view class="flex-1"></view>
       <view>{{ beforeNow(dayjs(props.options.createTime).toDate()) }}</view>
     </view>
+    <div v-if="isVideo" class="aspect-[1.64/1] rounded-lg overflow-hidden my-6" @click.stop>
+      <video class="w-full h-full" :src="options.bannerUrls[0]"></video>
+    </div>
     <view
+      v-if="!isVideo"
       :class="[
         props.options.bannerUrls?.length > 1 ? 'grid grid-cols-3 grid-gap-1' : 'w-full',
         'my-6',
@@ -111,10 +125,10 @@ onMounted(async () => {
         </view>
       </template>
     </view>
-    <view class="text-[rgba(0,0,0,0.85)] text-4 font-400 line-height-2.5 my-1">
+    <view class="text-[rgba(0,0,0,0.85)] text-4 font-400 my-1">
       {{ props.options.circleDesc }}
     </view>
-    <view class="my-5.5 flex gap-3.5">
+    <view class="my-5.5 flex flex-wrap gap-3.5">
       <template v-if="props.options.tagName !== ''">
         <template v-for="it of props.options.tagName?.split(',')" :key="it">
           <Tag>{{ it }}</Tag>

+ 1 - 0
packages/app/src/core/libs/requests.ts

@@ -182,6 +182,7 @@ export const createCircle = (data: Partial<Circle>) =>
   httpPost<any>('/app-api/member/circle/create', data)
 export const getCircle = (id: string) =>
   httpGet<Partial<CircleRes>>('/app-api/member/circle/get', { id })
+export const shareCircle = (id: string) => httpGet('/app-api/member/circle/share', { id })
 export const createCircleUpvote = (data: { circleId: number; userId: number; userName: string }) =>
   httpPost('/app-api/member/circle-upvote/create', data)
 export const cancelCircleUpvote = (query: { id: string }) =>

+ 10 - 0
packages/app/src/core/utils/common.ts

@@ -1,3 +1,13 @@
 export const handleCall = (phone: string) => {
   uni.makePhoneCall({ phoneNumber: phone })
 }
+export const isImageOrVideo = (url) => {
+  const ext = url.split('.').pop().toLowerCase()
+  if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)) {
+    return 'image'
+  } else if (['mp4', 'avi', 'mov', 'mkv', 'webm', 'flv'].includes(ext)) {
+    return 'video'
+  } else {
+    return 'unknown'
+  }
+}

+ 33 - 13
packages/app/src/pages/home/moment/index.vue

@@ -1,7 +1,10 @@
-<route lang="yaml">
-style:
-  navigationBarTitleText: '详情'
-  navigationBarBackgroundColor: '#fff'
+<route lang="json">
+{
+  "style": {
+    "navigationBarTitleText": "详情",
+    "navigationBarBackgroundColor": "#fff"
+  }
+}
 </route>
 <script setup lang="ts">
 import Tag from '@/components/tag.vue'
@@ -9,7 +12,7 @@ import {
   createCircleReview,
   getCircle,
   getCircleReviews,
-  getMoment,
+  shareCircle,
 } from '../../../core/libs/requests'
 import { handleUpvoteClick } from '../../../core/libs/actions'
 import { thumbsUp } from '../../../core/libs/svgs'
@@ -17,6 +20,7 @@ import CommentItem from '../components/comment-item.vue'
 import AvatarGroupCasual from '@/components/avatar-group-casual/avatar-group-casual.vue'
 import { useUserStore } from '../../../store'
 import { storeToRefs } from 'pinia'
+import { isImageOrVideo } from '@/core/utils/common'
 
 const userStore = useUserStore()
 const { userInfo } = storeToRefs(userStore)
@@ -34,6 +38,7 @@ const current = ref(0)
 const swiperSizes = ref()
 const swiperStyle = ref()
 const reviewContent = ref('')
+const isVideo = ref(false)
 const handleChange = ({ detail: { current } }) => {
   swiperStyle.value = {
     height: swiperSizes.value[current].height + 'px',
@@ -41,6 +46,10 @@ const handleChange = ({ detail: { current } }) => {
 }
 const setSwiperStyle = async () => {
   const { screenWidth } = await uni.getSystemInfo()
+  if (data.value.bannerUrls.length === 1 && isImageOrVideo(data.value.bannerUrls[0]) === 'video') {
+    isVideo.value = true
+    return
+  }
   swiperSizes.value = (
     await Promise.all(data.value.bannerUrls.map((src) => uni.getImageInfo({ src })))
   ).map(({ width, height }) => ({ width: screenWidth, height: height / (width / screenWidth) }))
@@ -69,13 +78,17 @@ onLoad(async (query: { id: string }) => {
   await runGetReviews()
   await setSwiperStyle()
 })
+onShareAppMessage(async () => {
+  await shareCircle(id.value)
+  return { title: data.value?.circleDesc }
+})
 </script>
 <template>
   <view class="bg-white flex-grow">
     <!-- <div class="my-4 text-black/90 text-lg font-normal font-['PingFang SC'] leading-[10.18px]">
       {{ data?.content }}
     </div> -->
-    <template v-if="swiperSizes">
+    <template v-if="swiperSizes && !isVideo">
       <swiper :style="swiperStyle" @change="handleChange">
         <template v-for="it of data?.bannerUrls" :key="it">
           <swiper-item>
@@ -84,6 +97,9 @@ onLoad(async (query: { id: string }) => {
         </template>
       </swiper>
     </template>
+    <template v-if="isVideo">
+      <video width="100%" class="w-full aspect-[1.64/1]" :src="data?.bannerUrls[0]"></video>
+    </template>
     <!-- <wd-swiper
       v-model="current"
       custom-class="my-1"
@@ -97,7 +113,7 @@ onLoad(async (query: { id: string }) => {
       <div class="text-black/90 text-base font-normal font-['PingFang SC'] leading-[10.18px]">
         {{ data?.circleDesc }}
       </div>
-      <view class="my-5.5 flex gap-3.5">
+      <view class="my-5.5 flex gap-3.5 flex-wrap">
         <!-- <TiltedButton>按钮</TiltedButton> -->
         <template v-if="data?.tagName !== ''">
           <template v-for="it of data?.tagName?.split(',')" :key="it">
@@ -185,12 +201,16 @@ onLoad(async (query: { id: string }) => {
         ></wd-input>
       </div>
       <view class="flex justify-around flex-1">
-        <view
-          class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
-        >
-          <wd-img width="15" height="15" src="/static/svgs/share.svg"></wd-img>
-          <view class="">{{ data?.shareCount }}</view>
-        </view>
+        <div>
+          <button open-type="share" class="bg-transparent! p-0!">
+            <view
+              class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
+            >
+              <wd-img width="15" height="15" src="/static/svgs/share.svg"></wd-img>
+              <view class="">{{ data?.shareCount || 0 }}</view>
+            </view>
+          </button>
+        </div>
         <view
           class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
         >

+ 3 - 0
packages/app/src/pages/publish/moment/index.vue

@@ -12,7 +12,9 @@ import { useToast } from 'wot-design-uni'
 import { CircleType, DictType } from '../../../core/models/moment'
 import DataForm from '@/components/data-form.vue'
 import { zipToObject } from 'radash'
+import { useRouter } from '../../../core/utils/router'
 
+const router = useRouter()
 const userStore = useUserStore()
 const { userInfo } = storeToRefs(userStore)
 const { error } = useToast()
@@ -50,6 +52,7 @@ const handleSubmit = async () => {
   uni.showToast({
     title: '发布成功',
   })
+  router.back()
 }
 const updateTagName = (tagNames: string[]) => {
   if (tagNames.length === 0) {