Files
frontend-app/pages/mine_package/mine_order/mine_order.vue
T
2025-08-12 11:28:59 +08:00

758 lines
21 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>
<view class="order_warp">
<view class="order_header">
<up-image src="/static/common/left.png" width="20" height="20" bgColor="#f1f6ff00" @click="jumpLeft"></up-image>
<up-search shape="round" bgColor="#FFFFFFFF" :showAction="false" @search="searchFun"></up-search>
</view>
<view class="order_type_title">
<view :class="form.type === item.id ? 'order_type_title_item order_type_title_item_sel' : 'order_type_title_item'"
v-for="(item, index) in orderTypeList" @click="checkType(item)" :key="index">
{{ item.title }}
</view>
</view>
<scroll-view scroll-y="true" @scrolltolower="loadMore" style="height: calc(100vh - 300rpx);">
<view v-if="orderList && orderList.length !== 0" class="order_list_warp">
<view class="order_item" v-for="item in orderList" :key="item.id">
<!-- 头部 -->
<view class="order_item_header">
<view class="order_item_header_left">
<up-image :src="item.shopLogo" width="22" height="22" bgColor="#f1f6ff00" shape="circle"></up-image>
<view class="order_product_title">{{ item.shopName }}</view>
</view>
<!-- 除开待付款 -->
<view v-if="item.status !== ORDER_TYPE.UNPAID" class="order_item_header_right"
:style="{ 'color': ORDER_STATUS_CSS[item.status] }">
{{ getValue(ORDER_STATUS, item.status) }}
</view>
<!-- 待付款 -->
<view v-else class="order_item_header_right order_right_due">
<view class="order_right_due_msg">等待付款</view>
<view class="order_right_due_time">{{ formatDate1(item.expireTime) }}前</view>
</view>
</view>
<!-- 产品详情 -->
<view class="order_item_content">
<view v-for="pItem in item.items" :key="pItem.id">
<view class="content_item" @click="jumpOrderInfo(item)">
<up-image :src="pItem.mainGraph" width="80" height="80" bgColor="#f1f6ff00"></up-image>
<view class="content_info">
<view class="content_info_title">{{ pItem.title }}</view>
<view class="content_info_tag">{{ pItem.goodsSpece }}</view>
<!-- <view>
<text class="content_info_description" v-for="dItem in pItem.description">
{{dItem}}
</text>
</view> -->
</view>
<view class="content_right">
<view class="content_right_total">¥{{ pItem.goodsAmount }}</view>
<view class="content_right_quantity">x{{ pItem.buyNum }}</view>
</view>
</view>
<view class="content_item_yd" v-if="pItem.expressNo">
<view>运单号:<text v-if="pItem.expressName">({{ pItem.expressName }})</text>{{ pItem.expressNo }}</view>
<view style="margin-left:10rpx;">
<up-image src="/static/common/copy.png" width="14" height="14" bgColor="#f1f6ff00"
@click="copyData(pItem.expressNo)"></up-image>
</view>
</view>
</view>
</view>
<!-- 汇总 -->
<view class="order_item_collect">
<view class="collect_msg collect_msg_s" v-if="this.form.type === MINE_ORDER_TYPE.NOT_RECEIVE">
<view class="content_item_yd_msg">(快递动态跟进请复制单号至[快递100官网] 查询)</view>
<view>共{{ item.buyNum }}件,合计¥{{ item.sumAmount }}</view>
</view>
<view class="collect_msg" v-else>
共{{ item.buyNum }}件,合计¥{{ item.sumAmount }}
</view>
<view class="collect_operate">
<!-- <view class="operate_comm operate_but_1" v-if="item.status === ORDER_TYPE.UNSHIPPED" @click="checkCancel(true)">取消订单</view> -->
<view class="operate_comm operate_but_2" v-if="item.status === ORDER_TYPE.UNPAID"
@click="jumpOrderInfo(item)">去付款</view>
<!-- <view class="operate_comm operate_but_1" v-if="item.status === ORDER_TYPE.COMPLETED">申请退款</view> -->
<view class="operate_comm operate_but_2" v-if="!isCheckSigne && item.status === ORDER_TYPE.NOT_RECEIVE"
@click="onSignContract(item)">去签署
</view>
<view v-if="isCheckSigne && item.status === ORDER_TYPE.NOT_RECEIVE" @click="confirmReceiptOk(item)">确认收货
</view>
<!-- <view class="operate_comm operate_but_3" v-if="item.status === ORDER_TYPE.UNSHIPPED">提醒发货</view> -->
<view class="operate_comm operate_but_1"
v-if="[ORDER_TYPE.NOT_RECEIVE, ORDER_TYPE.UNSHIPPED].includes(item.status) && isCheckSigne"
@click="afterShow = true;">
申请售后
</view>
<!-- <view class="operate_comm operate_but_1" v-if="item.status === ORDER_TYPE.AFTER_SALE">查看售后</view> -->
<!-- <view class="operate_comm operate_but_1" v-if="[ORDER_TYPE.COMPLETED].includes(item.status)">删除记录</view> -->
<!-- <view class="operate_comm operate_but_3" v-if="[ORDER_TYPE.COMPLETED,ORDER_TYPE.CANCELED].includes(item.status)">再次购买</view> -->
</view>
</view>
</view>
</view>
<view v-else class="not_order_warp">
<up-image src="https://cex-pub.s3.ap-southeast-1.amazonaws.com/static/not_order.png" width="80" height="80"
bgColor="#f1f6ff00"></up-image>
<view class="not_order_msg_warp">暂无相关订单</view>
</view>
<view v-if="loading" style="text-align: center;">加载中...</view>
</scroll-view>
<up-popup v-model:show="cancelShow" :round="10" :closeOnClickOverlay="false">
<view class="cancel_show_warp">
<view class="cancel_show_title_warp">
<view>取消订单</view>
<view class="cancel_show_title_icon" @click="checkCancel(false)"><up-icon name="close-circle" color="#9e9e9e"
size="20"></up-icon></view>
</view>
<view class="cancel_show_msg_warp">
<view>温馨提示:</view>
<view>1.限时特价、预约资格等购买优惠可能一并取消</view>
<view>2.订单一旦取消,支付优惠一并取消,可能无法恢复</view>
</view>
<view class="cancel_show_reason_warp">
<view class="reason_title">请选择取消订单的原因(必选):</view>
<up-radio-group v-model="cancelForm.reason" placement="column">
<up-radio :customStyle="{ marginBottom: '8px' }" v-for="(item, index) in reasonList" :key="index"
:label="item.name" :name="item.name">
</up-radio>
</up-radio-group>
<up-textarea v-model="cancelForm.remark"></up-textarea>
</view>
</view>
<view class="but_border_warp"></view>
<view class="cancel_show_but">
<view class="add_but" @click="cancelOk">提交</view>
</view>
</up-popup>
<up-toast ref="uToastRef"></up-toast>
<!-- 暂未开放 -->
<up-modal :show="openShow" :showConfirmButton="false">
<view class="slot-content">
<view class="close_warp" @click="openShow = false;">
<up-image src="/static/common/close.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
<view class="content_">
<view class="content_1">温馨提示</view>
<view class="content_2">暂未开放</view>
</view>
<view class="but_">
<view class="but_copy" @click="openShow = false;">确定</view>
</view>
</view>
</up-modal>
<!-- 申请售后 -->
<up-modal :show="afterShow" :showConfirmButton="false">
<view class="slot-content">
<view class="close_warp" @click="afterShow = false;">
<up-image src="/static/common/close.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
<view class="content_">
<view class="content_1">售后联系方式</view>
<view class="content_2">如遇退/换货等问题,请联系客服处理</view>
<view class="content_3">
<view style="margin-left: 20rpx;">
<up-image src="/static/common/kf_dh.png" width="40" height="40" bgColor="#f1f6ff00"></up-image>
</view>
<view class="content_info">
<view class="content_info_title">客服电话</view>
<view class="content_info_mobile">
139 2278 6999
<view style="margin-left: 20rpx;">
<up-image src="/static/common/copy_c.png" width="14" height="14" bgColor="#f1f6ff00"
@click="copyMobile(13922786999)"></up-image>
</view>
</view>
</view>
</view>
<view class="content_3">
<view style="margin-left: 20rpx;">
<up-image src="/static/common/kf_wx.png" width="40" height="40" bgColor="#f1f6ff00"></up-image>
</view>
<view class="content_info">
<view class="content_info_title">客服微信</view>
<view class="content_info_mobile">
139 2278 6999
<view style="margin-left: 20rpx;">
<up-image src="/static/common/copy_c.png" width="14" height="14" bgColor="#f1f6ff00"
@click="copyMobile(13922786999)"></up-image>
</view>
</view>
</view>
</view>
</view>
<view class="but_">
<!-- <view class="but_copy" @click="copyMobile('13922786999')">复制号码</view> -->
<view class="but_close" @click="afterShow = false;">确定</view>
</view>
</view>
</up-modal>
<!-- 腾讯电子签H5 → 集成到UniApp -->
<web-view v-if="signUrl" :src="signUrl" @message="handleMessage"></web-view>
</view>
</template>
<script>
import { MINE_ORDER_TYPE, ORDER_TYPE, ORDER_STATUS, getValue } from '@/utils/enumUtils.js';
import { ORDER_STATUS_CSS } from '@/utils/enumCssUtils.js';
import { getOrderList, confirmReceipt, getSignUrl, signContract, isSignContract, getMiniProgramSignUrl } from '@/api/order.js';
import dayjs from 'dayjs';
import { formatDate1, copyData } from '@/utils/index.js'
export default {
computed: {
MINE_ORDER_TYPE() {
return MINE_ORDER_TYPE;
},
ORDER_STATUS() {
return ORDER_STATUS;
},
ORDER_STATUS_CSS() {
return ORDER_STATUS_CSS;
},
ORDER_TYPE() {
return ORDER_TYPE;
}
},
data() {
return {
orderTypeList: [
{
id: MINE_ORDER_TYPE.UNPAID,
title: "待支付",
}, {
id: MINE_ORDER_TYPE.UNSHIPPED,
title: "待发货",
}, {
id: MINE_ORDER_TYPE.NOT_RECEIVE,
title: "待收货",
}, {
id: MINE_ORDER_TYPE.SUCCEED,
title: "已完成",
},
// {
// id:MINE_ORDER_TYPE.AFTER_SALE,
// title:"售后",
// },
],
form: {
search: null,//搜索
page: 1,
pageSize: 10,
type: MINE_ORDER_TYPE.UNPAID,// 选中的类型
},
hasMore: true, // 是否有更多数据可以加载
orderList: [],
cancelShow: false,// 取消订单
reasonList: [
{
id: 1,
name: '地址信息填写错误',
}, {
id: 2,
name: '不想要了',
}, {
id: 3,
name: '商品错选/多选',
}, {
id: 4,
name: '没用/少用/错用优惠券',
}, {
id: 5,
name: '商品降价',
}, {
id: 6,
name: '其他原因',
},
],
cancelForm: {
reason: null,
remark: null,
},
loading: false, // 加载状态标志
openShow: false,
afterShow: false,// 售后申请
isCheckSigne: false,
flowId: null,
signUrl: null
}
},
onLoad(options) {
const type = options.type;
this.form.type = type && type < 5 ? parseInt(type, 10) : MINE_ORDER_TYPE.UNPAID;
this.loadData();
// 待收货判断是否签署
if (this.form.type === MINE_ORDER_TYPE.NOT_RECEIVE) {
this.checkSigned();
}
},
methods: {
dayjs,
getValue,
formatDate1,
copyData,
copyMobile(mobile) {
copyData(mobile);
this.afterShow = false;
},
jumpLeft() {
uni.switchTab({
url: '/pages/mine/mine',
})
},
searchFun(val) {
console.log("searchFun", val);
},
checkType(item) {
console.log("checkType---", item);
this.form.page = 1;
this.form.type = item.id;
this.orderList = [];
// 待收货判断是否签署
if (this.form.type === MINE_ORDER_TYPE.NOT_RECEIVE) {
this.checkSigned();
}
if (item.id !== MINE_ORDER_TYPE.AFTER_SALE) {
this.loadData();
} else {
this.openShow = true;// 未开发的弹框
}
},
jumpOrderInfo(item) {
uni.navigateTo({
url: "/pages/mine_package/mine_order_info/mine_order_info?id=" + item.id,
})
},
// 处理到期时间
handleExpressTime(expressTime) {
let resultM = 0;
if (!expressTime || expressTime === 0) {
return resultM;
}
const currentTimestamp = dayjs().unix();
const time = currentTimestamp - expressTime;
resultM = dayjs(time).format('YYYY-MM-DD HH:MM:SS'); // 获取时分格式的字符串
// 如果需要将时分转换为分钟数(例如,'12:34'转换为754分钟),则需要额外计算:
// const [hours, minutes] = formattedTime.split(':').map(Number); // 分解小时和分钟为数字
// resultM = hours * 60 + minutes; // 计算总分钟数
// console.log(resultM); // 输出总分钟数,例如754
return resultM;
},
// 加载数据的方法
async loadData() {
if (this.loading) return; // 如果正在加载,则不重复加载
this.loading = true; // 设置加载状态为true
try {
// 模拟异步获取数据,实际应用中应该替换为你的数据获取逻辑,例如API调用
const newData = await this.fetchData(this.form.page, this.form.pageSize);
if (newData.entitys && newData.entitys.length !== 0) {
this.orderList = [...this.orderList, ...newData.entitys]; // 将新数据添加到列表中
this.form.page++; // 页码加1
console.log("this.orderList", this.orderList);
}
} catch (error) {
console.error('加载数据失败:', error);
} finally {
this.loading = false; // 设置加载状态为false
}
},
// 模拟获取数据的方法,实际应用中应该替换为你的数据获取逻辑,例如从服务器获取数据
async fetchData(page, pageSize) {
const params = {
...this.form,
page,
pageSize,
}
const data = await getOrderList(params);
if (data && data.bizcode === 100) {
return data.data
} else {
return [];
}
},
// 当滚动到底部时触发的方法
loadMore() {
this.loadData(); // 加载更多数据
},
checkCancel(status) {
this.cancelShow = status;
if (!status) {
this.cancelForm = {
reason: null,
remark: null,
}
}
},
/**
* 确认取消
*/
cancelOk() {
const params = {
...this.cancelForm,
}
if (!params.reason) {
this.$refs.uToastRef.show({
type: 'error',
message: "请选择取消原因",
});
return;
}
this.checkCancel(false);
},
/**
* 确认收货
*/
confirmReceiptOk(item) {
const then = this;
// uni.showModal({
// title: '提示',
// content: '是否确认收货?',
// success: function (res) {
// if (res.confirm) {
// then.confirmReceiptFun(item);
// }
// }
// });
},
async confirmReceiptFun(item) {
const params = {
id: item.id,
}
const resp = await confirmReceipt(params);
if (resp && resp.bizcode === 100) {
this.orderList = [];
this.form.page = 1;
this.loadData();
}
},
// 判断是否已经签名
async checkSigned() {
const { bizcode, data } = await isSignContract();
if (bizcode === 100) {
this.isCheckSigne = data;
}
},
// 发起合同签章
async onSignContract(item) {
const params = {
// 需要的参数
orderId: item.id,
}
const { bizcode, data } = await signContract(params);
if (bizcode === 100) {
this.flowId = item.flowId
if (this.flowId)
this.onGetSignUrl(this.flowId);
}
},
// 获取H5签署链接
async onGetSignUrl(flowId) {
const params = {
// 需要的参数
orderId: flowId,
}
const { bizcode, data } = await getSignUrl(params);
if (bizcode === 100) {
this.onGetMiniProgramSignUrl(data)
} else {
this.$refs.uToastRef.show({
type: 'error',
message: "获取签署链接失败,请稍后再试",
});
return null;
}
},
// 获取跳转至腾讯电子签小程序的签署链接
async onGetMiniProgramSignUrl(item) {
const params = {
// 需要的参数
flowId: this.flowId,
endPoint: item.flowApproverUrlInfos.signUrl
}
const { bizcode, data } = await getMiniProgramSignUrl(params);
if (bizcode === 100) {
// return data;
console.log("跳转至腾讯电子签小程序的签署链接", data);
// #ifdef APP-PLUS || WEB
// #endif
// #ifdef MP-WEIXIN
// 小程序
this.openTencentESign(data);
// #endif
} else {
this.$refs.uToastRef.show({
type: 'error',
message: "获取签署链接失败,请稍后再试",
});
return null;
}
},
// 电子签的回调地址
handleMessage(e) {
const data = e.detail.data[0];
console.log();
// if (data.type === 'signDone' && data.result === 'success') {
// uni.navigateTo({ url: '/pages/result/index' });
// }
},
// 小程序签名
openTencentESign() {
// 这个链接需要后端调用腾讯电子签 API 获取
// 类似:https://esign.tencent.com/miniprogram?flowId=xxxx&token=xxxx
const signPath = '/pages/sign/sign?flowId=xxxxx&token=yyyyy' // 腾讯电子签小程序内部页面路径
uni.navigateToMiniProgram({
appId: 'wxXXXXXXXXXXXXXXX', // 腾讯电子签官方小程序的 appId
path: signPath, // 跳转到的页面路径 + 参数
extraData: {}, // 如果需要传额外参数
envVersion: 'release', // 小程序版本 release / trial / develop
success(res) {
console.log('跳转成功', res)
},
fail(err) {
console.error('跳转失败', err)
}
})
}
}
}
</script>
<style lang="scss" scoped>
.order_warp {
height: calc(100vh - 130rpx);
background-color: $app-bj;
padding: 100rpx 30rpx 30rpx;
overflow-y: hidden;
}
.order_header {
display: flex;
align-items: center;
}
.order_type_title {
display: flex;
margin-top: 30rpx;
align-items: center;
.order_type_title_item {
margin-right: 40rpx;
font-weight: 500;
font-size: 30rpx;
color: #222222;
}
.order_type_title_item_sel {
font-weight: 800;
font-size: 36rpx;
color: $app-bt-bj;
}
}
.order_list_warp {
// height: calc(100vh - 270rpx);
// overflow-y: auto;
}
.order_item {
background: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx 20rpx;
margin-top: 20rpx;
.order_item_header {
display: flex;
justify-content: space-between;
align-items: center;
}
.order_product_title {
font-weight: bold;
font-size: 28rpx;
color: #1A1A1A;
margin-left: 10rpx;
}
.order_item_header_left {
display: flex;
align-items: center;
}
.order_item_header_right {
font-weight: 500;
font-size: 22rpx;
}
.order_right_due {
display: flex;
background: #FFF9F2;
border-radius: 19rpx 22rpx 22rpx 19rpx;
}
.order_right_due_msg {
background: $app-bt-bj;
border-radius: 22rpx 0rpx 12rpx 22rpx;
color: #FFFFFF;
padding: 10rpx 20rpx;
}
.order_right_due_time {
font-weight: bold;
font-size: 24rpx;
color: $app-bt-bj;
padding: 10rpx 20rpx;
}
.order_item_collect {
margin-top: 20rpx;
.collect_msg {
font-weight: 500;
font-size: 24rpx;
color: #666666;
text-align: right;
}
.collect_msg_s {
display: flex;
justify-content: space-between;
}
}
}
.cancel_show_warp {
padding: 20rpx;
.cancel_show_title_warp {
position: relative;
font-weight: bold;
font-size: 36rpx;
color: #222222;
line-height: 48rpx;
text-align: center;
}
.cancel_show_title_icon {
position: absolute;
right: 14rpx;
top: 6rpx;
}
.cancel_show_msg_warp {
background: #F8F8F8;
padding: 30rpx;
font-weight: 500;
font-size: 26rpx;
color: #222222;
line-height: 48rpx;
margin-top: 20rpx;
}
.cancel_show_reason_warp {
margin-top: 20rpx;
.reason_title {
font-weight: bold;
font-size: 32rpx;
color: #222222;
line-height: 36rpx;
margin-bottom: 20rpx;
}
}
}
.but_border_warp {
border: 1rpx solid #eeeeee94;
margin: 30rpx 0;
}
.cancel_show_but {
display: flex;
justify-content: center;
}
.add_but {
position: initial;
width: 94%;
}
.content_info_title {
width: 370rpx;
}
.content_item_yd {
font-weight: bold;
font-size: 24rpx;
display: flex;
align-items: center;
}
.content_item_yd_msg {
font-weight: bold;
font-size: 18rpx;
}
.content_2 {
font-size: 26rpx;
color: rgba(0, 0, 0, 0.4);
margin-bottom: 40rpx;
}
.content_3 {
display: flex;
background: #FFFFFF;
box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(0, 0, 0, 0.06);
border-radius: 12rpx;
.content_info {
display: grid;
margin-left: 20rpx;
text-align: left;
}
.content_info_title {
font-weight: 600;
font-size: 26rpx;
color: rgba(0, 0, 0, 0.9);
line-height: 38rpx;
}
.content_info_mobile {
font-size: 30rpx;
color: rgba(0, 0, 0, 0.4);
display: flex;
}
}
.but_ {
display: flex;
justify-content: center;
margin-top: 40rpx;
}
.but_close {
background: #F24A00;
box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(242, 74, 0, 0.5);
border-radius: 41rpx;
width: 60%;
padding: 20rpx 0;
font-size: 30rpx;
color: #FFFFFF;
}
</style>