前端优化: - 修复分享图片配置,使用API返回的share_image - 新增设置页面,包含用户协议、隐私政策、退出登录、注销账号 - 调整用户中心菜单,将协议相关功能移至设置页面 - 隐藏首页和详情页的参与次数显示 - 商城页面价格显示改为哈尼券(价格x100) 后台管理修复: - 修复用户列表货币字段映射错误(Diamond字段) - 修复资金变动对话框,动态加载货币名称 - 修复ChangeDiamondAsync方法使用正确的Money2字段
644 lines
14 KiB
Vue
644 lines
14 KiB
Vue
<template>
|
||
<page-container title="商城好物">
|
||
<banner :type-id="10" :height="326"></banner>
|
||
<view style="padding-bottom: 300rpx; background-color: white;">
|
||
<view class="" style="display: flex; flex-direction: column;">
|
||
<view class="grid-container"
|
||
:style="datas.length === 0 ? 'display:flex;justify-content:center;align-items:center;' : ''">
|
||
<empty-state v-if="datas.length === 0" message="暂无商品数据"></empty-state>
|
||
<view v-else v-for="(item, index) in datas" :key="index" class="grid-item"
|
||
@click="order_money(item)">
|
||
|
||
<view class=""
|
||
style="background-color: #D8D8D8; height: 324rpx; border-radius: 16rpx 16rpx 0rpx 0rpx;">
|
||
<image :src="item.imgurl"
|
||
style=" width: 326.39rpx; height: 324rpx; position: absolute; left: 2rpx; border-radius: 16rpx"
|
||
mode="">
|
||
</image>
|
||
</view>
|
||
<view class="goods-name hang1" style=" width: 290rpx;">
|
||
<text style="color: #333333; font-size: 27rpx;">{{ item.title }}</text>
|
||
</view>
|
||
<view class="price-box">
|
||
<view class="price">
|
||
<text>{{ item.price * 100 }}<text style="font-size: 20rpx;">{{ $config.getAppSetting('currency2_name') }}</text></text>
|
||
</view>
|
||
</view>
|
||
<view class="num-box">
|
||
<view class="num ml10"> {{ item.sale_stock }}/{{ item.stock }} </view>
|
||
<view class="box icon">
|
||
<image :src="$img1('index/box.png')" lazy-load></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</view>
|
||
<uni-popup ref="pop" type="bottom">
|
||
<view v-if="orderData" class="order-popup">
|
||
<!-- 头部 -->
|
||
<view class="popup-header">
|
||
<text class="popup-title">确认订单</text>
|
||
<view class="close-btn" @click="close('pop')">×</view>
|
||
</view>
|
||
|
||
<!-- 商品信息 -->
|
||
<view class="goods-card">
|
||
<view class="goods-img">
|
||
<image :src="orderData.goods.imgurl_detail" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="goods-info">
|
||
<view class="goods-title">{{ orderData.goods.title }}</view>
|
||
<view class="goods-meta">
|
||
<text>类型:明信片</text>
|
||
<text class="qty">×{{ orderData.goods.prize_num }}</text>
|
||
</view>
|
||
<view class="goods-price">{{ orderData.goods.price * 100 }}{{ $config.getAppSetting('currency2_name') }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 货币选项 -->
|
||
<view class="option-row" @click="changePay(0)"
|
||
v-if="orderData != null && orderData.goods_extend && orderData.goods_extend.pay_wechat == 1">
|
||
<view class="label-with-tip">
|
||
<text class="label">微信支付</text>
|
||
</view>
|
||
<view class="radio" :class="{ active: zhifu == 0 }"></view>
|
||
</view>
|
||
|
||
<view class="option-row" @click="changePay(1)"
|
||
v-if="orderData != null && orderData.goods_extend && orderData.goods_extend.pay_currency2 == 1">
|
||
<view class="label-with-tip">
|
||
<text class="label">{{ $config.getAppSetting('currency2_name') }} {{ orderData.goods.price * 100 }}</text>
|
||
<text class="tip">(剩余{{ orderData.score }})</text>
|
||
</view>
|
||
<view class="radio" :class="{ active: zhifu == 1 }"></view>
|
||
</view>
|
||
|
||
<!-- 售前售后须知 -->
|
||
<view class="notice-row" @click="$c.to({ url: '/pages/guize/guize?type=10' })">
|
||
<text class="notice-text">售前·售后须知</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
|
||
<!-- 支付按钮 -->
|
||
<view class="pay-btn" v-if="zhifu == 0" @click="$c.noDouble(() => confirmSubmit(1))">
|
||
<text>确认支付 ¥{{ orderData.price }}</text>
|
||
</view>
|
||
<view class="pay-btn" v-if="zhifu == 1" @click="$c.noDouble(() => pay(1))">
|
||
<text>{{ orderData.price * 100 }}{{ $config.getAppSetting('currency2_name') }}</text>
|
||
</view>
|
||
|
||
<!-- 协议 -->
|
||
<view class="agree-row" @click="isAgree = !isAgree">
|
||
<view class="check-icon" :class="{ active: isAgree }"></view>
|
||
<text class="agree-text">我已满18岁,阅读即同意《用户协议》和《隐私政策》</text>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
<PayDialog ref="payDialog" />
|
||
</view>
|
||
</page-container>
|
||
</template>
|
||
|
||
<script>
|
||
import { getAdvert } from '@/common/server/config.js';
|
||
import { getGoodsList } from '@/common/server/goods.js';
|
||
import { calcMallOrderMoney, createMallOrder, createOrder } from '@/common/server/order.js';
|
||
|
||
export default {
|
||
components: {
|
||
EmptyState: () => import('@/components/empty-state/empty-state.vue')
|
||
},
|
||
onShareAppMessage() {
|
||
let imageUrl = this.$config.getShareImageUrl();
|
||
// 使用小写 id,兼容新版 .NET API
|
||
const userinfo = uni.getStorageSync('userinfo') || {};
|
||
const pid = userinfo.id || userinfo.ID || '';
|
||
return {
|
||
imageUrl: imageUrl,
|
||
title: this.$config.getAppSetting('share_title') || "哈尼盲盒上线,来就送!",
|
||
path: '/pages/shouye/index?pid=' + pid
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
statusBarHeight: 0,
|
||
datas: [],
|
||
advert: [],
|
||
sendRuleData: '',
|
||
goodsId: "",
|
||
orderData: null,
|
||
isAgree: true,
|
||
isWXPay: true,
|
||
useMoney: false,
|
||
integral: true,
|
||
zhifu: 0,
|
||
}
|
||
},
|
||
onLoad() {
|
||
// 获取系统信息
|
||
uni.getSystemInfo({
|
||
success: (res) => {
|
||
// 状态栏的高度
|
||
this.statusBarHeight = res.statusBarHeight + 20;
|
||
}
|
||
});
|
||
|
||
this.getData();
|
||
this.load();
|
||
this.$c.getRule(10).then(res => {
|
||
if (res.status == 1) {
|
||
this.sendRuleData = res.data
|
||
}
|
||
});
|
||
|
||
},
|
||
onShow() {
|
||
|
||
const curPages = getCurrentPages()[0]; // 获取当前页面实例
|
||
if (typeof curPages.getTabBar === 'function' && curPages.getTabBar()) {
|
||
this.$mp.page.getTabBar().setData({
|
||
selected: 2
|
||
});
|
||
}
|
||
this.$platform.getOrderNo(this).then(order_num => {
|
||
if (order_num != null && order_num != "") {
|
||
this.$c.msg("购买成功!");
|
||
}
|
||
})
|
||
},
|
||
methods: {
|
||
async load() {
|
||
// API: getAdvert?type_id=3
|
||
const res = await getAdvert(3);
|
||
if (res) {
|
||
this.advert = res;
|
||
}
|
||
},
|
||
getStatusBarHeight() {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
this.statusBarHeight = systemInfo.statusBarHeight;
|
||
console.log('statusBarHeight', this.statusBarHeight);
|
||
},
|
||
|
||
async getData() {
|
||
let isWXPay = this.$config.GetVersion();
|
||
// API: goods
|
||
const res = await getGoodsList({
|
||
type: '10',
|
||
page: 1,
|
||
use_money_is: this.useMoney ? 1 : 2,
|
||
use_integral_is: this.isWXPay ? 1 : 2,
|
||
});
|
||
|
||
if (res.status == 1 && res.data && res.data.data) {
|
||
if (isWXPay) {
|
||
if (this.datas.length > 0) {
|
||
this.datas = this.datas.slice(0, this.datas.length);
|
||
}
|
||
for (let index = 0; index < res.data.data.length; index++) {
|
||
const element = res.data.data[index];
|
||
if (element.title.indexOf('京东卡') == -1) {
|
||
this.datas.push(element);
|
||
}
|
||
}
|
||
} else {
|
||
this.datas = res.data.data;
|
||
}
|
||
}
|
||
},
|
||
|
||
|
||
async order_money(data) {
|
||
console.log(234);
|
||
// 检查库存
|
||
if (data.sale_stock <= 0) {
|
||
uni.showToast({
|
||
title: '库存不足',
|
||
icon: 'none',
|
||
});
|
||
return;
|
||
}
|
||
this.goodsId = data.id;
|
||
// API: mall_ordermoney
|
||
const res = await calcMallOrderMoney({
|
||
prize_num: 1,
|
||
goods_id: data.id,
|
||
num: 1,
|
||
});
|
||
|
||
if (res.status == 1) {
|
||
this.orderData = res.data;
|
||
this.zhifu = 0;
|
||
// 使用 goods_extend(API 返回的下划线命名)
|
||
const goodsExtend = this.orderData.goods_extend || {};
|
||
if (goodsExtend.pay_wechat == 1) {
|
||
this.zhifu = 0;
|
||
} else if (goodsExtend.pay_currency2 == 1) {
|
||
this.zhifu = 1;
|
||
}
|
||
this.$refs.pop.open();
|
||
}
|
||
},
|
||
|
||
close(e) {
|
||
this.$refs[e].close()
|
||
},
|
||
|
||
changePay(e) {
|
||
if (this.zhifu != e) {
|
||
this.zhifu = e;
|
||
}
|
||
if (this.zhifu == 1) {
|
||
|
||
}
|
||
|
||
},
|
||
|
||
async confirmSubmit(type) {
|
||
|
||
if (!this.useMoney && !this.isWXPay) {
|
||
uni.showToast({
|
||
title: '请选择支付方式',
|
||
icon: 'none',
|
||
});
|
||
return;
|
||
}
|
||
|
||
console.log("type", type);
|
||
|
||
let data = {
|
||
goods_id: this.goodsId,
|
||
prize_num: 1,
|
||
num: 1,
|
||
use_money_is: 2,
|
||
use_integral_is: 2,
|
||
coupon_id: "",
|
||
use_money2_is: this.useMoney ? 1 : 2
|
||
};
|
||
|
||
let res;
|
||
if (type == 1) {
|
||
// API: orderbuy
|
||
res = await createOrder(data);
|
||
} else {
|
||
// API: mall_ordermoney
|
||
res = await calcMallOrderMoney(data);
|
||
}
|
||
|
||
if (res.status == 1) {
|
||
if (type == 0) {
|
||
console.log("res.data", res.data);
|
||
this.orderData = res.data;
|
||
}
|
||
|
||
if (type == 1) {
|
||
this.close('pop');
|
||
if (res.data.status == 1) {
|
||
const status = await this.$platform.pay({
|
||
data: res.data.res
|
||
}, this);
|
||
if (status == 'success') {
|
||
this.getData();
|
||
}
|
||
} else {
|
||
this.$c.toast({
|
||
title: res.msg,
|
||
duration: 500,
|
||
success: () => {
|
||
this.getData();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
|
||
async pay(type) {
|
||
|
||
var pri = this.orderData.goods.price * 100;
|
||
if (this.orderData.score < pri) {
|
||
uni.showToast({
|
||
title: this.$config.getAppSetting("currency2_name") + '不足',
|
||
icon: 'none',
|
||
});
|
||
return;
|
||
}
|
||
|
||
console.log("type", type);
|
||
|
||
let data = {
|
||
goods_id: this.goodsId,
|
||
prize_num: 1,
|
||
};
|
||
|
||
// API: mall_orderbuy
|
||
const res = await createMallOrder(data);
|
||
|
||
if (res.status == 1) {
|
||
if (type == 0) {
|
||
console.log("res.data", res.data);
|
||
this.orderData = res.data;
|
||
}
|
||
|
||
if (type == 1) {
|
||
this.close('pop');
|
||
this.$c.toast({
|
||
title: res.msg || '购买成功',
|
||
duration: 500,
|
||
success: () => {
|
||
this.getData();
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
// 购买失败也刷新数据
|
||
this.getData();
|
||
}
|
||
},
|
||
|
||
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page-title {
|
||
width: 100%;
|
||
top: 108rpx;
|
||
position: absolute;
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 34rpx;
|
||
justify-content: center;
|
||
color: black;
|
||
z-index: 100;
|
||
}
|
||
|
||
.grid-container {
|
||
display: grid;
|
||
margin: 33rpx;
|
||
padding-bottom: 200rpx;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 16px;
|
||
min-height: 55vh;
|
||
}
|
||
|
||
.grid-item {
|
||
height: 487rpx;
|
||
position: relative;
|
||
background-color: #F8F8F8;
|
||
border-radius: 0rpx 0rpx 16rpx 16rpx;
|
||
}
|
||
|
||
.goods-name {
|
||
position: absolute;
|
||
left: 25rpx;
|
||
font-size: 20rpx;
|
||
bottom: 90rpx;
|
||
}
|
||
|
||
.price-box {
|
||
display: flex;
|
||
position: absolute;
|
||
left: 18rpx;
|
||
bottom: 24rpx;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.price {
|
||
font-weight: 500;
|
||
font-size: 16rpx;
|
||
color: #333333;
|
||
}
|
||
}
|
||
|
||
.num-box {
|
||
display: flex;
|
||
align-items: center;
|
||
position: absolute;
|
||
bottom: 24rpx;
|
||
right: 20rpx;
|
||
|
||
.num {
|
||
font-size: 18rpx;
|
||
font-family: Source Han Sans CN;
|
||
font-weight: 400;
|
||
color: #6C6C6C;
|
||
}
|
||
|
||
.box {
|
||
width: 20rpx;
|
||
height: 18rpx;
|
||
margin-left: 6rpx;
|
||
}
|
||
}
|
||
|
||
.order-popup {
|
||
background: #FFFFFF;
|
||
border-radius: 24rpx 24rpx 0 0;
|
||
padding: 0 32rpx 60rpx;
|
||
|
||
.popup-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 32rpx 0;
|
||
position: relative;
|
||
|
||
.popup-title {
|
||
position: static;
|
||
width: auto;
|
||
top: auto;
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
z-index: auto;
|
||
}
|
||
|
||
.close-btn {
|
||
position: absolute;
|
||
right: 0;
|
||
font-size: 48rpx;
|
||
color: #999;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.goods-card {
|
||
display: flex;
|
||
padding: 24rpx;
|
||
background: #F7F7F7;
|
||
border-radius: 16rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
.goods-img {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
background: #EEE;
|
||
flex-shrink: 0;
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.goods-info {
|
||
flex: 1;
|
||
margin-left: 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
|
||
.goods-title {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.goods-meta {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
.qty {
|
||
color: #666;
|
||
}
|
||
}
|
||
|
||
.goods-price {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
.option-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 28rpx 0;
|
||
border-bottom: 1rpx solid #F0F0F0;
|
||
|
||
.label-with-tip {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.tip {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
margin-left: 8rpx;
|
||
}
|
||
}
|
||
|
||
.radio {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border: 2rpx solid #DDD;
|
||
border-radius: 50%;
|
||
flex-shrink: 0;
|
||
|
||
&.active {
|
||
border-color: #03D8F4;
|
||
background: #03D8F4;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
background: #FFF;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.notice-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx;
|
||
background: #E8F9E9;
|
||
border-radius: 12rpx;
|
||
margin: 24rpx 0;
|
||
|
||
.notice-text {
|
||
font-size: 28rpx;
|
||
color: #2DB84D;
|
||
}
|
||
|
||
.arrow {
|
||
font-size: 32rpx;
|
||
color: #2DB84D;
|
||
}
|
||
}
|
||
|
||
.pay-btn {
|
||
width: 100%;
|
||
height: 96rpx;
|
||
background: #03D8F4;
|
||
border-radius: 14rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #404040;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.agree-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.check-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
border: 2rpx solid #DDD;
|
||
border-radius: 50%;
|
||
margin-right: 12rpx;
|
||
flex-shrink: 0;
|
||
|
||
&.active {
|
||
border-color: #03D8F4;
|
||
background: #03D8F4;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '✓';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
font-size: 20rpx;
|
||
color: #FFF;
|
||
}
|
||
}
|
||
}
|
||
|
||
.agree-text {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
</style> |