2025-01-15 18:49:37 +08:00

910 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="settlement" :style="{ overflow: isShow ? 'hidden' : 'auto' }">
<OrderStatus :status="1" v-if="isSubmit" :reservationDate="currentDate" />
<div class="address" :class="isSubmit ? 'address_submit' : ''">
<div class="address_info">
<div class="title">
<div class="link_man">
{{ addressInfo.USER_NAME || ""
}}{{ addressInfo.USER_SEX_TEXT || "" }}
</div>
<div class="mobile">{{ addressInfo.MOBILEPHONE }}</div>
</div>
<div class="addressBox">
<div @click="handleOpenAddress" style="display: flex; align-items: center">
<text class="addressText">选择地址</text>
<img class="pickerImg" src="https://eshangtech.com/ShopICO/ahyd-mall/editIcon.svg" />
</div>
<div class="address_text">
{{ addressInfo.ADDRESS || "" }}{{ addressInfo.DOORPLATE || "" }}
</div>
</div>
</div>
<img src="/static/images/home/addressShopCar.png" alt="" class="addrss_bg" />
</div>
<div class="commodity margin_auto">
<CommodityItem :isSubmit="isSubmit" :obj="item" v-for="(item, index) in shopOrder.slice(0, 5)" :key="index" />
<div class="is_more" @click="isShowMore = !isShowMore">
<img v-if="shopOrder.length > 5" :src="isShowMore
? '/static/images/home/up_arrow.png'
: '/static/images/home/down_arrow.png'
" alt="" class="arrow_icon" />
共{{ shopOrder.length }}个品项,{{ shopCount }}件商品
</div>
</div>
<div class="order_remark margin_auto">
<div class="title">订单备注</div>
<div class="order_remark_input" v-if="!isSubmit">
<textarea auto-height placeholder="选填" v-model="remark"></textarea>
</div>
<div class="order_remark_cnt" v-else>
{{ remark }}
</div>
</div>
<OrderInfo :obj="orderInfo" v-if="isSubmit" />
<div class="place_order">
<div class="place_order_box" v-if="!isSubmit">
<div class="sum_count">
合计<span class="unit">¥</span><span class="price">{{ couponOrder }}</span>
</div>
<div class="place_order_btn" @click="createOrder">立即下单</div>
</div>
<div class="back" v-else @click="handleBackIndex">返回购物车</div>
</div>
<div v-if="datePicker" class="dataTimeSelect">
<date-time :show="datePicker" @change="handleTimeChange" :currentDate="currentDate"></date-time>
</div>
<loading v-if="isShowLoading"></loading>
<div v-if="isShowLoading" class="meng"></div>
<div v-if="datePicker" @click="datePicker = !datePicker" class="meng"></div>
<uni-popup ref="addressPopup" :safe-area="false">
<view class="addressPopupBox">
<view class="addressPopupTitle">选择收货地址</view>
<view class="addressList">
<view class="addressItem" v-for="(item, index) in addressList" :key="index">
<view class="addressItemTop">
<view class="itemTopLeft">
<radio :checked="item.MEMBERADDRESS_ID === selectAddressId" color="#1890FF"
@click="handleChangeAddress(item.MEMBERADDRESS_ID)"></radio>
<text class="addressText">{{ item.ADDRESS || "" }}{{ item.DOORPLATE || "" }}</text>
</view>
<view class="itemTopRight" @click="checkOrEdit(item.MEMBERADDRESS_ID)">
<img class="pickerImg" src="https://eshangtech.com/ShopICO/ahyd-mall/editIcon.svg" />
</view>
</view>
<view class="addressItemBottom">
<text class="bigName" style="margin-right: 8rpx">{{
item.USER_NAME || ""
}}</text>
<text class="name" style="margin-right: 8rpx">{{
item.USER_SEX_TEXT || ""
}}</text>
<text class="phone">{{ item.MOBILEPHONE || "" }}</text>
</view>
</view>
</view>
<navigator url="/pages/myAddress/newAdd/index" class="btn">新增收货地址</navigator>
</view>
</uni-popup>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import CommodityItem from "./components/commodityItem.vue";
import OrderInfo from "./components/orderInfo.vue";
import ReceiveGoods from "./components/receiveGoods.vue";
import OrderStatus from "./components/orderStatus.vue";
import Loading from "./components/loading/index.vue";
export default {
components: {
Loading,
CommodityItem,
OrderInfo,
OrderStatus,
ReceiveGoods,
},
data() {
let newM = new Date().getTime();
let startT = newM + 1000 * 60 * 15;
return {
isShowLoading: false,
datePicker: false,
isSubmit: false,
orderInfo: {},
isShowMore: true, // 是否展示更多菜品
start: this.$utils.getLocalTime(startT, "hh:mm"),
end: "23:59",
time: this.$utils.getLocalTime(startT, "hh:mm"),
startT: this.$utils.getLocalTime(new Date(), "hh:mm"),
remark: "", // 备注
shopName: "", // 站点名称
isShow: false,
shopOrder: [],
address: "",
currentDate: "",
shopCount: 0, // 多少件商品
addressList: [],
addressInfo: {}, // 选择的地址信息
selectAddressId: 0,
isFirst: true, // 判断是不是第一次进入到页面
};
},
computed: {
...mapGetters({
user: "user",
tableNum: "orderTable",
orderRemark: "orderRemark",
provinceCode: "provinceCode",
couponPrice: "couponPrice",
nowStore: "nowStore",
}),
couponOrder() {
// 商品金额
let amount = 0;
this.shopOrder.map((v) => {
amount += v.ORDER_AMOUNT;
});
return amount.toFixed(2);
},
},
onShow() {
if (!this.isFirst) {
// 更新用户的地址
this.handleGetAddressList();
}
},
onUnload() { },
async onLoad(option) {
console.log("option", option);
if (option.shopCarList) {
let shopList = JSON.parse(option.shopCarList);
let sum = 0;
if (shopList && shopList.length > 0) {
shopList.forEach((item) => {
sum += item.count;
});
}
this.shopOrder = shopList;
this.shopCount = sum;
}
console.log("this.shopOrder", this.shopOrder);
// 请求用户的地址
await this.handleGetAddressList();
console.log("1");
this.isFirst = false;
},
methods: {
// 打开选择地址的悬浮框
handleOpenAddress() {
this.$refs.addressPopup.open("bottom");
},
// 请求该用户的地址列表
async handleGetAddressList() {
const data = await this.$api.getCoop({ action_type: "GetAddressList" });
console.log("data", data);
let list = data.Data.List;
let defaultAddress = {};
if (list && list.length > 0) {
list.forEach((item) => {
if (this.isFirst) {
if (item.ISDEFAULT === 1) {
defaultAddress = item;
}
} else {
if (item.MEMBERADDRESS_ID === this.addressInfo.MEMBERADDRESS_ID) {
defaultAddress = item;
}
}
});
console.log("defaultAddress", defaultAddress);
if (!defaultAddress.MEMBERADDRESS_ID) {
defaultAddress = list[0];
}
this.addressList = list;
this.addressInfo = defaultAddress;
this.selectAddressId = defaultAddress.MEMBERADDRESS_ID;
this.$forceUpdate();
} else {
this.addressList = [];
this.addressInfo = {};
this.selectAddressId = 0;
}
},
// 切换选中的地址
handleChangeAddress(id) {
console.log("this.selectAddressId", this.selectAddressId);
this.addressList.forEach((item) => {
if (item.MEMBERADDRESS_ID === id) {
this.addressInfo = item;
this.selectAddressId = item.MEMBERADDRESS_ID;
}
});
this.$forceUpdate();
this.$refs.addressPopup.close();
},
// 编辑地址
checkOrEdit(id) {
uni.navigateTo({ url: "/pages/myAddress/newAdd/index?id=" + id });
},
// 立即下单
async createOrder() {
if (!this.addressInfo.MEMBERADDRESS_ID) {
uni.showToast({
title: "请选择收货地址!",
duration: 2000,
icon: "none",
});
return;
}
console.log("_this.user", this.user);
console.log("_this.shopOrder", this.shopOrder);
if (this.shopOrder && this.shopOrder.length > 0) {
this.shopOrder.forEach((item) => {
if (item.SALEDETAIL_DESC) {
} else {
item.SALEDETAIL_DESC = "";
}
});
}
let openId = uni.getStorageSync('openId')
console.log('openId', openId);
let req = {
action_type: "ScanOrder",
salebillType: "3000",
provinceCode: this.user.PROVINCE_CODE,
serverpartShopId: '5634',
salebillDesc: this.remark || "",
wechatOpenId: openId || "",
wechatUnionId: this.user.USER_UNIONID || "",
// tableNumber: '',
// takeType: '',
// packType: '',
// reservationDate: '',
addressId: this.addressInfo.MEMBERADDRESS_ID,
orderPersonTel: this.addressInfo.MOBILEPHONE,
// couponCode: '',//优惠券
t_saleorderdetail: JSON.stringify(this.shopOrder),
requestType: "application/x-www-form-urlencoded",
};
const data = await this.$api.postCoop(req);
console.log("data", data);
if (data.ResultCode === "100") {
let shopCarList = this.$store.state.myShopCar;
if (shopCarList && shopCarList.length > 0) {
let newList = []
shopCarList.forEach((item) => {
let find = false
this.shopOrder.forEach((subItem) => {
if (item.COMMODITY_ID === subItem.COMMODITY_ID) {
find = true
}
})
if (find) {
} else {
newList.push(item)
}
})
// list
this.$store.commit("myShopCar", newList);
} else {
this.$store.commit("myShopCar", []);
}
this.getOrderInfo(data.Data);
} else {
// uni.showToast({
// title: data.ResultDesc,
// icon: "none",
// duration: 2000,
// });
uni.showModal({
title: '提示',
content: data.ResultDesc,
success: function (res) {
}
});
}
},
// 生成订单号
generateOutTradeNo(length) {
// 定义允许的字符集
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_|\*';
// 生成随机字符串
let orderNumber = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
orderNumber += characters[randomIndex];
}
// 如果长度不在6到32之间调整为合法的长度
if (length < 6) {
length = 6;
} else if (length > 32) {
length = 32;
}
return orderNumber.slice(0, length); // 返回生成的订单号
},
// 生成一个符合要求的商户订单号长度为16的示例
// 获取后台信息调取微信支付
async getOrderInfo(obj) {
let _this = this;
// 拿到签名
let mchid = "1672298991";
let timeStamp = Math.ceil(new Date().getTime() / 1000);
let nonceStr = Math.random().toString(36).substring(2, 8)
let serial_no = "5BA7C0F427FC042DB5BF299E35B373D5EFCECD35"
// let out_trade_no = this.generateOutTradeNo(32)
let out_trade_no = obj.SALEBILL_CODE
let req = {
appid: "wxee018fb96955552a", // 公众账号ID
mchid: "1672298991", // 商户号
description: "彩云驿商城", //商品描述
out_trade_no: out_trade_no, // 商户订单号
notify_url: "https://mp.eshangtech.com/Coop.Merchant/Handler/Handler_Trade.ashx", // 商户回调地址
amount: {
total: Number(_this.couponOrder) * 100 || 1,
currency: "CNY",
}, // 订单金额
payer: {
openid: _this.user.WECHATAPP_OPENID,
}, // 支付者信息
}
console.log('req', req);
let reqSign = {
parameters: "POST\n/v3/pay/transactions/jsapi\n" + timeStamp + "\n" + nonceStr + "\n" + JSON.stringify(req) + "\n"
}
console.log("POST\n/v3/pay/transactions/jsapi\n" + timeStamp + "\n" + nonceStr + "\n" + JSON.stringify(req) + "\n");
const data = await this.$api.$get(
"/WeChat/GenerateSign",
reqSign
);
console.log('data3213123', data.Result_Data);
let Authorization = `mchid="${mchid}",nonce_str="${nonceStr}",signature="${data.Result_Data}",timestamp="${timeStamp}",serial_no="${serial_no}"`
let AuthorizationStr = `WECHATPAY2-SHA256-RSA2048 ${Authorization}`
console.log('AuthorizationStr', AuthorizationStr);
uni.request({
url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", //仅为示例,并非真实接口地址。
method: "POST",
data: req,
header: {
"Authorization": AuthorizationStr,
"Accept": "application/json", //自定义请求头信息
"Content-Type": "application/json",
},
success: async (res) => {
console.log(res.data.prepay_id);
this.text = "request success";
let paySign = ''
let reqSign = {
parameters: "wxee018fb96955552a\n" + timeStamp + "\n" + nonceStr + "\nprepay_id=" + res.data.prepay_id + "\n"
}
const data = await this.$api.$get(
"/WeChat/GenerateSign",
reqSign
);
paySign = data.Result_Data
wx.requestPayment({
timeStamp: timeStamp.toString(),
nonceStr: nonceStr,
package: `prepay_id=${res.data.prepay_id}`,
signType: 'RSA',
paySign: paySign,
total_fee: Number(_this.couponOrder) * 100 || 1,
success(res) {
console.log('res', res);
},
fail(res) {
console.log('fail', res);
},
complete(res) {
uni.redirectTo({
url: `/pages/order/orderdetail/index?orderInternal=${obj.SALEBILL_ID}`
});
}
})
},
});
return;
// let req = {
// action_type: "JsApiPay",
// action_data: 1,
// action_record: _this.user.WECHATAPP_OPENID,
// // action_record: 'ortWV5OP2g9P81cxxJYIIhrAezS4',
// TOTAL_FEE: _this.orderAmount,
// OFFPRICE: 0,
// payType: 2,
// SALEBILL_ID: _this.orderInternal,
// // SALEBILL_CODE: _this.orderNumber,
// SALEBILL_CODE: this.orderInfo.SALEBILL_CODE,
// requestType: "application/x-www-form-urlencoded",
// };
// console.log("getOrderInfo", req);
return;
_this.$api.postCoop(req).then((res) => {
console.log("getOrderInfo", res);
if (res) {
uni.requestPayment({
appId: "wxee018fb96955552a", // 公众号名称,由商户传入
timeStamp: res.timeStamp + "", // 时间戳自1970年以来的秒数
nonceStr: res.nonceStr, // 随机串
package: res.package,
signType: res.signType, // 微信签名方式
paySign: res.paySign, // 微信签名
success(res) {
if (res.errMsg === "requestPayment:ok") {
_this.$api
.postCoop({
action_type: "EndPay",
action_data: _this.orderNumber,
action_record: 1,
})
.then((res) => {
_this.$store.commit("couponPrice", "");
});
}
},
fail(res) {
if (res.errMsg === "requestPayment:fail cancel") {
}
},
complete(res) { },
});
} else {
uni.showToast({
title: "网络异常,请稍后再试",
icon: "none",
duration: 2000,
});
}
});
},
},
};
</script>
<style lang="less" scoped>
.meng {
width: 100vw;
height: 100%;
background: rgba(0, 0, 0, 0.3);
position: absolute;
top: 0;
left: 0;
z-index: 8;
}
.dataTimeSelect {
width: 100%;
height: 350px;
position: fixed;
bottom: 0px;
z-index: 999;
background: #fff;
padding-bottom: 20px;
.bottom {
width: 100%;
height: 40px;
padding: 5px 15px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
border-bottom: 2px solid #ccc;
.cancel {
color: #ccc;
}
.success {
color: green;
}
}
}
.settlement {
background-color: #f2f4f5;
min-height: 100vh;
box-sizing: border-box;
position: relative;
padding-bottom: 196rpx;
.address {
width: 638rpx;
background: #fefffe;
border-radius: 16rpx;
padding: 28rpx 24rpx;
display: flex;
flex-direction: row;
align-items: start;
margin: 24rpx auto;
position: relative;
z-index: 1;
.icon {
width: 40rpx;
height: 40rpx;
background: #1890ff;
border-radius: 4rpx;
color: #fff;
text-align: center;
line-height: 40rpx;
}
.address_info {
width: 582rpx;
margin-left: 16rpx;
.title {
display: flex;
flex-direction: row;
align-items: center;
font-size: 34rpx;
color: #020e1a;
height: 40rpx;
line-height: 40rpx;
line-height: 48rpx;
font-weight: 600;
.link_man {
margin-right: 16rpx;
}
}
.addressBox {
margin-top: 8px;
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
.addressText {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #020e1a;
line-height: 32rpx;
text-align: left;
font-style: normal;
}
.pickerImg {
width: 14px;
height: 14px;
}
.address_text {
font-size: 24rpx;
font-weight: 400;
color: #020e1a;
line-height: 32rpx;
}
.pickerBox {
display: flex;
align-items: center;
.pickerText {
font-size: 12px;
font-weight: 400;
color: #1890ff;
}
.pickerImg {
width: 14px;
height: 14px;
}
}
}
}
.addrss_bg {
position: absolute;
bottom: 0;
left: 18rpx;
width: 652rpx;
height: 4rpx;
}
}
.address_submit {
margin-top: -80rpx;
}
.serve_time {
width: 638rpx;
height: 48rpx;
padding: 28rpx 24rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin: 24rpx auto;
border-radius: 16rpx;
.serve_title {
font-size: 28rpx;
color: #020e1a;
}
.time {
font-size: 28rpx;
color: #1890ff;
display: flex;
flex-direction: row;
align-items: center;
img {
margin-left: 16rpx;
width: 14px;
height: 14px;
}
}
}
.commodity {
width: 638rpx;
padding: 24rpx 24rpx;
border-radius: 16rpx;
margin-bottom: 24rpx;
.store_name {
color: #020e1a;
font-size: 28rpx;
margin-bottom: 24rpx;
display: flex;
justify-content: space-between;
.link_service {
display: flex;
flex-direction: row;
align-items: center;
color: #1890ff;
.service {
width: 24rpx;
height: 24rpx;
margin-right: 12rpx;
}
}
}
.is_more {
width: 400rpx;
height: 40rpx;
margin: auto;
text-align: center;
//display: flex;
//flex-direction: row;
//align-items: center;
color: #9fa3a8;
font-size: 28rpx;
.arrow_icon {
width: 26rpx;
height: 16rpx;
margin-left: 16rpx;
}
}
}
.order_remark {
width: 638rpx;
padding: 24rpx 24rpx;
border-radius: 16rpx;
margin-bottom: 24rpx;
.title {
color: #020e1a;
font-size: 28rpx;
margin-bottom: 24rpx;
font-weight: 600;
}
.order_remark_input {
padding: 16rpx 24rpx;
background: #f2f4f5;
border-radius: 8rpx;
min-height: 120rpx;
}
.order_remark_cnt {
color: #6c737a;
line-height: 40rpx;
font-size: 28rpx;
}
}
.place_order {
position: fixed;
z-index: 3;
bottom: 0rpx;
left: 0rpx;
background: #ffffff;
width: 100%;
height: 164rpx;
padding-top: 16rpx;
.place_order_box {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.sum_count {
margin-left: 32rpx;
font-size: 28rpx;
color: #6c737a;
.unit {
color: #ff6219;
font-size: 24rpx;
}
.price {
color: #ff6219;
font-size: 36rpx;
}
}
}
.place_order_btn {
width: 240rpx;
height: 80rpx;
background: #1890ff;
border-radius: 8rpx;
margin-right: 32rpx;
color: #fff;
text-align: center;
line-height: 80rpx;
font-size: 32rpx;
}
.back {
margin: auto;
width: 686rpx;
height: 80rpx;
border-radius: 8rpx;
text-align: center;
line-height: 80rpx;
font-size: 32rpx;
color: #fff;
background: #1890ff;
}
.check {
background: #1890ff;
color: white;
}
}
.addressPopupBox {
width: 100%;
height: 60vh;
background-color: #fff;
box-sizing: border-box;
padding: 16rpx;
.addressPopupTitle {
font-family: PingFangSC, PingFang SC;
font-weight: 600;
font-size: 32rpx;
color: #020e1a;
line-height: 40rpx;
text-align: left;
font-style: normal;
display: block;
text-align: center;
}
.addressList {
margin-top: 24rpx;
width: 100%;
height: calc(60vh - 250rpx);
overflow-y: auto;
.addressItem {
width: 100%;
padding: 16rpx 0;
box-sizing: border-box;
border-bottom: 1px solid #f6f6f6;
.addressItemTop {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.itemTopLeft {
display: flex;
align-items: center;
.addressText {
font-size: 28rpx;
display: inline-block;
width: 70vw;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
.itemTopRight {
.pickerImg {
width: 18px;
height: 18px;
}
}
}
.addressItemBottom {
width: 100%;
margin-top: 8rpx;
box-sizing: border-box;
padding-left: 64rpx;
color: #9fa3a8;
font-size: 24rpx;
}
}
}
.addressList::-webkit-scrollbar {
display: none;
}
.btn {
height: 88rpx;
width: 90%;
line-height: 88rpx;
background: linear-gradient(to right, #1f1f1f, #62605f);
color: #f0dccf;
text-align: center;
font-size: 30rpx;
position: fixed;
bottom: 32rpx;
transform: translateX(-50%);
left: 50%;
border-radius: 12rpx;
}
}
}
.margin_auto {
margin: auto;
background: #fefffe;
}
uni-modal .uni-modal__bd {
white-space: pre-wrap;
}
</style>