forked from natuka/web.puabadge.com
修改:前端判断剩余生图次数
This commit is contained in:
1 parent
6dd4b4a724
commit
505c585772
1 file changed
+81
-7
@@ -197,7 +197,15 @@ const caseItems = [
|
||||
{ label: config.messages.caseLabels[2], src: config.images.caseScene },
|
||||
]
|
||||
|
||||
/**
|
||||
* 剩余次数:
|
||||
* - 首屏用接口 remain_count 打底
|
||||
* - 之后只按「本地点成功出图」递减
|
||||
* - 接口若未扣减(仍返回原值),不会把次数加回去
|
||||
*/
|
||||
const remainCount = ref(0)
|
||||
/** 打底时已统计到的成功次数;新增成功 = 当前成功数 - baselineUsed */
|
||||
const remainBaselineUsed = ref(0)
|
||||
const sessionId = ref('')
|
||||
const subjectName = ref('')
|
||||
/** stat 返回的主体文案(订单约定主体,标签始终展示此值) */
|
||||
@@ -270,6 +278,64 @@ const isEditing = computed(() => !!editingResultId.value)
|
||||
const isPendingCartoon = computed(
|
||||
() => Boolean(pendingPreview.value && photoInspect.value && isCartoonImage(photoInspect.value)),
|
||||
)
|
||||
|
||||
/** 统计已消耗的生图次数:成功 task + 对话里已出的结果卡 */
|
||||
function countUsedGenerations() {
|
||||
const ids = new Set<string>()
|
||||
const detail = sessionDetail.value as { tasks?: Array<Record<string, any>> } | null
|
||||
detail?.tasks?.forEach((task) => {
|
||||
const taskId = String(task?.task_id || '').trim()
|
||||
if (!taskId) return
|
||||
const images = Array.isArray(task.images) ? task.images : []
|
||||
const hasImage = images.some((image: any) => Boolean(image?.url))
|
||||
const status = String(task.status || '').toLowerCase()
|
||||
if (status === 'success' || hasImage) ids.add(`task:${taskId}`)
|
||||
})
|
||||
messages.value.forEach((msg) => {
|
||||
if (msg.type !== 'result') return
|
||||
const taskId = String(msg.taskId || '').trim()
|
||||
// 与 task 去重;无 taskId 的本地结果用消息 id
|
||||
ids.add(taskId ? `task:${taskId}` : `msg:${msg.id}`)
|
||||
})
|
||||
return ids.size
|
||||
}
|
||||
|
||||
/**
|
||||
* 首屏打底:接口 remain_count 在京东侧常不随出图减少,这里当作可生图总额,
|
||||
* 再按会话内已成功次数扣除;后续只减不增。
|
||||
*/
|
||||
function seedRemainFromApi(apiRemainRaw?: unknown) {
|
||||
const apiRemain = Number(apiRemainRaw)
|
||||
remainBaselineUsed.value = 0
|
||||
remainCount.value = Number.isFinite(apiRemain) ? Math.max(0, apiRemain) : 0
|
||||
refreshRemainByUsed()
|
||||
}
|
||||
|
||||
/** 按已成功出图数重算剩余(只减不加) */
|
||||
function refreshRemainByUsed(apiRemainRaw?: unknown) {
|
||||
const used = countUsedGenerations()
|
||||
const earned = Math.max(0, used - remainBaselineUsed.value)
|
||||
remainCount.value = Math.max(0, remainCount.value - earned)
|
||||
remainBaselineUsed.value = used
|
||||
|
||||
const apiRemain = Number(apiRemainRaw)
|
||||
if (!Number.isFinite(apiRemain)) return
|
||||
// 接口若已扣得更少,跟随接口;偏高(未扣)则忽略,避免加回次数
|
||||
if (apiRemain < remainCount.value) {
|
||||
remainCount.value = Math.max(0, apiRemain)
|
||||
}
|
||||
}
|
||||
|
||||
/** 生图接口成功即扣 1 次(不等待过渡动画),并抬高 baseline 避免结果入列后重复扣 */
|
||||
function noteGenerationSuccess() {
|
||||
remainCount.value = Math.max(0, remainCount.value - 1)
|
||||
remainBaselineUsed.value += 1
|
||||
}
|
||||
|
||||
function resetRemainQuota() {
|
||||
remainCount.value = 0
|
||||
remainBaselineUsed.value = 0
|
||||
}
|
||||
const titleSpec = computed(() => productTitleSpecFromOrder(orderStat.value))
|
||||
const hasRequiredTitle = computed(() => {
|
||||
if (!titleSpec.value) return true
|
||||
@@ -655,17 +721,17 @@ function onGenerateStageDone(generatingId: string) {
|
||||
}
|
||||
|
||||
if (pending.uploadId) lastUploadId.value = pending.uploadId
|
||||
remainCount.value = Math.max(0, remainCount.value - 1)
|
||||
// 成功扣次已在 noteGenerationSuccess;这里只把 baseline 与结果卡对齐
|
||||
remainBaselineUsed.value = Math.max(remainBaselineUsed.value, countUsedGenerations())
|
||||
isBusy.value = false
|
||||
photoInspect.value = null
|
||||
scrollToBottom()
|
||||
// 仅同步剩余次数,避免整页历史重绘冲掉当前气泡
|
||||
// 仅同步剩余次数;接口未扣减时不会把次数加回去
|
||||
void badgeApi
|
||||
.getOrderStat({})
|
||||
.then((res: any) => {
|
||||
const count = Number(res?.remain_count)
|
||||
if (Number.isFinite(count)) remainCount.value = Math.max(0, count)
|
||||
orderStat.value = res || orderStat.value
|
||||
refreshRemainByUsed(res?.remain_count)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
@@ -797,6 +863,8 @@ async function startGenerate(opts: {
|
||||
startedAt,
|
||||
}
|
||||
patchGeneratingResult(generatingId, resultUrl)
|
||||
// 接口已成功出图:立刻扣剩余次数(不依赖过渡动画是否播完)
|
||||
noteGenerationSuccess()
|
||||
scrollToBottom()
|
||||
} catch (error) {
|
||||
removeGenerating(generatingId)
|
||||
@@ -942,6 +1010,8 @@ function applySessionHistory(detail: ReturnType<typeof jingdongApi.parseSessionD
|
||||
})
|
||||
messages.value = next
|
||||
if (latestUpload) lastUploadId.value = latestUpload
|
||||
// 历史回填后:用接口总额 - 已成功次数
|
||||
seedRemainFromApi(orderStat.value?.remain_count)
|
||||
scrollToBottom()
|
||||
}
|
||||
|
||||
@@ -949,6 +1019,7 @@ function fetchSessionDetail(sid: string) {
|
||||
const id = String(sid || '').trim()
|
||||
if (!id) {
|
||||
sessionDetail.value = null
|
||||
seedRemainFromApi(orderStat.value?.remain_count)
|
||||
return Promise.resolve()
|
||||
}
|
||||
return jingdongApi
|
||||
@@ -965,6 +1036,7 @@ function fetchSessionDetail(sid: string) {
|
||||
})
|
||||
.catch(() => {
|
||||
sessionDetail.value = null
|
||||
seedRemainFromApi(orderStat.value?.remain_count)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -974,19 +1046,21 @@ function fetchOrderStat() {
|
||||
.then((res: any) => {
|
||||
// interceptor 已解包 data:remain_count / subject_name / type_name / session_id / prod_id ...
|
||||
orderStat.value = res || {}
|
||||
const count = Number(res?.remain_count)
|
||||
remainCount.value = Number.isFinite(count) ? Math.max(0, count) : 0
|
||||
subjectNameFromStat.value = String(res?.subject_name || '').trim()
|
||||
subjectName.value = subjectNameFromStat.value
|
||||
styleName.value = String(res?.style_name || '').trim()
|
||||
typeName.value = String(res?.type_name || '').trim()
|
||||
sessionId.value = String(res?.session_id || '').trim()
|
||||
subjectMatched.value = true
|
||||
// 先记下接口值;等会话历史回来后再按已生成次数扣除
|
||||
const apiRemain = Number(res?.remain_count)
|
||||
remainCount.value = Number.isFinite(apiRemain) ? Math.max(0, apiRemain) : 0
|
||||
remainBaselineUsed.value = 0
|
||||
return fetchSessionDetail(sessionId.value)
|
||||
})
|
||||
.catch(() => {
|
||||
orderStat.value = null
|
||||
remainCount.value = 0
|
||||
resetRemainQuota()
|
||||
subjectName.value = ''
|
||||
subjectNameFromStat.value = ''
|
||||
styleName.value = ''
|
||||
|
||||
Reference in new issue
Block a user