Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 79 additions & 23 deletions spx-gui/src/components/project/sharing/ProjectDirectShare.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,32 @@
<PlatformSelector v-model="selectedPlatform" @update:model-value="handlePlatformChange" />
<div v-if="!selectedPlatform?.shareType.supportURL" class="share-content-row">
<Poster ref="posterCompRef" :project-data="props.projectData" />
<div class="qrcode side">
<img v-if="qrCodeData" :src="qrCodeData" alt="QR Code" />
<div v-else-if="selectedPlatform?.shareType.supportImage" class="loading-container">
<div class="loading-icon">⏳</div>
<span class="loading-text">{{ $t({ en: 'Generating QR code...', zh: '正在生成二维码...' }) }}</span>
</div>
<div v-else class="unsupported-container">
<div class="unsupport-icon">❌</div>
<span class="unsupported-text">{{ $t({ en: 'Unsupported', zh: '暂不支持' }) }}</span>

<div class="side-content">
<XiaohongshuShareGuide
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个跟 #2189 (comment) 这里提到的有关,我们定义 platform-share 模块的目标是,把每个平台自身的逻辑统一维护(在 platform-share),而不需要扩散到每一个具体的业务模块(如 ProjectDirectSharing, ProjectRecordingSharing, ProjectScreenshotSharing)中;因此在这里出现针对 xiaohongshu 的逻辑不是我们预期的

这里要想一下怎么把 <XiaohongshuShareGuide> 的逻辑也做进现有的 PlatformConfig 中(我们大概率需要扩展 PlatformConfig);它可能体现为一个 component(component 可以看成是返回一份 UI 描述的函数),也可能体现为返回结构化的 steps 信息或者 markdown 字符串的函数,也可能是别的

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个跟 #2189 (comment) 这里提到的有关,我们定义 platform-share 模块的目标是,把每个平台自身的逻辑统一维护(在 platform-share),而不需要扩散到每一个具体的业务模块(如 ProjectDirectSharing, ProjectRecordingSharing, ProjectScreenshotSharing)中;因此在这里出现针对 xiaohongshu 的逻辑不是我们预期的

这里要想一下怎么把 <XiaohongshuShareGuide> 的逻辑也做进现有的 PlatformConfig 中(我们大概率需要扩展 PlatformConfig);它可能体现为一个 component(component 可以看成是返回一份 UI 描述的函数),也可能体现为返回结构化的 steps 信息或者 markdown 字符串的函数,也可能是别的

明白,我去和海龙沟通改进一下

v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'"
type="poster"
:is-loading="handleDownloadPoster.isLoading.value"
@download="handleDownloadPoster.fn"
/>

<div v-else class="qrcode-section">
<img v-if="qrCodeData" :src="qrCodeData" alt="QR Code" />
<div v-else-if="selectedPlatform?.shareType.supportImage" class="loading-container">
<div class="loading-icon">⏳</div>
<span class="loading-text">{{ $t({ en: 'Generating QR code...', zh: '正在生成二维码...' }) }}</span>
</div>
<div v-else class="unsupported-container">
<div class="unsupport-icon">❌</div>
<span class="unsupported-text">{{ $t({ en: 'Unsupported', zh: '暂不支持' }) }}</span>
</div>
<button class="download-btn" @click="handleDownloadPoster.fn">
{{ $t({ en: 'Download Poster', zh: '下载海报' }) }}
</button>
</div>
<button class="download-btn" @click="handleDownloadPoster">
{{ $t({ en: 'Download Poster', zh: '下载海报' }) }}
</button>
</div>
</div>

<div v-else class="qrcode">
<img v-if="qrCodeData" :src="qrCodeData" alt="QR Code" />
</div>
Expand All @@ -63,6 +74,7 @@ import type { PlatformConfig } from './platform-share'
import type { ProjectData } from '@/apis/project'
import PlatformSelector from './PlatformSelector.vue'
import Poster from './ProjectPoster.vue'
import XiaohongshuShareGuide from './XiaohongshuShareGuide.vue'
import QRCode from 'qrcode'

const props = defineProps<{
Expand Down Expand Up @@ -106,7 +118,6 @@ async function getPlatformShareURL(platform: PlatformConfig) {
if (platform.shareType.supportURL && platform.shareFunction.shareURL) {
return platform.shareFunction.shareURL(projectSharingLink.value)
} else if (platform.shareType.supportImage && platform.shareFunction.shareImage) {
// 生成海报文件并传递给shareImage方法
if (posterCompRef.value == null) {
throw new Error('Poster component not ready')
}
Expand All @@ -128,22 +139,24 @@ function generateQRCodeDataUrl(url: string, color: string) {
})
}

const handleDownloadPoster = async () => {
if (!posterCompRef.value) return

try {
const handleDownloadPoster = useMessageHandle(
async () => {
if (!posterCompRef.value) {
throw new Error('Poster component is not available.')
}
const posterFile = await posterCompRef.value.createPoster()
const url = URL.createObjectURL(posterFile)
const link = document.createElement('a')
link.href = url
link.download = `${props.projectData.name}-poster.png`
document.body.appendChild(link)
link.click()
// 清理URL对象
document.body.removeChild(link)
URL.revokeObjectURL(url)
} catch (error) {
console.error('Failed to download poster:', error)
}
}
},
{ en: 'Failed to download poster', zh: '下载海报失败' },
{ en: 'Poster downloaded successfully', zh: '海报下载成功' }
)
</script>

<style scoped lang="scss">
Expand Down Expand Up @@ -177,7 +190,7 @@ const handleDownloadPoster = async () => {
display: flex;
align-items: stretch;
justify-content: center;
gap: 48px;
gap: 18px;
}

.qrcode.side {
Expand Down Expand Up @@ -233,4 +246,47 @@ const handleDownloadPoster = async () => {
transform: rotate(360deg);
}
}
.side-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 300px;
}

.download-btn {
width: 100%;
margin-top: 8px;
border-radius: 6px;
padding: 8px 16px;
border: 1px solid var(--ui-color-primary-main);
background: var(--ui-color-primary-main);
color: white;
cursor: pointer;
transition: all 0.2s ease;

&:hover:not(:disabled) {
background: var(--ui-color-primary-shade);
color: var(--ui-color-primary-main);
}

&:disabled {
background: var(--ui-color-hint-2);
border-color: var(--ui-color-hint-2);
cursor: not-allowed;
}
}

.qrcode-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;

img {
width: 100px;
height: 100px;
}
}
</style>
54 changes: 26 additions & 28 deletions spx-gui/src/components/project/sharing/ProjectRecordingSharing.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import PlatformSelector from './PlatformSelector.vue'
import XiaohongshuShareGuide from './XiaohongshuShareGuide.vue'
import { type RecordingData } from '@/apis/recording'
import { type PlatformConfig } from './platform-share'
import { universalUrlToWebUrl } from '@/models/common/cloud'
Expand Down Expand Up @@ -70,22 +71,13 @@ async function updateVideoSrc() {
// Handle platform selection change
function handlePlatformChange(platform: PlatformConfig) {
selectedPlatform.value = platform

// 检查是否需要显示下载提示
if (!platform.shareType.supportVideo && !platform.shareType.supportURL) {
throw new DefaultException({
en: `Please download the video to local and share it on ${platform.basicInfo.label.en}`,
zh: `请下载视频到本地,然后去${platform.basicInfo.label.zh}分享`
})
}

// QR code generation is handled automatically by watch, no need to call manually
}
Comment on lines 72 to 75

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The check for unsupported sharing types has been removed from handlePlatformChange. Previously, if a platform supported neither video nor URL sharing (e.g., Bilibili), an informative message was shown to the user. The current implementation falls back to generating a QR code for the project URL, which can be confusing since the selected platform may not support this sharing method. This check should be restored or replaced with a more user-friendly guide for such platforms, similar to the one implemented for Xiaohongshu.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The check for unsupported sharing types has been removed from handlePlatformChange. Previously, if a platform supported neither video nor URL sharing (e.g., Bilibili), an informative message was shown to the user. The current implementation falls back to generating a QR code for the project URL, which can be confusing since the selected platform may not support this sharing method. This check should be restored or replaced with a more user-friendly guide for such platforms, similar to the one implemented for Xiaohongshu.

这个暂时不用,因为抖音后面可以支持了,小红书直接显示不支持,B站后面如果确定了行或者不行,就也给出比较明确的提示


// Use useMessageHandle wrapped platform change handler
const handlePlatformChangeWithMessage = useMessageHandle(handlePlatformChange, {
en: 'Video sharing not supported',
zh: '视频分享暂不支持'
en: 'Platform selection failed',
zh: '平台选择失败'
})

// Get current recording URL
Expand Down Expand Up @@ -276,7 +268,14 @@ watch(
</div>
<div class="qr-section">
<div class="qr-section-inner">
<div class="qr-content">
<XiaohongshuShareGuide
v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'"
type="video"
:is-loading="handleDownloadClick.isLoading.value"
@download="handleDownloadClick.fn"
/>

<div v-else class="qr-content">
<div class="qr-code">
<img
v-if="qrCodeData"
Expand All @@ -296,16 +295,19 @@ watch(
$t({ en: 'Scan the code with the corresponding platform to share', zh: '用对应平台进行扫码分享' })
}}
</div>
</div>
<div class="action-buttons">
<button
class="download-btn"
:disabled="!videoSrc"
:loading="handleDownloadClick.isLoading.value"
@click="handleDownloadClick.fn"
>
{{ $t({ en: 'Download Video', zh: '下载视频' }) }}
</button>
<div class="action-buttons">
<button
class="download-btn"
:disabled="!videoSrc || handleDownloadClick.isLoading.value"
@click="handleDownloadClick.fn"
>
{{
handleDownloadClick.isLoading.value
? $t({ en: 'Downloading...', zh: '下载中...' })
: $t({ en: 'Download Video', zh: '下载视频' })
}}
</button>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -365,9 +367,10 @@ watch(
}

.share-main {
height: 100%;
display: flex;
align-items: stretch;
gap: 24px;
min-height: 330px;
}

.video-section {
Expand All @@ -376,7 +379,6 @@ watch(
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
gap: 16px;
}

Expand Down Expand Up @@ -453,7 +455,6 @@ watch(
flex-direction: column;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}

.rerecord-hint {
Expand Down Expand Up @@ -488,7 +489,6 @@ watch(
width: 100%;
display: flex;
justify-content: center;
margin-top: 24px;
padding: 0 20px;
}

Expand All @@ -500,7 +500,6 @@ watch(
align-items: stretch;
min-width: 220px;
min-height: 0;
padding: 16px;
}

.qr-section-inner {
Expand Down Expand Up @@ -592,7 +591,6 @@ watch(
.actions {
display: flex;
gap: 10px;
margin-top: 20px;
justify-content: center;
}

Expand Down
57 changes: 24 additions & 33 deletions spx-gui/src/components/project/sharing/ProjectScreenshotSharing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { ref, watch, nextTick } from 'vue'
import Poster from './ProjectPoster.vue'
import PlatformSelector from './PlatformSelector.vue'
import XiaohongshuShareGuide from './XiaohongshuShareGuide.vue'
import type { ProjectData } from '@/apis/project'
import type { PlatformConfig } from './platform-share'
import QRCode from 'qrcode'
Expand Down Expand Up @@ -179,7 +180,6 @@ watch(
<template>
<div v-if="visible" class="project-screenshot-sharing">
<div class="screenshot-sharing-content">
<!-- 分享内容 -->
<div class="share-content">
<div class="share-title">
{{ $t({ en: 'This screenshot is great, share it with friends!', zh: '截图这么棒,分享给好友吧!' }) }}
Expand All @@ -190,7 +190,14 @@ watch(
</div>
<div class="qr-section">
<div class="qr-section-inner">
<div class="qr-content">
<XiaohongshuShareGuide
v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'"
type="poster"
:is-loading="handleDownloadPoster.isLoading.value"
@download="handleDownloadPoster.fn"
/>

<div v-else class="qr-content">
<div class="qr-code">
<img
v-if="qrCodeData"
Expand All @@ -199,10 +206,9 @@ watch(
class="qr-image"
/>
<div v-else class="qr-placeholder">
<span>{{
isGeneratingQR
? $t({ en: 'Generating...', zh: '生成中...' })
: $t({ en: 'Select platform to generate QR code', zh: '选择平台生成二维码' })
<span v-if="isGeneratingQR">{{ $t({ en: 'Generating...', zh: '生成中...' }) }}</span>
<span v-else>{{
$t({ en: 'Select platform to generate QR code', zh: '选择平台生成二维码' })
}}</span>
</div>
</div>
Expand All @@ -211,18 +217,18 @@ watch(
$t({ en: 'Scan the code with the corresponding platform to share', zh: '用对应平台进行扫码分享' })
}}
</div>
<button
class="download-btn"
:disabled="handleDownloadPoster.isLoading.value"
@click="handleDownloadPoster.fn"
>
{{
handleDownloadPoster.isLoading.value
? $t({ en: 'Downloading...', zh: '下载中...' })
: $t({ en: 'Download Poster', zh: '下载海报' })
}}
</button>
</div>
<button
class="download-btn"
:disabled="handleDownloadPoster.isLoading.value"
@click="handleDownloadPoster.fn"
>
{{
handleDownloadPoster.isLoading.value
? $t({ en: 'Downloading...', zh: '下载中...' })
: $t({ en: 'Download Poster', zh: '下载海报' })
}}
</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -383,7 +389,7 @@ watch(

&:hover:not(:disabled) {
background: var(--ui-color-primary-shade);
color: var(--ui-color-primary-main); // hover时文字显示为主题色
color: var(--ui-color-primary-main);
}

&:disabled {
Expand All @@ -400,21 +406,6 @@ watch(
justify-content: center;
}

/*
.actions button {
padding: 8px 16px;
border: 1px solid #ccc;
border-radius: 4px;
background: #f0f0f0;
cursor: pointer;
transition: all 0.2s ease;

&:hover {
background: #e0e0e0;
}
}
*/

.cancel-btn {
padding: 8px 16px;
border: 1px solid var(--ui-color-red-main);
Expand Down
Loading
Loading