2.2提交

This commit is contained in:
zoujiandong
2026-02-02 17:44:10 +08:00
parent d06ee397cf
commit a7b2a673a9
54 changed files with 3615 additions and 1317 deletions
+54 -21
View File
@@ -18,9 +18,9 @@
<view class="form-item" v-if="type==2">
<view class="label">邮箱</view>
<input class="input" v-model="email" type="text" placeholder="用于接收电子卡等信息(可选)" />
<input class="input" v-model="email" type="text" placeholder="请输入您的邮箱" />
</view>
<view class="divider-line" v-if="type==2"></view>
<view class="form-item select-item" @click="openAreaPicker" v-if="type==1">
<view class="label">地址</view>
@@ -28,13 +28,13 @@
<view class="input" v-else>{{ regionText }}</view>
<text class="arrow">›</text>
</view>
<view class="divider-line"></view>
<view class="divider-line" v-if="type==1"></view>
<view class="form-item" v-if="type==1">
<view class="label">详细地址</view>
<input class="input" v-model="detail" placeholder="请输入街道、门牌等详细地址信息" />
</view>
<view class="divider-line"></view>
<view class="divider-line" v-if="type==1"></view>
</scroll-view>
<view class="footer-bar" @click="submit">
@@ -64,28 +64,33 @@
</view>
</view>
<unidialog
:title="'确认收货信息'"
:title="'确认兑换信息'"
:visible="freeVisible"
:content="freeContent"
:titleColor="'#000'"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人:</view>
<view class="left">收件人:</view>
<view class="right">{{ receiver }}</view>
</view>
<view class="row">
<view class="left">手机号:</view>
<view class="left">手机号:</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row" >
<view class="left">地址:</view>
<view class="row" v-if="type==1">
<view class="left">地址:</view>
<view class="right">{{ regionText+detail }}</view>
</view>
<view class="row" v-else>
<view class="left">邮箱:</view>
<view class="right">{{ email?email:'无' }}</view>
</view>
<view class="row">
<view class="left">兑换积分:</view>
<view class="left">兑换积分:</view>
<view class="right"><text class="price">{{ points }}积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换,物品不退不换</view>
@@ -118,13 +123,13 @@ const freeConfirm = () => {
uni.showToast({
title: '兑换成功',
icon: 'none',
duration: 2000
duration: 1000
});
setTimeout(() => {
uni.navigateBack({
delta: 2
navTo({
url: '/pages_goods/pointMall/pointMall?from=exchange'
})
}, 2000)
}, 1000)
}
})
}
@@ -208,9 +213,30 @@ onLoad((opts) => {
goodsUuid.value = opts.goodsUuid
goodsNum.value = opts.goodsNum;
type.value = opts.type;
getAddress()
})
const saveAddress = () => {
uni.setStorageSync('goods_address', {
receiver: receiver.value,
mobile: mobile.value,
regionText: regionText.value,
detail: detail.value,
email: email.value
})
}
const getAddress = () => {
const address = uni.getStorageSync('goods_address')
if(address){
receiver.value = address.receiver
mobile.value = address.mobile
regionText.value = address.regionText
detail.value = address.detail
email.value = address.email
}
}
const submit = () => {
if (!receiver.value) return uni.showToast({ title: '请输入收件人', icon: 'none' })
if (!/^1\d{10}$/.test(mobile.value)) return uni.showToast({ title: '请输入正确手机号', icon: 'none' })
@@ -220,6 +246,7 @@ const submit = () => {
}else{
if (email.value && !/^([a-zA-Z0-9_\.-]+)@([a-zA-Z0-9\.-]+)\.([a-zA-Z]{2,})$/.test(email.value)) return uni.showToast({ title: '邮箱格式不正确', icon: 'none' })
}
saveAddress();
goods_api.createGoodsOrder({
goodsUuid: goodsUuid.value,
goodsNum: goodsNum.value,
@@ -229,22 +256,27 @@ const submit = () => {
address: regionText.value+detail.value
}).then(res => {
if(res.code == 1 || res.code == 200){
points.value = res.data.pionts*res.data.goods_num;
points.value = res.data.pionts;
freeVisible.value = true
goods_order_id.value = res.data.goods_order_id
}
})
}
</script>
<style scoped lang="scss">
.address-page :deep(.dialog-title){
color:#000!important;
}
.address-page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
.form-item { display: flex; align-items: center; padding: 24rpx; }
.form-item { display: flex; align-items: center; padding: 30rpx 24rpx; }
.label { width: 160rpx; color: #333; font-size: 30rpx; }
.input { flex: 1; color: #333; font-size: 30rpx; }
.placeholder { color: #bbb; }
.placeholder { color: #808080; }
.divider-line { height: 2rpx; background: #eee; margin: 0 24rpx; }
.select-item { position: relative; }
.arrow { position: absolute; right: 24rpx; color: #999; font-size: 48rpx; }
@@ -263,15 +295,16 @@ const submit = () => {
.picker-empty { padding: 40rpx; text-align: center; color: #999; }
.row{
display: flex;
align-items: center;
align-items: flex-start;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
margin-left: -100rpx;
.left{
text-align: left;
max-width: 125rpx;
max-width: 142rpx;
white-space: nowrap;
width:auto!important;
}
.price{
+437
View File
@@ -0,0 +1,437 @@
<template>
<view class="page">
<navBar :title="'兑换详情'" />
<scroll-view scroll-y class="content">
<!-- 兑换详情信息区域 -->
<view class="detail-card">
<view class="detail-row">
<text class="detail-label">兑换号:</text>
<text class="detail-value">{{ exchangeNo }}</text>
</view>
<view class="detail-row" style="align-items: flex-start;">
<text class="detail-label">兑换物品:</text>
<text class="detail-value">{{ goodsName }}</text>
</view>
<view class="detail-row">
<text class="detail-label">兑换数量:</text>
<text class="detail-value">{{ quantity }}</text>
</view>
<view class="detail-row">
<text class="detail-label">积分:</text>
<text class="detail-value points-value">{{ points }}</text>
</view>
<view class="detail-row">
<text class="detail-label">创建时间:</text>
<text class="detail-value">{{ createTime }}</text>
</view>
<view class="detail-row" v-if="type == 1">
<text class="detail-label">物流:</text>
<text class="detail-value">{{ logistics }}</text>
</view>
<view class="detail-row logistics-row" v-if="type == 1">
<text class="detail-label">物流编号:</text>
<view class="logistics-no-wrapper">
<text class="detail-value logistics-no" >{{ logisticsNo }}</text>
<view class="copy-btn" @click="copyLogisticsNo" v-if="logisticsNo ">复制</view>
</view>
</view>
<view class="detail-row" v-if="type == 2">
<text class="detail-label">手机号:</text>
<text class="detail-value">{{ mobile }}</text>
</view>
</view>
</scroll-view>
<!-- 底部快递查询按钮 -->
<view class="bottom-bar" @click="goLogistics" v-if="status == 4 && type == 1 && logistics && logisticsNo">
<text class="query-btn-text">快递查询</text>
</view>
<view class="bottom-bar bew" v-if="status == 1 && restTime > 0">
<view class="left"><up-count-down :time="restTime" format="mm:ss" @finish="finishCount"></up-count-down>分钟后此订单自动取消</view>
<view class="right">
<view class="cancel" @click="cancelOrder">取消订单</view>
<view class="pay" @click="goPay">去支付</view>
</view>
</view>
</view>
<unidialog
:title="'确认兑换信息'"
:visible="freeVisible"
:content="freeContent"
:titleColor="'#000'"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人:</view>
<view class="right">{{ user_name }}</view>
</view>
<view class="row">
<view class="left">手机号:</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row" v-if="type==1">
<view class="left">地址:</view>
<view class="right">{{ address }}</view>
</view>
<view class="row" v-else>
<view class="left">邮箱:</view>
<view class="right">{{ email }}</view>
</view>
<view class="row">
<view class="left">兑换积分:</view>
<view class="right"><text class="price">{{ points }}积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换,物品不退不换</view>
</view>
</template>
</unidialog>
</template>
<script setup>
import navBar from '@/components/navBar/navBar.vue';
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue';
import goods_api from '@/api/goods_api';
import navTo from '@/utils/navTo';
import unidialog from '@/components/dialog/dialog.vue';
import dayjs from 'dayjs';
const id = ref('');
const user_name = ref('');
const address = ref('');
const email = ref('');
const goods_order_id = ref('');
const cancelOrder = () => {
goods_api.cancelGoodsOrder({
goods_order_uuid: exchangeNo.value,
}).then(res => {
if(res.code == 200){
uni.showToast({
title: '取消成功',
icon: 'none',
duration: 2000
});
fetchExchangeDetail()
}
})
}
onLoad((options) => {
if (options && options.id) {
id.value = options.id;
}
fetchExchangeDetail()
});
// 响应式数据
const restTime = ref(0);
const exchangeNo = ref('');
const goodsName = ref('');
const quantity = ref();
const points = ref();
const createTime = ref('2');
const logistics = ref('');
const logisticsNo = ref('');
const mobile = ref('');
const type = ref(1);
const status = ref(null);
const freeVisible = ref(false)
// 复制物流编号
const freeClose = () => {
freeVisible.value = false
}
const freeConfirm = () => {
freeVisible.value = false;
goods_api.payGoodsOrder({
goods_order_uuid: goods_order_id.value,
}).then(res => {
if(res.code == 1 || res.code == 200){
uni.showToast({
title: '兑换成功',
icon: 'none',
duration:1000
});
setTimeout(() => {
navTo({
url: '/pages_goods/pointMall/pointMall?from=exchange'
})
}, 1000)
}
})
}
const finishCount = () => {
restTime.value = 0;
cancelOrder();
}
const copyLogisticsNo = () => {
uni.setClipboardData({
data: logisticsNo.value,
success: () => {
uni.showToast({
title: '已复制',
icon: 'none'
});
},
fail: () => {
uni.showToast({
title: '复制失败',
icon: 'none'
});
}
});
};
// 跳转到物流查询页面
const goLogistics = () => {
uni.navigateTo({
url: `/pages_goods/logistics/logistics?order_id=${exchangeNo.value}&name=${logistics.value}`
});
};
const goPay = () => {
console.log('222')
freeVisible.value = true
};
// 格式化时间
const formatDateTime = (timestamp) => {
if (!timestamp) return '';
const d = new Date(Number(timestamp) * 1000);
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const h = String(d.getHours()).padStart(2, '0');
const min = String(d.getMinutes()).padStart(2, '0');
return `${y}-${m}-${day} ${h}:${min}`;
};
// 获取兑换详情(如果需要从API获取)
const fetchExchangeDetail = async () => {
try {
// 这里可以调用相应的API获取订单详情
const res = await goods_api.getGoodsOrderDetail({
uuid:id.value
});
if (res.code === 200 && res.data) {
const data = res.data;
exchangeNo.value = data.goods_order_id || '';
goodsName.value = data.name || '';
quantity.value = data.goods_num || 0;
points.value = data.pionts || 0;
createTime.value = formatDateTime(data.create_date) || '';
logistics.value = data.express_name || '';
logisticsNo.value = data.express_id || '';
mobile.value = data.mobile || '';
type.value = data.type;
status.value = data.status;
goods_order_id.value = data.goods_order_id;
user_name.value = data.user_name || '';
address.value = data.address || '';
email.value = data.email || '';
let time1=dayjs(new Date().getTime());
//console.log(dayjs(data.time_expire*1000).format('YYYY-MM-DD HH:mm:ss'))
let time2=dayjs(data.time_expire*1000);
restTime.value = time2.diff(time1, 'millisecond');
if(restTime.value <=0 && status.value == 1){
cancelOrder();
}
console.log(restTime.value)
}
} catch (e) {
console.error('获取兑换详情失败:', e);
uni.showToast({
title: '获取详情失败',
icon: 'none'
});
}
};
</script>
<style scoped lang="scss">
.page {
min-height: 100vh;
background: #f5f5f5;
:deep(.dialog-title){
color:#000;
}
:deep(.u-count-down__text){
color:#ff0000!important;
}
}
.content {
position: absolute;
top: calc(var(--status-bar-height) + 44px);
bottom: 100rpx;
left: 0;
right: 0;
background: #f5f5f5;
}
// 兑换详情卡片
.detail-card {
background: #fff;
padding: 30rpx;
// border-radius: 16rpx;
margin-bottom: 40rpx;
padding-top: 0;
}
.detail-row {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
}
.detail-label {
color: #333;
font-size: 30rpx;
white-space: nowrap;
width: 180rpx;
flex-shrink: 0;
}
.detail-value {
color: #666;
font-size: 30rpx;
flex: 1;
word-break: break-all;
}
// 积分值红色显示
.points-value {
color: #ff0000;
font-weight: 500;
}
// 物流编号行
.logistics-row {
align-items: center;
}
.logistics-no-wrapper {
display: flex;
align-items: center;
flex: 1;
gap: 20rpx;
}
.logistics-no {
flex: 1;
}
// 复制按钮
.copy-btn {
background: #ff0000;
color: #fff;
font-size: 24rpx;
padding: 8rpx 20rpx;
border-radius: 8rpx;
white-space: nowrap;
flex-shrink: 0;
}
// 参考提示文字
.reference-text {
text-align: center;
color: #ff0000;
font-size: 30rpx;
padding: 40rpx 0;
}
// 底部按钮
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #27c5b8;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.bottom-bar.bew{
display: flex;
align-items: center;
justify-content: space-between;
background:#efefef;
.left{
display: flex;
align-items: center;
white-space: nowrap;
font-size: 26rpx;
margin-left: 30rpx;
color: #666;
}
.right{
margin-right: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.cancel{
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #666;
padding: 10rpx 20rpx;
border-radius: 10rpx;
border: 2rpx solid #666;
}
.pay{
display: flex;
align-items: center;
margin-left: 20rpx;
justify-content: center;
font-size: 26rpx;
color: #ffff;
background: #8b2116;
padding: 10rpx 20rpx;
border-radius: 10rpx;
border: 2rpx solid #8b2116;
}
}
}
.query-btn-text {
color: #fff;
font-size: 32rpx;
font-weight: 500;
}
.row{
display: flex;
align-items: flex-start;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
.left{
text-align: left;
max-width: 141rpx;
white-space: nowrap;
width:auto!important;
}
.price{
color: #FF4D4F;
}
}
.left{
width: 160rpx;
}
</style>
+29 -9
View File
@@ -18,7 +18,10 @@
</view> -->
<view class="goods-title">{{ title }}</view>
<view class="price">{{ price }}积分</view>
<view class="top-row flex">
<view class="price">{{ price }}积分</view>
<view class="times" v-if="times>0">已兑换{{ times }}次</view>
</view>
<view class="divider"></view>
@@ -31,8 +34,8 @@
</view>
</view>
<view class="section">
<view class="section-label">所需积分</view>
<view class="section flex">
<view class="section-label" style="margin-bottom: 0;">所需积分</view>
<view class="need-points">{{ needPoints }}积分</view>
</view>
</scroll-view>
@@ -42,7 +45,8 @@
</view>
</view>
<unidialog
:title="'确认收货信息'"
:title="'确认兑换信息'"
:titleColor="'#000'"
:visible="freeVisible"
:content="freeContent"
@close="freeClose"
@@ -66,9 +70,10 @@ const freeClose = () => {
const freeConfirm = () => {
freeVisible.value = false;
navTo({
url: '/pages_app/buyPoint/buyPoint'
url: '/pages_app/buyPoint/buyPoint?product_id='+id.value+'&type=goods'
})
}
const times=ref(0);
const title = ref('')
const price = ref(0)
const qty = ref(1)
@@ -92,13 +97,15 @@ onLoad((opts) => {
price.value = Number(opts.price || 0)
id.value = opts.id || ''
type.value = opts.type
times.value = opts.times
setQty(1)
getTotalPoints()
}
})
onShow(() => {
loadAddress()
getTotalPoints()
})
const STORAGE_KEY = 'goods_addresses'
@@ -183,6 +190,19 @@ const getTotalPoints = () => {
</script>
<style scoped>
.flex{
display: flex;
align-items: center;
justify-content: space-between;
}
.top-row {
padding-bottom: 24rpx;
padding-right: 24rpx;
}
.top-row .times{
color: #999;
font-size: 28rpx;
}
.exchange-page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
.addr-card { background: #fff; padding: 24rpx; border-bottom: 1rpx solid #f0f0f0; }
@@ -194,12 +214,12 @@ const getTotalPoints = () => {
.addr-row.small { color: #666; font-size: 26rpx; }
.addr-empty { color: #bbb; font-size: 28rpx; }
.goods-title { padding: 24rpx; font-size: 32rpx; color: #333; line-height: 1.6; }
.price { padding: 0 24rpx 24rpx; color: #e74c3c; font-size: 30rpx; }
.price { padding: 0 24rpx 0rpx; color: #e74c3c; font-size: 30rpx; }
.divider { height: 16rpx; background: #f5f5f5; }
.section { padding: 24rpx; }
.section-label { color: #333; font-size: 30rpx; margin-bottom: 20rpx; }
.qty-row { display: flex; gap: 24rpx; }
.qty-btn { flex: 1; text-align: center; height: 96rpx; line-height: 96rpx; border: 2rpx solid #38c1b1; color: #38c1b1; border-radius: 12rpx; font-size: 36rpx; }
.qty-row { display: flex; justify-content: space-between; }
.qty-btn { flex: 1;max-width:205rpx; text-align: center; height: 96rpx; line-height: 96rpx; border: 2rpx solid #38c1b1; color: #38c1b1; border-radius: 12rpx; font-size: 36rpx; }
.qty-btn.active { background: #38c1b1; color: #fff; }
.need-points { color: #333; font-size: 30rpx; text-align: right; }
.footer-bar { position: fixed; left: 0; right: 0; bottom: 0; height: 120rpx; background: #27c5b8; display: flex; align-items: center; justify-content: center; }
+348
View File
@@ -0,0 +1,348 @@
<template>
<navBar :title="'物流信息'"></navBar>
<view class="logistics-page">
<!-- 顶部导航 -->
<!-- 内容区域 -->
<scroll-view class="content" scroll-y>
<!-- 头部基础信息 -->
<view class="base-info" v-if="hasData">
<view class="row">
<text class="label">信息来源:</text>
<text class="value">{{ logisticsInfo.source }}</text>
</view>
<view class="row waybill-row">
<text class="label">运单编号:</text>
<text class="value">{{ logisticsInfo.waybillNo }}</text>
<view class="btn-copy" @click="onCopy">
复制
</view>
</view>
</view>
<!-- 时间轴 -->
<view class="timeline" v-if="hasData">
<view class="left"></view>
<!-- 左侧日期 -->
<up-steps current="0" direction="column" dot>
<up-steps-item :desc="item.context" v-for="(item, index) in logisticsList">
<template #title>
<view class="timebox">
<text class="time">{{ formatDate(item.time) }}</text>
<text class="date">{{ formatTime(item.time) }}</text>
</view>
</template>
</up-steps-item>
</up-steps>
<!-- <view
v-for="(item, index) in logisticsList"
:key="index"
class="timeline-item"
>
</view> -->
</view>
<empty :emptyDesc="'暂无物流信息'" v-else />
</scroll-view>
</view>
</template>
<script setup>
import { ref } from "vue";
import navBar from "@/components/navBar/navBar.vue";
import goodsApi from "@/api/goods_api";
import { onLoad } from "@dcloudio/uni-app";
import empty from "@/components/empty/empty.vue";
import dayjs from "dayjs";
const hasData = ref(false);
onLoad((options) => {
console.log(options);
if(options.order_id){
order_id.value = options.order_id;
}
if(options.name){
logisticsInfo.value.source = options.name;
}
getLogisticsInfo();
});
const order_id = ref('');
const logisticsInfo = ref({
source: "",
waybillNo: "",
});
const getLogisticsInfo = async () => {
const res = await goodsApi.getOrderTrack({
order_id: order_id.value,
});
if(res.code==200){
logisticsInfo.value.waybillNo=res.data.nu;
if(res.data && res.data.data.length > 0){
hasData.value = true;
logisticsList.value = res.data.data;
}else{
hasData.value = false;
}
}
};
const formatDate = (time) => {
return dayjs(time).format("MM-DD");
};
const formatTime = (time) => {
return dayjs(time).format("HH:mm");
};
// 模拟数据,布局参考上传截图
const logisticsList = ref([
{
date: "01-27",
time: "01:14",
desc: "您的快件离开【华北转运中心】,已发往【乌鲁木齐转运中心】。预计【01月30日】到达【乌鲁木齐市】,因运输距离较远,预计将在【30日晚上】为您更新快件状态,请您放心!",
},
{
date: "01-27",
time: "00:17",
desc: "您的快件已经到达【华北转运中心】。【物流问题无需找商家或平台,请致电(专属热线:95554)更快解决】",
},
{
date: "01-26",
time: "23:24",
desc: "您的快件离开【河北省廊坊市固安县】,已发往【华北转运中心】",
},
{
date: "01-26",
time: "18:31",
desc: "您的快件在【河北省廊坊市固安县】已揽收,揽收人:邢徐芳(18832637908)【物流问题无需找商家或平台,请致电(专属热线:95554)更快解决】",
},
]);
const onBack = () => {
// 使用 uni-app 返回上一页
uni.navigateBack({
delta: 1,
});
};
const onCopy = () => {
uni.setClipboardData({
data: logisticsInfo.value.waybillNo,
success: () => {
uni.showToast({
title: "已复制运单号",
icon: "none",
});
},
});
};
</script>
<style scoped lang="scss">
.timebox {
color: #333333;
margin-left: -130rpx;
display: flex;
flex-direction: column;
.date{
font-size: 26rpx;
color: #999999;
margin-left: 8rpx;
}
.time{
font-size: 28rpx;
color: #999999;
}
// margin-top: 20rpx;
}
.timeline :deep(.u-steps-item__content__desc){
margin-top: -68rpx;
}
.timeline :deep(.u-text__value--tips){
font-size: 28rpx!important;
color:#666666!important;
}
.logistics-page {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f7f7f7;
}
.nav-bar {
height: 44px;
padding: 0 12px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
}
.nav-left,
.nav-right {
width: 60rpx;
display: flex;
align-items: center;
justify-content: flex-start;
}
.nav-back-icon {
font-size: 18px;
color: #333333;
}
.nav-title {
flex: 1;
text-align: center;
font-size: 16px;
font-weight: 500;
color: #333333;
}
.content {
flex: 1;
margin-top: calc(var(--status-bar-height) + 44px);
}
.base-info {
padding: 16px 16px 12px;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
}
.row {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.row:last-child {
margin-bottom: 0;
}
.label {
font-size: 30rpx;
color: #333333;
}
.value {
font-size: 30rpx;
color: #999999;
}
.waybill-row .value {
margin-right: 8px;
}
.btn-copy {
padding: 2px 15px;
border-radius: 20px;
border: 1px solid #dddddd;
background-color: #f8f8f8;
font-size: 12px;
color: #666666;
}
.btn-copy-text {
font-size: 12px;
color: #666666;
}
.timeline {
margin-top: 12px;
padding: 16px 38px 32px;
background-color: #ffffff;
display: flex;
.left{
width: 250rpx;
}
}
.timeline-item {
display: flex;
align-items: flex-start;
}
.timeline-item + .timeline-item {
margin-top: 18px;
}
.time-col {
width: 76rpx;
text-align: left;
margin-right: 8px;
}
.date {
font-size: 26rpx;
color: #666666;
}
.time {
margin-top: 2px;
font-size: 28rpx;
color: #999999;
}
.axis-col {
width: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.dot {
width: 18px;
height: 18px;
border-radius: 50%;
border: 2px solid #e0e0e0;
background-color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
}
.dot.active {
background-color: #00c15b;
border-color: #00c15b;
}
.dot-icon {
font-size: 12px;
color: #ffffff;
}
.line {
flex: 1;
width: 2px;
background-color: #00c15b;
margin-top: 2px;
}
.line-gray {
background-color: #e0e0e0;
}
.content-col {
flex: 1;
padding-left: 8px;
}
.desc {
font-size: 13px;
line-height: 1.6;
color: #999999;
}
.desc-active {
color: #333333;
}
</style>
+57 -13
View File
@@ -1,7 +1,20 @@
<template>
<view class="page">
<!-- <uni-nav-bar left-icon="left" title="我的兑换" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#ffffff" @clickLeft="goBack" /> -->
<navBar :title="'我的兑换'" />
<!-- <navBar :title="'我的兑换'" /> -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="我的兑换"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
</view>
<scroll-view
scroll-y
class="content"
@@ -13,10 +26,10 @@
>
<empty v-if="!orderList.length" />
<!-- <view v-if="!orderList.length" class="empty">暂无兑换记录</view> -->
<view v-for="item in orderList" :key="item.uuid" class="card">
<view class="row">
<view v-for="item in orderList" :key="item.uuid" class="card" @click="goDetail(item)">
<view class="row" style="align-items: flex-start;">
<text class="label">兑换物品:</text>
<text class="value">{{ item.goods_name }}</text>
<text class="value oneline">{{ item.goods_name }}</text>
</view>
<view class="row">
<text class="label">兑换时间:</text>
@@ -24,7 +37,7 @@
</view>
<view class="row">
<text class="label">状态:</text>
<text class="status" :class="statusClass(item.status)">{{ statusText(item.status) }}</text>
<text class="status" >{{ statusText(item.status) }}</text>
</view>
</view>
<view class="list-footer" v-if="isLoading">加载中...</view>
@@ -38,12 +51,39 @@ import goods_api from '@/api/goods_api'
import { ref, onMounted } from 'vue'
import navBar from '@/components/navBar/navBar.vue'
import empty from '@/components/empty/empty.vue'
import navTo from '@/utils/navTo.js'
import { onLoad,onBackPress} from '@dcloudio/uni-app'
const orderList = ref([])
const page = ref(1)
const pageSize = ref(10)
const isLoading = ref(false)
const noMore = ref(false)
const refresherTriggered = ref(false)
const refresherTriggered = ref(false);
const from = ref('')
onLoad((options) => {
if(options.from){
from.value = options.from
}
})
const goBack = () => {
if(from.value){
plus.runtime.quit();
}else{
uni.navigateBack();
}
}
onBackPress(() => {
if(from.value){
plus.runtime.quit();
return true;
}
});
const goDetail=(item)=>{
navTo({
url: `/pages_goods/exchange/exchangeDetail?id=${item.uuid}`
})
}
const fetchList = () => {
if (isLoading.value || noMore.value) return
@@ -82,9 +122,13 @@ const formatDate = (sec) => {
}
const statusText = (s) => {
if (s === 1 || s === 2) return '已支付'
if (s === 3) return '待支付'
return ''
if (s === 1 ) return '待支付'
if (s === 2 ) return '已支付'
if (s === 3) return '已取消'
if (s === 4) return '已发货'
if (s === 5) return '已收货'
if(s === 6) return '订单异常'
}
const statusClass = (s) => {
@@ -97,17 +141,17 @@ onMounted(() => {
orderList.value = []
fetchList()
})
const goBack = () => uni.navigateBack()
</script>
<style scoped>
.page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 0; left: 0; right: 0; background: #fff; }
.card { background: #fff; padding: 24rpx; border-bottom: 2rpx solid #f5f5f5; }
.card { background: #fff; padding: 24rpx; border-bottom: 2rpx solid #eee; }
.row { display: flex; align-items: center; padding: 10rpx 0; }
.label { color: #333; font-size: 30rpx; width: 180rpx; }
.label { color: #333; white-space: nowrap;font-size: 30rpx; width: 157rpx; }
.value { color: #666; font-size: 30rpx; }
.status { font-size: 30rpx; }
.status { font-size: 30rpx; color: #666;}
.status.paid { color: #666; }
.status.unpaid { color: #666; }
.list-footer { text-align: center; color: #999; padding: 24rpx 0; }
+48 -18
View File
@@ -35,8 +35,8 @@
<!-- 轮播图横幅 -->
<view class="banner-section">
<view class="swipemask">
<view class="banner-subtitle" v-if="bannerList.length > 0">{{
<view class="swipemask" v-if="bannerList.length > 0">
<view class="banner-subtitle" >{{
bannerList[currentBannerIndex].title
}}</view>
<view class="dotbox">
@@ -50,10 +50,11 @@
</view>
<swiper
class="banner-swiper"
:indicator-dots="true"
:autoplay="true"
:indicator-dots="bannerList.length > 0 ? true : false"
:autoplay="bannerList.length > 0 ? true : false"
:interval="3000"
:duration="500"
:circular="true"
indicator-active-color="#8B2316"
@change="onSwiperChange"
>
@@ -74,10 +75,10 @@
<view class="banner-item">
<image
class="banner-image"
src="/static/banner-bg.jpg"
:src="rewardImg"
mode="aspectFill"
></image>
<view class="banner-content">
<!-- <view class="banner-content">
<view class="banner-text green"
>第二届京津冀感染肝病高峰论坛&</view
>
@@ -86,7 +87,7 @@
>
<view class="banner-text orange">2016.10.14-2016.10.16</view>
<view class="banner-text orange">河北•石家庄</view>
</view>
</view> -->
</view>
</swiper-item>
</swiper>
@@ -209,10 +210,12 @@
import { ref, onMounted } from "vue";
import goods_api from "@/api/goods_api";
import docUrl from "@/utils/docUrl";
import { onBackPress,onLoad } from "@dcloudio/uni-app";
import pointImg from "@/static/integralticket.png";
import buyPointImg from "@/static/buy_points.png";
import filter from "@/static/triangle_normal.png";
import filterOn from "@/static/triangle_green_theme.png";
import rewardImg from "@/static/reward.png";
// 轮播图数据
const bannerList = ref([]);
const currentBannerIndex = ref(0);
@@ -244,10 +247,32 @@ const sortOptions = ref([
{ label: "兑换从多到少", value: 5 },
{ label: "兑换从少到多", value: 6 },
]);
const from=ref('');
const name=ref('');
onBackPress(() => {
if(!from.vlaue){
plus.runtime.quit();
return true;
}
});
onLoad((opts) => {
if(opts.from){
from.value = opts.from;
}
if(opts.name){
name.value = opts.name;
}
});
// 方法
const goBack = () => {
uni.navigateBack();
if(!from.vlaue){
plus.runtime.quit();
}else{
uni.navigateBack();
}
};
const goToSearch = () => {
@@ -321,7 +346,7 @@ const goToBannerDetail = (banner) => {
uni.navigateTo({
url: `/pages_app/webview/webview?url=${encodeURIComponent(
docUrl+banner.path
)}&title=${banner.title}`,
)}&title=积分商城`,
});
};
@@ -361,7 +386,7 @@ const getGoodsList = () => {
const sortParam = selectedSortValue.value ? selectedSortValue.value : 1;
goods_api
.goodsList({
name: "",
name: name.value,
page: page.value,
sort: sortParam,
tag_type: tagParam,
@@ -606,8 +631,8 @@ onMounted(() => {
.dropdown-item {
padding: 12px 16px;
font-size: 14px;
color: #333;
font-size: 28rpx;
color: #666;
text-align: center;
border-bottom: 1px solid #eee;
}
@@ -625,8 +650,8 @@ onMounted(() => {
}
.filter-text {
font-size: 14px;
color: #333;
font-size: 28rpx;
color: #666;
margin-right: 4px;
}
@@ -662,9 +687,13 @@ onMounted(() => {
display: flex;
flex-wrap: wrap;
padding: 16px;
gap: 16px;
// gap: 16px;
}
.grid-wrap .product-item:nth-child(2n+1){
margin-right: 16px;
}
.list-footer {
text-align: center;
color: #999;
@@ -678,6 +707,7 @@ onMounted(() => {
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease;
margin-bottom: 16px;
}
.product-item:active {
@@ -702,7 +732,7 @@ onMounted(() => {
}
.product-title {
font-size: 12px;
font-size: 28rpx;
color: #333;
line-height: 1.4;
margin-bottom: 8px;
+52 -11
View File
@@ -18,7 +18,7 @@
<view class="swiper-box">
<swiper class="detail-swiper" :indicator-dots="true" :autoplay="images.length > 1 ? true : false" :interval="5000" :duration="400" indicator-color="#ccc" indicator-active-color="#8B2316" :circular="true">
<swiper-item v-for="(img, idx) in images" :key="idx">
<image class="swiper-image" :src="img" mode="aspectFit"></image>
<image class="swiper-image" :src="img" mode="widthFix"></image>
</swiper-item>
</swiper>
</view>
@@ -28,7 +28,7 @@
<view class="title"><text v-if="product.type == 1">[包邮]</text>{{ product.title }}</view>
<view class="price-row">
<text class="price">{{ product.price }}积分</text>
<text class="exchanged">已兑换{{ product.times }}件</text>
<text class="exchanged" v-if="product.times > 0">已兑换{{ product.times }}件</text>
</view>
</view>
@@ -51,8 +51,10 @@
</scroll-view>
<!-- 底部兑换按钮 -->
<view class="bottom-bar" @click="goExchange">
<view class="redeem-btn" >在线兑换</view>
<view class="bottom-bar" >
<view class="redeem-btn" @click="goExchange">在线兑换</view>
<view class="bar" v-if="isUpan"></view>
<view class="redeem-btn" @click="goExchangeUpan" v-if="isUpan" :class="{'disabled': restNum <= 0}">福利兑换<text v-if="restNum > 0">剩余{{ restNum }}个</text></view>
</view>
</view>
</template>
@@ -66,22 +68,35 @@ import navBar from '@/components/navBar/navBar.vue'
const product = ref({ id: '', title: '', price: 0, times: 0, content: '' })
const images = ref([])
const navTitle = ref('商品详情')
const navTitle = ref('商品详情');
const isUpan = ref(false);
const restNum = ref(0);
const goBack = () => uni.navigateBack()
const getUpanWelfareCount = async () => {
const res = await goods_api.getUpanWelfareCount()
if (res.code == 200) {
restNum.value=res.data;
};
}
const fetchDetail = async (id) => {
try {
const res = await goods_api.getGoodsDetail({ uuid: id })
if ((res.code === 200 || res.code === '200') && res.data) {
let content=res.data.content.replace(/\<img/gi, '<img class="richImg"');
product.value = {
id,
type: res.data.type,
title: res.data.name || '',
price: res.data.bonuspoints || 0,
times: res.data.times || 0,
content: res.data.content || ''
content: content
}
if(res.data.name.indexOf('U盘') > -1 || res.data.name.indexOf('u盘') > -1){
isUpan.value = true;
getUpanWelfareCount();
};
navTitle.value = (product.value.title || '').slice(0, 18)
const list = []
if (res.data.detial_imgpath) {
@@ -101,10 +116,18 @@ const fetchDetail = async (id) => {
onLoad((opts) => {
if (opts && opts.id) fetchDetail(opts.id)
})
const goExchangeUpan = () => {
console.log(restNum.value);
if(restNum.value>0){
uni.navigateTo({
url: `/pages_app/buyUpan/buyUpan?restNum=${restNum.value}`
})
}
}
const goExchange = () => {
uni.navigateTo({
url: `/pages_goods/exchange/index?id=${product.value.id}&title=${encodeURIComponent(product.value.title)}&price=${product.value.price}&type=${product.value.type}`
url: `/pages_goods/exchange/index?id=${product.value.id}&title=${encodeURIComponent(product.value.title)}&price=${product.value.price}&type=${product.value.type}&times=${product.value.times}`
})
}
</script>
@@ -127,8 +150,8 @@ const goExchange = () => {
/* 主图轮播 */
.swiper-box { background: #fff; }
.detail-swiper { height: 480rpx; }
.swiper-image { width: 100%; height: 100%; }
.detail-swiper { height: 440rpx; }
.swiper-image { width: 100%; height: 440rpx; }
/* 概要 */
.summary { background: #fff; padding: 24rpx; }
@@ -160,5 +183,23 @@ const goExchange = () => {
align-items: center;
justify-content: center;
}
.redeem-btn { color: #fff; font-size: 32rpx; font-weight: 700; }
.bottom-bar .bar{
height: 100rpx;
background-color: #f7f7f7;
width:2rpx;
}
.bottom-bar .redeem-btn{
height: 100rpx;
background-color: #27c5b8;
display: flex;
align-items: center;
justify-content: center;
color: #fff; font-size: 32rpx;flex:1;
}
.bottom-bar .redeem-btn.disabled{
background-color: #ccc;
}
.rich-wrapper >>> .richImg{
width: 100%!important;
}
</style>