新增:抖音支持一个链接下多单;图片按裁剪3:4比例;根据返回的数据显示门店名称和门店logo
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/prod Build is passing

This commit is contained in:
Linzm committed 2026-10-27 14:34:49 +08:00
1 parent 6bf542bf1d
commit 8e8cde9ef5
19 files changed
+2158 -404

No files matched your search

+158 -13
View File
@@ -20,12 +20,27 @@
<span class="check">✓</span>
</div>
<h1 class="hero-title">提交制作成功</h1>
<p class="hero-desc">效果图已确认并进入制作流程,可随时在生图记录中查看</p>
<p class="hero-desc">{{ heroDesc }}</p>
</div>
<div v-if="resultUrl" class="thumb-card" @click="openZoom">
<img :src="resultUrl" class="thumb-img" alt="已提交效果图">
<div v-if="resultList.length === 1" class="thumb-card" @click="openZoom(0)">
<img :src="resultList[0].url" class="thumb-img" alt="已提交效果图">
<div class="thumb-badge">已提交</div>
<div v-if="resultList[0].count > 1" class="thumb-count">×{{ resultList[0].count }}</div>
</div>
<div v-else-if="resultList.length > 1" class="thumb-grid">
<div
v-for="(item, idx) in resultList"
:key="`${item.taskId || item.url}-${idx}`"
class="thumb-grid-item"
@click="openZoom(idx)"
>
<img :src="item.url" class="thumb-img" alt="已提交效果图">
<div class="thumb-badge">已提交</div>
<div v-if="item.count > 1" class="thumb-count">×{{ item.count }}</div>
<div v-if="item.label" class="thumb-label">{{ item.label }}</div>
</div>
</div>
<div class="steps-card">
@@ -35,7 +50,7 @@
<span class="dot" />
<div>
<div class="step-name">确认效果并提交</div>
<div class="step-desc">已完成</div>
<div class="step-desc">已完成{{ totalCountText }}</div>
</div>
</li>
<li class="step is-active">
@@ -69,14 +84,92 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { showImagePreview } from 'vant'
import { douyinConfig as config } from '@/config/douyin'
import DyNavBar from './components/DyNavBar.vue'
type SuccessResult = {
url: string
count: number
label: string
taskId?: string
imageId?: string
}
const router = useRouter()
const resultUrl = ref(sessionStorage.getItem('douyin_result_url') || '')
const resultList = ref<SuccessResult[]>([])
function normalizeResult(item: any): SuccessResult | null {
const url = String(item?.url || item?.path || item?.result_url || '').trim()
if (!url) return null
return {
url,
count: Math.max(1, Number(item?.count) || 1),
label: String(item?.label || item?.style || '').trim(),
taskId: item?.taskId ? String(item.taskId) : '',
imageId: item?.imageId ? String(item.imageId) : '',
}
}
function loadResults() {
const list: SuccessResult[] = []
try {
const raw = sessionStorage.getItem('douyin_success_results')
if (raw) {
const parsed = JSON.parse(raw)
if (Array.isArray(parsed)) {
parsed.forEach((item) => {
const normalized = normalizeResult(item)
if (normalized) list.push(normalized)
})
}
}
} catch (_) {}
if (!list.length) {
const single = sessionStorage.getItem('douyin_result_url') || ''
if (single) {
list.push({
url: single,
count: 1,
label: '',
})
}
}
// 去重,保留首次出现顺序
const seen = new Set<string>()
resultList.value = list.filter((item) => {
const key = `${item.taskId || ''}|${item.imageId || ''}|${item.url}`
if (seen.has(key)) return false
seen.add(key)
return true
})
}
const totalPieces = computed(() =>
resultList.value.reduce((sum, item) => sum + (Number(item.count) || 1), 0),
)
const heroDesc = computed(() => {
const n = resultList.value.length
if (n > 1) {
return `已提交 ${n} 张效果图(共 ${totalPieces.value} 件),可随时在生图记录中查看`
}
if (totalPieces.value > 1) {
return `已提交 ${totalPieces.value} 件制作,可随时在生图记录中查看`
}
return '效果图已确认并进入制作流程,可随时在生图记录中查看'
})
const totalCountText = computed(() => {
const n = resultList.value.length
if (n > 1) return ` · ${n} 张 / ${totalPieces.value} 件`
if (totalPieces.value > 1) return ` · ${totalPieces.value} 件`
return ''
})
function goHome() {
router.replace(config.routes.home)
@@ -86,14 +179,20 @@ function goRecords() {
router.replace(config.routes.records)
}
function openZoom() {
if (!resultUrl.value) return
function openZoom(startIndex = 0) {
const images = resultList.value.map((item) => item.url).filter(Boolean)
if (!images.length) return
showImagePreview({
images: [resultUrl.value],
images,
startPosition: Math.max(0, Math.min(startIndex, images.length - 1)),
closeable: true,
closeIconPosition: 'top-right',
})
}
onMounted(() => {
loadResults()
})
</script>
<style scoped lang="scss">
@@ -215,7 +314,7 @@ function openZoom() {
.hero-desc {
margin: 8px auto 0;
max-width: 280px;
max-width: 300px;
font-size: 13px;
line-height: 1.55;
color: #7a8a76;
@@ -230,6 +329,24 @@ function openZoom() {
overflow: hidden;
background: #fff;
box-shadow: 0 8px 22px rgba(40, 70, 50, 0.1);
cursor: pointer;
}
.thumb-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
margin: 4px 0 14px;
}
.thumb-grid-item {
position: relative;
aspect-ratio: 1;
border-radius: 16px;
overflow: hidden;
background: #fff;
box-shadow: 0 6px 18px rgba(40, 70, 50, 0.1);
cursor: pointer;
}
.thumb-img {
@@ -242,9 +359,9 @@ function openZoom() {
.thumb-badge {
position: absolute;
left: 10px;
top: 10px;
padding: 4px 10px;
left: 8px;
top: 8px;
padding: 3px 8px;
border-radius: 999px;
background: rgba(95, 191, 69, 0.92);
color: #fff;
@@ -252,6 +369,34 @@ function openZoom() {
font-weight: 600;
}
.thumb-count {
position: absolute;
right: 8px;
top: 8px;
min-width: 28px;
padding: 3px 8px;
border-radius: 999px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
font-size: 11px;
font-weight: 600;
text-align: center;
}
.thumb-label {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 18px 8px 8px;
font-size: 11px;
color: #fff;
background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.55));
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.steps-card,
.tips-card {
background: #fff;