167 lines
5.2 KiB
TypeScript
167 lines
5.2 KiB
TypeScript
import { request } from '../../utils/request'
|
|
import { AiRecommendResult, ClothesItem } from '../../types/models'
|
|
import { navScroll } from '../../utils/nav'
|
|
import { logger } from '../../utils/logger'
|
|
|
|
// 日志模块名
|
|
const LOG = 'ai-recommend'
|
|
|
|
Page({
|
|
data: {
|
|
state: 'scene' as 'scene' | 'generating' | 'result' | 'empty',
|
|
showSceneSheet: true,
|
|
sceneType: 1,
|
|
scene: '',
|
|
result: null as AiRecommendResult | null,
|
|
clothes: [] as ClothesItem[],
|
|
generating: false,
|
|
// 滚动收缩:由 utils/nav.ts 的共享 handler 驱动
|
|
navScrolled: false,
|
|
// v2 玻璃弹层
|
|
confirmVisible: false,
|
|
confirmButtons: [
|
|
{ text: '取消', value: '' },
|
|
{ text: '开始生成', value: 'ok', type: 'main' },
|
|
],
|
|
limitVisible: false,
|
|
limitButtons: [
|
|
{ text: '取消', value: '' },
|
|
{ text: '去购买', value: 'ok', type: 'main' },
|
|
],
|
|
},
|
|
|
|
// scroll-view 滚动 → 导航收缩为玻璃小标题
|
|
onNavScroll: navScroll,
|
|
|
|
noop() {},
|
|
|
|
selectDaily() {
|
|
this.setData({ sceneType: 1 })
|
|
},
|
|
|
|
selectCustom() {
|
|
this.setData({ sceneType: 2 })
|
|
},
|
|
|
|
onSceneInput(e: WechatMiniprogram.Input) {
|
|
this.setData({ scene: e.detail.value })
|
|
},
|
|
|
|
onSkipScene() {
|
|
this.setData({ showSceneSheet: false })
|
|
this.startGenerate(1, '')
|
|
},
|
|
|
|
onStartGenerate() {
|
|
this.setData({ showSceneSheet: false })
|
|
this.startGenerate(this.data.sceneType, this.data.scene)
|
|
},
|
|
|
|
startGenerate(sceneType: number, scene: string) {
|
|
if (this.data.generating) return
|
|
// 待生成的场景参数暂存到实例,确认后再发起
|
|
;(this as any).pendingScene = { sceneType, scene }
|
|
this.setData({ confirmVisible: true })
|
|
},
|
|
|
|
onConfirmCancel() {
|
|
this.setData({ confirmVisible: false })
|
|
},
|
|
|
|
onConfirmGenerate(e: WechatMiniprogram.CustomEvent) {
|
|
this.setData({ confirmVisible: false })
|
|
if (e.detail.value !== 'ok') return
|
|
const pending = (this as any).pendingScene || { sceneType: 1, scene: '' }
|
|
this.doGenerate(pending.sceneType, pending.scene)
|
|
},
|
|
|
|
doGenerate(sceneType: number, scene: string) {
|
|
if (this.data.generating) return
|
|
this.setData({ state: 'generating', generating: true })
|
|
|
|
const body: Record<string, any> = { scene_type: sceneType }
|
|
if (sceneType === 2 && scene) body.scene = scene
|
|
|
|
request<AiRecommendResult>({ url: '/ai-recommend', method: 'POST', data: body, showError: false })
|
|
.then(async (res) => {
|
|
logger.info(LOG, 'AI 推荐生成成功, 单品数=', res.outfit_item && res.outfit_item.length)
|
|
const clothes = await Promise.all(
|
|
res.outfit_item.map(async (it) => {
|
|
try {
|
|
return await request<ClothesItem>({ url: `/clothes/${it.clothes_uuid}`, showError: false })
|
|
} catch (e: any) {
|
|
logger.warn(LOG, '单品详情拉取失败, uuid=', it.clothes_uuid, 'code=', e && e.code)
|
|
return { clothes_uuid: it.clothes_uuid } as ClothesItem
|
|
}
|
|
})
|
|
)
|
|
this.setData({ result: res, clothes, state: 'result', generating: false })
|
|
})
|
|
.catch((e: any) => {
|
|
this.setData({ generating: false })
|
|
const code = e && e.code
|
|
logger.warn(LOG, 'AI 推荐生成失败, code=', code)
|
|
if (code === 90400) {
|
|
this.setData({ state: 'empty' })
|
|
} else if (code === 90401 || code === 80000) {
|
|
// 90401=AI 推荐次数上限;80000=额度不足兜底,统一弹窗引导购买
|
|
this.setData({ state: 'scene', showSceneSheet: true })
|
|
this.showLimitModal()
|
|
} else if (code === 10003) {
|
|
wx.showToast({ title: '正在生成中,请稍候', icon: 'none' })
|
|
this.setData({ state: 'scene', showSceneSheet: true })
|
|
} else {
|
|
this.setData({ state: 'scene', showSceneSheet: true })
|
|
}
|
|
})
|
|
},
|
|
|
|
showLimitModal() {
|
|
this.setData({ limitVisible: true })
|
|
},
|
|
|
|
onLimitCancel() {
|
|
this.setData({ limitVisible: false })
|
|
},
|
|
|
|
onLimitConfirm(e: WechatMiniprogram.CustomEvent) {
|
|
this.setData({ limitVisible: false })
|
|
if (e.detail.value !== 'ok') return
|
|
wx.navigateTo({
|
|
url: '/pages/mall/mall',
|
|
fail: (err) => logger.warn(LOG, 'navigateTo 商城失败, err=', err && err.errMsg),
|
|
})
|
|
},
|
|
|
|
onSave() {
|
|
if (!this.data.result) return
|
|
request({
|
|
url: '/ai-recommend/save',
|
|
method: 'POST',
|
|
data: { outfit_uuid: this.data.result.outfit_uuid },
|
|
})
|
|
.then(() => {
|
|
logger.info(LOG, 'AI 穿搭保存成功')
|
|
wx.showToast({ title: '已保存到我的穿搭', icon: 'success' })
|
|
setTimeout(() => {
|
|
wx.redirectTo({
|
|
url: `/pages/outfit-detail/outfit-detail?uuid=${this.data.result!.outfit_uuid}&owner=1`,
|
|
fail: (e) => logger.warn(LOG, 'redirectTo 穿搭详情失败, err=', e && e.errMsg),
|
|
})
|
|
}, 500)
|
|
})
|
|
.catch((e: any) => logger.warn(LOG, 'AI 穿搭保存失败, code=', e && e.code))
|
|
},
|
|
|
|
onReroll() {
|
|
this.startGenerate(this.data.sceneType, this.data.scene)
|
|
},
|
|
|
|
onGoUpload() {
|
|
wx.navigateTo({
|
|
url: '/pages/upload/upload',
|
|
fail: (e) => logger.warn(LOG, 'navigateTo 上传页失败, err=', e && e.errMsg),
|
|
})
|
|
},
|
|
})
|