Commit 0810b91c by lijiabin

【需求 22261】 feat: 文章加入分享功能

parent 39f07557
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1780627614555" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5302" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M868.2 712.3c-53.8 0-101.3 27.4-129.3 69l-440-207.7c8.2-18.9 12.7-39.7 12.7-61.6 0-22-4.6-42.9-12.8-61.9L615 255.6c28.6 34.2 71.6 56.1 119.6 56.1 85.9 0 155.8-69.9 155.8-155.8S820.5 0 734.6 0 578.8 69.9 578.8 155.8c0 22 4.6 42.9 12.8 61.9L275.4 412.3c-28.6-34.2-71.6-56.1-119.6-56.1C69.9 356.2 0 426.1 0 512s69.9 155.8 155.8 155.8c48 0 91-21.8 119.6-56.1l444.1 209.7c-4.6 14.8-7.2 30.4-7.2 46.7 0 85.9 69.9 155.8 155.8 155.8S1024 954.1 1024 868.2s-69.9-155.9-155.8-155.9zM734.6 44.5c61.4 0 111.3 49.9 111.3 111.3S796 267.1 734.6 267.1s-111.3-49.9-111.3-111.3S673.2 44.5 734.6 44.5zM155.8 623.3c-61.4 0-111.3-49.9-111.3-111.3s49.9-111.3 111.3-111.3S267.1 450.6 267.1 512s-49.9 111.3-111.3 111.3z m712.4 356.2c-61.4 0-111.3-49.9-111.3-111.3s49.9-111.3 111.3-111.3 111.3 49.9 111.3 111.3-50 111.3-111.3 111.3z" p-id="5303" fill="currentColor"></path></svg>
...@@ -2,71 +2,53 @@ export * from './wxLogin' ...@@ -2,71 +2,53 @@ export * from './wxLogin'
export * from './initWXConfig' export * from './initWXConfig'
import * as ww from '@wecom/jssdk' import * as ww from '@wecom/jssdk'
/** const DEFAULT_SHARE_TITLE = '企业文化'
* 分享 const DEFAULT_SHARE_DESC = '点击查看详情'
*/ const DEFAULT_SHARE_IMAGE =
'https://res.mail.qq.com/node/ww/wwmng/style/images/index_share_logo$13c64306.png'
interface IShareWxOption { interface IShareWxOption {
/** 分享标题 */
title: string title: string
/** 分享链接 */ link?: string
link: string
/** 分享描述 */
desc?: string desc?: string
/** 分享封面 */
imgUrl?: string imgUrl?: string
} }
// export function wxShare(option: IShareWxOption) {
// const url = location.href.split('#')[0]
// option.link = url + '#' + option.link
// wx.invoke('shareAppMessage', option, function (res: any) {
// if (res.err_msg == 'openExistedChatWithMsg:ok') {
// }
// })
// }
export async function wxShare(option: IShareWxOption) { export async function wxShare(option: IShareWxOption) {
const url = location.href.split('#')[0]
await ww.shareAppMessage({ await ww.shareAppMessage({
title: '测试一下', title: option.title || DEFAULT_SHARE_TITLE,
desc: '让每个企业都有自己的微信', desc: option.desc || DEFAULT_SHARE_DESC,
link: url + '#' + option.link, link: option.link || location.href,
imgUrl: 'https://res.mail.qq.com/node/ww/wwmng/style/images/index_share_logo$13c64306.png', imgUrl: option.imgUrl || DEFAULT_SHARE_IMAGE,
}) })
} }
/**
* 企业微信获取部门人员SDK
* @params wxOption 企业微信 selectEnterpriseContact 的选项
* @params wxOption.fromDepartmentId 必填,表示打开的通讯录从指定的部门开始展示,-1表示自己所在部门开始, 0表示从最上层开始
* @params wxOption.mode 必填,选择模式,single表示单选,multi表示多选
* @params wxOption.type 必填,选择限制类型,指定department、user中的一个或者多个
* @params wxOption.selectedDepartmentIds 非必填,已选部门ID列表。用于多次选人时可重入,single模式下请勿填入多个id
* @params wxOption.selectedUserIds 非必填,已选用户ID列表。用于多次选人时可重入,single模式下请勿填入多个id
* @returns
*/
interface ISelectDepOrUser { interface ISelectDepOrUser {
err_msg: string err_msg: string
result: IResult result: IResult
} }
interface IResult { interface IResult {
userList: ISelectUser[] userList: ISelectUser[]
departmentList: ISelectDept[] departmentList: ISelectDept[]
} }
export interface ISelectUser { export interface ISelectUser {
id: string id: string
name: string name: string
avatar: string avatar: string
} }
export interface ISelectDept { export interface ISelectDept {
id: string id: string
name: string name: string
} }
export function selectDepOrUser(wxOption = {}): Promise<IResult> { export function selectDepOrUser(wxOption = {}): Promise<IResult> {
const defaultOption = { const defaultOption = {
fromDepartmentId: -1, fromDepartmentId: -1,
mode: 'single', // single multi mode: 'single',
type: ['user', 'department'], // 'user' 'department' type: ['user', 'department'],
// "selectedDepartmentIds": ['2', '3'],
// "selectedUserIds": ['lisi', 'lisi2']
} }
const option = { const option = {
...defaultOption, ...defaultOption,
......
...@@ -36,6 +36,8 @@ import type { Component } from 'vue' ...@@ -36,6 +36,8 @@ import type { Component } from 'vue'
import { useScrollTop } from '@/hooks' import { useScrollTop } from '@/hooks'
import { addOrCanceArticlelCollect, addOrCanceArticlelLike } from '@/api' import { addOrCanceArticlelCollect, addOrCanceArticlelLike } from '@/api'
import { push } from 'notivue' import { push } from 'notivue'
import { wxShare } from '@/utils/wxUtil'
const modelValue = defineModel<ArticleItemDto>('modelValue', { required: true }) const modelValue = defineModel<ArticleItemDto>('modelValue', { required: true })
const emit = defineEmits<{ const emit = defineEmits<{
...@@ -46,7 +48,7 @@ const { ScrollTopComp } = useScrollTop(window) ...@@ -46,7 +48,7 @@ const { ScrollTopComp } = useScrollTop(window)
interface StatItem { interface StatItem {
icon: Component icon: Component
count: number count: number | string
label: string label: string
active?: boolean active?: boolean
actionFn?: () => Promise<void> actionFn?: () => Promise<void>
...@@ -103,6 +105,24 @@ const stats = computed(() => { ...@@ -103,6 +105,24 @@ const stats = computed(() => {
emit('scrollToCommentBox') emit('scrollToCommentBox')
}, },
}, },
{
icon: <SvgIcon name="share" size="20"></SvgIcon>,
count: '分享',
label: '分享',
async actionFn() {
try {
await wxShare({
title: modelValue.value.title,
desc: [modelValue.value.createUserName, modelValue.value.region].filter(Boolean).join('——'),
imgUrl: modelValue.value.faceUrl || modelValue.value.imgUrl?.split(',').find(Boolean),
})
push.success('分享成功')
} catch (error) {
console.error(error)
push.error('分享失败')
}
},
},
] ]
}) })
......
...@@ -195,33 +195,43 @@ ...@@ -195,33 +195,43 @@
</div> </div>
<!-- 右侧数据 --> <!-- 右侧数据 -->
<div class="flex items-center gap-6 text-slate-500 text-sm select-none"> <div class="flex items-center gap-1 text-slate-500 text-base select-none">
<span <el-button
text
class="!ml-0 flex items-center gap-1 transition-colors hover:text-blue-500"
:class="{ '!text-blue-500': questionDetail?.hasPraised }"
@click="handleLikeArticle" @click="handleLikeArticle"
class="hover:text-slate-600 cursor-pointer transition-colors flex items-center gap-1"
> >
<el-icon> <el-icon size="17">
<svg-icon <svg-icon
:name="questionDetail?.hasPraised ? 'praise_fill' : 'praise'" :name="questionDetail?.hasPraised ? 'praise_fill' : 'praise'"
></svg-icon> ></svg-icon>
</el-icon> </el-icon>
<span :class="{ 'text-blue-500': questionDetail?.hasPraised }">{{ <span class="text-15px">{{ questionDetail?.praiseCount || 0 }}</span>
questionDetail?.praiseCount || 0 </el-button>
}}</span> <el-button
</span> text
<span class="!ml-0 flex items-center gap-1 transition-colors hover:text-blue-500"
:class="{ '!text-blue-500': questionDetail?.hasCollect }"
@click="handleCollectArticle" @click="handleCollectArticle"
class="hover:text-slate-600 cursor-pointer transition-colors flex items-center gap-1"
> >
<el-icon> <el-icon size="17">
<svg-icon <svg-icon
:name="questionDetail?.hasCollect ? 'collection_fill' : 'collection'" :name="questionDetail?.hasCollect ? 'collection_fill' : 'collection'"
></svg-icon> ></svg-icon>
</el-icon> </el-icon>
<span :class="{ 'text-blue-500': questionDetail?.hasCollect }">{{ <span class="text-15px">{{ questionDetail?.collectionCount || 0 }}</span>
questionDetail?.collectionCount || 0 </el-button>
}}</span> <el-button
</span> text
class="!ml-0 flex items-center gap-2 transition-colors hover:text-blue-500"
@click="handleShareQuestion"
>
<el-icon size="17">
<svg-icon name="share" size="15"></svg-icon>
</el-icon>
<span class="text-15px">分享</span>
</el-button>
</div> </div>
</div> </div>
</template> </template>
...@@ -460,6 +470,7 @@ import { storeToRefs } from 'pinia' ...@@ -460,6 +470,7 @@ import { storeToRefs } from 'pinia'
import { useNavigation, useScrollTop } from '@/hooks' import { useNavigation, useScrollTop } from '@/hooks'
import { useMessageBox } from '@/hooks' import { useMessageBox } from '@/hooks'
import { parseEmoji } from '@/utils/emoji' import { parseEmoji } from '@/utils/emoji'
import { wxShare } from '@/utils/wxUtil'
import { ArticleTypeEnum, BooleanFlag } from '@/constants' import { ArticleTypeEnum, BooleanFlag } from '@/constants'
import { push } from 'notivue' import { push } from 'notivue'
import { CommentSortTypeEnum } from '@/constants' import { CommentSortTypeEnum } from '@/constants'
...@@ -565,6 +576,22 @@ const handleCollectArticle = async () => { ...@@ -565,6 +576,22 @@ const handleCollectArticle = async () => {
push.success(`${questionDetail.value.hasCollect ? '收藏成功' : '取消收藏成功'}`) push.success(`${questionDetail.value.hasCollect ? '收藏成功' : '取消收藏成功'}`)
} }
const handleShareQuestion = async () => {
try {
await wxShare({
title: questionDetail.value.title,
desc: [questionDetail.value.createUserName, questionDetail.value.region]
.filter(Boolean)
.join('——'),
imgUrl: questionDetail.value.faceUrl || questionDetail.value.imgUrlList?.[0],
})
push.success('分享成功')
} catch (error) {
console.error(error)
push.error('分享失败')
}
}
const handleLikeAnswer = async (answer: CommentItemDto) => { const handleLikeAnswer = async (answer: CommentItemDto) => {
await addOrCancelCommentLike(answer.id) await addOrCancelCommentLike(answer.id)
answer.hasPraise = answer.hasPraise === BooleanFlag.YES ? BooleanFlag.NO : BooleanFlag.YES answer.hasPraise = answer.hasPraise === BooleanFlag.YES ? BooleanFlag.NO : BooleanFlag.YES
......
...@@ -184,6 +184,14 @@ ...@@ -184,6 +184,14 @@
</el-icon> </el-icon>
<span class="text-base">{{ videoDetail?.replyCount || 0 }}</span> <span class="text-base">{{ videoDetail?.replyCount || 0 }}</span>
</el-button> </el-button>
<el-button
text
class="flex items-center gap-2 transition-colors hover:text-blue-500"
@click="handleShareVideo"
>
<el-icon size="17"><svg-icon name="share" /></el-icon>
<span class="text-15px">分享</span>
</el-button>
<!-- 打赏 --> <!-- 打赏 -->
<el-button <el-button
text text
...@@ -348,6 +356,7 @@ import ActionMore from '@/components/common/ActionMore/index.vue' ...@@ -348,6 +356,7 @@ import ActionMore from '@/components/common/ActionMore/index.vue'
import SendMessageDialog from '@/components/common/SendMessageDialog/index.vue' import SendMessageDialog from '@/components/common/SendMessageDialog/index.vue'
import BackButton from '@/components/common/BackButton/index.vue' import BackButton from '@/components/common/BackButton/index.vue'
import { useNavigation } from '@/hooks' import { useNavigation } from '@/hooks'
import { wxShare } from '@/utils/wxUtil'
import { import {
ArticleTypeEnum, ArticleTypeEnum,
BooleanFlag, BooleanFlag,
...@@ -546,6 +555,20 @@ const handleReward = () => { ...@@ -546,6 +555,20 @@ const handleReward = () => {
rewardDialogRef.value?.open(videoDetail.value.id) rewardDialogRef.value?.open(videoDetail.value.id)
} }
const handleShareVideo = async () => {
try {
await wxShare({
title: videoDetail.value.title,
desc: [videoDetail.value.createUserName, videoDetail.value.region].filter(Boolean).join('——'),
imgUrl: videoDetail.value.faceUrl || videoDetail.value.imgUrl?.split(',').find(Boolean),
})
push.success('分享成功')
} catch (error) {
console.error(error)
push.error('分享失败')
}
}
onMounted(async () => { onMounted(async () => {
const { data } = await getArticleDetail(videoId) const { data } = await getArticleDetail(videoId)
videoDetail.value = data videoDetail.value = data
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment