Skip to content

Commit b042d99

Browse files
committed
refactor(sharing): extract XiaohongshuShareGuide into reusable component
1 parent 098cae4 commit b042d99

File tree

4 files changed

+209
-474
lines changed

4 files changed

+209
-474
lines changed

spx-gui/src/components/project/sharing/ProjectDirectShare.vue

Lines changed: 7 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -35,48 +35,12 @@
3535
<Poster ref="posterCompRef" :project-data="props.projectData" />
3636

3737
<div class="side-content">
38-
<div v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'" class="xiaohongshu-guide">
39-
<h3>📱 {{ $t({ en: 'How to share to Xiaohongshu?', zh: '如何分享到小红书?' }) }}</h3>
40-
41-
<div class="guide-steps">
42-
<div class="step">
43-
<span class="step-number">1️⃣</span>
44-
<div class="step-content">
45-
<strong>{{ $t({ en: 'Download Poster', zh: '下载海报' }) }}</strong>
46-
<p>{{ $t({ en: 'Click the button below to save poster', zh: '点击下方按钮保存海报到设备' }) }}</p>
47-
</div>
48-
</div>
49-
50-
<div class="step">
51-
<span class="step-number">2️⃣</span>
52-
<div class="step-content">
53-
<strong>{{ $t({ en: 'Open Xiaohongshu App', zh: '打开小红书APP' }) }}</strong>
54-
<p>{{ $t({ en: 'Tap "+" to create new post', zh: '点击"+"号发布新笔记' }) }}</p>
55-
</div>
56-
</div>
57-
58-
<div class="step">
59-
<span class="step-number">3️⃣</span>
60-
<div class="step-content">
61-
<strong>{{ $t({ en: 'Upload & Share', zh: '上传分享' }) }}</strong>
62-
<p>{{ $t({ en: 'Select the downloaded poster to share', zh: '选择刚下载的海报进行分享' }) }}</p>
63-
</div>
64-
</div>
65-
</div>
66-
67-
<div class="api-notice">
68-
<span class="notice-icon">💡</span>
69-
<p>
70-
{{
71-
$t({ en: 'Manual upload required due to API limitations', zh: '由于API限制,需要手动上传,感谢理解' })
72-
}}
73-
</p>
74-
</div>
75-
76-
<button class="download-btn primary" :disabled="!posterCompRef" @click="handleDownloadPoster">
77-
{{ $t({ en: 'Download Poster', zh: '下载海报' }) }}
78-
</button>
79-
</div>
38+
<XiaohongshuShareGuide
39+
v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'"
40+
type="poster"
41+
:is-loading="false"
42+
@download="handleDownloadPoster"
43+
/>
8044

8145
<div v-else class="qrcode-section">
8246
<img v-if="qrCodeData" :src="qrCodeData" alt="QR Code" />
@@ -110,6 +74,7 @@ import type { PlatformConfig } from './platform-share'
11074
import type { ProjectData } from '@/apis/project'
11175
import PlatformSelector from './PlatformSelector.vue'
11276
import Poster from './ProjectPoster.vue'
77+
import XiaohongshuShareGuide from './XiaohongshuShareGuide.vue'
11378
import QRCode from 'qrcode'
11479
11580
const props = defineProps<{
@@ -286,86 +251,6 @@ const handleDownloadPoster = async () => {
286251
min-width: 300px;
287252
}
288253
289-
.xiaohongshu-guide {
290-
width: 100%;
291-
max-width: 320px;
292-
padding: 10px;
293-
background: linear-gradient(135deg, #fff5f5 0%, #ffeef0 100%);
294-
border-radius: 12px;
295-
border: 2px solid #ffb3ba;
296-
box-shadow: 0 4px 12px rgba(255, 0, 53, 0.1);
297-
298-
h3 {
299-
margin: 0 0 16px 0;
300-
font-size: 16px;
301-
font-weight: 600;
302-
color: #ff0035;
303-
text-align: center;
304-
}
305-
}
306-
307-
.guide-steps {
308-
margin-bottom: 16px;
309-
310-
.step {
311-
display: flex;
312-
align-items: flex-start;
313-
margin-bottom: 12px;
314-
315-
&:last-child {
316-
margin-bottom: 0;
317-
}
318-
}
319-
320-
.step-number {
321-
font-size: 16px;
322-
margin-right: 10px;
323-
flex-shrink: 0;
324-
line-height: 1.2;
325-
}
326-
327-
.step-content {
328-
flex: 1;
329-
330-
strong {
331-
display: block;
332-
font-size: 13px;
333-
font-weight: 600;
334-
color: #333;
335-
margin-bottom: 2px;
336-
}
337-
338-
p {
339-
font-size: 12px;
340-
color: #666;
341-
margin: 0;
342-
line-height: 1.3;
343-
}
344-
}
345-
}
346-
347-
.api-notice {
348-
display: flex;
349-
align-items: flex-start;
350-
margin-bottom: 16px;
351-
padding: 10px 12px;
352-
background: rgba(255, 255, 255, 0.8);
353-
border-radius: 8px;
354-
355-
.notice-icon {
356-
font-size: 14px;
357-
margin-right: 6px;
358-
flex-shrink: 0;
359-
}
360-
361-
p {
362-
margin: 0;
363-
font-size: 11px;
364-
color: #888;
365-
line-height: 1.4;
366-
}
367-
}
368-
369254
.download-btn {
370255
width: 100%;
371256
margin-top: 8px;
@@ -389,30 +274,6 @@ const handleDownloadPoster = async () => {
389274
}
390275
}
391276
392-
.download-btn.primary {
393-
width: 100%;
394-
background: linear-gradient(135deg, #ff0035 0%, #ff4d6d 100%);
395-
color: white;
396-
border: none;
397-
padding: 12px 20px;
398-
border-radius: 8px;
399-
font-size: 14px;
400-
font-weight: 600;
401-
cursor: pointer;
402-
transition: all 0.3s ease;
403-
404-
&:hover:not(:disabled) {
405-
background: linear-gradient(135deg, #e6002f 0%, #ff3366 100%);
406-
transform: translateY(-1px);
407-
box-shadow: 0 4px 12px rgba(255, 0, 53, 0.3);
408-
}
409-
410-
&:disabled {
411-
opacity: 0.6;
412-
cursor: not-allowed;
413-
}
414-
}
415-
416277
.qrcode-section {
417278
display: flex;
418279
flex-direction: column;

spx-gui/src/components/project/sharing/ProjectRecordingSharing.vue

Lines changed: 7 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import { ref, computed, watch } from 'vue'
33
import PlatformSelector from './PlatformSelector.vue'
4+
import XiaohongshuShareGuide from './XiaohongshuShareGuide.vue'
45
import { type RecordingData } from '@/apis/recording'
56
import { type PlatformConfig } from './platform-share'
67
import { universalUrlToWebUrl } from '@/models/common/cloud'
@@ -267,59 +268,12 @@ watch(
267268
</div>
268269
<div class="qr-section">
269270
<div class="qr-section-inner">
270-
<div v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'" class="xiaohongshu-guide">
271-
<h3>📱 {{ $t({ en: 'How to share to Xiaohongshu?', zh: '如何分享到小红书?' }) }}</h3>
272-
273-
<div class="guide-steps">
274-
<div class="step">
275-
<span class="step-number">1️⃣</span>
276-
<div class="step-content">
277-
<strong>{{ $t({ en: 'Download Video', zh: '下载视频' }) }}</strong>
278-
<p>{{ $t({ en: 'Click the button below to save video', zh: '点击下方按钮保存视频到设备' }) }}</p>
279-
</div>
280-
</div>
281-
282-
<div class="step">
283-
<span class="step-number">2️⃣</span>
284-
<div class="step-content">
285-
<strong>{{ $t({ en: 'Open Xiaohongshu App', zh: '打开小红书APP' }) }}</strong>
286-
<p>{{ $t({ en: 'Tap "+" to create new post', zh: '点击"+"号发布新笔记' }) }}</p>
287-
</div>
288-
</div>
289-
290-
<div class="step">
291-
<span class="step-number">3️⃣</span>
292-
<div class="step-content">
293-
<strong>{{ $t({ en: 'Upload & Share', zh: '上传分享' }) }}</strong>
294-
<p>{{ $t({ en: 'Select the downloaded video to share', zh: '选择刚下载的视频进行分享' }) }}</p>
295-
</div>
296-
</div>
297-
</div>
298-
299-
<div class="api-notice">
300-
<span class="notice-icon">💡</span>
301-
<p>
302-
{{
303-
$t({
304-
en: 'Manual upload required due to API limitations',
305-
zh: '由于API限制,需要手动上传,感谢理解'
306-
})
307-
}}
308-
</p>
309-
</div>
310-
311-
<button
312-
class="download-btn primary"
313-
:disabled="!videoSrc || handleDownloadClick.isLoading.value"
314-
@click="handleDownloadClick.fn"
315-
>
316-
{{
317-
handleDownloadClick.isLoading.value
318-
? $t({ en: 'Downloading...', zh: '下载中...' })
319-
: $t({ en: 'Download Video', zh: '下载视频' })
320-
}}
321-
</button>
322-
</div>
271+
<XiaohongshuShareGuide
272+
v-if="selectedPlatform?.basicInfo.name === 'xiaohongshu'"
273+
type="video"
274+
:is-loading="handleDownloadClick.isLoading.value"
275+
@download="handleDownloadClick.fn"
276+
/>
323277

324278
<div v-else class="qr-content">
325279
<div class="qr-code">
@@ -637,117 +591,6 @@ watch(
637591
}
638592
}
639593
640-
.xiaohongshu-guide {
641-
width: 100%;
642-
max-width: 350px;
643-
padding: 16px;
644-
background: linear-gradient(135deg, #fff5f5 0%, #ffeef0 100%);
645-
border-radius: 10px;
646-
border: 1px solid #ffb3ba;
647-
box-shadow: 0 3px 12px rgba(255, 0, 53, 0.12);
648-
649-
h3 {
650-
margin: 0 0 14px 0;
651-
font-size: 15px;
652-
font-weight: 600;
653-
color: #ff0035;
654-
text-align: center;
655-
line-height: 1.2;
656-
}
657-
}
658-
659-
.guide-steps {
660-
margin-bottom: 14px;
661-
662-
.step {
663-
display: flex;
664-
align-items: flex-start;
665-
margin-bottom: 12px;
666-
667-
&:last-child {
668-
margin-bottom: 0;
669-
}
670-
}
671-
672-
.step-number {
673-
font-size: 14px;
674-
margin-right: 8px;
675-
flex-shrink: 0;
676-
line-height: 1.2;
677-
width: 16px;
678-
}
679-
680-
.step-content {
681-
flex: 1;
682-
min-width: 0;
683-
684-
strong {
685-
display: block;
686-
font-size: 13px;
687-
font-weight: 600;
688-
color: #333;
689-
margin-bottom: 3px;
690-
line-height: 1.3;
691-
}
692-
693-
p {
694-
font-size: 12px;
695-
color: #666;
696-
margin: 0;
697-
line-height: 1.4;
698-
word-wrap: break-word;
699-
}
700-
}
701-
}
702-
703-
.api-notice {
704-
display: flex;
705-
align-items: flex-start;
706-
margin-bottom: 14px;
707-
padding: 8px 10px;
708-
background: rgba(255, 255, 255, 0.8);
709-
border-radius: 6px;
710-
711-
.notice-icon {
712-
font-size: 12px;
713-
margin-right: 6px;
714-
flex-shrink: 0;
715-
}
716-
717-
p {
718-
margin: 0;
719-
font-size: 11px;
720-
color: #888;
721-
line-height: 1.4;
722-
word-wrap: break-word;
723-
}
724-
}
725-
726-
.download-btn.primary {
727-
width: 100%;
728-
background: linear-gradient(135deg, #ff0035 0%, #ff4d6d 100%);
729-
color: white;
730-
border: none;
731-
padding: 10px 16px;
732-
border-radius: 8px;
733-
font-size: 13px;
734-
font-weight: 600;
735-
cursor: pointer;
736-
transition: all 0.3s ease;
737-
box-shadow: 0 3px 8px rgba(255, 0, 53, 0.25);
738-
739-
&:hover:not(:disabled) {
740-
background: linear-gradient(135deg, #e6002f 0%, #ff3366 100%);
741-
transform: translateY(-1px);
742-
box-shadow: 0 4px 14px rgba(255, 0, 53, 0.35);
743-
}
744-
745-
&:disabled {
746-
opacity: 0.6;
747-
cursor: not-allowed;
748-
}
749-
}
750-
751594
.actions {
752595
display: flex;
753596
gap: 10px;

0 commit comments

Comments
 (0)