4 Commits
4 changed files with 383 additions and 58 deletions
+13
View File
@@ -885,6 +885,18 @@ export const chatMixinsV2 = {
this.currentGiftStepIndex-- this.currentGiftStepIndex--
} }
}, },
clearCurrentGiftStepData() {
const currentStep = this.giftBuyOptions[this.currentGiftStepIndex]
if (!currentStep) return
if (currentStep.type === 'option_card') {
const nextSelections = { ...this.giftSelections }
delete nextSelections[currentStep.id]
this.giftSelections = nextSelections
} else if (currentStep.type === 'price_input') {
this.giftBudget = ''
}
},
nextGiftStep() { nextGiftStep() {
const currentStep = this.giftBuyOptions[this.currentGiftStepIndex] const currentStep = this.giftBuyOptions[this.currentGiftStepIndex]
let hasSelection = false let hasSelection = false
@@ -912,6 +924,7 @@ export const chatMixinsV2 = {
} }
}, },
skipGiftStep() { skipGiftStep() {
this.clearCurrentGiftStepData()
if (this.currentGiftStepIndex < this.giftBuyOptions.length - 1) { if (this.currentGiftStepIndex < this.giftBuyOptions.length - 1) {
this.currentGiftStepIndex++ this.currentGiftStepIndex++
} else { } else {
+12
View File
@@ -148,3 +148,15 @@ export function aiGiftImageStatus(params) {
login: true login: true
}) })
} }
/**
* 获取商品以前使用过的AI礼品卡图片
* @param {*} params
* @returns
*/
export function aiGiftImageHistory(params) {
return request.get("/giftCard/aiGiftImages/history?productId=" + params.productId, {
login: true
})
}
@@ -0,0 +1,164 @@
<template>
<u-popup
:show="show"
mode="bottom"
round="40rpx"
:customStyle="{height: '600rpx'}"
@close="close"
>
<view class="cover-picker v12-pt-4">
<swiper
:current="currentIndex"
:autoplay="false"
:circular="true"
:indicator-dots="false"
@change="onChange"
previous-margin="180rpx"
next-margin="180rpx"
class="cover-swiper"
>
<swiper-item v-for="(item, i) in list" :key="i" class="cover-swiper-item" :class="{'n-actived' : currentIndex !== i}">
<view class="cover-item" :class="{'ios-cover': isIOS}">
<view class="img-wrap">
<image :src="item.cover" class="cover-image" mode="widthFix" />
</view>
</view>
</swiper-item>
</swiper>
<view class="v12-justify-center">
<view class="cover-confirm" @click="confirm">
确定
</view>
</view>
<view class="tips">礼包封面在对方领取时展示</view>
<view class="tips tips2">*图片由云灵AI生成仅供参考</view>
</view>
</u-popup>
</template>
<script>
export default {
props: {
index: {
type: Number,
default: 0
},
show: {
type: Boolean,
default: true
},
list: {
type: Array,
default: () => []
}
},
data() {
return {
currentIndex: this.index
}
},
computed: {
isIOS() {
return uni.getSystemInfoSync().osName === 'ios'
}
},
watch: {
index(val) {
this.currentIndex = val
},
show(val) {
if (val) {
this.currentIndex = this.index
}
}
},
methods: {
close() {
this.currentIndex = 0
this.$emit('update:show', false)
},
onChange(e) {
this.currentIndex = e.detail.current
this.$forceUpdate()
},
confirm() {
this.$emit('confirm', this.list[this.currentIndex])
this.$emit('update:show', false)
}
}
}
</script>
<style lang="less" scoped>
.n-actived{
.cover-item{
transform: scale(0.8);
margin-bottom: -70rpx !important;
}
}
.cover-swiper-item{
height: fit-content !important;
bottom: 0;
overflow: visible;
}
.img-wrap{
position: relative;
overflow: visible;
}
.tips{
font-size: 24rpx;
color: #999;
text-align: center;
margin-top: 20rpx;
}
.tips2{
color: #C52733;
}
.cover-swiper{
height: 800rpx;
}
.cover-picker {
.cover-title {
padding: 30rpx;
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.cover-item {
display: flex;
flex-direction: column;
align-items: center;
overflow: visible;
transition: all .3s ease-in-out;
margin-bottom: 30rpx;
.cover-image {
width: 420rpx;
// height: 580rpx;
border-radius: 16rpx;
transition: all .2s ease-in-out;
}
.cover-name {
margin-top: 20rpx;
font-size: 28rpx;
color: #333;
}
}
.cover-confirm {
margin-top: 40rpx;
width: 240rpx;
height: 80rpx;
border-radius: 16rpx;
font-size: 32rpx;
background-color: #C52733 !important;
color: #fff !important;
text-align: center;
line-height: 80rpx;
}
}
.ios-cover{
zoom: 1.01
}
</style>
+161 -25
View File
@@ -36,6 +36,7 @@
> >
<view class="ai-cover-body"> <view class="ai-cover-body">
<view class="ai-cover-container"> <view class="ai-cover-container">
<view v-if="!showAiImgHistoryListSelect">
<view v-if="showGenerateBtn" class="prompt"> <view v-if="showGenerateBtn" class="prompt">
<textarea <textarea
v-model.trim="aiCoverDesc" v-model.trim="aiCoverDesc"
@@ -45,8 +46,12 @@
/> />
<p class="prompt-tips">{{ aiCoverDesc.length }}/300</p> <p class="prompt-tips">{{ aiCoverDesc.length }}/300</p>
</view> </view>
<view v-else class="imgs-list-wrap"> <view v-else class="imgs-list-wrap ai-img-list-wrap">
<view class="img-item" v-for="(item, index) in aiCoverImgsList" :key="index"> <view
v-for="(item, index) in aiCoverImgsList"
:key="index"
class="img-item"
>
<image <image
:src="item.cover" :src="item.cover"
:class="{ :class="{
@@ -59,8 +64,39 @@
</view> </view>
</view> </view>
</view> </view>
<view v-else>
<view
:class="{'scrollable': aiHistoryCoverImgsList.length > 3}"
class="imgs-list-wrap"
>
<view
v-for="(item, index) in aiHistoryCoverImgsList"
:key="index"
class="img-item"
>
<image
:src="item.cover"
:class="{
'active': item.id === selectedAiCoverImage.id
}"
mode="heightFix"
class="img-image"
@click="handleSelectAiHistoryCover(item)"
/>
</view>
</view>
</view>
</view>
<view class="ai-cover-bottom"> <view class="ai-cover-bottom">
<block v-if="!showAiImgHistoryListSelect">
<view v-if="showGenerateBtn" class="btn-wrap"> <view v-if="showGenerateBtn" class="btn-wrap">
<view
v-if="!aiCoverGenerateLoading && aiHistoryCoverImgsList.length > 0"
class="btn btn2"
@click="toggleShowAiImgHistoryListSelect(true)"
>
历史图片
</view>
<view class="btn" @click="handleGenerateAiCover"> <view class="btn" @click="handleGenerateAiCover">
{{ aiCoverGenerateLoading ? '礼包封面生成中...' : 'AI生成礼包封面' }} {{ aiCoverGenerateLoading ? '礼包封面生成中...' : 'AI生成礼包封面' }}
<image v-if="!aiCoverGenerateLoading" :src="webUrl + '/page/gift/gift-tab-icon01.png'" class="icon"></image> <image v-if="!aiCoverGenerateLoading" :src="webUrl + '/page/gift/gift-tab-icon01.png'" class="icon"></image>
@@ -79,6 +115,17 @@
重新生成 重新生成
</view> </view>
</view> </view>
</block>
<block v-else>
<view class="btn-wrap">
<view class="btn" @click="handleShowAiHistoryCoverPicker">
预览
</view>
<view class="btn btn2" @click="toggleShowAiImgHistoryListSelect(false)">
使用AI生成
</view>
</view>
</block>
</view> </view>
</view> </view>
</view> </view>
@@ -232,6 +279,12 @@
:index="aiDefaultIndex" :index="aiDefaultIndex"
@confirm="onAiCoverConfirm" @confirm="onAiCoverConfirm"
/> />
<AiHistoryCoverPicker
:show.sync="showAiHistoryCoverPicker"
:list="aiHistoryCoverImgsList"
:index="aiHistoryDefaultIndex"
@confirm="onAiHistoryCoverConfirm"
/>
<passkeyborad <passkeyborad
ref='payPwdPop' ref='payPwdPop'
showMoney showMoney
@@ -302,7 +355,8 @@ import {
fetchSojoumGroupBuyGiftCarousel, fetchSojoumGroupBuyGiftCarousel,
computedSojoumGroupBuyGiftOrderPrice, computedSojoumGroupBuyGiftOrderPrice,
aiGiftImageGenerate, aiGiftImageGenerate,
aiGiftImageStatus aiGiftImageStatus,
aiGiftImageHistory
} from '@/api/gift' } from '@/api/gift'
import { import {
getAiSystemInfoSetting getAiSystemInfoSetting
@@ -312,6 +366,7 @@ import {mapGetters} from "vuex";
import giftTips from './components/giftTips.vue' import giftTips from './components/giftTips.vue'
import CoverPicker from './components/CoverPicker.vue' import CoverPicker from './components/CoverPicker.vue'
import AiCoverPicker from './components/AiCoverPicker.vue' import AiCoverPicker from './components/AiCoverPicker.vue'
import AiHistoryCoverPicker from './components/AiHistoryCoverPicker.vue'
import PayPicker from './components/PayPicker.vue'; import PayPicker from './components/PayPicker.vue';
import CouponsPopup from "@/components/CouponsPopup.vue" import CouponsPopup from "@/components/CouponsPopup.vue"
export default { export default {
@@ -319,6 +374,7 @@ export default {
giftTips, giftTips,
CoverPicker, CoverPicker,
AiCoverPicker, AiCoverPicker,
AiHistoryCoverPicker,
PayPicker, PayPicker,
passkeyborad, passkeyborad,
CouponsPopup CouponsPopup
@@ -361,6 +417,7 @@ export default {
defaultIndex:0, defaultIndex:0,
discount: null, discount: null,
computedResult: {}, computedResult: {},
skipCouponIdWatch: false,
couponList: { couponList: {
unusable: [], unusable: [],
usable: [] usable: []
@@ -406,11 +463,19 @@ export default {
selectedAiCoverImage: {}, selectedAiCoverImage: {},
showAiCoverPicker: false, showAiCoverPicker: false,
pollInterval: null, pollInterval: null,
aiDefaultIndex: 0 aiDefaultIndex: 0,
aiHistoryDefaultIndex: 0,
showAiHistoryCoverPicker: false,
aiHistoryCoverImgsList: [],
showAiImgHistoryListSelect: false
} }
}, },
watch: { watch: {
async couponId(value) { async couponId(value) {
if (this.skipCouponIdWatch) {
this.skipCouponIdWatch = false
return
}
if (this.isCountyLotteryGift) { if (this.isCountyLotteryGift) {
this.couponTitle = '' this.couponTitle = ''
if (Number(value || 0) !== 0) { if (Number(value || 0) !== 0) {
@@ -472,11 +537,27 @@ export default {
} }
}, },
methods: { methods: {
// 將面切换 // 封面类型切换
toggleSelectCoverType(type) { toggleSelectCoverType(type) {
if (this.selectCoverType === type) return if (this.selectCoverType === type) return
this.selectCoverType = type this.selectCoverType = type
}, },
// 获取商品以前使用过的AI礼品卡图片
aiGiftImageHistoryReq() {
aiGiftImageHistory({
productId: this.goodsInfo.productId
}).then(res => {
const { success, data } = res
if (success && data) {
this.aiHistoryCoverImgsList = data || []
this.aiHistoryCoverImgsList.map(historyItem => {
historyItem.cover = historyItem.coverUrl,
historyItem.image = historyItem.shareUrl,
historyItem.name = historyItem.name || ''
})
}
})
},
handleGenerateAiCover() { handleGenerateAiCover() {
if (!this.aiCoverDesc || !this.aiCoverDesc.trim()) { if (!this.aiCoverDesc || !this.aiCoverDesc.trim()) {
uni.showToast({ uni.showToast({
@@ -577,6 +658,11 @@ export default {
if (this.isCountyLotteryGift) return 0 if (this.isCountyLotteryGift) return 0
return this.couponId || 0 return this.couponId || 0
}, },
setCouponIdSilently(value) {
if (this.couponId === value) return
this.skipCouponIdWatch = true
this.couponId = value
},
isCountyLotteryCartItem(item) { isCountyLotteryCartItem(item) {
return Number( return Number(
(item && item.drawActivityId) || (item && item.drawActivityId) ||
@@ -591,7 +677,7 @@ export default {
if (!this.isCountyLotteryGift) return if (!this.isCountyLotteryGift) return
this.couponTitle = '' this.couponTitle = ''
if (Number(this.couponId || 0) !== 0) { if (Number(this.couponId || 0) !== 0) {
this.couponId = 0 this.setCouponIdSilently(0)
} }
}, },
adjustCoverListForProductStory(coverList, productInfo, defaultTemplate) { adjustCoverListForProductStory(coverList, productInfo, defaultTemplate) {
@@ -636,10 +722,10 @@ export default {
if (this.isCountyLotteryGift) { if (this.isCountyLotteryGift) {
this.couponTitle = '' this.couponTitle = ''
if (this.couponId !== 0) { if (this.couponId !== 0) {
this.couponId = 0 this.setCouponIdSilently(0)
} }
} else if(useDefaultCouponId) { } else if(useDefaultCouponId) {
this.couponId = res.data.result.defaultCouponId || 0 this.setCouponIdSilently(res.data.result.defaultCouponId || 0)
} }
}) })
}, },
@@ -649,6 +735,27 @@ export default {
handleShowAiCover() { handleShowAiCover() {
this.showAiCoverPicker = true this.showAiCoverPicker = true
}, },
handleShowAiHistoryCoverPicker() {
this.showAiHistoryCoverPicker = true
},
toggleShowAiImgHistoryListSelect(show) {
this.showAiImgHistoryListSelect = show
this.selectedAiCoverImage = {}
this.selectedCover = ''
this.giftImage = ''
this.templateId = ''
this.aiHistoryDefaultIndex = 0
this.aiDefaultIndex = 0
if (show) {
if (this.aiHistoryCoverImgsList.length > 0 && this.aiHistoryDefaultIndex === 0) {
const index = this.aiHistoryCoverImgsList.findIndex(item => item.isLastSelected)
if (index !== -1) {
this.aiHistoryDefaultIndex = index
}
this.handleSelectAiHistoryCover(this.aiHistoryCoverImgsList[this.aiHistoryDefaultIndex])
}
}
},
showCouponsPopup() { showCouponsPopup() {
if (this.isCountyLotteryGift) return if (this.isCountyLotteryGift) return
if (this.couponList.usable && this.couponList.usable.length === 0) return if (this.couponList.usable && this.couponList.usable.length === 0) return
@@ -664,7 +771,7 @@ export default {
if (this.couponList.usable && this.couponList.usable.length === 0) return if (this.couponList.usable && this.couponList.usable.length === 0) return
this.showPopup = !this.showPopup this.showPopup = !this.showPopup
if(!item.id) { if(!item.id) {
this.couponId = 0 this.setCouponIdSilently(0)
this.couponTitle = '' this.couponTitle = ''
if(this.isGroupBuy) { if(this.isGroupBuy) {
this.computedTravelGroupPrice(false) this.computedTravelGroupPrice(false)
@@ -673,7 +780,7 @@ export default {
} }
return return
} }
this.couponId = item.id this.setCouponIdSilently(item.id)
this.couponTitle = item.couponTitle this.couponTitle = item.couponTitle
if(this.isGroupBuy) { if(this.isGroupBuy) {
this.computedTravelGroupPrice(false) this.computedTravelGroupPrice(false)
@@ -708,7 +815,7 @@ export default {
this.giftImage = this.selectedAiCoverImage.image this.giftImage = this.selectedAiCoverImage.image
this.templateId = this.selectedAiCoverImage.id this.templateId = this.selectedAiCoverImage.id
} }
this.couponId = '' this.setCouponIdSilently('')
this.computedPrice(this.goodsInfo.cartNum) this.computedPrice(this.goodsInfo.cartNum)
}) })
}, },
@@ -745,10 +852,10 @@ export default {
if (this.isCountyLotteryGift) { if (this.isCountyLotteryGift) {
this.couponTitle = '' this.couponTitle = ''
if (this.couponId !== 0) { if (this.couponId !== 0) {
this.couponId = 0 this.setCouponIdSilently(0)
} }
} else if(!f) { } else if(!f) {
this.couponId = res.data.result.defaultCouponId || 0 this.setCouponIdSilently(res.data.result.defaultCouponId || 0)
this.$forceUpdate() this.$forceUpdate()
} }
this.payPrice = res.data.result.payPrice this.payPrice = res.data.result.payPrice
@@ -800,6 +907,16 @@ export default {
this.aiDefaultIndex = this.aiCoverImgsList.findIndex(item => item.id === cover.id) this.aiDefaultIndex = this.aiCoverImgsList.findIndex(item => item.id === cover.id)
} }
}, },
onAiHistoryCoverConfirm(cover) {
// 封面图片
this.selectedCover = cover.cover
// 分享对话图片
this.giftImage = cover.image
if (this.selectCoverType === 'ai') {
this.selectedAiCoverImage = cover
this.aiHistoryDefaultIndex = this.aiHistoryCoverImgsList.findIndex(item => item.id === cover.id)
}
},
handleSelectAiCover(cover) { handleSelectAiCover(cover) {
this.selectedAiCoverImage = cover this.selectedAiCoverImage = cover
this.aiDefaultIndex = this.aiCoverImgsList.findIndex(item => item.id === cover.id) this.aiDefaultIndex = this.aiCoverImgsList.findIndex(item => item.id === cover.id)
@@ -807,6 +924,13 @@ export default {
this.giftImage = cover.image this.giftImage = cover.image
this.templateId = cover.id this.templateId = cover.id
}, },
handleSelectAiHistoryCover(cover) {
this.selectedAiCoverImage = cover
this.aiHistoryDefaultIndex = this.aiHistoryCoverImgsList.findIndex(item => item.id === cover.id)
this.selectedCover = cover.cover
this.giftImage = cover.image
this.templateId = cover.id
},
showTips() { showTips() {
this.$refs.giftTips.showTips = true this.$refs.giftTips.showTips = true
}, },
@@ -817,25 +941,27 @@ export default {
} }
this.loading = true this.loading = true
getGiftCardSendOrderConfirm(params).then(res => { getGiftCardSendOrderConfirm(params).then(res => {
const temp = this.isGroupBuy ? res.data.giftCardTemplates : res.data.giftCardTemplates.filter(e => e.isTravelGroup === 0) const data = res.data
const hasSpecial = res.data.giftCardTemplates.map(e => e.id).includes(res.data.specialGiftCardTemplate.id) const temp = this.isGroupBuy ? data.giftCardTemplates : data.giftCardTemplates.filter(e => e.isTravelGroup === 0)
const initialCoverList = hasSpecial ? [...temp] : [...temp, res.data.specialGiftCardTemplate] const hasSpecial = data.giftCardTemplates.map(e => e.id).includes(data.specialGiftCardTemplate.id)
const goodsInfo = res.data.cartInfo[0] const initialCoverList = hasSpecial ? [...temp] : [...temp, data.specialGiftCardTemplate]
const { coverList, template } = this.adjustCoverListForProductStory(initialCoverList, goodsInfo && goodsInfo.productInfo, res.data.specialGiftCardTemplate) const goodsInfo = data.cartInfo[0]
const { coverList, template } = this.adjustCoverListForProductStory(initialCoverList, goodsInfo && goodsInfo.productInfo, data.specialGiftCardTemplate)
this.coverList = coverList this.coverList = coverList
this.giftNotice = res.data.giftCardGiftNotice this.giftNotice = data.giftCardGiftNotice
this.orderKey = res.data.orderKey this.orderKey = data.orderKey
this.goodsInfo = goodsInfo this.goodsInfo = goodsInfo
this.syncCountyLotteryGiftFlag(goodsInfo) this.syncCountyLotteryGiftFlag(goodsInfo)
this.templateId = template.id this.templateId = template.id
this.selectedCover = template.cover this.selectedCover = template.cover
this.giftImage = template.image this.giftImage = template.image
this.blindImage = res.data.giftCardBlindBoxShareImage this.blindImage = data.giftCardBlindBoxShareImage
this.defaultIndex = this.coverList.findIndex(item => item.id === this.templateId) this.defaultIndex = this.coverList.findIndex(item => item.id === this.templateId)
// if(!this.couponId) { // if(!this.couponId) {
// this.couponId = res.data.couponList.usable[0] && res.data.couponList.usable[0].id || '' // this.couponId = data.couponList.usable[0] && data.couponList.usable[0].id || ''
// } // }
this.computedPrice(this.goodsInfo.cartNum) this.computedPrice(this.goodsInfo.cartNum)
this.aiGiftImageHistoryReq()
this.isLoad = true this.isLoad = true
}).finally(() => { }).finally(() => {
this.loading = false this.loading = false
@@ -854,6 +980,7 @@ export default {
if (this.isCountyLotteryGift && this.isEligibleForDraw) { if (this.isCountyLotteryGift && this.isEligibleForDraw) {
this.showLotteryGiftPopup = true this.showLotteryGiftPopup = true
} }
this.aiGiftImageHistoryReq()
}, },
closeLotteryGiftPopup() { closeLotteryGiftPopup() {
this.showLotteryGiftPopup = false this.showLotteryGiftPopup = false
@@ -1333,19 +1460,28 @@ export default {
} }
.imgs-list-wrap { .imgs-list-wrap {
display: flex; display: flex;
justify-content: space-around; justify-content: center;
align-items: baseline; align-items: baseline;
gap: 24rpx; gap: 40rpx;
padding: 20rpx 0; padding: 20rpx 0;
box-sizing: border-box; box-sizing: border-box;
&.scrollable {
justify-content: flex-start;
flex-wrap: nowrap;
overflow-x: auto;
}
} }
.img-image { .img-image {
display: block; display: block;
height: 176rpx; height: 176rpx;
flex-shrink: 0;
&.active { &.active {
transform: scale(1.2); transform: scale(1.2) translateY(-16rpx);
} }
} }
.ai-img-list-wrap {
padding: 28rpx 0 20rpx 0;
}
} }
.ai-cover-bottom { .ai-cover-bottom {
margin-top: 12rpx; margin-top: 12rpx;