Task:礼品赠送/送礼、分享。收礼

This commit is contained in:
modendeveloper
2025-02-22 19:20:33 +08:00
parent f0a4a0edf9
commit aedc2fd768
9 changed files with 543 additions and 90 deletions
+185 -50
View File
@@ -1,18 +1,18 @@
<template>
<u-popup :show="show" mode="center" round="16">
<u-popup :show="show" @close="close" mode="center" round="16" closeable>
<view class="dialog-container">
<view class="dialog-title">填写收货地址</view>
<u-form :model="form" ref="uForm" labelPosition="left">
<u-form-item label="姓名" prop="name" borderBottom>
<u-input v-model="form.name" placeholder="请输入姓名" border="none"/>
<u-form :model="form" ref="uForm" labelPosition="left" labelWidth="100">
<u-form-item label="姓名:">
<u-input v-model="userAddress.realName" placeholder="请输入姓名" required border="none"/>
</u-form-item>
<u-form-item label="联系电话" prop="phone" borderBottom>
<u-input v-model="form.phone" placeholder="请输入联系电话" border="none"/>
<u-form-item label="联系电话:" >
<u-input v-model="userAddress.phone" placeholder="请输入联系电话" required border="none"/>
</u-form-item>
<u-form-item label="所在地区" prop="region" borderBottom>
<u-form-item label="所在地区:" >
<CitySelect
ref="cityselect"
:defaultValue="addressText"
@@ -21,11 +21,35 @@
></CitySelect>
</u-form-item>
<u-form-item label="详细地址" prop="address" borderBottom>
<u-input v-model="form.address" placeholder="请输入详细地址" border="none" />
<u-form-item label="详细地址:">
<u-input v-model="userAddress.detail" placeholder="请输入详细地址" required border="none" />
</u-form-item>
</u-form>
<view class="address-analysis-wrap">
<view class="inp">
<textarea
v-model.trim="addressInput"
placeholder="请粘贴收件人手机号、姓名、收货地址并用空格区分,系统将自动识别地址信息"
placeholder-style="font-size:24rpx;color:#C2C5CC;"
class="inp-textarea"
/>
</view>
<view class="btn-wrap">
<view
class="txt"
@click="clearHandle"
>
清空
</view>
<view
:class="addressInput ? '' : 'disable'"
class="btn"
@click="distinguishHandle"
>
识别
</view>
</view>
</view>
<view class="dialog-footer">
<u-button type="primary" color="#C52733" shape="circle" @click="handleSave">立即保存</u-button>
</view>
@@ -35,6 +59,9 @@
<script>
import CitySelect from '@/components/CitySelect'
import config from '@/utils/mapConfig'
import attrs, { chs_extphone, required } from '@/utils/validate'
import { validatorDefaultCatch } from '@/utils/dialog'
import { getAddress, getCity, postAddress, analysisAddress } from '@/api/user'
import { isWeixin } from '@/utils'
export default {
@@ -44,7 +71,7 @@ export default {
data() {
return {
district: [],
id: 0,
id: null,
// 是否选择地址模式:0-不是,1-来源订单创建页面,2-来源购物车
choosMode: 0,
userAddress: {
@@ -83,26 +110,124 @@ export default {
}
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
methods: {
clearHandle() {
if (!this.addressInput) return
this.addressInput = ''
},
// 识别
distinguishHandle() {
if (!this.addressInput) return
uni.showLoading()
analysisAddress({
content: this.addressInput
}).then((res) => {
uni.hideLoading()
console.log(res)
const { success, data } = res
if (success) {
this.address = {
province: data.province || '',
city: data.city || '',
district: data.district || '',
city_id: data.cityId
}
this.userAddress.realName = data.realName || ''
this.userAddress.phone = data.phone || ''
this.userAddress.detail = data.detail || ''
this.addressText = `${this.address.province} ${this.address.city} ${this.address.district}`
}
}).catch((err) => {
uni.hideLoading()
uni.showToast({
title: err.msg + '',
icon: 'none',
mask: false,
duration: 1500
})
})
},
open() {
this.show = true
this.getUserAddress()
this.getCityList()
},
result() {
close() {
this.show = false
},
result(values) {
this.address = {
province: values.province.name || "",
city: values.city.name || "",
district: values.district.name || "",
city_id: values.city.id
};
this.addressText = `${this.address.province} ${this.address.city} ${this.address.district}`;
// this.addressText =
// this.address.province + this.address.city + this.address.district;
},
handleRegionConfirm(e) {
this.form.region = e.province.label + ' ' + e.city.label + ' ' + e.area.label
},
handleSave() {
this.$refs.uForm.validate(valid => {
if (valid) {
// 这里处理保存逻辑
this.$emit('save', this.form)
this.show = false
}
})
async handleSave() {
const name = this.userAddress.realName || ''
const phone = this.userAddress.phone || ''
const addressText = this.addressText || ''
const detail = this.userAddress.detail || ''
const isDefault = this.userAddress.isDefault
if (phone.length < 11) {
uni.showToast({
title: "请输入11位手机号码",
icon: "none"
})
return;
}
try {
await this.$validator({
name: [
required(required.message("姓名")),
attrs.range([2, 16], attrs.range.message("姓名"))
],
phone: [
required(required.message("联系电话")),
chs_extphone(chs_extphone.message())
//chs_phone(chs_phone.message())
],
addressText: [required("请选择地址")],
detail: [required(required.message("具体地址"))]
}).validate({name, phone, addressText, detail});
} catch (e) {
return validatorDefaultCatch(e);
}
try {
let that = this,
data = {
id: that.id,
real_name: name,
phone: phone,
address: this.address,
detail: detail,
is_default: isDefault ? true : false,
post_code: ""
};
postAddress(data).then((res) => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.$emit('save', res.data.id)
});
} catch (err) {
uni.showToast({
title: err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
},
//获取当前定位地址
getCurAddress() {
@@ -235,38 +360,48 @@ export default {
that.$dialog.error(err.msg);
});
},
getUserAddress: function () {
if (!this.id) return false;
let that = this;
getAddress(that.id).then(res => {
that.userAddress = res.data;
that.addressText = res.data.province + " " + res.data.city + " " + res.data.district;
that.address.province = res.data.province;
that.address.city = res.data.city;
that.address.district = res.data.district;
if (that.district.length > 0) {
//设置city_id
var pIdx = that.getIndex(that.address.province, that.district);
if (pIdx > -1) {
var citys = that.district[pIdx].c;
var cIdx = that.getIndex(that.address.city, citys);
if (cIdx > -1) {
var city = citys[cIdx];
that.address.city_id = city.v;
console.log('city_id:' + city.v);
}
}
}
});
},
getAddress() {
},
}
}
</script>
<style scoped>
<style lang="less" scoped>
.address {
text {
width: 100%;
display: block;
}
}
.address-analysis-wrap {
padding: 20rpx;
margin: 20rpx;
border-radius: 15rpx;
background-color: #fff;
font-size: 24rpx;
.inp-textarea {
width: 100%;
height: 120rpx;
}
.btn-wrap {
display: flex;
justify-content: flex-end;
align-items: center;
margin: 20rpx 0 0 0;
.txt {
color: #999;
}
.btn {
padding: 12rpx 25rpx;
margin: 0 0 0 20rpx;
border-radius: 8rpx;
color: #fff;
background-color: #FE5261;
&.disable {
opacity: 0.75;
}
}
}
}
.dialog-container {
width: 600rpx;
padding: 40rpx;
@@ -0,0 +1,146 @@
<template>
<!-- 使用u-popup包裹整个地址列表 -->
<u-popup
:show="showPopup"
:safeAreaInsetBottom="false"
mode="center"
round="16"
closeable
@close="close"
@open="open"
>
<view class="v12-text-center v12-font-bold v12-mt-3">收货地址</view>
<view class="address-list">
<!-- 地址列表 -->
<view
class="address-item"
>
<view class="address-wrap" @click="handleSelect(addressList)">
<view class="v12-font-28 v12-font-bold">
收货地址
</view>
<view>
<view class="info">
<text class="v12-font-28 v12-font-bold v12-dark-text">{{ addressList.realName }}</text>
<text class="v12-font-28 v12-font-bold v12-dark-text v12-ml-1">{{ addressList.phone }}</text>
</view>
<view class="address v12-font-bold v12-font-28 v12-dark-text v12-mt-3 v12-mb-4">
{{ addressList.province + addressList.city + addressList.district + addressList.detail }}
<view @click.stop="editAddress">
<u-icon :name="webUrl+'/orderIcon/edit02.png'" color="#C52733"></u-icon>
</view>
</view>
</view>
</view>
</view>
<!-- 添加新地址按钮 -->
<view class="add-btn v12-primary v12-white-text" @click="addNewAddress">
<text>添加新地址</text>
</view>
</view>
</u-popup>
</template>
<script>
export default {
props: {
addressList: {
type: Object,
default: () => {}
}
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
showPopup: false, // 新增控制弹窗显示的状态
}
},
methods: {
editAddress() {
this.$yrouter.push({
path: "/pages/user/address/AddressManagement/index",
query: {
choosMode: 3
}
});
},
// 选择地址
handleSelect(item) {
uni.showModal({
title: '提示',
content: '确认选择这个收货地址吗?',
success: (res) => {
if (res.confirm) {
this.$emit('save', item.id)
}
}
})
},
// 添加新地址
addNewAddress() {
this.$yrouter.push({
path: "/pages/user/address/AddAddress/index",
query: {
choosMode: 3
}
});
},
// 新增打开弹窗方法
open() {
this.showPopup = true
},
// 新增关闭弹窗方法
close() {
this.showPopup = false
},
}
}
</script>
<style scoped>
.address-wrap{
display: flex;
justify-content: center;
margin-bottom: 20rpx;
}
.address-list {
padding: 20rpx;
width: 640rpx;
}
.address-item {
padding: 20rpx;
}
.info {
display: flex;
justify-content: flex-start;
margin-bottom: 10rpx;
}
.name {
font-size: 28rpx;
font-weight: bold;
}
.phone {
font-size: 28rpx;
color: #666;
}
.address {
font-size: 26rpx;
color: #888;
display: flex;
}
.add-btn {
margin-top: 30rpx;
padding: 20rpx;
text-align: center;
background-color: #fff;
border: 1rpx solid #ddd;
border-radius: 100rpx;
}
</style>
+48 -6
View File
@@ -13,13 +13,19 @@
:circular="true"
:indicator-dots="false"
@change="onChange"
previous-margin="160rpx"
next-margin="160rpx"
previous-margin="180rpx"
next-margin="180rpx"
class="cover-swiper"
>
<swiper-item v-for="(item, index) in list" :key="index" >
<swiper-item v-for="(item, index) in list" :key="index">
<view class="cover-item">
<image :src="item.image" :class="{ 'v12-mt-3': currentIndex === index }" class="cover-image" mode="widthFix|heightFix" />
<view class="img-wrap" :class="{ 'v12-mt-8': currentIndex === index }">
<view class="pro-img-wrap ">
<image :src="product.image" class="pro-cover-image" mode="widthFix|heightFix" />
</view>
<image :src="item.cover" class="cover-image" mode="widthFix|heightFix" />
<view class="message-text">{{ message || '礼笺轻启,礼藏心意' }}</view>
</view>
<view class="cover-name">{{ item.name }} </view>
</view>
</swiper-item>
@@ -44,6 +50,14 @@ export default {
list: {
type: Array,
default: () => []
},
product: {
type: Object,
default: () => {}
},
message: {
type: String,
default: ''
}
},
data() {
@@ -67,6 +81,34 @@ export default {
</script>
<style lang="less" scoped>
.message-text{
position: absolute;
text-align: center;
top: 200rpx;
font-size: 24rpx;
color: #fff;
left: 0;
right: 0;
margin: auto;
}
.pro-cover-image{
width: 160rpx;
height: 160rpx;
}
.pro-img-wrap{
position: absolute;
width: 160rpx;
height: 160rpx;
left: 0;
right: 0;
margin: auto;
border: 10rpx solid #FDF0D3;
top: -30px;
}
.img-wrap{
position: relative;
transition: all .2s ease-in-out;
}
.tips{
font-size: 24rpx;
color: #999;
@@ -90,8 +132,8 @@ export default {
flex-direction: column;
align-items: center;
.cover-image {
width: 380rpx;
height: 460rpx;
width: 320rpx;
height: 400rpx;
border-radius: 16rpx;
transition: all .2s ease-in-out;
}
+96 -13
View File
@@ -2,7 +2,7 @@
<view class="mask">
<view class="gift-card-modal" >
<image class="bg-image" :src="card.cover" mode="aspectFit|aspectFill|widthFix" lazy-load="false"></image>
<view class="image-wrap">
<view class="image-wrap" v-if="!card.isReceive">
<image class="pro-image" :src="card.giftProducts[0].productImage" mode="aspectFit|aspectFill|widthFix" lazy-load="false" @error="" @load="">
</image>
@@ -10,16 +10,28 @@
<view class="wrap-box">
</view>
<view class="auto-text-color">
<view class="auto-text-color" v-if="!card.isReceive">
{{ card.message || '礼笺轻启礼藏心意' }}
</view>
<view v-if="isReceive && !card.isReceive" @click="toOrder" style="z-index: 89999">
<view class="address-btn v12-white v12-primary-text">
您已领取礼包
</view>
<view class="v12-text-center v12-font-26 v12-white-text v12-mt-3">查看礼包详情>></view>
</view>
<view v-if="card.isReceive" @click="toHome" style="z-index: 89999">
<view class="address-btn v12-white v12-primary-text">
礼包已被领取
</view>
<view class="v12-text-center v12-font-26 v12-white-text v12-mt-3">去商城看看>></view>
</view>
<!-- 弹窗内容 -->
<view class="address-btn v12-white v12-primary-text" @click="setAddress">
<view v-if="!isReceive && !card.isReceive" class="address-btn v12-white v12-primary-text" @click="setAddress">
填写地址并收下
</view>
<view class="share-btn v12-white v12-primary-text" v-if="card.canTransfer !== 0">
<button open-type="share" class="share-btn v12-white v12-primary-text" v-if="card.canTransfer !== 0 && !isReceive">
点击转增给好友
</view>
</button>
<view class="tips">
<view class="tip-text v12-mr-1">
未领取礼包将于24小时后自动
@@ -28,36 +40,107 @@
</view>
</view>
<giftTips ref="giftTips" :richText="giftNotice"></giftTips>
<AddressDialog ref="addressDialog" ></AddressDialog>
<AddressDialog ref="addressDialog" @save="getReceive"></AddressDialog>
<AddressList ref="AddressList" :addressList="address" @save="getReceive"></AddressList>
</view>
</template>
<script>
import { getGiftCardSendNotice } from '@/api/gift'
import { getGiftCardSendNotice, getGiftCardReceive } from '@/api/gift'
import { getAddressList } from '@/api/user'
import giftTips from './giftTips.vue'
import AddressDialog from './AddressDialog.vue'
import AddressList from './AddressList.vue'
export default {
name: 'GiftCard',
components: {
giftTips,
AddressDialog
AddressDialog,
AddressList
},
props: {
// 组件属性
card: {
type: Object,
default: () => {}
},
addr: {
type: Object,
default: () => {}
}
},
data() {
return {
// 组件数据
giftNotice: ''
giftNotice: '',
isReceive: false,
address: {},
order: ''
}
},
watch: {
addr: {
handler(newVal, oldVal) {
if (newVal && newVal.id) {
this.address = newVal
}
},
deep: true
}
},
onShareAppMessage() {
return {
title: '送朋友',
path: `/pkg_user/views/gift/receive?code=${this.card.code}`,
imageUrl: this.card.image
}
},
methods: {
// 分享到微信好友
toShare() {
// 分享到微信好友
},
toOrder() {
this.$yrouter.push({
path: "/pages/order/OrderDetails/index",
query: {
id: this.order
}
});
},
toHome() {
console.log('??');
uni.switchTab({
url: '/pages/home/index'
})
},
getReceive(e) {
uni.showLoading({
title: '领取中...',
mask: true
})
// 领取礼包
getGiftCardReceive({
code: this.card.code,
addressId: e
}).then(res => {
this.$refs.addressDialog.close()
this.$refs.AddressList.close()
this.order = res.data.orderId
this.isReceive = true
}).finally(() => {
uni.hideLoading()
})
},
setAddress() {
this.$refs.addressDialog.open()
getAddressList().then(res => {
if (res.data.length === 0) {
this.$refs.addressDialog.open()
} else {
this.address = res.data.filter(item => item.isDefault === 1).length === 0 ? res.data[0] : res.data.filter(item => item.isDefault === 1)[0]
this.$refs.AddressList.open()
}
})
},
async showTips() {
// 获取发礼提示
@@ -113,11 +196,11 @@ export default {
.auto-text-color {
color: #fff;
font-size: 24rpx;
opacity: 0.9;
opacity: 0.8;
margin-top: 50rpx;
}
.share-btn{
width: fit-content;
padding: 15rpx 30rpx;
border-radius: 100rpx;
font-size: 24rpx;
margin-top: 40rpx;
@@ -140,7 +223,7 @@ export default {
bottom: 0;
width: 586rpx;
height: 704rpx;
background-color: #C52733;
/* background-color: #C52733; */
justify-content: center;
z-index: 999;
margin: auto;
+23 -9
View File
@@ -4,11 +4,15 @@
<view class="v12-justify-between v12-pa-2">
<view>
<view></view>
<view class="v12-font-28 v12-secondary-dark-text">送礼寄语</view>
<view class="v12-font-28 v12-secondary-dark-text v12-d-flex">
<u-icon :name="webUrl + '/icon/gift-primary.png'"></u-icon>
送礼寄语
</view>
</view>
<view class="v12-primary-text v12-font-26">
<view class="v12-primary-text v12-font-26 v12-d-flex v12-align-center">
<view @click="showCoverPicker = true">{{ cover }}封面</view>
<view>
<u-icon name="arrow-right" color="#c52733"></u-icon>
</view>
</view>
</view>
@@ -71,13 +75,13 @@
</view>
<u-divider v-if="isPayOk"></u-divider>
<view class="v12-font-26 v12-secondary-dark-text" v-if="isPayOk">
赠言{{ message }}
赠言{{ message || '礼笺轻启礼藏心意' }}
</view>
</view>
<view class="swich-btn" v-if="!isPayOk">
<view class="v12-font-28 v12-dark-text">是否支持好友转赠</view>
<view>
<u-switch v-model="canTransfe" ></u-switch>
<u-switch v-model="canTransfer" ></u-switch>
</view>
</view>
<button v-if="isPayOk" open-type="share" class="share-btn" >
@@ -102,7 +106,9 @@
<CoverPicker
:show.sync="showCoverPicker"
:list="coverList"
:product="goodsInfo.productInfo"
@confirm="onCoverConfirm"
:message="message"
/>
<passkeyborad
ref='payPwdPop'
@@ -137,7 +143,7 @@ export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
canTransfe: false,
canTransfer: false,
message: '',
cartId: '',
couponId: '',
@@ -146,6 +152,7 @@ export default {
showCoverPicker: false,
showPayPicker: false,
selectedCover: '',
giftImage: '',
orderKey: '',
goodsInfo: {},
cover: '默认',
@@ -170,7 +177,7 @@ export default {
return {
title: '送朋友',
path: `/pkg_user/views/gift/receive?code=${this.giftKey}`,
imageUrl: this.goodsInfo.productInfo.image
imageUrl: this.giftImage
}
},
methods: {
@@ -185,7 +192,8 @@ export default {
onCoverConfirm(cover) {
this.cover = cover.name
this.templateId = cover.id
this.selectedCover = cover.image
this.selectedCover = cover.cover
this.giftImage = cover.image
},
showTips() {
this.$refs.giftTips.showTips = true
@@ -235,7 +243,7 @@ export default {
templateId: this.templateId,
message : this.message,
cover: this.selectedCover,
canTransfe: this.canTransfe,
canTransfer: this.canTransfer ? 1 : 0,
payType: this.payType,
seckillId: this.orderGroupInfo.seckill_id,
combinationId: this.orderGroupInfo.combination_id,
@@ -287,7 +295,13 @@ export default {
case "WECHAT_PAY":
// 小程序支付
weappPay(data.result.jsConfig).finally(() => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.isPayOk = true;
this.giftKey = data.giftCard.code;
});
break;
+15 -5
View File
@@ -1,6 +1,6 @@
<template>
<view>
<GiftCard :card="giftCard"/>
<GiftCard :card="giftCard" :addr="giftChooseAddress" />
</view>
</template>
@@ -13,18 +13,28 @@ export default {
},
data() {
return {
giftCard: {}
giftCard: {},
giftChooseAddress: {}
}
},
onLoad(opts) {
this.getGiftCard(opts.code)
},
onShow() {
this.giftChooseAddress = uni.getStorageSync('giftChooseAddress') || {}
},
methods: {
async getGiftCard(code) {
const res = await getGiftCardDetail({
getGiftCard(code) {
getGiftCardDetail({
code: code
}).then(res => {
this.giftCard = res.data || {}
}).catch(err => {
this.giftCard = {
canTransfer: 0,
isReceive: true
}
})
this.giftCard = res.data
},
}