2025-10-21
商品详情加入购物车与创建订单 支付页面70%
This commit is contained in:
@@ -7,7 +7,11 @@ const baseUrl = "http://192.168.0.26:3000"
|
||||
export const mallAPI = {
|
||||
getMallList: (params) => http.get(baseUrl + '/api/products', params),
|
||||
getCategory: () => http.get(baseUrl + '/api/category'),
|
||||
getMallDetail: (id) => http.get(baseUrl + '/api/products/' + id)
|
||||
getMallDetail: (id) => http.get(baseUrl + '/api/products/' + id),
|
||||
getRecommended: (id) => http.get(baseUrl + `/api/products/${id}/recommended`), // 推荐商品
|
||||
addCart: (data) => http.post(baseUrl +"/api/cart/add", data), // 添加购物车
|
||||
createOrder: (data) => http.post(baseUrl + `/api/orders/create-from-cart`,data), // 创建订单
|
||||
getOrder: (orderId) => http.get(baseUrl + `/api/orders/pending-payment/${orderId}`), // 获取订单
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -53,6 +53,38 @@
|
||||
"__platform__" : [ "android" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios" : {
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
11
pages.json
11
pages.json
@@ -136,13 +136,20 @@
|
||||
"navigationBarTitleText": "商品详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/home/pay",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "确认订单",
|
||||
"backgroundColor": "#E4ECFF"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "uni-app",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
"backgroundColor": "#f5f8ff"
|
||||
},
|
||||
"uniIdRouter": {},
|
||||
"tabBar": {
|
||||
|
||||
@@ -203,7 +203,6 @@
|
||||
|
||||
// 加载数据
|
||||
const loadMallData = () => {
|
||||
console.log(111);
|
||||
if (loadStatus.value == 'nomore') return
|
||||
mallAPI.getMallList(params.value).then((res) => {
|
||||
mallList.value = mallList.value.concat(res.data.products)
|
||||
|
||||
@@ -7,15 +7,101 @@
|
||||
</template>
|
||||
</u-navbar>
|
||||
<scroll-view scroll-y="true" :style="'height:'+scrollHeight+'px'">
|
||||
111
|
||||
<view class="img-banner">
|
||||
<u-swiper height="400" img-mode="aspectFit" mode="none" bg-color="transparent" :list="dataInfo.banner"
|
||||
@change="handleChangeBanner" :current="currentBanner"></u-swiper>
|
||||
</view>
|
||||
<scroll-view scroll-x="true" class="img-sub-banner">
|
||||
<image v-for="(item,index) in dataInfo.banner" :src="item" class="img-item"
|
||||
:class="{active: currentBanner==index}" mode="aspectFit" @click="handleChangeBanner(index)">
|
||||
</image>
|
||||
</scroll-view>
|
||||
|
||||
<view class="mall-info">
|
||||
<view class="name">
|
||||
{{dataInfo.name}}
|
||||
</view>
|
||||
<view class="description">
|
||||
{{dataInfo.description}}
|
||||
</view>
|
||||
<view class="price">
|
||||
<view>
|
||||
<view class="mall-price">
|
||||
<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
|
||||
{{dataInfo.rongdou_price}}
|
||||
</view>
|
||||
<view class="mall-price">
|
||||
<u-icon name="integral"></u-icon>
|
||||
{{dataInfo.points_price}}
|
||||
</view>
|
||||
<view v-if="dataInfo.discount" class="discount-info">
|
||||
<u-tag type="error" text="1折优惠" />
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<view>已售{{dataInfo.sales}}</view>
|
||||
<view style="color: red;">剩余{{dataInfo.stock}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="rating">
|
||||
评分:<u-rate :disabled="true" :count="5" v-model="dataInfo.rating" active-color="#f7ba2a"></u-rate>
|
||||
</view>
|
||||
<view class="detail">
|
||||
<h3>具体描述</h3>
|
||||
<view v-html="dataInfo.details"></view>
|
||||
</view>
|
||||
<view class="recommend">
|
||||
<h3>推荐商品</h3>
|
||||
<view class="mall-list">
|
||||
<u-waterfall v-model="recommendedList" ref="mallListRef">
|
||||
<template v-slot:left="{leftList}">
|
||||
<view class="mall-item u-m-r-10" v-for="(item, index) in leftList" :key="index"
|
||||
@click="handleCheck(item)">
|
||||
<u-lazy-load threshold="-450" border-radius="10" :image="getImageUrl(item.image)"
|
||||
:index="index"></u-lazy-load>
|
||||
<view class="mall-title u-m-l-5 u-m-r-5">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="mall-price u-m-l-5 u-m-r-5">
|
||||
<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
|
||||
{{item.price}}
|
||||
</view>
|
||||
<view class="mall-price u-m-l-5 u-m-r-5">
|
||||
<u-icon name="integral"></u-icon>
|
||||
{{item.points}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right="{rightList}">
|
||||
<view class="mall-item u-m-l-10" v-for="(item, index) in rightList" :key="index"
|
||||
@click="handleCheck(item)">
|
||||
<u-lazy-load threshold="-450" border-radius="10" :image="getImageUrl(item.image)"
|
||||
:index="index"></u-lazy-load>
|
||||
<view class="mall-title u-m-l-5 u-m-r-5">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="mall-price u-m-l-5 u-m-r-5">
|
||||
<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
|
||||
{{item.price}}
|
||||
</view>
|
||||
<view class="mall-price u-m-l-5 u-m-r-5">
|
||||
<u-icon name="integral"></u-icon>
|
||||
{{item.points}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-waterfall>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="bottom-view" id="bottomViewId">
|
||||
<view class="icon-btn">
|
||||
<view class="item">
|
||||
<!-- <view class="item">
|
||||
<u-image width="100%" :fade="false" src="/static/mall/Home.png" mode="widthFix"></u-image>
|
||||
店铺
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="item">
|
||||
<u-image width="100%" :fade="false" src="/static/mall/Twitch.png" mode="widthFix"></u-image>
|
||||
客服
|
||||
@@ -26,19 +112,95 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-btn">
|
||||
<u-button class="add-car common" :hair-line="false" hover-class="none">加入购物车</u-button>
|
||||
<u-button class="buy common" :hair-line="false" hover-class="none">领券购买</u-button>
|
||||
<u-button class="add-car common" :hair-line="false" hover-class="none"
|
||||
@click="handleBtn(0)">加入购物车</u-button>
|
||||
<u-button class="buy common" :hair-line="false" hover-class="none" @click="handleBtn(1)">领券购买</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-popup v-model="showSure" mode="bottom" length="70%" :closeable="true" blur="90%">
|
||||
<scroll-view scroll-y="true" style="height: 100%;">
|
||||
<view class="sure-popup">
|
||||
<view class="title">{{popTitle}}</view>
|
||||
<view class="address">
|
||||
<view class="text">
|
||||
<image style="width: 40rpx;height: 40rpx;" src="/static/icon/Map pin2.png" mode=""></image>
|
||||
<view class="u-m-l-10">张三 | </view>
|
||||
<view class="u-m-l-10">浙江省 宁波市 海曙区</view>
|
||||
</view>
|
||||
<view class="right-icon">
|
||||
<image style="width: 100%;height: 100%;" src="/static/icon/Chevron right Menu.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="count-select u-p-l-10 u-p-r-10">
|
||||
<view class="pre-view">
|
||||
<u-image :src="getImageUrl(dataInfo.image_url)" height="100%" width="100%">
|
||||
<template v-slot:error>
|
||||
<view style="font-size: 24rpx;">暂无图片</view>
|
||||
</template>
|
||||
</u-image>
|
||||
</view>
|
||||
<view class="text">
|
||||
<view>
|
||||
实付<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
|
||||
{{dataInfo.price * order.count}}
|
||||
<view>
|
||||
<u-icon name="integral"></u-icon>
|
||||
{{dataInfo.points * order.count}}
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<u-number-box v-model="order.count" :max="dataInfo.stock" :min="1"></u-number-box>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="spec-option" v-for="item in specNames">
|
||||
<view class="title">
|
||||
{{item + "("+specOptions.get(item).size+")"}}
|
||||
</view>
|
||||
<view class="option-list">
|
||||
<view class="option-item" v-for="key in specOptions.get(item).keys()" :key="key"
|
||||
:class="{active: isChose(key), unactive: !canChose(key)}"
|
||||
@click="handleChangeSpec(key, item)">
|
||||
{{specOptions.get(item).get(key)}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="spec-option">
|
||||
<view class="title">
|
||||
订单备注
|
||||
</view>
|
||||
<view class="">
|
||||
<u-input type="textarea" :border="true" :height="100" v-model="order.orderNote"></u-input>
|
||||
</view>
|
||||
</view>
|
||||
<view class="spec-option">
|
||||
<u-button @click="handleSubmit">{{popTitle}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</u-popup>
|
||||
|
||||
<u-toast ref="msgRef" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, getCurrentInstance } from 'vue';
|
||||
<script setup>
|
||||
import {
|
||||
onMounted,
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import { mallAPI } from '../../api/mall';
|
||||
import {
|
||||
mallAPI
|
||||
} from '../../api/mall';
|
||||
import {
|
||||
getImageUrl
|
||||
} from '../../util/common.js';
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const scrollHeight = ref(0)
|
||||
@@ -46,21 +208,255 @@
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
let screenHeight = res.screenHeight
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#uNavbarId").boundingClientRect((data : any) => {
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#uNavbarId").boundingClientRect((
|
||||
data) => {
|
||||
scrollHeight.value = screenHeight - data.height
|
||||
}).exec()
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#bottomViewId").boundingClientRect((data : any) => {
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#bottomViewId").boundingClientRect((
|
||||
data) => {
|
||||
scrollHeight.value = scrollHeight.value - data.height
|
||||
}).exec()
|
||||
}
|
||||
})
|
||||
}
|
||||
const currentBanner = ref(0)
|
||||
const handleChangeBanner = (index) => {
|
||||
currentBanner.value = index
|
||||
}
|
||||
|
||||
const handleCheck = (item) => {
|
||||
uni.redirectTo({
|
||||
url: '/pages/home/mallDetail?id=' + item.id
|
||||
})
|
||||
}
|
||||
const msgRef = ref()
|
||||
|
||||
// 切换 加入购物车/确认购买
|
||||
const showSure = ref(false)
|
||||
const popTitle = ref('')
|
||||
const flag = ref(0)
|
||||
|
||||
const handleBtn = (sign) => {
|
||||
if (sign == 0) {
|
||||
popTitle.value = '加入购物车'
|
||||
flag.value = 0
|
||||
} else if (sign == 1) {
|
||||
popTitle.value = '确认购买'
|
||||
flag.value = 1
|
||||
}
|
||||
showSure.value = true
|
||||
}
|
||||
|
||||
const order = ref({
|
||||
count: 1
|
||||
})
|
||||
const choseKeys = ref([])
|
||||
|
||||
const handleChangeSpec = (key, allKey) => {
|
||||
if (!canChose(key)) return
|
||||
if (choseKeys.value.includes(key)) {
|
||||
// 取消选中
|
||||
choseKeys.value = choseKeys.value.filter(item => item != key)
|
||||
} else {
|
||||
// console.log(choseKeys.value);
|
||||
// console.log(specOptions.value.get(allKey));
|
||||
// 清除选项
|
||||
const keysArray = Array.from(specOptions.value.get(allKey).keys())
|
||||
choseKeys.value = choseKeys.value.filter(item => {
|
||||
if (keysArray.includes(item)) return false
|
||||
return true
|
||||
})
|
||||
// 选中
|
||||
choseKeys.value.push(key)
|
||||
}
|
||||
}
|
||||
|
||||
// 判断当前key是否可选
|
||||
const canChose = (key) => {
|
||||
// console.log("当前规格ID:", key);
|
||||
// console.log("规格组合列表:", activeKeys.value);
|
||||
// console.log("已选择的规格ID列表:", choseKeys.value);
|
||||
// console.log("规格选项:", specOptions.value);
|
||||
|
||||
// 如果已经选中,肯定可选(因为可以取消选中)
|
||||
if (isChose(key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 构建临时选择的key列表
|
||||
let tempChoseKeys = [...choseKeys.value];
|
||||
|
||||
// 找到当前key所属的规格类别
|
||||
let specCategory = '';
|
||||
for (const [category, options] of specOptions.value.entries()) {
|
||||
if (options.has(key)) {
|
||||
specCategory = category;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找到了所属规格类别,需要先移除同类别下已选的其他选项
|
||||
if (specCategory) {
|
||||
const sameCategoryKeys = Array.from(specOptions.value.get(specCategory).keys());
|
||||
tempChoseKeys = tempChoseKeys.filter(item => !sameCategoryKeys.includes(item));
|
||||
}
|
||||
|
||||
// 添加当前要判断的key
|
||||
tempChoseKeys.push(key);
|
||||
|
||||
// 检查是否存在包含所有临时选择key的有效规格组合
|
||||
const hasValidCombination = activeKeys.value.some(combination => {
|
||||
return arrayContainsAll(combination, tempChoseKeys);
|
||||
});
|
||||
|
||||
return hasValidCombination;
|
||||
}
|
||||
|
||||
// arr1是否包含arr2
|
||||
const arrayContainsAll = (arr1, arr2) => {
|
||||
return arr2.every(item => arr1.includes(item));
|
||||
}
|
||||
|
||||
// 是否被选中
|
||||
const isChose = (key) => {
|
||||
return choseKeys.value.includes(key)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
// 匹配规格
|
||||
let specification = dataInfo.value.specifications.filter(item => {
|
||||
let group = item.combination_key.split('-').map(Number)
|
||||
if (arraysEqualUnordered(group, choseKeys.value)) return true
|
||||
return false
|
||||
})
|
||||
let specificationId = null
|
||||
if (specification.length != 0) {
|
||||
specificationId = specification[0].id
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
title: '请选择规格',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 立即购买
|
||||
const cartItem = {
|
||||
productId: dataInfo.value.id,
|
||||
quantity: order.value.count,
|
||||
specificationId: specificationId,
|
||||
points: dataInfo.value.points,
|
||||
name: dataInfo.value.name,
|
||||
image: dataInfo.value.image,
|
||||
stock: dataInfo.value.stock
|
||||
}
|
||||
if (flag.value == 0) {
|
||||
// 加入购物车
|
||||
mallAPI.addCart(cartItem).then(res => {
|
||||
if (res.success) {
|
||||
msgRef.value.show({
|
||||
title: '已加入购物车',
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
title: res.data.message || '添加到购物车失败',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}).finally(() => {
|
||||
order.value.count = 1
|
||||
order.value.orderNote = ''
|
||||
choseKeys.value = []
|
||||
showSure.value = false
|
||||
})
|
||||
} else if (flag.value == 1) {
|
||||
mallAPI.addCart(cartItem).then(res => {
|
||||
if (res.success) {
|
||||
const cartItemId = res.data?.cart_item_id || res.data?.id || res.data
|
||||
?.cartItemId || res.id
|
||||
if (!cartItemId) {
|
||||
msgRef.value.show({
|
||||
title: '无法获取购物车项ID',
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
mallAPI.createOrder({
|
||||
cart_item_ids: [cartItemId]
|
||||
}).then(response => {
|
||||
if (response.success) {
|
||||
// 进入支付页面
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/pay?preOrderId=' + response.data
|
||||
.preOrderId
|
||||
})
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
title: '操作失败',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
title: res.data.message || '添加到购物车失败',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 判断两个数组值是否相等
|
||||
const arraysEqualUnordered = (arr1, arr2) => {
|
||||
if (arr1.length !== arr2.length) return false;
|
||||
|
||||
const sorted1 = [...arr1].sort();
|
||||
const sorted2 = [...arr2].sort();
|
||||
|
||||
return sorted1.every((item, index) => item === sorted2[index]);
|
||||
}
|
||||
|
||||
|
||||
const dataId = ref()
|
||||
const dataInfo = ref({})
|
||||
const recommendedList = ref([])
|
||||
const specNames = ref(new Set())
|
||||
const specOptions = ref(new Map())
|
||||
const activeKeys = ref([])
|
||||
|
||||
const loadData = () => {
|
||||
mallAPI.getMallDetail(dataId.value).then(res => {
|
||||
console.log(res);
|
||||
dataInfo.value = res.data.product
|
||||
dataInfo.value.banner = []
|
||||
if (dataInfo.value.images.length != 0) {
|
||||
dataInfo.value.images.forEach(item => {
|
||||
dataInfo.value.banner.push(getImageUrl(item))
|
||||
})
|
||||
}
|
||||
loadSpec()
|
||||
})
|
||||
mallAPI.getRecommended(dataId.value).then(res => {
|
||||
recommendedList.value = res.data.products
|
||||
})
|
||||
}
|
||||
|
||||
const loadSpec = () => {
|
||||
dataInfo.value.specifications.forEach(specification => {
|
||||
activeKeys.value.push(specification.combination_key)
|
||||
specification.spec_details.forEach(detail => {
|
||||
specNames.value.add(detail.spec_display_name)
|
||||
let data = specOptions.value.get(detail.spec_display_name)
|
||||
if (data == undefined) {
|
||||
data = new Map()
|
||||
data.set(detail.id, detail.display_value)
|
||||
specOptions.value.set(detail.spec_display_name, data)
|
||||
} else {
|
||||
data.set(detail.id, detail.display_value)
|
||||
specOptions.value.set(detail.spec_display_name, data)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -80,13 +476,138 @@
|
||||
height: 100vh;
|
||||
background: linear-gradient(180deg, #2F75F9 0%, #F0F3FF 34.13%);
|
||||
|
||||
|
||||
.collection {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.img-sub-banner {
|
||||
padding: 12rpx 0;
|
||||
background: #fff;
|
||||
white-space: nowrap;
|
||||
|
||||
.img-item {
|
||||
border-radius: 20rpx;
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1px solid #189eff;
|
||||
}
|
||||
}
|
||||
|
||||
.mall-info {
|
||||
padding: 20rpx 34rpx;
|
||||
|
||||
.name {
|
||||
font-weight: 650;
|
||||
font-size: 20px;
|
||||
leading-trim: NONE;
|
||||
line-height: 46rpx;
|
||||
letter-spacing: 0%;
|
||||
}
|
||||
|
||||
.price {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.mall-price {
|
||||
font-size: 30rpx;
|
||||
color: #305DEF;
|
||||
margin-top: 10rpx;
|
||||
|
||||
.icon {
|
||||
height: 30rpx;
|
||||
width: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail {
|
||||
margin-top: 20rpx;
|
||||
border: 1rpx solid #fff;
|
||||
padding: 10rpx 20rpx;
|
||||
box-shadow: 1px 1px 2px 2px rgba(0, 0, 255, 0.2);
|
||||
}
|
||||
|
||||
.recommend {
|
||||
margin-top: 20rpx;
|
||||
|
||||
.mall-list {
|
||||
margin-top: 20rpx;
|
||||
|
||||
.mall-item {
|
||||
border-radius: 16rpx;
|
||||
background: #F0F5FF;
|
||||
position: relative;
|
||||
margin-top: 20rpx;
|
||||
box-shadow: 0px 4px 4px 0px #00000040;
|
||||
padding-bottom: 10rpx;
|
||||
|
||||
.mall-title {
|
||||
font-size: 30rpx;
|
||||
margin-top: 10rpx;
|
||||
color: $u-main-color;
|
||||
}
|
||||
|
||||
.mall-price {
|
||||
font-size: 30rpx;
|
||||
color: $u-type-error;
|
||||
margin-top: 10rpx;
|
||||
|
||||
.icon {
|
||||
height: 30rpx;
|
||||
width: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.mall-tag {
|
||||
display: flex;
|
||||
margin-top: 5px;
|
||||
|
||||
.mall-tag-owner {
|
||||
background-color: $u-type-error;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 20rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.mall-tag-text {
|
||||
margin-right: 10px;
|
||||
border: 1px solid $u-type-primary;
|
||||
color: $u-type-primary;
|
||||
border-radius: 50rpx;
|
||||
line-height: 1;
|
||||
padding: 4rpx 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 50rpx;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.mall-shop {
|
||||
font-size: 22rpx;
|
||||
color: $u-tips-color;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bottom-view {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@@ -158,4 +679,93 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sure-popup {
|
||||
background: #F5F8FF;
|
||||
padding-bottom: 20rpx;
|
||||
|
||||
.title {
|
||||
font-weight: 274;
|
||||
font-style: Light;
|
||||
font-size: 32rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 48rpx;
|
||||
letter-spacing: 0%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.address {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 30rpx;
|
||||
padding: 20rpx 10rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.count-select {
|
||||
display: flex;
|
||||
margin-top: 10rpx;
|
||||
|
||||
.pre-view {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 30rpx;
|
||||
width: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-option {
|
||||
margin: 20rpx 0;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.title {
|
||||
font-weight: 700;
|
||||
font-style: Bold;
|
||||
font-size: 32rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 48rpx;
|
||||
letter-spacing: 0%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.option-list {
|
||||
display: flex;
|
||||
|
||||
.option-item {
|
||||
background: #f2f3f5;
|
||||
padding: 10rpx 20rpx;
|
||||
margin: 20rpx 20rpx 20rpx 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1rpx solid #ff6b35;
|
||||
color: #ff6b35;
|
||||
}
|
||||
|
||||
.unactive {
|
||||
background: #D9D9D9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
216
pages/home/pay.vue
Normal file
216
pages/home/pay.vue
Normal file
@@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<view class="pay-container">
|
||||
<scroll-view scroll-y="true" style="height: 100%;">
|
||||
<view class="scroll-container">
|
||||
<view class="box-bg">
|
||||
<view class="address">
|
||||
<view class="text">
|
||||
<image style="width: 40rpx;height: 40rpx;" src="/static/icon/Map pin2.png" mode=""></image>
|
||||
<view class="u-m-l-10">张三 | </view>
|
||||
<view class="u-m-l-10">浙江省 宁波市 海曙区</view>
|
||||
</view>
|
||||
<view class="right-icon">
|
||||
<image style="width: 100%;height: 100%;" src="/static/icon/Chevron right Menu.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="count-select u-p-l-10 u-p-r-10" v-for="item in dataInfo.items">
|
||||
<view class="pre-view">
|
||||
<u-image :src="getImageUrl(item.image_url)" height="100%" width="100%">
|
||||
<template v-slot:error>
|
||||
<view style="font-size: 24rpx;">暂无图片</view>
|
||||
</template>
|
||||
</u-image>
|
||||
</view>
|
||||
<view class="text">
|
||||
{{item.product_name}}
|
||||
融豆:{{item.rongdou_price}}
|
||||
积分:{{item.points_price}}
|
||||
数量X{{item.quantity}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-bg description u-m-t-20">
|
||||
<view class="item">
|
||||
<view class="title">
|
||||
订单编号
|
||||
</view>
|
||||
<view class="value">
|
||||
{{dataInfo.order_no}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="title">
|
||||
创建时间
|
||||
</view>
|
||||
<view class="value">
|
||||
{{dataInfo.created_at}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="box-bg pay-method u-m-t-20">
|
||||
<view class="title">
|
||||
支付方式
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="title">
|
||||
融豆
|
||||
</view>
|
||||
<view class="value">
|
||||
<u-checkbox v-model="checked" shape="circle" active-color="#305def"></u-checkbox>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="box-bottom">
|
||||
<view class="text">
|
||||
实际支付:1231
|
||||
</view>
|
||||
<view class="btn">
|
||||
<u-button>确认支付</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-toast ref="msgRef" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onMounted,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
mallAPI
|
||||
} from '../../api/mall';
|
||||
import {
|
||||
getImageUrl
|
||||
} from '../../util/common.js'
|
||||
|
||||
const checked = ref(false)
|
||||
|
||||
const dataInfo = ref({})
|
||||
|
||||
const loadData = () => {
|
||||
mallAPI.getOrder(preOrderId.value).then(res => {
|
||||
dataInfo.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const preOrderId = ref()
|
||||
|
||||
onLoad((val) => {
|
||||
preOrderId.value = val.preOrderId
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pay-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--Color, #E4ECFF);
|
||||
|
||||
.scroll-container {
|
||||
|
||||
.box-bg {
|
||||
background: #F5F8FF;
|
||||
}
|
||||
|
||||
.address {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 10rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.count-select {
|
||||
display: flex;
|
||||
margin-top: 10rpx;
|
||||
|
||||
.pre-view {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 30rpx;
|
||||
width: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
padding: 30rpx 40rpx;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-method {
|
||||
padding: 30rpx 40rpx;
|
||||
|
||||
|
||||
.title {
|
||||
font-weight: 400;
|
||||
font-style: Regular;
|
||||
font-size: 28rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.box-bottom {
|
||||
width: 100%;
|
||||
padding: 20rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background: #F5F8FF;
|
||||
|
||||
|
||||
.text {}
|
||||
|
||||
.btn {}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
static/icon/Map pin2.png
Normal file
BIN
static/icon/Map pin2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Reference in New Issue
Block a user